From 35fbc34c49251785712356c11f7bf8eb2eb56941 Mon Sep 17 00:00:00 2001 From: Jose Lopes Date: Tue, 26 May 2015 10:50:46 +0100 Subject: [PATCH 1/5] Added doctrine_mongo_autocomplete model filter --- Builder/DatagridBuilder.php | 11 ++ Filter/ModelAutocompleteFilter.php | 162 ++++++++++++++++++ Filter/ModelFilter.php | 8 +- .../config/doctrine_mongodb_filter_types.xml | 4 + 4 files changed, 178 insertions(+), 7 deletions(-) create mode 100644 Filter/ModelAutocompleteFilter.php diff --git a/Builder/DatagridBuilder.php b/Builder/DatagridBuilder.php index a308d3c1..baf3a831 100644 --- a/Builder/DatagridBuilder.php +++ b/Builder/DatagridBuilder.php @@ -121,6 +121,17 @@ public function addFilter(DatagridInterface $datagrid, $type = null, FieldDescri $admin->addFilterFieldDescription($fieldDescription->getName(), $fieldDescription); $fieldDescription->mergeOption('field_options', array('required' => false)); + + if ($type === 'doctrine_mongo_autocomplete') { + $fieldDescription->mergeOption('field_options', array( + 'class' => $fieldDescription->getTargetEntity(), + 'model_manager' => $fieldDescription->getAdmin()->getModelManager(), + 'admin_code' => $admin->getCode(), + 'context' => 'filter', + )); + $admin->attachAdminClass($fieldDescription); + } + $filter = $this->filterFactory->create($fieldDescription->getName(), $type, $fieldDescription->getOptions()); if (false !== $filter->getLabel() && !$filter->getLabel()) { diff --git a/Filter/ModelAutocompleteFilter.php b/Filter/ModelAutocompleteFilter.php new file mode 100644 index 00000000..519686fc --- /dev/null +++ b/Filter/ModelAutocompleteFilter.php @@ -0,0 +1,162 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\DoctrineMongoDBAdminBundle\Filter; + +use Sonata\CoreBundle\Form\Type\EqualType; +use Sonata\AdminBundle\Datagrid\ProxyQueryInterface; +use Doctrine\Common\Collections\Collection; + +class ModelAutocompleteFilter extends Filter +{ + + public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data) + { + if (!$data || !is_array($data) || !array_key_exists('value', $data)) { + return; + } + + if ($data['value'] instanceof Collection) { + $data['value'] = $data['value']->toArray(); + } + + $field = $this->getIdentifierField($field); + + if (is_array($data['value'])) { + $this->handleMultiple($queryBuilder, $alias, $field, $data); + } else { + $this->handleScalar($queryBuilder, $alias, $field, $data); + } + + } + + /** + * + * @param ProxyQueryInterface $queryBuilder + * @param type $alias + * @param type $field + * @param type $data + * @return type + */ + protected function handleMultiple(ProxyQueryInterface $queryBuilder, $alias, $field, $data) + { + if (count($data['value']) == 0) { + return; + } + + $ids = array(); + foreach ($data['value'] as $value) { + $ids[] = self::fixIdentifier($value->getId()); + } + + if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) { + $queryBuilder->field($field)->notIn($ids); + } else { + $queryBuilder->field($field)->in($ids); + } + + $this->active = true; + } + + /** + * + * @param ProxyQueryInterface $queryBuilder + * @param type $alias + * @param type $field + * @param type $data + * @return type + */ + protected function handleScalar(ProxyQueryInterface $queryBuilder, $alias, $field, $data) + { + if (empty($data['value'])) { + return; + } + + $id = self::fixIdentifier($data['value']->getId()); + + if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) { + $queryBuilder->field($field)->notEqual($id); + } else { + $queryBuilder->field($field)->equals($id); + } + + $this->active = true; + } + + /** + * {@inheritdoc} + */ + protected function association(ProxyQueryInterface $queryBuilder, $data) + { + $associationMappings = $this->getParentAssociationMappings(); + $associationMappings[] = $this->getAssociationMapping(); + $alias = $queryBuilder->entityJoin($associationMappings); + + return array($alias, false); + } + + /** + * Return \MongoId if $id is MongoId in string representation, otherwise custom string + * + * @param mixed $id + * @return \MongoId|string + */ + protected static function fixIdentifier($id) + { + try { + return new \MongoId($id); + } catch (\MongoException $ex) { + return $id; + } + } + + /** + * Identifier field name is 'field' if mapping type is simple; otherwise, it's 'field.$id' + * + * @param string $field + * @return string + */ + protected function getIdentifierField($field) + { + $field_mapping = $this->getFieldMapping(); + + return (true === $field_mapping['simple']) ? $field : $field . '.$id'; + } + + /** + * {@inheritdoc} + */ + public function getDefaultOptions() + { + return array( + 'field_name' => false, + 'field_type' => 'sonata_type_model_autocomplete', + 'field_options' => array(), + 'operator_type' => 'sonata_type_equal', + 'operator_options' => array(), + ); + } + + /** + * {@inheritdoc} + */ + public function getRenderSettings() + { + return array('sonata_type_filter_default', array( + 'field_type' => $this->getFieldType(), + 'field_options' => $this->getFieldOptions(), + 'operator_type' => $this->getOption('operator_type'), + 'operator_options' => $this->getOption('operator_options'), + 'label' => $this->getLabel() + )); + } +} + diff --git a/Filter/ModelFilter.php b/Filter/ModelFilter.php index 1b27dc31..bf73c3b6 100644 --- a/Filter/ModelFilter.php +++ b/Filter/ModelFilter.php @@ -18,13 +18,7 @@ class ModelFilter extends Filter { - /** - * @param ProxyQueryInterface $queryBuilder - * @param string $alias - * @param string $field - * @param mixed $data - * @return - */ + public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data) { if (!$data || !is_array($data) || !array_key_exists('value', $data)) { diff --git a/Resources/config/doctrine_mongodb_filter_types.xml b/Resources/config/doctrine_mongodb_filter_types.xml index f5e5e3f4..319751df 100644 --- a/Resources/config/doctrine_mongodb_filter_types.xml +++ b/Resources/config/doctrine_mongodb_filter_types.xml @@ -28,6 +28,10 @@ + + + + From 3d277409e4775d06950187d42e54ebc2b94e524f Mon Sep 17 00:00:00 2001 From: Jose Lopes Date: Tue, 26 May 2015 16:56:02 +0100 Subject: [PATCH 2/5] DataGrid to the last version of the ORM (more similar) with the attachAdmiClass on the fixFieldDescription as ORM -- Added getFieldName on Filter to respect the parents associations mappings --- Builder/DatagridBuilder.php | 34 ++++++++++++++++++++++++++++++++-- Filter/Filter.php | 18 ++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/Builder/DatagridBuilder.php b/Builder/DatagridBuilder.php index baf3a831..8c0ff5ca 100644 --- a/Builder/DatagridBuilder.php +++ b/Builder/DatagridBuilder.php @@ -12,6 +12,7 @@ namespace Sonata\DoctrineMongoDBAdminBundle\Builder; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; use Sonata\DoctrineMongoDBAdminBundle\Datagrid\Pager; use Sonata\AdminBundle\Admin\FieldDescriptionInterface; @@ -21,6 +22,7 @@ use Sonata\AdminBundle\Builder\DatagridBuilderInterface; use Sonata\AdminBundle\Guesser\TypeGuesserInterface; use Sonata\AdminBundle\Filter\FilterFactoryInterface; + use Symfony\Component\Form\FormFactory; class DatagridBuilder implements DatagridBuilderInterface @@ -85,6 +87,10 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter $fieldDescription->setOption('code', $fieldDescription->getOption('code', $fieldDescription->getName())); $fieldDescription->setOption('name', $fieldDescription->getOption('name', $fieldDescription->getName())); + + if (in_array($fieldDescription->getMappingType(), array(ClassMetadataInfo::ONE, ClassMetadataInfo::MANY, ClassMetadataInfo::REFERENCE_MANY, ClassMetadataInfo::REFERENCE_ONE ))) { + $admin->attachAdminClass($fieldDescription); + } } /** @@ -129,7 +135,6 @@ public function addFilter(DatagridInterface $datagrid, $type = null, FieldDescri 'admin_code' => $admin->getCode(), 'context' => 'filter', )); - $admin->attachAdminClass($fieldDescription); } $filter = $this->filterFactory->create($fieldDescription->getName(), $type, $fieldDescription->getOptions()); @@ -150,7 +155,8 @@ public function addFilter(DatagridInterface $datagrid, $type = null, FieldDescri */ public function getBaseDatagrid(AdminInterface $admin, array $values = array()) { - $pager = new Pager; + $pager = $this->getPager($admin->getPagerType()); + $pager->setCountColumn($admin->getModelManager()->getIdentifierFieldNames($admin->getClass())); $defaultOptions = array(); @@ -162,4 +168,28 @@ public function getBaseDatagrid(AdminInterface $admin, array $values = array()) return new Datagrid($admin->createQuery(), $admin->getList(), $pager, $formBuilder, $values); } + + /** + * Get pager by pagerType + * + * @param string $pagerType + * + * @return \Sonata\AdminBundle\Datagrid\PagerInterface + * + * @throws \RuntimeException If invalid pager type is set. + */ + protected function getPager($pagerType) + { + switch ($pagerType) { + case Pager::TYPE_DEFAULT: + return new Pager(); + + // TODO: Implement a Simple page that extends Simple Pager from admin? + //case Pager::TYPE_SIMPLE: + // return new SimplePager(); + + default: + throw new \RuntimeException(sprintf('Unknown pager type "%s".', $pagerType)); + } + } } diff --git a/Filter/Filter.php b/Filter/Filter.php index 6301e52e..eff5af3f 100644 --- a/Filter/Filter.php +++ b/Filter/Filter.php @@ -28,6 +28,24 @@ public function apply($queryBuilder, $value) $this->filter($queryBuilder, null, $this->getFieldName(), $value); } + public function getFieldName() + { + $fieldName = $this->getOption('field_name'); + + foreach($this->getOption('parent_association_mappings') as $map) { + if(!empty($map['name'])) { + $fieldName = $map['name'] . "." . $fieldName; + } elseif (!empty($map['fieldName'])) { + $fieldName = $map['fieldName'] . $fieldName; + } + } + if (!$fieldName) { + throw new \RuntimeException(sprintf('The option `field_name` must be set for field: `%s`', $this->getName())); + } + + return $fieldName; + } + /** * {@inheritdoc} */ From 86c1181e844e3714e48fb30fd1482f917bffb8c5 Mon Sep 17 00:00:00 2001 From: Jose Lopes Date: Tue, 26 May 2015 17:52:42 +0100 Subject: [PATCH 3/5] Removed the TODO's --- Builder/DatagridBuilder.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Builder/DatagridBuilder.php b/Builder/DatagridBuilder.php index 8c0ff5ca..385793bd 100644 --- a/Builder/DatagridBuilder.php +++ b/Builder/DatagridBuilder.php @@ -183,11 +183,6 @@ protected function getPager($pagerType) switch ($pagerType) { case Pager::TYPE_DEFAULT: return new Pager(); - - // TODO: Implement a Simple page that extends Simple Pager from admin? - //case Pager::TYPE_SIMPLE: - // return new SimplePager(); - default: throw new \RuntimeException(sprintf('Unknown pager type "%s".', $pagerType)); } From b41861c2dfb74a0100245d4fcff1c26f683bc9e7 Mon Sep 17 00:00:00 2001 From: Jose Lopes Date: Mon, 8 Jun 2015 10:09:53 +0100 Subject: [PATCH 4/5] Fixed tests -- bug on Filter --- Filter/Filter.php | 13 ++++++++----- composer.json | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Filter/Filter.php b/Filter/Filter.php index eff5af3f..3d35cab6 100644 --- a/Filter/Filter.php +++ b/Filter/Filter.php @@ -32,13 +32,16 @@ public function getFieldName() { $fieldName = $this->getOption('field_name'); - foreach($this->getOption('parent_association_mappings') as $map) { - if(!empty($map['name'])) { - $fieldName = $map['name'] . "." . $fieldName; - } elseif (!empty($map['fieldName'])) { - $fieldName = $map['fieldName'] . $fieldName; + if (is_array($this->getOption('parent_association_mappings'))) { + foreach($this->getOption('parent_association_mappings') as $map) { + if(!empty($map['name'])) { + $fieldName = $map['name'] . "." . $fieldName; + } elseif (!empty($map['fieldName'])) { + $fieldName = $map['fieldName'] . $fieldName; + } } } + if (!$fieldName) { throw new \RuntimeException(sprintf('The option `field_name` must be set for field: `%s`', $this->getName())); } diff --git a/composer.json b/composer.json index efdd4e7a..0152b722 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "sonata-project/admin-bundle": "~2.3" }, "require-dev": { - "jmikola/geojson": "~1.0" + "jmikola/geojson": "~1.0", + "phpunit/phpunit": "~4.0" }, "provide": { "sonata-project/admin-bundle-persistency-layer": "1.0.0" From 37f39046eb40995ec294031d302e01c9d0597565 Mon Sep 17 00:00:00 2001 From: Jose Lopes Date: Thu, 17 Sep 2015 10:15:36 +0100 Subject: [PATCH 5/5] Soullivaneuh Reviews --- Builder/DatagridBuilder.php | 20 ++++++++++---------- Filter/Filter.php | 9 +++------ Filter/ModelAutocompleteFilter.php | 17 +++++++---------- composer.json | 1 - 4 files changed, 20 insertions(+), 27 deletions(-) diff --git a/Builder/DatagridBuilder.php b/Builder/DatagridBuilder.php index df01e142..3eecc952 100644 --- a/Builder/DatagridBuilder.php +++ b/Builder/DatagridBuilder.php @@ -13,6 +13,7 @@ namespace Sonata\DoctrineMongoDBAdminBundle\Builder; use Doctrine\ODM\MongoDB\Mapping\ClassMetadataInfo; +use Sonata\AdminBundle\Datagrid\PagerInterface; use Sonata\DoctrineMongoDBAdminBundle\Datagrid\Pager; use Sonata\AdminBundle\Admin\FieldDescriptionInterface; use Sonata\AdminBundle\Admin\AdminInterface; @@ -53,8 +54,8 @@ public function __construct(FormFactory $formFactory, FilterFactoryInterface $fi } /** - * @param \Sonata\AdminBundle\Admin\AdminInterface $admin - * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription + * @param AdminInterface $admin + * @param FieldDescriptionInterface $fieldDescription */ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription) { @@ -90,10 +91,10 @@ public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInter } /** - * @param \Sonata\AdminBundle\Datagrid\DatagridInterface $datagrid + * @param DatagridInterface $datagrid * @param null $type - * @param \Sonata\AdminBundle\Admin\FieldDescriptionInterface $fieldDescription - * @param \Sonata\AdminBundle\Admin\AdminInterface $admin + * @param FieldDescriptionInterface $fieldDescription + * @param AdminInterface $admin */ public function addFilter(DatagridInterface $datagrid, $type = null, FieldDescriptionInterface $fieldDescription, AdminInterface $admin) { @@ -122,7 +123,7 @@ public function addFilter(DatagridInterface $datagrid, $type = null, FieldDescri $fieldDescription->mergeOption('field_options', array('required' => false)); - if ($type === 'doctrine_mongo_autocomplete') { + if ('doctrine_mongo_autocomplete' === $type) { $fieldDescription->mergeOption('field_options', array( 'class' => $fieldDescription->getTargetEntity(), 'model_manager' => $fieldDescription->getAdmin()->getModelManager(), @@ -141,10 +142,10 @@ public function addFilter(DatagridInterface $datagrid, $type = null, FieldDescri } /** - * @param \Sonata\AdminBundle\Admin\AdminInterface $admin + * @param AdminInterface $admin * @param array $values * - * @return \Sonata\AdminBundle\Datagrid\DatagridInterface + * @return DatagridInterface */ public function getBaseDatagrid(AdminInterface $admin, array $values = array()) { @@ -166,8 +167,7 @@ public function getBaseDatagrid(AdminInterface $admin, array $values = array()) * * @param string $pagerType * - * @return \Sonata\AdminBundle\Datagrid\PagerInterface - * + * @return PagerInterface * @throws \RuntimeException If invalid pager type is set. */ protected function getPager($pagerType) diff --git a/Filter/Filter.php b/Filter/Filter.php index a1ff5c4b..bb9152cb 100644 --- a/Filter/Filter.php +++ b/Filter/Filter.php @@ -19,19 +19,18 @@ abstract class Filter extends BaseFilter protected $active = false; /** - * {@inheritdoc} + * @param mixed $queryBuilder + * @param mixed $value */ public function apply($queryBuilder, $value) { $this->value = $value; - $this->filter($queryBuilder, null, $this->getFieldName(), $value); } public function getFieldName() { $fieldName = $this->getOption('field_name'); - if (is_array($this->getOption('parent_association_mappings'))) { foreach($this->getOption('parent_association_mappings') as $map) { if(!empty($map['name'])) { @@ -41,16 +40,14 @@ public function getFieldName() } } } - if (!$fieldName) { throw new \RuntimeException(sprintf('The option `field_name` must be set for field: `%s`', $this->getName())); } - return $fieldName; } /** - * {@inheritdoc} + * @return bool */ public function isActive() { diff --git a/Filter/ModelAutocompleteFilter.php b/Filter/ModelAutocompleteFilter.php index 519686fc..ad12dbc0 100644 --- a/Filter/ModelAutocompleteFilter.php +++ b/Filter/ModelAutocompleteFilter.php @@ -3,7 +3,8 @@ /* * This file is part of the Sonata package. * - * (c) Thomas Rabaix + * (c) Thomas Rabaix + * (c) Kévin Dunglas * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -15,6 +16,11 @@ use Sonata\AdminBundle\Datagrid\ProxyQueryInterface; use Doctrine\Common\Collections\Collection; +/** + * Class ModelAutocompleteFilter + * @author Jose Lopes + * @package Sonata\DoctrineMongoDBAdminBundle\Filter + */ class ModelAutocompleteFilter extends Filter { @@ -23,19 +29,15 @@ public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data) if (!$data || !is_array($data) || !array_key_exists('value', $data)) { return; } - if ($data['value'] instanceof Collection) { $data['value'] = $data['value']->toArray(); } - $field = $this->getIdentifierField($field); - if (is_array($data['value'])) { $this->handleMultiple($queryBuilder, $alias, $field, $data); } else { $this->handleScalar($queryBuilder, $alias, $field, $data); } - } /** @@ -51,7 +53,6 @@ protected function handleMultiple(ProxyQueryInterface $queryBuilder, $alias, $fi if (count($data['value']) == 0) { return; } - $ids = array(); foreach ($data['value'] as $value) { $ids[] = self::fixIdentifier($value->getId()); @@ -62,7 +63,6 @@ protected function handleMultiple(ProxyQueryInterface $queryBuilder, $alias, $fi } else { $queryBuilder->field($field)->in($ids); } - $this->active = true; } @@ -79,15 +79,12 @@ protected function handleScalar(ProxyQueryInterface $queryBuilder, $alias, $fiel if (empty($data['value'])) { return; } - $id = self::fixIdentifier($data['value']->getId()); - if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) { $queryBuilder->field($field)->notEqual($id); } else { $queryBuilder->field($field)->equals($id); } - $this->active = true; } diff --git a/composer.json b/composer.json index bceb2931..855c289a 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ }, "require-dev": { "jmikola/geojson": "~1.0", - "phpunit/phpunit": "~4.0", "symfony/phpunit-bridge": "~2.7|~3.0", "fabpot/php-cs-fixer": "~0.5|~1.0" },