Test Failed
Push — main ( 9eeb56...a643d6 )
by Jean-Christophe
02:25
created

AclControllerParser::parse()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.0218

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 15
ccs 8
cts 9
cp 0.8889
crap 4.0218
rs 9.9
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 1
	public function __construct() {
29 1
		$this->permissionMap = new PermissionsMap();
30 1
	}
31
32 1
	public function init() {
33 1
		$this->permissionMap->init();
34 1
	}
35
36 1
	protected function parseMethods($methods) {
37 1
		$hasPermission = false;
38 1
		$controllerClass = $this->controllerClass;
39 1
		$controller = ClassUtils::getClassSimpleName($controllerClass);
40 1
		foreach ($methods as $method) {
41 1
			$this->parseMethod($method, $hasPermission);
42 1
		}
43 1
		if ($hasPermission || $this->mainResource != null || $this->mainPermission != null) {
44 1
			$permission = 'ALL';
45
			$resource = $this->mainResource ? $this->mainResource->name : $controller;
46 1
			$this->permissionMap->addAction($controller, '*', $resource, $this->mainPermission ? $this->mainPermission->name : 'ALL');
47 1
			AclManager::addResource($resource, $controller . '.*');
48 1
			if (isset($this->mainPermission)) {
49 1
				$permission = $this->mainPermission->name;
50 1
				AclManager::addPermission($this->mainPermission->name, ($this->mainPermission->level) ?? 0);
51
			}
52 1
			$annotsAllow = Reflexion::getAnnotationClass($controllerClass, '@allow');
53 1
			if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
54
				$this->addAllows($annotsAllow, $controller, '*', $resource, $permission);
55
			}
56
		}
57
	}
58 1
59 1
	protected function parseMethod(\ReflectionMethod $method, bool &$hasPermission) {
60
		$action = $method->name;
61 1
		$permission = 'ALL';
62 1
		$resource = NULL;
63 1
		if ($method->getDeclaringClass()->getName() === $controllerClass) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $controllerClass seems to be never defined.
Loading history...
64
			try {
65
				$annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, '@resource');
66
				$annotPermission = Reflexion::getAnnotationMethod($controllerClass, $action, '@permission');
67
				if ($annotResource) {
68
					$resource = $annotResource->name;
69
					AclManager::addResource($annotResource->name, $controller . '.' . $action);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $controller seems to be never defined.
Loading history...
70 1
				}
71 1
				$resource ??= $this->mainResource ? $this->mainResource->name : $controller . '.' . $action;
72 1
				if ($annotPermission) {
73 1
					$permission = $annotPermission->name;
74 1
					AclManager::addPermission($annotPermission->name, $annotPermission->level);
75 1
					$hasPermission = true;
76
					$this->permissionMap->addAction($controller, $action, $resource, $annotPermission->name);
77
				} elseif ($annotResource) {
78
					$this->permissionMap->addAction($controller, $action, $resource, 'ALL');
79 1
				}
80 1
				$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, '@allow');
81
				if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
82
					$this->addAllows($annotsAllow, $controller, $action, $resource, $permission);
83
				}
84 1
			} catch (\Exception $e) {
85
				// Exception in controller code
86
			}
87
		}
88
	}
89
90
	protected function addAllows($annotsAllow, $controller, $action, $resource, $permission) {
91
		foreach ($annotsAllow as $annotAllow) {
92
			if (isset($annotAllow->resource) && isset($resource) && $resource !== $annotAllow->resource) {
93
				throw new AclException("Resources {$resource} and {$annotAllow->resource} are in conflict for action {$controller}.{$action}");
94
			}
95
			if (isset($annotAllow->permission) && isset($permission) && $permission !== $annotAllow->permission) {
96
				throw new AclException("Permissions {$permission} and {$annotAllow->permission} are in conflict for action {$controller}.{$action}");
97
			}
98 1
			AclManager::addAndAllow($annotAllow->role, $annotAllow->resource ?? $resource, $annotAllow->permission ?? $permission);
99 1
		}
100 1
	}
101 1
102
	public function parse($controllerClass) {
103 1
		$this->controllerClass = $controllerClass;
104 1
		$reflect = new \ReflectionClass($controllerClass);
105
		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) {
106
			try {
107
				$annotsResource = Reflexion::getAnnotationClass($controllerClass, '@resource');
108 1
				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, '@permission');
109 1
			} catch (\Exception $e) {
110
				// When controllerClass generates an exception
111 1
			}
112 1
			$this->mainResource = $annotsResource[0] ?? null;
113
			$this->mainPermission = $annotsPermission[0] ?? null;
114 1
115
			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC);
116 1
			$this->parseMethods($methods);
117 1
		}
118 1
	}
119 1
120
	public function save() {
121
		$this->permissionMap->save();
122
		AclManager::saveAll();
123
	}
124
}
125
126