Hooks   B
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 339
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 19
Bugs 0 Features 3
Metric Value
wmc 37
c 19
b 0
f 3
lcom 1
cbo 14
dl 0
loc 339
rs 8.6

14 Methods

Rating   Name   Duplication   Size   Complexity  
A get_user_permission_resolver() 0 4 1
A get_user_ownership_resolver() 0 4 1
A resolve_user_ownership() 0 9 4
A markup_user() 0 4 1
A app() 0 4 1
A before_roles_delete() 0 12 2
B on_security_exception_rescue() 0 27 4
A on_website_admin_not_accessible_rescue() 0 14 1
C before_routing_dispatcher_dispatch() 0 56 10
A get_user_id() 0 11 3
B get_user() 0 29 5
A check_user_permission() 0 6 1
A check_user_ownership() 0 6 1
A markup_form_login() 0 6 2
1
<?php
2
3
/*
4
 * This file is part of the Icybee package.
5
 *
6
 * (c) Olivier Laviale <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Icybee\Modules\Users;
13
14
use ICanBoogie\ActiveRecord;
15
use ICanBoogie\Core;
16
use ICanBoogie\HTTP\AuthenticationRequired;
17
use ICanBoogie\HTTP\PermissionRequired;
18
use ICanBoogie\HTTP\Response;
19
use ICanBoogie\HTTP\RequestDispatcher;
20
use ICanBoogie\HTTP\SecurityError;
21
use ICanBoogie\Operation;
22
use ICanBoogie\PropertyNotDefined;
23
use ICanBoogie\Routing\RouteDispatcher;
24
use ICanBoogie\Session;
25
26
use Icybee\Element\AdminDecorator;
27
use Icybee\Element\DocumentDecorator;
28
use Icybee\Modules\Members\Member;
29
use Icybee\Modules\Users\Binding\CoreBindings;
30
31
class Hooks
32
{
33
	/*
34
	 * Events
35
	 */
36
37
	/**
38
	 * Checks if the role to be deleted is used or not.
39
	 *
40
	 * @param Operation\BeforeProcessEvent $event
41
	 * @param \Icybee\Modules\Users\Roles\Operation\DeleteOperation $operation
42
	 */
43
	static public function before_roles_delete(Operation\BeforeProcessEvent $event, \Icybee\Modules\Users\Roles\Operation\DeleteOperation $operation)
44
	{
45
		$rid = $operation->key;
46
		$count = self::app()->models['users/has_many_roles']->filter_by_rid($rid)->count;
47
48
		if (!$count)
49
		{
50
			return;
51
		}
52
53
		$event->errors['rid'] = $event->errors->format('The role %name is used by :count users.', [ 'name' => $operation->record->name, ':count' => $count ]);
0 ignored issues
show
Bug introduced by
The method format() does not seem to exist on object<ICanBoogie\ErrorCollection>.

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...
54
	}
55
56
	/**
57
	 * Displays a login form on {@link SecurityError}.
58
	 *
59
	 * @param \ICanBoogie\Exception\RescueEvent $event
60
	 * @param SecurityError $target
61
	 */
62
	static public function on_security_exception_rescue(\ICanBoogie\Exception\RescueEvent $event, SecurityError $target)
63
	{
64
		$request = $event->request;
65
66
		if (!$request->is_get)
67
		{
68
			return;
69
		}
70
71
		if ($target instanceof PermissionRequired || \ICanBoogie\Routing\decontextualize($request->normalized_path) != '/admin/')
72
		{
73
			\ICanBoogie\log_error($target->getMessage());
74
		}
75
76
		$block = self::app()->modules['users']->getBlock('connect');
77
78
		$document = new DocumentDecorator(new AdminDecorator($block));
79
		$document->body->add_class('page-slug-authenticate');
80
81
		$event->response = new Response((string) $document, $target->getCode(), [
82
83
			'Content-Type' => 'text/html; charset=utf-8'
84
85
		]);
86
87
		$event->stop();
88
	}
