Skip to content

Instantly share code, notes, and snippets.

@bamadesigner
Last active April 22, 2020 16:04
Show Gist options
  • Save bamadesigner/2147ac63258b137c6613 to your computer and use it in GitHub Desktop.
Save bamadesigner/2147ac63258b137c6613 to your computer and use it in GitHub Desktop.
Get Your Pocket Items (And Filter By Tag) to List On Your Website
<?php
HAS BEEN MOVED TO https://github.com/bamadesigner/pocket-to-wordpress.
/**
* This adventure into the Pocket API was inspired
* because I wanted to get all of my Pocket items
* that were tagged "reading" and display them as
* a reading list on my website.
*
* This was written for a WordPress site but only a
* few parts would need to be tweaked/removed and
* you could use it on any site.
*
* This code will cache the item data in a transient
* at a default time of 2 hours. You can tweak
* this time with the 'store_items' argument.
*
* You'll need a Pocket consumer key and access token
* in order to use their API. Visit https://getpocket.com/developer/
* to register an app and get a key.
*
* You can then use https://github.com/jshawl/pocket-oauth-php
* to get your access token.
*
* If you don't mind trusting some random site, you can use
* http://reader.fxneumann.de/plugins/oneclickpocket/auth.php
* to get your access token a lot quicker.
*
* Then use the shortcode [pocket_items] or the function
* get_pocket_items_html() to display your pocket items.
*
* Or you can use get_pocket_items() to retrieve the item
* data and display as you like.
*/
add_shortcode( 'pocket_items', 'get_pocket_items_html' );
/**
* Shortcode and function to print your Pocket items.
*
* Pass a 'tag' to get category-specific Pocket items.
* It seems they only allow one tag at a time.
*
* @TODO: Get your Pocket authentication info.
*
* You'll need a Pocket consumer key and access token
* in order to use their API. Visit https://getpocket.com/developer/
* to register an app and get a key.
*
* You can then use https://github.com/jshawl/pocket-oauth-php
* to get your access token.
*
* You can get more info in their docs: https://getpocket.com/developer/docs/authentication
*/
/**
* Returns markup for all pocket items.
*
* @access public
* @param array - $args - the arguments to create/format the list
* @return string - $pocket_html - the items markup
*/
function get_pocket_items_html( $args = array() ) {
// Handle the arguments
$defaults = array(
'key' => null,
'token' => null,
'tag' => NULL,
'store_items' => '7200' // Will cache the item for 2 hours by default. Set to false for no cache.
);
extract( wp_parse_args( $args, $defaults ), EXTR_OVERWRITE );
// Build html
$pocket_html = NULL;
// Get the items
$pocket_items = get_pocket_items( shortcode_atts( $defaults, $args ) );
// If we have no items
if ( ! ( isset( $pocket_items ) && is_array( $pocket_items ) ) )
return NULL;
// Start building the HTML
$pocket_html .= '<div class="pocket-items">';
// Loop through each item
foreach( $pocket_items as $item ) {
$pocket_html .= get_pocket_item_html( $item );
}
$pocket_html .= '</div>';
return $pocket_html;
}
/**
* Returns markup for individual pocket items.
*
* @access public
* @param array - $item - the data for the item to be displayed
* @return string - $pocket_html - the item's markup
*/
function get_pocket_item_html( $item ) {
// Convert to object
$item = (object) $item;
// Set the item ID
$item_id = isset( $item->item_id ) && ! empty( $item->item_id ) ? $item->item_id : ( isset( $item->resolved_id ) && ! empty( $item->resolved_id ) ? $item->resolved_id : NULL );
// Set the URL
$item_url = isset( $item->given_url ) && ! empty( $item->given_url ) ? $item->given_url : ( isset( $item->resolved_url ) && ! empty( $item->resolved_url ) ? $item->resolved_url : NULL );
// Set the title
$item_title = isset( $item->given_title ) && ! empty( $item->given_title ) ? $item->given_title : ( isset( $item->resolved_title ) && ! empty( $item->resolved_title ) ? $item->resolved_title : $item_url );
// Set the time added
$item_time_added = isset( $item->time_added ) ? $item->time_added : false;
// Set the time updated
//$item_time_updated = isset( $item->time_updated ) ? $item->time_updated : false;
// Do we have authors?
$item_authors = isset( $item->authors ) ? $item->authors : false;
// Do we have an image?
$item_has_image = isset( $item->has_image ) ? $item->has_image : false;
$item_image_src = $item_has_image && isset( $item->image ) && isset( $item->image[ 'src'] ) ? $item->image[ 'src' ] : false;
// What's the word count?
$item_word_count = isset( $item->word_count ) ? $item->word_count : false;
// Start the item
$pocket_html = '<div id="pocket-' . $item_id . '" class="pocket-item' . ( $item_has_image && $item_image_src ? ' has-image' : NULL ) . '">';
// Add image
$pocket_html .= $item_has_image && $item_image_src ? '<div class="pocket-image" style="background-image: url(' . $item_image_src . ');"></div>' : NULL;
// Add the main stuff
$pocket_html .= '<div class="pocket-main">';
// Add the title
$pocket_html .= '<h3 class="pocket-title">';
// Add the URL
if ( $item_url ) {
$pocket_html .= '<a href="' . $item_url . '" target="_blank">' . $item_title . '</a>';
} else {
$pocket_html .= $item_title;
}
// Close the title
$pocket_html .= '</h3>';
// Add meta data
$pocket_html .= '<div class="pocket-meta">';
// Show when it was added
$pocket_html .= ! empty( $item_time_added ) ? '<span class="date-added meta-section">' . date( 'M\. j, Y', $item_time_added ) . '</span>' : NULL;
// Only add the first author
if ( $item_authors ) {
foreach( $item_authors as $author ) {
if ( isset( $author[ 'name' ] ) ) {
$pocket_html .= '<span class="author meta-section">';
// If we have a URL
if ( isset( $author[ 'url' ] ) ) {
$pocket_html .= '<a href="' . $author[ 'url' ] . '">' . $author[ 'name' ] . '</a>';
} else {
$pocket_html .= $author[ 'name' ];
}
$pocket_html .= '</span>';
break;
}
}
}
// Show the word count
$pocket_html .= $item_word_count > 0 ? '<span class="word-count meta-section">' . $item_word_count . ' words</span>' : NULL;
$pocket_html .= '</div>';
$pocket_html .= '<div class="pocket-excerpt">';
// Add excerpt
if ( isset( $item->excerpt ) && ! empty( $item->excerpt ) )
$pocket_html .= "<p>{$item->excerpt}</p>";
$pocket_html .= '</div>';
// Add tag list
if ( isset( $item->tags ) && ! empty( $item->tags ) ) {
// Start the list
$pocket_html .= '<ul class="pocket-item-tags">';
foreach( $item->tags as $tag => $tag_info ) {
$pocket_html .= '<li>' . $tag . '</li>';
}
// End the list
$pocket_html .= '</ul>';
}
$pocket_html .= '</div>';
$pocket_html .= '</div>';
return $pocket_html;
}
/**
* Get Pocket items using Pocket's API.
*
* @TODO: Get your Pocket authentication info.
*
* You'll need a Pocket consumer key and access token
* in order to use their API. Visit https://getpocket.com/developer/
* to register an app and get a key.
*
* You can then use https://github.com/jshawl/pocket-oauth-php
* to get your access token.
*
* You can get more info in their docs: https://getpocket.com/developer/docs/authentication
*
* @access public
* @param $args array arguments to be passed to the API
* @return array
*/
function get_pocket_items( $args = array() ) {
// Handle the arguments
$defaults = array(
'key' => null,
'token' => null,
'tag' => NULL, // Pass a tag to get category-specific Pocket items. It seems they only allow one tag at a time.
'count' => 10,
'store_items' => '7200' // Will cache the item for 2 hours by default. Set to false for no cache.
);
extract( wp_parse_args( $args, $defaults ), EXTR_OVERWRITE );
// Build request args
$pocket_request_args = array(
'consumer_key' => $key,
'access_token' => $token,
'tag' => $tag,
'detailType' => 'complete',
'state' => 'all',
'count' => $count,
);
// If we're set to store the items...
if ( $store_items !== false && $store_items > 0 ) {
// See if we have data in our transient data and that it matches our args
$pocket_transient_name = 'my_pocket_reading_list';
$pocket_transient_args_name = 'my_pocket_reading_list_args';
// If we have cached Pocket items...
if ( ( $transient_pocket_items = get_transient( $pocket_transient_name ) )
&& $transient_pocket_items !== false ) {
// Check the args to see if they match...
if ( ( $transient_pocket_item_args = get_transient( $pocket_transient_args_name ) )
&& $transient_pocket_item_args !== false && $transient_pocket_item_args == $pocket_request_args ) {
// Return the cached Pocket items
return $transient_pocket_items;
}
}
}
// Make our Pocket request
$pocket_request = get_pocket_response( 'https://getpocket.com/v3/get', $pocket_request_args );
// If we have results...
if ( isset( $pocket_request ) && is_array( $pocket_request ) && isset( $pocket_request[ 'list' ] ) && $pocket_request[ 'list' ] ) {
// If we're set to store items, store the data and args for the set transient time
if ( $store_items !== false && $store_items > 0 ) {
set_transient( $pocket_transient_name, $pocket_request[ 'list' ], $store_items );
set_transient( $pocket_transient_args_name, $pocket_request_args, $store_items );
}
// Return the items
return $pocket_request[ 'list' ];
}
return false;
}
/**
* Get a response from the Pocket API.
*
* @access public
* @param $url the API endpoint URL
* @param $post array data to be passed to the API
* @return mixed false if there's an error, otherwise an array of API data
*/
function get_pocket_response( $url, $post ) {
// Get the response
$response = wp_safe_remote_post( $url, array( 'body' => $post ) );
// Check for an error
if ( is_wp_error( $response ) ) {
return false;
}
// Return the response
return json_decode( wp_remote_retrieve_body( $response ), true );
}
@robneu
Copy link

