Test Failed
Push — main ( 573841...5a0b4f )
by Jean-Christophe
06:17
created

AclControllerParser::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

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
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\annotations\acl\ResourceAnnotation;
7
use Ubiquity\security\acl\AclManager;
8
use Ubiquity\cache\ClassUtils;
9
use Ubiquity\exceptions\AclException;
10
use Ubiquity\security\acl\persistence\AclCacheProvider;
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
	public function __construct() {
31
		$this->permissionMap = new PermissionsMap();
32
	}
33
34
	public function init() {
35
		$this->permissionMap->init();
36
	}
37
38
	protected function parseMethods($methods) {
39
		$hasPermission = false;
40
		$controllerClass = $this->controllerClass;
41
		$controller = ClassUtils::getClassSimpleName($controllerClass);
42
		foreach ($methods as $method) {
43
			$action = $method->name;
44
			$permission = 'ALL';
45
			if ($method->getDeclaringClass()->getName() === $controllerClass) {
46
				try {
47
					$annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, '@resource');
0 ignored issues
show
Bug introduced by
The method getAnnotationMethod() does not exist on Ubiquity\orm\parser\Reflexion. Did you maybe mean getAnnotationsMethod()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

47
					/** @scrutinizer ignore-call */ 
48
     $annotResource = Reflexion::getAnnotationMethod($controllerClass, $action, '@resource');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
48
					$annotPermission = Reflexion::getAnnotationMethod($controllerClass, $action, '@permission');
49
					$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $action, '@allow');
0 ignored issues
show
Unused Code introduced by
The assignment to $annotsAllow is dead and can be removed.
Loading history...
50
					if (isset($annotResource)) {
51
						$resource = $annotResource->name;
52
						AclManager::addResource($annotResource->name, $controller . '.' . $action);
53
					}
54
					if (isset($annotPermission)) {
55
						$permission = $annotPermission->name;
56
						AclManager::addPermission($annotPermission->name, $annotPermission->level);
57
						$hasPermission = true;
58
						$this->permissionMap->addAction($controller, $action, $annotResource ?? ($this->mainResource ? $this->mainResource->name : $controller . '.' . $action), $annotPermission->name);
59
					} elseif (isset($annotResource)) {
60
						$this->permissionMap->addAction($controller, $action, $annotResource, 'ALL');
61
					}
62
					$annotsAllow = Reflexion::getAnnotationsMethod($controllerClass, $method, '@allow');
63
					if (count($annotsAllow) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $annotsAllow can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
					if (count(/** @scrutinizer ignore-type */ $annotsAllow) > 0) {
Loading history...
64
						$this->addAllows($annotsAllow, $controller, $action, $resource, $permission);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $resource does not seem to be defined for all execution paths leading up to this point.
Loading history...
65
					}
66
				} catch (\Exception $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
67
			}
68
		}
69
		if ($hasPermission || $this->mainResource != null || $this->mainPermission != null) {
70
			$permission = 'ALL';
71
			$resource = $this->mainResource ? $this->mainResource->name : $controller;
72
			$this->permissionMap->addAction($controller, '*', $resource, $this->mainPermission ? $this->mainPermission->name : 'ALL');
73
			AclManager::addResource($resource, $controller . '.*');
74
			if (isset($this->mainPermission)) {
75
				$permission = $this->mainPermission->name;
76
				AclManager::addPermission($this->mainPermission->name, ($this->mainPermission->level) ?? 0);
77
			}
78
			$annotsAllow = $annotsAllow = Reflexion::getAnnotationClass($controllerClass, '@allow');
79
			if (count($annotsAllow) > 0) {
80
				$this->addAllows($annotsAllow, $controller, '*', $resource, $permission);
81
			}
82
		}
83
	}
84
85
	protected function addAllows($annotsAllow, $controller, $action, $resource, $permission) {
86
		foreach ($annotsAllow as $annotAllow) {
87
			if (isset($annotAllow->resource) && isset($resource) && $resource !== $annotAllow->resource) {
88
				throw new AclException("Resources {$resource} and {$annotAllow->resource} are in conflict for action {$controller}.{$action}");
89
			}
90
			if (isset($annotAllow->permission) && isset($permission) && $permission !== $annotAllow->permission) {
91
				throw new AclException("Permissions {$permission} and {$annotAllow->permission} are in conflict for action {$controller}.{$action}");
92
			}
93
			AclManager::addAndAllow($annotAllow->role, $annotAllow->resource ?? $resource, $annotAllow->permission ?? $permission);
94
		}
95
	}
96
97
	public function parse($controllerClass) {
98
		$this->controllerClass = $controllerClass;
99
		$reflect = new \ReflectionClass($controllerClass);
100
		if (! $reflect->isAbstract() && $reflect->isSubclassOf(Controller::class)) {
101
			try {
102
				$annotsResource = Reflexion::getAnnotationClass($controllerClass, '@resource');
103
				$annotsPermission = Reflexion::getAnnotationClass($controllerClass, '@permission');
104
			} catch (\Exception $e) {
105
				// When controllerClass generates an exception
106
			}
107
			$this->mainResource = $annotsResource[0] ?? null;
108
			$this->mainPermission = $annotsPermission[0] ?? null;
109
110
			$methods = Reflexion::getMethods($controllerClass, \ReflectionMethod::IS_PUBLIC);
111
			$this->parseMethods($methods);
112
		}
113
	}
114
115
	public function save() {
116
		$this->permissionMap->save();
117
		$aclList = AclManager::getAclList();
118
		$providers = $aclList->getProviders();
119
		$aclList->setProviders([
120
			new AclCacheProvider()
121
		]);
122
		$aclList->saveAll();
123
		$aclList->setProviders($providers);
124
	}
125
}
126
127