X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=framework%2Fmain%2Fclasses%2Fiterator%2Fregistry%2Fclass_RegistryIterator.php;h=9c9d0b4a44053849aeb6c5a4e7a6c261f193545e;hb=2c3a0173e6dbfab3093b01643dc03110ddb4538b;hp=522ad93440943dedebf33b95600791c8d923ca9c;hpb=9038ac3be74ac32db35adceb83f40170ac123e4f;p=core.git diff --git a/framework/main/classes/iterator/registry/class_RegistryIterator.php b/framework/main/classes/iterator/registry/class_RegistryIterator.php index 522ad934..9c9d0b4a 100644 --- a/framework/main/classes/iterator/registry/class_RegistryIterator.php +++ b/framework/main/classes/iterator/registry/class_RegistryIterator.php @@ -1,20 +1,25 @@ * @version 0.0.0 - * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team + * @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 * @@ -31,7 +36,28 @@ use \Iterator; * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -class RegistryIterator extends BaseIterator implements Iterator { +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; + + /** + * Registry instance (implementing Register) + */ + private $registryInstance = NULL; + /** * Protected constructor * @@ -40,6 +66,14 @@ class RegistryIterator extends BaseIterator implements Iterator { protected function __construct () { // Call parent constructor parent::__construct(__CLASS__); + + // Init registry keys array + $this->registryKeys = [ + // Generic registry + 'generic' => [], + // Instance registry + 'instance' => [], + ]; } /** @@ -59,18 +93,183 @@ class RegistryIterator extends BaseIterator implements Iterator { return $iteratorInstance; } + /** + * Setter for registry instance + * + * @param $registryInstance An instance of a Register class + * @return void + */ + protected final function setRegistryInstance (Register $registryInstance) { + $this->registryInstance = $registryInstance; + } + + /** + * Getter for registry instance + * + * @return $registryInstance The debug registry instance + */ + protected final function getRegistryInstance () { + return $this->registryInstance; + } + + /** + * 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: */ ApplicationEntryPoint::exitApplication(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: */ ApplicationEntryPoint::exitApplication(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: */ ApplicationEntryPoint::exitApplication(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 - $current = null; + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); + //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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: */ ApplicationEntryPoint::exitApplication(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; + } + } - $this->partialStub('Please implement this method.'); + // 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; } @@ -80,40 +279,110 @@ class RegistryIterator extends BaseIterator implements Iterator { * @return $key Current key in iteration */ public function key () { - // Default is null - $key = null; - - $this->partialStub('Please implement this method.'); - // Return it - return $key; + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: EXIT!', $this->key)); + return $this->key; } /** * Advances to the next entry * * @return void + * @throws BadMethodCallException If $this->valid() returns FALSE + * @throws UnexpectedValueException If $registryType is not changed */ public function next () { - $this->partialStub('Please implement this method.'); + // Is valid() still TRUE? + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); + //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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())); + } elseif ((count($this->registryKeys['generic']) == 0) && (count($this->registryKeys['instance']) == 0)) { + // Both arrays are empty + throw new BadMethodCallException('No array elements in "generic" and "instance" found but method called.'); + } + + // Default is not valid + $nextIndex = -1; + $isNextValid = FALSE; + $registryType = 'invalid'; + + // Get first array element ... + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: this->registryKeys[generic]()=%d,this->registryKeys[instance]()=%d', $this->key(), count($this->registryKeys['generic']), count($this->registryKeys['instance']))); + if (count($this->registryKeys['generic']) > 0) { + // First generic array + /* UNFINISHED */ ApplicationEntryPoint::exitApplication(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))); + } elseif (count($this->registryKeys['instance']) > 0) { + // Second instance, current key's index + 1 + $nextIndex = array_search($this->key(), $this->registryKeys['instance']) + 1; + $isNextValid = isset($this->registryKeys['instance'][$nextIndex]); + $registryType = 'instance'; + } + + // Is it still valid? + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: isNextValid=%d', $this->key(), intval($isNextValid))); + if (!$isNextValid) { + // Throw exception + throw new BadMethodCallException(sprintf('this->key=%s is last key in this iteration. Forgot to invoke valid() before?', $this->key())); + } elseif ($registryType == 'invalid') { + // Not changed! + throw new UnexpectedValueException('registryType has not been changed.'); + } + + // Yes, then advance to that entry + $this->key = $this->registryKeys[$registryType][$nextIndex]; + + // Trace message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: EXIT!', $this->key())); } /** * Rewinds to the beginning of the iteration * * @return void + * @throws BadMethodCallException If $this->key is already the first element */ public function rewind () { - $this->partialStub('Please implement this method.'); + // Is current key first key? + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); + //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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())); + } elseif ((count($this->registryKeys['generic']) == 0) && (count($this->registryKeys['instance']) == 0)) { + // Both arrays are empty + throw new BadMethodCallException('No array elements in "generic" and "instance" found but method called.'); + } + + // Get first array element ... + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: this->registryKeys[generic]()=%d,this->registryKeys[instance]()=%d', $this->key(), count($this->registryKeys['generic']), count($this->registryKeys['instance']))); + if (count($this->registryKeys['generic']) > 0) { + // First generic array + /* UNFINISHED */ ApplicationEntryPoint::exitApplication(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))); + } elseif (count($this->registryKeys['instance']) > 0) { + // Second instance + $this->key = $this->registryKeys['instance'][0]; + } + + // Trace message + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: EXIT!', $this->key())); } /** * Checks wether the current entry is valid (not at the end of the list) * - * @return void + * @return $valid Whether the current key is still valid */ public function valid () { - $this->partialStub('Please implement this method.'); + // Is the element there? + //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('REGISTRY-ITERATOR[%s]: CALLED!', $this->key())); + //* DEBUG-DIE: */ ApplicationEntryPoint::exitApplication(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; } }