Jelajahi Sumber

Update StringFilter

Thomas Rabaix 13 tahun lalu
induk
melakukan
0c5655ca0a

+ 41 - 6
Filter/ORM/StringFilter.php

@@ -11,24 +11,58 @@
 
 namespace Sonata\AdminBundle\Filter\ORM;
 
+use Sonata\AdminBundle\Form\Type\Filter\StringType;
+
 class StringFilter extends Filter
 {
     /**
-     * @param Querybuilder $queryBuilder
+     * @param QueryBuilder $queryBuilder
      * @param string $alias
      * @param string $field
-     * @param mixed $value
+     * @param string $value
      * @return
      */
     public function filter($queryBuilder, $alias, $field, $value)
     {
-        if ($value == null || strlen($value) == 0) {
+        if (!is_array($value)) {
+            return;
+        }
+
+        $value['text'] = trim($value['text']);
+
+        if (strlen($value['text']) == 0) {
             return;
         }
 
-        // c.name LIKE '%word%' => c.name LIKE :fieldName
-        $queryBuilder->andWhere(sprintf('%s.%s LIKE :%s', $alias, $field, $this->getName()));
-        $queryBuilder->setParameter($this->getName(), sprintf($this->getOption('format'), $value));
+        $operator = $this->getOperator((int) $value['type']);
+
+        if (!$operator) {
+            $operator = 'LIKE';
+        }
+
+        // c.name > '1' => c.name OPERATOR :FIELDNAME
+        $queryBuilder->andWhere(sprintf('%s.%s %s :%s', $alias, $field, $operator, $this->getName()));
+
+        if ($value['type'] == StringType::TYPE_EQUAL) {
+            $queryBuilder->setParameter($this->getName(), $value['text']);
+        } else {
+            $queryBuilder->setParameter($this->getName(), sprintf($this->getOption('format'), $value['text']));
+        }
+    }
+
+    /**
+     * @param $type
+     * @return bool
+     */
+    private function getOperator($type)
+    {
+        $choices = array(
+            StringType::TYPE_CONTAINS         => 'LIKE',
+            StringType::TYPE_NOT_CONTAINS     => 'NOT LIKE',
+            StringType::TYPE_EQUAL            => '=',
+        );
+
+        return isset($choices[$type]) ? $choices[$type] : false;
     }
 
     /**
@@ -40,4 +74,5 @@ class StringFilter extends Filter
             'format'   => '%%%s%%'
         );
     }
+
 }

+ 59 - 0
Form/Type/Filter/StringType.php

@@ -0,0 +1,59 @@
+<?php
+/*
+ * This file is part of the Sonata package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ */
+
+namespace Sonata\AdminBundle\Form\Type\Filter;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormTypeInterface;
+use Symfony\Component\Form\FormBuilder;
+use Symfony\Component\Form\FormView;
+use Symfony\Component\Form\FormInterface;
+use Symfony\Component\Translation\TranslatorInterface;
+
+class StringType extends AbstractType
+{
+    const TYPE_CONTAINS = 1;
+
+    const TYPE_NOT_CONTAINS = 2;
+
+    const TYPE_EQUAL = 3;
+
+    protected $translator;
+
+    public function __construct(TranslatorInterface $translator)
+    {
+        $this->translator = $translator;
+    }
+
+    /**
+     * Returns the name of this type.
+     *
+     * @return string The name of this type
+     */
+    function getName()
+    {
+        return 'sonata_type_filter_strinf';
+    }
+
+    public function buildForm(FormBuilder $builder, array $options)
+    {
+        $choices = array(
+            self::TYPE_CONTAINS        => $this->translator->trans('label_type_contains', array(), 'SonataAdminBundle'),
+            self::TYPE_NOT_CONTAINS    => $this->translator->trans('label_type_not_contains', array(), 'SonataAdminBundle'),
+            self::TYPE_EQUAL           => $this->translator->trans('label_type_equals', array(), 'SonataAdminBundle'),
+        );
+
+        $builder
+            ->add('type', 'choice', array('choices' => $choices, 'required' => false))
+            ->add('text', 'text', array('required' => false))
+        ;
+    }
+}

+ 1 - 1
Guesser/ORM/FilterTypeGuesser.php

@@ -98,7 +98,7 @@ class FilterTypeGuesser implements TypeGuesserInterface
                 return new TypeGuess('doctrine_orm_number', $options, Guess::MEDIUM_CONFIDENCE);
             case 'string':
             case 'text':
-                $options['field_type'] = 'text';
+                $options['field_type'] = 'sonata_type_filter_string';
 
                 return new TypeGuess('doctrine_orm_string', $options, Guess::MEDIUM_CONFIDENCE);
             case 'time':

+ 7 - 0
Resources/config/form_types.xml

@@ -39,6 +39,13 @@
             <argument type="service" id="translator" />
         </service>
 
+        <service id="sonata.admin.form.filter.type.string" class="Sonata\AdminBundle\Form\Type\Filter\StringType">
+            <tag name="form.type" alias="sonata_type_filter_string" />
+
+            <argument type="service" id="translator" />
+        </service>
+
+
         <service id="sonata.admin.form.filter.type.boolean" class="Sonata\AdminBundle\Form\Type\Filter\BooleanType">
             <tag name="form.type" alias="sonata_type_filter_boolean" />
 

+ 33 - 21
Tests/Filter/ORM/StringFilterTest.php

@@ -12,55 +12,67 @@
 namespace Sonata\AdminBundle\Tests\Filter\ORM;
 
 use Sonata\AdminBundle\Filter\ORM\StringFilter;
+use Sonata\AdminBundle\Form\Type\Filter\StringType;
 
 class StringFilterTest extends \PHPUnit_Framework_TestCase
 {
-
-    public function getFieldDescription(array $options)
+    public function testEmpty()
     {
-        $fieldDescription = $this->getMock('Sonata\AdminBundle\Admin\FieldDescriptionInterface');
-        $fieldDescription->expects($this->once())
-            ->method('getOptions')
-            ->will($this->returnValue($options));
+        $filter = new StringFilter;
+        $filter->initialize('field_name', array('field_options' => array('class' => 'FooBar')));
+
+        $builder = new QueryBuilder;
 
-        $fieldDescription->expects($this->once())
-            ->method('getName')
-            ->will($this->returnValue('field_name'));
+        $filter->filter($builder, 'alias', 'field', null);
+        $filter->filter($builder, 'alias', 'field', '');
 
-        return $fieldDescription;
+        $this->assertEquals(array(), $builder->query);
     }
 
-    public function testFilter()
+    public function testContains()
     {
         $filter = new StringFilter;
-        $filter->initialize('field_name', array('field_options' => array('class' => 'FooBar')));
+        $filter->initialize('field_name', array('format' => '%s'));
 
         $builder = new QueryBuilder;
+        $this->assertEquals(array(), $builder->query);
 
-        $filter->filter($builder, 'alias', 'field', null);
-        $filter->filter($builder, 'alias', 'field', '');
+        $filter->filter($builder, 'alias', 'field', array('text' => 'asd', 'type' => StringType::TYPE_CONTAINS));
+        $this->assertEquals(array('alias.field LIKE :field_name'), $builder->query);
+        $this->assertEquals(array('field_name' => 'asd'), $builder->parameters);
 
+
+        $builder = new QueryBuilder;
         $this->assertEquals(array(), $builder->query);
 
-        $filter->filter($builder, 'alias', 'field', 'asd');
+        $filter->filter($builder, 'alias', 'field', array('text' => 'asd', 'type' => null));
         $this->assertEquals(array('alias.field LIKE :field_name'), $builder->query);
-        $this->assertEquals(array('field_name' => '%asd%'), $builder->parameters);
+        $this->assertEquals(array('field_name' => 'asd'), $builder->parameters);
     }
 
-    public function testFormat()
+    public function testNotContains()
     {
         $filter = new StringFilter;
         $filter->initialize('field_name', array('format' => '%s'));
 
         $builder = new QueryBuilder;
+        $this->assertEquals(array(), $builder->query);
 
-        $filter->filter($builder, 'alias', 'field', null);
-        $filter->filter($builder, 'alias', 'field', '');
+        $filter->filter($builder, 'alias', 'field', array('text' => 'asd', 'type' => StringType::TYPE_NOT_CONTAINS));
+        $this->assertEquals(array('alias.field NOT LIKE :field_name'), $builder->query);
+        $this->assertEquals(array('field_name' => 'asd'), $builder->parameters);
+    }
 
+    public function testEquals()
+    {
+        $filter = new StringFilter;
+        $filter->initialize('field_name', array('format' => '%s'));
+
+        $builder = new QueryBuilder;
         $this->assertEquals(array(), $builder->query);
 
-        $filter->filter($builder, 'alias', 'field', 'asd');
-        $this->assertEquals(array('alias.field LIKE :field_name'), $builder->query);
+        $filter->filter($builder, 'alias', 'field', array('text' => 'asd', 'type' => StringType::TYPE_EQUAL));
+        $this->assertEquals(array('alias.field = :field_name'), $builder->query);
         $this->assertEquals(array('field_name' => 'asd'), $builder->parameters);
     }
 }