Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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: sfSimpleAutoload.class.php 23205 2009-10-20 13:20:17Z Kris.Wallsmith $
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
}