autoload.classPathCache.inc.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2008 by Konstantin V. Arkhipov                          *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00012     define('ONPHP_CLASS_CACHE_CHECKSUM', '__occc');
00013     
00014     /* void */ function __autoload($classname)
00015     {
00016         // numeric indexes for directories, literal indexes for classes
00017         static $cache       = null;
00018         static $path        = null;
00019         static $checksum    = null;
00020         
00021         if (strpos($classname, "\0") !== false) {
00022             // we can not avoid fatal error in this case
00023             return /* void */;
00024         }
00025         
00026         $currentPath = get_include_path();
00027         
00028         if ($currentPath != $path) {
00029             $checksum = crc32($currentPath.ONPHP_VERSION);
00030             $path = $currentPath;
00031         }
00032         
00033         $cacheFile = ONPHP_CLASS_CACHE.$checksum.'.occ';
00034         
00035         if ($cache && ($cache[ONPHP_CLASS_CACHE_CHECKSUM] <> $checksum))
00036             $cache = null;
00037         
00038         if (!$cache) {
00039             try {
00040                 $cache = unserialize(@file_get_contents($cacheFile, false));
00041             } catch (BaseException $e) {
00042                 /* ignore */
00043             }
00044             
00045             if (isset($cache[$classname])) {
00046                 try {
00047                     include $cache[$cache[$classname]].$classname.EXT_CLASS;
00048                     return /* void */;
00049                 } catch (ClassNotFoundException $e) {
00050                     throw $e;
00051                 } catch (BaseException $e) {
00052                     $cache = null;
00053                 }
00054             }
00055         }
00056         
00057         if (!$cache) {
00058             $cache = array();
00059             $dirCount = 0;
00060             
00061             foreach (explode(PATH_SEPARATOR, get_include_path()) as $directory) {
00062                 $cache[$dirCount] = realpath($directory).DIRECTORY_SEPARATOR;
00063                 
00064                 if ($paths = glob($cache[$dirCount].'*'.EXT_CLASS, GLOB_NOSORT)) {
00065                     foreach ($paths as $class) {
00066                         $class = basename($class, EXT_CLASS);
00067                         
00068                         // emulating include_path searching behaviour
00069                         if (!isset($cache[$class]))
00070                             $cache[$class] = $dirCount;
00071                     }
00072                 }
00073                 
00074                 ++$dirCount;
00075             }
00076             
00077             $cache[ONPHP_CLASS_CACHE_CHECKSUM] = $checksum;
00078             
00079             if (
00080                 is_writable(dirname($cacheFile))
00081                 && (
00082                     !file_exists($cacheFile)
00083                     || is_writable($cacheFile)
00084                 )
00085             )
00086                 file_put_contents($cacheFile, serialize($cache));
00087         }
00088         
00089         if (isset($cache[$classname])) {
00090             $fileName = $cache[$cache[$classname]].$classname.EXT_CLASS;
00091             
00092             try {
00093                 include $fileName;
00094             } catch (BaseException $e) {
00095                 if (is_readable($fileName))
00096                     // class compiling failed
00097                     throw $e;
00098                 else {
00099                     // cache is not actual
00100                     $cache[ONPHP_CLASS_CACHE_CHECKSUM] = null;
00101                     __autoload($classname);
00102                 }
00103             }
00104         } else {
00105             // ok, last chance to find class in non-cached include_path
00106             try {
00107                 include $classname.EXT_CLASS;
00108                 $cache[ONPHP_CLASS_CACHE_CHECKSUM] = null;
00109                 return /* void */;
00110             } catch (BaseException $e) {
00111                 __autoload_failed($classname, $e->getMessage());
00112             }
00113         }
00114     }
00115 ?>