Test Failed
Push — main ( dff987...173a16 )
by Jean-Christophe
02:20
created

AclControllerParser   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Test Coverage

Coverage 90.54%

Importance

Changes 4
Bugs 0 Features 1
Metric Value
eloc 73
c 4
b 0
f 1
dl 0
loc 116
ccs 67
cts 74
cp 0.9054
rs 8.96
wmc 43

7 Methods

Rating   Name   Duplication   Size   Complexity  
B parseMethods() 0 19 10
A __construct() 0 2 1
A init() 0 2 1
B parseMethod() 0 29 11
B addAllows() 0 12 11
A save() 0 3 1
B parse() 0 20 8

How to fix   Complexity   

Complex Class

Complex classes like AclControllerParser often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AclControllerParser, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Ubiquity\security\acl\cache;
3
4
use Ubiquity\controllers\Controller;
5
use Ubiquity\orm\parser\Reflexion;
6
use Ubiquity\security\acl\AclManager;
7
use Ubiquity\cache\ClassUtils;
8
use Ubiquity\exceptions\AclException;
9
10
/**
11
 * Ubiquity\security\acl\cache$AclControllerParser
12
 * This class is part of Ubiquity
13
 *
14
 * @author jc
15
 * @version 1.0.0
16
 *
17
 */
18
class AclControllerParser {
19
20
	protected $controllerClass;
21
22
	protected $mainResource;
23
24
	protected $mainPermission;
25
26
	protected $permissionMap;
27
28
	public function __construct() {
29
		$this->permissionMap = new PermissionsMap();
30 3
	}
31 3
32 3
	public function init() {
33
		$this->permissionMap->init();
34 3
	}
35 3
36 3
	protected function parseMethods($methods) {
37
		$hasPermission = false;
38 3
		$controllerClass = $this->controllerClass;
39 3
		$controller = ClassUtils::getClassSimpleName($controllerClass);
40 3
		foreach ($methods as $method) {
41 3
			$this->parseMethod($method, $hasPermission, $controller);
42 3
		}
43 3
		if ($hasPermission || $this->mainResource != null || $this->mainPermission != null) {
44
			$permission = 'ALL';
45 3
			$resource = $this->mainResource ? $this->mainResource->name : $controller;
46 3
			$this->permissionMap->addAction($controller, '*', $resource, $this->mainPermission ? $this->mainPermission->name : 'ALL');
47 3
			AclManager::addResource($resource, $controller . '.*');
48 3
			if (isset($this->mainPermission)) {
49 3
				$permission = $this->mainPermission->name;
50 3
				AclManager::addPermission($this->mainPermission->name, ($this->mainPermission->level) ?? 0);
51
			}
52
			$annotsAllow = Reflexion::getAnnotationClass($controllerClass, '@allow');
53
			if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
54 3
				$this->addAllows($annotsAllow, $controller, '*', $resource, $permission);
55 3
			}
56
		}
57
	}
58
59 3
	protected function parseMethod(\ReflectionMethod $method, bool &$hasPermission, $controller) {
60
		$action = $method->name;
61 3
		$permission = NULL;
62 3
		$resource = NULL;
63 3
		$controllerClass = $this->controllerClass;
64 3
		if ($method->getDeclaringClass()->getName() === $controllerClass) {
65 3
			try {
66 3
				$annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, '@resource');
67
				$annotPermission = Reflexion::getAnnotationMethod($controllerClass, $action, '@permission');
68 3
				if ($annotResource) {
69 3
					$resource = $annotResource->name;
70 3
					AclManager::addResource($annotResource->name, $controller . '.' . $action);
71 3
				}
72 3
				if ($annotPermission) {
73
					$permission = $annotPermission->name;
74 3
					AclManager::addPermission($annotPermission->name, $annotPermission->level ?? 0);
75 3
					$resource ??= $this->mainResource ? $this->mainResource->name : NULL;
76 3
					$hasPermission = true;
77 3
				} else {
78 3
					$resource ??= $this->mainResource ? $this->mainResource->name : ($controller . '.' . $action);
79
				}
80 3
				$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, '@allow');
81
				if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
82 3
					$this->addAllows($annotsAllow, $controller, $action, $resource, $permission);
83 3
				}
84 3
				if ($permission !== null && $resource !== null) {
85
					$this->permissionMap->addAction($controllerClass, $action, $resource, $permission);
86 3
				}
87 3
			} catch (\Exception $e) {
88
				// Exception in controller code
89
			}
90
		}
91
	}
92
93 3
	protected function addAllows($annotsAllow, $controller, $action, &$resource, &$permission) {
94
		foreach ($annotsAllow as $annotAllow) {
95 3
			if (isset($annotAllow->resource) && isset($resource) && $resource !== $annotAllow->resource && $permission != null) {
96 3
				throw new AclException("Resources {$resource} and {$annotAllow->resource} are in conflict for action {$controller}.{$action}");
97 3
			}
98
			if (isset($annotAllow->permission) && isset($permission) && $permission !== $annotAllow->permission) {
99
				throw new AclException("Permissions {$permission} and {$annotAllow->permission} are in conflict for action {$controller}.{$action}");
100 3
			}
101
			if ($permission === null && $annotAllow->permission === null) {
102
				$resource = $controller . '.' . $action;
103 3
			}
104 3
			AclManager::addAndAllow($annotAllow->role, $resource = $annotAllow->resource ?? $resource, $permission = $annotAllow->permission ?? $permission);
105
		}
106 3
	}
107
108 3
	public function parse($controllerClass) {
109
		$this->controllerClass = $controllerClass;
110 3
		$reflect = new \ReflectionClass($controllerClass);
111 3
		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) {
112 3
			try {
113 3
				$annotsResource = Reflexion::getAnnotationClass($controllerClass, '@resource');
114
				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, '@permission');
115 3
				$annotAllows = Reflexion::getAnnotationClass($controllerClass, '@allow');
116 3
			} catch (\Exception $e) {
117
				// When controllerClass generates an exception
118
			}
119
			$this->mainResource = $annotsResource[0] ?? null;
120 3
			$this->mainPermission = $annotsPermission[0] ?? null;
121 3
			if (\is_array($annotAllows) && \count($annotAllows) > 0) {
122
				$resource = $this->mainResource ? $this->mainResource->name : $reflect->getShortName();
123 3
				$permission = $this->mainPermission ? $this->mainPermission->name : 'ALL';
124 3
				$this->addAllows($annotAllows, $controllerClass, null, $resource, $permission);
125
			}
126 3
			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC);
127
			$this->parseMethods($methods);
128 3
		}
129 3
	}
130 3
131 3
	public function save() {
132
		$this->permissionMap->save();
133
		AclManager::saveAll();
134
	}
135
}
136
137