Просмотр файла cvServiceContainer/cvServiceContainerLoaderFileYaml.php

Размер файла: 6.07Kb
<?php

/**
 * cvServiceContainerLoaderFileYaml
 * 
 * cvServiceContainerLoaderFileYaml loads YAML files service definitions.
 * The YAML format does not support anonymous services (cf. the XML loader).
 * 
 * @package CYBERVILLE
 * @subpackage DI
 * @author Fabien Potencier <[email protected]>
 *         Kochergin Nick <[email protected]>, <http://cyberville-project.ru>
 * @version $Id$
 */
class cvServiceContainerLoaderFileYaml extends cvServiceContainerLoaderFile {
    public function doLoad($files) {
        return $this->parse($this->getFilesAsArray($files));
    }

    protected function parse($data) {
        $parameters = array();
        $definitions = array();

        foreach ($data as $file => $content) {
            // imports
            list($importedDefinitions, $importedParameters) = $this->parseImports($content, $file);
            $definitions = array_merge($definitions, $importedDefinitions);
            $parameters = array_merge($parameters, $importedParameters);

            // parameters
            if (isset($content['parameters'])) {
                foreach ($content['parameters'] as $key => $value) {
                    $parameters[strtolower($key)] = $this->resolveServices($value);
                }
            }

            // services
            $definitions = array_merge($definitions, $this->parseDefinitions($content, $file));
        }

        return array($definitions, $parameters);
    }

    protected function parseImports($content, $file) {
        if (!isset($content['imports'])) {
            return array(array(), array());
        }

        $definitions = array();
        $parameters = array();
        foreach ($content['imports'] as $import) {
            list($importedDefinitions, $importedParameters) = $this->parseImport($import, $file);

            $definitions = array_merge($definitions, $importedDefinitions);
            $parameters = array_merge($parameters, $importedParameters);
        }

        return array($definitions, $parameters);
    }

    protected function parseImport($import, $file) {
        if (isset($import['class']) && $import['class'] != get_class($this)) {
            $class = $import['class'];
            $loader = new $class($this->container, $this->paths);
        } else {
            $loader = $this;
        }

        $importedFile = $this->getAbsolutePath($import['resource'], dirname($file));

        return call_user_func(array($loader, 'doLoad'), array($importedFile));
    }

    protected function parseDefinitions($content, $file) {
        if (!isset($content['services'])) {
            return array();
        }

        $definitions = array();
        foreach ($content['services'] as $id => $service) {
            $definitions[$id] = $this->parseDefinition($service, $file);
        }

        return $definitions;
    }

    protected function parseDefinition($service, $file) {
        if (is_string($service) && 0 === strpos($service, '@')) {
            $alias = array(substr($service, 1), false);
            if (preg_match('/^([^&]+)&(.+)$/', $alias[0], $match)) {
                $alias = array($match[2], $match[1]);
            }
            return $alias;
        }

        $definition = new cvServiceDefinition($service['class']);

        if (isset($service['shared'])) {
            $definition->setShared($service['shared']);
        }

        if (isset($service['constructor'])) {
            $definition->setConstructor($service['constructor']);
        }

        if (isset($service['file'])) {
            $definition->setFile($service['file']);
        }

        if (isset($service['arguments'])) {
            $definition->setArguments($this->resolveServices($service['arguments']));
        }

        if (isset($service['configurator'])) {
            if (is_string($service['configurator'])) {
                $definition->setConfigurator($service['configurator']);
            } else {
                $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1]));
            }
        }

        if (isset($service['calls'])) {
            foreach ($service['calls'] as $call) {
                $definition->addMethodCall($call[0], $this->resolveServices($call[1]));
            }
        }

        return $definition;
    }

    protected function getFilesAsArray(array $files) {
        $yamls = array();
        foreach ($files as $file) {
            $file = $this->getAbsolutePath($file);

            if (!file_exists($file)) {
                throw new InvalidArgumentException(sprintf('The service file "%s" does not exist.', $file));
            }

            $yamls[$file] = $this->validate(sfYaml::load($file), $file);
        }

        return $yamls;
    }

    protected function validate($content, $file) {
        if (null === $content) {
            return $content;
        }

        if (!is_array($content)) {
            throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file));
        }

        foreach (array_keys($content) as $key) {
            if (!in_array($key, array('imports', 'parameters', 'services'))) {
                throw new InvalidArgumentException(sprintf('The service file "%s" is not valid ("%s" is not recognized).', $file, $key));
            }
        }

        return $content;
    }

    protected function resolveServices($value) {
        if (is_array($value)) {
            $value = array_map(array($this, 'resolveServices'), $value);
        } else
            if (is_string($value) && 0 === strpos($value, '@')) {
                $service_id = substr($value, 1);
                $container_id = null;
                if (preg_match('/^([^&]+)&(.+)$/', $service_id, $match)) {
                    $container_id = $match[1];
                    $service_id = $match[2];
                }
                $value = new cvServiceReference($service_id, $container_id);
            }

        return $value;
    }
}

?>