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) 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
 * sfProjectConfiguration represents a configuration for a symfony project.
13
 *
14
 * @package    symfony
15
 * @subpackage config
16
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17
 * @version    SVN: $Id: sfProjectConfiguration.class.php 27191 2010-01-26 13:38:49Z FabianLange $
18
 */
19
class sfProjectConfiguration
20
{
21
  protected
22
    $rootDir               = null,
23
    $symfonyLibDir         = null,
24
    $dispatcher            = null,
25
    $plugins               = array(),
26
    $pluginPaths           = array(),
27
    $overriddenPluginPaths = array(),
28
    $pluginConfigurations  = array(),
29
    $pluginsLoaded         = false;
30
 
31
  static protected
32
    $active = null;
33
 
34
  /**
35
   * Constructor.
36
   *
37
   * @param string              $rootDir    The project root directory
38
   * @param sfEventDispatcher   $dispatcher The event dispatcher
39
   */
40
  public function __construct($rootDir = null, sfEventDispatcher $dispatcher = null)
41
  {
42
    if (null === self::$active || $this instanceof sfApplicationConfiguration)
43
    {
44
      self::$active = $this;
45
    }
46
 
47
    $this->rootDir = null === $rootDir ? self::guessRootDir() : realpath($rootDir);
48
    $this->symfonyLibDir = realpath(dirname(__FILE__).'/..');
49
    $this->dispatcher = null === $dispatcher ? new sfEventDispatcher() : $dispatcher;
50
 
51
    ini_set('magic_quotes_runtime', 'off');
52
 
53
    sfConfig::set('sf_symfony_lib_dir', $this->symfonyLibDir);
54
 
55
    $this->setRootDir($this->rootDir);
56
 
57
    // provide forms the dispatcher
58
    sfFormSymfony::setEventDispatcher($this->dispatcher);
59
 
60
    $this->setup();
61
 
62
    $this->loadPlugins();
63
    $this->setupPlugins();
64
  }
65
 
66
  /**
67
   * Setups the current configuration.
68
   *
69
   * Override this method if you want to customize your project configuration.
70
   */
71
  public function setup()
72
  {
73
  }
74
 
75
  /**
76
   * Loads the project's plugin configurations.
77
   */
78
  public function loadPlugins()
79
  {
80
    foreach ($this->getPluginPaths() as $path)
81
    {
82
      if (false === $plugin = array_search($path, $this->overriddenPluginPaths))
83
      {
84
        $plugin = basename($path);
85
      }
86
      $class = $plugin.'Configuration';
87
 
88
      if (is_readable($file = sprintf('%s/config/%s.class.php', $path, $class)))
89
      {
90
        require_once $file;
91
        $configuration = new $class($this, $path, $plugin);
92
      }
93
      else
94
      {
95
        $configuration = new sfPluginConfigurationGeneric($this, $path, $plugin);
96
      }
97
 
98
      $this->pluginConfigurations[$plugin] = $configuration;
99
    }
100
 
101
    $this->pluginsLoaded = true;
102
  }
103
 
104
  /**
105
   * Sets up plugin configurations.
106
   *
107
   * Override this method if you want to customize plugin configurations.
108
   */
109
  public function setupPlugins()
110
  {
111
  }
112
 
113
  /**
114
   * Sets the project root directory.
115
   *
116
   * @param string $rootDir The project root directory
117
   */
118
  public function setRootDir($rootDir)
119
  {
120
    $this->rootDir = $rootDir;
121
 
122
    sfConfig::add(array(
123
      'sf_root_dir' => $rootDir,
124
 
125
      // global directory structure
126
      'sf_apps_dir'    => $rootDir.DIRECTORY_SEPARATOR.'apps',
127
      'sf_lib_dir'     => $rootDir.DIRECTORY_SEPARATOR.'lib',
128
      'sf_log_dir'     => $rootDir.DIRECTORY_SEPARATOR.'log',
129
      'sf_data_dir'    => $rootDir.DIRECTORY_SEPARATOR.'data',
130
      'sf_config_dir'  => $rootDir.DIRECTORY_SEPARATOR.'config',
131
      'sf_test_dir'    => $rootDir.DIRECTORY_SEPARATOR.'test',
132
      'sf_plugins_dir' => $rootDir.DIRECTORY_SEPARATOR.'plugins',
133
    ));
134
 
135
    $this->setWebDir($rootDir.DIRECTORY_SEPARATOR.'web');
136
    $this->setCacheDir($rootDir.DIRECTORY_SEPARATOR.'cache');
137
  }
138
 
139
  /**
140
   * Returns the project root directory.
141
   *
142
   * @return string The project root directory
143
   */
144
  public function getRootDir()
145
  {
146
    return $this->rootDir;
147
  }
148
 
149
  /**
150
   * Sets the cache root directory.
151
   *
152
   * @param string $cacheDir The absolute path to the cache dir.
153
   */
154
  public function setCacheDir($cacheDir)
155
  {
156
    sfConfig::set('sf_cache_dir', $cacheDir);
157
  }
158
 
159
  /**
160
   * Sets the log directory.
161
   *
162
   * @param string $logDir The absolute path to the log dir.
163
   */
164
  public function setLogDir($logDir)
165
  {
166
    sfConfig::set('sf_log_dir', $logDir);
167
  }
168
 
169
  /**
170
   * Sets the web root directory.
171
   *
172
   * @param string $webDir The absolute path to the web dir.
173
   */
174
  public function setWebDir($webDir)
175
  {
176
    sfConfig::add(array(
177
      'sf_web_dir'    => $webDir,
178
      'sf_upload_dir' => $webDir.DIRECTORY_SEPARATOR.'uploads',
179
    ));
180
  }
181
 
182
  /**
183
   * Gets directories where model classes are stored. The order of returned paths is lowest precedence
184
   * to highest precedence.
185
   *
186
   * @return array An array of directories
187
   */
188
  public function getModelDirs()
189
  {
190
    return array_merge(
191
      $this->getPluginSubPaths('/lib/model'),     // plugins
192
      array(sfConfig::get('sf_lib_dir').'/model') // project
193
    );
194
  }
195
 
196
  /**
197
   * Gets directories where template files are stored for a generator class and a specific theme.
198
   *
199
   * @param string $class  The generator class name
200
   * @param string $theme  The theme name
201
   *
202
   * @return array An array of directories
203
   */
204
  public function getGeneratorTemplateDirs($class, $theme)
205
  {
206
    return array_merge(
207
      array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/template'), // project
208
      $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/template'),      // plugins
209
      array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/template'),    // project (default theme)
210
      $this->getPluginSubPaths('/data/generator/'.$class.'/default/template')          // plugins (default theme)
211
    );
212
  }
213
 
214
  /**
215
   * Gets directories where the skeleton is stored for a generator class and a specific theme.
216
   *
217
   * @param string $class   The generator class name
218
   * @param string $theme   The theme name
219
   *
220
   * @return array An array of directories
221
   */
222
  public function getGeneratorSkeletonDirs($class, $theme)
223
  {
224
    return array_merge(
225
      array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/skeleton'), // project
226
      $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/skeleton'),      // plugins
227
      array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/skeleton'),    // project (default theme)
228
      $this->getPluginSubPaths('/data/generator/'.$class.'/default/skeleton')          // plugins (default theme)
229
    );
230
  }
231
 
232
  /**
233
   * Gets the template to use for a generator class.
234
   *
235
   * @param string $class   The generator class name
236
   * @param string $theme   The theme name
237
   * @param string $path    The template path
238
   *
239
   * @return string A template path
240
   *
241
   * @throws sfException
242
   */
243
  public function getGeneratorTemplate($class, $theme, $path)
244
  {
245
    $dirs = $this->getGeneratorTemplateDirs($class, $theme);
246
    foreach ($dirs as $dir)
247
    {
248
      if (is_readable($dir.'/'.$path))
249
      {
250
        return $dir.'/'.$path;
251
      }
252
    }
253
 
254
    throw new sfException(sprintf('Unable to load "%s" generator template in: %s.', $path, implode(', ', $dirs)));
255
  }
256
 
257
  /**
258
   * Gets the configuration file paths for a given relative configuration path.
259
   *
260
   * @param string $configPath The configuration path
261
   *
262
   * @return array An array of paths
263
   */
264
  public function getConfigPaths($configPath)
265
  {
266
    $globalConfigPath = basename(dirname($configPath)).'/'.basename($configPath);
267
 
268
    $files = array(
269
      $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony
270
    );
271
 
272
    foreach ($this->getPluginPaths() as $path)
273
    {
274
      if (is_file($file = $path.'/'.$globalConfigPath))
275
      {
276
        $files[] = $file;                                     // plugins
277
      }
278
    }
279
 
280
    $files = array_merge($files, array(
281
      $this->getRootDir().'/'.$globalConfigPath,              // project
282
      $this->getRootDir().'/'.$configPath,                    // project
283
    ));
284
 
285
    foreach ($this->getPluginPaths() as $path)
286
    {
287
      if (is_file($file = $path.'/'.$configPath))
288
      {
289
        $files[] = $file;                                     // plugins
290
      }
291
    }
292
 
293
    $configs = array();
294
    foreach (array_unique($files) as $file)
295
    {
296
      if (is_readable($file))
297
      {
298
        $configs[] = $file;
299
      }
300
    }
301
 
302
    return $configs;
303
  }
304
 
305
  /**
306
   * Sets the enabled plugins.
307
   *
308
   * @param array $plugins An array of plugin names
309
   *
310
   * @throws LogicException If plugins have already been loaded
311
   */
312
  public function setPlugins(array $plugins)
313
  {
314
    if ($this->pluginsLoaded)
315
    {
316
      throw new LogicException('Plugins have already been loaded.');
317
    }
318
 
319
    $this->plugins = $plugins;
320
 
321
    $this->pluginPaths = array();
322
  }
323
 
324
  /**
325
   * Enables a plugin or a list of plugins.
326
   *
327
   * @param array|string $plugins A plugin name or a plugin list
328
   */
329
  public function enablePlugins($plugins)
330
  {
331
    if (!is_array($plugins))
332
    {
333
      if (func_num_args() > 1)
334
      {
335
        $plugins = func_get_args();
336
      }
337
      else
338
      {
339
        $plugins = array($plugins);
340
      }
341
    }
342
 
343
    $this->setPlugins(array_merge($this->plugins, $plugins));
344
  }
345
 
346
  /**
347
   * Disables a plugin.
348
   *
349
   * @param array|string $plugins A plugin name or a plugin list
350
   *
351
   * @throws LogicException If plugins have already been loaded
352
   */
353
  public function disablePlugins($plugins)
354
  {
355
    if ($this->pluginsLoaded)
356
    {
357
      throw new LogicException('Plugins have already been loaded.');
358
    }
359
 
360
    if (!is_array($plugins))
361
    {
362
      $plugins = array($plugins);
363
    }
364
 
365
    foreach ($plugins as $plugin)
366
    {
367
      if (false !== $pos = array_search($plugin, $this->plugins))
368
      {
369
        unset($this->plugins[$pos]);
370
      }
371
      else
372
      {
373
        throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin));
374
      }
375
    }
