Skip to content

Commit

Permalink
Make ObjectIterator compatible with Doctrine Collections
Browse files Browse the repository at this point in the history
Ensure Collection::get() hydrates a document

Handle conversion in ObjectIterator::first() and ObjectIterator::last()

Handle conversion for ObjectIterator methods that return values

Add tests for ObjectCallbackIterator

CS fixes for ObjectIterator
  • Loading branch information
mcrumm committed Apr 4, 2017
1 parent 162bbe1 commit 146fa76
Show file tree
Hide file tree
Showing 11 changed files with 409 additions and 128 deletions.
104 changes: 5 additions & 99 deletions Collection/Collection.php
Expand Up @@ -11,107 +11,13 @@

namespace ONGR\ElasticsearchBundle\Collection;

use Doctrine\Common\Collections\ArrayCollection;

/**
* This class is a holder for collection of objects.
*
* @deprecated Use Doctrine\Common\Collections\ArrayCollection instead.
*/
class Collection implements \Countable, \Iterator, \ArrayAccess
class Collection extends ArrayCollection
{
/**
* @var array
*/
private $elements = [];

/**
* Constructor.
*
* @param array $elements
*/
public function __construct(array $elements = [])
{
$this->elements = $elements;
}

/**
* {@inheritdoc}
*/
public function current()
{
return current($this->elements);
}

/**
* {@inheritdoc}
*/
public function next()
{
next($this->elements);
}

/**
* {@inheritdoc}
*/
public function key()
{
return key($this->elements);
}

/**
* {@inheritdoc}
*/
public function valid()
{
return $this->offsetExists($this->key());
}

/**
* {@inheritdoc}
*/
public function rewind()
{
reset($this->elements);
}

/**
* {@inheritdoc}
*/
public function offsetExists($offset)
{
return array_key_exists($offset, $this->elements);
}

/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
return $this->elements[$offset];
}

/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{
if ($offset === null) {
$this->elements[] = $value;
} else {
$this->elements[$offset] = $value;
}
}

/**
* {@inheritdoc}
*/
public function offsetUnset($offset)
{
unset($this->elements[$offset]);
}

/**
* {@inheritdoc}
*/
public function count()
{
return count($this->elements);
}
}
8 changes: 4 additions & 4 deletions Resources/doc/mapping.md
Expand Up @@ -337,7 +337,7 @@ To insert a document with mapping from example above you have to create 2 object
As shown in the example above, by ElasticsearchBundle default, only a single object will be saved in the document.
Meanwhile, Elasticsearch database doesn't care if in an object is stored as a single value or as an array.
If it is necessary to store multiple objects (array), you have to add `multiple=true` to the annotation. While
initiating a document with multiple items you need to initialize property with the new instance of `Collection()`.
initiating a document with multiple items you need to initialize property with the new instance of `ArrayCollection()`.

Here's an example:

Expand All @@ -346,8 +346,8 @@ Here's an example:

namespace AppBundle\Document;

use Doctrine\Common\Collections\ArrayCollection;
use ONGR\ElasticsearchBundle\Annotation as ES;
use ONGR\ElasticsearchBundle\Collection\Collection;

/**
* @ES\Document()
Expand All @@ -368,7 +368,7 @@ class Product

public function __construct()
{
$this->variants = new Collection();
$this->variants = new ArrayCollection();
}

/**
Expand All @@ -379,7 +379,7 @@ class Product
*/
public function addVariant(VariantObject $variant)
{
$this->variants[] => $variant;
$this->variants[] = $variant;

return $this;
}
Expand Down
2 changes: 1 addition & 1 deletion Result/Converter.php
Expand Up @@ -11,9 +11,9 @@

namespace ONGR\ElasticsearchBundle\Result;

use Doctrine\Common\Collections\Collection;
use ONGR\ElasticsearchBundle\Annotation\Nested;
use ONGR\ElasticsearchBundle\Annotation\Object;
use ONGR\ElasticsearchBundle\Collection\Collection;
use ONGR\ElasticsearchBundle\Mapping\MetadataCollector;
use ONGR\ElasticsearchBundle\Service\Manager;

Expand Down
57 changes: 57 additions & 0 deletions Result/ObjectCallbackIterator.php
@@ -0,0 +1,57 @@
<?php

namespace ONGR\ElasticsearchBundle\Result;

class ObjectCallbackIterator extends \ArrayIterator
{
/**
* @var \Closure
*/
private $callback;

/**
* Converts array data to document objects via the callback function.
*
* @param \Closure $callback
* @param array $array
*/
public function __construct(\Closure $callback, array $array = array())
{
$this->callback = $callback;

parent::__construct($array);
}

/**
* {@inheritdoc}
*/
public function current()
{
$value = parent::current();

// Generate objects on demand
if ($value === null && $this->valid()) {
$key = $this->key();
$callback = $this->callback;
return $callback($key);
}

return $value;
}

/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
$value = parent::offsetGet($offset);

// Generate objects on demand
if ($value === null && $this->valid()) {
$callback = $this->callback;
return $callback($offset);
}

return $value;
}
}

0 comments on commit 146fa76

Please sign in to comment.