89
90
	/**
91
	 * Displays an _available websites_ form on {@link WebsiteAdminNotAccessible}.
92
	 *
93
	 * @param \ICanBoogie\Exception\RescueEvent $event
94
	 * @param WebsiteAdminNotAccessible $target
95
	 */
96
	static public function on_website_admin_not_accessible_rescue(\ICanboogie\Exception\RescueEvent $event, WebsiteAdminNotAccessible $target)
97
	{
98
		$block = self::app()->modules['users']->getBlock('available-sites');
99
100
		$document = new DocumentDecorator(new AdminDecorator($block));
101
102
		$event->response = new Response((string) $document, $target->getCode(), [
103
104
			'Content-Type' => 'text/html; charset=utf-8'
105
106
		]);
107
108
		$event->stop();
109
	}
110
111
	/**
112
	 * The {@link PermissionRequired} exception is thrown if a member attempts to enter the admin.
113
	 *
114
	 * Authenticated users who don't have access to the admin of a website are redirected to the
115
	 * `/admin/profile/sites` URL, in which case the `response` property of the event is altered
116
	 * with a {@link RedirectResponse}.
117
	 *
118
	 * @param RouteDispatcher\BeforeDispatchEvent $event
119
	 * @param RouteDispatcher $target
120
	 *
121
	 * @throws PermissionRequired if a member attempt to enter the admin.
122
	 * @throws WebsiteAdminNotAccessible if a user attempts to access the admin of a website he
123
	 * doesn't have access to.
124
	 */
125
	static public function before_routing_dispatcher_dispatch(RouteDispatcher\BeforeDispatchEvent $event, RouteDispatcher $target)
126
	{
127
		$path = \ICanBoogie\normalize_url_path($event->request->decontextualized_path);
128
129
		if (strpos($path, '/admin/') !== 0)
130
		{
131
			return;
132
		}
133
134
		$app = self::app();
135
		$user = $app->user;
136
137
		if ($user->is_guest)
138
		{
139
			throw new AuthenticationRequired;
140
		}
141
142
		if ($user instanceof Member)
143
		{
144
			throw new PermissionRequired;
145
		}
146
147
		if ($user->language)
148
		{
149
			$app->locale = $user->language;
150
		}
151
152
		if (strpos($path, '/admin/profile/sites/') === 0)
153
		{
154
			return;
155
		}
156
157
		$restricted_sites = null;
158
159
		try
160
		{
161
			$restricted_sites = $user->restricted_sites_ids;
162
		}
163
		catch (PropertyNotDefined $e)
164
		{
165
			throw $e;
166
		}
167
		catch (\Exception $e)
168
		{
169
			#
170
			# not important
171
			#
172
		}
173
174
		if (!$restricted_sites || in_array($app->site_id, $restricted_sites))
175
		{
176
			return;
177
		}
178
179
		throw new WebsiteAdminNotAccessible;
180
	}
181
182
	/*
183
	 * Prototype methods
184
	 */
185
186
	/**
187
	 * Returns the user's identifier.
188
	 *
189
	 * This is the getter for the `$app->user_id` property.
190
	 *
191
	 * @param Core $app
192
	 *
193
	 * @return int|null Returns the identifier of the user or null if the user is a guest.
194
	 *
195
	 * @see User::login()
196
	 */
197
	static public function get_user_id(Core $app)
198
	{
199
		$session = $app->session;
200
201
		if (!$session->is_referenced)
202
		{
203
			return null;
204
		}
205
206
		return isset($session['user_id']) ? $session['user_id'] : null;
207
	}
208
209
	/**
210
	 * Returns the user object.
211
	 *
212
	 * If the user identifier can be retrieved from the session, it is used to find the
213
	 * corresponding user.
214
	 *
215
	 * If no user could be found, a guest user object is returned.
216
	 *
217
	 * This is the getter for the `$app->user` property.
218
	 *
219
	 * @param Core|CoreBindings|\ICanBoogie\Binding\ActiveRecord\CoreBindings $app
220
	 *
221
	 * @return User The user object, or guest user object.
222
	 */
