Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6ac7b50

Browse filesBrowse files
bug #26355 [DI] Fix missing "id" normalization when dumping the container (nicolas-grekas)
This PR was merged into the 3.4 branch. Discussion ---------- [DI] Fix missing "id" normalization when dumping the container | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #26306 | License | MIT | Doc PR | - Commits ------- 4a5e43e [DI] Fix missing "id" normalization when dumping the container
2 parents 8f1a6b5 + 4a5e43e commit 6ac7b50
Copy full SHA for 6ac7b50
Expand file treeCollapse file tree

17 files changed

+76
-43
lines changed

‎src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php
+8-7Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public function process(ContainerBuilder $container)
6464
$this->lazy = false;
6565

6666
foreach ($container->getAliases() as $id => $alias) {
67-
$this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null);
67+
$targetId = $this->getDefinitionId((string) $alias);
68+
$this->graph->connect($id, $alias, $targetId, $this->getDefinition($targetId), null);
6869
}
6970

7071
parent::process($container);
@@ -87,12 +88,13 @@ protected function processValue($value, $isRoot = false)
8788
return $value;
8889
}
8990
if ($value instanceof Reference) {
90-
$targetDefinition = $this->getDefinition((string) $value);
91+
$targetId = $this->getDefinitionId((string) $value);
92+
$targetDefinition = $this->getDefinition($targetId);
9193

9294
$this->graph->connect(
9395
$this->currentId,
9496
$this->currentDefinition,
95-
$this->getDefinitionId((string) $value),
97+
$targetId,
9698
$targetDefinition,
9799
$value,
98100
$this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
@@ -134,8 +136,6 @@ protected function processValue($value, $isRoot = false)
134136
*/
135137
private function getDefinition($id)
136138
{
137-
$id = $this->getDefinitionId($id);
138-
139139
return null === $id ? null : $this->container->getDefinition($id);
140140
}
141141

@@ -149,7 +149,7 @@ private function getDefinitionId($id)
149149
return;
150150
}
151151

152-
return $id;
152+
return $this->container->normalizeId($id);
153153
}
154154

155155
private function getExpressionLanguage()
@@ -163,11 +163,12 @@ private function getExpressionLanguage()
163163
$this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
164164
if ('""' === substr_replace($arg, '', 1, -1)) {
165165
$id = stripcslashes(substr($arg, 1, -1));
166+
$id = $this->getDefinitionId($id);
166167

167168
$this->graph->connect(
168169
$this->currentId,
169170
$this->currentDefinition,
170-
$this->getDefinitionId($id),
171+
$id,
171172
$this->getDefinition($id)
172173
);
173174
}

‎src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ private function getAutowiredReference(TypedReference $reference, $deprecationMe
281281
$this->lastFailure = null;
282282
$type = $reference->getType();
283283

284-
if ($type !== (string) $reference || ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract())) {
284+
if ($type !== $this->container->normalizeId($reference) || ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract())) {
285285
return $reference;
286286
}
287287