robneu commented Jun 8, 2015

This is really cool! I have no idea why, but I saw you talking about this earlier and I needed something to take my mind off some other code I was working on, so I refactored this a bit. This is totally untested and I'm not 100% sure if the cURL replacement will work as expected, but I figured I'd share it anyway

<?php
/**
 * This adventure into the Pocket API was inspired because I wanted to get all
 * of my Pocket items that were tagged "reading" and display them as a reading
 * list on my website.
 *
 * This was written for a WordPress site but only a few parts would need to be
 * tweaked/removed and you could use it on any site.
 *
 * This code will cache the item data in a transient at a default time of 2
 * hours. You can tweak this time with the 'store_items' argument.
 *
 * You'll need a Pocket consumer key and access token in order to use their API.
 * Visit https://getpocket.com/developer/ to register an app and get a key.
 *
 * You can then use https://github.com/jshawl/pocket-oauth-php to get your
 * access token.
 *
 * If you don't mind trusting some random site, you can use
 * http://reader.fxneumann.de/plugins/oneclickpocket/auth.php
 * to get your access token a lot quicker.
 *
 * Then use the shortcode [pocket_items] or the function get_pocket_items_html()
 * to display your pocket items.
 *
 * Or you can use get_pocket_items() to retrieve the item data and display as
 * you like.
 */

