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

538 lines 15.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\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 = null;
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 ($post->post_type === 'post'
232 && $this->mainConfig->showPostContentBeforeMore() === true
233 && preg_match('/<!--more(.*?)?-->/', $post->post_content, $matches)
234 ) {
235 $uamPostContent = explode($matches[0], $post->post_content)[0].' '.$uamPostContent;
236 }
237
238 return stripslashes($uamPostContent);
239 }
240
241 /**
242 * Modifies the content of the post by the given settings.
243 *
244 * @param \WP_Post $post The current post.
245 *
246 * @return null|\WP_Post
247 */
248 private function processPost(\WP_Post $post)
249 {
250 $post->post_title .= $this->adminOutput($post->post_type, $post->ID);
251
252 if ($this->accessHandler->checkObjectAccess($post->post_type, $post->ID) === false) {
253 if ($this->removePostFromList($post->post_type) === true) {
254 return null;
255 }
256
257 $post->post_content = $this->processPostContent($post);
258
259 if ($this->mainConfig->hidePostTypeTitle($post->post_type) === true) {
260 $post->post_title = $this->mainConfig->getPostTypeTitle($post->post_type);
261 }
262
263 if ($this->mainConfig->lockPostTypeComments($post->post_type) === true) {
264 $post->comment_status = 'close';
265 }
266 }
267
268 return $post;
269 }
270
271 /**
272 * Filters the raw posts.
273 *
274 * @param array $rawPosts
275 *
276 * @return array
277 */
278 private function filterRawPosts(array $rawPosts)
279 {
280 $filteredPosts = [];
281
282 foreach ($rawPosts as $rawPost) {
283 $post = $this->getPost($rawPost);
284
285 if ($post !== false) {
286 $post = $this->processPost($post);
287
288 if ($post !== null) {
289 $filteredPosts[] = $post;
290 }
291 } else {
292 $filteredPosts[] = $rawPost;
293 }
294 }
295
296 return $filteredPosts;
297 }
298
299 /**
300 * The function for the the_posts filter.
301 *
302 * @param array $showPosts The posts.
303 *
304 * @return array
305 */
306 public function showPosts($showPosts = [])
307 {
308 if ($this->wordpress->isFeed() === false || $this->mainConfig->protectFeed() === true) {
309 $showPosts = $this->filterRawPosts($showPosts);
310 }
311
312 $this->restoreFilters();
313
314 return $showPosts;
315 }
316
317 /**
318 * The function for the get_pages filter.
319 *
320 * @param \WP_Post[] $rawPages The pages.
321 *
322 * @return array
323 */
324 public function showPages($rawPages = [])
325 {
326 return $this->filterRawPosts($rawPages);
327 }
328
329 /**
330 * Checks the access of the attached file.
331 *
332 * @param string $file
333 * @param int $attachmentId
334 *
335 * @return string|false
336 */
337 public function getAttachedFile($file, $attachmentId)
338 {
339 //TODO add check for images
340 if ($this->mainConfig->lockFile() === true) {
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 ($this->cachedCounts === null) {
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 = $counts;
455 }
456
457 return $this->cachedCounts;
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 showGroupMembership($link, $postId)
515 {
516 if ($this->mainConfig->showAssignedGroups() === true) {
517 $userGroups = $this->userGroupHandler->getFilteredUserGroupsForObject(
518 ObjectHandler::GENERAL_POST_OBJECT_TYPE,
519 $postId
520 );
521
522 if (count($userGroups) > 0) {
523 $escapedGroups = array_map(
524 function (AbstractUserGroup $group) {
525 return htmlentities($group->getName());
526 },
527 $userGroups
528 );
529
530 $link .= ' | '.TXT_UAM_ASSIGNED_GROUPS.': ';
531 $link .= implode(', ', $escapedGroups);
532 }
533 }
534
535 return $link;
536 }
537 }
538