Passed
Push — master ( 75437d...7ef250 )
by Jean-Christophe
07:19
created

DiControllerParser::isInjectable()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.432

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 13
ccs 7
cts 10
cp 0.7
rs 9.9666
c 0
b 0
f 0
cc 4
nc 4
nop 3
crap 4.432
1
<?php
2
3
namespace Ubiquity\controllers\di;
4
5
use Ubiquity\orm\parser\Reflexion;
6
use Ubiquity\utils\base\UArray;
7
use Ubiquity\utils\base\UString;
8
use Ubiquity\cache\ClassUtils;
9
use Ubiquity\exceptions\DiException;
10
11
/**
12
 * Parse the controllers for dependency injections.
13
 *
14
 * Ubiquity\controllers\di$DiControllerParser
15
 * This class is part of Ubiquity
16
 *
17
 * @author jcheron <[email protected]>
18
 * @version 1.0.0
19
 * @since Ubiquity 2.1.0
20
 *
21
 */
22
class DiControllerParser {
23
	protected $injections = [ ];
24
25 6
	public function parse($controllerClass, $config) {
26 6
		$instance = new $controllerClass ();
27 6
		$properties = Reflexion::getProperties ( $instance );
28 6
		foreach ( $properties as $property ) {
29 6
			$propName = $property->getName ();
30 6
			$annot = Reflexion::getAnnotationMember ( $controllerClass, $propName, "@injected" );
31 6
			if ($annot !== false) {
32 5
				$name = $annot->name;
33 5
				if ($this->isInjectable ( $controllerClass, $name ?? $propName, false )) {
34 5
					$this->injections [$propName] = $this->getInjection ( $name ?? $propName, $config, $controllerClass, $annot->code ?? null);
35
				}
36
			} else {
37 6
				$annot = Reflexion::getAnnotationMember ( $controllerClass, $propName, "@autowired" );
38 6
				if ($annot !== false) {
39 5
					$type = Reflexion::getPropertyType ( $controllerClass, $propName );
40 5
					if ($type !== false) {
41 5
						if ($this->isInjectable ( $controllerClass, $propName, false )) {
42 5
							$typeR = new \ReflectionClass ( $type );
43 5
							$nbParams = $typeR->getConstructor ()->getNumberOfRequiredParameters ();
44 5
							if ($nbParams == 0) {
45 5
								$this->injections [$propName] = "function(\$controller){return new " . $type . "();}";
46
							} elseif ($nbParams == 1) {
47
								$this->injections [$propName] = "function(\$controller){return new " . $type . "(\$controller);}";
48
							} else {
49
								throw new DiException ( sprintf ( 'Service %s constructor has too many mandatory arguments for %s injection!', $type, $propName ) );
50
							}
51
						}
52
					} else {
53
						throw new DiException ( sprintf ( '%s property has no type and cannot be autowired!', $propName ) );
54
					}
55
				}
56
			}
57
		}
58 6
		$this->scanGlobalDi ( $config ['di'] ?? [ ], $controllerClass );
59 6
	}
60
61 6
	protected function scanGlobalDi($diConfig, $controller) {
62 6
		$classname = ClassUtils::getClassSimpleName ( $controller );
63 6
		foreach ( $diConfig as $k => $v ) {
64 6
			if (UString::startswith ( $k, "*." ) || UString::startswith ( $k, $classname . "." )) {
65 6
				$dis = explode ( '.', $k );
66 6
				$nkey = end ( $dis );
67 6
				if (property_exists ( $controller, $nkey ) === false) {
68 6
					$this->injections [$nkey] = $v;
69
				}
70
			}
71
		}
72 6
	}
73
74 5
	protected function isInjectable($classname, $member, $silent = true) {
75 5
		$prop = new \ReflectionProperty ( $classname, $member );
76 5
		if ($prop->isPublic ()) {
77 5
			return true;
78
		}
79 5
		$setter = 'set' . ucfirst ( $member );
80 5
		if (method_exists ( $classname, $setter )) {
81 5
			return true;
82
		}
83
		if (! $silent) {
84
			throw new DiException ( sprintf ( '%s member must be public or have a setter to be injected in the class %s!', $member, $classname ) );
85
		}
86
		return false;
87
	}
88
89 5
	protected function getInjection($name, $config, $controller, $code = null) {
90 5
		if ($code != null) {
91
			return "function(\$controller){return " . $code . ";}";
92
		}
93 5
		if (isset ( $config ["di"] )) {
94 5
			$di = $config ['di'];
95 5
			if ($name != null) {
96 5
				$classname = ClassUtils::getClassSimpleName ( $controller );
97 5
				if (isset ( $di [$name] )) {
98
					return $di [$name];
99 5
				} elseif (isset ( $di [$classname . '.' . $name] )) {
100
					return $di [$classname . '.' . $name];
101 5
				} elseif (isset ( $di ['*.' . $name] )) {
102 5
					return $di ['*.' . $name];
103
				} else {
104
					throw new \Exception ( "key " . $name . " is not present in config di array" );
105
				}
106
			}
107
		} else {
108
			throw new \Exception ( "key di is not present in config array" );
109
		}
110
	}
111
112 6
	public function __toString() {
113 6
		return "return " . UArray::asPhpArray ( $this->injections, "array" ) . ";";
114
	}
115
116
	/**
117
	 *
118
	 * @return array
119
	 */
120 6
	public function getInjections() {
121 6
		return $this->injections;
122
	}
123
}
124
125