PluginProbe
Packeta / trunk
Packeta vtrunk
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / deps / nette / di / src / DI / Extensions / DefinitionSchema.php

DefinitionSchema.php in Packeta trunk, at deps/nette/di/src/DI/Extensions/DefinitionSchema.php

162 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7 declare (strict_types=1);
8 namespace Packetery\Nette\DI\Extensions;
9
10 use Packetery\Nette;
11 use Packetery\Nette\DI\Config\Helpers;
12 use Packetery\Nette\DI\Definitions;
13 use Packetery\Nette\DI\Definitions\Statement;
14 use Packetery\Nette\Schema\Context;
15 use Packetery\Nette\Schema\Expect;
16 use Packetery\Nette\Schema\Schema;
17 /**
18 * Service configuration schema.
19 */
20 class DefinitionSchema implements Schema
21 {
22 use \Packetery\Nette\SmartObject;
23 /** @var \Packetery\Nette\DI\ContainerBuilder */
24 private $builder;
25 public function __construct(\Packetery\Nette\DI\ContainerBuilder $builder)
26 {
27 $this->builder = $builder;
28 }
29 public function complete($def, Context $context)
30 {
31 if ($def === [\false]) {
32 return (object) $def;
33 }
34 if (Helpers::takeParent($def)) {
35 $def['reset']['all'] = \true;
36 }
37 foreach (['arguments', 'setup', 'tags'] as $k) {
38 if (isset($def[$k]) && Helpers::takeParent($def[$k])) {
39 $def['reset'][$k] = \true;
40 }
41 }
42 $def = $this->expandParameters($def);
43 $type = $this->sniffType(\end($context->path), $def);
44 $def = $this->getSchema($type)->complete($def, $context);
45 if ($def) {
46 $def->defType = $type;
47 }
48 return $def;
49 }
50 public function merge($def, $base)
51 {
52 if (!empty($def['alteration'])) {
53 unset($def['alteration']);
54 }
55 return \Packetery\Nette\Schema\Helpers::merge($def, $base);
56 }
57 /**
58 * Normalizes configuration of service definitions.
59 */
60 public function normalize($def, Context $context)
61 {
62 if ($def === null || $def === \false) {
63 return (array) $def;
64 } elseif (\is_string($def) && \interface_exists($def)) {
65 return ['implement' => $def];
66 } elseif ($def instanceof Statement && \is_string($def->getEntity()) && \interface_exists($def->getEntity())) {
67 $res = ['implement' => $def->getEntity()];
68 if (\array_keys($def->arguments) === ['tagged']) {
69 $res += $def->arguments;
70 } elseif (\array_keys($def->arguments) === [0]) {
71 $res['create'] = $def->arguments[0];
72 } elseif ($def->arguments) {
73 $res['references'] = $def->arguments;
74 }
75 return $res;
76 } elseif (!\is_array($def) || isset($def[0], $def[1])) {
77 return ['create' => $def];
78 } else {
79 // back compatibility
80 if (isset($def['factory']) && !isset($def['create'])) {
81 $def['create'] = $def['factory'];
82 unset($def['factory']);
83 }
84 if (isset($def['class']) && !isset($def['type']) && !isset($def['dynamic']) && !isset($def['imported'])) {
85 $def[isset($def['create']) ? 'type' : 'create'] = $def['class'];
86 unset($def['class']);
87 }
88 foreach (['class' => 'type', 'dynamic' => 'imported'] as $alias => $original) {
89 if (\array_key_exists($alias, $def)) {
90 if (\array_key_exists($original, $def)) {
91 throw new \Packetery\Nette\DI\InvalidConfigurationException(\sprintf("Options '%s' and '%s' are aliases, use only '%s'.", $alias, $original, $original));
92 }
93 \trigger_error(\sprintf("Service '%s': option '{$alias}' should be changed to '{$original}'.", \end($context->path)), \E_USER_DEPRECATED);
94 $def[$original] = $def[$alias];
95 unset($def[$alias]);
96 }
97 }
98 return $def;
99 }
100 }
101 public function completeDefault(Context $context)
102 {
103 }
104 private function sniffType($key, array $def) : string
105 {
106 if (\is_string($key)) {
107 $name = \preg_match('#^@[\\w\\\\]+$#D', $key) ? $this->builder->getByType(\substr($key, 1)) : $key;
108 if ($name && $this->builder->hasDefinition($name)) {
109 return \get_class($this->builder->getDefinition($name));
110 }
111 }
112 if (isset($def['implement'], $def['references']) || isset($def['implement'], $def['tagged'])) {
113 return Definitions\LocatorDefinition::class;
114 } elseif (isset($def['implement'])) {
115 return \method_exists($def['implement'], 'create') ? Definitions\FactoryDefinition::class : Definitions\AccessorDefinition::class;
116 } elseif (isset($def['imported'])) {
117 return Definitions\ImportedDefinition::class;
118 } elseif (!$def) {
119 throw new \Packetery\Nette\DI\InvalidConfigurationException("Service '{$key}': Empty definition.");
120 } else {
121 return Definitions\ServiceDefinition::class;
122 }
123 }
124 private function expandParameters(array $config) : array
125 {
126 $params = $this->builder->parameters;
127 if (isset($config['parameters'])) {
128 foreach ((array) $config['parameters'] as $k => $v) {
129 $v = \explode(' ', \is_int($k) ? $v : $k);
130 $params[\end($v)] = $this->builder::literal('$' . \end($v));
131 }
132 }
133 return \Packetery\Nette\DI\Helpers::expand($config, $params);
134 }
135 private static function getSchema(string $type) : Schema
136 {
137 static $cache;
138 $cache = $cache ?: [Definitions\ServiceDefinition::class => self::getServiceSchema(), Definitions\AccessorDefinition::class => self::getAccessorSchema(), Definitions\FactoryDefinition::class => self::getFactorySchema(), Definitions\LocatorDefinition::class => self::getLocatorSchema(), Definitions\ImportedDefinition::class => self::getImportedSchema()];
139 return $cache[$type];
140 }
141 private static function getServiceSchema() : Schema
142 {
143 return Expect::structure(['type' => Expect::type('string'), 'create' => Expect::type('callable|\\Packetery\\Nette\\DI\\Definitions\\Statement'), 'arguments' => Expect::array(), 'setup' => Expect::listOf('callable|\\Packetery\\Nette\\DI\\Definitions\\Statement|array:1'), 'inject' => Expect::bool(), 'autowired' => Expect::type('bool|string|array'), 'tags' => Expect::array(), 'reset' => Expect::array(), 'alteration' => Expect::bool()]);
144 }
145 private static function getAccessorSchema() : Schema
146 {
147 return Expect::structure(['type' => Expect::string(), 'implement' => Expect::string(), 'create' => Expect::type('callable|\\Packetery\\Nette\\DI\\Definitions\\Statement'), 'autowired' => Expect::type('bool|string|array'), 'tags' => Expect::array()]);
148 }
149 private static function getFactorySchema() : Schema
150 {
151 return Expect::structure(['type' => Expect::string(), 'create' => Expect::type('callable|\\Packetery\\Nette\\DI\\Definitions\\Statement'), 'implement' => Expect::string(), 'arguments' => Expect::array(), 'setup' => Expect::listOf('callable|\\Packetery\\Nette\\DI\\Definitions\\Statement|array:1'), 'parameters' => Expect::array(), 'references' => Expect::array(), 'tagged' => Expect::string(), 'inject' => Expect::bool(), 'autowired' => Expect::type('bool|string|array'), 'tags' => Expect::array(), 'reset' => Expect::array()]);
152 }
153 private static function getLocatorSchema() : Schema
154 {
155 return Expect::structure(['implement' => Expect::string(), 'references' => Expect::array(), 'tagged' => Expect::string(), 'autowired' => Expect::type('bool|string|array'), 'tags' => Expect::array()]);
156 }
157 private static function getImportedSchema() : Schema
158 {
159 return Expect::structure(['type' => Expect::string(), 'imported' => Expect::bool(), 'autowired' => Expect::type('bool|string|array'), 'tags' => Expect::array()]);
160 }
161 }
162