* (c) 2004-2006 Sean Kerr * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * * @package symfony * @subpackage config * @author Fabien Potencier * @author Sean Kerr * @version SVN: $Id: sfAutoloadConfigHandler.class.php 24062 2009-11-16 23:31:25Z FabianLange $ */ class sfAutoloadConfigHandler extends sfYamlConfigHandler { /** * Executes this configuration handler. * * @param array $configFiles An array of absolute filesystem path to a configuration file * * @return string Data to be written to a cache file * * @throws sfConfigurationException If a requested configuration file does not exist or is not readable * @throws sfParseException If a requested configuration file is improperly formatted */ public function execute($configFiles) { // set our required categories list and initialize our handler $this->initialize(array('required_categories' => array('autoload'))); $data = array(); foreach ($this->parse($configFiles) as $name => $mapping) { $data[] = sprintf("\n // %s", $name); foreach ($mapping as $class => $file) { $data[] = sprintf(" '%s' => '%s',", $class, str_replace('\\', '\\\\', $file)); } } // compile data return sprintf("parse($configFiles) as $mapping) { foreach ($mapping as $class => $file) { $mappings[$class] = $file; } } return $mappings; } protected function parse(array $configFiles) { // parse the yaml $config = self::getConfiguration($configFiles); $mappings = array(); foreach ($config['autoload'] as $name => $entry) { $mapping = array(); // file mapping or directory mapping? if (isset($entry['files'])) { // file mapping foreach ($entry['files'] as $class => $file) { $mapping[strtolower($class)] = $file; } } else { // directory mapping $ext = isset($entry['ext']) ? $entry['ext'] : '.php'; $path = $entry['path']; // we automatically add our php classes require_once(sfConfig::get('sf_symfony_lib_dir').'/util/sfFinder.class.php'); $finder = sfFinder::type('file')->name('*'.$ext)->follow_link(); // recursive mapping? $recursive = isset($entry['recursive']) ? $entry['recursive'] : false; if (!$recursive) { $finder->maxdepth(0); } // exclude files or directories? if (isset($entry['exclude']) && is_array($entry['exclude'])) { $finder->prune($entry['exclude'])->discard($entry['exclude']); } if ($matches = glob($path)) { foreach ($finder->in($matches) as $file) { $mapping = array_merge($mapping, $this->parseFile($path, $file, isset($entry['prefix']) ? $entry['prefix'] : '')); } } } $mappings[$name] = $mapping; } return $mappings; } static public function parseFile($path, $file, $prefix) { $mapping = array(); preg_match_all('~^\s*(?:abstract\s+|final\s+)?(?:class|interface)\s+(\w+)~mi', file_get_contents($file), $classes); foreach ($classes[1] as $class) { $localPrefix = ''; if ($prefix) { // FIXME: does not work for plugins installed with a symlink preg_match('~^'.str_replace('\*', '(.+?)', preg_quote(str_replace('/', DIRECTORY_SEPARATOR, $path), '~')).'~', str_replace('/', DIRECTORY_SEPARATOR, $file), $match); if (isset($match[$prefix])) { $localPrefix = $match[$prefix].'/'; } } $mapping[$localPrefix.strtolower($class)] = $file; } return $mapping; } /** * @see sfConfigHandler */ static public function getConfiguration(array $configFiles) { $configuration = sfProjectConfiguration::getActive(); $pluginPaths = $configuration->getPluginPaths(); $pluginConfigFiles = array(); // move plugin files to front foreach ($configFiles as $i => $configFile) { $configFilePath = str_replace(DIRECTORY_SEPARATOR, '/', $configFile); $path = str_replace(DIRECTORY_SEPARATOR, '/', realpath(join('/', array_slice(explode('/', $configFilePath), 0, -2)))); if (in_array($path, $pluginPaths)) { $pluginConfigFiles[] = $configFile; unset($configFiles[$i]); } } $configFiles = array_merge($pluginConfigFiles, $configFiles); $config = self::replaceConstants(self::parseYamls($configFiles)); foreach ($config['autoload'] as $name => $values) { if (isset($values['path'])) { $config['autoload'][$name]['path'] = self::replacePath($values['path']); } } $event = $configuration->getEventDispatcher()->filter(new sfEvent(__CLASS__, 'autoload.filter_config'), $config); $config = $event->getReturnValue(); return $config; } }