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

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

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