AclControllerParser::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 2
ccs 2
cts 2
cp 1
crap 1
rs 10
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.3
16
 *
17
 */
18
class AclControllerParser {
19
	
20
	protected $controllerClass;
21
	
22
	protected $mainResource;
23
	
24
	protected $mainPermission;
25
	
26
	protected $permissionMap;
27
	
28 2
	public function __construct() {
29 2
		$this->permissionMap = new PermissionsMap();
30
	}
31
	
32
	public function init() {
33
		$this->permissionMap->init();
34
	}
35
	
36 2
	public function parse($controllerClass) {
37 2
		$this->controllerClass = $controllerClass;
38 2
		$reflect = new \ReflectionClass($controllerClass);
39 2
		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) {
40
			try {
41 2
				$annotsResource = Reflexion::getAnnotationClass($controllerClass, 'resource');
42 2
				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, 'permission');
43 2
				$annotAllows = Reflexion::getAnnotationClass($controllerClass, 'allow');
44
			} catch (\Exception $e) {
45
				// When controllerClass generates an exception
46
			}
47 2
			$this->mainResource = $annotsResource[0] ?? null;
48 2
			$this->mainPermission = $annotsPermission[0] ?? null;
49 2
			if (\is_array($annotAllows) && \count($annotAllows) > 0) {
50
				$resource = $this->mainResource ? $this->mainResource->name : $reflect->getShortName();
51
				$permission = $this->mainPermission ? $this->mainPermission->name : 'ALL';
52
				$this->addAllows($annotAllows, $controllerClass, null, $resource, $permission);
53
				$this->permissionMap->addAction($controllerClass, '*', $resource, $permission);
54
			}
55 2
			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC);
56 2
			$this->parseMethods($methods);
57
		}
58
	}
59
	
60 2
	protected function parseMethods($methods) {
61 2
		$hasPermission = false;
62 2
		$controllerClass = $this->controllerClass;
63 2
		$controller = ClassUtils::getClassSimpleName($controllerClass);
64 2
		foreach ($methods as $method) {
65 2
			$this->parseMethod($method, $hasPermission, $controller);
66
		}
67 2
		if ($hasPermission || $this->mainResource != null || $this->mainPermission != null) {
68 2
			$permission = 'ALL';
69 2
			$resource = $this->mainResource ? $this->mainResource->name : $controller;
70 2
			$this->permissionMap->addAction($controllerClass, '*', $resource, $this->mainPermission ? $this->mainPermission->name : 'ALL');
71 2
			AclManager::addResource($resource, $controller . '.*');
72 2
			if (isset($this->mainPermission)) {
73
				$permission = $this->mainPermission->name;
74
				AclManager::addPermission($this->mainPermission->name, ($this->mainPermission->level) ?? 0);
75
			}
76 2
			$annotsAllow = Reflexion::getAnnotationClass($controllerClass, 'allow');
77 2
			if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
78
				$this->addAllows($annotsAllow, $controller, '*', $resource, $permission);
79
			}
80
		}
81
	}
82
	
83 2
	protected function parseMethod(\ReflectionMethod $method, bool &$hasPermission, $controller) {
84 2
		$action = $method->name;
85 2
		$permission = NULL;
86 2
		$resource = NULL;
87 2
		$controllerClass = $this->controllerClass;
88 2
		if ($method->getDeclaringClass()->getName() === $controllerClass) {
89
			try {
90 2
				$annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, 'resource');
91 2
				$annotPermission = Reflexion::getAnnotationMethod($controllerClass, $action, 'permission');
92 2
				if ($annotResource) {
93 2
					$resource = $annotResource->name;
94 2
					AclManager::addResource($annotResource->name, $controller . '.' . $action);
95
				}
96 2
				if ($annotPermission) {
97 2
					if(\is_int($annotPermission->name) && $annotPermission->level===0){
98
						$annotPermission->level=$annotPermission->name;
99
						$annotPermission->name=null;
100
					}
101 2
					$permission = $annotPermission->name??\strtoupper($action);
102 2
					AclManager::addPermission($permission, $annotPermission->level ?? 0);
103 2
					$hasPermission = true;
104
				}
105 2
				$resource ??= $this->mainResource ? $this->mainResource->name : ($controller . '.' . $action);
106
				
107 2
				$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, 'allow');
108 2
				if (\is_array($annotsAllow) && \count($annotsAllow) > 0) {
109 2
					$this->addAllows($annotsAllow, $controller, $action, $resource, $permission);
110 2
					$this->permissionMap->addAction($controllerClass, $action, $resource, $permission ?? 'ALL');
111 2
				} elseif ($permission !== null && $resource !== null) {
112 2
					$this->permissionMap->addAction($controllerClass, $action, $resource, $permission ?? 'ALL');
113
				}
114
			} catch (\Exception $e) {
115
				// Exception in controller code
116
			}
117
		}
118
	}
119
	
120 2
	protected function addAllows($annotsAllow, $controller, $action, &$resource, &$permission) {
121 2
		foreach ($annotsAllow as $annotAllow) {
122 2
			if (isset($annotAllow->resource) && isset($resource) && \strpos($resource, '.') === FALSE && $resource !== $annotAllow->resource && $permission != null) {
123
				throw new AclException("Resources {$resource} and {$annotAllow->resource} are in conflict for action {$controller}.{$action}");
124
			}
125 2
			if (isset($annotAllow->permission) && isset($permission) && $permission !== $annotAllow->permission) {
126
				throw new AclException("Permissions {$permission} and {$annotAllow->permission} are in conflict for action {$controller}.{$action}");
127
			}
128
			
129 2
			$resource = ($annotAllow->resource ?? $resource)??$controller . '.' . $action;
130 2
			$permission = ($annotAllow->permission ?? $permission)??\strtoupper($action);
131
			
132 2
			if (\is_array($annotAllow->role)) {
133
				foreach ($annotAllow->role as $role) {
134
					AclManager::addAndAllow($role, $resource, $permission);
135
				}
136
			} else {
137 2
				AclManager::addAndAllow($annotAllow->role, $resource, $permission);
138
			}
139
		}
140
	}
141
	
142 2
	public function save() {
143 2
		$this->permissionMap->save();
144 2
		AclManager::saveAll();
145
	}
146
147
	public function cacheUpdated(): bool {
148
		if ($this->permissionMap->cacheUpdated()) {
149
			return true;
150
		}
151
		return AclManager::cacheUpdated();
152
	}
153
}
154
155