Passed
Push — master ( 6c3219...97ce76 )
by Adam
03:05
created

PermissionsExtension::loadConfiguration()   C

Complexity

Conditions 11
Paths 54

Size

Total Lines 67
Code Lines 34

Duplication

Lines 24
Ratio 35.82 %

Code Coverage

Tests 26
CRAP Score 12.5763

Importance

Changes 0
Metric Value
dl 24
loc 67
ccs 26
cts 34
cp 0.7647
rs 5.8904
c 0
b 0
f 0
cc 11
eloc 34
nc 54
nop 0
crap 12.5763

How to fix   Long Method    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
/**
3
 * PermissionsExtension.php
4
 *
5
 * @copyright      More in license.md
6
 * @license        https://www.ipublikuj.eu
7
 * @author         Adam Kadlec https://www.ipublikuj.eu
8
 * @package        iPublikuj:Permissions!
9
 * @subpackage     DI
10
 * @since          1.0.0
11
 *
12
 * @date           10.10.14
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\Permissions\DI;
18
19
use Nette;
20
use Nette\DI;
21
use Nette\PhpGenerator as Code;
22
use Nette\Security as NS;
23
use Nette\Utils;
24
25
use IPub\Permissions;
26
use IPub\Permissions\Access;
27
use IPub\Permissions\Entities;
28
use IPub\Permissions\Exceptions;
29
use IPub\Permissions\Providers;
30
use IPub\Permissions\Security;
31
32
/**
33
 * Permission extension container
34
 *
35
 * @package        iPublikuj:Permissions!
36
 * @subpackage     DI
37
 *
38
 * @author         Adam Kadlec <[email protected]>
39
 */