‎src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function process(ContainerBuilder $container)
5050
$alias = $container->getAlias($inner);
5151
$public = $alias->isPublic();
5252
$private = $alias->isPrivate();
53-
$container->setAlias($renamedId, new Alias((string) $alias, false));
53+
$container->setAlias($renamedId, new Alias($container->normalizeId($alias), false));
5454
} else {
5555
$decoratedDefinition = $container->getDefinition($inner);
5656
$definition->setTags(array_merge($decoratedDefinition->getTags(), $definition->getTags()));

‎src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php
+7-7Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,12 @@ public function process(ContainerBuilder $container)
5151
private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $resolveClassPassChanges, array $previous = array())
5252
{
5353
// circular reference
54-
$lcId = strtolower($id);
55-
if (isset($previous[$lcId])) {
54+
if (isset($previous[$id])) {
5655
return;
5756
}
5857

5958
$factory = $definition->getFactory();
60-
if (null === $factory || (!isset($resolveClassPassChanges[$lcId]) && null !== $definition->getClass())) {
59+
if (null === $factory || (!isset($resolveClassPassChanges[$id]) && null !== $definition->getClass())) {
6160
return;
6261
}
6362

@@ -73,9 +72,10 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $
7372
}
7473
} else {
7574
if ($factory[0] instanceof Reference) {
76-
$previous[$lcId] = true;
77-
$factoryDefinition = $container->findDefinition((string) $factory[0]);
78-
$this->updateDefinition($container, $factory[0], $factoryDefinition, $resolveClassPassChanges, $previous);
75+
$previous[$id] = true;
76+
$factoryId = $container->normalizeId($factory[0]);
77+
$factoryDefinition = $container->findDefinition($factoryId);
78+
$this->updateDefinition($container, $factoryId, $factoryDefinition, $resolveClassPassChanges, $previous);
7979
$class = $factoryDefinition->getClass();
8080
} else {
8181
$class = $factory[0];
@@ -103,7 +103,7 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $
103103
}
104104
}
105105

106-
if (null !== $returnType && (!isset($resolveClassPassChanges[$lcId]) || $returnType !== $resolveClassPassChanges[$lcId])) {
106+
if (null !== $returnType && (!isset($resolveClassPassChanges[$id]) || $returnType !== $resolveClassPassChanges[$id])) {
107107
@trigger_error(sprintf('Relying on its factory\'s return-type to define the class of service "%s" is deprecated since Symfony 3.3 and won\'t work in 4.0. Set the "class" attribute to "%s" on the service definition instead.', $id, $returnType), E_USER_DEPRECATED);
108108
}
109109
$definition->setClass($returnType);

‎src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ protected function processValue($value, $isRoot = false)
6767
$value = clone $value;
6868
}
6969

70-
if (!$value instanceof Reference || !$this->container->hasDefinition($id = (string) $value)) {
70+
if (!$value instanceof Reference || !$this->container->hasDefinition($id = $this->container->normalizeId($value))) {
7171
return parent::processValue($value, $isRoot);
7272
}
7373

‎src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ protected function processValue($value, $isRoot = false)
8585
$serviceMap[$key] = new Reference($type);
8686
}
8787

88-
$subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $declaringClass, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
88+
$subscriberMap[$key] = new TypedReference($this->container->normalizeId($serviceMap[$key]), $type, $declaringClass, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
8989
unset($serviceMap[$key]);
9090
}
9191

‎src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function process(ContainerBuilder $container)
3636
$seenAliasTargets = array();
3737
$replacements = array();
3838
foreach ($container->getAliases() as $definitionId => $target) {
39-
$targetId = (string) $target;
39+
$targetId = $container->normalizeId($target);
4040
// Special case: leave this target alone
4141
if ('service_container' === $targetId) {
4242
continue;
@@ -77,7 +77,7 @@ public function process(ContainerBuilder $container)
7777
*/
7878
protected function processValue($value, $isRoot = false)
7979
{
80-
if ($value instanceof Reference && isset($this->replacements[$referenceId = (string) $value])) {
80+
if ($value instanceof Reference && isset($this->replacements[$referenceId = $this->container->normalizeId($value)])) {
8181
// Perform the replacement
8282
$newId = $this->replacements[$referenceId];
8383
$value = new Reference($newId, $value->getInvalidBehavior());

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function process(ContainerBuilder $container)
4949
*/
5050
protected function processValue($value, $isRoot = false)
5151
{
52-
if ($value instanceof TypedReference && $value->getType() === (string) $value) {
52+
if ($value instanceof TypedReference && $value->getType() === $this->container->normalizeId($value)) {
5353
// Already checked
5454
$bindings = $this->container->getDefinition($this->currentId)->getBindings();
5555

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveHotPathPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveHotPathPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected function processValue($value, $isRoot = false)
5555
if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) {
5656
return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value;
5757
}
58-
if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) {
58+
if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = $this->container->normalizeId($value))) {
5959
$definition = $this->container->findDefinition($id);
6060
if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) {
6161
$this->resolvedIds[$id] = true;

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ private function processValue($value, $rootLevel = 0, $level = 0)
9090
$value = array_values($value);
9191
}
9292
} elseif ($value instanceof Reference) {
93-
$id = (string) $value;
94-
95-
if ($this->container->has($id)) {
93+
if ($this->container->has($value)) {
9694
return $value;
9795
}
9896
$invalidBehavior = $value->getInvalidBehavior();

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function process(ContainerBuilder $container)
3030
parent::process($container);
3131

3232
foreach ($container->getAliases() as $id => $alias) {
33-
$aliasId = (string) $alias;
33+
$aliasId = $container->normalizeId($alias);
3434
if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
3535
$container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate());
3636
}
@@ -43,7 +43,7 @@ public function process(ContainerBuilder $container)
4343
protected function processValue($value, $isRoot = false)
4444
{
4545
if ($value instanceof Reference) {
46-
$defId = $this->getDefinitionId($id = (string) $value, $this->container);
46+
$defId = $this->getDefinitionId($id = $this->container->normalizeId($value), $this->container);
4747

4848
if ($defId !== $id) {
4949
return new Reference($defId, $value->getInvalidBehavior());
@@ -69,7 +69,7 @@ private function getDefinitionId($id, ContainerBuilder $container)
6969
throw new ServiceCircularReferenceException($id, array_keys($seen));
7070
}
7171
$seen[$id] = true;
72-
$id = (string) $container->getAlias($id);
72+
$id = $container->normalizeId($container->getAlias($id));
7373
}
7474

7575
return $id;

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveServiceSubscribersPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveServiceSubscribersPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ResolveServiceSubscribersPass extends AbstractRecursivePass
2626

2727
protected function processValue($value, $isRoot = false)
2828
{
29-
if ($value instanceof Reference && $this->serviceLocator && ContainerInterface::class === (string) $value) {
29+
if ($value instanceof Reference && $this->serviceLocator && ContainerInterface::class === $this->container->normalizeId($value)) {
3030
return new Reference($this->serviceLocator);
3131
}
3232

‎src/Symfony/Component/DependencyInjection/Container.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Container.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ protected function getEnv($name)
507507
*/
508508
public function normalizeId($id)
509509
{
510-
if (!is_string($id)) {
510+
if (!\is_string($id)) {
511511
$id = (string) $id;
512512
}
513513
if (isset($this->normalizedIds[$normalizedId = strtolower($id)])) {

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+16-4Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
627627
*
628628
* @throws BadMethodCallException When this ContainerBuilder is compiled
629629
*/
630-
public function merge(ContainerBuilder $container)
630+
public function merge(self $container)
631631
{
632632
if ($this->isCompiled()) {
633633
throw new BadMethodCallException('Cannot merge on a compiled container.');
@@ -1373,16 +1373,16 @@ public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs
13731373
$value = $bag->resolveValue($value);
13741374
}
13751375

1376-
if (is_array($value)) {
1376+
if (\is_array($value)) {
13771377
$result = array();
13781378
foreach ($value as $k => $v) {
1379-
$result[$this->resolveEnvPlaceholders($k, $format, $usedEnvs)] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs);
1379+
$result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs);
13801380
}
13811381

13821382
return $result;
13831383
}
13841384

1385-
if (!is_string($value)) {
1385+
if (!\is_string($value) || 38 > \strlen($value)) {
13861386
return $value;
13871387
}
13881388
$envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders;
@@ -1455,6 +1455,18 @@ public function log(CompilerPassInterface $pass, $message)
14551455
$this->getCompiler()->log($pass, $message);
14561456
}
14571457

1458+
/**
1459+
* {@inheritdoc}
1460+
*/
1461+
public function normalizeId($id)
1462+
{
1463+
if (!\is_string($id)) {
1464+
$id = (string) $id;
1465+
}
1466+
1467+
return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || isset($this->removedIds[$id]) ? $id : parent::normalizeId($id);
1468+
}
1469+
14581470
/**
14591471
* Returns the Service Conditionals.
14601472
*

‎src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+8-6Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,9 +1232,9 @@ private function addAliases()
12321232
$code = " \$this->aliases = array(\n";
12331233
ksort($aliases);
12341234
foreach ($aliases as $alias => $id) {
1235-
$id = (string) $id;
1235+
$id = $this->container->normalizeId($id);
12361236
while (isset($aliases[$id])) {
1237-
$id = (string) $aliases[$id];
1237+
$id = $this->container->normalizeId($aliases[$id]);
12381238
}
12391239
$code .= ' '.$this->doExport($alias).' => '.$this->doExport($id).",\n";
12401240
}
@@ -1555,7 +1555,7 @@ private function getServiceCallsFromArguments(array $arguments, array &$calls, $
15551555
if (is_array($argument)) {
15561556
$this->getServiceCallsFromArguments($argument, $calls, $isPreInstance, $callerId, $behavior, $step);
15571557
} elseif ($argument instanceof Reference) {
1558-
$id = (string) $argument;
1558+
$id = $this->container->normalizeId($argument);
15591559

15601560
if (!isset($calls[$id])) {
15611561
$calls[$id] = (int) ($isPreInstance && isset($this->circularReferences[$callerId][$id]));
@@ -1625,7 +1625,7 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi
16251625

16261626
continue;
16271627
} elseif ($argument instanceof Reference) {
1628-
$argumentId = (string) $argument;
1628+
$argumentId = $this->container->normalizeId($argument);
16291629
if ($id === $argumentId) {
16301630
return true;
16311631
}
@@ -1790,11 +1790,12 @@ private function dumpValue($value, $interpolate = true)
17901790
} elseif ($value instanceof Variable) {
17911791
return '$'.$value;
17921792
} elseif ($value instanceof Reference) {
1793-
if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) {
1793+
$id = $this->container->normalizeId($value);
1794+
if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) {
17941795
return $this->dumpValue($this->referenceVariables[$id], $interpolate);
17951796
}
17961797

1797-
return $this->getServiceCall((string) $value, $value);
1798+
return $this->getServiceCall($id, $value);
17981799
} elseif ($value instanceof Expression) {
17991800
return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
18001801
} elseif ($value instanceof Parameter) {
@@ -1881,6 +1882,7 @@ private function getServiceCall($id, Reference $reference = null)
18811882
while ($this->container->hasAlias($id)) {
18821883
$id = (string) $this->container->getAlias($id);
18831884
}
1885+
$id = $this->container->normalizeId($id);
18841886

18851887
if ('service_container' === $id) {
18861888
return '$this';

‎src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,16 @@ public function resolve()
173173
*/
174174
public function resolveValue($value, array $resolving = array())
175175
{
176-
if (is_array($value)) {
176+
if (\is_array($value)) {
177177
$args = array();
178178
foreach ($value as $k => $v) {
179-
$args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving);
179+
$args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving);
180180
}
181181

182182
return $args;
183183
}
184184

185-
if (!is_string($value)) {
185+
if (!\is_string($value) || 2 > \strlen($value)) {
186186
return $value;
187187
}
188188

‎src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,26 @@ public function testParameterWithLowerCase()
10011001

10021002
$this->assertSame('bar', $container->getParameter('FOO'));
10031003
}
1004+
1005+
/**
1006+
* @group legacy
1007+
* @expectedDeprecation Service identifiers will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since Symfony 3.3.
1008+
* @expectedDeprecation The "Foo" service is deprecated. You should stop using it, as it will soon be removed.
1009+
*/
1010+
public function testReferenceWithLowerCaseId()
1011+
{
1012+
$container = new ContainerBuilder();
1013+
$container->register('Bar', 'stdClass')->setProperty('foo', new Reference('foo'))->setPublic(true);
1014+
$container->register('Foo', 'stdClass')->setDeprecated();
1015+
$container->compile();
1016+
1017+
$dumper = new PhpDumper($container);
1018+
eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Reference_With_Lower_Case_Id')));
1019+
1020+
$container = new \Symfony_DI_PhpDumper_Test_Reference_With_Lower_Case_Id();
1021+
1022+
$this->assertEquals((object) array('foo' => (object) array()), $container->get('Bar'));
1023+
}
10041024
}
10051025

10061026
class Rot13EnvVarProcessor implements EnvVarProcessorInterface

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.