PluginProbe
User Access Manager / 2.1.12
User Access Manager v2.1.12
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.1.12, at src/Controller/Frontend/PostController.php

544 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * FrontendPostController.php
4 *
5 * The FrontendPostController 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 */
15 namespace UserAccessManager\Controller\Frontend;
16
17 use UserAccessManager\Access\AccessHandler;
18 use UserAccessManager\Config\MainConfig;
19 use UserAccessManager\Config\WordpressConfig;
20 use UserAccessManager\Database\Database;
21 use UserAccessManager\Object\ObjectHandler;
22 use UserAccessManager\UserGroup\AbstractUserGroup;
23 use UserAccessManager\User\UserHandler;
24 use UserAccessManager\UserGroup\UserGroupHandler;
25 use UserAccessManager\Util\Util;
26 use UserAccessManager\Wrapper\Php;
27 use UserAccessManager\Wrapper\Wordpress;
28
29 /**
30 * Class FrontendPostController
31 *
32 * @package UserAccessManager\Controller
33 */
34 class PostController extends ContentController
35 {
36 /**
37 * @var Database
38 */
39 private $database;
40
41 /**
42 * @var array
43 */
44 private $wordpressFilters = [];
45
46 /**
47 * @var null|\stdClass
48 */
49 private $cachedCounts = [];
50
51 /**
52 * PostController constructor.
53 *
54 * @param Php $php
55 * @param Wordpress $wordpress
56 * @param WordpressConfig $wordpressConfig
57 * @param MainConfig $mainConfig
58 * @param Database $database
59 * @param Util $util
60 * @param ObjectHandler $objectHandler
61 * @param UserHandler $userHandler
62 * @param UserGroupHandler $userGroupHandler
63 * @param AccessHandler $accessHandler
64 */
65 public function __construct(
66 Php $php,
67 Wordpress $wordpress,
68 WordpressConfig $wordpressConfig,
69 MainConfig $mainConfig,
70 Database $database,
71 Util $util,
72 ObjectHandler $objectHandler,
73 UserHandler $userHandler,
74 UserGroupHandler $userGroupHandler,
75 AccessHandler $accessHandler
76 ) {
77 parent::__construct(
78 $php,
79 $wordpress,
80 $wordpressConfig,
81 $mainConfig,
82 $util,
83 $objectHandler,
84 $userHandler,
85 $userGroupHandler,
86 $accessHandler
87 );
88 $this->database = $database;
89 }
90
91
92
93 /**
94 * Returns true if the filters are suppressed.
95 *
96 * @param \WP_Query $wpQuery
97 *
98 * @return bool
99 */
100 private function filtersSuppressed($wpQuery)
101 {
102 return isset($wpQuery->query_vars['suppress_filters']) === true
103 && $wpQuery->query_vars['suppress_filters'] === true;
104 }
105
106 /**
107 * Manipulates the wordpress query object to filter content.
108 *
109 * @param \WP_Query $wpQuery The wordpress query object.
110 */
111 public function parseQuery($wpQuery)
112 {
113 if ($this->filtersSuppressed($wpQuery) === true) {
114 $excludedPosts = $this->accessHandler->getExcludedPosts();
115
116 if ($excludedPosts !== []) {
117 $postsNotIn = (isset($wpQuery->query_vars['post__not_in']) === true) ?
118 $wpQuery->query_vars['post__not_in'] : [];
119
120 $wpQuery->query_vars['post__not_in'] = array_unique(
121 array_merge($postsNotIn, $excludedPosts)
122 );
123 }
124 }
125 }
126
127 /**
128 * Extracts the user access manager filters and returns true if it was successful.
129 *
130 * @param \WP_Hook[] $filters
131 *
132 * @return bool
133 */
134 private function extractOwnFilters(array &$filters)
135 {
136 if (isset($filters['the_posts']->callbacks[10]) === true) {
137 foreach ($filters['the_posts']->callbacks[10] as $postFilter) {
138 if (is_array($postFilter['function']) === true
139 && $postFilter['function'][0] instanceof PostController
140 && $postFilter['function'][1] === 'showPosts'
141 ) {
142 $this->wordpressFilters['the_posts'] = $filters['the_posts'];
143 $filters['the_posts']->callbacks = [10 => [$postFilter]];
144 return true;
145 }
146 }
147 }
148
149 return false;
150 }
151
152 /**
153 * If filters are suppressed we still want to filter posts, so we have to turn the suppression off,
154 * remove all other filters than the ones from the user access manager and store them to restore
155 * them later.
156 *
157 * @param array $posts
158 * @param \WP_Query $query
159 *
160 * @return mixed
161 */
162 public function postsPreQuery($posts, \WP_Query $query)
163 {
164 if ($this->filtersSuppressed($query) === true) {
165 $filters = $this->wordpress->getFilters();
166
167 // Only unset filter if the user access filter is active
168 if ($this->extractOwnFilters($filters) === true) {
169 $query->query_vars['suppress_filters'] = false;
170
171 if (isset($filters['posts_results']) === true) {
172 $this->wordpressFilters['posts_results'] = $filters['posts_results'];
173 unset($filters['posts_results']);
174 }
175
176 $this->wordpress->setFilters($filters);
177 }
178 }
179
180 return $posts;
181 }
182
183 /**
184 * Restores the filters to normal.
185 */
186 private function restoreFilters()
187 {
188 if (count($this->wordpressFilters) > 0) {
189 $filters = $this->wordpress->getFilters();
190
191 foreach ($this->wordpressFilters as $filterKey => $filter) {
192 $filters[$filterKey] = $filter;
193 }
194
195 $this->wordpress->setFilters($filters);
196 $this->wordpressFilters = [];
197 }
198 }
199
200 /**
201 * Tries to get the post from the given mixed data.
202 *
203 * @param mixed $post
204 *
205 * @return false|\WP_Post
206 */
207 private function getPost($post)
208 {
209 if ($post instanceof \WP_post) {
210 return $post;
211 } elseif (is_int($post) === true) {
212 return $this->objectHandler->getPost($post);
213 } elseif (isset($post->ID) === true) {
214 return $this->objectHandler->getPost($post->ID);
215 }
216
217 return false;
218 }
219
220 /**
221 * Processes the post content and searches for the more tag.
222 *
223 * @param \WP_Post $post
224 *
225 * @return string
226 */
227 private function processPostContent(\WP_Post $post)
228 {
229 $uamPostContent = htmlspecialchars_decode($this->mainConfig->getPostTypeContent($post->post_type));
230
231 if ($this->mainConfig->showPostTypeContentBeforeMore($post->post_type) === true
232 && preg_match('/<!--more(.*?)?-->/', $post->post_content, $matches)
233 ) {
234 $uamPostContent = explode($matches[0], $post->post_content)[0].' '.$uamPostContent;
235 }
236
237 return stripslashes($uamPostContent);
238 }
239
240 /**
241 * Modifies the content of the post by the given settings.
242 *
243 * @param \WP_Post $post The current post.
244 *
245 * @return null|\WP_Post
246 */
247 private function processPost(\WP_Post $post)
248 {
249 $post->post_title .= $this->adminOutput($post->post_type, $post->ID);
250
251 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === false) {
252 if ($this->removePostFromList($post->post_type) === true) {
253 return null;
254 }
255
256 $post->post_content = $this->processPostContent($post);
257
258 if ($this->mainConfig->hidePostTypeTitle($post->post_type) === true) {
259 $post->post_title = $this->mainConfig->getPostTypeTitle($post->post_type);
260 }
261
262 if ($this->mainConfig->lockPostTypeComments($post->post_type) === true) {
263 $post->comment_status = 'close';
264 }
265 }
266
267 return $post;
268 }
269
270 /**
271 * Filters the raw posts.
272 *
273 * @param array $rawPosts
274 *
275 * @return array
276 */
277 private function filterRawPosts(array $rawPosts)
278 {
279 $filteredPosts = [];
280
281 foreach ($rawPosts as $rawPost) {
282 $post = $this->getPost($rawPost);
283
284 if ($post !== false) {
285 $post = $this->processPost($post);
286
287 if ($post !== null) {
288 $filteredPosts[] = $post;
289 }
290 } else {
291 $filteredPosts[] = $rawPost;
292 }
293 }
294
295 return $filteredPosts;
296 }
297
298 /**
299 * The function for the the_posts filter.
300 *
301 * @param array $showPosts The posts.
302 *
303 * @return array
304 */
305 public function showPosts($showPosts = [])
306 {
307 if ($this->wordpress->isFeed() === false || $this->mainConfig->protectFeed() === true) {
308 $showPosts = $this->filterRawPosts($showPosts);
309 }
310
311 $this->restoreFilters();
312
313 return $showPosts;
314 }
315
316 /**
317 * The function for the get_pages filter.
318 *
319 * @param \WP_Post[] $rawPages The pages.
320 *
321 * @return array
322 */
323 public function showPages($rawPages = [])
324 {
325 return $this->filterRawPosts($rawPages);
326 }
327
328 /**
329 * Checks the access of the attached file.
330 *
331 * @param string $file
332 * @param int $attachmentId
333 *
334 * @return string|false
335 */
336 public function getAttachedFile($file, $attachmentId)
337 {
338 $isImage = (bool) preg_match('/(?i)\.(jpg|jpeg|jpe|png|gif)$/', $file);
339
340 if ($this->mainConfig->lockFile() === true && $isImage === false) {
341 $hasAccess = $this->accessHandler->checkObjectAccess(ObjectHandler::ATTACHMENT_OBJECT_TYPE, $attachmentId);
342 return ($hasAccess === true) ? $file : false;
343 }
344
345 return $file;
346 }
347
348 /**
349 * Adds the excluded posts filter to the given query.
350 *
351 * @param string $query
352 * @param string $table
353 *
354 * @return string
355 */
356 private function addQueryExcludedPostFilter($query, $table)
357 {
358 $excludedPosts = $this->accessHandler->getExcludedPosts();
359
360 if ($excludedPosts !== []) {
361 $excludedPostsStr = implode(', ', $excludedPosts);
362 $query .= " AND {$table}.ID NOT IN ($excludedPostsStr) ";
363 }
364
365 return $query;
366 }
367
368 /**
369 * The function for the posts_where_paged filter.
370 *
371 * @param string $query The where sql statement.
372 *
373 * @return string
374 */
375 public function showPostSql($query)
376 {
377 return $this->addQueryExcludedPostFilter($query, $this->database->getPostsTable());
378 }
379
380 /**
381 * The function for the get_previous_post_where and
382 * the get_next_post_where filter.
383 *
384 * @param string $query The current sql string.
385 *
386 * @return string
387 */
388 public function showNextPreviousPost($query)
389 {
390 return $this->addQueryExcludedPostFilter($query, 'p');
391 }
392
393 /**
394 * Returns the post count query.
395 *
396 * @param array $excludedPosts
397 * @param string $type
398 * @param string $perm
399 *
400 * @return string
401 */
402 private function getPostCountQuery(array $excludedPosts, $type, $perm)
403 {
404 $excludedPosts = implode('\', \'', $excludedPosts);
405 $query = "SELECT post_status, COUNT(*) AS num_posts
406 FROM {$this->database->getPostsTable()}
407 WHERE post_type = %s
408 AND ID NOT IN ('{$excludedPosts}')";
409
410 if ('readable' === $perm
411 && $this->wordpress->isUserLoggedIn() === true
412 && $this->wordpress->currentUserCan(
413 $this->wordpress->getPostTypeObject($type)->cap->read_private_posts
414 ) === false
415 ) {
416 $query .= $this->database->prepare(
417 ' AND (post_status != \'private\' OR (post_author = %d AND post_status = \'private\'))',
418 $this->wordpress->getCurrentUser()->ID
419 );
420 }
421
422 $query .= ' GROUP BY post_status';
423 return $query;
424 }
425
426 /**
427 * Function for the wp_count_posts filter.
428 *
429 * @param \stdClass $counts
430 * @param string $type
431 * @param string $perm
432 *
433 * @return \stdClass
434 */
435 public function showPostCount($counts, $type, $perm)
436 {
437 if (isset($this->cachedCounts[$type]) === false) {
438 $excludedPosts = $this->accessHandler->getExcludedPosts();
439
440 if ($excludedPosts !== []) {
441 $query = $this->getPostCountQuery($excludedPosts, $type, $perm);
442 $results = (array)$this->database->getResults(
443 $this->database->prepare($query, $type),
444 ARRAY_A
445 );
446
447 foreach ($results as $result) {
448 if (isset($counts->{$result['post_status']})) {
449 $counts->{$result['post_status']} = $result['num_posts'];
450 }
451 }
452 }
453
454 $this->cachedCounts[$type] = $counts;
455 }
456
457 return $this->cachedCounts[$type];
458 }
459
460 /**
461 * Checks if the post comment should be completely hidden.
462 *
463 * @param string $postType
464 *
465 * @return bool
466 */
467 private function hidePostComment($postType)
468 {
469 return $this->mainConfig->lockPostTypeComments($postType) === true
470 || $this->mainConfig->hidePostType($postType) === true
471 || $this->wordpressConfig->atAdminPanel() === true;
472 }
473
474 /**
475 * The function for the comments_array filter.
476 *
477 * @param \WP_Comment[] $comments The comments.
478 *
479 * @return array
480 */
481 public function showComment($comments = [])
482 {
483 $showComments = [];
484
485 foreach ($comments as $comment) {
486 $post = $this->objectHandler->getPost($comment->comment_post_ID);
487
488 if ($post !== false
489 && $this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === false
490 ) {
491 if ($this->hidePostComment($post->post_type)) {
492 continue;
493 }
494
495 if ($this->mainConfig->hidePostTypeComments($post->post_type) === true) {
496 $comment->comment_content = $this->mainConfig->getPostTypeCommentContent($post->post_type);
497 }
498 }
499
500 $showComments[] = $comment;
501 }
502
503 return $showComments;
504 }
505
506 /**
507 * The function for the edit_post_link filter.
508 *
509 * @param string $link The edit link.
510 * @param integer $postId The _iId of the post.
511 *
512 * @return string
513 */
514 public function showEditLink($link, $postId)
515 {
516 if ($this->mainConfig->hideEditLinkOnNoAccess() === true
517 && $this->accessHandler->checkObjectAccess(ObjectHandler::GENERAL_POST_OBJECT_TYPE, $postId, true) === false
518 ) {
519 $link = '';
520 }
521
522 if ($this->mainConfig->showAssignedGroups() === true) {
523 $userGroups = $this->userGroupHandler->getFilteredUserGroupsForObject(
524 ObjectHandler::GENERAL_POST_OBJECT_TYPE,
525 $postId
526 );
527
528 if (count($userGroups) > 0) {
529 $escapedGroups = array_map(
530 function (AbstractUserGroup $group) {
531 return htmlentities($group->getName());
532 },
533 $userGroups
534 );
535
536 $link .= $link !== '' ? ' | ' : ' ';
537 $link .= TXT_UAM_ASSIGNED_GROUPS.': '.implode(', ', $escapedGroups);
538 }
539 }
540
541 return $link;
542 }
543 }
544