PluginProbe
User Access Manager / 2.2.13
User Access Manager v2.2.13
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
← All changes | src/Access/AccessHandler.php +212 -101 trunk2.2.13 View file →
@@ -1,5 +1,18 @@
1 1 <?php
2 +/**
3 + * AccessHandler.php
4 + *
5 + * The AccessHandler class file.
6 + *
7 + * PHP versions 5
8 + *
9 + * @author Alexander Schneider <alexanderschneider85@gmail.com>
10 + * @copyright 2008-2017 Alexander Schneider
11 + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2
12 + * @version SVN: $id$
13 + * @link http://wordpress.org/extend/plugins/user-access-manager/
14 + */
2 15
3 16 declare(strict_types=1);
4 17
5 18 namespace UserAccessManager\Access;
@@ -9,53 +22,118 @@
9 22 use UserAccessManager\Database\Database;
10 23 use UserAccessManager\Object\ObjectHandler;
11 24 use UserAccessManager\User\UserHandler;
12 25 use UserAccessManager\UserGroup\AbstractUserGroup;
26 +use UserAccessManager\UserGroup\DynamicUserGroup;
13 27 use UserAccessManager\UserGroup\UserGroupHandler;
14 28 use UserAccessManager\UserGroup\UserGroupTypeException;
15 29 use UserAccessManager\Wrapper\Wordpress;
16 30
31 +/**
32 + * Class AccessHandler
33 + * @package UserAccessManager\AccessHandler
34 + */
17 35 class AccessHandler
18 36 {
19 - private ?array $excludedTerms = null;
20 - private ?array $excludedPosts = null;
21 - private array $objectAccess = [];
22 - private ?array $visiblePostTypes = null;
37 + /**
38 + * @var Wordpress
39 + */
40 + private $wordpress;
23 41
42 + /**
43 + * @var MainConfig
44 + */
45 + private $mainConfig;
46 +
47 + /**
48 + * @var Database
49 + */
50 + private $database;
51 +
52 + /**
53 + * @var ObjectHandler
54 + */
55 + private $objectHandler;
56 +
57 + /**
58 + * @var UserHandler
59 + */
60 + private $userHandler;
61 +
62 + /**
63 + * @var UserGroupHandler
64 + */
65 + private $userGroupHandler;
66 +
67 + /**
68 + * @var null|array
69 + */
70 + private $excludedTerms = null;
71 +
72 + /**
73 + * @var null|array
74 + */
75 + private $excludedPosts = null;
76 +
77 + /**
78 + * @var array
79 + */
80 + private $objectAccess = [];
81 +
82 + /**
83 + * @var null|array
84 + */
85 + private $noneHiddenPostTypes = null;
86 +
87 + /**
88 + * AccessHandler constructor.
89 + * @param Wordpress $wordpress
90 + * @param MainConfig $mainConfig
91 + * @param Database $database
92 + * @param ObjectHandler $objectHandler
93 + * @param UserHandler $userHandler
94 + * @param UserGroupHandler $userGroupHandler
95 + */
24 96 public function __construct(
25 - private Wordpress $wordpress,
26 - private MainConfig $mainConfig,
27 - private Database $database,
28 - private ObjectHandler $objectHandler,
29 - private UserHandler $userHandler,
30 - private UserGroupHandler $userGroupHandler
97 + Wordpress $wordpress,
98 + MainConfig $mainConfig,
99 + Database $database,
100 + ObjectHandler $objectHandler,
101 + UserHandler $userHandler,
102 + UserGroupHandler $userGroupHandler
31 103 ) {
104 + $this->wordpress = $wordpress;
105 + $this->mainConfig = $mainConfig;
106 + $this->database = $database;
107 + $this->objectHandler = $objectHandler;
108 + $this->userHandler = $userHandler;
109 + $this->userGroupHandler = $userGroupHandler;
32 110 }
33 111
34 - private function canManageUserGroups(): bool
112 + /**
113 + * Checks it the user has access because he is the author.
114 + * @param string $objectType
115 + * @param int|string $objectId
116 + * @return bool
117 + */
118 + private function hasAuthorAccess(string $objectType, $objectId): bool
35 119 {
36 - return $this->userHandler->checkUserAccess(UserHandler::MANAGE_USER_GROUPS_CAPABILITY) === true;
37 - }
38 -
39 - private function hasAuthorAccess(string $objectType, int|string|null $objectId): bool
40 - {
41 - if ($this->mainConfig->authorsHasAccessToOwn() !== true
42 - || $this->objectHandler->isPostType($objectType) === false
120 + if ($this->mainConfig->authorsHasAccessToOwn() === true
121 + && $this->objectHandler->isPostType($objectType)
43 122 ) {
44 - return false;
123 + $post = $this->objectHandler->getPost($objectId);
124 + return $post !== false
125 + && $this->wordpress->getCurrentUser()->ID === (int) $post->post_author;
45 126 }
46 127
47 - $post = $this->objectHandler->getPost($objectId);
48 -
49 - if ($post === false) {
50 - return false;
51 - }
52 -
53 - $currentUserId = $this->wordpress->getCurrentUser()->ID;
54 -
55 - return $currentUserId !== 0 && $currentUserId === (int) $post->post_author;
128 + return false;
56 129 }
57 130
131 + /**
132 + * Checks if the is admin value is set if not grabs it from the wordpress function.
133 + * @param null|bool $isAdmin
134 + * @return bool
135 + */
58 136 private function isAdmin(?bool $isAdmin): bool
59 137 {
60 138 return ($isAdmin === null) ? $this->wordpress->isAdmin() : $isAdmin;
61 139 }
@@ -60,11 +138,14 @@
60 138 return ($isAdmin === null) ? $this->wordpress->isAdmin() : $isAdmin;
61 139 }
62 140
63 141 /**
142 + * Returns the user user groups filtered by the write access.
143 + * @param null|bool $isAdmin If set we force the admin mode.
144 + * @return AbstractUserGroup[]
64 145 * @throws UserGroupTypeException
65 146 */
66 - private function getUserUserGroupsForObjectAccess(?bool $isAdmin = null): array
147 + private function getUserUserGroupsForObjectAccess($isAdmin = null): array
67 148 {
68 149 $userUserGroups = $this->userGroupHandler->getUserGroupsForUser();
69 150
70 151 if ($this->isAdmin($isAdmin) === true) {
@@ -69,9 +150,11 @@
69 150
70 151 if ($this->isAdmin($isAdmin) === true) {
71 152 $userUserGroups = array_filter(
72 153 $userUserGroups,
73 - fn(AbstractUserGroup $userGroup) => $userGroup->getWriteAccess() !== 'none'
154 + function (AbstractUserGroup $userGroup) {
155 + return $userGroup->getWriteAccess() !== 'none';
156 + }
74 157 );
75 158 }
76 159
77 160 return $this->wordpress->applyFilters('uam_get_user_user_groups_for_object_access', $userUserGroups, $isAdmin);
@@ -77,45 +160,46 @@
77 160 return $this->wordpress->applyFilters('uam_get_user_user_groups_for_object_access', $userUserGroups, $isAdmin);
78 161 }
79 162
80 163 /**
164 + * Checks if the current_user has access to the given post.
165 + * @param string|null $objectType The object type which should be checked.
166 + * @param int|string $objectId The id of the object.
167 + * @param null|bool $isAdmin If set we force the admin mode.
168 + * @return bool
81 169 * @throws UserGroupTypeException
82 170 * @throws Exception
83 171 */
84 - private function resolveObjectAccess(?string $objectType, int|string|null $objectId, bool $isAdmin): bool
172 + public function checkObjectAccess(?string $objectType, $objectId, $isAdmin = null): bool
85 173 {
86 - if ($this->objectHandler->isValidObjectType($objectType) === false
87 - || $this->canManageUserGroups() === true
88 - || $this->hasAuthorAccess($objectType, $objectId) === true
89 - ) {
90 - return true;
91 - }
174 + $isAdmin = $this->isAdmin($isAdmin);
92 175
93 - $membership = $this->userGroupHandler->getUserGroupsForObject($objectType, $objectId);
94 - $access = $membership === []
95 - || array_intersect_key($membership, $this->getUserUserGroupsForObjectAccess($isAdmin)) !== [];
176 + if (isset($this->objectAccess[$isAdmin][$objectType][$objectId]) === false) {
177 + if ($this->objectHandler->isValidObjectType($objectType) === false
178 + || $this->userHandler->checkUserAccess(UserHandler::MANAGE_USER_GROUPS_CAPABILITY) === true
179 + || $this->hasAuthorAccess($objectType, $objectId) === true
180 + ) {
181 + $access = true;
182 + } else {
183 + $access = true;
184 + $membership = $this->userGroupHandler->getUserGroupsForObject($objectType, $objectId);
96 185
97 - if ($access === true && $this->wordpress->isUserLoggedIn() && $this->wordpress->isMultiSite()) {
98 - return $this->wordpress->isUserMemberOfBlog();
99 - }
186 + if (count($membership) > 0) {
187 + $userGroupDiff = array_intersect_key(
188 + $membership,
189 + $this->getUserUserGroupsForObjectAccess($isAdmin)
190 + );
191 + $nonLoggedInGroupKey = DynamicUserGroup::USER_TYPE . '|'
192 + . DynamicUserGroup::NOT_LOGGED_IN_USER_ID;
100 193
101 - return $access;
102 - }
194 + $access = count($userGroupDiff) > 0 && (
195 + isset($userGroupDiff[$nonLoggedInGroupKey]) ||
196 + $this->wordpress->isUserMemberOfBlog()
197 + );
198 + }
199 + }
103 200
104 - /**
105 - * @throws UserGroupTypeException
106 - * @throws Exception
107 - */
108 - public function checkObjectAccess(?string $objectType, int|string|null $objectId, ?bool $isAdmin = null): bool
109 - {
110 - $isAdmin = $this->isAdmin($isAdmin);
111 -
112 - if (isset($this->objectAccess[$isAdmin][$objectType][$objectId]) === false) {
113 - $this->objectAccess[$isAdmin][$objectType][$objectId] = $this->resolveObjectAccess(
114 - $objectType,
115 - $objectId,
116 - $isAdmin
117 - );
201 + $this->objectAccess[$isAdmin][$objectType][$objectId] = $access;
118 202 }
119 203
120 204 return $this->objectAccess[$isAdmin][$objectType][$objectId];
121 205 }
@@ -120,43 +204,55 @@
120 204 return $this->objectAccess[$isAdmin][$objectType][$objectId];
121 205 }
122 206
123 207 /**
124 - * $ignoredObjectTypes is matched against the assigned object type (the array value), not the object id.
125 - *
208 + * Returns the excluded objects.
209 + * @param string $type
210 + * @param array $filterTypesMap
211 + * @return array
126 212 * @throws UserGroupTypeException
127 213 * @throws Exception
128 214 */
129 - private function getExcludedObjects(string $type, array $ignoredObjectTypes = []): array
215 + private function getExcludedObjects(string $type, array $filterTypesMap = []): array
130 216 {
131 217 $excludedObjects = [];
218 + $userGroups = $this->userGroupHandler->getFullUserGroups();
132 219
133 - foreach ($this->userGroupHandler->getFullUserGroups() as $userGroup) {
220 + foreach ($userGroups as $userGroup) {
134 221 $excludedObjects += $userGroup->getAssignedObjectsByType($type);
135 222 }
136 223
137 - foreach ($this->userGroupHandler->getUserGroupsForUser() as $userGroup) {
224 + $userUserGroups = $this->userGroupHandler->getUserGroupsForUser();
225 +
226 + foreach ($userUserGroups as $userGroup) {
138 227 $excludedObjects = array_diff_key($excludedObjects, $userGroup->getAssignedObjectsByType($type));
139 228 }
140 229
141 - $excludedObjects = array_filter(
142 - $excludedObjects,
143 - fn($objectType) => isset($ignoredObjectTypes[$objectType]) === false
144 - );
230 + if ($filterTypesMap !== []) {
231 + $excludedObjects = array_filter(
232 + $excludedObjects,
233 + function ($element) use ($filterTypesMap) {
234 + return isset($filterTypesMap[$element]) === false;
235 + }
236 + );
237 + }
145 238
146 239 $objectIds = array_keys($excludedObjects);
147 -
148 240 return array_combine($objectIds, $objectIds);
149 241 }
150 242
151 243 /**
244 + * Returns the excluded terms for a user.
245 + * @return array
152 246 * @throws UserGroupTypeException
153 247 */
154 248 public function getExcludedTerms(): ?array
155 249 {
156 - if ($this->canManageUserGroups() === true) {
250 + if ($this->userHandler->checkUserAccess(UserHandler::MANAGE_USER_GROUPS_CAPABILITY)) {
157 251 $this->excludedTerms = [];
158 - } elseif ($this->excludedTerms === null) {
252 + }
253 +
254 + if ($this->excludedTerms === null) {
159 255 $this->excludedTerms = $this->getExcludedObjects(ObjectHandler::GENERAL_TERM_OBJECT_TYPE);
160 256 }
161 257
162 258 return $this->excludedTerms;
@@ -161,54 +257,69 @@
161 257
162 258 return $this->excludedTerms;
163 259 }
164 260
165 - private function getVisiblePostTypes(): array
261 + /**
262 + * Returns the none hidden post types map.
263 + * @return array
264 + */
265 + private function getNoneHiddenPostTypes(): ?array
166 266 {
167 - if ($this->visiblePostTypes !== null) {
168 - return $this->visiblePostTypes;
169 - }
267 + if ($this->noneHiddenPostTypes === null) {
268 + $this->noneHiddenPostTypes = [];
170 269
171 - $this->visiblePostTypes = [];
270 + if ($this->wordpress->isAdmin() === false) {
271 + $postTypes = $this->objectHandler->getPostTypes();
172 272
173 - if ($this->wordpress->isAdmin() === false) {
174 - foreach ($this->objectHandler->getPostTypes() as $postType) {
175 - if ($this->mainConfig->hidePostType($postType) === false) {
176 - $this->visiblePostTypes[$postType] = $postType;
273 + foreach ($postTypes as $postType) {
274 + if ($this->mainConfig->hidePostType($postType) === false) {
275 + $this->noneHiddenPostTypes[$postType] = $postType;
276 + }
177 277 }
178 278 }
179 279 }
180 280
181 - return $this->visiblePostTypes;
281 + return $this->noneHiddenPostTypes;
182 282 }
183 283
184 - private function getOwnPostIds(): array
185 - {
186 - $query = $this->database->prepare(
187 - "SELECT `ID` FROM `{$this->database->getPostsTable()}`
188 - WHERE `post_author` = %d",
189 - $this->wordpress->getCurrentUser()->ID
190 - );
191 -
192 - return array_column((array) $this->database->getResults($query), 'ID', 'ID');
193 - }
194 -
195 284 /**
285 + * Returns the excluded posts.
286 + * @return array
196 287 * @throws UserGroupTypeException
197 288 */
198 289 public function getExcludedPosts(): ?array
199 290 {
200 - if ($this->canManageUserGroups() === true) {
291 + if ($this->userHandler->checkUserAccess(UserHandler::MANAGE_USER_GROUPS_CAPABILITY)) {
201 292 $this->excludedPosts = [];
202 - } elseif ($this->excludedPosts === null) {
203 - $excludedPosts = $this->getExcludedObjects(
204 - ObjectHandler::GENERAL_POST_OBJECT_TYPE,
205 - $this->getVisiblePostTypes()
206 - );
293 + }
207 294
208 - $this->excludedPosts = ($this->mainConfig->authorsHasAccessToOwn() === true)
209 - ? array_diff_key($excludedPosts, $this->getOwnPostIds())
210 - : $excludedPosts;
295 + if ($this->excludedPosts === null) {
296 + $noneHiddenPostTypes = $this->getNoneHiddenPostTypes();
297 + $excludedPosts = $this->getExcludedObjects(ObjectHandler::GENERAL_POST_OBJECT_TYPE, $noneHiddenPostTypes);
298 +
299 + if ($this->mainConfig->authorsHasAccessToOwn() === true) {
300 + $query = $this->database->prepare(
301 + "SELECT ID FROM {$this->database->getPostsTable()}
302 + WHERE post_author = %d",
303 + $this->wordpress->getCurrentUser()->ID
304 + );
305 +
306 + $ownPosts = array_filter(
307 + (array) $this->database->getResults($query),
308 + function ($ownPost) {
309 + return isset($ownPost->ID);
310 + }
311 + );
312 + $ownPostIds = [];
313 +
314 + foreach ($ownPosts as $ownPost) {
315 + $ownPostIds[$ownPost->ID] = $ownPost->ID;
316 + }
317 +
318 + $excludedPosts = array_diff_key($excludedPosts, $ownPostIds);
319 + }
320 +
321 + $this->excludedPosts = $excludedPosts;
211 322 }
212 323
213 324 return $this->excludedPosts;
214 325 }