1: <?php
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: namespace Thelia\Core\DependencyInjection\Loader;
25:
26: use Symfony\Component\Config\Resource\FileResource;
27: use Symfony\Component\DependencyInjection\Loader\XmlFileLoader as XmlLoader;
28: use Symfony\Component\Config\Util\XmlUtils;
29: use Symfony\Component\DependencyInjection\DefinitionDecorator;
30: use Symfony\Component\DependencyInjection\ContainerInterface;
31: use Symfony\Component\DependencyInjection\Alias;
32: use Symfony\Component\DependencyInjection\Definition;
33: use Symfony\Component\DependencyInjection\Reference;
34: use Symfony\Component\DependencyInjection\SimpleXMLElement;
35: use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
36: use Symfony\Component\DependencyInjection\Exception\RuntimeException;
37: use Symfony\Component\DependencyInjection\Loader\FileLoader;
38:
39: class XmlFileLoader extends FileLoader
40: {
41: 42: 43: 44: 45: 46:
47: public function load($file, $type = null)
48: {
49: $path = $this->locator->locate($file);
50:
51: $xml = $this->parseFile($path);
52: $xml->registerXPathNamespace('config', 'http://thelia.net/schema/dic/config');
53:
54: $this->container->addResource(new FileResource($path));
55:
56: $this->parseLoops($xml);
57:
58: $this->parseFilters($xml);
59:
60: $this->parseBaseParams($xml);
61:
62: $this->parseTestLoops($xml);
63:
64: $this->parseParameters($xml);
65:
66: $this->parseDefinitions($xml, $path);
67: }
68:
69: 70: 71: 72: 73:
74: protected function parseParameters(SimpleXMLElement $xml)
75: {
76: if (!$xml->parameters) {
77: return;
78: }
79:
80: $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter'));
81: }
82:
83: 84: 85: 86: 87: 88:
89: protected function parseLoops(SimpleXMLElement $xml)
90: {
91: if (false === $loops = $xml->xpath('//config:loops/config:loop')) {
92: return;
93: }
94: try {
95: $loopConfig = $this->container->getParameter("Tpex.loop");
96: } catch (\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) {
97: $loopConfig = array();
98: }
99:
100: foreach ($loops as $loop) {
101: $loopConfig[$loop->getAttributeAsPhp("name")] = $loop->getAttributeAsPhp("class");
102: }
103:
104: $this->container->setParameter("Tpex.loop", $loopConfig);
105: }
106:
107: 108: 109: 110: 111:
112: protected function parseFilters(SimpleXMLElement $xml)
113: {
114: if (false === $filters = $xml->xpath('//config:filters/config:filter')) {
115: return;
116: }
117: try {
118: $filterConfig = $this->container->getParameter("Tpex.filter");
119: } catch (\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) {
120: $filterConfig = array();
121: }
122:
123: foreach ($filters as $filter) {
124: $filterConfig[$filter->getAttributeAsPhp("name")] = $filter->getAttributeAsPhp("class");
125: }
126:
127: $this->container->setParameter("Tpex.filter", $filterConfig);
128: }
129:
130: 131: 132: 133: 134:
135: protected function parseBaseParams(SimpleXMLElement $xml)
136: {
137: if (false === $baseParams = $xml->xpath('//config:baseParams/config:baseParam')) {
138: return;
139: }
140: try {
141: $baseParamConfig = $this->container->getParameter("Tpex.baseParam");
142: } catch (\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) {
143: $baseParamConfig = array();
144: }
145:
146: foreach ($baseParams as $baseParam) {
147: $baseParamConfig[$baseParam->getAttributeAsPhp("name")] = $baseParam->getAttributeAsPhp("class");
148: }
149:
150: $this->container->setParameter("Tpex.baseParam", $baseParamConfig);
151: }
152:
153: 154: 155: 156: 157:
158: protected function parseTestLoops(SimpleXMLElement $xml)
159: {
160: if (false === $testLoops = $xml->xpath('//config:testLoops/config:testLoop')) {
161: return;
162: }
163: try {
164: $baseParamConfig = $this->container->getParameter("Tpex.baseParam");
165: } catch (\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) {
166: $baseParamConfig = array();
167: }
168:
169: foreach ($testLoops as $testLoop) {
170: $baseParamConfig[$testLoop->getAttributeAsPhp("name")] = $testLoop->getAttributeAsPhp("class");
171: }
172:
173: $this->container->setParameter("Tpex.testLoop", $baseParamConfig);
174: }
175:
176: 177: 178: 179: 180: 181:
182: protected function parseDefinitions(SimpleXMLElement $xml, $file)
183: {
184: if (false === $services = $xml->xpath('//config:services/config:service')) {
185: return;
186: }
187: foreach ($services as $service) {
188: $this->parseDefinition((string) $service['id'], $service, $file);
189: }
190: }
191:
192: 193: 194: 195: 196: 197: 198:
199: protected function parseDefinition($id, $service, $file)
200: {
201:
202: if ((string) $service['alias']) {
203: $public = true;
204: if (isset($service['public'])) {
205: $public = $service->getAttributeAsPhp('public');
206: }
207: $this->container->setAlias($id, new Alias((string) $service['alias'], $public));
208:
209: return;
210: }
211:
212: if (isset($service['parent'])) {
213: $definition = new DefinitionDecorator((string) $service['parent']);
214: } else {
215: $definition = new Definition();
216: }
217:
218: foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'abstract') as $key) {
219: if (isset($service[$key])) {
220: $method = 'set'.str_replace('-', '', $key);
221: $definition->$method((string) $service->getAttributeAsPhp($key));
222: }
223: }
224:
225: if ($service->file) {
226: $definition->setFile((string) $service->file);
227: }
228:
229: $definition->setArguments($service->getArgumentsAsPhp('argument'));
230: $definition->setProperties($service->getArgumentsAsPhp('property'));
231:
232: if (isset($service->configurator)) {
233: if (isset($service->configurator['function'])) {
234: $definition->setConfigurator((string) $service->configurator['function']);
235: } else {
236: if (isset($service->configurator['service'])) {
237: $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
238: } else {
239: $class = (string) $service->configurator['class'];
240: }
241:
242: $definition->setConfigurator(array($class, (string) $service->configurator['method']));
243: }
244: }
245:
246: foreach ($service->call as $call) {
247: $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument'));
248: }
249:
250: foreach ($service->tag as $tag) {
251: $parameters = array();
252: foreach ($tag->attributes() as $name => $value) {
253: if ('name' === $name) {
254: continue;
255: }
256:
257: $parameters[$name] = SimpleXMLElement::phpize($value);
258: }
259:
260: $definition->addTag((string) $tag['name'], $parameters);
261: }
262:
263: $this->container->setDefinition($id, $definition);
264: }
265:
266: 267: 268: 269: 270: 271: 272: 273: 274:
275: protected function parseFile($file)
276: {
277: try {
278: $dom = XmlUtils::loadFile($file, array($this, 'validateSchema'));
279: } catch (\InvalidArgumentException $e) {
280: throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
281: }
282:
283: return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement');
284: }
285:
286: 287: 288: 289: 290: 291: 292: 293: 294:
295: public function validateSchema(\DOMDocument $dom)
296: {
297: $schemaLocations = array('http://thelia.net/schema/dic/config' => str_replace('\\', '/',__DIR__.'/schema/dic/config/thelia-1.0.xsd'));
298:
299: $tmpfiles = array();
300: $imports = '';
301: foreach ($schemaLocations as $namespace => $location) {
302: $parts = explode('/', $location);
303: if (0 === stripos($location, 'phar://')) {
304: $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
305: if ($tmpfile) {
306: copy($location, $tmpfile);
307: $tmpfiles[] = $tmpfile;
308: $parts = explode('/', str_replace('\\', '/', $tmpfile));
309: }
310: }
311: $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
312: $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));
313:
314: $imports .= sprintf(' <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location);
315: }
316:
317: $source = <<<EOF
318: <?xml version="1.0" encoding="utf-8" ?>
319: <xsd:schema xmlns="http://symfony.com/schema"
320: xmlns:xsd="http://www.w3.org/2001/XMLSchema"
321: targetNamespace="http://symfony.com/schema"
322: elementFormDefault="qualified">
323:
324: <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
325: $imports
326: </xsd:schema>
327: EOF
328: ;
329:
330: $valid = @$dom->schemaValidateSource($source);
331:
332: foreach ($tmpfiles as $tmpfile) {
333: @unlink($tmpfile);
334: }
335:
336: return $valid;
337: }
338:
339: /**
340: * Returns true if this class supports the given resource.
341: *
342: * @param mixed $resource A resource
343: * @param string $type The resource type
344: *
345: * @return Boolean true if this class supports the given resource, false otherwise
346: */
347: public function supports($resource, $type = null)
348: {
349: // TODO: Implement supports() method.
350: }
351: }