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

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