├── .State ├── .gitignore ├── .travis.yml ├── composer.json ├── Source ├── Map.php ├── Glob.php ├── Mock.php ├── Limit.php ├── Append.php ├── Filter.php ├── Outer.php ├── Infinite.php ├── NoRewind.php ├── Seekable.php ├── Aggregate.php ├── IteratorIterator.php ├── Recursive │ ├── Map.php │ ├── Filter.php │ ├── Iterator.php │ ├── CallbackFilter.php │ ├── Recursive.php │ ├── RegularExpression.php │ ├── Mock.php │ └── Directory.php ├── CallbackFilter.php ├── Exception.php ├── Iterator.php ├── Multiple.php ├── FileSystem.php ├── CallbackGenerator.php ├── Directory.php ├── SplFileInfo.php ├── Counter.php ├── Demultiplexer.php ├── Lookbehind.php ├── Repeater.php ├── Lookahead.php ├── Buffer.php └── RegularExpression.php ├── Test └── Unit │ ├── Infinite.php │ ├── CallbackGenerator.php │ ├── NoRewind.php │ ├── Mock.php │ ├── Counter.php │ ├── Limit.php │ ├── Append.php │ ├── Repeater.php │ ├── Filter.php │ ├── Multiple.php │ ├── Map.php │ ├── Demultiplexer.php │ ├── RegularExpression.php │ ├── FileSystem.php │ ├── IteratorIterator.php │ ├── Lookbehind.php │ ├── Lookahead.php │ ├── SplFileInfo.php │ ├── CallbackFilter.php │ └── Directory.php └── CHANGELOG.md /.State: -------------------------------------------------------------------------------- 1 | finalized 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /composer.lock 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | matrix: 4 | include: 5 | - php: 5.5 6 | - php: 5.6 7 | - php: 7.0 8 | - php: 7.1 9 | env: 10 | - ENABLE_XDEBUG=true 11 | - php: 7.1 12 | env: 13 | - ENABLE_DEVTOOLS=true 14 | - php: nightly 15 | allow_failures: 16 | - php: nightly 17 | fast_finish: true 18 | 19 | os: 20 | - linux 21 | 22 | notifications: 23 | irc: "chat.freenode.net#hoaproject" 24 | 25 | sudo: false 26 | 27 | env: 28 | global: 29 | - secure: "AAAAB3NzaC1yc2EAAAADAQABAAAAgQCUYJezBTczYZG85EJh06W3JyT9TShON5kNEKCfnzFjU1ZpOsrXG076lfJjF2hmkG8iXMxf+MI6OvNPMbEywzg7eNBu+092SzKBq5tFAIU9Sy6zHlbo2EvZoVqiJ2xn313jjkJApdRp8qSUT4gfPeIZKTdhvmn1Qcftb3pQQEh/Mw==" 30 | 31 | cache: 32 | directories: 33 | - vendor/ 34 | 35 | before_script: 36 | - export PATH="$PATH:$HOME/.composer/vendor/bin" 37 | - if [[ ! $ENABLE_XDEBUG ]]; then 38 | phpenv config-rm xdebug.ini || echo "ext-xdebug is not available, cannot remove it."; 39 | fi 40 | 41 | script: 42 | - composer install 43 | - vendor/bin/hoa test:run 44 | - if [[ $ENABLE_DEVTOOLS ]]; then 45 | composer global require friendsofphp/php-cs-fixer; 46 | vendor/bin/hoa devtools:cs --diff --dry-run .; 47 | fi 48 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "hoa/iterator", 3 | "description": "The Hoa\\Iterator library.", 4 | "type" : "library", 5 | "keywords" : ["library", "iterator"], 6 | "homepage" : "https://hoa-project.net/", 7 | "license" : "BSD-3-Clause", 8 | "authors" : [ 9 | { 10 | "name" : "Ivan Enderlin", 11 | "email": "ivan.enderlin@hoa-project.net" 12 | }, 13 | { 14 | "name" : "Hoa community", 15 | "homepage": "https://hoa-project.net/" 16 | } 17 | ], 18 | "support": { 19 | "email" : "support@hoa-project.net", 20 | "irc" : "irc://chat.freenode.net/hoaproject", 21 | "forum" : "https://users.hoa-project.net/", 22 | "docs" : "https://central.hoa-project.net/Documentation/Library/Iterator", 23 | "source": "https://central.hoa-project.net/Resource/Library/Iterator" 24 | }, 25 | "require": { 26 | "php" : ">=7.1", 27 | "hoa/consistency": "dev-master", 28 | "hoa/exception" : "dev-master" 29 | }, 30 | "require-dev": { 31 | "hoa/test": "dev-master" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "Hoa\\Iterator\\" : "Source", 36 | "Hoa\\Iterator\\Test\\": "Test" 37 | } 38 | }, 39 | "extra": { 40 | "branch-alias": { 41 | "dev-master": "2.x-dev" 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Source/Map.php: -------------------------------------------------------------------------------- 1 | given( 57 | $iterator = new LUT\Map(['a']), 58 | $infinite = new LUT\Infinite($iterator), 59 | $limit = new LUT\Limit($infinite, 0, 100) 60 | ) 61 | ->when($result = iterator_to_array($limit, false)) 62 | ->then 63 | ->array($result) 64 | ->isEqualTo(array_fill(0, 100, 'a')) 65 | ->size 66 | ->isEqualTo(100); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Test/Unit/CallbackGenerator.php: -------------------------------------------------------------------------------- 1 | given( 57 | $iterator = new LUT\CallbackGenerator(function ($key) { 58 | return $key * 2; 59 | }), 60 | $limit = new LUT\Limit($iterator, 0, 5) 61 | ) 62 | ->when($result = iterator_to_array($limit)) 63 | ->then 64 | ->array($result) 65 | ->isEqualTo([ 66 | 0, 67 | 2, 68 | 4, 69 | 6, 70 | 8 71 | ]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Test/Unit/NoRewind.php: -------------------------------------------------------------------------------- 1 | given( 57 | $dummyArray = ['f', 'o', 'o', 'b', 'a', 'r'], 58 | $iterator = new LUT\Map($dummyArray), 59 | $norewind = new LUT\NoRewind($iterator) 60 | ) 61 | ->when($result = iterator_to_array($norewind)) 62 | ->then 63 | ->array($result) 64 | ->isEqualTo($dummyArray) 65 | 66 | ->when($norewind->rewind()) 67 | ->boolean($norewind->valid()) 68 | ->isFalse() 69 | 70 | ->when($result = iterator_to_array($norewind)) 71 | ->then 72 | ->array($result) 73 | ->isEmpty(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Source/Multiple.php: -------------------------------------------------------------------------------- 1 | _infos[] = $default; 69 | } else { 70 | $this->_infos[$infos] = $default; 71 | } 72 | 73 | return $out; 74 | } 75 | 76 | /** 77 | * Get the registered iterator instances. 78 | */ 79 | public function current(): array 80 | { 81 | $out = parent::current(); 82 | 83 | foreach ($out as $key => &$value) { 84 | if (null === $value) { 85 | $value = $this->_infos[$key]; 86 | } 87 | } 88 | 89 | return $out; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Source/FileSystem.php: -------------------------------------------------------------------------------- 1 | _splFileInfoClass = $splFileInfoClass; 63 | 64 | if (null === $flags) { 65 | parent::__construct($path); 66 | } else { 67 | parent::__construct($path, $flags); 68 | } 69 | 70 | return; 71 | } 72 | 73 | /** 74 | * Current. 75 | * Please, see \FileSystemIterator::current() method. 76 | */ 77 | public function current() 78 | { 79 | $out = parent::current(); 80 | 81 | if (null !== $this->_splFileInfoClass && 82 | $out instanceof \SplFileInfo) { 83 | $out->setInfoClass($this->_splFileInfoClass); 84 | $out = $out->getFileInfo(); 85 | } 86 | 87 | return $out; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Test/Unit/Mock.php: -------------------------------------------------------------------------------- 1 | given($iterator = new LUT\Mock()) 57 | ->when($result = iterator_to_array($iterator)) 58 | ->then 59 | ->array($result) 60 | ->isEmpty(); 61 | } 62 | 63 | public function case_recursive_mock_mock(): void 64 | { 65 | $this 66 | ->when($iterator = new LUT\Recursive\Mock(new LUT\Mock())) 67 | ->then 68 | ->variable($iterator->getChildren()) 69 | ->isNull() 70 | ->boolean($iterator->hasChildren()) 71 | ->isFalse(); 72 | } 73 | 74 | public function case_recursive(): void 75 | { 76 | $this 77 | ->given( 78 | $map = new LUT\Map(['a', 'b', 'c']), 79 | $mock = new LUT\Recursive\Mock($map), 80 | $iteratoriterator = new LUT\Recursive\Iterator($mock) 81 | ) 82 | ->when($result = iterator_to_array($map, false)) 83 | ->then 84 | ->array($result) 85 | ->isEqualTo(['a', 'b', 'c']); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Test/Unit/Counter.php: -------------------------------------------------------------------------------- 1 | given($iterator = new LUT\Counter(0, 12, 3)) 57 | ->when($result = iterator_to_array($iterator)) 58 | ->then 59 | ->array($result) 60 | ->isEqualTo([0, 3, 6, 9]); 61 | } 62 | 63 | public function case_offset(): void 64 | { 65 | $this 66 | ->given($iterator = new LUT\Counter(6, 12, 3)) 67 | ->when($result = iterator_to_array($iterator)) 68 | ->then 69 | ->array($result) 70 | ->isEqualTo([6, 9]); 71 | } 72 | 73 | public function case_too_small(): void 74 | { 75 | $this 76 | ->exception(function (): void { 77 | new LUT\Counter(0, 0, 0); 78 | }) 79 | ->isInstanceOf(LUT\Exception::class); 80 | } 81 | 82 | public function case_too_big(): void 83 | { 84 | $this 85 | ->given($iterator = new LUT\Counter(0, 12, 13)) 86 | ->when($result = iterator_to_array($iterator)) 87 | ->then 88 | ->array($result) 89 | ->isEqualTo([0]); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Source/CallbackGenerator.php: -------------------------------------------------------------------------------- 1 | _callback = $callback; 71 | 72 | return; 73 | } 74 | 75 | /** 76 | * Return the current element. 77 | */ 78 | public function current() 79 | { 80 | $handle = $this->_callback; 81 | 82 | return $this->_current = $handle($this->_key); 83 | } 84 | 85 | /** 86 | * Return the key of the current element. 87 | */ 88 | public function key() 89 | { 90 | return $this->_key; 91 | } 92 | 93 | /** 94 | * Move forward to next element. 95 | */ 96 | public function next(): void 97 | { 98 | ++$this->_key; 99 | } 100 | 101 | /** 102 | * Rewind the iterator to the first element. 103 | */ 104 | public function rewind(): void 105 | { 106 | $this->_key = 0; 107 | $this->_current = null; 108 | } 109 | 110 | /** 111 | * Check if current position is valid. 112 | */ 113 | public function valid(): bool 114 | { 115 | return true; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Test/Unit/Limit.php: -------------------------------------------------------------------------------- 1 | given( 61 | $iterator = new LUT\Map(self::$_dummyArray), 62 | $limit = new LUT\Limit($iterator, 2, 3) 63 | ) 64 | ->when($result = iterator_to_array($limit)) 65 | ->then 66 | ->array($result) 67 | ->isEqualTo([ 68 | 2 => 'o', 69 | 3 => 'b', 70 | 4 => 'a' 71 | ]); 72 | } 73 | 74 | public function case_negative_offset(): void 75 | { 76 | $this 77 | ->given($iterator = new LUT\Map(self::$_dummyArray)) 78 | ->exception(function () use ($iterator): void { 79 | new LUT\Limit($iterator, -2, 3); 80 | }) 81 | ->isInstanceOf(\OutOfRangeException::class); 82 | } 83 | 84 | public function case_empty(): void 85 | { 86 | $this 87 | ->given( 88 | $iterator = new LUT\Map(self::$_dummyArray), 89 | $limit = new LUT\Limit($iterator, 0, 0) 90 | ) 91 | ->exception(function () use ($limit): void { 92 | iterator_to_array($limit); 93 | }) 94 | ->isInstanceOf(\OutOfBoundsException::class); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Source/Recursive/RegularExpression.php: -------------------------------------------------------------------------------- 1 | hasChildren() || 76 | true === parent::accept(); 77 | } 78 | 79 | /** 80 | * Get an iterator for the current entry. 81 | */ 82 | public function getChildren(): self 83 | { 84 | return new static( 85 | true === $this->hasChildren() 86 | ? $this->getInnerIterator()->getChildren() 87 | : null, 88 | $this->getRegex(), 89 | $this->getMode(), 90 | $this->getFlags(), 91 | $this->getPregFlags() 92 | ); 93 | } 94 | 95 | /** 96 | * Check whether an iterator can be obtained for the current entry. 97 | */ 98 | public function hasChildren(): bool 99 | { 100 | return $this->getInnerIterator()->hasChildren(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Source/Directory.php: -------------------------------------------------------------------------------- 1 | _splFileInfoClass = $splFileInfoClass; 68 | parent::__construct($path); 69 | $this->setRelativePath($path); 70 | 71 | return; 72 | } 73 | 74 | /** 75 | * Current. 76 | * Please, see \DirectoryIterator::current() method. 77 | */ 78 | public function current() 79 | { 80 | $out = parent::current(); 81 | 82 | if (null !== $this->_splFileInfoClass && 83 | $out instanceof \SplFileInfo) { 84 | $out->setInfoClass($this->_splFileInfoClass); 85 | $out = $out->getFileInfo(); 86 | 87 | if ($out instanceof SplFileInfo) { 88 | $out->setRelativePath($this->getRelativePath()); 89 | } 90 | } 91 | 92 | return $out; 93 | } 94 | 95 | /** 96 | * Set relative path. 97 | */ 98 | protected function setRelativePath($path): ?string 99 | { 100 | $old = $this->_relativePath; 101 | $this->_relativePath = $path; 102 | 103 | return $old; 104 | } 105 | 106 | /** 107 | * Get relative path (if given). 108 | */ 109 | public function getRelativePath(): string 110 | { 111 | return $this->_relativePath; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Test/Unit/Append.php: -------------------------------------------------------------------------------- 1 | given( 57 | $counter1 = new LUT\Counter(0, 12, 3), 58 | $counter2 = new LUT\Counter(13, 23, 2), 59 | $append = new LUT\Append(), 60 | $append->append($counter1), 61 | $append->append($counter2) 62 | ) 63 | ->when($result = iterator_to_array($append, false)) 64 | ->then 65 | ->array($result) 66 | ->isEqualTo([ 67 | 0, 68 | 3, 69 | 6, 70 | 9, 71 | 13, 72 | 15, 73 | 17, 74 | 19, 75 | 21 76 | ]); 77 | } 78 | 79 | public function case_singleton(): void 80 | { 81 | $this 82 | ->given( 83 | $counter1 = new LUT\Counter(0, 12, 3), 84 | $append = new LUT\Append(), 85 | $append->append($counter1) 86 | ) 87 | ->when($result = iterator_to_array($append)) 88 | ->then 89 | ->array($result) 90 | ->isEqualTo([ 91 | 0, 92 | 3, 93 | 6, 94 | 9 95 | ]); 96 | } 97 | 98 | public function case_empty(): void 99 | { 100 | $this 101 | ->given($append = new LUT\Append()) 102 | ->when($result = iterator_to_array($append)) 103 | ->then 104 | ->array($result) 105 | ->isEmpty(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Source/SplFileInfo.php: -------------------------------------------------------------------------------- 1 | getMTime()) { 68 | $this->_hash = md5($this->getPathname() . $mtime); 69 | } 70 | 71 | $this->_relativePath = $relativePath; 72 | 73 | return; 74 | } 75 | 76 | /** 77 | * Get the hash. 78 | */ 79 | public function getHash(): string 80 | { 81 | return $this->_hash; 82 | } 83 | 84 | /** 85 | * Get the MTime. 86 | */ 87 | public function getMTime(): int 88 | { 89 | try { 90 | return parent::getMTime(); 91 | } catch (\RuntimeException $e) { 92 | return -1; 93 | } 94 | } 95 | 96 | /** 97 | * Set relative path. 98 | */ 99 | public function setRelativePath(string $relativePath): ?string 100 | { 101 | $old = $this->_relativePath; 102 | $this->_relativePath = $relativePath; 103 | 104 | return $old; 105 | } 106 | 107 | /** 108 | * Get relative path (if given). 109 | */ 110 | public function getRelativePath(): ?string 111 | { 112 | return $this->_relativePath; 113 | } 114 | 115 | /** 116 | * Get relative pathname (if possible). 117 | */ 118 | public function getRelativePathname(): string 119 | { 120 | if (null === $relative = $this->getRelativePath()) { 121 | return $this->getPathname(); 122 | } 123 | 124 | return substr($this->getPathname(), strlen($relative)); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Test/Unit/Repeater.php: -------------------------------------------------------------------------------- 1 | given( 61 | $iterator = new LUT\Map(self::$_dummyArray), 62 | $repeater = new LUT\Repeater($iterator, 3) 63 | ) 64 | ->when($result = iterator_to_array($repeater)) 65 | ->then 66 | ->array($result) 67 | ->isEqualTo( 68 | self::$_dummyArray + 69 | self::$_dummyArray + 70 | self::$_dummyArray 71 | ); 72 | } 73 | 74 | public function case_with_body(): void 75 | { 76 | $self = $this; 77 | 78 | $this 79 | ->given( 80 | $iterator = new LUT\Map(self::$_dummyArray), 81 | $count = 0, 82 | $repeater = new LUT\Repeater( 83 | $iterator, 84 | 3, 85 | function ($repetition) use ($self, &$count): void { 86 | $this 87 | ->integer($repetition) 88 | ->isEqualTo($count + 1); 89 | 90 | ++$count; 91 | } 92 | ) 93 | ) 94 | ->when($result = iterator_to_array($repeater)) 95 | ->then 96 | ->array($result) 97 | ->isEqualTo( 98 | self::$_dummyArray + 99 | self::$_dummyArray + 100 | self::$_dummyArray 101 | ) 102 | ->integer($count) 103 | ->isEqualTo(3); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Source/Recursive/Mock.php: -------------------------------------------------------------------------------- 1 | getIterator(); 63 | } 64 | 65 | $this->_iterator = $iterator; 66 | 67 | return; 68 | } 69 | 70 | /** 71 | * Return the current element. 72 | */ 73 | public function current() 74 | { 75 | return $this->_iterator->current(); 76 | } 77 | 78 | /** 79 | * Return the key of the current element. 80 | */ 81 | public function key() 82 | { 83 | return $this->_iterator->key(); 84 | } 85 | 86 | /** 87 | * Move forward to next element. 88 | */ 89 | public function next(): void 90 | { 91 | $this->_iterator->next(); 92 | } 93 | 94 | /** 95 | * Rewind the iterator to the first element. 96 | */ 97 | public function rewind(): void 98 | { 99 | $this->_iterator->rewind(); 100 | } 101 | 102 | /** 103 | * Check if current position is valid. 104 | * 105 | * @return bool 106 | */ 107 | public function valid(): bool 108 | { 109 | return $this->_iterator->valid(); 110 | } 111 | 112 | /** 113 | * Return an iterator for the current entry. 114 | * It's a fake, we return null. 115 | */ 116 | public function getChildren() 117 | { 118 | return null; 119 | } 120 | 121 | /** 122 | * Return if an iterator can be created for the current entry. 123 | * It's a fake, we return false. 124 | */ 125 | public function hasChildren(): bool 126 | { 127 | return false; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Source/Counter.php: -------------------------------------------------------------------------------- 1 | _from = $from; 91 | $this->_to = $to; 92 | $this->_step = $step; 93 | 94 | return; 95 | } 96 | 97 | /** 98 | * Return the current element. 99 | */ 100 | public function current(): int 101 | { 102 | return $this->_i; 103 | } 104 | 105 | /** 106 | * Return the key of the current element. 107 | */ 108 | public function key(): int 109 | { 110 | return $this->_key; 111 | } 112 | 113 | /** 114 | * Move forward to next element. 115 | */ 116 | public function next(): void 117 | { 118 | ++$this->_key; 119 | $this->_i += $this->_step; 120 | } 121 | 122 | /** 123 | * Rewind the iterator to the first element. 124 | */ 125 | public function rewind(): void 126 | { 127 | $this->_key = 0; 128 | $this->_i = $this->_from; 129 | } 130 | 131 | /** 132 | * Check if current position is valid. 133 | */ 134 | public function valid(): bool 135 | { 136 | return $this->_i < $this->_to; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /Source/Demultiplexer.php: -------------------------------------------------------------------------------- 1 | getIterator(); 73 | } 74 | 75 | $this->_iterator = $iterator; 76 | $this->_demuxer = $demuxer; 77 | 78 | return; 79 | } 80 | 81 | /** 82 | * Return the current element. 83 | */ 84 | public function current() 85 | { 86 | if (null !== $this->_current) { 87 | return $this->_current; 88 | } 89 | 90 | $demuxer = $this->_demuxer; 91 | 92 | return $this->_current = $demuxer($this->_iterator->current()); 93 | } 94 | 95 | /** 96 | * Return the key of the current element. 97 | */ 98 | public function key() 99 | { 100 | return $this->_iterator->key(); 101 | } 102 | 103 | /** 104 | * Move forward to next element. 105 | */ 106 | public function next(): void 107 | { 108 | $this->_current = null; 109 | $this->_iterator->next(); 110 | } 111 | 112 | /** 113 | * Rewind the iterator to the first element. 114 | */ 115 | public function rewind(): void 116 | { 117 | $this->_iterator->rewind(); 118 | } 119 | 120 | /** 121 | * Check if current position is valid. 122 | */ 123 | public function valid(): bool 124 | { 125 | return $this->_iterator->valid(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.17.01.10 2 | 3 | * Quality: Happy new year! (Alexis von Glasow, 2017-01-09T21:38:04+01:00) 4 | 5 | # 2.16.11.19 6 | 7 | * Documentation: New `README.md` file. (Ivan Enderlin, 2016-10-18T15:52:39+02:00) 8 | * Documentation: Use HTTPS in `composer.json`. (Ivan Enderlin, 2016-10-07T07:56:41+02:00) 9 | * Documentation: Update support properties. (Alexis von Glasow, 2016-10-06T19:17:39+02:00) 10 | * Test: Use the `::class` constant. (Ivan Enderlin, 2016-09-09T09:29:43+02:00) 11 | 12 | # 2.16.03.15 13 | 14 | * Buffer: Make `current` & `key` methods inlinable. (Ivan Enderlin, 2016-02-22T12:01:39+01:00) 15 | * README: Illustrate `Hoa\Iterator\Buffer`. (Ivan Enderlin, 2016-01-21T01:09:38+01:00) 16 | * Test: Write test suite of `Hoa\Iterator\Buffer`. (Ivan Enderlin, 2016-01-21T01:01:32+01:00) 17 | * Iterator: New `Buffer` iterator. (Ivan Enderlin, 2016-01-21T00:55:07+01:00) 18 | * Documentation: Update API annotation. (Ivan Enderlin, 2016-01-20T22:18:30+01:00) 19 | 20 | # 2.16.01.11 21 | 22 | * Quality: Drop PHP5.4. (Ivan Enderlin, 2016-01-11T09:15:26+01:00) 23 | * Quality: Run devtools:cs. (Ivan Enderlin, 2016-01-09T09:03:23+01:00) 24 | * Core: Remove `Hoa\Core`. (Ivan Enderlin, 2016-01-09T08:17:49+01:00) 25 | * Consistency: Use `Hoa\Consistency`. (Ivan Enderlin, 2015-12-08T11:16:47+01:00) 26 | * Exception: Use `Hoa\Exception`. (Ivan Enderlin, 2015-11-20T07:54:23+01:00) 27 | 28 | # 1.15.10.29 29 | 30 | * Test: Specify file type with `hoa://Test/Vfs`. (Ivan Enderlin, 2015-10-29T22:20:43+01:00) 31 | 32 | # 1.15.09.08 33 | 34 | * Format code. (Ivan Enderlin, 2015-08-27T09:29:13+02:00) 35 | * Add a `.gitignore` file. (Stéphane HULARD, 2015-08-03T11:33:46+02:00) 36 | 37 | # 1.15.05.29 38 | 39 | * Move to PSR-1 and PSR-2. (Ivan Enderlin, 2015-05-05T09:26:53+02:00) 40 | 41 | # 1.15.02.20 42 | 43 | * Add the CHANGELOG.md file. (Ivan Enderlin, 2015-02-20T09:38:07+01:00) 44 | * Happy new year! (Ivan Enderlin, 2015-01-05T14:36:22+01:00) 45 | 46 | # 1.14.12.10 47 | 48 | * Move to PSR-4. (Ivan Enderlin, 2014-12-09T13:52:31+01:00) 49 | 50 | # 1.14.11.26 51 | 52 | * Require `hoa/test`. (Ivan Enderlin, 2014-11-24T15:37:30+01:00) 53 | 54 | # 1.14.11.07 55 | 56 | * Finalized the library! (Ivan Enderlin, 2014-11-07T14:39:57+01:00) 57 | * `Recursive\Lookahead` has been removed. (Ivan Enderlin, 2014-11-07T14:29:59+01:00) 58 | * Add a note about Lookbehind. (Ivan Enderlin, 2014-11-07T14:28:33+01:00) 59 | * `RegularExpression` no longer extend `\RegexIterator`. (Ivan Enderlin, 2014-11-07T14:26:04+01:00) 60 | * Remove a note about PHP5.4. (Ivan Enderlin, 2014-11-07T14:24:48+01:00) 61 | * Add tests. (Ivan Enderlin, 2014-09-28T21:41:45+02:00) 62 | * Implement the `Lookbehind` iterator. (Ivan Enderlin, 2014-09-29T21:23:54+02:00) 63 | * `HasChildren` and `Tree` have been removed. (Ivan Enderlin, 2014-11-07T14:05:06+01:00) 64 | * Remove the `Recursive\Tree` iterator. (Ivan Enderlin, 2014-11-07T14:04:30+01:00) 65 | * `HasChildren` is not very well-defined, remove it. (Ivan Enderlin, 2014-11-07T13:38:15+01:00) 66 | * Fix API documentation. (Ivan Enderlin, 2014-10-11T09:17:42+02:00) 67 | * Fix the specific `fileinfo` class support. (Ivan Enderlin, 2014-10-11T09:15:37+02:00) 68 | * Update API documentation. (Ivan Enderlin, 2014-10-09T23:29:31+02:00) 69 | * Re-implement SPL `RegexIterator` and `Recursive~`. (Ivan Enderlin, 2014-10-06T14:47:25+02:00) 70 | * Bye bye `Recursive\Lookahead`. (Ivan Enderlin, 2014-10-01T22:25:48+02:00) 71 | * Rewrite the `Lookahead` iterator. (Ivan Enderlin, 2014-09-29T20:50:34+02:00) 72 | * Fix key. (Ivan Enderlin, 2014-09-28T21:41:51+02:00) 73 | * Add the `CallbackGenerator` iterator. (Ivan Enderlin, 2014-09-29T09:34:07+02:00) 74 | * Remove `from`/`import` and update to PHP5.4. (Ivan Enderlin, 2014-09-28T20:50:27+02:00) 75 | 76 | # 0.14.09.23 77 | 78 | * Add `branch-alias`. (Stéphane PY, 2014-09-23T11:50:40+02:00) 79 | 80 | # 0.14.09.17 81 | 82 | * Drop PHP5.3. (Ivan Enderlin, 2014-09-17T16:58:17+02:00) 83 | * Add the installation section. (Ivan Enderlin, 2014-09-17T16:57:53+02:00) 84 | 85 | (first snapshot) 86 | -------------------------------------------------------------------------------- /Source/Recursive/Directory.php: -------------------------------------------------------------------------------- 1 | _relativePath = $path; 74 | $this->setSplFileInfoClass($splFileInfoClass); 75 | 76 | return; 77 | } 78 | 79 | /** 80 | * Current. 81 | * Please, see \RecursiveDirectoryIterator::current() method. 82 | */ 83 | public function current() 84 | { 85 | $out = parent::current(); 86 | 87 | if (null !== $this->_splFileInfoClass && 88 | $out instanceof \SplFileInfo) { 89 | $out->setInfoClass($this->_splFileInfoClass); 90 | $out = $out->getFileInfo(); 91 | 92 | if ($out instanceof \Hoa\Iterator\SplFileInfo) { 93 | $out->setRelativePath($this->getRelativePath()); 94 | } 95 | } 96 | 97 | return $out; 98 | } 99 | 100 | /** 101 | * Get children. 102 | * Please, see \RecursiveDirectoryIterator::getChildren() method. 103 | */ 104 | public function getChildren() 105 | { 106 | $out = parent::getChildren(); 107 | $out->_relativePath = $this->getRelativePath(); 108 | $out->setSplFileInfoClass($this->_splFileInfoClass); 109 | 110 | return $out; 111 | } 112 | 113 | /** 114 | * Set SplFileInfo classname. 115 | */ 116 | public function setSplFileInfoClass(?string $splFileInfoClass): void 117 | { 118 | $this->_splFileInfoClass = $splFileInfoClass; 119 | } 120 | 121 | /** 122 | * Get relative path (if given). 123 | */ 124 | public function getRelativePath(): string 125 | { 126 | return $this->_relativePath; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Test/Unit/Filter.php: -------------------------------------------------------------------------------- 1 | given( 72 | $foobar = $this->getDummyIterator(), 73 | $filter = new \Mock\Hoa\Iterator\Test\Unit\MyFilter($foobar), 74 | $this->calling($filter)->accept = function () { 75 | $value = $this->current(); 76 | 77 | return false === in_array($value, ['a', 'e', 'i', 'o', 'u']); 78 | } 79 | ) 80 | ->when($result = iterator_to_array($filter)) 81 | ->then 82 | ->array($result) 83 | ->isEqualTo([ 84 | 0 => 'f', 85 | 3 => 'b', 86 | 5 => 'r' 87 | ]); 88 | } 89 | 90 | public function case_remove_all(): void 91 | { 92 | $this 93 | ->given( 94 | $foobar = $this->getDummyIterator(), 95 | $filter = new \Mock\Hoa\Iterator\Test\Unit\MyFilter($foobar), 96 | $this->calling($filter)->accept = false 97 | ) 98 | ->when($result = iterator_to_array($filter)) 99 | ->then 100 | ->array($result) 101 | ->isEmpty(); 102 | } 103 | 104 | public function case_remove_none(): void 105 | { 106 | $this 107 | ->given( 108 | $foobar = $this->getDummyIterator(), 109 | $filter = new MyFilter($foobar) 110 | ) 111 | ->when( 112 | $foobarResult = iterator_to_array($foobar), 113 | $filterResult = iterator_to_array($filter) 114 | ) 115 | ->then 116 | ->array($foobarResult) 117 | ->isEqualTo($filterResult); 118 | } 119 | 120 | protected function getDummyIterator() 121 | { 122 | return new LUT\Map(['f', 'o', 'o', 'b', 'a', 'r']); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Source/Lookbehind.php: -------------------------------------------------------------------------------- 1 | _iterator = $iterator; 71 | 72 | return; 73 | } 74 | 75 | /** 76 | * Get inner iterator. 77 | */ 78 | public function getInnerIterator(): iterable 79 | { 80 | return $this->_iterator; 81 | } 82 | 83 | /** 84 | * Return the current element. 85 | */ 86 | public function current() 87 | { 88 | return $this->getInnerIterator()->current(); 89 | } 90 | 91 | /** 92 | * Return the key of the current element. 93 | */ 94 | public function key() 95 | { 96 | return $this->getInnerIterator()->key(); 97 | } 98 | 99 | /** 100 | * Move forward to next element. 101 | */ 102 | public function next(): void 103 | { 104 | $this->_previousKey = $this->key(); 105 | $this->_previousCurrent = $this->current(); 106 | 107 | $this->getInnerIterator()->next(); 108 | } 109 | 110 | /** 111 | * Rewind the iterator to the first element. 112 | */ 113 | public function rewind(): void 114 | { 115 | $this->_previousKey = -1; 116 | $this->_previousCurrent = null; 117 | 118 | $this->getInnerIterator()->rewind(); 119 | } 120 | 121 | /** 122 | * Check if current position is valid. 123 | */ 124 | public function valid(): bool 125 | { 126 | return $this->getInnerIterator()->valid(); 127 | } 128 | 129 | /** 130 | * Check whether there is a previous element. 131 | */ 132 | public function hasPrevious(): bool 133 | { 134 | return -1 !== $this->_previousKey; 135 | } 136 | 137 | /** 138 | * Get previous value. 139 | */ 140 | public function getPrevious() 141 | { 142 | return $this->_previousCurrent; 143 | } 144 | 145 | /** 146 | * Get previous key. 147 | */ 148 | public function getPreviousKey() 149 | { 150 | return $this->_previousKey; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Source/Repeater.php: -------------------------------------------------------------------------------- 1 | = $n) { 76 | throw new Exception( 77 | 'n must be greater than 0, given %d.', 78 | 0, 79 | $n 80 | ); 81 | } 82 | 83 | if ($iterator instanceof \IteratorAggregate) { 84 | $iterator = $iterator->getIterator(); 85 | } 86 | 87 | $this->_iterator = $iterator; 88 | $this->_n = $n; 89 | $this->_body = $body; 90 | 91 | return; 92 | } 93 | 94 | /** 95 | * Return the current element. 96 | */ 97 | public function current() 98 | { 99 | return $this->_iterator->current(); 100 | } 101 | 102 | /** 103 | * Return the key of the current element. 104 | */ 105 | public function key() 106 | { 107 | return $this->_iterator->key(); 108 | } 109 | 110 | /** 111 | * Move forward to next element. 112 | */ 113 | public function next(): void 114 | { 115 | $this->_iterator->next(); 116 | } 117 | 118 | /** 119 | * Rewind the iterator to the first element. 120 | */ 121 | public function rewind(): void 122 | { 123 | $this->_iterator->rewind(); 124 | } 125 | 126 | /** 127 | * Check if current position is valid. 128 | */ 129 | public function valid(): bool 130 | { 131 | $valid = $this->_iterator->valid(); 132 | 133 | if (true === $valid) { 134 | return true; 135 | } 136 | 137 | if (null !== $this->_body) { 138 | $handle = &$this->_body; 139 | $handle($this->_i); 140 | } 141 | 142 | $this->rewind(); 143 | 144 | if ($this->_n <= $this->_i++) { 145 | $this->_i = 1; 146 | 147 | return false; 148 | } 149 | 150 | return true; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Test/Unit/Multiple.php: -------------------------------------------------------------------------------- 1 | given( 57 | $foo = new LUT\Map(['f', 'o', 'o']), 58 | $bar = new LUT\Map(['b', 'a', 'r']), 59 | $multiple = new LUT\Multiple( 60 | LUT\Multiple::MIT_NEED_ANY 61 | | LUT\Multiple::MIT_KEYS_ASSOC 62 | ), 63 | $multiple->attachIterator($foo, 'one'), 64 | $multiple->attachIterator($bar, 'two') 65 | ) 66 | ->when($result = iterator_to_array($multiple, false)) 67 | ->then 68 | ->array($result) 69 | ->isEqualTo([ 70 | ['one' => 'f', 'two' => 'b'], 71 | ['one' => 'o', 'two' => 'a'], 72 | ['one' => 'o', 'two' => 'r'] 73 | ]); 74 | } 75 | 76 | public function case_default_value(): void 77 | { 78 | $this 79 | ->given( 80 | $foobar = new LUT\Map(['f', 'o', 'o', 'b', 'a', 'r']), 81 | $baz = new LUT\Map(['b', 'a', 'z']), 82 | $multiple = new LUT\Multiple( 83 | LUT\Multiple::MIT_NEED_ANY 84 | | LUT\Multiple::MIT_KEYS_ASSOC 85 | ), 86 | $multiple->attachIterator($foobar, 'one', '!'), 87 | $multiple->attachIterator($baz, 'two', '?') 88 | ) 89 | ->when($result = iterator_to_array($multiple, false)) 90 | ->then 91 | ->array($result) 92 | ->isEqualTo([ 93 | ['one' => 'f', 'two' => 'b'], 94 | ['one' => 'o', 'two' => 'a'], 95 | ['one' => 'o', 'two' => 'z'], 96 | ['one' => 'b', 'two' => '?'], 97 | ['one' => 'a', 'two' => '?'], 98 | ['one' => 'r', 'two' => '?'], 99 | ]); 100 | } 101 | 102 | public function case_empty(): void 103 | { 104 | $this 105 | ->given($multiple = new LUT\Multiple()) 106 | ->when($result = iterator_to_array($multiple)) 107 | ->then 108 | ->array($result) 109 | ->isEmpty(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Test/Unit/Map.php: -------------------------------------------------------------------------------- 1 | given($iterator = new LUT\Map(self::$_dummyArray)) 61 | ->when($result = iterator_to_array($iterator)) 62 | ->then 63 | ->array($result) 64 | ->isEqualTo(self::$_dummyArray); 65 | } 66 | 67 | public function case_empty(): void 68 | { 69 | $this 70 | ->given($iterator = new LUT\Map()) 71 | ->when($result = iterator_to_array($iterator)) 72 | ->then 73 | ->array($result) 74 | ->isEmpty(); 75 | } 76 | 77 | public function case_recursive(): void 78 | { 79 | $this 80 | ->given( 81 | $array = [ 82 | 'a' => ['b', 'c', 'd'], 83 | 'e' => ['f', 'g', 'i'], 84 | 'k' 85 | ], 86 | $iterator = new LUT\Recursive\Map($array) 87 | ) 88 | ->when(function () use ($iterator): void { 89 | foreach ($iterator as $key => $value) { 90 | if ('a' === $key) { 91 | $this 92 | ->boolean($iterator->hasChildren()) 93 | ->isTrue() 94 | ->object($children = $iterator->getChildren()) 95 | ->isInstanceOf(LUT\Recursive\Map::class) 96 | ->array(iterator_to_array($children)) 97 | ->isEqualTo(['b', 'c', 'd']); 98 | } elseif ('e' === $key) { 99 | $this 100 | ->boolean($iterator->hasChildren()) 101 | ->isTrue() 102 | ->object($children = $iterator->getChildren()) 103 | ->isInstanceOf(LUT\Recursive\Map::class) 104 | ->array(iterator_to_array($children)) 105 | ->isEqualTo(['f', 'g', 'i']); 106 | } elseif ('k' === $value) { 107 | $this 108 | ->boolean($iterator->hasChildren()) 109 | ->isFalse(); 110 | } 111 | } 112 | }); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Test/Unit/Demultiplexer.php: -------------------------------------------------------------------------------- 1 | given( 57 | $counter = new LUT\Counter(0, 10, 1), 58 | $multiple = new LUT\Multiple(), 59 | $multiple->attachIterator($counter), 60 | $multiple->attachIterator(clone $counter), 61 | $demultiplexer = new LUT\Demultiplexer( 62 | $multiple, 63 | function ($current) { 64 | return $current[0] * $current[1]; 65 | } 66 | ) 67 | ) 68 | ->when($result = iterator_to_array($demultiplexer, false)) 69 | ->then 70 | ->array($result) 71 | ->isEqualTo([ 72 | 0, 73 | 1, 74 | 4, 75 | 9, 76 | 16, 77 | 25, 78 | 36, 79 | 49, 80 | 64, 81 | 81 82 | ]); 83 | } 84 | 85 | public function case_associative_keys(): void 86 | { 87 | $this 88 | ->given( 89 | $counter = new LUT\Counter(0, 10, 1), 90 | $multiple = new LUT\Multiple( 91 | LUT\Multiple::MIT_NEED_ANY 92 | | LUT\Multiple::MIT_KEYS_ASSOC 93 | ), 94 | $multiple->attachIterator($counter, 'one'), 95 | $multiple->attachIterator(clone $counter, 'two'), 96 | $demultiplexer = new LUT\Demultiplexer( 97 | $multiple, 98 | function ($current) { 99 | return $current['one'] * $current['two']; 100 | } 101 | ) 102 | ) 103 | ->when($result = iterator_to_array($demultiplexer, false)) 104 | ->then 105 | ->array($result) 106 | ->isEqualTo([ 107 | 0, 108 | 1, 109 | 4, 110 | 9, 111 | 16, 112 | 25, 113 | 36, 114 | 49, 115 | 64, 116 | 81 117 | ]); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Source/Lookahead.php: -------------------------------------------------------------------------------- 1 | _iterator = $iterator; 76 | 77 | return; 78 | } 79 | 80 | /** 81 | * Get inner iterator. 82 | */ 83 | public function getInnerIterator(): iterable 84 | { 85 | return $this->_iterator; 86 | } 87 | 88 | /** 89 | * Return the current element. 90 | */ 91 | public function current() 92 | { 93 | return $this->_current; 94 | } 95 | 96 | /** 97 | * Return the key of the current element. 98 | */ 99 | public function key() 100 | { 101 | return $this->_key; 102 | } 103 | 104 | /** 105 | * Move forward to next element. 106 | */ 107 | public function next(): void 108 | { 109 | $innerIterator = $this->getInnerIterator(); 110 | $this->_valid = $innerIterator->valid(); 111 | 112 | if (false === $this->_valid) { 113 | return; 114 | } 115 | 116 | $this->_key = $innerIterator->key(); 117 | $this->_current = $innerIterator->current(); 118 | 119 | $innerIterator->next(); 120 | } 121 | 122 | /** 123 | * Rewind the iterator to the first element. 124 | */ 125 | public function rewind(): void 126 | { 127 | $this->getInnerIterator()->rewind(); 128 | $this->next(); 129 | } 130 | 131 | /** 132 | * Check if current position is valid. 133 | */ 134 | public function valid(): bool 135 | { 136 | return $this->_valid; 137 | } 138 | 139 | /** 140 | * Check whether there is a next element. 141 | */ 142 | public function hasNext(): bool 143 | { 144 | return $this->getInnerIterator()->valid(); 145 | } 146 | 147 | /** 148 | * Get next value. 149 | */ 150 | public function getNext() 151 | { 152 | return $this->getInnerIterator()->current(); 153 | } 154 | 155 | /** 156 | * Get next key. 157 | */ 158 | public function getNextKey() 159 | { 160 | return $this->getInnerIterator()->key(); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Test/Unit/RegularExpression.php: -------------------------------------------------------------------------------- 1 | given( 57 | $map = new LUT\Map([ 58 | 'abc', 59 | 'dea', 60 | 'fgh', 61 | 'iaj', 62 | 'klm' 63 | ]), 64 | $iterator = new LUT\RegularExpression($map, '/a/') 65 | ) 66 | ->when($result = iterator_to_array($iterator)) 67 | ->then 68 | ->array($result) 69 | ->isEqualTo([ 70 | 0 => 'abc', 71 | 1 => 'dea', 72 | 3 => 'iaj' 73 | ]); 74 | } 75 | 76 | public function case_recursive(): void 77 | { 78 | $this 79 | ->given( 80 | $map = new LUT\Recursive\Map([ 81 | ['abc', 'dea', 'fgh'], 82 | ['iaj', 'klm'] 83 | ]), 84 | $regex = new LUT\Recursive\RegularExpression($map, '/a/'), 85 | $iterator = new LUT\Recursive\Iterator($regex) 86 | ) 87 | ->when($result = iterator_to_array($iterator, false)) 88 | ->then 89 | ->array($result) 90 | ->isEqualTo([ 91 | 0 => 'abc', 92 | 1 => 'dea', 93 | 2 => 'iaj' 94 | ]); 95 | } 96 | 97 | public function case_recursive_children_flags(): void 98 | { 99 | $this 100 | ->given( 101 | $map = new LUT\Recursive\Map([ 102 | ['abc', 'dea', 'fgh'], 103 | ['iaj', 'klm'] 104 | ]), 105 | $mode = LUT\Recursive\RegularExpression::ALL_MATCHES, 106 | $flag = LUT\Recursive\RegularExpression::USE_KEY, 107 | $pregFlag = LUT\Recursive\RegularExpression::ALL_MATCHES, 108 | $iterator = new LUT\Recursive\RegularExpression( 109 | $map, 110 | '/a/', 111 | $mode, 112 | $flag, 113 | $pregFlag 114 | ) 115 | ) 116 | ->when($result = $iterator->getChildren()) 117 | ->then 118 | ->object($result) 119 | ->isInstanceOf(LUT\Recursive\RegularExpression::class) 120 | ->integer($result->getMode()) 121 | ->isEqualTo($mode) 122 | ->integer($result->getFlags()) 123 | ->isEqualTo($flag) 124 | ->integer($result->getPregFlags()) 125 | ->isEqualTo($pregFlag); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Test/Unit/FileSystem.php: -------------------------------------------------------------------------------- 1 | given( 58 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 59 | $this->resolve('hoa://Test/Vfs/Root/.?type=directory'), 60 | $this->resolve('hoa://Test/Vfs/Root/..?type=directory'), 61 | $this->resolve('hoa://Test/Vfs/Root/A?type=file'), 62 | $this->resolve('hoa://Test/Vfs/Root/B?type=file'), 63 | $iterator = new LUT\FileSystem($root), 64 | $result = [] 65 | ) 66 | ->when(function () use ($iterator, &$result): void { 67 | foreach ($iterator as $pathname => $file) { 68 | $this 69 | ->object($file) 70 | ->isInstanceOf('SplFileInfo'); 71 | 72 | $result[basename($pathname)] = $file->getFilename(); 73 | } 74 | }) 75 | ->array($result) 76 | ->isEqualTo([ 77 | 'A' => 'A', 78 | 'B' => 'B' 79 | ]); 80 | } 81 | 82 | public function case_splFileClassInfo(): void 83 | { 84 | $this 85 | ->given( 86 | $splFileInfo = 'Hoa\Iterator\SplFileInfo', 87 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 88 | $this->resolve('hoa://Test/Vfs/Root/a?type=file'), 89 | $this->resolve('hoa://Test/Vfs/Root/b?type=file'), 90 | $this->resolve('hoa://Test/Vfs/Root/c?type=file'), 91 | $this->resolve('hoa://Test/Vfs/Root/d?type=file'), 92 | $this->resolve('hoa://Test/Vfs/Root/e?type=file'), 93 | $this->resolve('hoa://Test/Vfs/Root/f?type=file'), 94 | $iterator = new LUT\FileSystem( 95 | $root, 96 | LUT\FileSystem::CURRENT_AS_FILEINFO, 97 | $splFileInfo 98 | ), 99 | $result = [] 100 | ) 101 | ->when(function () use ($iterator, $splFileInfo, &$result): void { 102 | foreach ($iterator as $file) { 103 | $this 104 | ->object($file) 105 | ->isInstanceOf($splFileInfo); 106 | 107 | $result[] = $file->getFilename(); 108 | } 109 | }) 110 | ->then 111 | ->array($result) 112 | ->isEqualTo([ 113 | 'a', 114 | 'b', 115 | 'c', 116 | 'd', 117 | 'e', 118 | 'f' 119 | ]); 120 | } 121 | 122 | private function resolve(string $path) 123 | { 124 | return Protocol\Protocol::getInstance()->resolve($path); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Test/Unit/IteratorIterator.php: -------------------------------------------------------------------------------- 1 | given( 57 | $iterator = new LUT\Map([]), 58 | $iteratoriterator = new LUT\IteratorIterator($iterator) 59 | ) 60 | ->when($result = $iteratoriterator->getInnerIterator()) 61 | ->then 62 | ->object($result) 63 | ->isIdenticalTo($iterator); 64 | } 65 | 66 | public function case_traverse(): void 67 | { 68 | $this 69 | ->given( 70 | $iterator = new LUT\Map(['a', 'b', 'c']), 71 | $iteratoriterator = new LUT\IteratorIterator($iterator) 72 | ) 73 | ->when($result = iterator_to_array($iteratoriterator)) 74 | ->then 75 | ->array($result) 76 | ->isEqualTo(['a', 'b', 'c']); 77 | } 78 | 79 | public function case_recursive_leaves_only(): void 80 | { 81 | $this 82 | ->given( 83 | $array = [ 84 | 'a' => ['b', 'c', 'd'], 85 | 'e' => ['f', 'g', 'i'] 86 | ], 87 | $iterator = new LUT\Recursive\Map($array), 88 | $iteratoriterator = new LUT\Recursive\Iterator( 89 | $iterator, 90 | LUT\Recursive\Iterator::LEAVES_ONLY 91 | ) 92 | ) 93 | ->when($result = iterator_to_array($iteratoriterator, false)) 94 | ->then 95 | ->array($result) 96 | ->isEqualTo(['b', 'c', 'd', 'f', 'g', 'i']); 97 | } 98 | 99 | public function case_recursive_self_first(): void 100 | { 101 | $this 102 | ->given( 103 | $array = [ 104 | 'a' => ['b', 'c', 'd'], 105 | 'e' => ['f', 'g', 'i'] 106 | ], 107 | $iterator = new LUT\Recursive\Map($array), 108 | $iteratoriterator = new LUT\Recursive\Iterator( 109 | $iterator, 110 | LUT\Recursive\Iterator::SELF_FIRST 111 | ) 112 | ) 113 | ->when($result = iterator_to_array($iteratoriterator, false)) 114 | ->then 115 | ->array($result) 116 | ->isEqualTo([ 117 | ['b', 'c', 'd'], 118 | 'b', 119 | 'c', 120 | 'd', 121 | ['f', 'g', 'i'], 122 | 'f', 123 | 'g', 124 | 'i' 125 | ]); 126 | } 127 | 128 | public function case_recursive_child_first(): void 129 | { 130 | $this 131 | ->given( 132 | $array = [ 133 | 'a' => ['b', 'c', 'd'], 134 | 'e' => ['f', 'g', 'i'] 135 | ], 136 | $iterator = new LUT\Recursive\Map($array), 137 | $iteratoriterator = new LUT\Recursive\Iterator( 138 | $iterator, 139 | LUT\Recursive\Iterator::CHILD_FIRST 140 | ) 141 | ) 142 | ->when($result = iterator_to_array($iteratoriterator, false)) 143 | ->then 144 | ->array($result) 145 | ->isEqualTo([ 146 | 'b', 147 | 'c', 148 | 'd', 149 | ['b', 'c', 'd'], 150 | 'f', 151 | 'g', 152 | 'i', 153 | ['f', 'g', 'i'] 154 | ]); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Source/Buffer.php: -------------------------------------------------------------------------------- 1 | _iterator = $iterator; 81 | $this->_bufferSize = max($bufferSize, 1); 82 | $this->_buffer = new \SplDoublyLinkedList(); 83 | 84 | return; 85 | } 86 | 87 | /** 88 | * Get inner iterator. 89 | */ 90 | public function getInnerIterator(): iterable 91 | { 92 | return $this->_iterator; 93 | } 94 | 95 | /** 96 | * Get buffer. 97 | */ 98 | protected function getBuffer(): \SplDoublyLinkedList 99 | { 100 | return $this->_buffer; 101 | } 102 | 103 | /** 104 | * Get buffer size. 105 | */ 106 | public function getBufferSize(): int 107 | { 108 | return $this->_bufferSize; 109 | } 110 | 111 | /** 112 | * Return the current element. 113 | */ 114 | public function current() 115 | { 116 | return $this->getBuffer()->current()[self::BUFFER_VALUE]; 117 | } 118 | 119 | /** 120 | * Return the key of the current element. 121 | */ 122 | public function key() 123 | { 124 | return $this->getBuffer()->current()[self::BUFFER_KEY]; 125 | } 126 | 127 | /** 128 | * Move forward to next element. 129 | */ 130 | public function next(): void 131 | { 132 | $innerIterator = $this->getInnerIterator(); 133 | $buffer = $this->getBuffer(); 134 | 135 | $buffer->next(); 136 | 137 | // End of the buffer, need a new value. 138 | if (false === $buffer->valid()) { 139 | for ( 140 | $bufferSize = count($buffer), 141 | $maximumBufferSize = $this->getBufferSize(); 142 | $bufferSize >= $maximumBufferSize; 143 | --$bufferSize 144 | ) { 145 | $buffer->shift(); 146 | } 147 | 148 | $innerIterator->next(); 149 | 150 | $buffer->push([ 151 | self::BUFFER_KEY => $innerIterator->key(), 152 | self::BUFFER_VALUE => $innerIterator->current() 153 | ]); 154 | 155 | // Seek to the end of the buffer. 156 | $buffer->setIteratorMode($buffer::IT_MODE_LIFO | $buffer::IT_MODE_KEEP); 157 | $buffer->rewind(); 158 | $buffer->setIteratorMode($buffer::IT_MODE_FIFO | $buffer::IT_MODE_KEEP); 159 | } 160 | } 161 | 162 | /** 163 | * Move backward to previous element. 164 | */ 165 | public function previous(): void 166 | { 167 | $this->getBuffer()->prev(); 168 | } 169 | 170 | /** 171 | * Rewind the iterator to the first element. 172 | */ 173 | public function rewind(): void 174 | { 175 | $innerIterator = $this->getInnerIterator(); 176 | $buffer = $this->getBuffer(); 177 | 178 | $innerIterator->rewind(); 179 | 180 | if (true === $buffer->isEmpty()) { 181 | $buffer->push([ 182 | self::BUFFER_KEY => $innerIterator->key(), 183 | self::BUFFER_VALUE => $innerIterator->current() 184 | ]); 185 | } 186 | 187 | $buffer->rewind(); 188 | 189 | return; 190 | } 191 | 192 | /** 193 | * Check if current position is valid. 194 | */ 195 | public function valid(): bool 196 | { 197 | return 198 | $this->getBuffer()->valid() && 199 | $this->getInnerIterator()->valid(); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /Test/Unit/Lookbehind.php: -------------------------------------------------------------------------------- 1 | given( 57 | $iterator = new LUT\Map(['a', 'b', 'c']), 58 | $lookbehind = new LUT\Lookbehind($iterator) 59 | ) 60 | ->when($result = iterator_to_array($iterator)) 61 | ->then 62 | ->array($result) 63 | ->isEqualTo(['a', 'b', 'c']); 64 | } 65 | 66 | public function case_check_behind(): void 67 | { 68 | $this 69 | ->given( 70 | $iterator = new LUT\Map(['a', 'b', 'c']), 71 | $lookbehind = new LUT\Lookbehind($iterator) 72 | ) 73 | ->when( 74 | $lookbehind->rewind(), 75 | $key = $lookbehind->key(), 76 | $current = $lookbehind->current(), 77 | $hasPrevious = $lookbehind->hasPrevious(), 78 | $previous = $lookbehind->getPrevious() 79 | ) 80 | ->then 81 | ->integer($key) 82 | ->isEqualTo(0) 83 | ->string($current) 84 | ->isEqualTo('a') 85 | ->boolean($hasPrevious) 86 | ->isFalse() 87 | ->variable($previous) 88 | ->isNull() 89 | 90 | ->when( 91 | $lookbehind->next(), 92 | $key = $lookbehind->key(), 93 | $current = $lookbehind->current(), 94 | $hasPrevious = $lookbehind->hasPrevious(), 95 | $previous = $lookbehind->getPrevious() 96 | ) 97 | ->then 98 | ->integer($key) 99 | ->isEqualTo(1) 100 | ->string($current) 101 | ->isEqualTo('b') 102 | ->boolean($hasPrevious) 103 | ->isTrue() 104 | ->string($previous) 105 | ->isEqualTo('a') 106 | 107 | ->when( 108 | $lookbehind->next(), 109 | $key = $lookbehind->key(), 110 | $current = $lookbehind->current(), 111 | $hasPrevious = $lookbehind->hasPrevious(), 112 | $previous = $lookbehind->getPrevious() 113 | ) 114 | ->then 115 | ->integer($key) 116 | ->isEqualTo(2) 117 | ->string($current) 118 | ->isEqualTo('c') 119 | ->boolean($hasPrevious) 120 | ->isTrue() 121 | ->string($previous) 122 | ->isEqualTo('b'); 123 | } 124 | 125 | public function case_double_rewind(): void 126 | { 127 | $this 128 | ->given( 129 | $iterator = new LUT\Map(['a', 'b', 'c']), 130 | $lookbehind = new LUT\Lookbehind($iterator) 131 | ) 132 | ->when( 133 | $lookbehind->rewind(), 134 | $key = $lookbehind->key(), 135 | $current = $lookbehind->current(), 136 | $hasPrevious = $lookbehind->hasPrevious() 137 | ) 138 | ->then 139 | ->integer($key) 140 | ->isEqualTo(0) 141 | ->string($current) 142 | ->isEqualTo('a') 143 | ->boolean($hasPrevious) 144 | ->isFalse() 145 | 146 | ->when( 147 | $lookbehind->rewind(), 148 | $key = $lookbehind->key(), 149 | $current = $lookbehind->current(), 150 | $hasPrevious = $lookbehind->hasPrevious() 151 | ) 152 | ->then 153 | ->integer($key) 154 | ->isEqualTo(0) 155 | ->string($current) 156 | ->isEqualTo('a') 157 | ->boolean($hasPrevious) 158 | ->isFalse(); 159 | } 160 | 161 | public function case_empty(): void 162 | { 163 | $this 164 | ->given( 165 | $iterator = new LUT\Mock(), 166 | $lookbehind = new LUT\Lookbehind($iterator) 167 | ) 168 | ->when( 169 | $lookbehind->rewind(), 170 | $valid = $lookbehind->valid() 171 | ) 172 | ->then 173 | ->boolean($valid) 174 | ->isFalse(); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /Test/Unit/Lookahead.php: -------------------------------------------------------------------------------- 1 | given( 57 | $iterator = new LUT\Map(['a', 'b', 'c']), 58 | $lookahead = new LUT\Lookahead($iterator) 59 | ) 60 | ->when($result = iterator_to_array($iterator)) 61 | ->then 62 | ->array($result) 63 | ->isEqualTo(['a', 'b', 'c']); 64 | } 65 | 66 | public function case_check_ahead(): void 67 | { 68 | $this 69 | ->given( 70 | $iterator = new LUT\Map(['a', 'b', 'c']), 71 | $lookahead = new LUT\Lookahead($iterator) 72 | ) 73 | ->when( 74 | $lookahead->rewind(), 75 | $key = $lookahead->key(), 76 | $current = $lookahead->current(), 77 | $hasNext = $lookahead->hasNext(), 78 | $next = $lookahead->getNext() 79 | ) 80 | ->then 81 | ->integer($key) 82 | ->isEqualTo(0) 83 | ->string($current) 84 | ->isEqualTo('a') 85 | ->boolean($hasNext) 86 | ->isTrue() 87 | ->string($next) 88 | ->isEqualTo('b') 89 | 90 | ->when( 91 | $lookahead->next(), 92 | $key = $lookahead->key(), 93 | $current = $lookahead->current(), 94 | $hasNext = $lookahead->hasNext(), 95 | $next = $lookahead->getNext() 96 | ) 97 | ->then 98 | ->integer($key) 99 | ->isEqualTo(1) 100 | ->string($current) 101 | ->isEqualTo('b') 102 | ->boolean($hasNext) 103 | ->isTrue() 104 | ->string($next) 105 | ->isEqualTo('c') 106 | 107 | ->when( 108 | $lookahead->next(), 109 | $key = $lookahead->key(), 110 | $current = $lookahead->current(), 111 | $hasNext = $lookahead->hasNext(), 112 | $next = $lookahead->getNext() 113 | ) 114 | ->then 115 | ->integer($key) 116 | ->isEqualTo(2) 117 | ->string($current) 118 | ->isEqualTo('c') 119 | ->boolean($hasNext) 120 | ->isFalse() 121 | ->variable($next) 122 | ->isNull(); 123 | } 124 | 125 | public function case_double_rewind(): void 126 | { 127 | $this 128 | ->given( 129 | $iterator = new LUT\Map(['a', 'b', 'c']), 130 | $lookahead = new LUT\Lookahead($iterator) 131 | ) 132 | ->when( 133 | $lookahead->rewind(), 134 | $key = $lookahead->key(), 135 | $current = $lookahead->current(), 136 | $hasNext = $lookahead->hasNext(), 137 | $next = $lookahead->getNext() 138 | ) 139 | ->then 140 | ->integer($key) 141 | ->isEqualTo(0) 142 | ->string($current) 143 | ->isEqualTo('a') 144 | ->boolean($hasNext) 145 | ->isTrue() 146 | ->string($next) 147 | ->isEqualTo('b') 148 | 149 | ->when( 150 | $lookahead->rewind(), 151 | $key = $lookahead->key(), 152 | $current = $lookahead->current(), 153 | $hasNext = $lookahead->hasNext(), 154 | $next = $lookahead->getNext() 155 | ) 156 | ->then 157 | ->integer($key) 158 | ->isEqualTo(0) 159 | ->string($current) 160 | ->isEqualTo('a') 161 | ->boolean($hasNext) 162 | ->isTrue() 163 | ->string($next) 164 | ->isEqualTo('b'); 165 | } 166 | 167 | public function case_empty(): void 168 | { 169 | $this 170 | ->given( 171 | $iterator = new LUT\Mock(), 172 | $lookahead = new LUT\Lookahead($iterator) 173 | ) 174 | ->when( 175 | $lookahead->rewind(), 176 | $valid = $lookahead->valid() 177 | ) 178 | ->then 179 | ->boolean($valid) 180 | ->isFalse(); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Test/Unit/SplFileInfo.php: -------------------------------------------------------------------------------- 1 | given($pathname = 'hoa://Test/Vfs/Foo.bar?type=file') 57 | ->when($result = new LUT\SplFileInfo($pathname)) 58 | ->then 59 | ->boolean($result->isFile()) 60 | ->isTrue() 61 | ->string($result->getType()) 62 | ->isEqualTo('file'); 63 | } 64 | 65 | public function case_directory(): void 66 | { 67 | $this 68 | ->given($pathname = 'hoa://Test/Vfs/Foo?type=directory') 69 | ->when($result = new LUT\SplFileInfo($pathname)) 70 | ->then 71 | ->boolean($result->isDir()) 72 | ->isTrue() 73 | ->string($result->getType()) 74 | ->isEqualTo('dir'); 75 | } 76 | 77 | public function case_path_informations(): void 78 | { 79 | $this 80 | ->given( 81 | $relativePath = 'hoa://Test/Vfs/A/B/', 82 | $relativePathname = 'C/Foo.bar', 83 | $pathname = $relativePath . $relativePathname 84 | ) 85 | ->when($result = new LUT\SplFileInfo($pathname . '?type=file', $relativePath)) 86 | ->then 87 | ->boolean($result->isFile()) 88 | ->isTrue() 89 | ->string($result->getBasename()) 90 | ->isEqualTo('Foo.bar?type=file') 91 | ->string($result->getExtension()) 92 | ->isEqualTo('bar?type=file') 93 | ->string($result->getRelativePath()) 94 | ->isEqualTo($relativePath) 95 | ->string($result->getRelativePathname()) 96 | ->isEqualTo($relativePathname . '?type=file') 97 | ->string($result->getPath()) 98 | ->isEqualTo('hoa://Test/Vfs/A/B/C') 99 | ->string($result->getPathname()) 100 | ->isEqualTo($pathname . '?type=file'); 101 | } 102 | 103 | public function case_times(): void 104 | { 105 | $this 106 | ->given( 107 | $timestamp = $this->realdom->boundinteger( 108 | $this->realdom->timestamp('yesterday'), 109 | $this->realdom->timestamp('tomorrow') 110 | ), 111 | $atime = $this->sample($timestamp), 112 | $ctime = $this->sample($timestamp), 113 | $mtime = $this->sample($timestamp), 114 | $pathname = 115 | 'hoa://Test/Vfs/Foo.bar?' . 116 | http_build_query([ 117 | 'type' => 'file', 118 | 'atime' => $atime, 119 | 'ctime' => $ctime, 120 | 'mtime' => $mtime 121 | ]) 122 | ) 123 | ->when($result = new LUT\SplFileInfo($pathname)) 124 | ->then 125 | ->integer($result->getATime()) 126 | ->isEqualTo($atime) 127 | ->integer($result->getCTime()) 128 | ->isEqualTo($ctime) 129 | ->integer($result->getMTime()) 130 | ->isEqualTo($mtime); 131 | } 132 | 133 | public function case_permissions(): void 134 | { 135 | $this 136 | ->given($pathname = 'hoa://Test/Vfs/Fo.bar?type=file&permissions=0744') 137 | ->when($result = new LUT\SplFileInfo($pathname)) 138 | ->then 139 | ->boolean($result->isReadable()) 140 | ->isTrue() 141 | ->boolean($result->isWritable()) 142 | ->isTrue() 143 | ->boolean($result->isExecutable()) 144 | ->isTrue() 145 | 146 | ->given($pathname = 'hoa://Test/Vfs/Foo.bar?type=file&permissions=0644') 147 | ->when($result = new LUT\SplFileInfo($pathname)) 148 | ->then 149 | ->boolean($result->isReadable()) 150 | ->isTrue() 151 | ->boolean($result->isWritable()) 152 | ->isTrue() 153 | ->boolean($result->isExecutable()) 154 | ->isFalse() 155 | 156 | ->given($pathname = 'hoa://Test/Vfs/Fooo.bar?type=file&permissions=0444') 157 | ->when($result = new LUT\SplFileInfo($pathname)) 158 | ->then 159 | ->boolean($result->isReadable()) 160 | ->isTrue() 161 | ->boolean($result->isWritable()) 162 | ->isFalse() 163 | ->boolean($result->isExecutable()) 164 | ->isFalse() 165 | 166 | ->given($pathname = 'hoa://Test/Vfs/Foooo.bar?type=file&permissions=0044') 167 | ->when($result = new LUT\SplFileInfo($pathname)) 168 | ->then 169 | ->boolean($result->isReadable()) 170 | ->isFalse() 171 | ->boolean($result->isWritable()) 172 | ->isFalse() 173 | ->boolean($result->isExecutable()) 174 | ->isFalse(); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /Test/Unit/CallbackFilter.php: -------------------------------------------------------------------------------- 1 | given( 57 | $foobar = $this->getDummyIterator(), 58 | $filter = new LUT\CallbackFilter( 59 | $foobar, 60 | function ($value) { 61 | return false === in_array($value, ['a', 'e', 'i', 'o', 'u']); 62 | } 63 | ) 64 | ) 65 | ->when($result = iterator_to_array($filter)) 66 | ->then 67 | ->array($result) 68 | ->isEqualTo([ 69 | 0 => 'f', 70 | 3 => 'b', 71 | 5 => 'r' 72 | ]); 73 | } 74 | 75 | public function case_all_callback_parameters(): void 76 | { 77 | $self = $this; 78 | 79 | $this 80 | ->given( 81 | $foobar = $this->getDummyIterator(), 82 | $keys = [], 83 | $values = [], 84 | $filter = new LUT\CallbackFilter( 85 | $foobar, 86 | function ($value, $key, $iterator) use ( 87 | $self, 88 | $foobar, 89 | &$keys, 90 | &$values 91 | ) { 92 | $self 93 | ->object($iterator) 94 | ->isIdenticalTo($foobar); 95 | 96 | $keys[] = $key; 97 | $values[] = $value; 98 | 99 | return false === in_array($value, ['a', 'e', 'i', 'o', 'u']); 100 | } 101 | ) 102 | ) 103 | ->when($result = iterator_to_array($filter)) 104 | ->then 105 | ->array($result) 106 | ->isEqualTo([ 107 | 0 => 'f', 108 | 3 => 'b', 109 | 5 => 'r' 110 | ]) 111 | ->array(array_combine($keys, $values)) 112 | ->isEqualTo(iterator_to_array($foobar)); 113 | } 114 | 115 | public function case_remove_all(): void 116 | { 117 | $this 118 | ->given( 119 | $foobar = $this->getDummyIterator(), 120 | $filter = new LUT\CallbackFilter( 121 | $foobar, 122 | function () { 123 | return false; 124 | } 125 | ) 126 | ) 127 | ->when($result = iterator_to_array($filter)) 128 | ->then 129 | ->array($result) 130 | ->isEmpty(); 131 | } 132 | 133 | public function case_remove_none(): void 134 | { 135 | $this 136 | ->given( 137 | $foobar = $this->getDummyIterator(), 138 | $filter = new LUT\CallbackFilter( 139 | $foobar, 140 | function () { 141 | return true; 142 | } 143 | ) 144 | ) 145 | ->when( 146 | $foobarResult = iterator_to_array($foobar), 147 | $filterResult = iterator_to_array($filter) 148 | ) 149 | ->then 150 | ->array($foobarResult) 151 | ->isEqualTo($filterResult); 152 | } 153 | 154 | public function case_recursive(): void 155 | { 156 | $this 157 | ->given( 158 | $foobar = $this->getDummyRecursiveIterator(), 159 | $filter = new LUT\Recursive\CallbackFilter( 160 | $foobar, 161 | function ($value) { 162 | return false === in_array($value, ['a', 'e', 'i', 'o', 'u']); 163 | } 164 | ), 165 | $iterator = new LUT\Recursive\Iterator($filter) 166 | ) 167 | ->when($result = iterator_to_array($iterator, false)) 168 | ->then 169 | ->array($result) 170 | ->isEqualTo([ 171 | 0 => 'f', 172 | 1 => 'b', 173 | 2 => 'r' 174 | ]); 175 | } 176 | 177 | public function case_recursive_remove_all(): void 178 | { 179 | $this 180 | ->given( 181 | $foobar = $this->getDummyRecursiveIterator(), 182 | $filter = new LUT\Recursive\CallbackFilter( 183 | $foobar, 184 | function () { 185 | return false; 186 | } 187 | ), 188 | $iterator = new LUT\Recursive\Iterator($filter) 189 | ) 190 | ->when($result = iterator_to_array($iterator)) 191 | ->then 192 | ->array($result) 193 | ->isEmpty(); 194 | } 195 | 196 | public function case_recursive_remove_none(): void 197 | { 198 | $this 199 | ->given( 200 | $foobar = $this->getDummyRecursiveIterator(), 201 | $filter = new LUT\Recursive\CallbackFilter( 202 | $foobar, 203 | function () { 204 | return true; 205 | } 206 | ), 207 | $foobarIterator = new LUT\Recursive\Iterator($foobar), 208 | $filterIterator = new LUT\Recursive\Iterator($filter) 209 | ) 210 | ->when( 211 | $foobarResult = iterator_to_array($foobarIterator), 212 | $filterResult = iterator_to_array($filterIterator) 213 | ) 214 | ->then 215 | ->array($foobarResult) 216 | ->isEqualTo($filterResult); 217 | } 218 | 219 | protected function getDummyIterator() 220 | { 221 | return new LUT\Map(['f', 'o', 'o', 'b', 'a', 'r']); 222 | } 223 | 224 | protected function getDummyRecursiveIterator() 225 | { 226 | return new LUT\Recursive\Map([['f', 'o', 'o'], ['b', 'a', 'r']]); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /Source/RegularExpression.php: -------------------------------------------------------------------------------- 1 | _regex = $regex; 139 | $this->setMode($mode); 140 | $this->setFlags($flags); 141 | $this->setPregFlags($pregFlags); 142 | $this->replacement = null; 143 | 144 | return; 145 | } 146 | 147 | /** 148 | * Get accept status. 149 | */ 150 | public function accept(): bool 151 | { 152 | if (is_array(parent::current())) { 153 | return false; 154 | } 155 | 156 | $this->_key = parent::key(); 157 | $this->_current = parent::current(); 158 | 159 | $matches = []; 160 | $useKey = $this->_flags & self::USE_KEY; 161 | $subject = $useKey ? $this->_key : $this->_current; 162 | $out = false; 163 | 164 | switch ($this->_mode) { 165 | 166 | case self::MATCH: 167 | $out = 0 !== preg_match( 168 | $this->_regex, 169 | $subject, 170 | $matches, 171 | $this->_pregFlags 172 | ); 173 | 174 | break; 175 | 176 | case self::GET_MATCH: 177 | $this->_current = []; 178 | $out = 0 !== preg_match( 179 | $this->_regex, 180 | $subject, 181 | $this->_current, 182 | $this->_pregFlags 183 | ); 184 | 185 | break; 186 | 187 | case self::ALL_MATCHES: 188 | $this->_current = []; 189 | $out = 0 < preg_match_all( 190 | $this->_regex, 191 | $subject, 192 | $this->_current, 193 | $this->_pregFlags 194 | ); 195 | 196 | break; 197 | 198 | case self::SPLIT: 199 | $this->_current = preg_split( 200 | $this->_regex, 201 | $subject, 202 | null, 203 | $this->_pregFlags 204 | ); 205 | 206 | $out = 207 | is_array($this->_current) && 208 | 1 < count($this->_current); 209 | 210 | break; 211 | 212 | case self::REPLACE: 213 | $numberOfReplacement = 0; 214 | $result = preg_replace( 215 | $this->_regex, 216 | $this->replacement, 217 | $subject, 218 | -1, 219 | $numberOfReplacement 220 | ); 221 | 222 | if (null === $result || 0 === $numberOfReplacement) { 223 | $out = false; 224 | 225 | break; 226 | } 227 | 228 | if (0 !== $useKey) { 229 | $this->_key = $result; 230 | $out = true; 231 | 232 | break; 233 | } 234 | 235 | $this->_current = $result; 236 | $out = true; 237 | 238 | break; 239 | 240 | default: 241 | $out = false; 242 | 243 | break; 244 | } 245 | 246 | if (0 !== ($this->_flags & self::INVERT_MATCH)) { 247 | return false === $out; 248 | } 249 | 250 | return $out; 251 | } 252 | 253 | /** 254 | * Get current key. 255 | */ 256 | public function key(): int 257 | { 258 | return $this->_key; 259 | } 260 | 261 | /** 262 | * Get current value. 263 | */ 264 | public function current(): string 265 | { 266 | return $this->_current; 267 | } 268 | 269 | /** 270 | * Set mode. 271 | */ 272 | public function setMode(int $mode): void 273 | { 274 | if ($mode < self::MATCH || $mode > self::REPLACE) { 275 | throw new \InvalidArgumentException( 276 | 'Illegal mode ' . $mode . '.' 277 | ); 278 | } 279 | 280 | $this->_mode = $mode; 281 | } 282 | 283 | /** 284 | * Set flags. 285 | */ 286 | public function setFlags(int $flags): void 287 | { 288 | $this->_flags = $flags; 289 | } 290 | 291 | /** 292 | * Set preg flags. 293 | */ 294 | public function setPregFlags(int $pregFlags): void 295 | { 296 | $this->_pregFlags = $pregFlags; 297 | } 298 | 299 | /** 300 | * Get regular expression. 301 | */ 302 | public function getRegex(): ?string 303 | { 304 | return $this->_regex; 305 | } 306 | 307 | /** 308 | * Get mode. 309 | */ 310 | public function getMode(): int 311 | { 312 | return $this->_mode; 313 | } 314 | 315 | /** 316 | * Get flags. 317 | */ 318 | public function getFlags(): int 319 | { 320 | return $this->_flags; 321 | } 322 | 323 | /** 324 | * Get preg flags. 325 | */ 326 | public function getPregFlags(): int 327 | { 328 | return $this->_pregFlags; 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /Test/Unit/Directory.php: -------------------------------------------------------------------------------- 1 | given( 58 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 59 | $this->resolve('hoa://Test/Vfs/Root/A?type=file'), 60 | $this->resolve('hoa://Test/Vfs/Root/Aa?type=file'), 61 | $this->resolve('hoa://Test/Vfs/Root/Aaa?type=file'), 62 | $iterator = new LUT\Directory($root), 63 | $result = [] 64 | ) 65 | ->when(function () use ($iterator, &$result): void { 66 | foreach ($iterator as $key => $file) { 67 | $result[$key] = $file->getFilename(); 68 | 69 | $this 70 | ->object($file) 71 | ->isInstanceOf(LUT\Directory::class); 72 | } 73 | }) 74 | ->then 75 | ->array($result) 76 | ->isEqualTo([ 77 | 0 => 'A', 78 | 1 => 'Aa', 79 | 2 => 'Aaa' 80 | ]); 81 | } 82 | 83 | public function case_seek_and_dots(): void 84 | { 85 | $this 86 | ->given( 87 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 88 | $this->resolve('hoa://Test/Vfs/Root/.?type=directory'), 89 | $this->resolve('hoa://Test/Vfs/Root/..?type=directory'), 90 | $this->resolve('hoa://Test/Vfs/Root/Skip?type=file'), 91 | $this->resolve('hoa://Test/Vfs/Root/Gotcha?type=file'), 92 | $iterator = new LUT\Directory($root) 93 | ) 94 | ->when($result = $iterator->current()) 95 | ->then 96 | ->boolean($result->isDot()) 97 | ->isTrue() 98 | 99 | ->when( 100 | $iterator->next(), 101 | $result = $iterator->current() 102 | ) 103 | ->then 104 | ->boolean($result->isDot()) 105 | ->isTrue() 106 | 107 | ->when( 108 | $iterator->seek(3), 109 | $result = $iterator->current() 110 | ) 111 | ->then 112 | ->string($result->getFilename()) 113 | ->isEqualTo('Gotcha') 114 | 115 | ->when( 116 | $iterator->seek(2), 117 | $result = $iterator->current() 118 | ) 119 | ->then 120 | ->string($result->getFilename()) 121 | ->isEqualTo('Skip'); 122 | } 123 | 124 | public function case_recursive(): void 125 | { 126 | $this 127 | ->given( 128 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 129 | $this->resolve('hoa://Test/Vfs/Root/A?type=file'), 130 | $this->resolve('hoa://Test/Vfs/Root/Aa?type=file'), 131 | $this->resolve('hoa://Test/Vfs/Root/Aaa?type=file'), 132 | $this->resolve('hoa://Test/Vfs/Root/Foo?type=directory'), 133 | $this->resolve('hoa://Test/Vfs/Root/Foo/Bar?type=directory'), 134 | $this->resolve('hoa://Test/Vfs/Root/Foo/Bar/B?type=file'), 135 | $this->resolve('hoa://Test/Vfs/Root/Foo/Bar/Bb?type=file'), 136 | $this->resolve('hoa://Test/Vfs/Root/Foo/Bar/Bbb?type=file'), 137 | $this->resolve('hoa://Test/Vfs/Root/Foo/C?type=file'), 138 | $this->resolve('hoa://Test/Vfs/Root/Foo/Cc?type=file'), 139 | $this->resolve('hoa://Test/Vfs/Root/Foo/Ccc?type=file'), 140 | $directory = new LUT\Recursive\Directory($root), 141 | $iterator = new LUT\Recursive\Iterator($directory), 142 | $result = [] 143 | ) 144 | ->when(function () use ($iterator, &$result): void { 145 | foreach ($iterator as $file) { 146 | $result[] = $file->getFilename(); 147 | } 148 | }) 149 | ->then 150 | ->array($result) 151 | ->isEqualTo([ 152 | 'A', 153 | 'Aa', 154 | 'Aaa', 155 | 'B', 156 | 'Bb', 157 | 'Bbb', 158 | 'C', 159 | 'Cc', 160 | 'Ccc' 161 | ]); 162 | } 163 | 164 | public function case_splFileClassInfo(): void 165 | { 166 | $this 167 | ->given( 168 | $splFileInfo = 'Hoa\Iterator\SplFileInfo', 169 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 170 | $this->resolve('hoa://Test/Vfs/Root/a?type=file'), 171 | $this->resolve('hoa://Test/Vfs/Root/b?type=file'), 172 | $this->resolve('hoa://Test/Vfs/Root/c?type=file'), 173 | $this->resolve('hoa://Test/Vfs/Root/d?type=file'), 174 | $this->resolve('hoa://Test/Vfs/Root/e?type=file'), 175 | $this->resolve('hoa://Test/Vfs/Root/f?type=file'), 176 | $iterator = new LUT\Directory( 177 | $root, 178 | $splFileInfo 179 | ), 180 | $result = [] 181 | ) 182 | ->when(function () use ($iterator, $splFileInfo, &$result): void { 183 | foreach ($iterator as $file) { 184 | $this 185 | ->object($file) 186 | ->isInstanceOf($splFileInfo); 187 | 188 | $result[] = $file->getFilename(); 189 | } 190 | }) 191 | ->then 192 | ->array($result) 193 | ->isEqualTo([ 194 | 'a', 195 | 'b', 196 | 'c', 197 | 'd', 198 | 'e', 199 | 'f' 200 | ]); 201 | } 202 | 203 | public function case_recursive_splFileClassInfo(): void 204 | { 205 | $this 206 | ->given( 207 | $splFileInfo = 'Hoa\Iterator\SplFileInfo', 208 | $root = $this->resolve('hoa://Test/Vfs/Root?type=directory'), 209 | $this->resolve('hoa://Test/Vfs/Root/A?type=directory'), 210 | $this->resolve('hoa://Test/Vfs/Root/A/a?type=file'), 211 | $this->resolve('hoa://Test/Vfs/Root/A/b?type=file'), 212 | $this->resolve('hoa://Test/Vfs/Root/A/c?type=file'), 213 | $this->resolve('hoa://Test/Vfs/Root/B?type=directory'), 214 | $this->resolve('hoa://Test/Vfs/Root/B/d?type=file'), 215 | $this->resolve('hoa://Test/Vfs/Root/B/e?type=file'), 216 | $this->resolve('hoa://Test/Vfs/Root/B/c?type=directory'), 217 | $this->resolve('hoa://Test/Vfs/Root/B/c/f?type=file'), 218 | $directory = new LUT\Recursive\Directory( 219 | $root, 220 | LUT\FileSystem::CURRENT_AS_FILEINFO, 221 | $splFileInfo 222 | ), 223 | $iterator = new LUT\Recursive\Iterator($directory), 224 | $result = [] 225 | ) 226 | ->when(function () use ($iterator, $splFileInfo, &$result): void { 227 | foreach ($iterator as $file) { 228 | $this 229 | ->object($file) 230 | ->isInstanceOf($splFileInfo); 231 | 232 | $result[] = $file->getFilename(); 233 | } 234 | }) 235 | ->then 236 | ->array($result) 237 | ->isEqualTo([ 238 | 'a', 239 | 'b', 240 | 'c', 241 | 'd', 242 | 'e', 243 | 'f' 244 | ]); 245 | } 246 | 247 | private function resolve(string $path) 248 | { 249 | return Protocol\Protocol::getInstance()->resolve($path); 250 | } 251 | } 252 | --------------------------------------------------------------------------------