PluginProbe
User Access Manager / 2.3.4
User Access Manager v2.3.4
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/Controller/Frontend/PostController.php +13 -186 2.3.152.3.4 View file →
@@ -16,27 +16,18 @@
16 16 use UserAccessManager\UserGroup\UserGroupTypeException;
17 17 use UserAccessManager\Util\Util;
18 18 use UserAccessManager\Wrapper\Php;
19 19 use UserAccessManager\Wrapper\Wordpress;
20 -use WeakMap;
21 20 use WP_Comment;
22 -use WP_Error;
23 21 use WP_Hook;
24 22 use WP_Post;
25 23 use WP_Query;
26 -use WP_REST_Request;
27 -use WP_REST_Response;
28 24
29 25 class PostController extends ContentController
30 26 {
31 - private const REST_OBJECT_ROUTE_PATTERN = '#^/[^/]+/v\d+/([^/]+)/(\d+)(?:/(\w+))?#';
32 -
33 27 private array $wordpressFilters = [];
34 28 private stdClass|array|null $cachedCounts = [];
35 - private ?array $restBaseToPostTypeMap = null;
36 29
37 - private WeakMap $posts;
38 -
39 30 public function __construct(
40 31 Php $php,
41 32 Wordpress $wordpress,
42 33 WordpressConfig $wordpressConfig,
@@ -58,10 +49,8 @@
58 49 $userHandler,
59 50 $userGroupHandler,
60 51 $accessHandler
61 52 );
62 -
63 - $this->posts = new WeakMap();
64 53 }
65 54
66 55 public function getWordpressFilters(): array
67 56 {
@@ -73,13 +62,8 @@
73 62 return isset($wpQuery->query_vars['suppress_filters']) === true
74 63 && $wpQuery->query_vars['suppress_filters'] === true;
75 64 }
76 65
77 - private function addExcludedPosts(mixed $postsNotIn, array $excludedPosts): array
78 - {
79 - return array_unique(array_merge((array) $postsNotIn, $excludedPosts));
80 - }
81 -
82 66 /**
83 67 * @throws UserGroupTypeException
84 68 */
85 69 public function parseQuery(WP_Query $wpQuery): void
@@ -87,11 +71,13 @@
87 71 if ($this->filtersSuppressed($wpQuery) === true) {
88 72 $excludedPosts = $this->accessHandler->getExcludedPosts();
89 73
90 74 if ($excludedPosts !== []) {
91 - $wpQuery->query_vars['post__not_in'] = $this->addExcludedPosts(
92 - $wpQuery->query_vars['post__not_in'] ?? [],
93 - $excludedPosts
75 + $postsNotIn = (isset($wpQuery->query_vars['post__not_in']) === true) ?
76 + $wpQuery->query_vars['post__not_in'] : [];
77 +
78 + $wpQuery->query_vars['post__not_in'] = array_unique(
79 + array_merge($postsNotIn, $excludedPosts)
94 80 );
95 81 }
96 82 }
97 83 }
@@ -180,15 +166,15 @@
180 166
181 167 /**
182 168 * @throws UserGroupTypeException
183 169 */
184 - private function processPost(WP_Post $post): WP_Post|bool
170 + private function processPost(WP_Post $post): ?WP_Post
185 171 {
186 172 $post->post_title .= $this->adminOutput($post->post_type, $post->ID);
187 173
188 174 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === false) {
189 175 if ($this->removePostFromList($post->post_type) === true) {
190 - return false;
176 + return null;
191 177 }
192 178
193 179 $post->post_content = $this->processPostContent($post);
194 180
@@ -206,17 +192,8 @@
206 192
207 193 /**
208 194 * @throws UserGroupTypeException
209 195 */
210 - private function getProcessedPost(WP_Post $post): ?WP_Post
211 - {
212 - $post = $this->posts[$post] ??= $this->processPost($post);
213 - return $post === false ? null : $post;
214 - }
215 -
216 - /**
217 - * @throws UserGroupTypeException
218 - */
219 196 private function filterRawPosts(array $rawPosts): array
220 197 {
221 198 $filteredPosts = [];
222 199
@@ -223,9 +200,9 @@
223 200 foreach ($rawPosts as $rawPost) {
224 201 $post = $this->getPost($rawPost);
225 202
226 203 if ($post !== false) {
227 - $post = $this->getProcessedPost($post);
204 + $post = $this->processPost($post);
228 205
229 206 if ($post !== null) {
230 207 $filteredPosts[] = $post;
231 208 }
@@ -259,161 +236,11 @@
259 236 {
260 237 return $this->filterRawPosts($rawPages);
261 238 }
262 239
263 - private function getRestAccessDeniedError(): WP_Error
264 - {
265 - return $this->wordpress->getWpError(
266 - 'uam_rest_access_denied',
267 - TXT_UAM_REST_ACCESS_DENIED,
268 - ['status' => $this->wordpress->isUserLoggedIn() === true ? 403 : 401]
269 - );
270 - }
271 -
272 - private function isSingleObjectRestRequest(mixed $request, WP_Post $post): bool
273 - {
274 - $routeId = $request instanceof WP_REST_Request ? ($request->get_url_params()['id'] ?? null) : null;
275 -
276 - return $routeId !== null && (int) $routeId === (int) $post->ID;
277 - }
278 -
279 - private function setRestField(array &$data, string $field, string $value): void
280 - {
281 - if (array_key_exists($field, $data) === false) {
282 - return;
283 - }
284 -
285 - if (is_array($data[$field]) === false) {
286 - $data[$field] = $value;
287 -
288 - return;
289 - }
290 -
291 - $restrictedValues = ['rendered' => $value, 'raw' => $value, 'protected' => false];
292 -
293 - foreach ($restrictedValues as $key => $restrictedValue) {
294 - if (array_key_exists($key, $data[$field]) === true) {
295 - $data[$field][$key] = $restrictedValue;
296 - }
297 - }
298 - }
299 -
300 240 /**
301 241 * @throws UserGroupTypeException
302 242 */
303 - public function restrictRestResponse(mixed $response, mixed $post = null, mixed $request = null): mixed
304 - {
305 - if (($response instanceof WP_REST_Response) === false
306 - || ($post instanceof WP_Post) === false
307 - || $this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === true
308 - ) {
309 - return $response;
310 - }
311 -
312 - if ($this->removePostFromList($post->post_type) === true
313 - && $this->isSingleObjectRestRequest($request, $post) === true
314 - ) {
315 - return $this->getRestAccessDeniedError();
316 - }
317 -
318 - $restrictedContent = $this->processPostContent($post);
319 - $data = (array) $response->get_data();
320 -
321 - $this->setRestField($data, 'content', $restrictedContent);
322 - $this->setRestField($data, 'excerpt', $restrictedContent);
323 -
324 - if ($this->mainConfig->hidePostTypeTitle($post->post_type) === true) {
325 - $this->setRestField($data, 'title', $this->mainConfig->getPostTypeTitle($post->post_type));
326 - }
327 -
328 - $response->set_data($data);
329 -
330 - return $response;
331 - }
332 -
333 - /**
334 - * @throws UserGroupTypeException
335 - */
336 - public function excludeRestrictedPostsFromRestQuery(array $queryArgs): array
337 - {
338 - $excludedPosts = $this->accessHandler->getExcludedPosts();
339 -
340 - if ($excludedPosts !== []) {
341 - $queryArgs['post__not_in'] = $this->addExcludedPosts($queryArgs['post__not_in'] ?? [], $excludedPosts);
342 - }
343 -
344 - return $queryArgs;
345 - }
346 -
347 - private function getRestBaseToPostTypeMap(): array
348 - {
349 - if ($this->restBaseToPostTypeMap !== null) {
350 - return $this->restBaseToPostTypeMap;
351 - }
352 -
353 - $this->restBaseToPostTypeMap = [];
354 -
355 - foreach ((array) $this->objectHandler->getPostTypes() as $postType) {
356 - $restBase = $this->wordpress->getPostTypeObject($postType)?->rest_base;
357 - $this->restBaseToPostTypeMap[empty($restBase) === true ? $postType : $restBase] = $postType;
358 - }
359 -
360 - return $this->restBaseToPostTypeMap;
361 - }
362 -
363 - /**
364 - * @return array{0: string, 1: int}|null
365 - */
366 - private function getGuardedRestRouteTarget(WP_REST_Request $request): ?array
367 - {
368 - if (preg_match(self::REST_OBJECT_ROUTE_PATTERN, (string) $request->get_route(), $matches) !== 1) {
369 - return null;
370 - }
371 -
372 - $isSubResourceRoute = ($matches[3] ?? '') !== '';
373 - $isReadingRequest = in_array(
374 - strtoupper((string) $request->get_method()),
375 - Wordpress::REST_READING_METHODS,
376 - true
377 - );
378 -
379 - if ($isReadingRequest === true && $isSubResourceRoute === false) {
380 - return null;
381 - }
382 -
383 - $postType = $this->getRestBaseToPostTypeMap()[$matches[1]] ?? null;
384 -
385 - return $postType === null ? null : [$postType, (int) $matches[2]];
386 - }
387 -
388 - /**
389 - * @throws UserGroupTypeException
390 - */
391 - public function restrictRestRequest(mixed $result, mixed $server = null, mixed $request = null): mixed
392 - {
393 - if (($request instanceof WP_REST_Request) === false) {
394 - return $result;
395 - }
396 -
397 - $routeTarget = $this->getGuardedRestRouteTarget($request);
398 -
399 - $this->wordpress->setRestRequestContext(
400 - $routeTarget !== null || $request->get_param('context') === 'edit'
401 - );
402 -
403 - if ($result !== null
404 - || $routeTarget === null
405 - || $this->accessHandler->checkObjectAccess($routeTarget[0], $routeTarget[1], true) === true
406 - ) {
407 - return $result;
408 - }
409 -
410 - return $this->getRestAccessDeniedError();
411 - }
412 -
413 - /**
414 - * @throws UserGroupTypeException
415 - */
416 243 public function getAttachedFile(string $file, int|string|null $attachmentId): bool|string
417 244 {
418 245 $isImage = (bool) preg_match('/(?i)\.(jpg|jpeg|jpe|png|gif)$/', $file);
419 246
@@ -432,9 +259,9 @@
432 259 {
433 260 $excludedPosts = $this->accessHandler->getExcludedPosts();
434 261
435 262 if ($excludedPosts !== []) {
436 - $excludedPostsStr = implode(', ', array_map('intval', $excludedPosts));
263 + $excludedPostsStr = implode(', ', $excludedPosts);
437 264 $query .= " AND $table.ID NOT IN ($excludedPostsStr) ";
438 265 }
439 266
440 267 return $query;
@@ -457,13 +284,13 @@
457 284 }
458 285
459 286 private function getPostCountQuery(array $excludedPosts, string $type, string $perm): string
460 287 {
461 - $excludedPosts = implode(', ', array_map('intval', $excludedPosts));
462 - $query = "SELECT post_status, COUNT(*) AS num_posts
463 - FROM {$this->database->getPostsTable()}
288 + $excludedPosts = implode('\', \'', $excludedPosts);
289 + $query = "SELECT post_status, COUNT(*) AS num_posts
290 + FROM {$this->database->getPostsTable()}
464 291 WHERE post_type = %s
465 - AND ID NOT IN ($excludedPosts)";
292 + AND ID NOT IN ('$excludedPosts')";
466 293
467 294 if ('readable' === $perm
468 295 && $this->wordpress->isUserLoggedIn() === true
469 296 && $this->wordpress->currentUserCan(