Passed
Push — main ( 610fba...dd0d39 )
by Jean-Christophe
02:42
created

AclControllerParser::parseMethod()   B

Complexity

Conditions 10
Paths 132

Size

Total Lines 29
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 10.7998

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 25
c 1
b 0
f 0
nc 132
nop 3
dl 0
loc 29
ccs 20
cts 25
cp 0.8
crap 10.7998
rs 7.4

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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