From f6c3672eeb33798ff31a1f697ca0c9aece87a977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Burnichon?= Date: Fri, 22 Apr 2016 12:22:27 +0200 Subject: [PATCH] Add RecordCollection class to avoid multiple record_adapter fetching --- .../Phrasea/Databox/DataboxGroupable.php | 41 ++++ .../Phrasea/Record/PerDataboxRecordId.php | 20 ++ .../Phrasea/Record/RecordCollection.php | 218 ++++++++++++++++++ .../Record/RecordReferenceCollection.php | 73 +++++- 4 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Databox/DataboxGroupable.php create mode 100644 lib/Alchemy/Phrasea/Record/PerDataboxRecordId.php create mode 100644 lib/Alchemy/Phrasea/Record/RecordCollection.php diff --git a/lib/Alchemy/Phrasea/Databox/DataboxGroupable.php b/lib/Alchemy/Phrasea/Databox/DataboxGroupable.php new file mode 100644 index 0000000000..75bd392a68 --- /dev/null +++ b/lib/Alchemy/Phrasea/Databox/DataboxGroupable.php @@ -0,0 +1,41 @@ + + */ + public function groupByDatabox(); + + /** + * Returns databoxes ids + * + * @return int[] + */ + public function getDataboxIds(); + + /** + * @param int $databoxId + * @return array + */ + public function getDataboxGroup($databoxId); + + /** + * Reorder groups if needed + * + * @return void + */ + public function reorderGroups(); +} diff --git a/lib/Alchemy/Phrasea/Record/PerDataboxRecordId.php b/lib/Alchemy/Phrasea/Record/PerDataboxRecordId.php new file mode 100644 index 0000000000..8699990e55 --- /dev/null +++ b/lib/Alchemy/Phrasea/Record/PerDataboxRecordId.php @@ -0,0 +1,20 @@ + + */ + private $groups; + + /** + * @var bool + */ + private $reorderNeeded = false; + + public function __construct($records = []) + { + Assertion::allIsInstanceOf($records, \record_adapter::class); + + foreach ($records as $index => $record) { + $this->add($record, $index); + } + } + + /** + * @param \record_adapter $record + * @param null|int|string $index + * @return void + */ + public function add(\record_adapter $record, $index = null) + { + if (null === $index) { + $this->addWithUnknownIndex($record); + + return; + } + + if (isset($this->records[$index])){ + unset($this->groups[$this->records[$index]->getDataboxId()][$index]); + $this->reorderNeeded = true; + } + + $this->records[$index] = $record; + + $this->addIndexToGroups($record, $index); + } + + /** + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->records); + } + + /** + * @param int|string $offset + * @return bool + */ + public function offsetExists($offset) + { + return isset($this->records[$offset]); + } + + /** + * @param int|string $offset + * @return \record_adapter + */ + public function offsetGet($offset) + { + return $this->records[$offset]; + } + + /** + * @param int|string $offset + * @param \record_adapter $value + */ + public function offsetSet($offset, $value) + { + Assertion::isInstanceOf($value, \record_adapter::class); + + $this->add($value, $offset); + } + + /** + * @param int|string $offset + * @return void + */ + public function offsetUnset($offset) + { + if (isset($this->records[$offset])) { + unset($this->groups[$this->records[$offset]->getDataboxId()][$offset]); + } + + unset($this->records[$offset]); + } + + /** + * @return int + */ + public function count() + { + return count($this->records); + } + + /** + * Returns records groups by databoxId (possibly not in order) + * + * @return \record_adapter[][] + */ + public function groupByDatabox() + { + return $this->groups; + } + + /** + * @return int[] + */ + public function getDataboxIds() + { + return array_keys($this->groups); + } + + /** + * @param int $databoxId + * @return \record_adapter[] + */ + public function getDataboxGroup($databoxId) + { + return isset($this->groups[$databoxId]) ? $this->groups[$databoxId] : []; + } + + /** + * @return void + */ + public function reorderGroups() + { + if (!$this->reorderNeeded) { + return; + } + + $groups = []; + + foreach ($this->records as $index => $record) { + $databoxId = $record->getDataboxId(); + + if (!isset($groups[$databoxId])) { + $groups[$databoxId] = []; + } + + $groups[$databoxId][$index] = $record; + } + + $this->groups = $groups; + $this->reorderNeeded = false; + } + + /** + * @param int $databoxId + * @return int[] + */ + public function getDataboxRecordIds($databoxId) + { + $recordIds = []; + + foreach ($this->getDataboxGroup($databoxId) as $record) { + $recordIds[$record->getRecordId()] = true; + } + + return array_keys($recordIds); + } + + /** + * @param \record_adapter $record + * @return void + */ + private function addWithUnknownIndex(\record_adapter $record) + { + $this->records[] = $record; + + end($this->records); + + $this->addIndexToGroups($record, key($this->records)); + } + + /** + * @param \record_adapter $record + * @param int|string $index + * @return void + */ + private function addIndexToGroups(\record_adapter $record, $index) + { + $databoxId = $record->getDataboxId(); + + if (!isset($this->groups[$databoxId])) { + $this->groups[$databoxId] = []; + } + + $this->groups[$databoxId][$index] = $record; + } +} diff --git a/lib/Alchemy/Phrasea/Record/RecordReferenceCollection.php b/lib/Alchemy/Phrasea/Record/RecordReferenceCollection.php index 97bb80ceef..787bbe5f93 100644 --- a/lib/Alchemy/Phrasea/Record/RecordReferenceCollection.php +++ b/lib/Alchemy/Phrasea/Record/RecordReferenceCollection.php @@ -10,10 +10,11 @@ namespace Alchemy\Phrasea\Record; +use Alchemy\Phrasea\Databox\DataboxGroupable; use Alchemy\Phrasea\Model\RecordReferenceInterface; use Assert\Assertion; -class RecordReferenceCollection implements \IteratorAggregate, \ArrayAccess +class RecordReferenceCollection implements \IteratorAggregate, \ArrayAccess, \Countable, DataboxGroupable, PerDataboxRecordId { /** * @param array $records @@ -192,13 +193,17 @@ class RecordReferenceCollection implements \IteratorAggregate, \ArrayAccess return $records; } + /** + * @param int|string $offset + * @return bool + */ public function offsetExists($offset) { return isset($this->references[$offset]); } /** - * @param mixed $offset + * @param int|string $offset * @return RecordReferenceInterface */ public function offsetGet($offset) @@ -206,6 +211,10 @@ class RecordReferenceCollection implements \IteratorAggregate, \ArrayAccess return $this->references[$offset]; } + /** + * @param int|string $offset + * @param RecordReferenceInterface $value + */ public function offsetSet($offset, $value) { Assertion::isInstanceOf($value, RecordReferenceInterface::class); @@ -213,9 +222,69 @@ class RecordReferenceCollection implements \IteratorAggregate, \ArrayAccess $this->add($value, $offset); } + /** + * @param int|string $offset + * @return void + */ public function offsetUnset($offset) { unset($this->references[$offset]); $this->groups = null; } + + /** + * @return RecordReferenceInterface[][] + */ + public function groupByDatabox() + { + $this->reorderGroups(); + + return $this->groups; + } + + public function reorderGroups() + { + if ($this->groups) { + return; + } + + $groups = []; + + foreach ($this->references as $index => $reference) { + if (!isset($groups[$reference->getDataboxId()])) { + $groups[$reference->getDataboxId()] = []; + } + + $groups[$reference->getDataboxId()][$index] = $reference; + } + + $this->groups = $groups; + } + + /** + * @param int $databoxId + * @return RecordReferenceInterface[] + */ + public function getDataboxGroup($databoxId) + { + $this->reorderGroups(); + + return isset($this->groups[$databoxId]) ? $this->groups[$databoxId] : []; + } + + public function getDataboxRecordIds($databoxId) + { + $recordsIds = []; + + foreach ($this->getDataboxGroup($databoxId) as $references) { + $recordsIds[$references->getRecordId()] = true; + } + + return array_keys($recordsIds); + } + + public function count() + { + return count($this->references); + } }