type) && !interface_exists($type)) { throw new \InvalidArgumentException(sprintf('Unknown type %s', $type)); } $this->type = $type; $this->objectManager = $objectManager; $this->configInterface = $configInterface; array_walk( $array, function ($item, $index) { $this->assertValidTypeLazy($item, $index); } ); $this->array = $array; $this->counter = count($array); $this->objectCreationStrategy = $objectCreationStrategy; } /** * Asserts that item type is collection defined type * * @param string $instanceName * @param string|int|null $index * @return void * @throws \InvalidArgumentException */ private function assertValidTypeLazy($instanceName, $index = null) { $realType = $this->configInterface->getInstanceType( $this->configInterface->getPreference($instanceName) ); if (!in_array( $this->type, array_unique(array_merge(class_parents($realType), class_implements($realType))), true )) { $this->throwTypeException($realType, $index); } } /** * Throws exception according type mismatch * * @param string $inputType * @param string $index * @return void * @throws \InvalidArgumentException */ private function throwTypeException($inputType, $index) { $message = 'Type mismatch. Expected type: %s. Actual: %s, Code: %s'; throw new \InvalidArgumentException( sprintf($message, $this->type, $inputType, $index) ); } /** * Returns object for requested index * * @param string|int $index * @return object */ private function initObject($index) { if (isset($this->objectsArray[$index])) { return $this->objectsArray[$index]; } $objectCreationStrategy = $this->objectCreationStrategy; return $this->objectsArray[$index] = $objectCreationStrategy === null ? $this->objectManager->create($this->array[$index]) : $objectCreationStrategy($this->objectManager, $this->array[$index]); } /** * {inheritdoc} */ public function getIterator() { if (array_keys($this->array) != array_keys($this->objectsArray)) { foreach (array_keys($this->array) as $index) { $this->initObject($index); } } return new \ArrayIterator($this->objectsArray); } /** * {inheritdoc} */ public function offsetExists($offset) { return array_key_exists($offset, $this->array); } /** * {inheritdoc} */ public function offsetGet($offset) { return isset($this->array[$offset]) ? $this->initObject($offset) : null; } /** * {inheritdoc} */ public function offsetSet($offset, $value) { $this->assertValidTypeLazy($value, $offset); if ($offset === null) { $this->array[] = $value; } else { $this->array[$offset] = $value; } $this->counter++; } /** * {inheritdoc} */ public function offsetUnset($offset) { if ($this->counter && isset($this->array[$offset])) { $this->counter--; unset($this->array[$offset]); if (isset($this->objectsArray[$offset])) { unset($this->objectsArray[$offset]); } } } /** * {inheritdoc} */ public function count() { return $this->counter; } }