PluginProbe
User Access Manager / 2.2.20
User Access Manager v2.2.20
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 +204 -102 trunk2.2.20 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,37 @@
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 + $membership = $this->userGroupHandler->getUserGroupsForObject($objectType, $objectId);
184 + $access = $membership === []
185 + || array_intersect_key($membership, $this->getUserUserGroupsForObjectAccess($isAdmin)) !== [];
96 186
97 - if ($access === true && $this->wordpress->isUserLoggedIn() && $this->wordpress->isMultiSite()) {
98 - return $this->wordpress->isUserMemberOfBlog();
99 - }
187 + if ($access && $this->wordpress->isUserLoggedIn() && $this->wordpress->isMultiSite()) {
188 + $access = $this->wordpress->isUserMemberOfBlog();
189 + }
190 + }
100 191
101 - return $access;
102 - }
103 -
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 - );
192 + $this->objectAccess[$isAdmin][$objectType][$objectId] = $access;
118 193 }
119 194
120 195 return $this->objectAccess[$isAdmin][$objectType][$objectId];
121 196 }
@@ -120,43 +195,55 @@
120 195 return $this->objectAccess[$isAdmin][$objectType][$objectId];
121 196 }
122 197
123 198 /**
124 - * $ignoredObjectTypes is matched against the assigned object type (the array value), not the object id.
125 - *
199 + * Returns the excluded objects.
200 + * @param string $type
201 + * @param array $filterTypesMap
202 + * @return array
126 203 * @throws UserGroupTypeException
127 204 * @throws Exception
128 205 */
129 - private function getExcludedObjects(string $type, array $ignoredObjectTypes = []): array
206 + private function getExcludedObjects(string $type, array $filterTypesMap = []): array
130 207 {
131 208 $excludedObjects = [];
209 + $userGroups = $this->userGroupHandler->getFullUserGroups();
132 210
133 - foreach ($this->userGroupHandler->getFullUserGroups() as $userGroup) {
211 + foreach ($userGroups as $userGroup) {
134 212 $excludedObjects += $userGroup->getAssignedObjectsByType($type);
135 213 }
136 214
137 - foreach ($this->userGroupHandler->getUserGroupsForUser() as $userGroup) {
215 + $userUserGroups = $this->userGroupHandler->getUserGroupsForUser();
216 +
217 + foreach ($userUserGroups as $userGroup) {
138 218 $excludedObjects = array_diff_key($excludedObjects, $userGroup->getAssignedObjectsByType($type));
139 219 }
140 220
141 - $excludedObjects = array_filter(
142 - $excludedObjects,
143 - fn($objectType) => isset($ignoredObjectTypes[$objectType]) === false
144 - );
221 + if ($filterTypesMap !== []) {
222 + $excludedObjects = array_filter(
223 + $excludedObjects,
224 + function ($element) use ($filterTypesMap) {
225 + return isset($filterTypesMap[$element]) === false;
226 + }
227 + );
228 + }
145 229
146 230 $objectIds = array_keys($excludedObjects);
147 -
148 231 return array_combine($objectIds, $objectIds);
149 232 }
150 233
151 234 /**
235 + * Returns the excluded terms for a user.
236 + * @return array
152 237 * @throws UserGroupTypeException
153 238 */
154 239 public function getExcludedTerms(): ?array
155 240 {
156 - if ($this->canManageUserGroups() === true) {
241 + if ($this->userHandler->checkUserAccess(UserHandler::MANAGE_USER_GROUPS_CAPABILITY)) {
157 242 $this->excludedTerms = [];
158 - } elseif ($this->excludedTerms === null) {
243 + }
244 +
245 + if ($this->excludedTerms === null) {
159 246 $this->excludedTerms = $this->getExcludedObjects(ObjectHandler::GENERAL_TERM_OBJECT_TYPE);
160 247 }
161 248
162 249 return $this->excludedTerms;
@@ -161,54 +248,69 @@
161 248
162 249 return $this->excludedTerms;
163 250 }
164 251
165 - private function getVisiblePostTypes(): array
252 + /**
253 + * Returns the none hidden post types map.
254 + * @return array
255 + */
256 + private function getNoneHiddenPostTypes(): ?array
166 257 {
167 - if ($this->visiblePostTypes !== null) {
168 - return $this->visiblePostTypes;
169 - }
258 + if ($this->noneHiddenPostTypes === null) {
259 + $this->noneHiddenPostTypes = [];
170 260
171 - $this->visiblePostTypes = [];
261 + if ($this->wordpress->isAdmin() === false) {
262 + $postTypes = $this->objectHandler->getPostTypes();
172 263
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;
264 + foreach ($postTypes as $postType) {
265 + if ($this->mainConfig->hidePostType($postType) === false) {
266 + $this->noneHiddenPostTypes[$postType] = $postType;
267 + }
177 268 }
178 269 }
179 270 }
180 271
181 - return $this->visiblePostTypes;
272 + return $this->noneHiddenPostTypes;
182 273 }
183 274
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 275 /**
276 + * Returns the excluded posts.
277 + * @return array
196 278 * @throws UserGroupTypeException
197 279 */
198 280 public function getExcludedPosts(): ?array
199 281 {
200 - if ($this->canManageUserGroups() === true) {
282 + if ($this->userHandler->checkUserAccess(UserHandler::MANAGE_USER_GROUPS_CAPABILITY)) {
201 283 $this->excludedPosts = [];
202 - } elseif ($this->excludedPosts === null) {
203 - $excludedPosts = $this->getExcludedObjects(
204 - ObjectHandler::GENERAL_POST_OBJECT_TYPE,
205 - $this->getVisiblePostTypes()
206 - );
284 + }
207 285
208 - $this->excludedPosts = ($this->mainConfig->authorsHasAccessToOwn() === true)
209 - ? array_diff_key($excludedPosts, $this->getOwnPostIds())
210 - : $excludedPosts;
286 + if ($this->excludedPosts === null) {
287 + $noneHiddenPostTypes = $this->getNoneHiddenPostTypes();
288 + $excludedPosts = $this->getExcludedObjects(ObjectHandler::GENERAL_POST_OBJECT_TYPE, $noneHiddenPostTypes);
289 +
290 + if ($this->mainConfig->authorsHasAccessToOwn() === true) {
291 + $query = $this->database->prepare(
292 + "SELECT ID FROM {$this->database->getPostsTable()}
293 + WHERE post_author = %d",
294 + $this->wordpress->getCurrentUser()->ID
295 + );
296 +
297 + $ownPosts = array_filter(
298 + (array) $this->database->getResults($query),
299 + function ($ownPost) {
300 + return isset($ownPost->ID);
301 + }
302 + );
303 + $ownPostIds = [];
304 +
305 + foreach ($ownPosts as $ownPost) {
306 + $ownPostIds[$ownPost->ID] = $ownPost->ID;
307 + }
308 +
309 + $excludedPosts = array_diff_key($excludedPosts, $ownPostIds);
310 + }
311 +
312 + $this->excludedPosts = $excludedPosts;
211 313 }
212 314
213 315 return $this->excludedPosts;
214 316 }