Apache Zeta Components Manual :: File Source for file.php
Source for file file.php
Documentation is available at file.php
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @version //autogentag//
* Provides a selection of static independent methods to provide functionality
* for file and file system handling.
* This example shows how to use the findRecursive method:
* // lists all the files under /etc (including subdirectories) that end in
* $confFiles = ezcBaseFile::findRecursive( "/etc", array( '@\.conf$@' ) );
* // lists all autoload files in the components source tree and excludes the
* // ones in the autoload subdirectory. Statistics are returned in the $stats
* // variable which is passed by reference.
* $files = ezcBaseFile::findRecursive(
* "/dat/dev/ezcomponents",
* array( '@src/.*_autoload.php$@' ),
* array( '@/autoload/@' ),
* // lists all binaries in /bin except the ones starting with a "g"
* $data = ezcBaseFile::findRecursive( "/bin", array(), array( '@^/bin/g@' ) );
* @version //autogentag//
* This is the callback used by findRecursive to collect data.
* This callback method works together with walkRecursive() and is called
* for every file/and or directory. The $context is a callback specific
* container in which data can be stored and shared between the different
* calls to the callback function. The walkRecursive() function also passes
* in the full absolute directory in $sourceDir, the filename in $fileName
* and file information (such as size, modes, types) as an array as
* returned by PHP's stat() in the $fileInfo parameter.
* @param ezcBaseFileFindContext $context
* @param string $sourceDir
* @param string $fileName
* @param array(stat) $fileInfo
static protected function findRecursiveCallback( ezcBaseFileFindContext $context, $sourceDir, $fileName, $fileInfo )
// ignore if we have a directory
if ( $fileInfo['mode'] & 0x4000 )
$context->elements[] =
$sourceDir .
DIRECTORY_SEPARATOR .
$fileName;
$context->size +=
$fileInfo['size'];
* Walks files and directories recursively on a file system
* This method walks over a directory and calls a callback from every file
* and directory it finds. You can use $includeFilters to include only
* specific files, and $excludeFilters to exclude certain files from being
* returned. The function will always go into subdirectories even if the
* entry would not have passed the filters.
* The callback is passed in the $callback parameter, and the
* $callbackContext will be send to the callback function/method as
* parameter so that you can store data in there that persists with all the
* calls and recursive calls to this method. It's up to the callback method
* to do something useful with this. The callback function's parameters are
* <li>ezcBaseFileFindContext $context</li>
* <li>string $sourceDir</li>
* <li>string $fileName</li>
* <li>array(stat) $fileInfo</li>
* See {@see findRecursiveCallback()} for an example of a callback function.
* Filters are regular expressions and are therefore required to have
* starting and ending delimiters. The Perl Compatible syntax is used as
* regular expression language.
* @param string $sourceDir
* @param array(string) $includeFilters
* @param array(string) $excludeFilters
* @param callback $callback
* @param mixed $callbackContext
* @throws ezcBaseFileNotFoundException if the $sourceDir directory is not
* a directory or does not exist.
* @throws ezcBaseFilePermissionException if the $sourceDir directory could
* not be opened for reading.
static public function walkRecursive( $sourceDir, array $includeFilters =
array(), array $excludeFilters =
array(), $callback, &$callbackContext )
while ( ( $entry =
$d->read() ) !==
false )
if ( $entry ==
'.' ||
$entry ==
'..' )
$fileInfo =
@stat( $sourceDir .
DIRECTORY_SEPARATOR .
$entry );
$fileInfo =
array( 'size' =>
0, 'mode' =>
0 );
if ( $fileInfo['mode'] & 0x4000 )
// We need to ignore the Permission exceptions here as it can
// be normal that a directory can not be accessed. We only need
// the exception if the top directory could not be read.
$subList =
self::walkRecursive( $sourceDir .
DIRECTORY_SEPARATOR .
$entry, $includeFilters, $excludeFilters, $callback, $callbackContext );
// By default a file is included in the return list
// Iterate over the $includeFilters and prohibit the file from
// being returned when atleast one of them does not match
foreach ( $includeFilters as $filter )
if ( !preg_match( $filter, $sourceDir .
DIRECTORY_SEPARATOR .
$entry ) )
// Iterate over the $excludeFilters and prohibit the file from
// being returns when atleast one of them matches
foreach ( $excludeFilters as $filter )
if ( preg_match( $filter, $sourceDir .
DIRECTORY_SEPARATOR .
$entry ) )
// If everything's allright, call the callback and add the
// entry to the elements array
call_user_func( $callback, $callbackContext, $sourceDir, $entry, $fileInfo );
$elements[] =
$sourceDir .
DIRECTORY_SEPARATOR .
$entry;
* Finds files recursively on a file system
* With this method you can scan the file system for files. You can use
* $includeFilters to include only specific files, and $excludeFilters to
* exclude certain files from being returned. The function will always go
* into subdirectories even if the entry would not have passed the filters.
* It uses the {@see walkRecursive()} method to do the actually recursion.
* Filters are regular expressions and are therefore required to have
* starting and ending delimiters. The Perl Compatible syntax is used as
* regular expression language.
* If you pass an empty array to the $statistics argument, the function
* will in details about the number of files found into the 'count' array
* element, and the total filesize in the 'size' array element. Because this
* argument is passed by reference, you *have* to pass a variable and you
* can not pass a constant value such as "array()".
* @param string $sourceDir
* @param array(string) $includeFilters
* @param array(string) $excludeFilters
* @param array() $statistics
* @throws ezcBaseFileNotFoundException if the $sourceDir directory is not
* a directory or does not exist.
* @throws ezcBaseFilePermissionException if the $sourceDir directory could
* not be opened for reading.
static public function findRecursive( $sourceDir, array $includeFilters =
array(), array $excludeFilters =
array(), &$statistics =
null )
$statistics['count'] =
0;
// create the context, and then start walking over the array
self::walkRecursive( $sourceDir, $includeFilters, $excludeFilters, array( 'ezcBaseFile', 'findRecursiveCallback' ), $context );
// collect the statistics
$statistics['size'] =
$context->size;
$statistics['count'] =
$context->count;
// return the found and pattern-matched files
sort( $context->elements );
return $context->elements;
* Removes files and directories recursively from a file system
* This method recursively removes the $directory and all its contents.
* You should be <b>extremely</b> careful with this method as it has the
* potential to erase everything that the current user has access to.
* @param string $directory
// check if we can remove the dir
$parentDir =
realpath( $directory .
DIRECTORY_SEPARATOR .
'..' );
while ( ( $entry =
$d->read() ) !==
false )
if ( $entry ==
'.' ||
$entry ==
'..' )
if ( is_dir( $sourceDir .
DIRECTORY_SEPARATOR .
$entry ) )
self::removeRecursive( $sourceDir .
DIRECTORY_SEPARATOR .
$entry );
if ( @unlink( $sourceDir .
DIRECTORY_SEPARATOR .
$entry ) ===
false )
* Recursively copy a file or directory.
* Recursively copy a file or directory in $source to the given
* destination. If a depth is given, the operation will stop, if the given
* recursion depth is reached. A depth of -1 means no limit, while a depth
* of 0 means, that only the current file or directory will be copied,
* You may optionally define modes used to create files and directories.
* @throws ezcBaseFileNotFoundException
* If the $sourceDir directory is not a directory or does not exist.
* @throws ezcBaseFilePermissionException
* If the $sourceDir directory could not be opened for reading, or the
* destination is not writeable.
* @param string $destination
static public function copyRecursive( $source, $destination, $depth = -
1, $dirMode =
0775, $fileMode =
0664 )
// Check if source file exists at all.
// Destination file should NOT exist
// Skip non readable files in source directory
// To ignore umask, umask() should not be changed with
// multithreaded servers...
chmod( $destination, $dirMode );
copy( $source, $destination );
chmod( $destination, $fileMode );
// Do not recurse (any more)
while ( ( $file =
readdir( $dh ) ) !==
false )
if ( ( $file ===
'.' ) ||
$destination .
'/' .
$file,
$depth -
1, $dirMode, $fileMode
* Calculates the relative path of the file/directory '$path' to a given
* $path and $base should be fully absolute paths. This function returns the
* answer of "How do I go from $base to $path". If the $path and $base are
* the same path, the function returns '.'. This method does not touch the
// Sanitize the paths to use the correct directory separator for the platform
$path =
strtr( $path, '\\/', DIRECTORY_SEPARATOR .
DIRECTORY_SEPARATOR );
$base =
strtr( $base, '\\/', DIRECTORY_SEPARATOR .
DIRECTORY_SEPARATOR );
$base =
explode( DIRECTORY_SEPARATOR, $base );
$path =
explode( DIRECTORY_SEPARATOR, $path );
// If the paths are the same we return
while ( $pathPart ==
$basePart )
// prevent a trailing DIRECTORY_SEPARATOR in case there is only a ..
if ( count( $path ) ==
0 )
$result =
substr( $result, 0, -
strlen( DIRECTORY_SEPARATOR ) );
$result .=
join( DIRECTORY_SEPARATOR, $path );
* Returns whether the passed $path is an absolute path, giving the current $os.
* With the $os parameter you can tell this function to use the semantics
* for a different operating system to determine whether a path is
* absolute. The $os argument defaults to the OS that the script is running
// Stream wrapper like phar can also be considered absolute paths
// Sanitize the paths to use the correct directory separator for the platform
$path =
strtr( $path, '\\/', '\\\\' );
// Absolute paths with drive letter: X:\
// Absolute paths with network paths: \\server\share\
if ( preg_match( '@^\\\\\\\\[A-Z]+\\\\[^\\\\]@i', $path ) )
// Sanitize the paths to use the correct directory separator for the platform
$path =
strtr( $path, '\\/', '//' );