376
 
377
    $this->pluginPaths = array();
378
  }
379
 
380
  /**
381
   * Enabled all installed plugins except the one given as argument.
382
   *
383
   * @param array|string $plugins A plugin name or a plugin list
384
   *
385
   * @throws LogicException If plugins have already been loaded
386
   */
387
  public function enableAllPluginsExcept($plugins = array())
388
  {
389
    if ($this->pluginsLoaded)
390
    {
391
      throw new LogicException('Plugins have already been loaded.');
392
    }
393
 
394
    $this->plugins = array_keys($this->getAllPluginPaths());
395
 
396
    sort($this->plugins);
397
 
398
    $this->disablePlugins($plugins);
399
  }
400
 
401
  /**
402
   * Gets the list of enabled plugins.
403
   *
404
   * @return array An array of enabled plugins
405
   */
406
  public function getPlugins()
407
  {
408
    return $this->plugins;
409
  }
410
 
411
  /**
412
   * Gets the paths plugin sub-directories, minding overloaded plugins.
413
   *
414
   * @param  string $subPath The subdirectory to look for
415
   *
416
   * @return array The plugin paths.
417
   */
418
  public function getPluginSubPaths($subPath = '')
419
  {
420
    if (array_key_exists($subPath, $this->pluginPaths))
421
    {
422
      return $this->pluginPaths[$subPath];
423
    }
424
 
425
    $this->pluginPaths[$subPath] = array();
426
    $pluginPaths = $this->getPluginPaths();
427
    foreach ($pluginPaths as $pluginPath)
428
    {
429
      if (is_dir($pluginPath.$subPath))
430
      {
431
        $this->pluginPaths[$subPath][] = $pluginPath.$subPath;
432
      }
433
    }
434
 
435
    return $this->pluginPaths[$subPath];
436
  }
