PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.1-beta
16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / vendor / wp-php-toolkit / filesystem / functions.php
jetpack / vendor / wp-php-toolkit / filesystem Last commit date
ByteStream 6 days ago Layer 6 days ago Mixin 6 days ago Path 6 days ago Visitor 6 days ago LICENSE.md 6 days ago README.md 6 days ago class-filesystemexception.php 6 days ago class-inmemoryfilesystem.php 6 days ago class-localfilesystem.php 6 days ago class-sqlitefilesystem.php 6 days ago class-uploadedfilesystem.php 6 days ago composer.json 6 days ago functions.php 6 days ago interface-filesystem.php 6 days ago
functions.php
290 lines
1 <?php
2
3 namespace WordPress\Filesystem;
4
5 use ValueError;
6
7 function ls_recursive( Filesystem $filesystem, $path = '/' ) {
8 $tree = array();
9 foreach ( $filesystem->ls( $path ) as $item ) {
10 if ( $filesystem->is_dir( $item ) ) {
11 $tree[] = array(
12 'name' => $item,
13 'type' => 'dir',
14 'children' => ls_recursive( $filesystem, $item ),
15 );
16 } else {
17 $tree[] = array(
18 'name' => $item,
19 'type' => 'file',
20 );
21 }
22 }
23
24 return $tree;
25 }
26
27 /**
28 * Copies a file or directory between two Filesystem instances.
29 *
30 * @param array $args The arguments to pass to the copy function. {
31 * @type Filesystem $source_filesystem The source filesystem.
32 * @type Filesystem $destination_filesystem The destination filesystem.
33 * @type string $source_path The path to the source file or directory. It must use forward slashes as path separators.
34 * @type string $destination_path The path to the destination file or directory. It must use forward slashes as path separators.
35 * @type bool $recursive Whether to copy the file or directory recursively.
36 * }
37 */
38 function copy_between_filesystems( array $args ) {
39 $source = $args['source_filesystem'];
40 $source_path = $args['source_path'] ?? '/';
41 $destination = $args['target_filesystem'];
42 $destination_path = $args['target_path'] ?? '/';
43 $recursive = $args['recursive'] ?? true;
44
45 if ( $source->is_file( $source_path ) ) {
46 $destination_dir = wp_unix_dirname( $destination_path );
47 if ( ! $destination->is_dir( $destination_dir ) ) {
48 $destination->mkdir(
49 $destination_dir,
50 array(
51 'recursive' => true,
52 )
53 );
54 }
55
56 $to_stream = $destination->open_write_stream( $destination_path );
57 try {
58 $from_stream = $source->open_read_stream( $source_path );
59 try {
60 $chunks_written = 0;
61 while ( ! $from_stream->reached_end_of_data() ) {
62 $available = $from_stream->pull( 65536 );
63 $to_stream->append_bytes( $from_stream->consume( $available ), $to_stream );
64 ++$chunks_written;
65 }
66 if ( 0 === $chunks_written ) {
67 // Make sure the file receives at least one chunk.
68 // so we can be sure it gets created in case the.
69 // destination filesystem is lazy.
70 $to_stream->append_bytes( '' );
71 }
72 } finally {
73 $from_stream->close_reading();
74 }
75 } finally {
76 $to_stream->close_writing();
77 }
78 } elseif ( $source->is_dir( $source_path ) ) {
79 if ( ! $recursive ) {
80 throw new FilesystemException( 'Cannot copy a directory. Set the option `recursive` to true to copy directories recursively.' );
81 }
82 if ( ! $destination->is_dir( $destination_path ) ) {
83 $destination->mkdir(
84 $destination_path,
85 array(
86 'recursive' => true,
87 )
88 );
89 }
90 foreach ( $source->ls( $source_path ) as $item ) {
91 copy_between_filesystems(
92 array(
93 'source_filesystem' => $source,
94 'source_path' => wp_join_unix_paths( $source_path, $item ),
95 'target_filesystem' => $destination,
96 'target_path' => wp_join_unix_paths( $destination_path, $item ),
97 )
98 );
99 }
100 } elseif ( $source->exists( $source_path ) ) {
101 // For now ignore paths that are neither files nor directories.
102 // For example, in GitFilesystem that could be a submodule.
103 return; // No-op, intentionally ignore.
104 } else {
105 // When a path does not exist, throw a clear error.
106 throw new FilesystemException( 'Path does not exist in the source filesystem: ' . $source_path );
107 }
108 }
109
110 /**
111 * Pipes data from one stream to another.
112 *
113 * @param ByteReadStream $from_stream The stream to read from.
114 * @param ByteWriteStream $to_stream The stream to write to.
115 * @param int $chunk_size Optional. The size of chunks to read at a time. Default 65536.
116 *
117 * @return int The number of chunks written.
118 * @throws FilesystemException If there's an error during the transfer.
119 */
120 function pipe_stream( $from_stream, $to_stream, $chunk_size = 65536 ) {
121 $chunks_written = 0;
122 while ( ! $from_stream->reached_end_of_data() ) {
123 $available = $from_stream->pull( $chunk_size );
124 $to_stream->append_bytes( $from_stream->consume( $available ) );
125 ++$chunks_written;
126 }
127
128 if ( 0 === $chunks_written ) {
129 // Make sure the file receives at least one chunk
130 // so we can be sure it gets created in case the
131 // destination filesystem is lazy.
132 $to_stream->append_bytes( '' );
133 $chunks_written = 1;
134 }
135
136 return $chunks_written;
137 }
138
139
140 function wp_unix_path_segments( $path ) {
141 $without_dots = wp_unix_path_resolve_dots( $path );
142 $without_slashes = trim( $without_dots, '/' );
143
144 return explode( '/', $without_slashes );
145 }
146
147 /**
148 * Joins multiple path segments together into a single path.
149 *
150 * Removes any double slashes between path segments.
151 */
152 function wp_join_unix_paths( ...$path_segments ) {
153 $input_starts_with_slash = null;
154
155 $paths = array();
156 foreach ( $path_segments as $path_segment ) {
157 if ( '' !== $path_segment ) {
158 $paths[] = $path_segment;
159 if ( null === $input_starts_with_slash ) {
160 $input_starts_with_slash = 0 === strncmp( $path_segment, '/', strlen( '/' ) );
161 }
162 }
163 }
164 $path = implode( '/', $paths );
165
166 $result = preg_replace( '#/+#', '/', $path );
167 if ( $input_starts_with_slash && 0 !== strncmp( $result, '/', strlen( '/' ) ) ) {
168 $result = '/' . $result;
169 }
170
171 return $result;
172 }
173
174 /**
175 * Cleans up a path segment.
176 *
177 * - Removes the /./ segments
178 * - Flattens the /../ segments
179 *
180 * Example:
181 *
182 * wp_unix_path_resolve_dots( 'foo/bar/../baz' ) => '/foo/baz'
183 *
184 * @param string $path The file path that needs cleaning up
185 * @return string The cleaned, absolute path
186 */
187 function wp_unix_path_resolve_dots( $path ) {
188 // Convert to absolute path.
189 if ( 0 !== strncmp( $path, '/', strlen( '/' ) ) ) {
190 $path = '/' . $path;
191 }
192
193 // Resolve . and ..
194 $parts = explode( '/', $path );
195 $normalized = array();
196 foreach ( $parts as $part ) {
197 if ( '.' === $part || '' === $part ) {
198 continue;
199 }
200 if ( '..' === $part ) {
201 array_pop( $normalized );
202 continue;
203 }
204 $normalized[] = $part;
205 }
206
207 $result = implode( '/', $normalized );
208 if ( '.' === $result ) {
209 $result = '';
210 }
211 return $result;
212 }
213
214
215 /**
216 * Like sys_get_temp_dir(), but returns a path using forward slashes
217 * as separators.
218 */
219 function wp_unix_sys_get_temp_dir() {
220 $path = sys_get_temp_dir();
221 if ( '\\' === DIRECTORY_SEPARATOR ) {
222 $path = str_replace( '\\', '/', $path );
223 }
224 return $path;
225 }
226
227 /**
228 * A clone of PHP's dirname() that assumes the path is a Unix path.
229 *
230 * Both functions agree on the following:
231 *
232 * dirname("/") === wp_unix_dirname("/") === "/"
233 * dirname("/foo/bar") === wp_unix_dirname("/foo/bar") === "/foo"
234 * dirname("/foo/bar/") === wp_unix_dirname("/foo/bar/") === "/foo/bar"
235 *
236 * However, they disagree on Windows paths:
237 *
238 * dirname("C:/") === "C:/" (when ran on windows)
239 * dirname("C:/") === "." (when ran on unix)
240 *
241 * wp_unix_dirname("C:/") === "." (regardless of the OS)
242 *
243 * This ensures we get reliable results on all host OSes.
244 *
245 * It might seem weird to use unix semantics on windows. However, keep in mind,
246 * that php-toolkit supports more filesystems than just a local disk and that
247 * C: is a valid filename on unix.
248 *
249 * @param string $path Path to inspect (assumed Unix).
250 * @param int $levels How many levels to climb (≥ 1).
251 * @return string
252 * @throws ValueError on $levels < 1 (keeps parity with PHP 8.x).
253 */
254 function wp_unix_dirname( string $path, int $levels = 1 ): string {
255 if ( $levels < 1 ) {
256 throw new ValueError( 'unix_dirname(): $levels must be >= 1' );
257 }
258
259 // treat empty string the same way PHP does.
260 if ( '' === $path ) {
261 return '';
262 }
263
264 // if the path is nothing but slashes, the result is always "/".
265 if ( strspn( $path, '/' ) === strlen( $path ) ) {
266 return 1 === $levels ? '/' : wp_unix_dirname( '/', $levels - 1 );
267 }
268
269 // strip trailing slashes (but never the single root slash).
270 $path = rtrim( $path, '/' );
271 if ( '' === $path ) { // happens when the original was just "/".
272 return 1 === $levels ? '/' : wp_unix_dirname( '/', $levels - 1 );
273 }
274
275 // locate the last slash.
276 $slash = strrpos( $path, '/' );
277 if ( false === $slash ) { // no slash → current dir.
278 $path = '.';
279 } else {
280 $path = substr( $path, 0, $slash ); // cut off the basename.
281 $path = rtrim( $path, '/' ); // collapse duplicate slashes.
282 if ( '' === $path ) {
283 $path = '/'; // “/foo” → “/”.
284 }
285 }
286
287 // recurse for additional levels.
288 return $levels > 1 ? wp_unix_dirname( $path, $levels - 1 ) : $path;
289 }
290