Procházet zdrojové kódy

Fix filters parameter names to avoid conflict due to dot in names.

Romain Geissler před 13 roky
rodič
revize
034daa4266

+ 12 - 7
Filter/AbstractDateFilter.php

@@ -49,15 +49,18 @@ abstract class AbstractDateFilter extends Filter
             //default type for range filter
             $data['type'] = !isset($data['type']) || !is_numeric($data['type']) ?  DateRangeType::TYPE_BETWEEN : $data['type'];
 
+            $startDateParameterName = $this->getNewParameterName();
+            $endDateParameterName = $this->getNewParameterName();
+
             if ($data['type'] == DateRangeType::TYPE_NOT_BETWEEN) {
-                $this->applyWhere($queryBuilder, sprintf('%s.%s < :%s OR %s.%s > :%s', $alias, $field, $this->getName().'_start', $alias, $field, $this->getName().'_end'));
+                $this->applyWhere($queryBuilder, sprintf('%s.%s < :%s OR %s.%s > :%s', $alias, $field, $startDateParameterName, $alias, $field, $endDateParameterName));
             } else {
-                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '>=', $this->getName().'_start'));
-                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '<=', $this->getName().'_end'));
+                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '>=', $startDateParameterName));
+                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '<=', $endDateParameterName));
             }
 
-            $queryBuilder->setParameter($this->getName().'_start',  $data['value']['start']);
-            $queryBuilder->setParameter($this->getName().'_end',  $data['value']['end']);
+            $queryBuilder->setParameter($startDateParameterName,  $data['value']['start']);
+            $queryBuilder->setParameter($endDateParameterName,  $data['value']['end']);
         } else {
 
             if (!$data['value']) {
@@ -74,8 +77,10 @@ abstract class AbstractDateFilter extends Filter
             if (in_array($operator, array('NULL', 'NOT NULL'))) {
                 $this->applyWhere($queryBuilder, sprintf('%s.%s IS %s ', $alias, $field, $operator));
             } else {
-                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $this->getName()));
-                $queryBuilder->setParameter($this->getName(), $data['value']);
+                $parameterName = $this->getNewParameterName();
+
+                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $parameterName));
+                $queryBuilder->setParameter($parameterName, $data['value']);
             }
         }
     }

+ 3 - 2
Filter/BooleanFilter.php

@@ -49,8 +49,9 @@ class BooleanFilter extends Filter
                 return;
             }
 
-            $this->applyWhere($queryBuilder, sprintf('%s.%s = :%s', $alias, $field, $this->getName()));
-            $queryBuilder->setParameter($this->getName(), ($data['value'] == BooleanType::TYPE_YES) ? 1 : 0);
+            $parameterName = $this->getNewParameterName();
+            $this->applyWhere($queryBuilder, sprintf('%s.%s = :%s', $alias, $field, $parameterName));
+            $queryBuilder->setParameter($parameterName, ($data['value'] == BooleanType::TYPE_YES) ? 1 : 0);
         }
     }
 

+ 5 - 3
Filter/ChoiceFilter.php

@@ -50,13 +50,15 @@ class ChoiceFilter extends Filter
                 return;
             }
 
+            $parameterName = $this->getNewParameterName();
+
             if ($data['type'] == ChoiceType::TYPE_NOT_CONTAINS) {
-                $this->applyWhere($queryBuilder, sprintf('%s.%s <> :%s', $alias, $field, $this->getName()));
+                $this->applyWhere($queryBuilder, sprintf('%s.%s <> :%s', $alias, $field, $parameterName));
             } else {
-                $this->applyWhere($queryBuilder, sprintf('%s.%s = :%s', $alias, $field, $this->getName()));
+                $this->applyWhere($queryBuilder, sprintf('%s.%s = :%s', $alias, $field, $parameterName));
             }
 
-            $queryBuilder->setParameter($this->getName(), $data['value']);
+            $queryBuilder->setParameter($parameterName, $data['value']);
         }
     }
 

+ 11 - 0
Filter/Filter.php

