* @version 0.0.0 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team * @license GNU GPL 3.0 or any newer version * @link http://www.ship-simu.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ class RegistryIterator extends BaseIterator implements IteratableRegistry { /** * All found registry keys */ private $registryKeys = []; /** * An array containing keys ob sub-registries which keys should only be * included in the iterator. */ private $onlyRegistries = []; /** * Current array key */ private $key = NULL; /** * Protected constructor * * @return void */ protected function __construct () { // Call parent constructor parent::__construct(__CLASS__); // Init registry keys array $this->registryKeys = [ // Generic registry 'generic' => [], // Instance registry 'instance' => [], ]; } /** * Creates an instance of this class * * @param $registryInstance An instance of a Register class * @return $iteratorInstance An instance of a Iterator class */ public final static function createRegistryIterator (Register $registryInstance) { // Get new instance $iteratorInstance = new RegistryIterator(); // Set registry here $iteratorInstance->setRegistryInstance($registryInstance); // Return the prepared instance return $iteratorInstance; } /** * Setter for only-registries array * * @param $onlyRegistries Array with keys only being iterated over * @return void */ private function setOnlyRegistries (array $onlyRegistries) { $this->onlyRegistries = $onlyRegistries; } /** * Initializes this iterator by scanning over the registry for all keys. * * @param $onlyRegistries Only iterate on these sub-registry keys, default is all * @return void * @throws LogicException If a registry entry does not implement Registerable * @throws NullPointerException If criteriaKey or criteriaMethod is not set but a call-back instance is set */ public function initIterator (array $onlyRegistries = []) { // Set it in this registry /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR: onlyRegistries()=%d - CALLED!', count($onlyRegistries))); $this->setOnlyRegistries($onlyRegistries); // Get generic registry entries from it $entries = $this->getRegistryInstance()->getGenericRegistry(); // Anything in there? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[generic]: entries()=%d', count($entries))); if (count($entries) > 0) { // Debugging: /* DEBUG-DIE: */ die(sprintf('[%s:%d]: UNFINISHED: entries=%s', __METHOD__, __LINE__, print_r($entries, TRUE))); } // END - if // Get instance registry entries from it $entries = $this->getRegistryInstance()->getInstanceRegistry(); // Anything in there? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: entries()=%d', count($entries))); if (count($entries) > 0) { // Then run over all foreach ($entries as $key => $entry) { // Is an unwanted registry found? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s,entry[]=%s', $key, gettype($entry))); if (substr($key, -8, 8) == 'registry') { // Skip this! /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is a registry key, skipping ...', $key)); continue; } // Is it an instance of a sub-registry? if (count($onlyRegistries) > 0 && !in_array($key, $onlyRegistries, TRUE)) { // Not in requested registries /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s is not wanted, skipping ...', $key)); continue; } elseif ($entry instanceof SubRegistry) { // Get iterator from this instance $subRegistryInstances = $entry->getInstanceRegistry(); // Add all sub-registry keys to this registry keys array /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: subRegistryInstances()=%d', count($subRegistryInstances))); //* DEBUG-DIE: */ die(sprintf('[%s:%d]: key=%s,subRegistryInstances=%s', __METHOD__, __LINE__, $key, print_r($subRegistryInstances, TRUE))); foreach (array_keys($subRegistryInstances) as $subKey) { // Add it /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Adding key=%s,subKey=%s ...', $key, $subKey)); array_push($this->registryKeys['instance'], $subKey); // Is the current key set? if (is_null($this->key)) { // Init key /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting subKey=%s as first key ...', $subKey)); $this->key = $subKey; } } // Skip below code continue; } elseif (!($entry instanceof Registerable)) { // Not registerable?! throw new LogicException(sprintf('entry[]=%s does not implement Registerable.', gettype($entry))); } // Is the current key set? if (is_null($this->key)) { // Init key /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: Setting key=%s as first key ...', $key)); $this->key = $key; } // Add key to array /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[instance]: key=%s - Adding ...', $key)); //* DEBUG-DIE: */ die(sprintf('[%s:%d]: key=%s,entry=%s', __METHOD__, __LINE__, $key, print_r($entry, TRUE))); array_push($this->registryKeys['instance'], $key); } // END - foreach } // END - if // Trace message /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('REGISTRY-ITERATOR: EXIT!'); } /** * Getter for all registry keys (array) * * @return $registryKeys Registry keys */ public final function getRegistryKeys () { // Return it return $this->registryKeys; } /** * Getter for current value from group or generic * * @return $current Current value in iteration * @throws NullPointerException If current key points to a non-existing entry in searched registries */ public function current () { // Default is null /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); //* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->valid=%d,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), intval($this->valid()), print_r($this->registryKeys, TRUE))); $current = NULL; $entries = []; // Get all registries $allRegistries = $this->getRegistryInstance()->getInstanceRegistry(); // Loop through all sub-sets /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: allRegistries()=%d', $this->key(), count($allRegistries))); foreach ($allRegistries as $registryKey => $registryInstance) { // Is this key wanted? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s', $this->key(), $registryKey)); if (count($this->onlyRegistries) == 0 || in_array($registryKey, $this->onlyRegistries)) { // Yes, then loop through them only $instances = $registryInstance->getInstanceRegistry(); // The key should be there /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: Handling registryKey=%s ...', $this->key(), $registryKey)); //* DEBUG-DIE: */ die(sprintf('[%s:%d]: instances=%s', __METHOD__, __LINE__, print_r($instances, TRUE))); if (!isset($instances[$this->key()])) { // Skip below code /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s has no this->key=%s, skipping ...', $this->key(), $registryKey)); continue; } // Set as current element and leave loop $current = $instances[$this->key()]; /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: registryKey=%s,current=%s found. - BREAK!', $this->key(), $registryKey, $current->__toString())); break; } } // Is current still NULL? if (is_null($current)) { // This cannot happen and indicates a logic error throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER); } // Return it /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: current[%s]=%s - EXIT!', $this->key(), gettype($current), $current)); return $current; } /** * Getter for key from group or generic * * @return $key Current key in iteration */ public function key () { // Return it return $this->key; } /** * Advances to the next entry * * @return void * @throws BadMethodCallException If $this->valid() returns FALSE */ public function next () { // Is valid() still TRUE? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); /* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->valid=%d,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), intval($this->valid()), print_r($this->registryKeys, TRUE))); if (!$this->valid()) { // Bad method call! throw new BadMethodCallException(sprintf('this->key[%s]=%s is no longer valid, but method was called.', gettype($this->key()), $this->key())); } } /** * Rewinds to the beginning of the iteration * * @return void * @throws BadMethodCallException If $this->key is already the first element */ public function rewind () { // Is current key first key? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); /* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->valid=%d,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), intval($this->valid()), print_r($this->registryKeys, TRUE))); if (array_search($this->key(), $this->getRegistryKeys()) === 0) { // rewind() cannot rewind first entry! throw new BadMethodCallException(sprintf('this->key=%s is already first element, but method was called.', $this->key())); } } /** * Checks wether the current entry is valid (not at the end of the list) * * @return $valid Whether the current key is still valid */ public function valid () { // Is the element there? /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); //* DEBUG-DIE: */ die(sprintf('[%s:%d]: this->key(%d)[%s]=%s,this->registryKeys=%s', __METHOD__, __LINE__, strlen($this->key()), gettype($this->key()), $this->key(), print_r($this->registryKeys, TRUE))); $valid = (in_array($this->key(), $this->registryKeys['instance']) || in_array($this->key(), $this->registryKeys['generic'])); // Return flag /* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: valid=%d - EXIT!', $this->key(), intval($valid))); return $valid; } }