223
	static public function get_user(Core $app)
224
	{
225
		$user = null;
226
		$uid = $app->user_id;
227
		$model = $app->models['users'];
228
229
		try
230
		{
231
			if ($uid)
232
			{
233
				$user = $model[$uid];
234
			}
235
		}
236
		catch (\Exception $e) {}
237
238
		if (!$user)
239
		{
240
			$session = $app->session;
241
242
			if ($session->is_referenced)
243
			{
244
				unset($session['user_id']);
245
			}
246
247
			$user = new User($model);
248
		}
249
250
		return $user;
251
	}
252
253
	/**
254
	 * Returns a user permission resolver configured with the `users` config.
255
	 *
256
	 * @param Core $app
257
	 *
258
	 * @return PermissionResolver
259
	 */
260
	static public function get_user_permission_resolver(Core $app)
261
	{
262
		return new PermissionResolver($app->configs['users_permission_resolver_list']);
263
	}
264
265
	/**
266
	 * Returns a user permission resolver configured with the `users` config.
267
	 *
268
	 * @param Core $app
269
	 *
270
	 * @return OwnershipResolver
271
	 */
272
	static public function get_user_ownership_resolver(Core $app)
273
	{
274
		return new OwnershipResolver($app->configs['users_ownership_resolver_list']);
275
	}
276
277
	/**
278
	 * Checks if a user has a given permission.
279
	 *
280
	 * @param Core|CoreBindings $app
281
	 * @param User $user
282
	 * @param string $permission
283
	 * @param string $target
284
	 *
285
	 * @return bool
286
	 */
287
	static public function check_user_permission(Core $app, User $user, $permission, $target = null)
288
	{
289
		$user_permission_resolver = $app->user_permission_resolver;
290
291
		return $user_permission_resolver($user, $permission, $target);
292
	}
293
294
	/**
295
	 * Checks if a user has the ownership of a record.
296
	 *
297
	 * @param Core|CoreBindings $app
298
	 * @param User $user
299
	 * @param ActiveRecord $record
300
	 *
301
	 * @return bool
302
	 */
303
	static public function check_user_ownership(Core $app, User $user, ActiveRecord $record)
304
	{
305
		$user_ownership_resolver = $app->user_ownership_resolver;
306
307
		return $user_ownership_resolver($user, $record);
308
	}
309
310
	/**
311
	 * Resolves user ownership of a record.
312
	 *
313
	 * @param User $user
314
	 * @param ActiveRecord $record
315
	 *
316
	 * @return boolean|null `true` if the user identifier is 1, or the `uid` property of
317
	 * the record is not empty and it matches the user identifier. `null` otherwise.
318
	 */
319
	static public function resolve_user_ownership(User $user, ActiveRecord $record)
320
	{
321
		$uid = $user->uid;
322
323
		if ($uid == 1 || (!empty($record->uid) && $record->uid == $uid))
324
		{
325
			return true;
326
		}
327
	}
328
329
	/*
330
	 * Markups
331
	 */
332
333
	static public function markup_form_login(array $args, $engine, $template)
334
	{
335
		$form = new LoginForm();
336
337
		return $template ? $engine($template, $form) : $form;
338
	}
339
340
	/**
341
	 * Retrieves the current user.
342
	 *
343
	 * <pre>
344
	 * <p:user>
345
	 * <!-- Content: with-param*, template -->
346
	 * </p:user>
347
	 * </pre>
348
	 *
349
	 * @param array $args
350
	 * @param \Patron\Engine $engine
351
	 * @param array $template
352
	 */
353
	static public function markup_user(array $args, $engine, $template)
354
	{
355
		return $engine($template, self::app()->user);
356
	}
357
358
	/*
359
	 * Support
360
	 */
361
362
	/**
363
	 * @return Core|\Icybee\Binding\CoreBindings
364
	 */
365
	static private function app()
366
	{
367
		return \ICanBoogie\app();
368
	}
369
}
370