Skip to content

Commit d708bb4

Browse files
author
Tomasz Cyrankowski
committed
Added support for Document EmbedOne fields
1 parent 06ae939 commit d708bb4

2 files changed

Lines changed: 102 additions & 33 deletions

File tree

Grid/Source/Document.php

Lines changed: 82 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ class Document extends Source
7373
*/
7474
protected $referencedMappings = [];
7575

76+
/**
77+
* @var array
78+
*/
79+
protected $embedColumns = [];
80+
81+
/**
82+
* @var array
83+
*/
84+
protected $embedMappings = [];
85+
7686
/**
7787
* @param string $documentName e.g. "Cms:Page"
7888
*/
@@ -197,8 +207,12 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr
197207

198208
//checks if exists '.' notation on referenced columns and build query if it's filtered
199209
$subColumn = explode('.', $column->getId());
200-
if (count($subColumn) > 1 && isset($this->referencedMappings[$subColumn[0]])) {
201-
$this->addReferencedColumnn($subColumn, $column);
210+
if (count($subColumn) > 1) {
211+
if (isset($this->referencedMappings[$subColumn[0]])) {
212+
$this->addReferencedColumn($subColumn, $column);
213+
} elseif (isset($this->embedMappings[$subColumn[0]])) {
214+
$this->addEmbedColumn($subColumn, $column);
215+
}
202216

203217
continue;
204218
}
@@ -255,7 +269,11 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr
255269
// As I didn't find out this information, I'm gonna test it with Cursor returned only.
256270
$cursor = $this->query->getQuery()->execute();
257271

258-
$this->count = $cursor->count();
272+
if ($cursor instanceof \Countable) {
273+
$this->count = $cursor->count();
274+
} else {
275+
$this->count = count($cursor->toArray());
276+
}
259277

260278
foreach ($cursor as $resource) {
261279
$row = new Row();
@@ -268,6 +286,7 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr
268286
}
269287

270288
$this->addReferencedFields($row, $resource);
289+
$this->addEmbedFields($row, $resource);
271290

272291
//call overridden prepareRow or associated closure
273292
if (($modifiedRow = $this->prepareRow($row)) !== null) {
@@ -278,11 +297,7 @@ public function execute($columns, $page = 0, $limit = 0, $maxResults = null, $gr
278297
return $result;
279298
}
280299

281-
/**
282-
* @param array $subColumn
283-
* @param Column \APY\DataGridBundle\Grid\Column\Column
284-
*/
285-
protected function addReferencedColumnn(array $subColumn, Column $column)
300+
protected function addReferencedColumn(array $subColumn, Column $column)
286301
{
287302
$this->referencedColumns[$subColumn[0]][] = $subColumn[1];
288303

@@ -298,13 +313,19 @@ protected function addReferencedColumnn(array $subColumn, Column $column)
298313

299314
$cursor = $helperQuery->getQuery()->execute();
300315

316+
if ($cursor instanceof \Countable) {
317+
$count = $cursor->count();
318+
} else {
319+
$count = count($cursor->toArray());
320+
}
321+
301322
foreach ($cursor as $resource) {
302323
// Is this case possible? I don't think so
303-
if ($cursor->count() > 0) {
324+
if ($count > 0) {
304325
$this->query->select($subColumn[0]);
305326
}
306327

307-
if ($cursor->count() == 1) {
328+
if ($count === 1) {
308329
$this->query->field($subColumn[0])->references($resource);
309330
} else {
310331
$this->query->addOr($this->query->expr()->field($subColumn[0])->references($resource));
@@ -314,33 +335,63 @@ protected function addReferencedColumnn(array $subColumn, Column $column)
314335
}
315336
}
316337

338+
protected function addEmbedColumn(array $subColumn, Column $column)
339+
{
340+
$this->embedColumns[$subColumn[0]][] = $subColumn[1];
341+
342+
if ($column->isFiltered()) {
343+
$filters = $column->getFilters('document');
344+
foreach ($filters as $filter) {
345+
$operator = $this->normalizeOperator($filter->getOperator());
346+
$value = $this->normalizeValue($operator, $filter->getValue());
347+
if ($column->getDataJunction() === Column::DATA_DISJUNCTION) {
348+
$this->query->addOr($this->query->expr()->field($column->getField())->$operator($value));
349+
} else {
350+
$this->query->field($column->getField())->$operator($value);
351+
}
352+
}
353+
}
354+
355+
if ($column->isSorted()) {
356+
$this->query->sort($column->getField(), $column->getOrder());
357+
}
358+
}
359+
317360
/**
318-
* @param \APY\DataGridBundle\Grid\Row $row
319-
* @param Document $resource
361+
* @param Row $row
362+
* @param Document $resource
320363
*
321364
* @throws \Exception if getter for field does not exists
322-
*
323-
* @return \APY\DataGridBundle\Grid\Row $row with referenced fields
324365
*/
325366
protected function addReferencedFields(Row $row, $resource)
326367
{
327368
foreach ($this->referencedColumns as $parent => $subColumns) {
328-
$node = $this->getClassProperties($resource);
329-
if (isset($node[strtolower($parent)])) {
330-
$node = $node[strtolower($parent)];
331-
332-
foreach ($subColumns as $field) {
333-
$getter = 'get' . ucfirst($field);
334-
if (method_exists($node, $getter)) {
335-
$row->setField($parent . '.' . $field, $node->$getter());
336-
} else {
337-
throw new \Exception(sprintf('Method %s for Document %s not exists', $getter, $this->referencedMappings[$parent]));
338-
}
369+
$this->addSubfield($row, $resource, $parent, $subColumns);
370+
}
371+
}
372+
373+
protected function addEmbedFields(Row $row, $resource)
374+
{
375+
foreach ($this->embedColumns as $parent => $subColumns) {
376+
$this->addSubfield($row, $resource, $parent, $subColumns);
377+
}
378+
}
379+
380+
protected function addSubfield(Row $row, $resource, $parent, array $subColumns)
381+
{
382+
$node = $this->getClassProperties($resource);
383+
if (isset($node[strtolower($parent)])) {
384+
$node = $node[strtolower($parent)];
385+
386+
foreach ($subColumns as $field) {
387+
$getter = 'get' . ucfirst($field);
388+
if (method_exists($node, $getter)) {
389+
$row->setField($parent . '.' . $field, $node->$getter());
390+
} else {
391+
throw new \Exception(sprintf('Method %s for Document %s not exists', $getter, $this->referencedMappings[$parent]));
339392
}
340393
}
341394
}
342-
343-
return $row;
344395
}
345396

346397
public function getTotalCount($maxResults = null)
@@ -416,17 +467,17 @@ public function getFieldsMetadata($class, $group = 'default')
416467
$values['type'] = 'date';
417468
break;
418469
case 'collection':
470+
case 'many':
419471
$values['type'] = 'array';
420472
break;
421473
case 'one':
422474
$values['type'] = 'array';
423-
if (isset($mapping['reference']) && $mapping['reference'] === true) {
475+
if (isset($mapping['reference']) && true === $mapping['reference']) {
424476
$this->referencedMappings[$name] = $mapping['targetDocument'];
477+
} elseif (isset($mapping['embedded']) && true === $mapping['embedded']) {
478+
$this->embedMappings[$name] = $mapping['targetDocument'];
425479
}
426480
break;
427-
case 'many':
428-
$values['type'] = 'array';
429-
break;
430481
default:
431482
$values['type'] = 'text';
432483
}

Resources/doc/source/document_source.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,29 @@ And the template:
7070
{{ grid(grid) }}
7171
```
7272

73+
## Mapped fields (Referenced or embed) example
74+
75+
```php
76+
/**
77+
* @MongoDB\Document(collection="room")
78+
* @GRID\Source(columns="id, gameParameters, gameParameters.maxPlayers")
79+
*/
80+
class Room
81+
{
82+
/**
83+
* @var GameParameters
84+
* @MongoDB\EmbedOne(targetDocument=GameParameters::class)
85+
* @GRID\Column(field="gameParameters", visible=false)
86+
* @GRID\Column(field="gameParameters.maxPlayers", filterable=true, defaultOperator="eq", type="number")
87+
*/
88+
private $gameParameters;
89+
}
90+
```
91+
92+
7393
## Missing features
7494

75-
* Mapped fileds (Referenced or embed)
7695
* GroupBy attributes and aggregate DQL functions (If someone is skilled with the mapReduce feature, contact us)
77-
* Array column
7896
* Filter doesn't work with a ODM timestamp but it is show as a date and it can be sort
7997

8098
## Unsupported features

0 commit comments

Comments
 (0)