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 / Autowiring.php

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

129 lines 5.1 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;
9
10 use Packetery\Nette;
11 /**
12 * Autowiring.
13 */
14 class Autowiring
15 {
16 use \Packetery\Nette\SmartObject;
17 /** @var ContainerBuilder */
18 private $builder;
19 /** @var array[] type => services, used by getByType() */
20 private $highPriority = [];
21 /** @var array[] type => services, used by findByType() */
22 private $lowPriority = [];
23 /** @var string[] of classes excluded from autowiring */
24 private $excludedClasses = [];
25 public function __construct(ContainerBuilder $builder)
26 {
27 $this->builder = $builder;
28 }
29 /**
30 * Resolves service name by type.
31 * @param bool $throw exception if service not found?
32 * @return ($throw is true ? string : ?string)
33 * @throws MissingServiceException when not found
34 * @throws ServiceCreationException when multiple found
35 */
36 public function getByType(string $type, bool $throw = \false) : ?string
37 {
38 $type = Helpers::normalizeClass($type);
39 $types = $this->highPriority;
40 if (empty($types[$type])) {
41 if ($throw) {
42 if (!\class_exists($type) && !\interface_exists($type)) {
43 throw new MissingServiceException(\sprintf("Service of type '%s' not found. Check the class name because it cannot be found.", $type));
44 }
45 throw new MissingServiceException(\sprintf('Service of type %s not found. Did you add it to configuration file?', $type));
46 }
47 return null;
48 } elseif (\count($types[$type]) === 1) {
49 return $types[$type][0];
50 } else {
51 $list = $types[$type];
52 \natsort($list);
53 $hint = \count($list) === 2 && ($tmp = \strpos($list[0], '.') xor \strpos($list[1], '.')) ? '. If you want to overwrite service ' . $list[$tmp ? 0 : 1] . ', give it proper name.' : '';
54 throw new ServiceCreationException(\sprintf("Multiple services of type {$type} found: %s%s", \implode(', ', $list), $hint));
55 }
56 }
57 /**
58 * Gets the service names and definitions of the specified type.
59 * @return Definitions\Definition[] service name is key
60 */
61 public function findByType(string $type) : array
62 {
63 $type = Helpers::normalizeClass($type);
64 $definitions = $this->builder->getDefinitions();
65 $names = \array_merge($this->highPriority[$type] ?? [], $this->lowPriority[$type] ?? []);
66 $res = [];
67 foreach ($names as $name) {
68 $res[$name] = $definitions[$name];
69 }
70 return $res;
71 }
72 /**
73 * @param string[] $types
74 */
75 public function addExcludedClasses(array $types) : void
76 {
77 foreach ($types as $type) {
78 if (\class_exists($type) || \interface_exists($type)) {
79 $type = Helpers::normalizeClass($type);
80 $this->excludedClasses += \class_parents($type) + \class_implements($type) + [$type => $type];
81 }
82 }
83 }
84 public function getClassList() : array
85 {
86 return [$this->lowPriority, $this->highPriority];
87 }
88 public function rebuild() : void
89 {
90 $this->lowPriority = $this->highPriority = $preferred = [];
91 foreach ($this->builder->getDefinitions() as $name => $def) {
92 if (!($type = $def->getType())) {
93 continue;
94 }
95 $autowired = $def->getAutowired();
96 if (\is_array($autowired)) {
97 foreach ($autowired as $k => $autowiredType) {
98 if ($autowiredType === ContainerBuilder::ThisService) {
99 $autowired[$k] = $type;
100 } elseif (!\is_a($type, $autowiredType, \true)) {
101 throw new ServiceCreationException(\sprintf("Incompatible class %s in autowiring definition of service '%s'.", $autowiredType, $name));
102 }
103 }
104 }
105 foreach (\class_parents($type) + \class_implements($type) + [$type] as $parent) {
106 if (!$autowired || isset($this->excludedClasses[$parent])) {
107 continue;
108 } elseif (\is_array($autowired)) {
109 $priority = \false;
110 foreach ($autowired as $autowiredType) {
111 if (\is_a($parent, $autowiredType, \true)) {
112 if (empty($preferred[$parent]) && isset($this->highPriority[$parent])) {
113 $this->lowPriority[$parent] = \array_merge($this->lowPriority[$parent] ?? [], $this->highPriority[$parent]);
114 $this->highPriority[$parent] = [];
115 }
116 $preferred[$parent] = $priority = \true;
117 break;
118 }
119 }
120 } else {
121 $priority = empty($preferred[$parent]);
122 }
123 $list = $priority ? 'highPriority' : 'lowPriority';
124 $this->{$list}[$parent][] = $name;
125 }
126 }
127 }
128 }
129