Widget with random posts from a blog for external sites

How can I create a customizable widget with random posts from my blog that can be published on another site as js, iframe or div.
Is there any WordPress plugin for that?

Related posts

Leave a Reply

2 comments

  1. To create a special output of random posts:

    1. Register an endpoint to the root of your blog. See A (Mostly) Complete Guide to the WordPress Rewrite API for details.
    2. Refresh the permalink settings. I would do this on (de)activation only.
    3. Hook into 'template_redirect' and return your output depending on the details of the requested endpoint. Then exit.

    That’s all.

    Well … some code may help to understand the details. 🙂

    Let’s build a small plugin for HTML and JSON output.

    I have named it T5 Random Posts Endpoint; all code goes into a class with static methods to keep the global namespace clean.

    add_action( 'init', array ( 'T5_Random_Posts_Endpoint', 'init' ) );
    
    /**
     * Build a root endpoint.
     */
    class T5_Random_Posts_Endpoint
    {
        /**
         * Register endpoint and actions.
         *
         * @wp-hook 'init'
         * @return  void
         */
        public static function init()
        {
            add_rewrite_endpoint( 'randomposts', EP_ROOT );
            add_filter( 'request', array ( __CLASS__, 'filter_request' ) );
            add_action( 'template_redirect', array ( __CLASS__, 'render' ) );
        }
    }
    

    As you can see, we call a central init method on 'init' to … initialize our plugin. Creative naming, huh?

    The endpoint is named randomposts and attached to the root. So after activation you can get the out put on example.com/randomposts/ or example.com/randomposts/json/.

    But … if you call the first URL the endpoint works and the request variable randomposts is set – but it is empty. That’s why we hook into 'request' and give the variable a default value we can work with later. Let’s use html as default:

        /**
         * Prepare the endpoint variable so it has always a value.
         *
         * @wp-hook 'request'
         * @param   array $request
         * @return  array
         */
        public static function filter_request( $request )
        {
            if ( isset ( $request['randomposts'] )
                and empty ( $request['randomposts'] )
            )
            {
                $request['randomposts'] = 'html';
            }
    
            return $request;
        }
    

    Now we hook into 'template_redirect' so WordPress will not use the default template index.php but our own output.

        /**
         * Create output.
         *
         * @wp-hook 'template_redirect'
         * @return  void
         */
        public static function render()
        {
            // This is not our endpoint.
            if ( '' === $type = get_query_var( 'randomposts' ) )
            {
                return;
            }
    
            // Someone is poking around.
            // You can extend this and build different output variants.
            if ( ! in_array( $type, array ( 'html', 'json' ) ) )
            {
                status_header( 414 );
                print 'Unsupported Media Type. Use "html" or "json" only.';
                exit;
            }
    
            // Empty blog?
            if ( ! $posts = get_posts( array ( 'numberposts' => 10, 'orderby' => 'rand' ) ) )
            {
                status_header( 404 );
                print 'No posts found.';
                exit;
            }
    
            self::$type( self::prepare_post_data( $posts ) );
            exit;
        }
    

    First we check if we are really on our endpoint by looking into get_query_var( 'randomposts' ). We filled this variable in our request filter, so if it is still empty, we know for sure that is not our business and we return quickly.

    Then we test if the request was for one of our predefined output variants html or json. If someone is calling /randomposts/css or /randomposts/lala we raise a 414 error with a helpful message. And exit.

    Then we get finally our posts with get_posts() and remove all the data we don’t need in a dedicated method named prepare_post_data():

        /**
         * Build a simple array with just titles and permalinks.
         *
         * @wp-hook 'template_redirect'
         * @param   array $posts
         * @return void
         */
        protected static function prepare_post_data( $posts )
        {
            $data = array ();
    
            foreach ( $posts as $post )
            {
                if ( empty ( $post->post_title) )
                {
                    continue;
                }
    
                $data[ $post->ID ] = array (
                    'title' => strip_tags( $post->post_title ),
                    'url'   => get_permalink( $post->ID )
                );
            }
    
            return $data;
        }
    

    We pass this simple array to a method named exactly like our output: html() or json().
    Let’s start with json(); that’s the easy part. See How to encode post content as JSON? for some background.

        /**
         * Render JSON output
         *
         * @wp-hook 'template_redirect'
         * @param  array $data
         * @return void
         */
        protected static function json( array $data )
        {
            header( 'Content-type: application/json' );
            print json_encode( $data );
        }
    

    Easy, isn’t it? The html() is not that much harder, just longer:

            /**
             * Render HTML output
             *
             * @wp-hook 'template_redirect'
             * @param  array $data
             * @return void
             */
            protected static function html( array $data )
            {
                ?>
    <!doctype html>
    <title><?php bloginfo( 'name' ); ?></title>
    <meta name="viewport" content="width=device-width; initial-scale=1.0">
    <?php
    // Just a sample style. Be creative! :)
    ?>
    <style>
    body, body *
    {
        display:         block;
        font:            1em/1.4 Calibri, sans-serif;
        list-style:      none;
        margin:          0;
        padding:         0;
        text-decoration: none;
    }
    a
    {
        background:      #f5f5f5;
        border-bottom:   1px solid #ddd;
        color:           #333;
        padding:         5px 10px;
    }
    a:hover, a:focus
    {
        background:      #333;
        color:           #f5f5f5;
    }
    h1 a
    {
        font-size:      1.2em;
        font-weight:    bold;
    }
    </style>
    <h1><a href="<?php bloginfo( 'url' ); ?>"><?php bloginfo( 'name' ); ?></a></h1>
    <ul>
    <?php
    foreach ( $data as $post )
    {
        print '<li><a href="' . $post['url'] . '">' . $post['title'] . '</a></li>';
    }
    ?>
    </ul>
    <?php
            }
    

    This is how it looks with the theme test data:

    enter image description here

    Now our output is finished – we are still in render() – and we call exit because otherwise WordPress would include the index.php from the active theme.

    Now we need just a method to refresh the permalink settings:

        /**
         * Reset permalinks.
         *
         * @wp-hook 'activate_' . __FILE__
         * @wp-hook 'deactivate_' . __FILE__
         * @return  void
         */
        public static function flush_rewrite_rules()
        {
            remove_action( 'init', array ( __CLASS__, 'init' ) );
            add_action( 'init', 'flush_rewrite_rules', 11 );
        }
    

    We prevent our default init hook here because on activation we are on the plugin list where we don’t need the endpoint, and on deactivation we do not want to re-register the now unused permalink.

    We attach this method to (de)activation with:

    // refresh permalink settings
    register_activation_hook(
        __FILE__ ,
        array ( 'T5_Random_Posts_Endpoint', 'flush_rewrite_rules' )
    );
    register_deactivation_hook(
        __FILE__ ,
        array ( 'T5_Random_Posts_Endpoint', 'flush_rewrite_rules' )
    );
    

    And now we can say: That’s all. Really.

    If you made it this far grab the complete plugin from GitHub.

  2. I think in essence what you’re talking about is a Custom Widget that will parse and display RSS Feed of your Blog. Here, you can build a Custom Widget of your own and hard-code the RSS Feed URL of your Blog in your Widget PHP itself to make sure Widget User doesn’t change the URL; so your widget will show RSS of your Blog only.

    Now, once you finalize to use RSS to fork your Blog, you’ve several options open in front of you. Either you can use WordPress’s own RSS Feed abilities to save you time (but this will impose many limitations) OR write your own RSS Feed maker code as Web Service installed on your Server/Web Hosting that will interact with your Widget. So, make your Widget PHP to send request to your Blog’s RSS Feed Publishing Web Service; then parse the results returned by your Server and display RSS Feed items.

    If you’ve time to invest and serious about this Widget, then better you implement your own Web Service. I don’t think it’ll be too hard for you… just play with WP_Query and return the results in proper RSS Feed XML Format. This way you will also be able to offer Category list in Drop-down to your Widget User to choose from and make your Widget PHP to request RSS of Posts only from selected Category of your Blog. Plus, you’ll have better control over how many Posts to return in RSS Feed requested by your Widget.

    I hope this helps.

    Cheers,

    Ruturaaj.