Details
-
Type:
Improvement
-
Status:
Open
-
Priority:
Minor
-
Resolution: Unresolved
-
Affects Version/s: None
-
Fix Version/s: Next Major Release
-
Component/s: Zend_Cache, Zend_Loader
-
Labels:None
Description
Both Zend_Cache::_isReadable() and Zend_Loader::isReadable() code/performance could be improved using the new PHP 5.3.2 stream_resolve_include_path() function.
Zend_Cache::_isReadable() can be particularly slow due to error suppression so
private static function _isReadable($filename) { if (!$fh = @fopen($filename, 'r', true)) { return false; } @fclose($fh); return true; }
could be rewritten to:
private static function _isReadable($filename) { return is_string(stream_resolve_include_path($filename)); }
or, for backward compatibility:
private static function _isReadable($filename) { if (function_exists('stream_resolve_include_path')) { return is_string(stream_resolve_include_path($filename)); } if (!$fh = @fopen($filename, 'r', true)) { return false; } @fclose($fh); return true; }
Something similar applies to Zend_Loader
public static function isReadable($filename) { // NEW CODE if (function_exists('stream_resolve_include_path')) { return is_string(stream_resolve_include_path($filename)); } // OLD CODE [....] foreach (self::explodeIncludePath() as $path) { if ($path == '.') { if (is_readable($filename)) { return true; } continue; } $file = $path . '/' . $filename; if (is_readable($file)) { return true; } } return false; }
so that the foreach loop can be avoided with PHP 5.3.2.
Zend_Cache method comes from Zend_Loader (see #ZF-2891 for details) so it would make sense to extrapolate the code in a separate class, taking into consideration to use Zend_Loader code instead of the error suppression, something like this (comments removed for brevity):
class Zend_File
{
public static function isReadable($filename)
{
if (function_exists('stream_resolve_include_path')) {
return is_string(stream_resolve_include_path($filename));
}
if (is_readable($filename)) {
return true;
}
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'
&& preg_match('/^[a-z]:/i', $filename)
) {
return false;
}
foreach (Zend_Application::getIncludePathArray() as $path) {
if ($path == '.') {
if (is_readable($filename)) {
return true;
}
continue;
}
$file = $path . '/' . $filename;
if (is_readable($file)) {
return true;
}
}
return false;
}
}
adding this to Zend_Application:
/**
* explodeIncludePath() method renamed to getIncludePathArray()
* Todo: Cache the result ?
*/
public static function getIncludePathArray($path = null)
{
if (null === $path) {
$path = get_include_path();
}
if (PATH_SEPARATOR == ':') {
$paths = preg_split('#:(?!//)#', $path);
} else {
$paths = explode(PATH_SEPARATOR, $path);
}
return $paths;
}
To avoid confusion with PHP is_readable() function, why not renaming isReadable() to isAccessible() deprecating the old methods with a trigger_error('...', E_USER_NOTICE) ?
Unfortunately, this cannot be a solution until 2.0 at the earliest; the 1.X branch has a minimum required version of PHP 5.2.4, meaning we cannot use PHP 5.3-specific solutions.
I'm marking the improvement as for "next major version".