How to add “Stick this post to the front page” to front end?

I have a baseball related website with multiple authors. I use the “Stick this post to the front page” to denote an “Editor’s Pick” on an article. I would like to add a link/button to allow editor to do this from the front end. The method can either be in the article itself or in the Admin Bar. I do not really have a preference.

I have looked through many, many different “Admin Bar” plugins, but haven’t been to find anything relating to “Stick this post to the front page”.

Read More

Thanks

Related posts

Leave a Reply

3 comments

  1. I think this small source code is your solution. It currently doesn’t have frontend feedback for the Sticky Post change, but you can enhance this string, class or whatever you want in the function fb_stick_post.

    The first function adds the item in the Admin Bar and creates a new Url with a param value. Also, on click calls a function to read the Url param and, if it’s true, then do the change to the sticky status of this post id.

    add_action( 'admin_bar_menu', 'fb_add_admin_bar_sticky', 35 );
    function fb_add_admin_bar_sticky() {
        global $wp_admin_bar;
    
        if ( ! is_super_admin() || ! is_admin_bar_showing() )
            return;
    
        $current_object = get_queried_object();
        if ( empty($current_object) )
            return;
    
        if ( ! empty( $current_object->post_type ) && 
            ( $post_type_object = get_post_type_object( $current_object->post_type ) ) && 
            current_user_can( $post_type_object->cap->edit_post, $current_object->ID ) 
        ) {
            $wp_admin_bar->add_menu( 
                array(
                    'id' => 'sticky_post', 
                    'title' => __('Sticky'), 
                    'href' => get_permalink() . '?stick_post=true', 
                    'meta' => array(
                        'title' => __( 'Click me' ),
                        'onclick' => fb_stick_post( get_the_ID() )
                    )
                )
            );
        }
    }
    
    function fb_stick_post( $post_id ) {
    
        if ( isset($_GET['stick_post']) && 'true' == htmlspecialchars( $_GET['stick_post'] ) )
            stick_post( $post_id );
    }
    

    Update 07/30/2012

    Now an small plugin with easy solution. The plugin adds an item inside the Admin Bar. The string of the button check for is sticky and give the possibility to stick or unstick the current post.

    Example in Twenty Eleven Theme for an post, there was with an sticky flag

    I change the hook for add the admin bar item to ´template_redirect` for use an redirect after update the stick flag on post.

    <?php
    /**
     * Plugin Name: Stick/Unstick post via Admin bar
     * 
     */
    
    if ( ! function_exists( 'fb_add_admin_bar_sticky' ) ) {
    
        add_action( 'template_redirect', 'fb_add_admin_bar_sticky' );
        function fb_add_admin_bar_sticky() {
            global $wp_admin_bar;
    
            if ( ! is_super_admin() || ! is_admin_bar_showing() )
                return;
    
            $current_object = get_queried_object();
            if ( empty($current_object) )
                return;
    
            if ( ! empty( $current_object->post_type ) && 
                ( $post_type_object = get_post_type_object( $current_object->post_type ) ) && 
                current_user_can( $post_type_object->cap->edit_post, $current_object->ID ) 
            ) {
    
                // check, if an sticky post
                if ( is_sticky( get_the_ID() ) ) {
                    $title = __('Unsticky');
                    $link = '?unstick_post=true';
                    $attr_title = __( 'Make this post unsticky' );
                } else {
                    $title = __('Sticky');
                    $link = '?stick_post=true';
                    $attr_title = __( 'Make this post sticky' );
                }
    
                $wp_admin_bar->add_menu(
                    array(
                        'id' => 'sticky_post', 
                        'title' => $title, 
                        'href' => get_permalink() . $link, 
                        'meta' => array(
                            'title' => $attr_title,
                            'onclick' => fb_stick_post( get_the_ID() )
                        )
                    )
                );
            }
        }
    
        function fb_stick_post( $post_id ) {
    
            if ( isset($_GET['stick_post']) && 'true' == htmlspecialchars( $_GET['stick_post'] ) ) {
                stick_post( $post_id );
                wp_redirect( get_permalink( $post_id ) );
                exit();
            }
    
            if ( isset($_GET['unstick_post']) && 'true' == htmlspecialchars( $_GET['unstick_post'] ) ) {
                unstick_post( $post_id );
                wp_redirect( get_permalink( $post_id ) );
                exit();
            }
        }
    
    }
    

    or download this plugin Gist 3214922

  2. There are a few functions that come in handy here:

    With those three in mind, all we need to do is stick them together with some admin menu bar glue.

    First off, let’s wrap everything in a class for fun and profit. This class will have some constants that we’ll use later: a nonce, an action for unsticking the post and an action for sticking the post.

    class WPSE_58818_Stick_Post
    {
        /**
         * Ajax nonce.
         *
         * @since   1.0
         */
        const NONCE = 'wpse58818_nonce_';
    
        /**
         * Unstick ajax action
         *
         * @since   1.0
         */
        const UNSTICK = 'wpse58818_unstick';
    
        /**
         * Stick Ajax action
         *
         * @since   1.0
         */
        const STICK = 'wpse58818_stick';
    } // end class
    

    Then let’s add an init function to add our actions. The first action being that we hook into template_redirect.

    <?php
    class WPSE_58818_Stick_Post
    {
        // snip snip
    
        /**
         * Adds actions and such.
         *
         * @since   1.0
         * @access  public
         * @uses    add_action
         */
        public static function init()
        {
            add_action(
                'template_redirect',
                array(__CLASS__, 'template_r')
            );
        }
    }
    

    NOTE: from here on out I’ll be omitting the class bit. You can view the entire thing here.

    In the function hooked into template_redirect, we’ll check to see if we’re on a single post page and whether or not the user can edit it. If they can, we’ll hook into admin_bar_menu and wp_footer.

    /**
     * Hooked into `template_redirect`.  Adds the admin bar stick/unstick
     * button if we're on a single post page and the current user can edit
     * the post
     * 
     * @since   1.0
     * @access  public
     * @uses    add_action
     */
    public static function template_r()
    {
        if(
            !is_single() ||
            !current_user_can('edit_post', get_queried_object_id())
        ) return; // not a single post or the user can't edit it
    
        // Hook into admin_bar_menu to add stuff
        add_action(
            'admin_bar_menu',
            array(__CLASS__, 'menu'),
            100
        );
    
        // Hook into the footer and spit out some JavaScript
        add_action(
            'wp_footer',
            array(__CLASS__, 'footer')
        );
    }
    

    In the menu function, hooked into admin_bar_menu, we can add our new item:

    /**
     * Hooked into `admin_bar_menu`.  Adds our stick/unstick node.
     *
     * @since   1.0
     * @access  public
     */
    public static function menu($mb)
    {
        // get the current post ID
        $post_id = get_queried_object_id();
    
        $mb->add_node(array(
            'id'    => 'wpse58818-sticker',
            'meta'  => array(
                'class' => 'wpse58818-sticker',
                'title' => is_sticky($post_id) ? 'unstick' : 'stick'
            ),
            'title' => is_sticky($post_id) ? __('Unstick') : __('Stick'),
            'href'  => self::get_url($post_id)
        ));
    }
    

    Here we get our first “utility function” that builds a URL for the admin menu bar node. It’s just a wrapper around add_query_arg to nonce, and build a url that we’ll use with AJAX later on:

    /**
     * Get an Ajax URL to use for a given post
     *
     * @since   1.0
     * @access  protected
     */
    protected static function get_url($post_id)
    {
        return add_query_arg(array(
            'post_id' => absint($post_id),
            'action'  => is_sticky($post_id) ? self::UNSTICK : self::STICK,
            'nonce'   => wp_create_nonce(self::NONCE . $post_id)
        ), admin_url('admin-ajax.php'));
    }
    

    The footer function just spits out some JavaScript to make the AJAX calls. Basic overview: when someone clicks on our new link, make a GET request to the given URL. If it’s successful, change the (un)stick link’s href, text, and title.

    /**
     * Hooked into `wp_footer`.  Spits out a bit of JS to stick/unstick a post
     *
     * @since   1.0
     * @access  public
     */
    public static function footer()
    {
        ?>
        <script type="text/javascript">
        jQuery(document).ready(function($) {
            $('.wpse58818-sticker a').on('click', function(e) {
                e.preventDefault();
                var action = $(this).attr('title');
                var that = this;
                $.get(
                    $(this).attr('href'),
                    {},
                    function(data) {
                        if('0' == data)
                        {
                            console.log(data);
                            alert('<?php echo esc_js(__('An error occurred')); ?>');
                            return;
                        }
    
                        $(that).attr('href', data);
                        if('stick' == action) {
                            $(that).html('<?php echo esc_js(__('Unstick')); ?>');
                            $(that).attr('title', 'unstick');
                        } else {
                            $(that).html('<?php echo esc_js(__('Stick')); ?>');
                            $(that).attr('title', 'stick');
                        }
                    }
                );
            });
        });
        </script>
        <?php
    }
    

    And now we come to the AJAX callbacks. Ajax in plugins/themes is worth reading up on.

    We’ll modify our init function a bit to add two more actions:

    /**
     * Adds actions and such.
     *
     * @since   1.0
     * @access  public
     * @uses    add_action
     */
    public static function init()
    {
        add_action(
            'template_redirect',
            array(__CLASS__, 'template_r')
        );
    
        // Ajax actions
        add_action(
            'wp_ajax_' . self::STICK,
            array(__CLASS__, 'stick')
        );
    
        add_action(
            'wp_ajax_' . self::UNSTICK,
            array(__CLASS__, 'unstick')
        );
    }
    

    And our AJAX callbacks. These could very easily be the same function. I split them up here because it seemed easier to extend/change in the future. Both of these check to see if the AJAX request is valid, (un)stick the post accordingly, and echo out the new URL for future (un)sticking.

    /**
     * Ajax callback for the stick function
     *
     * @since   1.0
     * @access  public
     */
    public static function stick()
    {
        $post_id = self::can_ajax();
    
        stick_post($post_id);
    
        echo self::get_url($post_id);
        die();
    }
    
    /**
     * Ajax callback for the unstick function
     *
     * @since   1.0
     * @access  public
     * @uses    unstick_post
     */
    public static function unstick()
    {
        $post_id = self::can_ajax();
    
        // nonces checked, everything is good to go. Unstick!
        unstick_post($post_id);
    
        echo self::get_url($post_id);
        die();
    }
    

    Our second “utility function” makes an appearance here. can_ajax verifies our nonces and user permissions and returns post ID to (un)stick. If any checks fail, it exits (via die('1')).

    /**
     * Check to see if the current user can ajax.  Returns the post ID to 
     * stick/unstick if successful. Kills the program otherwise
     *
     * @since   1.0
     * @access  protected
     */
    protected static function can_ajax()
    {
        $post_id = isset($_REQUEST['post_id']) ? $_REQUEST['post_id'] : '';
    
        if(
            !$post_id ||
            !check_ajax_referer(self::NONCE . $post_id, 'nonce', false)
        ) die('0');
    
        if(!current_user_can('edit_post', $post_id))
            die('0');
    
        return $post_id;
    }
    

    Here is that whole mess as a plugin.

  3. Here is a much simpler solution that will get the job done using the_content filter hook

    add_filter('the_content','simplest_sticky_solution');
    function simplest_sticky_solution($content){
        global $post;
        //early exit if not needed
        if (!is_single() || !current_user_can('edit_post',$post->ID)) 
            return $content;
    
        //check if form is submitted and act as needed
        if (isset($_POST['sticky_action']) && isset($_POST['sticky_id']) && isset($_POST['sticky_nonce']) && wp_verify_nonce($_POST['sticky_nonce'], 'StickIt')){
            if (is_sticky($post->ID)){
                stick_post($post->ID);
            }else{
                unstick_post($post->ID);
            }
        }
    
        //create the form
        $label = (is_sticky())? "Unstick": "Stick";
        $form = '
        <form action="" method="POST">
            <input type="hidden" name="sticky_id" value="'.$post->id.'">
            <input type="hidden" name="sticky_action" value="stickit">
            <input type="hidden" name="sticky_nonce" value="'.wp_create_nonce('StickIt').'">
            <input type="button" name="submit" value="'.$label.'">
        </form>';
        return $form.'<br/>'.$content;
    }