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

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