437
 
438
  /**
439
   * Gets the paths to plugins root directories, minding overloaded plugins.
440
   *
441
   * @return array The plugin root paths.
442
   *
443
   * @throws InvalidArgumentException If an enabled plugin does not exist
444
   */
445
  public function getPluginPaths()
446
  {
447
    if (!isset($this->pluginPaths['']))
448
    {
449
      $pluginPaths = $this->getAllPluginPaths();
450
 
451
      $this->pluginPaths[''] = array();
452
      foreach ($this->getPlugins() as $plugin)
453
      {
454
        if (isset($pluginPaths[$plugin]))
455
        {
456
          $this->pluginPaths[''][] = $pluginPaths[$plugin];
457
        }
458
        else
459
        {
460
          throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin));
461
        }
462
      }
463
    }
464
 
465
    return $this->pluginPaths[''];
466
  }
467
 
468
  /**
469
   * Returns an array of paths for all available plugins.
470
   *
471
   * @return array
472
   */
473
  public function getAllPluginPaths()
474
  {
475
    $pluginPaths = array();
476
 
477
    // search for *Plugin directories representing plugins
478
    // follow links and do not recurse. No need to exclude VC because they do not end with *Plugin
479
    $finder = sfFinder::type('dir')->maxdepth(0)->ignore_version_control(false)->follow_link()->name('*Plugin');
480
    $dirs = array(
481
      $this->getSymfonyLibDir().'/plugins',
482
      sfConfig::get('sf_plugins_dir'),
483
    );
484
 
485
    foreach ($finder->in($dirs) as $path)
486
    {
487
      $pluginPaths[basename($path)] = $path;
488
    }
489
 
490
    foreach ($this->overriddenPluginPaths as $plugin => $path)
491
    {
492
      $pluginPaths[$plugin] = $path;
493
    }
494
 
495
    return $pluginPaths;
496
  }