add_shortcode( 'pocket_items', 'pocket_items_shortcode' );
/**
 * Shortcode and function to print your Pocket items.
 *
 * Pass a 'tag' to get category-specific Pocket items. It seems they only allow
 * one tag at a time.
 *
 * @TODO: Get your Pocket authentication info.
 *
 * You'll need a Pocket consumer key and access token
 * in order to use their API. Visit https://getpocket.com/developer/
 * to register an app and get a key.
 *
 * You can then use https://github.com/jshawl/pocket-oauth-php
 * to get your access token.
 *
 * You can get more info in their docs:
 * https://getpocket.com/developer/docs/authentication
 */
function pocket_items_shortcode( $atts = array() ) {

    // Handle the arguments
    $defaults = array(
        'key'         => 'XXXXXXXXXX',
        'token'       => 'XXXXXXXXXX',
        'tag'         => null,
        'store_items' => '7200',
    );

    // Get the items
    $pocket_items = get_pocket_items( shortcode_atts( $defaults, $atts ) );

    // If we have no items
    if ( empty( $pocket_items ) ) {
        return null;
    }

    $output = '<div class="pocket-items">';

    // Loop through each item
    foreach ( $pocket_items as $item ) {
        $output .= get_pocket_item_html( get_pocket_item_data( $item ) );
    }

    $output .= '</div><!-- .pocket-items -->';

    return $output;
}