@@ -16,6 +16,7 @@ use Sonata\AdminBundle\Filter\Filter as BaseFilter;
 abstract class Filter extends BaseFilter
 {
     protected $active = false;
+    protected $parameterUniqueId = 0;
 
     public function apply($queryBuilder, $value)
     {
@@ -43,6 +44,16 @@ abstract class Filter extends BaseFilter
         $this->active = true;
     }
 
+    protected function getNewParameterName()
+    {
+        // dots are not accepted in a DQL identifier so replace them
+        // by underscores. To avoid any name conflict with two filters
+        // named myEntity.myProperty and myEntity_myProperty used at the
+        // same time, we also use the object hash, that are different
+        // for two objects alive at the same time.
+        return str_replace('.', '_', $this->getName()).'_'.spl_object_hash($this).'_'.($this->parameterUniqueId++);
+    }
+
     public function isActive()
     {
         return $this->active;

+ 15 - 9
Filter/ModelFilter.php

@@ -43,13 +43,15 @@ class ModelFilter extends Filter
             return;
         }
 
+        $parameterName = $this->getNewParameterName();
+
         if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) {
-            $this->applyWhere($queryBuilder, $queryBuilder->expr()->notIn($alias, ':'.$this->getName()));
+            $this->applyWhere($queryBuilder, $queryBuilder->expr()->notIn($alias, ':'.$parameterName));
         } else {
-            $this->applyWhere($queryBuilder, $queryBuilder->expr()->in($alias, ':'.$this->getName()));
+            $this->applyWhere($queryBuilder, $queryBuilder->expr()->in($alias, ':'.$parameterName));
         }
 
-        $queryBuilder->setParameter($this->getName(), $data['value']->toArray());
+        $queryBuilder->setParameter($parameterName, $data['value']->toArray());
     }
 
     protected function handleModel($queryBuilder, $alias, $field, $data)
@@ -58,17 +60,21 @@ class ModelFilter extends Filter
             return;
         }
 
+        $parameterName = $this->getNewParameterName();
+
         if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) {
-            $this->applyWhere($queryBuilder, sprintf('%s != :%s', $alias, $this->getName()));
+            $this->applyWhere($queryBuilder, sprintf('%s != :%s', $alias, $parameterName));
         } else {
-            $this->applyWhere($queryBuilder, sprintf('%s = :%s', $alias, $this->getName()));
+            $this->applyWhere($queryBuilder, sprintf('%s = :%s', $alias, $parameterName));
         }
 
-        $queryBuilder->setParameter($this->getName(), $data['value']);
+        $queryBuilder->setParameter($parameterName, $data['value']);
     }
 
     protected function association($queryBuilder, $data)
     {
+        list($alias, $field) = parent::association($queryBuilder, $data);
+
         $types = array(
             ClassMetadataInfo::ONE_TO_ONE,
             ClassMetadataInfo::ONE_TO_MANY,
@@ -84,11 +90,11 @@ class ModelFilter extends Filter
             throw new \RunTimeException('Please provide a field_name options');
         }
 
-        $alias = 's_'.$this->getName();
+        $newAlias = $alias.'_'.$field;
 
-        $queryBuilder->leftJoin(sprintf('%s.%s', $queryBuilder->getRootAlias(), $this->getFieldName()), $alias);
+        $queryBuilder->leftJoin(sprintf('%s.%s', $alias, $field), $newAlias);
 
-        return array($alias, 'id');
+        return array($newAlias, false);
     }
 
     public function getDefaultOptions()

+ 3 - 2
Filter/NumberFilter.php

@@ -37,8 +37,9 @@ class NumberFilter extends Filter
         }
 
         // c.name > '1' => c.name OPERATOR :FIELDNAME
-        $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $this->getName()));
-        $queryBuilder->setParameter($this->getName(),  $data['value']);
+        $parameterName = $this->getNewParameterName();
+        $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $parameterName));
+        $queryBuilder->setParameter($parameterName,  $data['value']);
     }
 
     /**

+ 4 - 3
Filter/StringFilter.php

@@ -43,12 +43,13 @@ class StringFilter extends Filter
         }
 
         // c.name > '1' => c.name OPERATOR :FIELDNAME
-        $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $this->getName()));
+        $parameterName = $this->getNewParameterName();
+        $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $parameterName));
 
         if ($data['type'] == ChoiceType::TYPE_EQUAL) {
-            $queryBuilder->setParameter($this->getName(), $data['value']);
+            $queryBuilder->setParameter($parameterName, $data['value']);
         } else {
-            $queryBuilder->setParameter($this->getName(), sprintf($this->getOption('format'), $data['value']));
+            $queryBuilder->setParameter($parameterName, sprintf($this->getOption('format'), $data['value']));
         }
     }