Passed
Push — master ( 390b86...897bf5 )
by Jean-Christophe
21:03
created

DiControllerParser::getInjection()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 8.8142

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 20
ccs 10
cts 15
cp 0.6667
rs 8.8333
c 0
b 0
f 0
cc 7
nc 7
nop 4
crap 8.8142
1
<?php
2
3
namespace Ubiquity\controllers\di;
4
5
use Hybridauth\Thirdparty\OpenID\ErrorException;
1 ignored issue
show
Bug introduced by
The type Hybridauth\Thirdparty\OpenID\ErrorException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Ubiquity\orm\parser\Reflexion;
7
use Ubiquity\utils\base\UArray;
8
use Ubiquity\utils\base\UString;
9
use Ubiquity\cache\ClassUtils;
10
use Ubiquity\exceptions\DiException;
11
12
/**
13
 * Parse the controllers for dependency injections.
14
 *
15
 * Ubiquity\controllers\di$DiControllerParser
16
 * This class is part of Ubiquity
17
 *
18
 * @author jcheron <[email protected]>
19
 * @version 1.0.5
20
 * @since Ubiquity 2.1.0
21
 *
22
 */
23
class DiControllerParser {
24
	protected $injections = [ ];
25
26 8
	public function parse($controllerClass, $config) {
27 8
		$properties = Reflexion::getProperties ( $controllerClass );
28 8
		foreach ( $properties as $property ) {
29 8
			$propName = $property->getName ();
30 8
			$annot = Reflexion::getAnnotationMember ( $controllerClass, $propName, 'injected' );
31 8
			if ($annot !== false) {
32 8
				$name = $annot->name;
33 8
				if ($this->isInjectable ( $controllerClass, $propName, false )) {
34 8
					$this->injections [$propName] = $this->getInjection ( $name ?? $propName, $config, $controllerClass, $annot->code ?? null);
35
				}
36
			} else {
37 8
				$annot = Reflexion::getAnnotationMember ( $controllerClass, $propName, 'autowired' );
38 8
				if ($annot !== false) {
39 8
					$type = Reflexion::getPropertyType ( $controllerClass, $propName );
40 8
					if ($type !== false) {
41 8
						if ($this->isInjectable ( $controllerClass, $propName, false )) {
42 8
							if(\is_string($type)){
43 8
								$this->getInjectableAutowired ( $type, $propName );
44 8
							}elseif($type instanceof \ReflectionProperty || $type instanceof \ReflectionNamedType){
45 8
								$this->getInjectableAutowired ( $type->getName (), $propName );
46
							}
47
						}
48
					} else {
49
						throw new DiException ( sprintf ( '%s property has no type and cannot be autowired!', $propName ) );
50
					}
51
				}
52
			}
53
		}
54 8
		$this->scanGlobalDi ( $config ['di'] ?? [ ], $controllerClass );
55
	}
56
57 8
	protected function getInjectableAutowired($type, $propName) {
58 8
		$typeR = new \ReflectionClass ( $type );
59 8
		if ($typeR->isInstantiable ()) {
60 8
			$constructor = $typeR->getConstructor ();
61 8
			$nbParams = $constructor == null ? 0 : $typeR->getConstructor ()->getNumberOfRequiredParameters ();
62 8
			if ($nbParams == 0) {
63 8
				$this->injections [$propName] = "function(){return new " . $type . "();}";
64 8
			} elseif ($nbParams == 1) {
65 8
				$this->injections [$propName] = "function(\$controller){return new " . $type . "(\$controller);}";
66
			} else {
67 8
				throw new DiException ( sprintf ( 'Service %s constructor has too many mandatory arguments for %s injection!', $type, $propName ) );
68
			}
69
		} else {
70
			$namespace = $typeR->getNamespaceName ();
71
			$oClass = $namespace . "\\" . ucfirst ( $propName );
72
			if (class_exists ( $oClass )) {
73
				if (is_subclass_of ( $oClass, $type )) {
74
					$this->getInjectableAutowired ( $oClass, $propName );
75
				} else {
76
					throw new DiException ( sprintf ( 'Class %s is not a subclass of %s!', $oClass, $type ) );
77
				}
78
			} else {
79
				throw new DiException ( sprintf ( 'Class %s does not exists!', $oClass ) );
80
			}
81
		}
82
	}
83
84 8
	protected function scanGlobalDi($diConfig, $controller) {
85 8
		$classname = ClassUtils::getClassSimpleName ( $controller );
86 8
		foreach ( $diConfig as $k => $v ) {
87 8
			if (UString::startswith ( $k, "*." ) || UString::startswith ( $k, $classname . "." )) {
88 8
				$dis = explode ( '.', $k );
89 8
				$nkey = end ( $dis );
90 8
				if (property_exists ( $controller, $nkey ) === false) {
91 8
					$this->injections [$nkey] = $v;
92
				}
93
			}
94
		}
95
	}
96
97 8
	protected function isInjectable($classname, $member, $silent = true) {
98 8
		if (\property_exists($classname, $member)) {
99 8
			$prop = new \ReflectionProperty ($classname, $member);
100 8
			if ($prop->isPublic()) {
101 8
				return true;
102
			}
103
		}
104 8
		$setter = 'set' . ucfirst ( $member );
105 8
		if (\method_exists ( $classname, $setter )) {
106 8
			return true;
107
		}
108
		if (! $silent) {
109
			throw new DiException ( sprintf ( '%s member must be public or have a setter to be injected in the class %s!', $member, $classname ) );
110
		}
111
		return false;
112
	}
113
114 8
	protected function getInjection($name, $config, $controller, $code = null) {
115 8
		if ($code != null) {
116
			return "function(\$controller){return " . $code . ";}";
117
		}
118 8
		if (isset ( $config ["di"] )) {
119 8
			$di = $config ['di'];
120 8
			if ($name != null) {
121 8
				$classname = ClassUtils::getClassSimpleName ( $controller );
122 8
				if (isset ( $di [$name] )) {
123
					return $di [$name];
124 8
				} elseif (isset ( $di [$classname . '.' . $name] )) {
125
					return $di [$classname . '.' . $name];
126 8
				} elseif (isset ( $di ['*.' . $name] )) {
127 8
					return $di ['*.' . $name];
128
				} else {
129
					throw new \Exception ( "key " . $name . " is not present in config di array" );
130
				}
131
			}
132
		} else {
133
			throw new \Exception ( "key di is not present in config array" );
134
		}
135
	}
136
137
	public function __toString() {
138
		return "return " . UArray::asPhpArray ( $this->injections, "array" ) . ";";
139
	}
140
141
	/**
142
	 *
143
	 * @return array
144
	 */
145 8
	public function getInjections() {
146 8
		return $this->injections;
147
	}
148
}
149
150