/**
 * Returns a formatted array of data about a given Pocket item.
 *
 * @access public
 * @param  $item array the item which holds the data we need to format
 * @return $data array the item's data attributes
 */
function get_pocket_item_data( $item ) {
    $item = (object) $item;

    $data = array(
        'id'         => ! empty( $item->resolved_id )    ? $item->resolved_id:    null,
        'url'        => ! empty( $item->resolved_url )   ? $item->resolved_url:   null,
        'title'      => ! empty( $item->resolved_title ) ? $item->resolved_title: null,
        'time_added' => ! empty( $item->time_added )     ? $item->time_added:     false,
        'authors'    => ! empty( $item->authors )        ? $item->authors:        false,
        'word_count' => ! empty( $item->word_count )     ? $item->word_count:     false,
        'has_image'  => ! empty( $item->has_image )      ? $item->has_image:      false,
        'excerpt'    => ! empty( $item->excerpt )        ? $item->excerpt:        false,
        'tags'       => ! empty( $item->tags )           ? $item->tags:           false,
        'image_src'  => false,
    );

    if ( ! empty( $item->item_id ) ) {
        $data['id'] = $item->item_id;
    }

    if ( ! empty( $item->given_url ) ) {
        $data['url'] = $item->given_url;
    }

    if ( ! empty( $item->given_title ) ) {
        $data['title'] = $item->given_title;
    }

    if ( empty( $data['title'] ) ) {
        $data['title'] = $data['url'];
    }

    if ( ! empty( $item->image['src'] ) ) {
        $data['image_src'] = $item->image['src'];
    }

    return $data;
}

/**
 * Returns markup for individual pocket items.
 *
 * @access public
 * @param  $data array the data for the item to be displayed
 * @return $output string the item's markup
 */
