vendor/symfony/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
author ymh <ymh.work@gmail.com>
Sat, 24 Sep 2011 15:40:41 +0200
changeset 0 7f95f8617b0b
permissions -rwxr-xr-x
first commit
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
<?php
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/*
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * This file is part of the Symfony package.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * (c) Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * For the full copyright and license information, please view the LICENSE
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * file that was distributed with this source code.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
namespace Symfony\Component\DependencyInjection\Loader;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
use Symfony\Component\DependencyInjection\DefinitionDecorator;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
use Symfony\Component\DependencyInjection\ContainerInterface;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
use Symfony\Component\DependencyInjection\Alias;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
use Symfony\Component\DependencyInjection\Definition;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
use Symfony\Component\DependencyInjection\Reference;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
use Symfony\Component\DependencyInjection\ContainerBuilder;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
use Symfony\Component\DependencyInjection\SimpleXMLElement;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
use Symfony\Component\Config\Resource\FileResource;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
/**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
 * XmlFileLoader loads XML files service definitions.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
 *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
 * @author Fabien Potencier <fabien@symfony.com>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
 */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
class XmlFileLoader extends FileLoader
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
{
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
     * Loads an XML file.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
     * @param mixed  $file The resource
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
     * @param string $type The resource type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    public function load($file, $type = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        $path = $this->locator->locate($file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        $xml = $this->parseFile($path);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        $xml->registerXPathNamespace('container', 'http://symfony.com/schema/dic/services');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        $this->container->addResource(new FileResource($path));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
        // anonymous services
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        $xml = $this->processAnonymousServices($xml, $path);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
        // imports
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
        $this->parseImports($xml, $path);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        // parameters
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
        $this->parseParameters($xml, $path);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        // extensions
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        $this->loadFromExtensions($xml);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        // services
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        $this->parseDefinitions($xml, $path);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
     * Returns true if this class supports the given resource.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
     * @param mixed  $resource A resource
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
     * @param string $type     The resource type
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
     * @return Boolean true if this class supports the given resource, false otherwise
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    public function supports($resource, $type = null)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
     * Parses parameters
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
     * @param SimpleXMLElement $xml
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
    private function parseParameters(SimpleXMLElement $xml, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
        if (!$xml->parameters) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
            return;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
     * Parses imports
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
     * @param SimpleXMLElement $xml
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
    private function parseImports(SimpleXMLElement $xml, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
        if (false === $imports = $xml->xpath('//container:imports/container:import')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
            return;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
        foreach ($imports as $import) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
            $this->setCurrentDir(dirname($file));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
            $this->import((string) $import['resource'], null, (Boolean) $import->getAttributeAsPhp('ignore-errors'), $file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
     * Parses multiple definitions
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
     * @param SimpleXMLElement $xml
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
    private function parseDefinitions(SimpleXMLElement $xml, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
        if (false === $services = $xml->xpath('//container:services/container:service')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
            return;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
        foreach ($services as $service) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
            $this->parseDefinition((string) $service['id'], $service, $file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
     * Parses an individual Definition
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
     * @param string $id
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
     * @param SimpleXMLElement $service
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    private function parseDefinition($id, $service, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
        if ((string) $service['alias']) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
            $public = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
            if (isset($service['public'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
                $public = $service->getAttributeAsPhp('public');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
            $this->container->setAlias($id, new Alias((string) $service['alias'], $public));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
            return;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
        if (isset($service['parent'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
            $definition = new DefinitionDecorator((string) $service['parent']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
        } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
            $definition = new Definition();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
        foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'abstract') as $key) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
            if (isset($service[$key])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
                $method = 'set'.str_replace('-', '', $key);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
                $definition->$method((string) $service->getAttributeAsPhp($key));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
        if ($service->file) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
            $definition->setFile((string) $service->file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
        $definition->setArguments($service->getArgumentsAsPhp('argument'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
        $definition->setProperties($service->getArgumentsAsPhp('property'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
        if (isset($service->configurator)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
            if (isset($service->configurator['function'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
                $definition->setConfigurator((string) $service->configurator['function']);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
                if (isset($service->configurator['service'])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
                    $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
                    $class = (string) $service->configurator['class'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
                $definition->setConfigurator(array($class, (string) $service->configurator['method']));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
        foreach ($service->call as $call) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
            $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
        foreach ($service->tag as $tag) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
            $parameters = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
            foreach ($tag->attributes() as $name => $value) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
                if ('name' === $name) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
                    continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
                $parameters[$name] = SimpleXMLElement::phpize($value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
            $definition->addTag((string) $tag['name'], $parameters);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
        $this->container->setDefinition($id, $definition);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
     * Parses a XML file.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
     * @param string $file Path to a file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
     * @throws \InvalidArgumentException When loading of XML file returns error
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
    private function parseFile($file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
        $dom = new \DOMDocument();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
        libxml_use_internal_errors(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
        if (!$dom->load($file, LIBXML_COMPACT)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
            throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors()));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
        $dom->validateOnParse = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
        $dom->normalizeDocument();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
        libxml_use_internal_errors(false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
        $this->validate($dom, $file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
        return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
     * Processes anonymous services
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
     * @param SimpleXMLElement $xml
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
     * @return array An array of anonymous services
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
    private function processAnonymousServices(SimpleXMLElement $xml, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
        $definitions = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
        $count = 0;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
        // anonymous services as arguments
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
        if (false === $nodes = $xml->xpath('//container:argument[@type="service"][not(@id)]')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
            return $xml;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
        foreach ($nodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
            // give it a unique name
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
            $node['id'] = sprintf('%s_%d', md5($file), ++$count);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
            $definitions[(string) $node['id']] = array($node->service, $file, false);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
            $node->service['id'] = (string) $node['id'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
        // anonymous services "in the wild"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
        if (false === $nodes = $xml->xpath('//container:services/container:service[not(@id)]')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
            return $xml;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
        foreach ($nodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
            // give it a unique name
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
            $node['id'] = sprintf('%s_%d', md5($file), ++$count);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
            $definitions[(string) $node['id']] = array($node, $file, true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
            $node->service['id'] = (string) $node['id'];
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
        // resolve definitions
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
        krsort($definitions);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
        foreach ($definitions as $id => $def) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
            // anonymous services are always private
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
            $def[0]['public'] = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
            $this->parseDefinition($id, $def[0], $def[1]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
            $oNode = dom_import_simplexml($def[0]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
            if (true === $def[2]) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
                $nNode = new \DOMElement('_services');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
                $oNode->parentNode->replaceChild($nNode, $oNode);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
                $nNode->setAttribute('id', $id);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
                $oNode->parentNode->removeChild($oNode);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
        return $xml;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
     * Validates an XML document.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
     * @param DOMDocument $dom
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
    private function validate(\DOMDocument $dom, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
        $this->validateSchema($dom, $file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
        $this->validateExtensions($dom, $file);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
     * Validates a documents XML schema.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
     * @param \DOMDocument $dom
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
     * @throws \RuntimeException         When extension references a non-existent XSD file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
     * @throws \InvalidArgumentException When xml doesn't validate its xsd schema
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
    private function validateSchema(\DOMDocument $dom, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
        $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
        if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
            $items = preg_split('/\s+/', $element);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
            for ($i = 0, $nb = count($items); $i < $nb; $i += 2) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
                if (!$this->container->hasExtension($items[$i])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
                    continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
                if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
                    $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
                    if (!file_exists($path)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
                        throw new \RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
                    $schemaLocations[$items[$i]] = $path;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
        $tmpfiles = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
        $imports = '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
        foreach ($schemaLocations as $namespace => $location) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
            $parts = explode('/', $location);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
            if (preg_match('#^phar://#i', $location)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
                $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
                if ($tmpfile) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
                    file_put_contents($tmpfile, file_get_contents($location));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
                    $tmpfiles[] = $tmpfile;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
                    $parts = explode('/', str_replace('\\', '/', $tmpfile));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
            $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
            $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
            $imports .= sprintf('  <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
        $source = <<<EOF
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
<?xml version="1.0" encoding="utf-8" ?>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
<xsd:schema xmlns="http://symfony.com/schema"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
    targetNamespace="http://symfony.com/schema"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
    elementFormDefault="qualified">
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
$imports
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
</xsd:schema>
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
EOF
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
        ;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
        $current = libxml_use_internal_errors(true);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
        $valid = $dom->schemaValidateSource($source);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
        foreach ($tmpfiles as $tmpfile) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
            @unlink($tmpfile);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
        if (!$valid) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
            throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors()));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
        libxml_use_internal_errors($current);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
     * Validates an extension.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
     * @param \DOMDocument $dom
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
     * @param string $file
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
     * @throws  \InvalidArgumentException When non valid tag are found or no extension are found
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
    private function validateExtensions(\DOMDocument $dom, $file)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
        foreach ($dom->documentElement->childNodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
            if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
                continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
            // can it be handled by an extension?
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
            if (!$this->container->hasExtension($node->namespaceURI)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
                $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions()));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
                throw new \InvalidArgumentException(sprintf(
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
                    'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
                    $node->tagName,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
                    $file,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
                    $node->namespaceURI,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
                    $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
                ));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
     * Returns an array of XML errors.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
     * @return array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
    private function getXmlErrors()
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
        $errors = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
        foreach (libxml_get_errors() as $error) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
                $error->code,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
                trim($error->message),
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
                $error->file ? $error->file : 'n/a',
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
                $error->line,
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
                $error->column
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
            );
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
        libxml_clear_errors();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
        return $errors;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
     * Loads from an extension.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
     * @param SimpleXMLElement $xml
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
     * @return void
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
    private function loadFromExtensions(SimpleXMLElement $xml)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
        foreach (dom_import_simplexml($xml)->childNodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
            if (!$node instanceof \DOMElement || $node->namespaceURI === 'http://symfony.com/schema/dic/services') {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
                continue;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
            $values = static::convertDomElementToArray($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
            if (!is_array($values)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
                $values = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
            $this->container->loadFromExtension($node->namespaceURI, $values);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
    /**
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
     * Converts a \DomElement object to a PHP array.
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
     * The following rules applies during the conversion:
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
     *  * Each tag is converted to a key value or an array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
     *    if there is more than one "value"
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
     *    if the tag also has some nested tags
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
     *  * The attributes are converted to keys (<foo foo="bar"/>)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
     * @param \DomElement $element A \DomElement instance
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
     *
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
     * @return array A PHP array
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
     */
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
    static public function convertDomElementToArray(\DomElement $element)
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
    {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
        $empty = true;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
        $config = array();
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
        foreach ($element->attributes as $name => $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
            $config[$name] = SimpleXMLElement::phpize($node->value);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
            $empty = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
        $nodeValue = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
        foreach ($element->childNodes as $node) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
            if ($node instanceof \DOMText) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
                if (trim($node->nodeValue)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
                    $nodeValue = trim($node->nodeValue);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
                    $empty = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
            } elseif (!$node instanceof \DOMComment) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
                if ($node instanceof \DOMElement && '_services' === $node->nodeName) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
                    $value = new Reference($node->getAttribute('id'));
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
                    $value = static::convertDomElementToArray($node);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
                $key = $node->localName;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
                if (isset($config[$key])) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
                    if (!is_array($config[$key]) || !is_int(key($config[$key]))) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
                        $config[$key] = array($config[$key]);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
                    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
                    $config[$key][] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
                } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
                    $config[$key] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
                }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
                $empty = false;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
        if (false !== $nodeValue) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
            $value = SimpleXMLElement::phpize($nodeValue);
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
            if (count($config)) {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
                $config['value'] = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
            } else {
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
                $config = $value;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
            }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
        }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
        return !$empty ? $config : null;
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
    }
7f95f8617b0b first commit
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
}