Skip to content

Commit

Permalink
Added support for Document EmbedOne fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomasz Cyrankowski committed Apr 7, 2020
1 parent 06ae939 commit 96bba5a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 32 deletions.
100 changes: 70 additions & 30 deletions Grid/Source/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"
*/
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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];

Expand All @@ -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));
Expand All @@ -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)
Expand Down Expand Up @@ -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';
}
Expand Down
22 changes: 20 additions & 2 deletions Resources/doc/source/document_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 96bba5a

Please sign in to comment.