<?php /** * Hoa * * * @license * * New BSD License * * Copyright © 2007-2017, Hoa community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Hoa nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace Psy\Readline\Hoa; /** * Abstract class for all `hoa://`'s nodes. */ class ProtocolNode implements \ArrayAccess, \IteratorAggregate { /** * Node's name. */ protected $_name = null; /** * Path for the `reach` method. */ protected $_reach = null; /** * Children of the node. */ private $_children = []; /** * Construct a protocol's node. * If it is not a data object (i.e. if it does not extend this class to * overload the `$_name` attribute), we can set the `$_name` attribute * dynamically. This is useful to create a node on-the-fly. */ public function __construct(string $name = null, string $reach = null, array $children = []) { if (null !== $name) { $this->_name = $name; } if (null !== $reach) { $this->_reach = $reach; } foreach ($children as $child) { $this[] = $child; } return; } /** * Add a node. */ #[\ReturnTypeWillChange] public function offsetSet($name, $node) { if (!($node instanceof self)) { throw new ProtocolException('Protocol node must extend %s.', 0, __CLASS__); } if (empty($name)) { $name = $node->getName(); } if (empty($name)) { throw new ProtocolException('Cannot add a node to the `hoa://` protocol without a name.', 1); } $this->_children[$name] = $node; } /** * Get a specific node. */ public function offsetGet($name): self { if (!isset($this[$name])) { throw new ProtocolException('Node %s does not exist.', 2, $name); } return $this->_children[$name]; } /** * Check if a node exists. */ public function offsetExists($name): bool { return true === \array_key_exists($name, $this->_children); } /** * Remove a node. */ #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->_children[$name]); } /** * Resolve a path, i.e. iterate the nodes tree and reach the queue of * the path. */ protected function _resolve(string $path, &$accumulator, string $id = null) { if (\substr($path, 0, 6) === 'hoa://') { $path = \substr($path, 6); } if (empty($path)) { return null; } if (null === $accumulator) { $accumulator = []; $posId = \strpos($path, '#'); if (false !== $posId) { $id = \substr($path, $posId + 1); $path = \substr($path, 0, $posId); } else { $id = null; } } $path = \trim($path, '/'); $pos = \strpos($path, '/'); if (false !== $pos) { $next = \substr($path, 0, $pos); } else { $next = $path; } if (isset($this[$next])) { if (false === $pos) { if (null === $id) { $this->_resolveChoice($this[$next]->reach(), $accumulator); return true; } $accumulator = null; return $this[$next]->reachId($id); } $tnext = $this[$next]; $this->_resolveChoice($tnext->reach(), $accumulator); return $tnext->_resolve(\substr($path, $pos + 1), $accumulator, $id); } $this->_resolveChoice($this->reach($path), $accumulator); return true; } /** * Resolve choices, i.e. a reach value has a “;”. */ protected function _resolveChoice($reach, &$accumulator) { if (null === $reach) { $reach = ''; } if (empty($accumulator)) { $accumulator = \explode(';', $reach); return; } if (false === \strpos($reach, ';')) { if (false !== $pos = \strrpos($reach, "\r")) { $reach = \substr($reach, $pos + 1); foreach ($accumulator as &$entry) { $entry = null; } } foreach ($accumulator as &$entry) { $entry .= $reach; } return; } $choices = \explode(';', $reach); $ref = $accumulator; $accumulator = []; foreach ($choices as $choice) { if (false !== $pos = \strrpos($choice, "\r")) { $choice = \substr($choice, $pos + 1); foreach ($ref as $entry) { $accumulator[] = $choice; } } else { foreach ($ref as $entry) { $accumulator[] = $entry.$choice; } } } unset($ref); return; } /** * Queue of the node. * Generic one. Must be overrided in children classes. */ public function reach(string $queue = null) { return empty($queue) ? $this->_reach : $queue; } /** * ID of the component. * Generic one. Should be overrided in children classes. */ public function reachId(string $id) { throw new ProtocolException('The node %s has no ID support (tried to reach #%s).', 4, [$this->getName(), $id]); } /** * Set a new reach value. */ public function setReach(string $reach) { $old = $this->_reach; $this->_reach = $reach; return $old; } /** * Get node's name. */ public function getName() { return $this->_name; } /** * Get reach's root. */ protected function getReach() { return $this->_reach; } /** * Get an iterator. */ public function getIterator(): \ArrayIterator { return new \ArrayIterator($this->_children); } /** * Get root the protocol. */ public static function getRoot(): Protocol { return Protocol::getInstance(); } /** * Print a tree of component. */ public function __toString(): string { static $i = 0; $out = \str_repeat(' ', $i).$this->getName()."\n"; foreach ($this as $node) { ++$i; $out .= $node; --$i; } return $out; } }
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
Terminfo | Folder | 0755 |
|
|
Autocompleter.php | File | 2.08 KB | 0644 |
|
AutocompleterAggregate.php | File | 3.26 KB | 0644 |
|
AutocompleterPath.php | File | 4.92 KB | 0644 |
|
AutocompleterWord.php | File | 3.1 KB | 0644 |
|
Console.php | File | 7.8 KB | 0644 |
|
ConsoleCursor.php | File | 20.35 KB | 0644 |
|
ConsoleException.php | File | 1.77 KB | 0644 |
|
ConsoleInput.php | File | 4.15 KB | 0644 |
|
ConsoleOutput.php | File | 5.23 KB | 0644 |
|
ConsoleProcessus.php | File | 20.43 KB | 0644 |
|
ConsoleTput.php | File | 20.9 KB | 0644 |
|
ConsoleWindow.php | File | 12.15 KB | 0644 |
|
Event.php | File | 5.94 KB | 0644 |
|
EventBucket.php | File | 2.88 KB | 0644 |
|
EventException.php | File | 1.74 KB | 0644 |
|
EventListenable.php | File | 1.89 KB | 0644 |
|
EventListener.php | File | 3.99 KB | 0644 |
|
EventListens.php | File | 2.59 KB | 0644 |
|
EventSource.php | File | 1.74 KB | 0644 |
|
Exception.php | File | 2.66 KB | 0644 |
|
ExceptionIdle.php | File | 7.07 KB | 0644 |
|
File.php | File | 7.67 KB | 0644 |
|
FileDirectory.php | File | 6.33 KB | 0644 |
|
FileDoesNotExistException.php | File | 1.83 KB | 0644 |
|
FileException.php | File | 1.8 KB | 0644 |
|
FileFinder.php | File | 15.77 KB | 0644 |
|
FileGeneric.php | File | 11.17 KB | 0644 |
|
FileLink.php | File | 4.19 KB | 0644 |
|
FileLinkRead.php | File | 5.84 KB | 0644 |
|
FileLinkReadWrite.php | File | 6.81 KB | 0644 |
|
FileRead.php | File | 4.58 KB | 0644 |
|
FileReadWrite.php | File | 6.8 KB | 0644 |
|
IStream.php | File | 1.82 KB | 0644 |
|
IteratorFileSystem.php | File | 2.74 KB | 0644 |
|
IteratorRecursiveDirectory.php | File | 3.71 KB | 0644 |
|
IteratorSplFileInfo.php | File | 3.22 KB | 0644 |
|
Protocol.php | File | 6.43 KB | 0644 |
|
ProtocolException.php | File | 1.74 KB | 0644 |
|
ProtocolNode.php | File | 7.92 KB | 0644 |
|
ProtocolNodeLibrary.php | File | 3.14 KB | 0644 |
|
ProtocolWrapper.php | File | 13.38 KB | 0644 |
|
Readline.php | File | 26.37 KB | 0644 |
|
Stream.php | File | 14.51 KB | 0644 |
|
StreamBufferable.php | File | 2.43 KB | 0644 |
|
StreamContext.php | File | 3.54 KB | 0644 |
|
StreamException.php | File | 1.77 KB | 0644 |
|
StreamIn.php | File | 2.81 KB | 0644 |
|
StreamLockable.php | File | 2.55 KB | 0644 |
|
StreamOut.php | File | 2.66 KB | 0644 |
|
StreamPathable.php | File | 1.97 KB | 0644 |
|
StreamPointable.php | File | 2.39 KB | 0644 |
|
StreamStatable.php | File | 2.99 KB | 0644 |
|
StreamTouchable.php | File | 3.09 KB | 0644 |
|
Ustring.php | File | 5.01 KB | 0644 |
|
Xcallable.php | File | 7.18 KB | 0644 |
|