Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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".

Thanks

share|improve this question
add comment

3 Answers

up vote 4 down vote accepted
+100

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

share|improve this answer
    
The small source (and elegant) works out of the box, I just miss the Unstick function, but then: it was not asked for! –  brasofilo Jul 29 '12 at 23:21
    
Yes, I think also; but was not on the question. It is also possible via url param and the function unstick( $post_id ). Also I miss an visible feedback for change the sticky status. –  bueltge Jul 30 '12 at 6:47
    
Thanks! The plugin works perfectly. –  Travis Pflanz Jul 30 '12 at 22:13
    
Welcome! Now also a plugin for download on a Gist 3214922 –  bueltge Jul 31 '12 at 8:27
add comment

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;
}
share|improve this answer
    
I am getting this error Parse error: syntax error, unexpected T_RETURN in /home1/travisp2/public_html/crowncrazed/wp-content/themes/qawker/functions.php on line 7 which is return $content; –  Travis Pflanz Jul 30 '12 at 20:59
    
Sorry, typo it fixed –  Bainternet Jul 30 '12 at 22:14
add comment

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.

share|improve this answer
    
+1 for the working plugin, does exactly what asked in question. –  amit Jul 29 '12 at 21:11
    
Getting this error when uploading the .php plugin file via WordPress. The package could not be installed. PCLZIP_ERR_BAD_FORMAT (-10) : Unable to find End of Central Dir Record signature –  Travis Pflanz Jul 29 '12 at 21:45
    
So upload via FTP and report back? It's likely because the plugin is not in its own folder or something. –  chrisguitarguy Jul 29 '12 at 21:50
    
I added the .php file to a folder, then the folder to a .zip. Uploaded the plugin via WordpPress. Everything uploaded and installed. The "Stick" button is present on the admin bar, but when clicked, an error displays that simply says - "An error occurred". I am using Google Chrome, if that makes a difference. –  Travis Pflanz Jul 29 '12 at 22:03
1  
That means something when wrong in the ajax call. Either a faulty nonce, post id or permissions. Short of me going into your site to fix it (which I'm not going to do), I can't help you -- works fine on my local machine. Step 1: does it work with the default theme? Are other plugins causing problems? –  chrisguitarguy Jul 29 '12 at 22:13
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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