Development

/branches/1.4/lib/autoload/sfSimpleAutoload.class.php

You must first sign up to be able to contribute.

root/branches/1.4/lib/autoload/sfSimpleAutoload.class.php

Revision 23205, 7.1 kB (checked in by Kris.Wallsmith, 5 years ago)

[1.3] fixed project autoloading in unit tests

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1 <?php
2
3 /*
4  * This file is part of the symfony package.
5  * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10
11 /**
12  * sfSimpleAutoload class.
13  *
14  * This class is a singleton as PHP seems to be unable to register 2 autoloaders that are instances
15  * of the same class (why?).
16  *
17  * @package    symfony
18  * @subpackage autoload
19  * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
20  * @version    SVN: $Id$
21  */
22 class sfSimpleAutoload
23 {
24   static protected
25     $registered = false,
26     $instance   = null;
27
28   protected
29     $cacheFile    = null,
30     $cacheLoaded  = false,
31     $cacheChanged = false,
32     $dirs         = array(),
33     $files        = array(),
34     $classes      = array(),
35     $overriden    = array();
36
37   protected function __construct($cacheFile = null)
38   {
39     if (null !== $cacheFile)
40     {
41       $this->cacheFile = $cacheFile;
42     }
43
44     $this->loadCache();
45   }
46
47   /**
48    * Retrieves the singleton instance of this class.
49    *
50    * @param  string $cacheFile  The file path to save the cache
51    *
52    * @return sfSimpleAutoload   A sfSimpleAutoload implementation instance.
53    */
54   static public function getInstance($cacheFile = null)
55   {
56     if (!isset(self::$instance))
57     {
58       self::$instance = new sfSimpleAutoload($cacheFile);
59     }
60
61     return self::$instance;
62   }
63
64   /**
65    * Register sfSimpleAutoload in spl autoloader.
66    *
67    * @return void
68    */
69   static public function register()
70   {
71     if (self::$registered)
72     {
73       return;
74     }
75
76     ini_set('unserialize_callback_func', 'spl_autoload_call');
77     if (false === spl_autoload_register(array(self::getInstance(), 'autoload')))
78     {
79       throw new sfException(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance())));
80     }
81
82     if (self::getInstance()->cacheFile)
83     {
84       register_shutdown_function(array(self::getInstance(), 'saveCache'));
85     }
86
87     self::$registered = true;
88   }
89
90   /**
91    * Unregister sfSimpleAutoload from spl autoloader.
92    *
93    * @return void
94    */
95   static public function unregister()
96   {
97     spl_autoload_unregister(array(self::getInstance(), 'autoload'));
98     self::$registered = false;
99   }
100
101   /**
102    * Handles autoloading of classes.
103    *
104    * @param  string $class A class name.
105    *
106    * @return boolean Returns true if the class has been loaded
107    */
108   public function autoload($class)
109   {
110     $class = strtolower($class);
111
112     // class already exists
113     if (class_exists($class, false) || interface_exists($class, false))
114     {
115       return true;
116     }
117
118     // we have a class path, let's include it
119     if (isset($this->classes[$class]))
120     {
121       try
122       {
123         require $this->classes[$class];
124       }
125       catch (sfException $e)
126       {
127         $e->printStackTrace();
128       }
129       catch (Exception $e)
130       {
131         sfException::createFromException($e)->printStackTrace();
132       }
133
134       return true;
135     }
136
137     return false;
138   }
139
140   /**
141    * Loads the cache.
142    */
143   public function loadCache()
144   {
145     if (!$this->cacheFile || !is_readable($this->cacheFile))
146     {
147       return;
148     }
149
150     list($this->classes, $this->dirs, $this->files) = unserialize(file_get_contents($this->cacheFile));
151
152     $this->cacheLoaded = true;
153     $this->cacheChanged = false;
154   }
155
156   /**
157    * Saves the cache.
158    */
159   public function saveCache()
160   {
161     if ($this->cacheChanged)
162     {
163       if (is_writable(dirname($this->cacheFile)))
164       {
165         file_put_contents($this->cacheFile, serialize(array($this->classes, $this->dirs, $this->files)));
166       }
167
168       $this->cacheChanged = false;
169     }
170   }
171
172   /**
173    * Reloads cache.
174    */
175   public function reload()
176   {
177     $this->classes = array();
178     $this->cacheLoaded = false;
179
180     foreach ($this->dirs as $dir)
181     {
182       $this->addDirectory($dir);
183     }
184
185     foreach ($this->files as $file)
186     {
187       $this->addFile($file);
188     }
189
190     foreach ($this->overriden as $class => $path)
191     {
192       $this->classes[$class] = $path;
193     }
194
195     $this->cacheLoaded = true;
196     $this->cacheChanged = true;
197   }
198
199   /**
200    * Removes the cache.
201    */
202   public function removeCache()
203   {
204     @unlink($this->cacheFile);
205   }
206
207   /**
208    * Adds a directory to the autoloading system if not yet present and give it the highest possible precedence.
209    *
210    * @param string $dir The directory to look for classes
211    * @param string $ext The extension to look for
212    */
213   public function addDirectory($dir, $ext = '.php')
214   {
215     $finder = sfFinder::type('file')->follow_link()->name('*'.$ext);
216
217     if ($dirs = glob($dir))
218     {
219       foreach ($dirs as $dir)
220       {
221         if (false !== $key = array_search($dir, $this->dirs))
222         {
223           unset($this->dirs[$key]);
224           $this->dirs[] = $dir;
225
226           if ($this->cacheLoaded)
227           {
228             continue;
229           }
230         }
231         else
232         {
233           $this->dirs[] = $dir;
234         }
235
236         $this->cacheChanged = true;
237         $this->addFiles($finder->in($dir), false);
238       }
239     }
240   }
241
242   /**
243    * Adds files to the autoloading system.
244    *
245    * @param array   $files    An array of files
246    * @param Boolean $register Whether to register those files as single entities (used when reloading)
247    */
248   public function addFiles(array $files, $register = true)
249   {
250     foreach ($files as $file)
251     {
252       $this->addFile($file, $register);
253     }
254   }
255
256   /**
257    * Adds a file to the autoloading system.
258    *
259    * @param string  $file     A file path
260    * @param Boolean $register Whether to register those files as single entities (used when reloading)
261    */
262   public function addFile($file, $register = true)
263   {
264     if (!is_file($file))
265     {
266       return;
267     }
268
269     if (in_array($file, $this->files))
270     {
271       if ($this->cacheLoaded)
272       {
273         return;
274       }
275     }
276     else
277     {
278       if ($register)
279       {
280         $this->files[] = $file;
281       }
282     }
283
284     if ($register)
285     {
286       $this->cacheChanged = true;
287     }
288
289     preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface)\s+(\w+)~mi', file_get_contents($file), $classes);
290     foreach ($classes[1] as $class)
291     {
292       $this->classes[strtolower($class)] = $file;
293     }
294   }
295
296   /**
297    * Sets the path for a particular class.
298    *
299    * @param string $class A PHP class name
300    * @param string $path  An absolute path
301    */
302   public function setClassPath($class, $path)
303   {
304     $class = strtolower($class);
305
306     $this->overriden[$class] = $path;
307
308     $this->classes[$class] = $path;
309   }
310
311   /**
312    * Returns the path where a particular class can be found.
313    *
314    * @param string $class A PHP class name
315    *
316    * @return string|null An absolute path
317    */
318   public function getClassPath($class)
319   {
320     $class = strtolower($class);
321
322     return isset($this->classes[$class]) ? $this->classes[$class] : null;
323   }
324
325   /**
326    * Loads configuration from the supplied files.
327    *
328    * @param array $files An array of autoload.yml files
329    *
330    * @see sfAutoloadConfigHandler
331    */
332   public function loadConfiguration(array $files)
333   {
334     $config = new sfAutoloadConfigHandler();
335     foreach ($config->evaluate($files) as $class => $file)
336     {
337       $this->setClassPath($class, $file);
338     }
339   }
340 }
341
Note: See TracBrowser for help on using the browser.