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 / Definitions / LocatorDefinition.php

LocatorDefinition.php in Packeta trunk, at deps/nette/di/src/DI/Definitions/LocatorDefinition.php

122 lines 5.5 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\Definitions;
9
10 use Packetery\Nette;
11 /**
12 * Multi accessor/factory definition.
13 */
14 final class LocatorDefinition extends Definition
15 {
16 /** @var Reference[] */
17 private $references = [];
18 /** @var string|null */
19 private $tagged;
20 /** @return static */
21 public function setImplement(string $interface)
22 {
23 if (!\interface_exists($interface)) {
24 throw new \Packetery\Nette\InvalidArgumentException(\sprintf("Service '%s': Interface '%s' not found.", $this->getName(), $interface));
25 }
26 $methods = (new \ReflectionClass($interface))->getMethods();
27 if (!$methods) {
28 throw new \Packetery\Nette\InvalidArgumentException(\sprintf("Service '%s': Interface %s must have at least one method.", $this->getName(), $interface));
29 }
30 foreach ($methods as $method) {
31 if ($method->isStatic() || !(\preg_match('#^(get|create)$#', $method->name) && $method->getNumberOfParameters() === 1 || \preg_match('#^(get|create)[A-Z]#', $method->name) && $method->getNumberOfParameters() === 0)) {
32 throw new \Packetery\Nette\InvalidArgumentException(\sprintf("Service '%s': Method %s::%s() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static.", $this->getName(), $interface, $method->name));
33 }
34 if ($method->getNumberOfParameters() === 0) {
35 try {
36 \Packetery\Nette\DI\Helpers::ensureClassType(\Packetery\Nette\Utils\Type::fromReflection($method), "return type of {$interface}::{$method->name}()", \true);
37 } catch (\Packetery\Nette\DI\ServiceCreationException $e) {
38 \trigger_error($e->getMessage(), \E_USER_DEPRECATED);
39 }
40 }
41 }
42 return parent::setType($interface);
43 }
44 public function getImplement() : ?string
45 {
46 return $this->getType();
47 }
48 /** @return static */
49 public function setReferences(array $references)
50 {
51 $this->references = [];
52 foreach ($references as $name => $ref) {
53 $this->references[$name] = \substr($ref, 0, 1) === '@' ? new Reference(\substr($ref, 1)) : Reference::fromType($ref);
54 }
55 return $this;
56 }
57 /** @return Reference[] */
58 public function getReferences() : array
59 {
60 return $this->references;
61 }
62 /** @return static */
63 public function setTagged(?string $tagged)
64 {
65 $this->tagged = $tagged;
66 return $this;
67 }
68 public function getTagged() : ?string
69 {
70 return $this->tagged;
71 }
72 public function resolveType(\Packetery\Nette\DI\Resolver $resolver) : void
73 {
74 }
75 public function complete(\Packetery\Nette\DI\Resolver $resolver) : void
76 {
77 if ($this->tagged !== null) {
78 $this->references = [];
79 foreach ($resolver->getContainerBuilder()->findByTag($this->tagged) as $name => $tag) {
80 if (isset($this->references[$tag])) {
81 \trigger_error(\sprintf("Service '%s': duplicated tag '%s' with value '%s'.", $this->getName(), $this->tagged, $tag));
82 }
83 $this->references[$tag] = new Reference($name);
84 }
85 }
86 foreach ($this->references as $name => $ref) {
87 $this->references[$name] = $resolver->normalizeReference($ref);
88 }
89 }
90 public function generateMethod(\Packetery\Nette\PhpGenerator\Method $method, \Packetery\Nette\DI\PhpGenerator $generator) : void
91 {
92 $class = (new \Packetery\Nette\PhpGenerator\ClassType())->addImplement($this->getType());
93 $class->addProperty('container')->setPrivate();
94 $class->addMethod('__construct')->addBody('$this->container = $container;')->addParameter('container')->setType($generator->getClassName());
95 foreach ((new \ReflectionClass($this->getType()))->getMethods() as $rm) {
96 \preg_match('#^(get|create)(.*)#', $rm->name, $m);
97 $name = \lcfirst($m[2]);
98 $nullable = $rm->getReturnType()->allowsNull();
99 $methodInner = $class->addMethod($rm->name)->setReturnType((string) \Packetery\Nette\Utils\Type::fromReflection($rm));
100 if (!$name) {
101 $class->addProperty('mapping', \array_map(function ($item) {
102 return $item->getValue();
103 }, $this->references))->setPrivate();
104 $methodInner->setBody('if (!isset($this->mapping[$name])) {
105 ' . ($nullable ? 'return null;' : 'throw new \\Packetery\\Nette\\DI\\MissingServiceException("Service \'$name\' is not defined.");') . '
106 }
107 return $this->container->' . $m[1] . 'Service($this->mapping[$name]);')->addParameter('name');
108 } elseif (isset($this->references[$name])) {
109 $ref = $this->references[$name]->getValue();
110 if ($m[1] === 'get') {
111 $methodInner->setBody('return $this->container->getService(?);', [$ref]);
112 } else {
113 $methodInner->setBody('return $this->container->?();', [\Packetery\Nette\DI\Container::getMethodName($ref)]);
114 }
115 } else {
116 $methodInner->setBody($nullable ? 'return null;' : 'throw new \\Packetery\\Nette\\DI\\MissingServiceException("Service is not defined.");');
117 }
118 }
119 $method->setBody('return new class ($this) ' . $class . ';');
120 }
121 }
122