Created
July 3, 2013 07:46
-
-
Save damiankloip/5916161 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\Entity\EntityIterator. | |
*/ | |
namespace Drupal\Core\Entity; | |
/** | |
* Provides an Iterator class for dealing with large amounts of entities | |
* but not loading them all into memory. | |
*/ | |
class EntityIterator implements \Iterator { | |
/** | |
* The entity storage controller to load entities. | |
* | |
* @var \Drupal\Core\Entity\EntityStorageControllerInterface | |
*/ | |
protected $entityStorageController; | |
/** | |
* An array of entity IDs to iterate over. | |
* | |
* @var array | |
*/ | |
protected $entityIds; | |
/** | |
* An array of queued entityIDs. Loaded IDs are removed (until rewind() is called). | |
* | |
* @var array | |
*/ | |
protected $entityIdQueue; | |
/** | |
* The Amount of cached entities to store before clearing out the static cache. | |
* | |
* @var int | |
*/ | |
protected $cacheLimit; | |
/** | |
* The current array position in $entityIds. | |
* | |
* @var int | |
*/ | |
protected $current; | |
/** | |
* Currently loaded entities. | |
* | |
* @var array | |
*/ | |
protected $loadedEntities = array(); | |
/** | |
* Constructs an entity iterator object. | |
* | |
* @param \Drupal\Core\Entity\EntityControllerInterface $entity_controller | |
* @param array $ids | |
* @param int $cache_limit | |
*/ | |
public function __construct(EntityStorageControllerInterface $entity_storage_controller, array $ids, $cache_limit = 10) { | |
$this->entityStorageController = $entity_storage_controller; | |
// Make sure we don't use a keyed array. | |
$this->entityIds = array_values($ids); | |
$this->cacheLimit = (int) $cache_limit; | |
$this->rewind(); | |
} | |
/** | |
* Gets the total count for all passed entity IDs. | |
* | |
* @return int | |
*/ | |
public function getEntityIdCount() { | |
return count($this->entityIds); | |
} | |
/** | |
* Implements \Iterator::current() | |
*/ | |
public function current() { | |
// Increment the entity cache count. | |
return $this->getEntity(); | |
} | |
/** | |
* Implements \Iterator::key() | |
*/ | |
public function key() { | |
return $this->current; | |
} | |
/** | |
* Implements \Iterator::next() | |
*/ | |
public function next() { | |
return $this->current++; | |
} | |
/** | |
* Implements \Iterator::rewind() | |
*/ | |
public function rewind() { | |
$this->entityStorageController->resetCache(); | |
$this->entityIdQueue = $this->entityIds; | |
$this->loadedEntities = array(); | |
$this->current = key($this->entityIds); | |
} | |
/** | |
* Implements \Iterator::valid() | |
*/ | |
public function valid() { | |
return $this->getEntityId(); | |
} | |
/** | |
* Returns the entity ID from the value of the current $entityIds array position. | |
* | |
* @return bool | |
*/ | |
protected function getEntityId() { | |
if (isset($this->entityIds[$this->current])) { | |
return $this->entityIds[$this->current]; | |
} | |
return NULL; | |
} | |
/** | |
* Returns a loaded entity. | |
* | |
* @return \Drupal\Core\Entity\EntityInterface. | |
*/ | |
protected function getEntity() { | |
$id = $this->getEntityId(); | |
if (isset($this->loadedEntities[$id])) { | |
return $this->loadedEntities[$id]; | |
} | |
// If no entity is loaded. Try to load new entities and try again. This | |
// should only need to happen once to know if there are any more to load. | |
$this->loadEntities(); | |
if (isset($this->loadedEntities[$id])) { | |
return $this->loadedEntities[$id]; | |
} | |
} | |
/** | |
* Loads a set of entities. Depends on the cacheLimit. | |
*/ | |
protected function loadEntities() { | |
// Reset any previously loaded entities. | |
$this->entityStorageController->resetCache(); | |
// Take the cacheLimit amount of IDs from the beginning of the array and | |
// load them. This will keep reducing the queued Ids until they are gone. It | |
// doesn't make sense to use SqlQueue or anything, as we want multiple at | |
// once. | |
$ids = array_splice($this->entityIdQueue, 0, $this->cacheLimit); | |
$this->loadedEntities = $this->entityStorageController->load($ids); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment