Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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