40 1
final class PermissionsExtension extends DI\CompilerExtension
41
{
42
	/**
43
	 * @var array
44
	 */
45
	private $defaults = [
46
		'annotation'  => TRUE,
47
		'redirectUrl' => NULL,
48
		'providers'   => [
49
			'roles'       => TRUE,
50
			'resources'   => TRUE,
51
			'permissions' => TRUE,
52
		],
53
	];
54
55
	public function loadConfiguration() : void
56
	{
57
		// Get container builder
58 1
		$builder = $this->getContainerBuilder();
59
		// Get extension configuration
60 1
		$configuration = $this->getConfig($this->defaults);
61
62
		// Application permissions
63 1
		$builder->addDefinition($this->prefix('permissions'))
64 1
			->setType(Security\Permission::class);
65
66 1
		$builder->addDefinition($this->prefix('config'))
67 1
			->setType(Permissions\Configuration::class)
68 1
			->setArguments([
69 1
				$configuration['redirectUrl'],
70
			]);
71
72
		/**
73
		 * Data providers
74
		 */
75
76 1 View Code Duplication
		if ($configuration['providers']['roles'] === TRUE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
77
			$builder->addDefinition($this->prefix('providers.roles'))
78
				->setType(Providers\RolesProvider::class);
79
80 1
		} elseif (is_string($configuration['providers']['roles']) && class_exists($configuration['providers']['roles'])) {
81
			$builder->addDefinition($this->prefix('providers.roles'))
82
				->setType($configuration['providers']['roles']);
83
		}
84
85 1 View Code Duplication
		if ($configuration['providers']['resources'] === TRUE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
			$builder->addDefinition($this->prefix('providers.resources'))
87
				->setType(Providers\ResourcesProvider::class);
88
89 1
		} elseif (is_string($configuration['providers']['resources']) && class_exists($configuration['providers']['resources'])) {
90 1
			$builder->addDefinition($this->prefix('providers.resources'))
91 1
				->setType($configuration['providers']['resources']);
92
		}
93
94 1 View Code Duplication
		if ($configuration['providers']['permissions'] === TRUE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
95
			$builder->addDefinition($this->prefix('providers.permissions'))
96
				->setType(Providers\PermissionsProvider::class);
97
98 1
		} elseif (is_string($configuration['providers']['permissions']) && class_exists($configuration['providers']['permissions'])) {
99 1
			$builder->addDefinition($this->prefix('providers.permissions'))
100 1
				->setType($configuration['providers']['permissions']);
101
		}
102
103
		/**
104
		 * Access checkers
105
		 */
106
107
		// Check if annotation checker is enabled
108 1
		if ($configuration['annotation'] === TRUE) {
109
			// Annotation access checkers
110 1
			$builder->addDefinition($this->prefix('checkers.annotation'))
111 1
				->setType(Access\AnnotationChecker::class);
112
		}
113
114
		// Latte access checker
115 1
		$builder->addDefinition($this->prefix('checkers.latte'))
116 1
			->setType(Access\LatteChecker::class);
117
118
		// Link access checker
119 1
		$builder->addDefinition($this->prefix('checkers.link'))
120 1
			->setType(Access\LinkChecker::class);
121 1
	}
122
123
	/**
124
	 * {@inheritdoc}
125
	 */
126
	public function beforeCompile() : void
127
	{
128 1
		parent::beforeCompile();
129
130
		// Get container builder
131 1
		$builder = $this->getContainerBuilder();
132
133
		// Get acl permissions service
134 1
		$permissionsProvider = $builder->findByType(Providers\IPermissionsProvider::class);
135 1
		$permissionsProvider = reset($permissionsProvider);
136
137
		// Get acl resources service
138 1
		$resourcesProvider = $builder->findByType(Providers\IResourcesProvider::class);
139 1
		$resourcesProvider = reset($resourcesProvider);
140
141
		// Check all extensions and search for permissions provider
142 1
		foreach ($this->compiler->getExtensions() as $extension) {
143 1
			if (!$extension instanceof IPermissionsProvider) {
144 1
				continue;
145
			}
146
147
			// Get permissions & details
148 1
			$this->registerPermissionsResources($extension->getPermissions(), $resourcesProvider, $permissionsProvider);
0 ignored issues
show
Security Bug introduced by
It seems like $resourcesProvider defined by reset($resourcesProvider) on line 139 can also be of type false; however, IPub\Permissions\DI\Perm...rPermissionsResources() does only seem to accept null|object<Nette\DI\ServiceDefinition>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
Security Bug introduced by
It seems like $permissionsProvider defined by reset($permissionsProvider) on line 135 can also be of type false; however, IPub\Permissions\DI\Perm...rPermissionsResources() does only seem to accept null|object<Nette\DI\ServiceDefinition>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
149
		}
150
151
		// Install extension latte macros
152 1
		$latteFactory = $builder->getDefinition($builder->getByType(Nette\Bridges\ApplicationLatte\ILatteFactory::class) ?: 'nette.latteFactory');
153
154
		$latteFactory
155 1
			->addSetup('IPub\Permissions\Latte\Macros::install(?->getCompiler())', ['@self']);
156 1
	}
157
158
	/**
159
	 * @param Nette\Configurator $config
160
	 * @param string $extensionName
161
	 *
162
	 * @return void
163
	 */
164
	public static function register(Nette\Configurator $config, $extensionName = 'permissions') : void
165
	{
166 1
		$config->onCompile[] = function (Nette\Configurator $config, Nette\DI\Compiler $compiler) use ($extensionName) {
167 1
			$compiler->addExtension($extensionName, new PermissionsExtension());
168 1
		};
169 1
	}
170
171
	/**
172
	 * @param array $permissions
173
	 * @param DI\ServiceDefinition|NULL $resourcesProvider
174
	 * @param DI\ServiceDefinition|NULL $permissionsProvider
175
	 *
176
	 * @return void
177
	 *
178
	 * @throws Exceptions\InvalidArgumentException
179
	 */
180
	private function registerPermissionsResources(
181
		array $permissions,
182
		DI\ServiceDefinition $resourcesProvider = NULL,
183
		DI\ServiceDefinition $permissionsProvider = NULL
184
	) : void {
185 1
		foreach ($permissions as $permission => $details) {
186 1
			if (is_string($permission) && Utils\Strings::contains($permission, Entities\IPermission::DELIMITER)) {
187
				// Parse resource & privilege from permission
188 1
				list($resource, $privilege) = explode(Entities\IPermission::DELIMITER, $permission);
189
190
				// Remove white spaces
191 1
				$resource = Utils\Strings::trim($resource);
192 1
				$privilege = Utils\Strings::trim($privilege);
193
194 1
				$resource = new Entities\Resource($resource);
195
196 1
			} elseif (is_array($details)) {
197 1
				if (!isset($details['resource']) || !isset($details['privilege'])) {
198 1
					throw new Exceptions\InvalidArgumentException('Permission must include resource & privilege.');
199
				}
200
201
				// Remove white spaces
202 1
				$resource = Utils\Strings::trim($details['resource']);
203 1
				$privilege = Utils\Strings::trim($details['privilege']);
204
205 1
				$resource = new Entities\Resource($resource);
206
207 1
				$details = NULL;
208
209
			} elseif ($details instanceof Entities\IPermission) {
210 1
				$resource = $details->getResource();
211 1
				$privilege = $details->getPrivilege();
212
213 1
				$details = NULL;
214
215
				// Resource & privilege is in string with delimiter
216
			} else {
217
				throw new Exceptions\InvalidArgumentException(sprintf('Permission must be only string with delimiter, array with resource & privilege or instance of IPub\Permissions\Entities\IPermission, %s given', gettype($permission)));
218
			}
219
220 1
			$privilege = $privilege === '' ? NS\IAuthorizator::ALL : $privilege;
221
222
			// Assign permission to service
223 1
			$permissionsProvider->addSetup('addPermission', [$resource, $privilege, $details]);
0 ignored issues
show
Bug introduced by
It seems like $permissionsProvider is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
224 1
			$resourcesProvider->addSetup('addResource', [$resource->getResourceId()]);
0 ignored issues
show
Bug introduced by
It seems like $resourcesProvider is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
225
		}
226 1
	}
227
}
228