annotate vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\DependencyInjection\ParameterBag;
Chris@0 13
Chris@17 14 use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
Chris@0 15 use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
Chris@0 16 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
Chris@0 17
Chris@0 18 /**
Chris@0 19 * Holds parameters.
Chris@0 20 *
Chris@0 21 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 22 */
Chris@0 23 class ParameterBag implements ParameterBagInterface
Chris@0 24 {
Chris@17 25 protected $parameters = [];
Chris@0 26 protected $resolved = false;
Chris@0 27
Chris@17 28 private $normalizedNames = [];
Chris@14 29
Chris@0 30 /**
Chris@0 31 * @param array $parameters An array of parameters
Chris@0 32 */
Chris@17 33 public function __construct(array $parameters = [])
Chris@0 34 {
Chris@0 35 $this->add($parameters);
Chris@0 36 }
Chris@0 37
Chris@0 38 /**
Chris@0 39 * Clears all parameters.
Chris@0 40 */
Chris@0 41 public function clear()
Chris@0 42 {
Chris@17 43 $this->parameters = [];
Chris@0 44 }
Chris@0 45
Chris@0 46 /**
Chris@0 47 * Adds parameters to the service container parameters.
Chris@0 48 *
Chris@0 49 * @param array $parameters An array of parameters
Chris@0 50 */
Chris@0 51 public function add(array $parameters)
Chris@0 52 {
Chris@0 53 foreach ($parameters as $key => $value) {
Chris@14 54 $this->set($key, $value);
Chris@0 55 }
Chris@0 56 }
Chris@0 57
Chris@0 58 /**
Chris@0 59 * {@inheritdoc}
Chris@0 60 */
Chris@0 61 public function all()
Chris@0 62 {
Chris@0 63 return $this->parameters;
Chris@0 64 }
Chris@0 65
Chris@0 66 /**
Chris@0 67 * {@inheritdoc}
Chris@0 68 */
Chris@0 69 public function get($name)
Chris@0 70 {
Chris@14 71 $name = $this->normalizeName($name);
Chris@0 72
Chris@18 73 if (!\array_key_exists($name, $this->parameters)) {
Chris@0 74 if (!$name) {
Chris@0 75 throw new ParameterNotFoundException($name);
Chris@0 76 }
Chris@0 77
Chris@17 78 $alternatives = [];
Chris@0 79 foreach ($this->parameters as $key => $parameterValue) {
Chris@0 80 $lev = levenshtein($name, $key);
Chris@17 81 if ($lev <= \strlen($name) / 3 || false !== strpos($key, $name)) {
Chris@0 82 $alternatives[] = $key;
Chris@0 83 }
Chris@0 84 }
Chris@0 85
Chris@0 86 $nonNestedAlternative = null;
Chris@17 87 if (!\count($alternatives) && false !== strpos($name, '.')) {
Chris@0 88 $namePartsLength = array_map('strlen', explode('.', $name));
Chris@0 89 $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength)));
Chris@17 90 while (\count($namePartsLength)) {
Chris@0 91 if ($this->has($key)) {
Chris@17 92 if (\is_array($this->get($key))) {
Chris@0 93 $nonNestedAlternative = $key;
Chris@0 94 }
Chris@0 95 break;
Chris@0 96 }
Chris@0 97
Chris@0 98 $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength)));
Chris@0 99 }
Chris@0 100 }
Chris@0 101
Chris@0 102 throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative);
Chris@0 103 }
Chris@0 104
Chris@0 105 return $this->parameters[$name];
Chris@0 106 }
Chris@0 107
Chris@0 108 /**
Chris@0 109 * Sets a service container parameter.
Chris@0 110 *
Chris@0 111 * @param string $name The parameter name
Chris@0 112 * @param mixed $value The parameter value
Chris@0 113 */
Chris@0 114 public function set($name, $value)
Chris@0 115 {
Chris@14 116 $this->parameters[$this->normalizeName($name)] = $value;
Chris@0 117 }
Chris@0 118
Chris@0 119 /**
Chris@0 120 * {@inheritdoc}
Chris@0 121 */
Chris@0 122 public function has($name)
Chris@0 123 {
Chris@18 124 return \array_key_exists($this->normalizeName($name), $this->parameters);
Chris@0 125 }
Chris@0 126
Chris@0 127 /**
Chris@0 128 * Removes a parameter.
Chris@0 129 *
Chris@0 130 * @param string $name The parameter name
Chris@0 131 */
Chris@0 132 public function remove($name)
Chris@0 133 {
Chris@14 134 unset($this->parameters[$this->normalizeName($name)]);
Chris@0 135 }
Chris@0 136
Chris@0 137 /**
Chris@0 138 * {@inheritdoc}
Chris@0 139 */
Chris@0 140 public function resolve()
Chris@0 141 {
Chris@0 142 if ($this->resolved) {
Chris@0 143 return;
Chris@0 144 }
Chris@0 145
Chris@17 146 $parameters = [];
Chris@0 147 foreach ($this->parameters as $key => $value) {
Chris@0 148 try {
Chris@0 149 $value = $this->resolveValue($value);
Chris@0 150 $parameters[$key] = $this->unescapeValue($value);
Chris@0 151 } catch (ParameterNotFoundException $e) {
Chris@0 152 $e->setSourceKey($key);
Chris@0 153
Chris@0 154 throw $e;
Chris@0 155 }
Chris@0 156 }
Chris@0 157
Chris@0 158 $this->parameters = $parameters;
Chris@0 159 $this->resolved = true;
Chris@0 160 }
Chris@0 161
Chris@0 162 /**
Chris@0 163 * Replaces parameter placeholders (%name%) by their values.
Chris@0 164 *
Chris@0 165 * @param mixed $value A value
Chris@0 166 * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
Chris@0 167 *
Chris@0 168 * @return mixed The resolved value
Chris@0 169 *
Chris@0 170 * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
Chris@0 171 * @throws ParameterCircularReferenceException if a circular reference if detected
Chris@14 172 * @throws RuntimeException when a given parameter has a type problem
Chris@0 173 */
Chris@17 174 public function resolveValue($value, array $resolving = [])
Chris@0 175 {
Chris@14 176 if (\is_array($value)) {
Chris@17 177 $args = [];
Chris@0 178 foreach ($value as $k => $v) {
Chris@14 179 $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving);
Chris@0 180 }
Chris@0 181
Chris@0 182 return $args;
Chris@0 183 }
Chris@0 184
Chris@14 185 if (!\is_string($value) || 2 > \strlen($value)) {
Chris@0 186 return $value;
Chris@0 187 }
Chris@0 188
Chris@0 189 return $this->resolveString($value, $resolving);
Chris@0 190 }
Chris@0 191
Chris@0 192 /**
Chris@0 193 * Resolves parameters inside a string.
Chris@0 194 *
Chris@0 195 * @param string $value The string to resolve
Chris@0 196 * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
Chris@0 197 *
Chris@0 198 * @return string The resolved string
Chris@0 199 *
Chris@0 200 * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
Chris@0 201 * @throws ParameterCircularReferenceException if a circular reference if detected
Chris@14 202 * @throws RuntimeException when a given parameter has a type problem
Chris@0 203 */
Chris@17 204 public function resolveString($value, array $resolving = [])
Chris@0 205 {
Chris@0 206 // we do this to deal with non string values (Boolean, integer, ...)
Chris@0 207 // as the preg_replace_callback throw an exception when trying
Chris@0 208 // a non-string in a parameter value
Chris@0 209 if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
Chris@0 210 $key = $match[1];
Chris@14 211 $lcKey = strtolower($key); // strtolower() to be removed in 4.0
Chris@0 212
Chris@0 213 if (isset($resolving[$lcKey])) {
Chris@0 214 throw new ParameterCircularReferenceException(array_keys($resolving));
Chris@0 215 }
Chris@0 216
Chris@0 217 $resolving[$lcKey] = true;
Chris@0 218
Chris@0 219 return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
Chris@0 220 }
Chris@0 221
Chris@0 222 return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) {
Chris@0 223 // skip %%
Chris@0 224 if (!isset($match[1])) {
Chris@0 225 return '%%';
Chris@0 226 }
Chris@0 227
Chris@0 228 $key = $match[1];
Chris@14 229 $lcKey = strtolower($key); // strtolower() to be removed in 4.0
Chris@0 230 if (isset($resolving[$lcKey])) {
Chris@0 231 throw new ParameterCircularReferenceException(array_keys($resolving));
Chris@0 232 }
Chris@0 233
Chris@0 234 $resolved = $this->get($key);
Chris@0 235
Chris@17 236 if (!\is_string($resolved) && !is_numeric($resolved)) {
Chris@17 237 throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, \gettype($resolved), $value));
Chris@0 238 }
Chris@0 239
Chris@0 240 $resolved = (string) $resolved;
Chris@0 241 $resolving[$lcKey] = true;
Chris@0 242
Chris@0 243 return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving);
Chris@0 244 }, $value);
Chris@0 245 }
Chris@0 246
Chris@0 247 public function isResolved()
Chris@0 248 {
Chris@0 249 return $this->resolved;
Chris@0 250 }
Chris@0 251
Chris@0 252 /**
Chris@0 253 * {@inheritdoc}
Chris@0 254 */
Chris@0 255 public function escapeValue($value)
Chris@0 256 {
Chris@17 257 if (\is_string($value)) {
Chris@0 258 return str_replace('%', '%%', $value);
Chris@0 259 }
Chris@0 260
Chris@17 261 if (\is_array($value)) {
Chris@17 262 $result = [];
Chris@0 263 foreach ($value as $k => $v) {
Chris@0 264 $result[$k] = $this->escapeValue($v);
Chris@0 265 }
Chris@0 266
Chris@0 267 return $result;
Chris@0 268 }
Chris@0 269
Chris@0 270 return $value;
Chris@0 271 }
Chris@0 272
Chris@0 273 /**
Chris@0 274 * {@inheritdoc}
Chris@0 275 */
Chris@0 276 public function unescapeValue($value)
Chris@0 277 {
Chris@17 278 if (\is_string($value)) {
Chris@0 279 return str_replace('%%', '%', $value);
Chris@0 280 }
Chris@0 281
Chris@17 282 if (\is_array($value)) {
Chris@17 283 $result = [];
Chris@0 284 foreach ($value as $k => $v) {
Chris@0 285 $result[$k] = $this->unescapeValue($v);
Chris@0 286 }
Chris@0 287
Chris@0 288 return $result;
Chris@0 289 }
Chris@0 290
Chris@0 291 return $value;
Chris@0 292 }
Chris@14 293
Chris@14 294 private function normalizeName($name)
Chris@14 295 {
Chris@14 296 if (isset($this->normalizedNames[$normalizedName = strtolower($name)])) {
Chris@14 297 $normalizedName = $this->normalizedNames[$normalizedName];
Chris@14 298 if ((string) $name !== $normalizedName) {
Chris@14 299 @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
Chris@14 300 }
Chris@14 301 } else {
Chris@14 302 $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name;
Chris@14 303 }
Chris@14 304
Chris@14 305 return $normalizedName;
Chris@14 306 }
Chris@0 307 }