function get_pocket_item_html( $data ) {
    $img_src = $data['image_src'] ? $data['image_src'] : false;
    $class   = 'pocket-item';
    $title   = $data['title'];

    if ( $img_src ) {
        $class .= ' has-image';
    }

    if ( $url = $data['url'] ) {
        $title = '<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $title ) . '</a>';
    }

    // Here we go! Start building the output...
    $output = '<div id="pocket-' . absint( $data['id'] ) . '" class="' . $class . '">';

    if ( $img_src ) {
        $output .= '<div class="pocket-image" style="background-image: url(' . esc_url( $img_src ) . ');"></div>';
    }

    $output .= '<div class="pocket-main">';

    $output .= '<h3 class="pocket-title">' . $title . '</h3>';

    $output .= '<div class="pocket-meta">';

    if ( $time = $data['time_added'] ) {
        $output .= '<span class="date-added meta-section">';
        $output .= date( 'M\. j, Y', esc_attr( $time ) );
        $output .= '</span>';
    }

    if ( $authors = $data['authors'] ) {
        foreach ( (array) $authors as $author ) {
            if ( isset( $author['name'] ) ) {

                $name = $author['name'];
                if ( isset( $author['url'] ) ) {
                    $name = '<a href="' . esc_url( $author['url'] ) . '">' . esc_html( $name ) . '</a>';
                }

                $output .= '<span class="author meta-section">' . $name . '</span>';

                break;
            }
        }
    }

    if ( $word_count = $data['word_count'] ) {
        $output .= '<span class="word-count meta-section">';
        $output .= absint( $word_count ) . ' words';
        $output .= '</span>';
    }

    $output .= '</div><!-- .pocket-meta -->';

    if ( $excerpt = $data['excerpt'] ) {
        $output .= '<div class="pocket-excerpt">';
        $output .= wpautop( $excerpt, false );
        $output .= '</div><!-- .pocket-excerpt -->';
    }

    if ( $tags = $data['tags'] ) {
        $output .= '<ul class="pocket-item-tags">';
        foreach ( $tags as $tag => $tag_info ) {
            $output .= '<li>' . esc_html( $tag ) . '</li>';
        }
        $output .= '</ul>';
    }

    $output .= '</div><!-- .pocket-main -->';

    $output .= '</div><!-- #pocket-' . absint( $data['id'] ) . ' -->';

    return $output;
}

/**
 * Get Pocket items using Pocket's API.
 *
 * @access public
 * @param  $args array arguments to be passed to the API
 * @return array
 */
function get_pocket_items( $args = array() ) {
    $defaults = array(
        'key'         => null,
        'token'       => null,
        'tag'         => null,
        'count'       => 10,
        'store_items' => '7200',
    );

    $args = wp_parse_args( $args, $defaults );

    // Bail if we don't have the required access token and consumer key data.
    if ( ! isset( $args['key'], $args['token'] ) ) {
        return false;
    }

    // Build the request we'll be sending to Pocket.
    $request_args = array(
        'consumer_key' => $args['key'],
        'access_token' => $args['token'],
        'tag'          => $args['tag'],
        'detailType'   => 'complete',
        'state'        => 'all',
        'count'        => $args['count'],
    );

    $cache_tag      = 'my_pocket_reading_list';
    $cache_args_tag = 'my_pocket_reading_list_args';

    if ( ! empty( $args['store_items'] ) ) {
        $cache      = get_transient( $cache_tag );
        $cache_args = get_transient( $cache_args_tag );

        // Return cache if we have cached data that matches our request args.
        if ( ! empty( $cache ) && $cache_args === $request_args ) {
            return $cache;
        }
    }

    $request = get_pocket_response( 'https://getpocket.com/v3/get', $request_args );

    // Bail if something went wrong with the request.
    if ( ! $request || empty( $request['list'] ) ) {
        return false;
    }

    // If we're using cache, store the data and args and set the cache length.
    if ( ! empty( $args['store_items'] ) ) {
        set_transient( $cache_tag, $request['list'], $args['store_items'] );
        set_transient( $cache_args_tag, $request_args, $args['store_items'] );
    }

    return $request['list'];
}

/**
 * Get a response from the Pocket API.
 *
 * @access public
 * @param  $url the API endpoint URL
 * @param  $post array data to be passed to the API
 * @return mixed false if there's an error, otherwise an array of API data
 */
function get_pocket_response( $url, $post ) {
    $response = wp_safe_remote_post( $url, array( 'body' => $post ) );

    if ( is_wp_error( $response ) ) {
        return false;
    }

    return json_decode( wp_remote_retrieve_body( $response ), true );
}

@bamadesigner
Copy link
Author

Thank you, thank you, thank you Rob! Right after I shared that I noticed I needed to update the curl stuff, I've just been busy working on another project today. You're amazing. I will test this out and update the code.

@robneu
Copy link

robneu commented Jun 8, 2015

Sounds good! I wish gists had some way to send notifications or something... I noticed a couple of the item data points didn't make it into the data array when I was moving things around, so I updated my comment with the changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment