filebackend: use self:: instead of FileBackend:: for some constant uses
[lhc/web/wiklou.git] / includes / libs / filebackend / fileiteration / FSFileBackendList.php
1 <?php
2 /**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 * @ingroup FileBackend
20 */
21
22 /**
23 * Wrapper around RecursiveDirectoryIterator/DirectoryIterator that
24 * catches exception or does any custom behavoir that we may want.
25 * Do not use this class from places outside FSFileBackend.
26 *
27 * @ingroup FileBackend
28 */
29 abstract class FSFileBackendList implements Iterator {
30 /** @var Iterator */
31 protected $iter;
32
33 /** @var int */
34 protected $suffixStart;
35
36 /** @var int */
37 protected $pos = 0;
38
39 /** @var array */
40 protected $params = [];
41
42 /**
43 * @param string $dir File system directory
44 * @param array $params
45 */
46 public function __construct( $dir, array $params ) {
47 $path = realpath( $dir ); // normalize
48 if ( $path === false ) {
49 $path = $dir;
50 }
51 $this->suffixStart = strlen( $path ) + 1; // size of "path/to/dir/"
52 $this->params = $params;
53
54 try {
55 $this->iter = $this->initIterator( $path );
56 } catch ( UnexpectedValueException $e ) {
57 $this->iter = null; // bad permissions? deleted?
58 }
59 }
60
61 /**
62 * Return an appropriate iterator object to wrap
63 *
64 * @param string $dir File system directory
65 * @return Iterator
66 */
67 protected function initIterator( $dir ) {
68 if ( !empty( $this->params['topOnly'] ) ) { // non-recursive
69 # Get an iterator that will get direct sub-nodes
70 return new DirectoryIterator( $dir );
71 } else { // recursive
72 # Get an iterator that will return leaf nodes (non-directories)
73 # RecursiveDirectoryIterator extends FilesystemIterator.
74 # FilesystemIterator::SKIP_DOTS default is inconsistent in PHP 5.3.x.
75 $flags = FilesystemIterator::CURRENT_AS_SELF | FilesystemIterator::SKIP_DOTS;
76
77 return new RecursiveIteratorIterator(
78 new RecursiveDirectoryIterator( $dir, $flags ),
79 RecursiveIteratorIterator::CHILD_FIRST // include dirs
80 );
81 }
82 }
83
84 /**
85 * @see Iterator::key()
86 * @return int
87 */
88 public function key() {
89 return $this->pos;
90 }
91
92 /**
93 * @see Iterator::current()
94 * @return string|bool String or false
95 */
96 public function current() {
97 return $this->getRelPath( $this->iter->current()->getPathname() );
98 }
99
100 /**
101 * @see Iterator::next()
102 * @throws FileBackendError
103 */
104 public function next() {
105 try {
106 $this->iter->next();
107 $this->filterViaNext();
108 } catch ( UnexpectedValueException $e ) { // bad permissions? deleted?
109 throw new FileBackendError( "File iterator gave UnexpectedValueException." );
110 }
111 ++$this->pos;
112 }
113
114 /**
115 * @see Iterator::rewind()
116 * @throws FileBackendError
117 */
118 public function rewind() {
119 $this->pos = 0;
120 try {
121 $this->iter->rewind();
122 $this->filterViaNext();
123 } catch ( UnexpectedValueException $e ) { // bad permissions? deleted?
124 throw new FileBackendError( "File iterator gave UnexpectedValueException." );
125 }
126 }
127
128 /**
129 * @see Iterator::valid()
130 * @return bool
131 */
132 public function valid() {
133 return $this->iter && $this->iter->valid();
134 }
135
136 /**
137 * Filter out items by advancing to the next ones
138 */
139 protected function filterViaNext() {
140 }
141
142 /**
143 * Return only the relative path and normalize slashes to FileBackend-style.
144 * Uses the "real path" since the suffix is based upon that.
145 *
146 * @param string $dir
147 * @return string
148 */
149 protected function getRelPath( $dir ) {
150 $path = realpath( $dir );
151 if ( $path === false ) {
152 $path = $dir;
153 }
154
155 return strtr( substr( $path, $this->suffixStart ), '\\', '/' );
156 }
157 }