497
 
498
  /**
499
   * Manually sets the location of a particular plugin.
500
   *
501
   * This method can be used to ease functional testing of plugins. It is not
502
   * intended to support sharing plugins between projects, as many plugins
503
   * save project specific code (to /lib/form/base, for example).
504
   *
505
   * @param string $plugin
506
   * @param string $path
507
   */
508
  public function setPluginPath($plugin, $path)
509
  {
510
    $this->overriddenPluginPaths[$plugin] = realpath($path);
511
  }
512
 
513
  /**
514
   * Returns the configuration for the requested plugin.
515
   *
516
   * @param   string $name
517
   *
518
   * @return  sfPluginConfiguration
519
   */
520
  public function getPluginConfiguration($name)
521
  {
522
    if (!isset($this->pluginConfigurations[$name]))
523
    {
524
      throw new InvalidArgumentException(sprintf('There is no configuration object for the "%s" object.', $name));
525
    }
526
 
527
    return $this->pluginConfigurations[$name];
528
  }
529
 
530
  /**
531
   * Returns the event dispatcher.
532
   *
533
   * @return sfEventDispatcher A sfEventDispatcher instance
534
   */
535
  public function getEventDispatcher()
536
  {
537
    return $this->dispatcher;
538
  }
539
 
540
  /**
541
   * Returns the symfony lib directory.
542
   *
543
   * @return string The symfony lib directory
544
   */
545
  public function getSymfonyLibDir()
546
  {
547
    return $this->symfonyLibDir;
548
  }
549
 
550
  /**
551
   * Returns the active configuration.
552
   *
553
   * @return sfProjectConfiguration The current sfProjectConfiguration instance
554
   */
555
  static public function getActive()
556
  {
557
    if (!self::hasActive())
558
    {
559
      throw new RuntimeException('There is no active configuration.');
560
    }
561
 
562
    return self::$active;
563
  }
564
 
565
  /**
566
   * Returns true if these is an active configuration.
567
   *
568
   * @return boolean
569
   */
570
  static public function hasActive()
571
  {
572
    return null !== self::$active;
573
  }
574
 
575
  /**
576
   * Guesses the project root directory.
577
   *
578
   * @return string The project root directory
579
   */
580
  static public function guessRootDir()
581
  {
582
    $r = new ReflectionClass('ProjectConfiguration');
583
 
584
    return realpath(dirname($r->getFileName()).'/..');
585
  }
586
 
587
  /**
588
   * Returns a sfApplicationConfiguration configuration for a given application.
589
   *
590
   * @param string            $application    An application name
591
   * @param string            $environment    The environment name
592
   * @param Boolean           $debug          true to enable debug mode
593
   * @param string            $rootDir        The project root directory
594
   * @param sfEventDispatcher $dispatcher     An event dispatcher
595
   *
596
   * @return sfApplicationConfiguration A sfApplicationConfiguration instance
597
   */
598
  static public function getApplicationConfiguration($application, $environment, $debug, $rootDir = null, sfEventDispatcher $dispatcher = null)
599
  {
600
    $class = $application.'Configuration';
601
 
602
    if (null === $rootDir)
603
    {
604
      $rootDir = self::guessRootDir();
605
    }
606
 
607
    if (!file_exists($file = $rootDir.'/apps/'.$application.'/config/'.$class.'.class.php'))
608
    {
609
      throw new InvalidArgumentException(sprintf('The application "%s" does not exist.', $application));
610
    }
611
 
612
    require_once $file;
613
 
614
    return new $class($environment, $debug, $rootDir, $dispatcher);
615
  }
616
 
617
  /**
618
   * Calls methods defined via sfEventDispatcher.
619
   *
620
   * @param string $method The method name
621
   * @param array  $arguments The method arguments
622
   *
623
   * @return mixed The returned value of the called method
624
   */
625
  public function __call($method, $arguments)
626
  {
627
    $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'configuration.method_not_found', array('method' => $method, 'arguments' => $arguments)));
628
    if (!$event->isProcessed())
629
    {
630
      throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
631
    }
632
 
633
    return $event->getReturnValue();
634
  }
635
}