Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/paid-memberships-pro/includes/content.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + /*
3 + Functions to detect member content and protect it.
4 + */
5 + function pmpro_has_membership_access($post_id = NULL, $user_id = NULL, $return_membership_levels = false)
6 + {
7 + global $post, $wpdb, $current_user;
8 +
9 + //get queried object in case we check against that
10 + if(!is_admin())
11 + $queried_object = get_queried_object();
12 + else
13 + $queried_object = NULL;
14 +
15 + //use post global or queried object if no $post_id was passed in
16 + if(!$post_id && !empty($post) && !empty($post->ID))
17 + $post_id = $post->ID;
18 + elseif(!$post_id && !empty($queried_object) && !empty($queried_object->ID))
19 + $post_id = $queried_object->ID;
20 +
21 + //no post, return true (changed from false in version 1.7.2)
22 + if(!$post_id)
23 + return true;
24 +
25 + //use current user if no value is supplied
26 + if(!$user_id)
27 + $user_id = $current_user->ID;
28 +
29 + //if no post or current_user object, set them up
30 + if(isset($queried_object->ID) && !empty($queried_object->ID) && $post_id == $queried_object->ID)
31 + $mypost = $queried_object;
32 + elseif(isset($post->ID) && !empty($post->ID) && $post_id == $post->ID)
33 + $mypost = $post;
34 + else
35 + $mypost = get_post($post_id);
36 +
37 + if($user_id == $current_user->ID)
38 + $myuser = $current_user;
39 + else
40 + $myuser = get_userdata($user_id);
41 +
42 + //for these post types, we want to check the parent
43 + if(isset($mypost->post_type) && in_array( $mypost->post_type, array("attachment", "revision")))
44 + {
45 + $mypost = get_post($mypost->post_parent);
46 + }
47 +
48 + // Allow plugins and themes to find the protected post
49 + $mypost = apply_filters( 'pmpro_membership_access_post', $mypost, $myuser );
50 +
51 + if(isset($mypost->post_type) && $mypost->post_type == "post")
52 + {
53 + // Get the categories for this post.
54 + $post_terms = wp_get_post_categories( $mypost->ID );
55 +
56 + // Get the tags for this post.
57 + $post_terms = array_merge( $post_terms, wp_get_post_tags( $mypost->ID, array('fields' => 'ids' ) ) );
58 +
59 + if( ! $post_terms )
60 + {
61 + //just check for entries in the memberships_pages table
62 + $sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "'";
63 + }
64 + else
65 + {
66 + //are any of the post categories associated with membership levels? also check the memberships_pages table
67 + $sqlQuery = "(SELECT m.id, m.name FROM $wpdb->pmpro_memberships_categories mc LEFT JOIN $wpdb->pmpro_membership_levels m ON mc.membership_id = m.id WHERE mc.category_id IN(" . implode(",", array_map( 'intval', $post_terms ) ) . ") AND m.id IS NOT NULL) UNION (SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "')";
68 + }
69 + }
70 + else
71 + {
72 + //are any membership levels associated with this page?
73 + $sqlQuery = "SELECT m.id, m.name FROM $wpdb->pmpro_memberships_pages mp LEFT JOIN $wpdb->pmpro_membership_levels m ON mp.membership_id = m.id WHERE mp.page_id = '" . esc_sql( $mypost->ID ) . "'";
74 + }
75 +
76 +
77 + $post_membership_levels = $wpdb->get_results($sqlQuery);
78 +
79 + $post_membership_levels_ids = array();
80 + $post_membership_levels_names = array();
81 +
82 + if(!$post_membership_levels)
83 + {
84 + $hasaccess = true;
85 + }
86 + else
87 + {
88 + // Reorder the $post_membership_levels to match sorted order.
89 + $post_membership_levels = pmpro_sort_levels_by_order( $post_membership_levels );
90 +
91 + //we need to see if the user has access
92 + foreach($post_membership_levels as $level)
93 + {
94 + $post_membership_levels_ids[] = $level->id;
95 + $post_membership_levels_names[] = $level->name;
96 + }
97 +
98 + //levels found. check if this is in a feed or if the current user is in at least one of those membership levels
99 + if(is_feed())
100 + {
101 + //always block restricted feeds
102 + $hasaccess = false;
103 + }
104 + elseif(!empty($myuser->ID))
105 + {
106 + $myuser->membership_level = pmpro_getMembershipLevelForUser($myuser->ID); // kept in for legacy filter users below.
107 + $myuser->membership_levels = pmpro_getMembershipLevelsForUser($myuser->ID);
108 + $mylevelids = array();
109 + foreach($myuser->membership_levels as $curlevel) {
110 + $mylevelids[] = $curlevel->id;
111 + }
112 + if(count($myuser->membership_levels)>0 && count(array_intersect($mylevelids, $post_membership_levels_ids))>0)
113 + {
114 + //the users membership id is one that will grant access
115 + $hasaccess = true;
116 + }
117 + else
118 + {
119 + //user isn't a member of a level with access
120 + $hasaccess = false;
121 + }
122 + }
123 + else
124 + {
125 + //user is not logged in and this content requires membership
126 + $hasaccess = false;
127 + }
128 + }
129 +
130 + /*
131 + Filters
132 + The generic filter is run first. Then if there is a filter for this post type, that is run.
133 + */
134 + //general filter for all posts
135 + $hasaccess = apply_filters("pmpro_has_membership_access_filter", $hasaccess, $mypost, $myuser, $post_membership_levels);
136 + //filter for this post type
137 + if( isset($mypost->post_type) && has_filter("pmpro_has_membership_access_filter_" . $mypost->post_type))
138 + $hasaccess = apply_filters("pmpro_has_membership_access_filter_" . $mypost->post_type, $hasaccess, $mypost, $myuser, $post_membership_levels);
139 +
140 + //return
141 + if($return_membership_levels)
142 + return array($hasaccess, $post_membership_levels_ids, $post_membership_levels_names);
143 + else
144 + return $hasaccess;
145 + }
146 +
147 + /**
148 + * Filter PMPro pages from search results.
149 + * @since 3.0 This functionality was moved out
150 + * of the pmpro_search_filter function.
151 + */
152 + function pmpro_search_filter_pmpro_pages( $query ) {
153 + global $pmpro_pages;
154 +
155 + // Ignore queries from the admin dashboard.
156 + if ( $query->is_admin ) {
157 + return $query;
158 + }
159 +
160 + // Ignore queries that aren't search related.
161 + if ( ! $query->is_search ) {
162 + return $query;
163 + }
164 +
165 + // Ignore post parent queries.
166 + if ( ! empty( $query->query['post_parent'] ) ) {
167 + return $query;
168 + }
169 +
170 + // We're good. Remove the PMPro pages from the results.
171 + $pmpro_page_ids = empty( $pmpro_pages ) ? array() : array_filter( array_values( $pmpro_pages ) );
172 + $query->set( 'post__not_in', array_merge( pmpro_get_post_not_in( $query ), $pmpro_page_ids ) );
173 +
174 + return $query;
175 + }
176 + add_filter( 'pre_get_posts', 'pmpro_search_filter_pmpro_pages' );
177 +
178 + /**
179 + * Filter restricted posts from searches and archive queries.
180 + */
181 + function pmpro_search_filter( $query ) {
182 + global $current_user, $wpdb, $pmpro_pages;
183 +
184 + /**
185 + * Filter which post types to hide members-only content from search.
186 + *
187 + * @param array $pmpro_search_filter_post_types The post types to include in the search filter.
188 + * The default included post types are page and post.
189 + *
190 + * @return array $pmpro_search_filter_post_types.
191 + */
192 + $pmpro_search_filter_post_types = apply_filters( 'pmpro_search_filter_post_types', array( 'page', 'post' ) );
193 + if ( ! is_array( $pmpro_search_filter_post_types ) ) {
194 + $pmpro_search_filter_post_types = array( $pmpro_search_filter_post_types );
195 + }
196 +
197 + // Ignore queries from the admin dashboard.
198 + if ( $query->is_admin ) {
199 + return $query;
200 + }
201 +
202 + // Ignore single post queries.
203 + if ( $query->is_singular ) {
204 + return $query;
205 + }
206 +
207 + // Ignore REST API requests.
208 + if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
209 + return $query;
210 + }
211 +
212 + // If post_parent is set, this is probably a menu/submenu query. Ignore it.
213 + if ( ! empty( $query->query['post_parent'] ) ) {
214 + return $query;
215 + }
216 +
217 + // If post_type is set, make sure it's in the array of post types to filter.
218 + if ( ! empty( $query->query_vars['post_type'] ) && ! array_intersect( (array)$query->query_vars['post_type'], $pmpro_search_filter_post_types ) ) {
219 + return $query;
220 + }
221 +
222 + // If posts aren't being filtered, don't filter categories either.
223 + if ( ! in_array( 'post', $pmpro_search_filter_post_types ) && $query->is_category() ) {
224 + return $query;
225 + }
226 +
227 + // If posts aren't being filtered, don't filter tags either.
228 + if ( ! in_array( 'post', $pmpro_search_filter_post_types ) && $query->is_tag() ) {
229 + return $query;
230 + }
231 +
232 + /**
233 + * Okay. We're going to filter the search results.
234 + * We save the array of posts to hide in a static var for cache.
235 + * So first, check if we have a cache, and if so use that.
236 + */
237 + static $final_hidden_posts = null;
238 + if ( isset( $final_hidden_posts ) ) {
239 + if( ! empty( $final_hidden_posts ) ) {
240 + $query->set( 'post__not_in', array_merge( pmpro_get_post_not_in( $query ), $final_hidden_posts ) );
241 + }
242 + return $query;
243 + }
244 +
245 + /**
246 + * No cache yet. Let's run the queries.
247 + * Some explanation of what we're doing.
248 + * A = All posts hidden by level.
249 + * B = All posts hidden by category.
250 + * C = All posts the current user has access to by level.
251 + * D = All posts the current user has access to by category.
252 + *
253 + * Then the final hidden posts = (A + B) - (C + D)
254 + *
255 + * Then we merge and add to post__not_in.
256 + */
257 +
258 + // First, figure out if their is a current user with levels.
259 + if ( ! empty( $current_user->ID ) ) {
260 + $levels = pmpro_getMembershipLevelsForUser( $current_user->ID );
261 + $level_ids = ! empty( $levels ) ? wp_list_pluck( $levels, 'ID' ) : [];
262 + } else {
263 + $level_ids = [];
264 + }
265 +
266 + // Query A: All posts hidden by level
267 + $sql_A = "SELECT DISTINCT(mp.page_id)
268 + FROM {$wpdb->pmpro_memberships_pages} mp
269 + LEFT JOIN {$wpdb->posts} p ON mp.page_id = p.ID
270 + WHERE p.post_type IN('" . implode( "', '", array_map('esc_sql', $pmpro_search_filter_post_types)) . "')";
271 + $posts_hidden_by_level = $wpdb->get_col( $sql_A );
272 +
273 + // Query B: All posts hidden by category
274 + $sql_B = "SELECT DISTINCT(tr.object_id)
275 + FROM {$wpdb->term_relationships} tr
276 + LEFT JOIN {$wpdb->posts} p ON tr.object_id = p.ID
277 + WHERE tr.term_taxonomy_id IN(
278 + SELECT category_id
279 + FROM {$wpdb->pmpro_memberships_categories}
280 + )
281 + AND p.post_type IN('" . implode( "', '", array_map('esc_sql', $pmpro_search_filter_post_types)) . "')";
282 + $posts_hidden_by_category = $wpdb->get_col( $sql_B );
283 +
284 + // Query C: All posts the current user has access to by level
285 + if ( ! empty( $level_ids ) ) {
286 + $sql_C = "SELECT DISTINCT(mp.page_id)
287 + FROM {$wpdb->pmpro_memberships_pages} mp
288 + LEFT JOIN {$wpdb->posts} p ON mp.page_id = p.ID
289 + WHERE mp.membership_id IN (" . implode(',', array_map('esc_sql', $level_ids)) . ")
290 + AND p.post_type IN('" . implode( "', '", array_map('esc_sql', $pmpro_search_filter_post_types)) . "')";
291 + $accessible_posts_by_level = $wpdb->get_col( $sql_C );
292 + } else {
293 + $accessible_posts_by_level = [];
294 + }
295 +
296 + // Query D: All posts the current user has access to by category
297 + if ( ! empty ($level_ids ) ) {
298 + $sql_D = "SELECT DISTINCT(tr.object_id)
299 + FROM {$wpdb->term_relationships} tr
300 + LEFT JOIN {$wpdb->posts} p ON tr.object_id = p.ID
301 + WHERE tr.term_taxonomy_id IN(
302 + SELECT category_id
303 + FROM {$wpdb->pmpro_memberships_categories}
304 + WHERE membership_id IN (" . implode(',', array_map('esc_sql', $level_ids)) . ")
305 + ) AND p.post_type IN('" . implode( "', '", array_map('esc_sql', $pmpro_search_filter_post_types)) . "')";
306 + $accessible_posts_by_category = $wpdb->get_col ($sql_D );
307 + } else {
308 + $accessible_posts_by_category = [];
309 + }
310 +
311 + // Combine and compute final hidden posts
312 + $hidden_posts = array_unique(array_merge($posts_hidden_by_level, $posts_hidden_by_category));
313 + $accessible_posts = array_unique(array_merge($accessible_posts_by_level, $accessible_posts_by_category));
314 + $final_hidden_posts = array_diff($hidden_posts, $accessible_posts);
315 +
316 + // If we have posts to hide, add them to the query.
317 + if( ! empty( $final_hidden_posts ) ) {
318 + $query->set( 'post__not_in', array_merge( pmpro_get_post_not_in( $query ), $final_hidden_posts ) );
319 + }
320 +
321 + return $query;
322 + }
323 + $filterqueries = get_option("pmpro_filterqueries");
324 + if( ! empty( $filterqueries ) ) {
325 + add_filter( 'pre_get_posts', 'pmpro_search_filter' );
326 + }
327 +
328 + function pmpro_membership_content_filter( $content, $skipcheck = false ) {
329 + global $post, $current_user;
330 +
331 + if( ! $skipcheck ) {
332 + $hasaccess = pmpro_has_membership_access(NULL, NULL, true);
333 + if( is_array( $hasaccess ) ) {
334 + //returned an array to give us the membership level values
335 + $post_membership_levels_ids = $hasaccess[1];
336 + $post_membership_levels_names = $hasaccess[2];
337 + $hasaccess = $hasaccess[0];
338 + }
339 + }
340 +
341 + /**
342 + * Filter to let other plugins change how PMPro filters member content.
343 + * If anything other than false is returned, that value will overwrite
344 + * the $content variable and no further processing is done in this function.
345 + */
346 + $content_filter = apply_filters( 'pmpro_membership_content_filter', false, $content, $hasaccess );
347 + if ( $content_filter !== false ) {
348 + return $content_filter;
349 + }
350 +
351 + if( $hasaccess ) {
352 + //all good, return content
353 + return $content;
354 + } else {
355 + //if show excerpts is set, return just the excerpt
356 + if( get_option( "pmpro_showexcerpts" ) ) {
357 + //show excerpt
358 + global $post;
359 + if( $post->post_excerpt ) {
360 + //defined excerpt
361 + $content = wpautop( $post->post_excerpt );
362 + } elseif(strpos($content, "<span id=\"more-" . $post->ID . "\"></span>") !== false) {
363 + //more tag
364 + $pos = strpos($content, "<span id=\"more-" . $post->ID . "\"></span>");
365 + $content = substr($content, 0, $pos);
366 + } elseif(strpos($content, 'class="more-link">') !== false) {
367 + //more link
368 + $content = preg_replace("/\<a.*class\=\"more\-link\".*\>.*\<\/a\>/", "", $content);
369 + } elseif(strpos($content, "<!-- wp:more -->") !== false) {
370 + //more block
371 + $pos = strpos($content, "<!-- wp:more -->");
372 + $content = substr($content, 0, $pos);
373 + } elseif(strpos($content, "<!--more-->") !== false) {
374 + //more tag
375 + $pos = strpos($content, "<!--more-->");
376 + $content = substr($content, 0, $pos);
377 + } else {
378 + //auto generated excerpt. pulled from wp_trim_excerpt
379 + $content = strip_shortcodes( $content );
380 + $content = str_replace(']]>', ']]&gt;', $content);
381 + $content = wp_strip_all_tags( $content );
382 + $excerpt_length = apply_filters('excerpt_length', 55);
383 + $words = preg_split("/[\n\r\t ]+/", $content, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
384 + if ( count($words) > $excerpt_length ) {
385 + array_pop($words);
386 + $content = implode(' ', $words);
387 + $content = $content . "... ";
388 + } else {
389 + $content = implode(' ', $words) . "... ";
390 + }
391 +
392 + $content = wpautop($content);
393 + }
394 + } else {
395 + //else hide everything
396 + $content = "";
397 + }
398 +
399 + $content = pmpro_get_no_access_message( $content, $post_membership_levels_ids, $post_membership_levels_names );
400 + }
401 +
402 + return $content;
403 + }
404 + add_filter('the_content', 'pmpro_membership_content_filter', 5);
405 + add_filter('the_content_rss', 'pmpro_membership_content_filter', 5);
406 + add_filter('comment_text_rss', 'pmpro_membership_content_filter', 5);
407 +
408 + /*
409 + If the_excerpt is called, we want to disable the_content filters so the PMPro messages aren't added to the content before AND after the excerpt.
410 + */
411 + function pmpro_membership_excerpt_filter($content, $skipcheck = false) {
412 + remove_filter('the_content', 'pmpro_membership_content_filter', 5);
413 + $content = pmpro_membership_content_filter($content, $skipcheck);
414 + add_filter('the_content', 'pmpro_membership_content_filter', 5);
415 +
416 + return $content;
417 + }
418 +
419 + function pmpro_membership_get_excerpt_filter_start($content, $skipcheck = false) {
420 + remove_filter('the_content', 'pmpro_membership_content_filter', 5);
421 + return $content;
422 + }
423 +
424 + function pmpro_membership_get_excerpt_filter_end($content, $skipcheck = false) {
425 + add_filter('the_content', 'pmpro_membership_content_filter', 5);
426 + return $content;
427 + }
428 + add_filter('the_excerpt', 'pmpro_membership_excerpt_filter', 15);
429 + add_filter('get_the_excerpt', 'pmpro_membership_get_excerpt_filter_start', 1);
430 + add_filter('get_the_excerpt', 'pmpro_membership_get_excerpt_filter_end', 100);
431 +
432 + function pmpro_comments_filter($comments, $post_id = NULL) {
433 + global $current_user;
434 +
435 + if(!$comments)
436 + return $comments; //if they are closed anyway, we don't need to check
437 +
438 + $hasaccess = pmpro_has_membership_access(NULL, NULL, true);
439 + if( is_array( $hasaccess ) ) {
440 + //returned an array to give us the membership level values
441 + $post_membership_levels_ids = $hasaccess[1];
442 + $post_membership_levels_names = $hasaccess[2];
443 + $hasaccess = $hasaccess[0];
444 + }
445 +
446 + if($hasaccess)
447 + {
448 + //all good, return content
449 + return $comments;
450 + } else {
451 + if(!$post_membership_levels_ids)
452 + $post_membership_levels_ids = array();
453 +
454 + if(!$post_membership_levels_names)
455 + $post_membership_levels_names = array();
456 +
457 + //get the correct message
458 + if(is_feed())
459 + {
460 + if(is_array($comments))
461 + return array();
462 + else
463 + return false;
464 + }
465 + elseif($current_user->ID)
466 + {
467 + //not a member
468 + if(is_array($comments))
469 + return array();
470 + else
471 + return false;
472 + }
473 + else
474 + {
475 + //not logged in!
476 + if(is_array($comments))
477 + return array();
478 + else
479 + return false;
480 + }
481 + }
482 + return $comments;
483 + }
484 + add_filter("comments_array", "pmpro_comments_filter", 10, 2);
485 + add_filter("comments_open", "pmpro_comments_filter", 10, 2);
486 +
487 + //keep non-members from getting to certain pages (attachments, etc)
488 + function pmpro_hide_pages_redirect() {
489 + global $post;
490 +
491 + if( ! is_admin() && ! empty( $post->ID ) ) {
492 + if( $post->post_type == "attachment" ) {
493 + //check if the user has access to the parent
494 + if( ! pmpro_has_membership_access( $post->ID ) ) {
495 + wp_redirect( pmpro_url( "levels" ) );
496 + exit;
497 + }
498 + }
499 + }
500 + }
501 + add_action( 'wp', 'pmpro_hide_pages_redirect' );
502 +
503 + /**
504 + * Adds custom classes to the array of post classes.
505 + *
506 + * pmpro-level-required = this post requires at least one level
507 + * pmpro-level-1 = this post requires level 1
508 + * pmpro-has-access = this post is usually locked, but the current user has access to this post
509 + *
510 + * @param array $classes Classes for the post element.
511 + * @return array
512 + *
513 + * @since 1.8.5.4
514 + */
515 + function pmpro_post_classes( $classes, $class, $post_id ) {
516 +
517 + $post = get_post($post_id);
518 +
519 + if(empty($post))
520 + return $classes;
521 +
522 + $post_levels = array();
523 + $post_levels = pmpro_has_membership_access( $post->ID, NULL, true );
524 +
525 + if( ! empty( $post_levels ) ) {
526 + if( ! empty( $post_levels[1] ) ) {
527 + $classes[] = 'pmpro-level-required';
528 + foreach( $post_levels[1] as $post_level_id ) {
529 + $classes[] = 'pmpro-level-' . $post_level_id;
530 + }
531 + }
532 + if(!empty($post_levels[0]) && $post_levels[0] == true) {
533 + $classes[] = 'pmpro-has-access';
534 + } else {
535 + $classes[] = 'pmpro-no-access';
536 + }
537 + }
538 + return $classes;
539 + }
540 + add_filter( 'post_class', 'pmpro_post_classes', 10, 3 );
541 +
542 + /**
543 + * Adds custom classes to the array of body classes.
544 + * Same as the above, but acts on the "queried object" instead of the post global.
545 + *
546 + * pmpro-body-level-required = this post requires at least one level
547 + * pmpro-body-level-1 = this post requires level 1
548 + * pmpro-body-has-access = this post is usually locked, but the current user has access to this post
549 + *
550 + * @param array $classes Classes for the body element.
551 + * @return array
552 + *
553 + * @since 1.8.6.1
554 + */
555 + function pmpro_body_classes( $classes ) {
556 +
557 + $post = get_queried_object();
558 +
559 + if(empty($post) || !is_singular())
560 + return $classes;
561 +
562 + $post_levels = array();
563 + $post_levels = pmpro_has_membership_access($post->ID,NULL,true);
564 +
565 + if( ! empty( $post_levels ) ) {
566 + if( ! empty( $post_levels[1] ) ) {
567 + $classes[] = 'pmpro-body-level-required';
568 + foreach( $post_levels[1] as $post_level_id ) {
569 + $classes[] = 'pmpro-body-level-' . $post_level_id;
570 + }
571 + }
572 + if( ! empty( $post_levels[0] ) && $post_levels[0] == true) {
573 + $classes[] = 'pmpro-body-has-access';
574 + }
575 + }
576 + return $classes;
577 + }
578 + add_filter( 'body_class', 'pmpro_body_classes' );
579 +
580 + /**
581 + * Helper function to get the post__not_in array from a WP_Query object ensuring it is an array.
582 + *
583 + * @since 3.5.2
584 + *
585 + * @param WP_Query $query The WP_Query object.
586 + * @return array The post__not_in array.
587 + */
588 + function pmpro_get_post_not_in( $query ) {
589 + if ( ! is_a( $query, 'WP_Query' ) ) {
590 + return array();
591 + }
592 +
593 + $post_not_in = $query->get( 'post__not_in' );
594 + if ( empty( $post_not_in ) || ! is_array( $post_not_in ) ) {
595 + $post_not_in = array();
596 + }
597 +
598 + return $post_not_in;
599 + }
600 +