0

I Need to filter content for posts. If the user is not logged in, then the post content should display "please log in....". If he is logged in, then he can see the post content. I wrote the filter:

add_filter('the_content', 'check_user_logedin',10);

function check_user_logedin($content){
global $post; 
if (  $post->post_type == 'do_pobrania'  && has_term( 'zabezpieczony','rodzaj_plikow'  ) && !is_user_logged_in()  ) {
   return  $content ='My text';
    
}else{
    
    return $content;
}
}

And here comes my problem, because the plugin I use uses get_the_content() and my filter doesn't work on it. It still displays all content for each user. Is it possible to filter content for get_the_content()? Maybe there is another way to solve this issue?

2 Answers 2

1

tl;dr. There's probably a good way for you to do this in the specific case you describe, although WordPress does not allow for good, general filtering of the return value from get_the_content().

You cannot do this directly, but ...

There currently (as of WordPress 5.9.2, checked on 24 March 2022) isn't a convenient, direct and reliable filter hook for filtering the entire output of get_the_content() just as such. the_content() runs its output through a final filter before outputting it, but get_the_content() does not run its output through a final filter before returning it; sorry.

You can review the source code for get_the_content() at the WordPress Code Reference site to confirm; you are looking for instances of the function apply_filters( ... ) which might be applied on the return-value variable $output. In the current version of WordPress, there aren't any, although there are instances of apply_filters( ... ) being used to filter components of the output (for example the "Read More..." link element near the end of the function.

Still, in your specific case, you might be able to highjack the Password-Protected Post functionality to do what you want to do ...

HOWEVER, there is a potential solution for this, if you are willing to potentially interfere with the normal functionality of Password-Protected Posts in your installation of WordPress. (That is, posts where an editor has set a password for readers to access the content of that one particular post. If you're not using this feature and not likely to do so in the future, then this solution may work for you. If you are using that feature, or may do so in the future, the solution you adopt might need to become significantly more complex to avoid unwanted side-effects.

Here's what you need to do:

  1. Set up a filter on the hook post_password_required which will return true if the user is not logged in, and false if the user is logged in. For example, you could put this code in functions.php or another appropriate location:

    add_filter( 'post_password_required', function ( $required, $post ) {
        $required = ( ! is_user_logged_in() );
        return $required;
    }, 2, 10);
    

    For your original example, you need a bit more complex behavior than this -- in particular, you apparently only want this to happen with posts within a hard-coded Custom Post Type and assigned to a particular hard-coded Term. In that case, you can use a more complex boolean expression in the assignment to $required:

    add_filter( 'post_password_required', function ( $required, $post ) {
        $required = ( $post->post_type == 'do_pobrania' && has_term( 'zabezpieczony','rodzaj_plikow', $post ) && ! is_user_logged_in() );
        return $required;
    }, 2, 10);
    
  2. Set up a hook on the filter the_password_form which returns the HTML that you want to display when the user is excluded from seeing the content. For example, here's how to display a paragraph including a link to log in to WordPress, and then redirect back to the page you were viewing before:

    add_filter( 'the_password_form', function ( $output, $post ) {
        $login_url = wp_login_url( home_url( $_SERVER['REQUEST_URI'] ) );
        $output = sprintf('<p>Please <a href="%s">log in</a> ...</p>', esc_url( $login_url ) );
        return $output;
     }, 2, 10);
    

    This procedure removes the input form that is normally used to collect the post password for password-protected posts; so, again, if you use that functionality, this solution will break it unless you do something significantly more complicated here.

Once these two filters are added, any template or function that uses get_the_content() to retrieve post content will be blocked when users aren't logged in (or whenever the conditions you set in the first filter function, whatever those may be, are met). Note that this solution will, in general, cause login-gated posts to be treated the way that password-protected posts are treated -- for example, they will not have excerpts displayed, their content will not appear in RSS/Atom feeds, etc. etc. Given what you are trying to do here, it seems likely that these side-effects may be acceptable; but if not, then be careful.

Some Technical Notes on Why This Works

The relevant part of get_the_content() is on lines 313-316 of wp-includes/post-template.php:

function get_the_content( $more_link_text = null, $strip_teaser = false, $post = null ) {

/* [...] */

    // If post password required and it doesn't match the cookie.
    if ( post_password_required( $_post ) ) {
        return get_the_password_form( $_post );
    }
 
/* [...] */

}

So IF post_password_required() returns true, THEN get_the_content() will just return the value returned by get_the_password_form() in place of the post content. These functions can both be filtered using simple filter hooks:

function post_password_required( $post = null ) {
 
    /**
     * Filters whether a post requires the user to supply a password.
     *
     * @since 4.7.0
     *
     * @param bool    $required Whether the user needs to supply a password. True if password has not been
     *                          provided or is incorrect, false if password has been supplied or is not required.
     * @param WP_Post $post     Post object.
     */
    return apply_filters( 'post_password_required', $required, $post );
}
function get_the_password_form( $post = 0 ) {
    $post   = get_post( $post );
    $label  = 'pwbox-' . ( empty( $post->ID ) ? rand() : $post->ID );
    $output = '<form action="' . esc_url( site_url( 'wp-login.php?action=postpass', 'login_post' ) ) . '" class="post-password-form" method="post">
    <p>' . __( 'This content is password protected. To view it please enter your password below:' ) . '</p>
    <p><label for="' . $label . '">' . __( 'Password:' ) . ' <input name="post_password" id="' . $label . '" type="password" size="20" /></label> <input type="submit" name="Submit" value="' . esc_attr_x( 'Enter', 'post password form' ) . '" /></p></form>
    ';
 
    /**
     * Filters the HTML output for the protected post password form.
     *
     * If modifying the password field, please note that the core database schema
     * limits the password field to 20 characters regardless of the value of the
     * size attribute in the form input.
     *
     * @since 2.7.0
     * @since 5.8.0 Added the `$post` parameter.
     *
     * @param string  $output The password form HTML output.
     * @param WP_Post $post   Post object.
     */
    return apply_filters( 'the_password_form', $output, $post );
}

You can take advantage of these filter hooks (1) to require WordPress to block the post content in any context that respects Password-Protected Post security; and (2) to deliver arbitrary HTML (in this case a simple login link) in place of the post content in any context that displays an input field to get the post password. Hope this helps!

1
  • In my case, this solution works very well. Thank you very much for your help!!!!
    – Czechu92
    Commented Mar 25, 2022 at 6:29
0

Per the user-contributed comment by Hay on the get_the_content() docs page:

Note that get_the_content doesn’t return the same thing as what the_content displays. For that you need to do this:

$content = apply_filters( 'the_content', get_the_content() );
echo $content;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.