PluginProbe
User Access Manager / 2.3.9
User Access Manager v2.3.9
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
user-access-manager / src / Controller / Frontend / PostController.php

PostController.php in User Access Manager 2.3.9, at src/Controller/Frontend/PostController.php

407 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace UserAccessManager\Controller\Frontend;
6
7 use stdClass;
8 use UserAccessManager\Access\AccessHandler;
9 use UserAccessManager\Config\MainConfig;
10 use UserAccessManager\Config\WordpressConfig;
11 use UserAccessManager\Database\Database;
12 use UserAccessManager\Object\ObjectHandler;
13 use UserAccessManager\User\UserHandler;
14 use UserAccessManager\UserGroup\AbstractUserGroup;
15 use UserAccessManager\UserGroup\UserGroupHandler;
16 use UserAccessManager\UserGroup\UserGroupTypeException;
17 use UserAccessManager\Util\Util;
18 use UserAccessManager\Wrapper\Php;
19 use UserAccessManager\Wrapper\Wordpress;
20 use WP_Comment;
21 use WP_Hook;
22 use WP_Post;
23 use WP_Query;
24
25 class PostController extends ContentController
26 {
27 private array $wordpressFilters = [];
28 private stdClass|array|null $cachedCounts = [];
29
30 public function __construct(
31 Php $php,
32 Wordpress $wordpress,
33 WordpressConfig $wordpressConfig,
34 MainConfig $mainConfig,
35 Util $util,
36 ObjectHandler $objectHandler,
37 UserHandler $userHandler,
38 UserGroupHandler $userGroupHandler,
39 AccessHandler $accessHandler,
40 private Database $database
41 ) {
42 parent::__construct(
43 $php,
44 $wordpress,
45 $wordpressConfig,
46 $mainConfig,
47 $util,
48 $objectHandler,
49 $userHandler,
50 $userGroupHandler,
51 $accessHandler
52 );
53 }
54
55 public function getWordpressFilters(): array
56 {
57 return $this->wordpressFilters;
58 }
59
60 private function filtersSuppressed(WP_Query $wpQuery): bool
61 {
62 return isset($wpQuery->query_vars['suppress_filters']) === true
63 && $wpQuery->query_vars['suppress_filters'] === true;
64 }
65
66 /**
67 * @throws UserGroupTypeException
68 */
69 public function parseQuery(WP_Query $wpQuery): void
70 {
71 if ($this->filtersSuppressed($wpQuery) === true) {
72 $excludedPosts = $this->accessHandler->getExcludedPosts();
73
74 if ($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)
80 );
81 }
82 }
83 }
84
85 /**
86 * @param WP_Hook[] $filters
87 */
88 private function extractOwnFilters(array $filters): bool
89 {
90 if (isset($filters['the_posts']->callbacks[10]) === true) {
91 foreach ($filters['the_posts']->callbacks[10] as $postFilter) {
92 if (is_array($postFilter['function']) === true
93 && $postFilter['function'][0] instanceof PostController
94 && $postFilter['function'][1] === 'showPosts'
95 ) {
96 $this->wordpressFilters['the_posts'] = $filters['the_posts'];
97 $filters['the_posts']->callbacks = [10 => [$postFilter]];
98 return true;
99 }
100 }
101 }
102
103 return false;
104 }
105
106 public function postsPreQuery(?array $posts, WP_Query $query): ?array
107 {
108 if ($this->filtersSuppressed($query) === true) {
109 $filters = $this->wordpress->getFilters();
110
111 // Only unset filter if the user access filter is active
112 if ($this->extractOwnFilters($filters) === true) {
113 $query->query_vars['suppress_filters'] = false;
114
115 if (isset($filters['posts_results']) === true) {
116 $this->wordpressFilters['posts_results'] = $filters['posts_results'];
117 unset($filters['posts_results']);
118 }
119
120 $this->wordpress->setFilters($filters);
121 }
122 }
123
124 return $posts;
125 }
126
127 private function restoreFilters(): void
128 {
129 if (count($this->wordpressFilters) > 0) {
130 $filters = $this->wordpress->getFilters();
131
132 foreach ($this->wordpressFilters as $filterKey => $filter) {
133 $filters[$filterKey] = $filter;
134 }
135
136 $this->wordpress->setFilters($filters);
137 $this->wordpressFilters = [];
138 }
139 }
140
141 private function getPost(mixed $post): bool|WP_Post
142 {
143 if ($post instanceof WP_post) {
144 return $post;
145 } elseif (is_int($post) === true) {
146 return $this->objectHandler->getPost($post);
147 } elseif (isset($post->ID) === true) {
148 return $this->objectHandler->getPost($post->ID);
149 }
150
151 return false;
152 }
153
154 private function processPostContent(WP_Post $post): string
155 {
156 $uamPostContent = htmlspecialchars_decode($this->mainConfig->getPostTypeContent($post->post_type));
157
158 if ($this->mainConfig->showPostTypeContentBeforeMore($post->post_type) === true
159 && preg_match('/<!--more(.*?)?-->/', $post->post_content, $matches)
160 ) {
161 $uamPostContent = explode($matches[0], $post->post_content)[0] . ' ' . $uamPostContent;
162 }
163
164 return stripslashes($uamPostContent);
165 }
166
167 /**
168 * @throws UserGroupTypeException
169 */
170 private function processPost(WP_Post $post): ?WP_Post
171 {
172 $post->post_title .= $this->adminOutput($post->post_type, $post->ID);
173
174 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === false) {
175 if ($this->removePostFromList($post->post_type) === true) {
176 return null;
177 }
178
179 $post->post_content = $this->processPostContent($post);
180
181 if ($this->mainConfig->hidePostTypeTitle($post->post_type) === true) {
182 $post->post_title = $this->mainConfig->getPostTypeTitle($post->post_type);
183 }
184
185 if ($this->mainConfig->lockPostTypeComments($post->post_type) === true) {
186 $post->comment_status = 'close';
187 }
188 }
189
190 return $post;
191 }
192
193 /**
194 * @throws UserGroupTypeException
195 */
196 private function filterRawPosts(array $rawPosts): array
197 {
198 $filteredPosts = [];
199
200 foreach ($rawPosts as $rawPost) {
201 $post = $this->getPost($rawPost);
202
203 if ($post !== false) {
204 $post = $this->processPost($post);
205
206 if ($post !== null) {
207 $filteredPosts[] = $post;
208 }
209 } else {
210 $filteredPosts[] = $rawPost;
211 }
212 }
213
214 return $filteredPosts;
215 }
216
217 /**
218 * @throws UserGroupTypeException
219 */
220 public function showPosts(?array $showPosts = []): ?array
221 {
222 if ($this->wordpress->isFeed() === false || $this->mainConfig->protectFeed() === true) {
223 $showPosts = $this->filterRawPosts((array) $showPosts);
224 }
225
226 $this->restoreFilters();
227
228 return $showPosts;
229 }
230
231 /**
232 * @param WP_Post[] $rawPages The pages.
233 * @throws UserGroupTypeException
234 */
235 public function showPages(array $rawPages = []): array
236 {
237 return $this->filterRawPosts($rawPages);
238 }
239
240 /**
241 * @throws UserGroupTypeException
242 */
243 public function getAttachedFile(string $file, int|string|null $attachmentId): bool|string
244 {
245 $isImage = (bool) preg_match('/(?i)\.(jpg|jpeg|jpe|png|gif)$/', $file);
246
247 if ($isImage === false && $this->mainConfig->lockFile() === true) {
248 $hasAccess = $this->accessHandler->checkObjectAccess(ObjectHandler::ATTACHMENT_OBJECT_TYPE, $attachmentId);
249 return ($hasAccess === true) ? $file : false;
250 }
251
252 return $file;
253 }
254
255 /**
256 * @throws UserGroupTypeException
257 */
258 private function addQueryExcludedPostFilter(string $query, string $table): string
259 {
260 $excludedPosts = $this->accessHandler->getExcludedPosts();
261
262 if ($excludedPosts !== []) {
263 $excludedPostsStr = implode(', ', $excludedPosts);
264 $query .= " AND $table.ID NOT IN ($excludedPostsStr) ";
265 }
266
267 return $query;
268 }
269
270 /**
271 * @throws UserGroupTypeException
272 */
273 public function showPostSql(string $query): string
274 {
275 return $this->addQueryExcludedPostFilter($query, $this->database->getPostsTable());
276 }
277
278 /**
279 * @throws UserGroupTypeException
280 */
281 public function showNextPreviousPost(string $query): string
282 {
283 return $this->addQueryExcludedPostFilter($query, 'p');
284 }
285
286 private function getPostCountQuery(array $excludedPosts, string $type, string $perm): string
287 {
288 $excludedPosts = implode('\', \'', $excludedPosts);
289 $query = "SELECT post_status, COUNT(*) AS num_posts
290 FROM {$this->database->getPostsTable()}
291 WHERE post_type = %s
292 AND ID NOT IN ('$excludedPosts')";
293
294 if ('readable' === $perm
295 && $this->wordpress->isUserLoggedIn() === true
296 && $this->wordpress->currentUserCan(
297 $this->wordpress->getPostTypeObject($type)->cap->read_private_posts
298 ) === false
299 ) {
300 $query .= $this->database->prepare(
301 ' AND (post_status != \'private\' OR (post_author = %d AND post_status = \'private\'))',
302 $this->wordpress->getCurrentUser()->ID
303 );
304 }
305
306 $query .= ' GROUP BY post_status';
307 return $query;
308 }
309
310 /**
311 * @throws UserGroupTypeException
312 */
313 public function showPostCount(stdClass $counts, string $type, string $perm): stdClass
314 {
315 if (isset($this->cachedCounts[$type]) === false) {
316 $excludedPosts = $this->accessHandler->getExcludedPosts();
317
318 if ($excludedPosts !== []) {
319 $query = $this->getPostCountQuery($excludedPosts, $type, $perm);
320 $results = (array) $this->database->getResults(
321 $this->database->prepare($query, $type),
322 ARRAY_A
323 );
324
325 foreach ($results as $result) {
326 if (isset($counts->{$result['post_status']})) {
327 $counts->{$result['post_status']} = $result['num_posts'];
328 }
329 }
330 }
331
332 $this->cachedCounts[$type] = $counts;
333 }
334
335 return $this->cachedCounts[$type];
336 }
337
338 private function hidePostComment(string $postType): bool
339 {
340 return $this->mainConfig->lockPostTypeComments($postType) === true
341 || $this->mainConfig->hidePostType($postType) === true
342 || $this->wordpressConfig->atAdminPanel() === true;
343 }
344
345 /**
346 * @param WP_Comment[] $comments The comments.
347 * @throws UserGroupTypeException
348 */
349 public function showComment(array $comments = []): array
350 {
351 $showComments = [];
352
353 foreach ($comments as $comment) {
354 $post = $this->objectHandler->getPost($comment->comment_post_ID);
355
356 if ($post !== false
357 && $this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === false
358 ) {
359 if ($this->hidePostComment($post->post_type)) {
360 continue;
361 }
362
363 if ($this->mainConfig->hidePostTypeComments($post->post_type) === true) {
364 $comment->comment_content = $this->mainConfig->getPostTypeCommentContent($post->post_type);
365 }
366 }
367
368 $showComments[] = $comment;
369 }
370
371 return $showComments;
372 }
373
374 /**
375 * @throws UserGroupTypeException
376 */
377 public function showEditLink(?string $link, int|string|null $postId): string
378 {
379 if ($this->mainConfig->hideEditLinkOnNoAccess() === true
380 && $this->accessHandler->checkObjectAccess(ObjectHandler::GENERAL_POST_OBJECT_TYPE, $postId, true) === false
381 ) {
382 $link = '';
383 }
384
385 if ($this->mainConfig->showAssignedGroups() === true) {
386 $userGroups = $this->userGroupHandler->getFilteredUserGroupsForObject(
387 ObjectHandler::GENERAL_POST_OBJECT_TYPE,
388 $postId
389 );
390
391 if (count($userGroups) > 0) {
392 $escapedGroups = array_map(
393 function (AbstractUserGroup $group) {
394 return htmlentities($group->getName());
395 },
396 $userGroups
397 );
398
399 $link .= $link !== '' ? ' | ' : ' ';
400 $link .= TXT_UAM_ASSIGNED_GROUPS . ': ' . implode(', ', $escapedGroups);
401 }
402 }
403
404 return (string) $link;
405 }
406 }
407