Test Failed
Push — master ( f5c3bd...75437d )
by Jean-Christophe
09:25
created

DiControllerParser::parse()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7.0071

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 26
ccs 18
cts 19
cp 0.9474
rs 8.8333
c 0
b 0
f 0
cc 7
nc 7
nop 2
crap 7.0071
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
					$this->injections [$propName] = $this->getInjection ( $name ?? $propName, $config, $controllerClass, $annot->code ?? null);
35 6
				}
36 6
			} else {
37 5
				$annot = Reflexion::getAnnotationMember ( $controllerClass, $propName, "@autowired" );
38 5
				if ($annot !== false) {
39 5
					$type = Reflexion::getPropertyType ( $controllerClass, $propName );
40
					if ($type !== false) {
41
						if ($this->isInjectable ( $controllerClass, $propName, false )) {
42
							$this->injections [$propName] = "function(\$controller){return new " . $type . "();}";
43
						}
44
					} else {
45
						throw new DiException ( sprintf ( '%s property has no type and cannot be autowired!', $propName ) );
46 6
					}
47 6
				}
48
			}
49 6
		}
50 6
		$this->scanGlobalDi ( $config ['di'] ?? [ ], $controllerClass );
51 6
	}
52 6
53 6
	protected function scanGlobalDi($diConfig, $controller) {
54 6
		$classname = ClassUtils::getClassSimpleName ( $controller );
55 6
		foreach ( $diConfig as $k => $v ) {
56 6
			if (UString::startswith ( $k, "*." ) || UString::startswith ( $k, $classname . "." )) {
57
				$dis = explode ( '.', $k );
58
				$nkey = end ( $dis );
59
				if (property_exists ( $controller, $nkey ) === false) {
60 6
					$this->injections [$nkey] = $v;
61
				}
62 5
			}
63 5
		}
64
	}
65
66 5
	protected function isInjectable($classname, $member, $silent = true) {
67 5
		$prop = new \ReflectionProperty ( $classname, $member );
68 5
		if ($prop->isPublic ()) {
69 5
			return true;
70 5
		}
71
		$setter = 'set' . ucfirst ( $member );
72 5
		if (method_exists ( $classname, $setter )) {
73
			return true;
74 5
		}
75 5
		if (! $silent) {
76
			throw new DiException ( sprintf ( '%s member must be public or have a setter to be injected in the class %s!', $member, $classname ) );
77
		}
78
		return false;
79
	}
80
81
	protected function getInjection($name, $config, $controller, $code = null) {
82
		if ($code != null) {
83
			return "function(\$controller){return " . $code . ";}";
84
		}
85 6
		if (isset ( $config ["di"] )) {
86 6
			$di = $config ['di'];
87
			if ($name != null) {
88
				$classname = ClassUtils::getClassSimpleName ( $controller );
89
				if (isset ( $di [$name] )) {
90
					return $di [$name];
91
				} elseif (isset ( $di [$classname . '.' . $name] )) {
92
					return $di [$classname . '.' . $name];
93 6
				} elseif (isset ( $di ['*.' . $name] )) {
94 6
					return $di ['*.' . $name];
95
				} else {
96
					throw new \Exception ( "key " . $name . " is not present in config di array" );
97
				}
98
			}
99
		} else {
100
			throw new \Exception ( "key di is not present in config array" );
101
		}
102
	}
103
104
	public function __toString() {
105
		return "return " . UArray::asPhpArray ( $this->injections, "array" ) . ";";
106
	}
107
108
	/**
109
	 *
110
	 * @return array
111
	 */
112
	public function getInjections() {
113
		return $this->injections;
114
	}
115
}
116
117