From 96bba5ad2f253f3e0e474e51ac43330d525bc16c Mon Sep 17 00:00:00 2001 From: Tomasz Cyrankowski Date: Sun, 5 Apr 2020 02:01:11 +0200 Subject: [PATCH] Added support for Document EmbedOne fields --- Grid/Source/Document.php | 100 +++++++++++++++++------- Resources/doc/source/document_source.md | 22 +++++- 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/Grid/Source/Document.php b/Grid/Source/Document.php index d72efa9a..e2a225fb 100644 --- a/Grid/Source/Document.php +++ b/Grid/Source/Document.php @@ -73,6 +73,16 @@ class Document extends Source */ protected $referencedMappings = []; + /** + * @var array + */ + protected $embedColumns = []; + + /** + * @var array + */ + protected $embedMappings = []; + /** * @param string $documentName e.g. "Cms:Page" */ @@ -197,8 +207,12 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr //checks if exists '.' notation on referenced columns and build query if it's filtered $subColumn = explode('.', $column->getId()); - if (count($subColumn) > 1 && isset($this->referencedMappings[$subColumn[0]])) { - $this->addReferencedColumnn($subColumn, $column); + if (count($subColumn) > 1) { + if (isset($this->referencedMappings[$subColumn[0]])) { + $this->addReferencedColumn($subColumn, $column); + } elseif (isset($this->embedMappings[$subColumn[0]])) { + $this->addEmbedColumn($subColumn, $column); + } continue; } @@ -254,7 +268,6 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr // I really don't know if Cursor is the right type returned (I mean, every single type). // As I didn't find out this information, I'm gonna test it with Cursor returned only. $cursor = $this->query->getQuery()->execute(); - $this->count = $cursor->count(); foreach ($cursor as $resource) { @@ -268,6 +281,7 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr } $this->addReferencedFields($row, $resource); + $this->addEmbedFields($row, $resource); //call overridden prepareRow or associated closure if (($modifiedRow = $this->prepareRow($row)) !== null) { @@ -278,11 +292,7 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr return $result; } - /** - * @param array $subColumn - * @param Column \APY\DataGridBundle\Grid\Column\Column - */ - protected function addReferencedColumnn(array $subColumn, Column $column) + protected function addReferencedColumn(array $subColumn, Column $column) { $this->referencedColumns[$subColumn[0]][] = $subColumn[1]; @@ -304,7 +314,7 @@ protected function addReferencedColumnn(array $subColumn, Column $column) $this->query->select($subColumn[0]); } - if ($cursor->count() == 1) { + if ($cursor->count() === 1) { $this->query->field($subColumn[0])->references($resource); } else { $this->query->addOr($this->query->expr()->field($subColumn[0])->references($resource)); @@ -314,33 +324,63 @@ protected function addReferencedColumnn(array $subColumn, Column $column) } } + protected function addEmbedColumn(array $subColumn, Column $column) + { + $this->embedColumns[$subColumn[0]][] = $subColumn[1]; + + if ($column->isFiltered()) { + $filters = $column->getFilters('document'); + foreach ($filters as $filter) { + $operator = $this->normalizeOperator($filter->getOperator()); + $value = $this->normalizeValue($operator, $filter->getValue()); + if ($column->getDataJunction() === Column::DATA_DISJUNCTION) { + $this->query->addOr($this->query->expr()->field($column->getField())->$operator($value)); + } else { + $this->query->field($column->getField())->$operator($value); + } + } + } + + if ($column->isSorted()) { + $this->query->sort($column->getField(), $column->getOrder()); + } + } + /** - * @param \APY\DataGridBundle\Grid\Row $row - * @param Document $resource + * @param Row $row + * @param Document $resource * * @throws \Exception if getter for field does not exists - * - * @return \APY\DataGridBundle\Grid\Row $row with referenced fields */ protected function addReferencedFields(Row $row, $resource) { foreach ($this->referencedColumns as $parent => $subColumns) { - $node = $this->getClassProperties($resource); - if (isset($node[strtolower($parent)])) { - $node = $node[strtolower($parent)]; - - foreach ($subColumns as $field) { - $getter = 'get' . ucfirst($field); - if (method_exists($node, $getter)) { - $row->setField($parent . '.' . $field, $node->$getter()); - } else { - throw new \Exception(sprintf('Method %s for Document %s not exists', $getter, $this->referencedMappings[$parent])); - } + $this->addSubfield($row, $resource, $parent, $subColumns); + } + } + + protected function addEmbedFields(Row $row, $resource) + { + foreach ($this->embedColumns as $parent => $subColumns) { + $this->addSubfield($row, $resource, $parent, $subColumns); + } + } + + protected function addSubfield(Row $row, $resource, $parent, array $subColumns) + { + $node = $this->getClassProperties($resource); + if (isset($node[strtolower($parent)])) { + $node = $node[strtolower($parent)]; + + foreach ($subColumns as $field) { + $getter = 'get' . ucfirst($field); + if (method_exists($node, $getter)) { + $row->setField($parent . '.' . $field, $node->$getter()); + } else { + throw new \Exception(sprintf('Method %s for Document %s not exists', $getter, $this->referencedMappings[$parent])); } } } - - return $row; } public function getTotalCount($maxResults = null) @@ -416,17 +456,17 @@ public function getFieldsMetadata($class, $group = 'default') $values['type'] = 'date'; break; case 'collection': + case 'many': $values['type'] = 'array'; break; case 'one': $values['type'] = 'array'; - if (isset($mapping['reference']) && $mapping['reference'] === true) { + if (isset($mapping['reference']) && true === $mapping['reference']) { $this->referencedMappings[$name] = $mapping['targetDocument']; + } elseif (isset($mapping['embedded']) && true === $mapping['embedded']) { + $this->embedMappings[$name] = $mapping['targetDocument']; } break; - case 'many': - $values['type'] = 'array'; - break; default: $values['type'] = 'text'; } diff --git a/Resources/doc/source/document_source.md b/Resources/doc/source/document_source.md index 4ba0237f..f160eb2c 100644 --- a/Resources/doc/source/document_source.md +++ b/Resources/doc/source/document_source.md @@ -70,11 +70,29 @@ And the template: {{ grid(grid) }} ``` +## Mapped fields (Referenced or embed) example + +```php +/** + * @MongoDB\Document(collection="room") + * @GRID\Source(columns="id, gameParameters, gameParameters.maxPlayers") + */ +class Room +{ + /** + * @var GameParameters + * @MongoDB\EmbedOne(targetDocument=GameParameters::class) + * @GRID\Column(field="gameParameters", visible=false) + * @GRID\Column(field="gameParameters.maxPlayers", filterable=true, defaultOperator="eq", type="number") + */ + private $gameParameters; +} +``` + + ## Missing features -* Mapped fileds (Referenced or embed) * GroupBy attributes and aggregate DQL functions (If someone is skilled with the mapReduce feature, contact us) -* Array column * Filter doesn't work with a ODM timestamp but it is show as a date and it can be sort ## Unsupported features