Plugin Directory

Changeset 817148


Ignore:
Timestamp:
12/08/2013 11:41:41 PM (12 years ago)
Author:
straker503
Message:

1.0.9 (2013-12-8)

  • Filters for post type and category now work for all Time Intervals
  • Fixed the Total View column error in the "All Posts" page for posts that were not published
  • Added an option in the Settings page to display Total Views in the "All Posts" page (defaults to off)
  • Added post meta for each time interval (Day, Week, Month, Year)
  • Widgets set to display Popular Posts with Time Interval: Day should no longer disappear when stats reset (although post output will likely be random)
  • Can now disable the use of the Jetpack get_stats_csv function to get popular posts using either Blog URI or Blog ID id desired
Location:
jetpack-post-views
Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • jetpack-post-views/trunk/jetpack-post-views.php

    r782591 r817148  
    66 * Description: Adds a widget that displays your most popular posts using Jetpack stats. <strong>NOTE:</strong> If the plugin does not work, visit the <a href="options-general.php?page=jetpack_post_views">Settings</a> page to enter a WordPress API Key.
    77 * Author: Steven Lambert
    8  * Version: 1.0.8
     8 * Version: 1.0.9
    99 * Author URI: http://sklambert.com
    1010 * License: GPL2+
     
    1313// Define plugin version
    1414if ( !defined( 'JETPACK_POST_VIEWS_VERSION_NUM' ) ) {
    15     define( 'JETPACK_POST_VIEWS_VERSION_NUM', '1.0.8' );
     15    define( 'JETPACK_POST_VIEWS_VERSION_NUM', '1.0.9' );
    1616}
    1717
     
    2121 * Queries the Jetpack API and adds a custom post_meta 'jetpack-post-views' that holds the total views of a
    2222 * post as listed on Jetpack. Adds a widget to display the top posts for a site.
    23  * NOTE: Plugin must have a correct Wordpress API Key before the post_meta data is added.
    2423 */
    2524class Jetpack_Post_Views extends WP_Widget {
    2625
    27     // Private variables
    28     var $apiUrlBefore = 'http://stats.wordpress.com/csv.php';
    29     var $apiUrlAfter  = '&table=postviews&days=-1&limit=-1&summarize&format=json';
    30 
    31     // Update test data
    32     var $updateMessages = array();
    33     var $DEBUG = false;
    34 
    35     /* CONSTRUCTOR */
    36     function __construct() {
    37 
    38         // Admin hooks
    39         add_action( 'admin_init',                            array( &$this, 'register_setting' ) );
    40         add_action( 'admin_menu',                            array( &$this, 'register_settings_page' ) );
    41         add_action( 'manage_posts_custom_column',            array( &$this, 'add_post_views_column_content' ), 10, 2);
    42         add_filter( 'plugin_action_links',                   array( &$this, 'settings_link' ), 10, 2 );
    43         add_filter( 'manage_posts_columns',                  array( &$this, 'add_post_views_column' ) );
    44         add_filter( 'manage_edit-post_sortable_columns',     array( &$this, 'post_views_column_sort') );
    45         add_filter( 'request',                               array( &$this, 'post_views_column_orderby' ) );
    46 
    47         // Scheduled hooks
    48         add_action( 'jetpack_post_views_scheduled_update',   array( &$this, 'get_post_views' ) );
    49 
    50         // Post hooks
    51         add_action( 'publish_post',                          array( &$this, 'add_jetpack_meta' ) );
    52 
    53         // Query the database for the blog_id
    54         global $wpdb;
    55         $options_table = $wpdb->base_prefix."options";
    56         $stats_options = $wpdb->get_var( "SELECT option_value
    57                                           FROM   $options_table
    58                                           WHERE  option_name = 'stats_options'" );
    59         $stats = unserialize($stats_options);
    60 
    61         // Set blog_id
    62         if ( $stats ) {
    63             $this->blog_id = $stats['blog_id'];
    64         }
    65         else { // Jetpack stats unavailable
    66 
    67             // Try another possiblility to get the blog_id
    68             $jetpack_options = $wpdb->get_var( "SELECT option_value
    69                                                 FROM   $options_table
    70                                                 WHERE  option_name = 'jetpack_options'" );
    71             $jetpack = unserialize($jetpack_options);
    72 
    73             if ( $jetpack ) {
    74                 $this->blog_id = $jetpack['id'];
    75             }
    76             else { // Jetpack stats really unavailable
    77                 $this->blog_id = -1;
    78             }
    79         }
    80 
    81         // Grab the api key if it already exists
    82         $api_key = get_option( 'jetpack_post_views_wp_api_key' ) != "" ? get_option( 'jetpack_post_views_wp_api_key' ) : "";
    83 
    84         // Default settings
    85         $this->defaultsettings = (array) apply_filters( 'jetpack_post_views_defaultsettings', array(
    86             'version'          => JETPACK_POST_VIEWS_VERSION_NUM,
    87             'api_key'          => $api_key,
    88             'blog_id'          => $this->blog_id,
    89             'blog_uri'         => get_bloginfo( 'wpurl' ),
    90             'changed'          => 0,
    91             'connect_blog_id'  => 0,
    92             'connect_blog_uri' => 0
    93         ) );
    94 
    95         // Create the settings array by merging the user's settings and the defaults
    96         $usersettings = (array) get_option('jetpack_post_views_settings');
    97         $this->settings = wp_parse_args( $usersettings, $this->defaultsettings );
    98 
    99         // Controls and options
    100         $widget_ops = array(
    101             'classname'   => 'jetpack-post-views',
    102             'description' => __( 'Your site\'s most popular posts using Jetpack stats', 'jetpack-post-views')
    103         );
     26    // Private variables
     27    var $apiUrl  = 'http://stats.wordpress.com/csv.php';
     28    var $apiArgs = array(
     29        'table'     => 'postviews',
     30        'days'      => -1,
     31        'limit'     => -1,
     32        'summarize' =>  1,
     33        'format'    => 'json'
     34    );
     35    var $interval = array(
     36        'Unlimited' =>  -1,
     37        'Day'       =>   1,
     38        'Week'      =>   7,
     39        'Month'     =>  30,
     40        'Year'      => 365
     41    );
     42
     43    // Update test data
     44    var $updateMessages = array();
     45    var $DEBUG          = false;
     46
     47    /* CONSTRUCTOR */
     48    function __construct() {
     49
     50        // Admin hooks
     51        add_action( 'admin_init',                            array( &$this, 'register_setting' ) );
     52        add_action( 'admin_menu',                            array( &$this, 'register_settings_page' ) );
     53        add_action( 'manage_posts_custom_column',            array( &$this, 'add_post_views_column_content' ), 10, 2);
     54        add_filter( 'plugin_action_links',                   array( &$this, 'settings_link' ), 10, 2 );
     55        add_filter( 'manage_posts_columns',                  array( &$this, 'add_post_views_column' ) );
     56        add_filter( 'manage_edit-post_sortable_columns',     array( &$this, 'post_views_column_sort') );
     57        add_filter( 'request',                               array( &$this, 'post_views_column_orderby' ) );
     58
     59        // Scheduled hooks
     60        add_action( 'jetpack_post_views_scheduled_update',   array( &$this, 'get_post_views' ) );
     61
     62        // Post hooks
     63        add_action( 'publish_post',                          array( &$this, 'add_jetpack_meta' ) );
     64
     65        // Query the database for the blog_id
     66        global $wpdb;
     67        $options_table = $wpdb->base_prefix."options";
     68        $stats_options = $wpdb->get_var( "SELECT option_value
     69                                          FROM   $options_table
     70                                          WHERE  option_name = 'stats_options'" );
     71        $stats = unserialize($stats_options);
     72
     73        // Set blog_id
     74        if ( $stats ) {
     75            $this->blog_id = $stats['blog_id'];
     76        }
     77        else { // Jetpack stats unavailable
     78
     79            // Try another possibility to get the blog_id
     80            $jetpack_options = $wpdb->get_var( "SELECT option_value
     81                                                FROM   $options_table
     82                                                WHERE  option_name = 'jetpack_options'" );
     83            $jetpack = unserialize($jetpack_options);
     84
     85            if ( $jetpack ) {
     86                $this->blog_id = $jetpack['id'];
     87            }
     88            else { // Jetpack stats really unavailable
     89                $this->blog_id = -1;
     90            }
     91        }
     92
     93        // Get the api key if it already exists
     94        $api_key = get_option( 'jetpack_post_views_wp_api_key' ) != "" ? get_option( 'jetpack_post_views_wp_api_key' ) : "";
     95
     96        // Default settings
     97        $this->defaultsettings = (array) apply_filters( 'jetpack_post_views_defaultsettings', array(
     98            'version'             => JETPACK_POST_VIEWS_VERSION_NUM,
     99            'api_key'             => $api_key,
     100            'blog_id'             => $this->blog_id,
     101            'blog_uri'            => home_url( '/' ),
     102            'changed'             => 0,
     103            'connect_blog_id'     => 0,
     104            'connect_blog_uri'    => 0,
     105            'display_total_views' => "",
     106            'use_stats_get_csv'   => "on",
     107            'use_blog_uri'        => "on"
     108        ) );
     109
     110        // Create the settings array by merging the user's settings and the defaults
     111        $usersettings = (array) get_option('jetpack_post_views_settings');
     112        $this->settings = wp_parse_args( $usersettings, $this->defaultsettings );
     113
     114        // Controls and options
     115        $widget_ops = array(
     116            'classname'   => 'jetpack-post-views',
     117            'description' => __( 'Your site\'s most popular posts using Jetpack stats', 'jetpack-post-views')
     118        );
    104119        $control_ops = array(
    105             'id_base' => 'jetpack-post-views-widget'
     120            'id_base' => 'jetpack-post-views-widget'
    106121        );
    107122
    108123        // Set widget information
    109124        $this->WP_Widget( 'jetpack-post-views-widget', __( 'Jetpack Post Views Widget', 'jetpack-post-views'), $widget_ops, $control_ops );
    110     }
    111 
    112     /* REGISTER SETTINGS PAGE */
    113     function register_settings_page() {
    114         add_options_page( __( 'Jetpack Post Views Settings', 'jetpack-post-views' ), __( 'Jetpack Post Views', 'jetpack-post-views' ), 'manage_options', 'jetpack_post_views', array( &$this, 'settings_page' ) );
    115     }
    116 
    117     /* REGISTER PLUGIN SETTINGS */
    118     function register_setting() {
    119         register_setting( 'jetpack_post_views_settings', 'jetpack_post_views_settings', array( &$this, 'validate_settings' ) );
    120     }
    121 
    122 
    123     /* ADD JETPACK POST META ON POST PUBLISH */
    124     function add_jetpack_meta() {
    125         global $post;
    126         add_post_meta( $post->ID, 'jetpack-post-views', 0, true );
    127     }
    128 
    129     /* ADD POST VIEWS TO POST ADMIN PAGE */
    130     function add_post_views_column( $defaults ) {
    131         $defaults['post_views'] = __( 'Total Views', 'jetpack-post-views' );
    132         return $defaults;
    133     }
    134 
    135     /* SHOW THE TOTAL NUMBER OF VIEWS FOR A POST */
    136     function add_post_views_column_content( $column_name, $post_ID ) {
    137         if ($column_name == 'post_views') {
    138             echo number_format_i18n( get_post_meta( $post_ID, "jetpack-post-views", true ) ).__( ' views', 'jetpack-post-views' );
    139         }
    140     }
    141 
    142     /* ALLOW SORTING OF POST VIEW COLUMN */
    143     function post_views_column_sort( $columns ) {
    144         $columns['post_views'] = 'post_views';
    145         return $columns;
    146     }
    147 
    148     /* SORT POST VIEW COLUMN BY VIEWS */
    149     function post_views_column_orderby( $vars ) {
    150         if ( isset( $vars['orderby'] ) && 'post_views' == $vars['orderby'] ) {
    151             $vars = array_merge( $vars, array(
    152                 'meta_key' => 'jetpack-post-views',
    153                 'orderby' => 'meta_value_num'
    154             ) );
    155         }
    156         return $vars;
    157     }
    158 
    159     /* ADD A "SETTINGS" LINK TO PLUGINS PAGE */
    160     function settings_link( $links, $file ) {
    161         static $this_plugin;
    162 
    163         if( empty($this_plugin) )
    164             $this_plugin = plugin_basename(__FILE__);
    165 
    166         if ( $file == $this_plugin )
    167             $links[] = '<a href="' . admin_url( 'options-general.php?page=jetpack_post_views' ) . '">' . __( 'Settings', 'jetpack-post-views' ) . '</a>';
    168 
    169         return $links;
    170     }
    171 
    172     /* SETTINGS PAGE */
    173     function settings_page() { ?>
    174 
    175         <style>
    176             .light {
    177                 height: 14px;
    178                 width: 14px;
    179                 border-radius: 14px;
    180                 -webkit-border-radius: 14px;
    181                 -moz-border-radius: 14px;
    182                 -ms-border-radius: 14px;
    183                 -o-border-radius: 14px;
    184                 position: relative;
    185                 top: 3px;
    186                 box-shadow:
    187                     0 1px 2px #fff,
    188                     0 -1px 1px #666,
    189                     inset 1px -2px 6px rgba(0,0,0,0.5),
    190                     inset -1px 1px 6px rgba(255,255,255,0.8);
    191             }
    192                 .green {
    193                     background-color: #00b028;
    194                 }
    195                 .red {
    196                     background-color: #d20406;
    197                 }
    198 
    199             .inner-light {
    200                 position: absolute;
    201                 top: -1px;
    202                 left: 5px;
    203             }
    204                 .green .inner-light {
    205                     background-color: rgba(123,252,149,0.7);
    206                     border: 3px solid rgba(47,205,82,0.7);
    207                     width: 1px;
    208                     height: 1px;
    209                     border-radius: 1px;
    210                     -webkit-border-radius: 1px;
    211                     -moz-border-radius: 1px;
    212                     -ms-border-radius: 1px;
    213                     -o-border-radius: 1px;
    214                     filter: blur(1.5px);
    215                     -webkit-filter: blur(1.5px);
    216                     -moz-filter: blur(1.5px);
    217                     -ms-filter: blur(1.5px);
    218                     -o-filter: blur(1.5px);
    219                 }
    220                 .red .inner-light {
    221                     background-color: rgba(225,162,157,0.7);
    222                     border: 1px solid rgba(222,222,222,0.7);
    223                     width: 7px;
    224                     height: 7px;
    225                     border-radius: 7px;
    226                     -webkit-border-radius: 7px;
    227                     -moz-border-radius: 7px;
    228                     -ms-border-radius: 7px;
    229                     -o-border-radius: 7px;
    230                     filter: blur(2px);
    231                     -webkit-filter: blur(2px);
    232                     -moz-filter: blur(2px);
    233                     -ms-filter: blur(2px);
    234                     -o-filter: blur(2px);
    235                 }
    236         </style>
    237 
    238         <div class="wrap">
    239         <?php if ( function_exists('screen_icon') ) screen_icon(); ?>
    240 
    241             <h2><?php _e( 'Jetpack Post Views Settings', 'jetpack-post-views' ); ?></h2>
    242 
    243             <p><?php _e( 'Use the settings below if the plugin is unable to connect to Jetpack using the function <code>stats_get_csv()</code>.', 'jetpack-post-views' ); ?></p>
    244 
    245             <form method="post" action="options.php">
    246 
    247             <?php settings_fields('jetpack_post_views_settings'); ?>
    248 
    249             <table class="form-table">
    250                 <tr valign="top">
    251                     <th scope="row"><label for="jetpack-post-views-api-key"><?php _e( 'WordPress API Key', 'jetpack-post-views' ); ?></label></th>
    252                     <td><input name="jetpack_post_views_settings[api_key]" type="text" id="jetpack-post-views-api-key" value="<?php echo esc_attr( $this->settings['api_key'] ); ?>" class="regular-text" placeholder="<?php _e("https://apikey.wordpress.com/", 'jetpack-post-views'); ?>" /></td>
    253                 </tr>
    254                 <tr valign="top">
    255                     <th scope="row"><label for="jetpack-post-views-blog_uri"><?php _e( 'Blog URI', 'jetpack-post-views' ); ?></label></th>
    256                     <td><input name="jetpack_post_views_settings[blog_uri]" type="text" id="jetpack-post-views-blog-uri" value="<?php echo esc_attr( $this->settings['blog_uri'] ); ?>" class="regular-text" /></td>
    257                 </tr>
    258             </table>
    259 
    260             <h3><?php _e( 'Connections', 'jetpack-post-views' ); ?></h3>
    261 
    262             <p><?php _e( 'Shows the status of connections to the Jetpack API. If at least one of the below connections shows green, the plugin should work properly.<br>Stats updated using the first connection available  in the order that they are listed.', 'jetpack-post-views' ); ?></p>
    263 
    264             <?php
    265                 if ( $this->settings['changed'] ) {
    266                     // Test the URI connection
    267                     $middle = '?api_key='.$this->settings['api_key'].'&blog_uri='.$this->settings['blog_uri'];
    268                     $url = $this->apiUrlBefore.$middle.$this->apiUrlAfter;
    269                     $json = file_get_contents( $url );
    270                     $data = json_decode( $json, true );
    271 
    272                     if ( $data[0]['postviews'] ) { // We got data back
    273                         $this->settings['connect_blog_uri'] = 1;
    274                     }
    275                     else {
    276                         $this->settings['connect_blog_uri'] = 0;
    277                     }
    278 
    279                     // Test the Blog ID connection
    280                     $middle = '?api_key='.$this->settings['api_key'].'&blog_id='.$this->settings['blog_id'];
    281                     $url = $this->apiUrlBefore.$middle.$this->apiUrlAfter;
    282                     $json = file_get_contents( $url );
    283                     $data = json_decode( $json, true );
    284 
    285                     if ( $data[0]['postviews'] ) { // We got data back
    286                         $this->settings['connect_blog_id'] = 1;
    287                     }
    288                     else {
    289                         $this->settings['connect_blog_id'] = 0;
    290                     }
    291 
    292                     $this->get_post_views();
    293                 }
    294             ?>
    295 
    296             <input type="hidden" name="jetpack_post_views_settings[connect_blog_uri]" id="jetpack-post-views-connect-blog-id" value="<?php echo esc_attr( $this->settings['connect_blog_uri'] ); ?>" />
    297             <input type="hidden" name="jetpack_post_views_settings[connect_blog_id]" id="jetpack-post-views-connect-blog-id" value="<?php echo esc_attr( $this->settings['connect_blog_id'] ); ?>" />
    298             <table class="form-table">
    299                 <fieldset>
    300                     <tr valign="top">
    301                         <th scope="row"><?php _e( 'Function <code>stats_get_csv()</code> exists', 'jetpack-post-views' ); ?></th>
    302                         <td>
    303                             <?php if ( function_exists('stats_get_csv') ) { ?>
    304                                 <div class="light green"><div class="inner-light"></div></div>
    305                             <?php } else { ?>
    306                                 <div class="light red"><div class="inner-light"></div></div>
    307                             <?php } ?>
    308                         </td>
    309                     </tr>
    310                     <tr valign="top">
    311                         <th scope="row"><?php _e( 'Can connect using Blog URI', 'jetpack-post-views' ); ?></th>
    312                         <td>
    313                             <?php if ( $this->settings['connect_blog_uri'] ) { ?>
    314                                 <div class="light green"><div class="inner-light"></div></div>
    315                             <?php } else { ?>
    316                                 <div class="light red"><div class="inner-light"></div></div>
    317                             <?php } ?>
    318                         </td>
    319                     </tr>
    320                     <tr valign="top">
    321                         <th scope="row"><?php _e( 'Can connect using Blog ID', 'jetpack-post-views' ); ?></th>
    322                         <td>
    323                             <?php if ( $this->settings['connect_blog_id'] ) { ?>
    324                                 <div class="light green"><div class="inner-light"></div></div>
    325                             <?php } else { ?>
    326                                 <div class="light red"><div class="inner-light"></div></div>
    327                             <?php } ?>
    328                         </td>
    329                     </tr>
    330                 </fieldset>
    331             </table>
    332 
    333             <p class="submit">
    334             <?php
    335                 if ( function_exists( 'submit_button' ) ) {
    336                     submit_button( null, 'primary', 'jetpack-post-views-submit', false );
    337                 } else {
    338                     echo '<input type="submit" name="jetpack-post-views-submit" class="button-primary" value="' . __( 'Save Changes', 'jetpack-post-views' ) . '" />' . "\n";
    339                 }
    340             ?>
    341             </p>
    342 
    343             <p>
    344                 <h3>Donate to Help Support this Plugin</h3>
    345                 <p>Jetpack Post Views remains a free plugin thanks to donations from supporters like you. Donations like yours help me to continue supporting this plugin with regular updates and bug fixes. Thanks for being a supporter!</p>
    346                 <p> - Steven Lambert</p>
    347                 <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CPUDV9EYETJYJ" title="Donate to this plugin!">
    348                     <img src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" alt="" />
    349                 </a>
    350             </p>
    351 
    352             <?php
    353                 if ($this->DEBUG) {
    354                     echo "<div class='widefat'><h3>Plugin options</h3><pre>";
    355                     foreach ($this->settings as $key => $value) {
    356                         echo "[$key]: $value\n";
    357                     }
    358                     echo "</pre></div>";
    359 
    360                     if (function_exists('stats_get_csv')) {
    361                         echo "<br>stats_get_csv function exists<br>";
    362                     }
    363                     else {
    364                         echo "<br>stats_get_csv function does not exist<br>";
    365                     }
    366 
    367                     $this->get_post_views();
    368                     ksort($this->updateMessages);
    369 
    370                     echo "<br><div class='widefat'><h3>Update Messages by Post ID</h3><pre>";
    371                     foreach ($this->updateMessages as $key => $value) {
    372                         if ( gettype($value) == "array") {
    373                             echo "[$key]: ";
    374                             print_r($value);
    375                         }
    376                         else {
    377                             echo "[$key]: $value\n";
    378                         }
    379                     }
    380                     echo "</pre></div>";
    381                 }
    382             ?>
    383 
    384         </form>
    385 
    386     </div>
    387 
    388     <?php
    389     }
    390 
    391     /* WIDGET OUTPUT */
    392     function widget( $args, $instance ) {
    393         global $post;
    394         extract ( $args );
    395 
    396         $title = apply_filters('widget_title', $instance['title'] );
    397         $results = "";
    398         $exclude_posts = explode( ',', $instance['exclude_posts'] );
    399 
    400         echo $before_widget;
    401 
    402         // Print the title
    403         if ( $title )
    404             echo $before_title . $title . $after_title;
    405 
    406         ?>
    407 
    408         <style>
    409             .JPV_list {
    410                 overflow: hidden;
    411             }
    412 
    413             .JPV_thumbnail {
    414                 width: 45%;
    415             }
    416 
    417             .JPV_thumbnail > .JPV_thumbnail_img {
    418                 max-width: 125px;
    419                 height: auto;
    420             }
    421 
    422             .JPV_thumbnail + .JPV_text {
    423                 width: 45%;
    424                 padding-bottom: 10px;
    425                 text-align: center;
    426                 margin-top: -5px;
    427             }
    428 
    429             .JPV_thumbnail_title {
    430                 float: left;
    431                 width: 21.276596%;
    432             }
    433 
    434             .JPV_thumbnail_title > .JPV_thumbnail_img {
    435                 max-width: 40px;
    436                 height: auto;
    437             }
    438 
    439             .JPV_thumbnail_title + .JPV_text {
    440                 float: right;
    441                 width: 73.404255%;
    442                 padding-bottom: 10px;
    443             }
    444 
    445         </style>
    446 
    447         <?php
    448 
    449         // Get all categories
    450         $categories = get_categories();
    451 
    452         // Get all post types
    453         $all_post_types = array();
    454         $all_post_types = get_post_types( array( '_builtin' => false ), 'names' );
    455         $all_post_types['post'] = 'post';
    456 
    457         // Filter which post types are displayed
    458         $post_types = array();
    459         foreach ( $all_post_types as $key => $value ) {
    460             if ( $instance['type_'.$key] ) {
    461                 array_push($post_types, $key);
    462             }
    463         }
    464 
    465         // Grab the top posts and display them using the stats_get_csv function
    466         if ( $instance['days'] != '-1' && function_exists('stats_get_csv') ) {
    467             $posts = stats_get_csv('postviews', 'days='.$instance['days'].'&limit=-1' );
    468             $exclude_posts = explode( ',', $instance['exclude_posts'] );
    469             $count = 0;
    470 
    471             // Print top posts in order
    472             $results = "<ul>";
    473             foreach( $posts as $post ) {
    474                 // Stop printing posts if we reach the limit
    475                 if ( $count >= intval( $instance['num_posts'] ) ) {
    476                     break;
    477                 }
    478 
    479                 // // Get all categories
    480                 // $cat_list = array();
    481                 // foreach ( $categories as $key => $value ) {
    482                 //  if ( $instance['category_'.$value->slug] ) {
    483                 //      array_push($cat_list, $value->cat_ID);
    484                 //  }
    485                 // }
    486 
    487                 // // Get the post's categories
    488                 // $cat_ids = array();
    489                 // $category = get_the_category( $post['post_id'] );
    490                 // foreach ($category as $cat) {
    491                 //  array_push($cat_ids, $cat->cat_ID);
    492                 // }
    493 
    494                 // $inCat = false;
    495                 // if ( array_intersect($cat_list, $cat_ids) ) {
    496                 //  $inCat = true;
    497                 // }
    498 
    499                 // Only display posts and from the selected categories
    500                 if ( $post['post_id'] && get_post( $post['post_id'] ) && in_array( get_post_type( $post['post_id'] ), $post_types ) && !in_array( $post['post_id'], $exclude_posts) ) {
    501                     $title = get_the_title( $post['post_id'] );
    502                     $thumbnail = wp_get_attachment_image_src( get_post_thumbnail_id( $post['post_id'] ), 'post-thumbnail' );
    503                     $views = number_format_i18n( $post['views'] ? $post['views'] : 0 ).__( ' views', 'jetpack-post-views' );
    504 
    505                     $results .= '<li class="JPV_list"><a href="'.get_permalink( $post['post_id'] ).'" title="'.$title.'" class="JPV_'.$instance["display_type"].'">';
    506                     switch ( $instance["display_type"] ) {
    507                         case "thumbnail":
    508                             $results .= '<img src="'.$thumbnail[0].'" class="JPV_thumbnail_img"/></a>';
    509                             if ( $instance["show_views"] )
    510                                 $results .= '<div class="JPV_text">'.$views.'</div>';
    511                             break;
    512                         case "thumbnail_title":
    513                             $results .= '<img src="'.$thumbnail[0].'" class="JPV_thumbnail_img"/></a><div class="JPV_text"><a href="'.get_permalink( $post['post_id'] ).'" title="'.$title.'">'.$title.'</a>';
    514                             if ( $instance["show_views"] )
    515                                 $results .= " - ".$views.'</div>';
    516                             break;
    517                         default:
    518                             $results .= $title.'</a>';
    519                             if ( $instance["show_views"] )
    520                                 $results .= " - ".$views;
    521                     }
    522                     $results .= '</li>';
    523                     $count++;
    524                 }
    525             }
    526             $results .= "</ul>";
    527         }
    528         // Else grab the top posts using the post meta
    529         else {
    530             // Filter results by category
    531             $cat_list = array();
    532             foreach ( $categories as $key => $value ) {
    533                 if ( $instance['category_'.$value->slug] ) {
    534                     array_push($cat_list, $value->cat_ID);
    535                 }
    536             }
    537             $category = implode(',', $cat_list);
    538 
    539             $args = array(
    540                 'numberposts' => $instance['num_posts'],
    541                 'orderby'     => 'meta_value_num',
    542                 'order'       => 'DESC',
    543                 'exclude'     => $instance['exclude_posts'],
    544                 'meta_key'    => 'jetpack-post-views',
    545                 'post_type'   => $post_types,
    546                 'category'    => $category
    547             );
    548             $posts = get_posts( $args );
    549 
    550             // Print top posts in order
    551             $results = "<ul>";
    552             foreach( $posts as $post ) {
    553                 $title = get_the_title( $post->ID );
    554                 $thumbnail = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'post-thumbnail' );
    555                 $views = number_format_i18n( get_post_meta( $post->ID, "jetpack-post-views", true ) ).__( ' views', 'jetpack-post-views' );
    556 
    557                 $results .= '<li class="JPV_list"><a href="'.get_permalink( $post->ID ).'" title="'.$title.'" class="JPV_'.$instance["display_type"].'">';
    558                 switch ( $instance["display_type"] ) {
    559                     case "thumbnail":
    560                         $results .= '<img src="'.$thumbnail[0].'" class="JPV_thumbnail_img"/></a>';
    561                         if ( $instance["show_views"] )
    562                             $results .= '<div class="JPV_text">'.$views.'</div>';
    563                         break;
    564                     case "thumbnail_title":
    565                         $results .= '<img src="'.$thumbnail[0].'" class="JPV_thumbnail_img"/></a><div class="JPV_text"><a href="'.get_permalink( $post->ID ).'" title="'.$title.'">'.$title.'</a>';
    566                         if ( $instance["show_views"] )
    567                             $results .= " - ".$views.'</div>';
    568                         break;
    569                     default:
    570                         $results .= $title.'</a>';
    571                         if ( $instance["show_views"] )
    572                             $results .= " - ".$views;
    573                 }
    574                 $results .= '</li>';
    575             }
    576             $results .= "</ul>";
    577         }
    578 
    579         echo $results;
    580 
    581         echo $after_widget;
    582     }
    583 
    584     /* UPDATE WIDGET OPTIONS */
    585     function update( $new_instance, $old_instance ) {
    586         $instance = $old_instance;
    587 
    588         // Check nonce
    589         check_admin_referer('jetpack-post-views-widget-form-submission');
    590 
    591         $instance['title'] = strip_tags( $new_instance['title'] );
    592         $instance['show_views'] = strip_tags( $new_instance['show_views'] );
    593         $instance['days'] = strip_tags( $new_instance['days'] );
    594         $instance['exclude_custom_types'] = strip_tags( $new_instance['exclude_custom_types'] );
    595         $instance['exclude_posts'] = strip_tags( $new_instance['exclude_posts'] );
    596         $instance['display_type'] = strip_tags( $new_instance['display_type'] );
    597         $instance['display_post_types'] = strip_tags( $new_instance['display_post_types'] );
    598 
    599         // Get all post types
    600         $post_types = get_post_types( array( '_builtin' => false ), 'names' );
    601         $post_types['post'] = 'post';
    602         foreach ( $post_types as $key => $value ) {
    603             if ( $value != 'safecss' ) {
    604                 $instance['type_'.$key] = strip_tags( $new_instance['type_'.$key] );
    605             }
    606         }
    607 
    608         // Get all categories
    609         $categories = get_categories();
    610         foreach ( $categories as $key => $value ) {
    611             $instance['category_'.$value->slug] = strip_tags( $new_instance['category_'.$value->slug] );
    612         }
    613 
    614         // Set default number of posts to display if invalid option
    615         $num_posts = intval( strip_tags( $new_instance['num_posts'] ) );
    616         $instance['num_posts'] = ($num_posts > 0 ? $num_posts : 5);
    617 
    618         return $instance;
    619     }
    620 
    621     /* DISPLAY WIDGET OPTIONS */
    622     function form( $instance ) {
    623 
    624         // Default widget settings
    625         $defaults = array(
    626             'title'                => __( 'Most Popular Posts', 'jetpack-post-views' ),
    627             'error'                => '',
    628             'num_posts'            => 5,
    629             'days'                 => '-1',
    630             'show_views'           => false,
    631             'display_type'         => 'title',
    632             'exclude_posts'        => '',
    633             'display_post_types'   => ''
    634         );
    635 
    636         // Get all post types
    637         $post_types = get_post_types( array( '_builtin' => false ), 'names' );
    638         $post_types['post'] = 'post';
    639         foreach ( $post_types as $key => $value ) {
    640             if ( $value != 'safecss' ) { // I have no idea what this is but it's not a valid post type
    641                 $defaults['type_'.$key] = 'on';
    642             }
    643         }
    644 
    645         // Get all categories
    646         $categories = get_categories();
    647         foreach ( $categories as $key => $value ) {
    648             $defaults['category_'.$value->slug] = 'on';
    649         }
    650 
    651         $instance = wp_parse_args( (array) $instance, $defaults );
    652 
    653         // echo "<pre>";
    654         // print_r($instance);
    655         // echo "</pre>";
    656 
    657         // Set nonce
    658         if ( function_exists('wp_nonce_field') ) {
    659             wp_nonce_field( 'jetpack-post-views-widget-form-submission' );
    660             echo "\n<!-- end of wp_nonce_field -->\n";
    661         }
    662 
    663         ?>
    664 
    665         <style>
    666             #JPV-display-content h3 {
    667                 margin-top: 0;
    668             }
    669         </style>
    670 
    671         <div id="JPV-display-content" class="JPV-tab-content active">
    672             <h3>Display</h3>
    673 
    674             <p>
    675                 <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'jetpack-post-views'); ?></label>
    676                 <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" type="text" />
    677             </p>
    678 
    679             <p>
    680                 <label for="<?php echo $this->get_field_id( 'num_posts' ); ?>"><?php _e('Number of posts to show:', 'jetpack-post-views'); ?></label>
    681                 <input id="<?php echo $this->get_field_id( 'num_posts' ); ?>" name="<?php echo $this->get_field_name( 'num_posts' ); ?>" value="<?php echo $instance['num_posts']; ?>" type="text" size="3" />
    682             </p>
    683 
    684             <p>
    685                 <label for="<?php echo $this->get_field_id( 'days' ); ?>"><?php _e('<span class="error">*</span>Time interval:', 'jetpack-post-views'); ?></label>
    686                 <select id="<?php echo $this->get_field_id( 'days' ); ?>" name="<?php echo $this->get_field_name( 'days' ); ?>">
    687                     <option value="-1" <?php echo ($instance['days'] == '-1' ? 'selected' : '') ?> ><?php _e('Unlimited', 'jetpack-post-views'); ?></option>
    688                     <option value="1" <?php echo ($instance['days'] == '1' ? 'selected' : '') ?> ><?php _e('Day', 'jetpack-post-views'); ?></option>
    689                     <option value="7" <?php echo ($instance['days'] == '7' ? 'selected' : '') ?> ><?php _e('Week', 'jetpack-post-views'); ?></option>
    690                     <option value="30" <?php echo ($instance['days'] == '30' ? 'selected' : '') ?> ><?php _e('Month', 'jetpack-post-views'); ?></option>
    691                     <option value="366" <?php echo ($instance['days'] == '366' ? 'selected' : '') ?> ><?php _e('Year', 'jetpack-post-views'); ?></option>
    692                 </select>
    693             </p>
    694 
    695             <p>
    696                 <input class="checkbox" type="checkbox" <?php checked( $instance['show_views'], 'on' ); ?> id="<?php echo $this->get_field_id( 'show_views' ); ?>" name="<?php echo $this->get_field_name( 'show_views' ); ?>" />
    697                 <label for="<?php echo $this->get_field_id( 'show_views' ); ?>"><?php _e('Display number of views?', 'jetpack-post-views'); ?></label>
    698             </p>
    699 
    700             <p>
    701                 <label for="<?php echo $this->get_field_id( 'display_type' ); ?>"><?php _e('Display as:', 'jetpack-post-views'); ?></label>
    702                 <select id="<?php echo $this->get_field_id( 'display_type' ); ?>" name="<?php echo $this->get_field_name( 'display_type' ); ?>">
    703                     <option value="title" <?php echo ($instance['display_type'] == 'title' ? 'selected' : '') ?> ><?php _e('Title', 'jetpack-post-views'); ?></option>
    704                     <option value="thumbnail" <?php echo ($instance['display_type'] == 'thumbnail' ? 'selected' : '') ?> ><?php _e('Thumbnail', 'jetpack-post-views'); ?></option>
    705                     <option value="thumbnail_title" <?php echo ($instance['display_type'] == 'thumbnail_title' ? 'selected' : '') ?> ><?php _e('Thumbnail + Title', 'jetpack-post-views'); ?></option>
    706                 </select>
    707             </p>
    708 
    709             <p>
    710                 <div><?php _e('<span class="error">*</span>Only works if the function <code>stats_get_csv()</code> exists', 'jetpack-post-views'); ?></div>
    711             </p>
    712         </div>
    713 
    714         <div id="JPV-filter-content" class="JPV-tab-content">
    715             <h3>Filter</h3>
    716 
    717             <p>
    718                 <label for="<?php echo $this->get_field_id( 'exclude_posts' ); ?>"><?php _e('Exclude Posts:', 'jetpack-post-views'); ?></label>
    719                 <input class="widefat" id="<?php echo $this->get_field_id( 'exclude_posts' ); ?>" name="<?php echo $this->get_field_name( 'exclude_posts' ); ?>" value="<?php echo $instance['exclude_posts']; ?>" type="text" placeholder="<?php _e('Comma-separated list of post IDs', 'jetpack-post-views'); ?>" />
    720             </p>
    721 
    722             <p>
    723                 <?php _e('Display only from selected post types:', 'jetpack-post-views'); ?>
    724                 <br>
    725                 <?php
    726                     foreach ( $post_types as $key => $value ) {
    727                         if ( $value != 'safecss' ) {
    728                 ?>
    729                             <input class="checkbox" type="checkbox" <?php checked( $instance['type_'.$key], 'on' ); ?> id="<?php echo $this->get_field_id( 'type_'.$key ); ?>" name="<?php echo $this->get_field_name( 'type_'.$key ); ?>" />
    730                             <label for="<?php echo $this->get_field_id( 'type_'.$key ); ?>"><?php echo $key ?></label>
    731                             <br/>
    732                 <?php
    733                         }
    734                     }
    735                 ?>
    736 
    737             </p>
    738 
    739             <p>
    740                 <?php _e('Display only from selected categories:', 'jetpack-post-views'); ?>
    741                 <br>
    742                 <?php
    743                     foreach ( $categories as $key => $value ) {
    744                 ?>
    745                         <input class="checkbox" type="checkbox" <?php checked( $instance['category_'.$value->slug], 'on' ); ?> id="<?php echo $this->get_field_id( 'category_'.$value->slug ); ?>" name="<?php echo $this->get_field_name( 'category_'.$value->slug ); ?>" />
    746                         <label for="<?php echo $this->get_field_id( 'category_'.$value->slug ); ?>"><?php echo $value->name ?></label>
    747                         <br/>
    748                 <?php
    749                     }
    750                 ?>
    751 
    752             </p>
    753         </div>
    754 
    755     <?php
    756     }
    757 
    758     /*
    759     * SCHEDULED UPDATE
    760     * Update all posts 'jetpack-post-views' post meta
    761     */
    762     function get_post_views() {
    763         $run_stats = 0;
    764         $post_stats = array();
    765         $postdata = array();
    766 
    767         // Get stats using the stats_get_csv function
    768         if ( function_exists('stats_get_csv') ) {
    769             // Hack to break cache suggested by Glisse
    770             // http://wordpress.org/support/topic/post-views-not-updating
    771             $random = rand( 9999, 9999999 );
    772             $post_stats = stats_get_csv('postviews', 'days='.$random.'&limit=-1&summarize');
    773 
    774             $post_stats = stats_get_csv('postviews', 'days=-1&limit=-1&summarize');
    775             $this->updateMessages[ -2 ] = "Stats being updated using the stats_get_csv function";
    776             $run_stats = 1;
    777         }
    778         // Else get the stats using the blog_uri
    779         else if ( $this->settings['connect_blog_uri'] ) {
    780             $this->updateMessages[ -2 ] = "Stats being updated using blog_uri";
    781             $middle = '?api_key='.$this->settings['api_key'].'&blog_uri='.$this->settings['blog_uri'];
    782             $url = $this->apiUrlBefore.$middle.$this->apiUrlAfter;
    783             $json = file_get_contents( $url );
    784             $data = json_decode( $json, true );
    785             $post_stats = $data[0]['postviews'];
    786             $run_stats = 1;
    787         }
    788         // Otherwise get the stats using the blog_id
    789         else if ( $this->settings['connect_blog_id'] ) {
    790             $this->updateMessages[ -2 ] = "Stats being updated using blog_id";
    791             $middle = '?api_key='.$this->settings['api_key'].'&blog_uri='.$this->settings['blog_uri'];
    792             $url = $this->apiUrlBefore.$middle.$this->apiUrlAfter;
    793             $json = file_get_contents( $url );
    794             $data = json_decode( $json, true );
    795             $post_stats = $data[0]['postviews'];
    796             $run_stats = 1;
    797         }
    798 
    799         if ( $run_stats ) {
    800             $this->updateMessages[ -1 ] = $post_stats;
    801             global $post;
    802 
    803             // Create a temporary array and save all data
    804             foreach ( $post_stats as $postinfo ) {
    805                 $postdata[ $postinfo['post_id'] ] = strip_tags( $postinfo['views'] );
    806             }
    807 
    808             // Grab all posts and update them
    809             $post_types = get_post_types( array( '_builtin' => false ), 'names' );
    810             $post_types['post'] = 'post';
    811 
    812             $args = array(
    813                 'numberposts' => -1,
    814                 'post_type'   => $post_types,
    815                 'post_status' => 'publish'
    816             );
    817             $allposts = get_posts( $args );
    818             foreach( $allposts as $post) {
    819                 // Ensure that the $post-ID exists as a key in the array before trying to update post information.
    820                 // This prevents the user from pulling data from another website and trying to add it to their own
    821                 // posts.
    822                 if ( array_key_exists( $post->ID, $postdata) ) {
    823                     $newViews = intval( $postdata[ $post->ID ] );
    824                     $oldViews = get_post_meta( $post->ID, 'jetpack-post-views', true );
    825 
    826                     // Only update posts with new stats. Prevents posts from being updated with '0' views when
    827                     // the API service is down.
    828                     if ( $oldViews >= 0 && $newViews > $oldViews ) {
    829                         $this->updateMessages[ $post->ID ] = "'".get_the_title( $post->ID )."' succesfully updated with newViews(".$newViews.")";
    830                         update_post_meta( $post->ID, 'jetpack-post-views', $newViews );
    831                     }
    832                     else {
    833                         if (!$oldViews) {
    834                             $this->updateMessages[ $post->ID ] = "'".get_the_title( $post->ID )."' failed to update because oldViews(".$oldViews.") is 0 or does not exist";
    835                         }
    836                         else {
    837                             $this->updateMessages[ $post->ID ] = "'".get_the_title( $post->ID )."' did not update because newViews(".$newViews.") <= oldViews(".$oldViews.")";
    838                         }
    839                         add_post_meta( $post->ID, 'jetpack-post-views', ($newViews ? $newViews: 0), true );
    840                     }
    841                 }
    842                 else {
    843                     $this->updateMessages[ $post->ID ] = "'".get_the_title( $post->ID )."' failed to update because post->ID is not in postData";
    844                     add_post_meta( $post->ID, 'jetpack-post-views', 0, true );
    845                 }
    846             }
    847         }
    848     }
    849 
    850     /* UPGRADE PLUGIN TO NEW VERSION */
    851     function upgrade() {
    852         global $post;
    853 
    854         // Delete old options
    855         delete_option( 'jetpack-post-views_version' );
    856         delete_option( 'jetpack_post_views_wp_api_key' );
    857         delete_option( 'jetpack_post_views_stats_has_run' );
    858 
    859         // Add post meta for each post
    860         $post_types = get_post_types( array( '_builtin' => false ), 'names' );
    861         $post_types['post'] = 'post';
    862 
    863         $args = array(
    864             'numberposts' => -1,
    865             'post_type'   => $post_types,
    866             'post_status' => 'publish'
    867         );
    868         $allposts = get_posts( $args );
    869         foreach( $allposts as $post) {
    870             $views = get_post_meta( $post->ID, 'jetpack-post-views', true );
    871 
    872             if (!$views) {
    873                 add_post_meta( $post->ID, 'jetpack-post-views', 0, true );
    874             }
    875         }
    876 
    877         define( 'JETPACK_POST_VIEWS_VERSION_NUM', '1.0.8' );
    878     }
    879 
    880     /* VALIDATE SETTING PAGE SETTINGS */
    881     function validate_settings( $settings ) {
    882         if ( !empty($_POST['jetpack-post-views-defaults']) ) {
    883             $settings = $this->defaultsettings;
    884             $_REQUEST['_wp_http_referer'] = add_query_arg( 'defaults', 'true', $_REQUEST['_wp_http_referer'] );
    885         } else {
    886             // Hidden fields
    887             $settings['connect_blog_uri'] = strip_tags( $settings['connect_blog_uri'] );
    888             $settings['connect_blog_id']  = strip_tags( $settings['connect_blog_id'] );
    889 
    890             $settings['api_key']  = ( !empty($settings['api_key']) )  ? strip_tags( $settings['api_key'] )  : "";
    891             $settings['blog_uri'] = ( !empty($settings['blog_uri']) ) ? strip_tags( $settings['blog_uri'] ) : get_bloginfo( 'wpurl' );
    892 
    893             // Flag settings change
    894             if ( $settings['api_key'] != $this->settings['api_key'] || $settings['blog_uri'] != $this->settings['blog_uri'] ) {
    895                 $settings['changed'] = 1;
    896             }
    897         }
    898 
    899         return $settings;
    900     }
    901 
    902     // PHP4 compatibility
    903     function Jetpack_Post_Views() {
    904         $this->__construct();
    905     }
     125    }
     126
     127    /* REGISTER SETTINGS PAGE */
     128    function register_settings_page() {
     129        add_options_page( __( 'Jetpack Post Views Settings', 'jetpack-post-views' ), __( 'Jetpack Post Views', 'jetpack-post-views' ), 'manage_options', 'jetpack_post_views', array( &$this, 'settings_page' ) );
     130    }
     131
     132    /* REGISTER PLUGIN SETTINGS */
     133    function register_setting() {
     134        register_setting( 'jetpack_post_views_settings', 'jetpack_post_views_settings', array( &$this, 'validate_settings' ) );
     135    }
     136
     137
     138    /* ADD JETPACK POST META ON POST PUBLISH */
     139    function add_jetpack_meta() {
     140        global $post;
     141        add_post_meta( $post->ID, 'jetpack-post-views', 0, true );
     142    }
     143
     144    /* ADD POST VIEWS TO POST ADMIN PAGE */
     145    function add_post_views_column( $defaults ) {
     146        if ( $this->settings['display_total_views'] ) {
     147            $defaults['post_views'] = __( 'Total Views', 'jetpack-post-views' );
     148        }
     149        return $defaults;
     150    }
     151
     152    /* SHOW THE TOTAL NUMBER OF VIEWS FOR A POST */
     153    function add_post_views_column_content( $column_name, $post_ID ) {
     154        if ($column_name == 'post_views') {
     155            $views = get_post_meta( $post_ID, "jetpack-post-views", true );
     156
     157            if ( $views ) {
     158                echo number_format_i18n( $views ).__( ' views', 'jetpack-post-views' );
     159            }
     160            else {
     161                echo '0 views';
     162            }
     163        }
     164    }
     165
     166    /* ALLOW SORTING OF POST VIEW COLUMN */
     167    function post_views_column_sort( $columns ) {
     168        $columns['post_views'] = 'post_views';
     169        return $columns;
     170    }
     171
     172    /* SORT POST VIEW COLUMN BY VIEWS */
     173    function post_views_column_orderby( $vars ) {
     174        if ( isset( $vars['orderby'] ) && 'post_views' == $vars['orderby'] ) {
     175            $vars = array_merge( $vars, array(
     176                'meta_key' => 'jetpack-post-views',
     177                'orderby'  => 'meta_value_num'
     178            ) );
     179        }
     180        return $vars;
     181    }
     182
     183    /* ADD A "SETTINGS" LINK TO PLUGINS PAGE */
     184    function settings_link( $links, $file ) {
     185        static $this_plugin;
     186
     187        if( empty($this_plugin) )
     188            $this_plugin = plugin_basename(__FILE__);
     189
     190        if ( $file == $this_plugin )
     191            $links[] = '<a href="' . admin_url( 'options-general.php?page=jetpack_post_views' ) . '">' . __( 'Settings', 'jetpack-post-views' ) . '</a>';
     192
     193        return $links;
     194    }
     195
     196    /* VALIDATE SETTING PAGE SETTINGS */
     197    function validate_settings( $settings ) {
     198        if ( !empty($_POST['jetpack-post-views-defaults']) ) {
     199            $settings = $this->defaultsettings;
     200            $_REQUEST['_wp_http_referer']    = add_query_arg( 'defaults', 'true', $_REQUEST['_wp_http_referer'] );
     201        } else {
     202            // Hidden fields
     203            $settings['connect_blog_uri']    = strip_tags( $settings['connect_blog_uri'] );
     204            $settings['connect_blog_id']     = strip_tags( $settings['connect_blog_id'] );
     205
     206            // Settings
     207            $settings['api_key']             = ( !empty( $settings['api_key'] ) )             ? strip_tags( $settings['api_key'] )             : "";
     208            $settings['blog_uri']            = ( !empty( $settings['blog_uri'] ) )            ? strip_tags( $settings['blog_uri'] )            : home_url( '/' );
     209            $settings['display_total_views'] = ( !empty( $settings['display_total_views'] ) ) ? strip_tags( $settings['display_total_views'] ) : "";
     210            $settings['use_stats_get_csv']   = ( !empty( $settings['use_stats_get_csv'] ) )   ? strip_tags( $settings['use_stats_get_csv'] )   : "";
     211            $settings['use_blog_uri']        = ( !empty( $settings['use_blog_uri'] ) )        ? strip_tags( $settings['use_blog_uri'] )        : "";
     212
     213            // Flag settings change
     214            if ( $settings['api_key'] != $this->settings['api_key'] || $settings['blog_uri'] != $this->settings['blog_uri'] ) {
     215                $settings['changed']         = 1;
     216            }
     217        }
     218
     219        return $settings;
     220    }
     221
     222    /* SETTINGS PAGE */
     223    function settings_page() { ?>
     224
     225        <style>
     226            .light {
     227                height: 14px;
     228                width: 14px;
     229                border-radius: 14px;
     230                -webkit-border-radius: 14px;
     231                -moz-border-radius: 14px;
     232                -ms-border-radius: 14px;
     233                -o-border-radius: 14px;
     234                position: relative;
     235                top: 3px;
     236                box-shadow:
     237                    0 1px 2px #fff,
     238                    0 -1px 1px #666,
     239                    inset 1px -2px 6px rgba(0,0,0,0.5),
     240                    inset -1px 1px 6px rgba(255,255,255,0.8);
     241            }
     242                .green {
     243                    background-color: #00b028;
     244                }
     245                .red {
     246                    background-color: #d20406;
     247                }
     248
     249            .inner-light {
     250                position: absolute;
     251                top: -1px;
     252                left: 5px;
     253            }
     254                .green .inner-light {
     255                    background-color: rgba(123,252,149,0.7);
     256                    border: 3px solid rgba(47,205,82,0.7);
     257                    width: 1px;
     258                    height: 1px;
     259                    border-radius: 1px;
     260                    -webkit-border-radius: 1px;
     261                    -moz-border-radius: 1px;
     262                    -ms-border-radius: 1px;
     263                    -o-border-radius: 1px;
     264                    filter: blur(1.5px);
     265                    -webkit-filter: blur(1.5px);
     266                    -moz-filter: blur(1.5px);
     267                    -ms-filter: blur(1.5px);
     268                    -o-filter: blur(1.5px);
     269                }
     270                .red .inner-light {
     271                    background-color: rgba(225,162,157,0.7);
     272                    border: 1px solid rgba(222,222,222,0.7);
     273                    width: 7px;
     274                    height: 7px;
     275                    border-radius: 7px;
     276                    -webkit-border-radius: 7px;
     277                    -moz-border-radius: 7px;
     278                    -ms-border-radius: 7px;
     279                    -o-border-radius: 7px;
     280                    filter: blur(2px);
     281                    -webkit-filter: blur(2px);
     282                    -moz-filter: blur(2px);
     283                    -ms-filter: blur(2px);
     284                    -o-filter: blur(2px);
     285                }
     286        </style>
     287
     288        <div class="wrap">
     289        <?php if ( function_exists('screen_icon') ) screen_icon(); ?>
     290
     291            <h2><?php _e( 'Jetpack Post Views Settings', 'jetpack-post-views' ); ?></h2>
     292
     293            <form method="post" action="options.php">
     294
     295            <?php settings_fields('jetpack_post_views_settings'); ?>
     296
     297            <table class="form-table">
     298                <tr valign="top">
     299                    <th scope="row"><label for="jetpack-post-views-display-total-views"><?php _e( 'Total Views', 'jetpack-post-views' ); ?></label></th>
     300                    <td><label for="jetpack-post-views-display-total-views">
     301                            <input name="jetpack_post_views_settings[display_total_views]" class="checkbox" type="checkbox" <?php checked( $this->settings['display_total_views'], 'on' ); ?> id="jetpack-post-views-display-total-views" />
     302                            <span><?php _e( 'Display total views for each post on the "All Posts" page.', 'jetpack-post-views' ); ?></span>
     303                        </label>
     304                    </td>
     305                </tr>
     306                <tr valign="top">
     307                    <th scope="row"><label for="jetpack-post-views-use-stats-get-csv"><?php _e( 'Stats_get_csv', 'jetpack-post-views' ); ?></th>
     308                    <td><label for="jetpack-post-views-use-stats-get-csv">
     309                            <input name="jetpack_post_views_settings[use_stats_get_csv]" class="checkbox" type="checkbox" <?php checked( $this->settings['use_stats_get_csv'], 'on' ); ?> id="jetpack-post-views-use-stats-get-csv" />
     310                            <span><?php _e( 'Use the Jetpack function <code>stats_get_csv()</code> to update post views. Disable this option to use the Blog URI or Blog ID instead (for example, if you are using a different site\'s settings).', 'jetpack-post-views' ); ?></span>
     311                        </label>
     312                    </td>
     313                </tr>
     314                <tr valign="top">
     315                    <th scope="row"><label for="jetpack-post-views-use-blog-uri"><?php _e( 'Blog URI', 'jetpack-post-views' ); ?></th>
     316                    <td><label for="jetpack-post-views-use-blog-uri">
     317                            <input name="jetpack_post_views_settings[use_blog_uri]" class="checkbox" type="checkbox" <?php checked( $this->settings['use_blog_uri'], 'on' ); ?> id="jetpack-post-views-use-blog-uri" />
     318                            <span><?php _e( 'Use the Blog URI and WordPress API Key to update post views. If you are not using the Jetpack function <code>stats_get_csv()</code>, disabling this option may help correctly update post views.', 'jetpack-post-views' ); ?></span>
     319                        </label>
     320                    </td>
     321                </tr>
     322            </table>
     323
     324            <h3><?php _e( 'Blog Information', 'jetpack-post-views' ); ?></h3>
     325
     326            <p><?php _e( 'Use the settings below if the plugin is unable to connect to Jetpack using the function <code>stats_get_csv()</code>.', 'jetpack-post-views' ); ?></p>
     327
     328            <table class="form-table">
     329                <tr valign="top">
     330                    <th scope="row"><label for="jetpack-post-views-api-key"><?php _e( 'WordPress API Key', 'jetpack-post-views' ); ?></label></th>
     331                    <td><input name="jetpack_post_views_settings[api_key]" type="text" id="jetpack-post-views-api-key" value="<?php echo esc_attr( $this->settings['api_key'] ); ?>" class="regular-text" placeholder="<?php _e("https://apikey.wordpress.com/", 'jetpack-post-views'); ?>" /></td>
     332                </tr>
     333                <tr valign="top">
     334                    <th scope="row"><label for="jetpack-post-views-blog_uri"><?php _e( 'Blog URI', 'jetpack-post-views' ); ?></label></th>
     335                    <td><input name="jetpack_post_views_settings[blog_uri]" type="text" id="jetpack-post-views-blog-uri" value="<?php echo esc_attr( $this->settings['blog_uri'] ); ?>" class="regular-text" /></td>
     336                </tr>
     337            </table>
     338
     339            <h3><?php _e( 'Connections', 'jetpack-post-views' ); ?></h3>
     340
     341            <p><?php _e( 'Shows the status of connections to the Jetpack API. If at least one of the below connections shows green, the plugin should work properly.<br>Stats updated using the first connection available in the order that they are listed.', 'jetpack-post-views' ); ?></p>
     342
     343            <?php
     344                // Check connections only when settings have changed
     345                if ( $this->settings['changed'] ) {
     346                    $args            = $this->apiArgs;
     347                    $args['limit']   = 1;
     348                    $args['api_key'] = $this->settings['api_key'];
     349
     350                    // Test the URI connection by testing for results from the api
     351                    $args['blog_uri'] = $this->settings['blog_uri'];
     352
     353                    $url              = add_query_arg( $args, $this->apiUrl );
     354                    $json             = wp_remote_get( $url );
     355                    $data             = ( is_array( $json ) && !empty( $json['body'] ) ? json_decode( $json['body'], true ) : array());
     356
     357                    $this->settings['connect_blog_uri'] = ( !empty( $data[0]['postviews'] ) ? 1 : 0 );
     358
     359                    // Test the Blog ID connection by testing for results from the api
     360                    unset( $args['blog_uri'] );
     361                    $args['blog_id']  = $this->settings['blog_id'];
     362
     363                    $url              = add_query_arg( $args, $this->apiUrl );
     364                    $json             = wp_remote_get( $url );
     365                    $data             = ( is_array( $json ) && !empty( $json['body'] ) ? json_decode( $json['body'], true ) : array());
     366
     367                    $this->settings['connect_blog_id'] = ( !empty( $data[0]['postviews'] ) ? 1 : 0 );
     368
     369                    $this->get_post_views();
     370                }
     371            ?>
     372
     373            <input type="hidden" name="jetpack_post_views_settings[connect_blog_uri]" id="jetpack-post-views-connect-blog-id" value="<?php echo esc_attr( $this->settings['connect_blog_uri'] ); ?>" />
     374            <input type="hidden" name="jetpack_post_views_settings[connect_blog_id]" id="jetpack-post-views-connect-blog-id" value="<?php echo esc_attr( $this->settings['connect_blog_id'] ); ?>" />
     375            <table class="form-table">
     376                <fieldset>
     377                    <tr valign="top">
     378                        <th scope="row"><?php _e( 'Function <code>stats_get_csv()</code> exists', 'jetpack-post-views' ); ?></th>
     379                        <td>
     380                            <div class="light <?php echo (function_exists('stats_get_csv') ? "green" : "red") ?>"><div class="inner-light"></div></div>
     381                        </td>
     382                    </tr>
     383                    <tr valign="top">
     384                        <th scope="row"><?php _e( 'Can connect using Blog URI', 'jetpack-post-views' ); ?></th>
     385                        <td>
     386                            <div class="light <?php echo ($this->settings['connect_blog_uri'] ? "green" : "red") ?>"><div class="inner-light"></div></div>
     387                        </td>
     388                    </tr>
     389                    <tr valign="top">
     390                        <th scope="row"><?php _e( 'Can connect using Blog ID', 'jetpack-post-views' ); ?></th>
     391                        <td>
     392                            <div class="light <?php echo ($this->settings['connect_blog_id'] ? "green" : "red") ?>"><div class="inner-light"></div></div>
     393                        </td>
     394                    </tr>
     395                </fieldset>
     396            </table>
     397
     398            <p class="submit">
     399            <?php
     400                if ( function_exists( 'submit_button' ) ) {
     401                    submit_button( null, 'primary', 'jetpack-post-views-submit', false );
     402                } else {
     403                    echo '<input type="submit" name="jetpack-post-views-submit" class="button-primary" value="' . __( 'Save Changes', 'jetpack-post-views' ) . '" />' . "\n";
     404                }
     405            ?>
     406            </p>
     407
     408            <p>
     409                <h3><?php _e( 'Donate to Help Support this Plugin', 'jetpack-post-views' ); ?></h3>
     410                <p><?php _e( 'Jetpack Post Views remains a free plugin thanks to donations from supporters like you. Donations like yours help me to continue supporting this plugin with regular updates and bug fixes. Thanks for being a supporter!', 'jetpack-post-views' ); ?></p>
     411                <p><?php _e( '- Steven Lambert', 'jetpack-post-views' ); ?></p>
     412                <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CPUDV9EYETJYJ" title="Donate to this plugin!">
     413                    <img src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" alt="" />
     414                </a>
     415            </p>
     416
     417            <?php
     418                if ($this->DEBUG) {
     419                    echo "<div class='widefat'><h3>Plugin options</h3><pre>";
     420                    foreach ($this->settings as $key => $value) {
     421                        echo "[$key]: $value\n";
     422                    }
     423                    echo "</pre></div>";
     424
     425                    if (function_exists('stats_get_csv')) {
     426                        echo "<br>stats_get_csv function exists<br>";
     427                    }
     428                    else {
     429                        echo "<br>stats_get_csv function does not exist<br>";
     430                    }
     431
     432                    $this->get_post_views();
     433                    ksort($this->updateMessages);
     434
     435                    echo "<br><div class='widefat'><h3>Update Messages by Post ID</h3><pre>";
     436                    foreach ($this->updateMessages as $key => $value) {
     437                        if ( gettype($value) == "array") {
     438                            echo "[$key]: ";
     439                            print_r($value);
     440                        }
     441                        else {
     442                            echo "[$key]: $value\n";
     443                        }
     444                    }
     445                    echo "</pre></div>";
     446                }
     447            ?>
     448
     449        </form>
     450
     451    </div>
     452
     453    <?php
     454    }
     455
     456    /* WIDGET OUTPUT */
     457    function widget( $args, $instance ) { ?>
     458
     459        <style>
     460            .JPV_list {
     461                overflow: hidden;
     462            }
     463
     464            .JPV_thumbnail {
     465                width: 45%;
     466            }
     467
     468            .JPV_thumbnail > .JPV_thumbnail_img {
     469                max-width: 125px;
     470                height: auto;
     471            }
     472
     473            .JPV_thumbnail + .JPV_text {
     474                width: 45%;
     475                padding-bottom: 10px;
     476                text-align: center;
     477                margin-top: -5px;
     478            }
     479
     480            .JPV_thumbnail_title {
     481                float: left;
     482                width: 21.276596%;
     483            }
     484
     485            .JPV_thumbnail_title > .JPV_thumbnail_img {
     486                max-width: 40px;
     487                height: auto;
     488            }
     489
     490            .JPV_thumbnail_title + .JPV_text {
     491                float: right;
     492                width: 73.404255%;
     493                padding-bottom: 10px;
     494            }
     495        </style>
     496
     497        <?php
     498        global $post;
     499        extract ( $args );
     500
     501        $title         = apply_filters('widget_title', $instance['title'] );
     502        $results       = "";
     503        $exclude_posts = explode( ',', $instance['exclude_posts'] );
     504
     505        echo $before_widget;
     506
     507        // Print the title
     508        if ( $title ) {
     509            echo $before_title . $title . $after_title;
     510        }
     511
     512        // Get all categories
     513        $categories = get_categories();
     514
     515        // Get all post types
     516        $all_post_types         = array();
     517        $all_post_types         = get_post_types( array( '_builtin' => false ), 'names' );
     518        $all_post_types['post'] = 'post';
     519
     520        // Filter which post types are displayed
     521        $post_types = array();
     522        foreach ( $all_post_types as $key => $value ) {
     523            if ( $instance['type_'.$key] ) {
     524                array_push($post_types, $key);
     525            }
     526        }
     527        // Filter results by category
     528        $cat_list = array();
     529        foreach ( $categories as $key => $value ) {
     530            if ( $instance['category_'.$value->slug] ) {
     531                array_push($cat_list, $value->cat_ID);
     532            }
     533        }
     534        $category = implode(',', $cat_list);
     535
     536        // Get all posts
     537        $meta_key = 'jetpack-post-views';
     538        if ( $instance['days'] != $this->interval['Unlimited'] ) {
     539            $key       = array_search( $instance['days'], $this->interval );
     540            $meta_key .= '-'.$key;
     541        }
     542        $args = array(
     543            'numberposts' => $instance['num_posts'],
     544            'orderby'     => 'meta_value_num',
     545            'order'       => 'DESC',
     546            'exclude'     => $instance['exclude_posts'],
     547            'meta_key'    => $meta_key,
     548            'post_type'   => $post_types,
     549            'category'    => $category
     550        );
     551        $posts = get_posts( $args );
     552
     553        // Print top posts in order
     554        $results = "<ul>";
     555        foreach( $posts as $post ) {
     556            $title     = get_the_title( $post->ID );
     557            $thumbnail = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'post-thumbnail' );
     558            $views     = number_format_i18n( get_post_meta( $post->ID, $meta_key, true ) ).__( ' views', 'jetpack-post-views' );
     559
     560            $results .= '<li class="JPV_list"><a href="'.get_permalink( $post->ID ).'" title="'.$title.'" class="JPV_'.$instance["display_type"].'">';
     561            switch ( $instance["display_type"] ) {
     562                case "thumbnail":
     563                    $results .= '<img src="'.$thumbnail[0].'" class="JPV_thumbnail_img"/></a>';
     564                    if ( $instance["show_views"] )
     565                        $results .= '<div class="JPV_text">'.$views.'</div>';
     566                    break;
     567                case "thumbnail_title":
     568                    $results .= '<img src="'.$thumbnail[0].'" class="JPV_thumbnail_img"/></a><div class="JPV_text"><a href="'.get_permalink( $post->ID ).'" title="'.$title.'">'.$title.'</a>';
     569                    if ( $instance["show_views"] )
     570                        $results .= " - ".$views.'</div>';
     571                    break;
     572                default:
     573                    $results .= $title.'</a>';
     574                    if ( $instance["show_views"] )
     575                        $results .= " - ".$views;
     576            }
     577            $results .= '</li>';
     578        }
     579        $results .= "</ul>";
     580
     581        echo $results;
     582
     583        echo $after_widget;
     584    }
     585
     586    /* UPDATE WIDGET OPTIONS */
     587    function update( $new_instance, $old_instance ) {
     588        $instance = $old_instance;
     589
     590        // Check nonce
     591        check_admin_referer('jetpack-post-views-widget-form-submission');
     592
     593        $instance['title'] = strip_tags( $new_instance['title'] );
     594        $instance['show_views'] = strip_tags( $new_instance['show_views'] );
     595        $instance['days'] = strip_tags( $new_instance['days'] );
     596        $instance['exclude_custom_types'] = strip_tags( $new_instance['exclude_custom_types'] );
     597        $instance['exclude_posts'] = strip_tags( $new_instance['exclude_posts'] );
     598        $instance['display_type'] = strip_tags( $new_instance['display_type'] );
     599        $instance['display_post_types'] = strip_tags( $new_instance['display_post_types'] );
     600
     601        // Get all post types
     602        $post_types = get_post_types( array( '_builtin' => false ), 'names' );
     603        $post_types['post'] = 'post';
     604        foreach ( $post_types as $key => $value ) {
     605            if ( $value != 'safecss' ) {
     606                $instance['type_'.$key] = strip_tags( $new_instance['type_'.$key] );
     607            }
     608        }
     609
     610        // Get all categories
     611        $categories = get_categories();
     612        foreach ( $categories as $key => $value ) {
     613            $instance['category_'.$value->slug] = strip_tags( $new_instance['category_'.$value->slug] );
     614        }
     615
     616        // Set default number of posts to display if invalid option
     617        $num_posts = intval( strip_tags( $new_instance['num_posts'] ) );
     618        $instance['num_posts'] = ($num_posts > 0 ? $num_posts : 5);
     619
     620        return $instance;
     621    }
     622
     623    /* DISPLAY WIDGET OPTIONS */
     624    function form( $instance ) {
     625
     626        // Default widget settings
     627        $defaults = array(
     628            'title'                => __( 'Most Popular Posts', 'jetpack-post-views' ),
     629            'error'                => '',
     630            'num_posts'            => 5,
     631            'days'                 => '-1',
     632            'show_views'           => false,
     633            'display_type'         => 'title',
     634            'exclude_posts'        => '',
     635            'display_post_types'   => ''
     636        );
     637
     638        // Get all post types
     639        $post_types = get_post_types( array( '_builtin' => false ), 'names' );
     640        $post_types['post'] = 'post';
     641        foreach ( $post_types as $key => $value ) {
     642            if ( $value != 'safecss' ) { // I have no idea what this is but it's not a valid post type
     643                $defaults['type_'.$key] = 'on';
     644            }
     645        }
     646
     647        // Get all categories
     648        $categories = get_categories();
     649        foreach ( $categories as $key => $value ) {
     650            $defaults['category_'.$value->slug] = 'on';
     651        }
     652
     653        $instance = wp_parse_args( (array) $instance, $defaults );
     654
     655        // Set nonce
     656        if ( function_exists('wp_nonce_field') ) {
     657            wp_nonce_field( 'jetpack-post-views-widget-form-submission' );
     658            echo "\n<!-- end of wp_nonce_field -->\n";
     659        }
     660
     661        ?>
     662
     663        <style>
     664            #JPV-display-content h3 {
     665                margin-top: 0;
     666            }
     667        </style>
     668
     669        <div id="JPV-display-content" class="JPV-tab-content active">
     670            <h3>Display</h3>
     671
     672            <p>
     673                <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'jetpack-post-views'); ?></label>
     674                <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" type="text" />
     675            </p>
     676
     677            <p>
     678                <label for="<?php echo $this->get_field_id( 'num_posts' ); ?>"><?php _e('Number of posts to show:', 'jetpack-post-views'); ?></label>
     679                <input id="<?php echo $this->get_field_id( 'num_posts' ); ?>" name="<?php echo $this->get_field_name( 'num_posts' ); ?>" value="<?php echo $instance['num_posts']; ?>" type="text" size="3" />
     680            </p>
     681
     682            <p>
     683                <label for="<?php echo $this->get_field_id( 'days' ); ?>"><?php _e('Time interval:', 'jetpack-post-views'); ?></label>
     684                <select id="<?php echo $this->get_field_id( 'days' ); ?>" name="<?php echo $this->get_field_name( 'days' ); ?>">
     685                    <option value="<?php echo $this->interval['Unlimited'] ?>" <?php echo ($instance['days'] == $this->interval['Unlimited'] ? 'selected' : '') ?> ><?php _e('Unlimited', 'jetpack-post-views'); ?></option>
     686                    <option value="<?php echo $this->interval['Day'] ?>"       <?php echo ($instance['days'] == $this->interval['Day']       ? 'selected' : '') ?> ><?php _e('Day',       'jetpack-post-views'); ?></option>
     687                    <option value="<?php echo $this->interval['Week'] ?>"      <?php echo ($instance['days'] == $this->interval['Week']      ? 'selected' : '') ?> ><?php _e('Week',      'jetpack-post-views'); ?></option>
     688                    <option value="<?php echo $this->interval['Month'] ?>"     <?php echo ($instance['days'] == $this->interval['Month']     ? 'selected' : '') ?> ><?php _e('Month',     'jetpack-post-views'); ?></option>
     689                    <option value="<?php echo $this->interval['Year'] ?>"      <?php echo ($instance['days'] == $this->interval['Year']      ? 'selected' : '') ?> ><?php _e('Year',      'jetpack-post-views'); ?></option>
     690                </select>
     691            </p>
     692
     693            <p>
     694                <input class="checkbox" type="checkbox" <?php checked( $instance['show_views'], 'on' ); ?> id="<?php echo $this->get_field_id( 'show_views' ); ?>" name="<?php echo $this->get_field_name( 'show_views' ); ?>" />
     695                <label for="<?php echo $this->get_field_id( 'show_views' ); ?>"><?php _e('Display number of views?', 'jetpack-post-views'); ?></label>
     696            </p>
     697
     698            <p>
     699                <label for="<?php echo $this->get_field_id( 'display_type' ); ?>"><?php _e('Display as:', 'jetpack-post-views'); ?></label>
     700                <select id="<?php echo $this->get_field_id( 'display_type' ); ?>" name="<?php echo $this->get_field_name( 'display_type' ); ?>">
     701                    <option value="title"           <?php echo ($instance['display_type'] == 'title'           ? 'selected' : '') ?> ><?php _e('Title',             'jetpack-post-views'); ?></option>
     702                    <option value="thumbnail"       <?php echo ($instance['display_type'] == 'thumbnail'       ? 'selected' : '') ?> ><?php _e('Thumbnail',         'jetpack-post-views'); ?></option>
     703                    <option value="thumbnail_title" <?php echo ($instance['display_type'] == 'thumbnail_title' ? 'selected' : '') ?> ><?php _e('Thumbnail + Title', 'jetpack-post-views'); ?></option>
     704                </select>
     705            </p>
     706        </div>
     707
     708        <div id="JPV-filter-content" class="JPV-tab-content">
     709            <h3>Filter</h3>
     710
     711            <p>
     712                <label for="<?php echo $this->get_field_id( 'exclude_posts' ); ?>"><?php _e('Exclude Posts:', 'jetpack-post-views'); ?></label>
     713                <input class="widefat" id="<?php echo $this->get_field_id( 'exclude_posts' ); ?>" name="<?php echo $this->get_field_name( 'exclude_posts' ); ?>" value="<?php echo $instance['exclude_posts']; ?>" type="text" placeholder="<?php _e('Comma-separated list of post IDs', 'jetpack-post-views'); ?>" />
     714            </p>
     715
     716            <p>
     717                <?php _e('Display only from selected post types:', 'jetpack-post-views'); ?>
     718                <br>
     719                <?php
     720                    foreach ( $post_types as $key => $value ) {
     721                        if ( $value != 'safecss' ) {
     722                ?>
     723                            <input class="checkbox" type="checkbox" <?php checked( $instance['type_'.$key], 'on' ); ?> id="<?php echo $this->get_field_id( 'type_'.$key ); ?>" name="<?php echo $this->get_field_name( 'type_'.$key ); ?>" />
     724                            <label for="<?php echo $this->get_field_id( 'type_'.$key ); ?>"><?php echo $key ?></label>
     725                            <br/>
     726                <?php
     727                        }
     728                    }
     729                ?>
     730
     731            </p>
     732
     733            <p>
     734                <?php _e('Display only from selected categories:', 'jetpack-post-views'); ?>
     735                <br>
     736                <?php
     737                    foreach ( $categories as $key => $value ) {
     738                ?>
     739                        <input class="checkbox" type="checkbox" <?php checked( $instance['category_'.$value->slug], 'on' ); ?> id="<?php echo $this->get_field_id( 'category_'.$value->slug ); ?>" name="<?php echo $this->get_field_name( 'category_'.$value->slug ); ?>" />
     740                        <label for="<?php echo $this->get_field_id( 'category_'.$value->slug ); ?>"><?php echo $value->name ?></label>
     741                        <br/>
     742                <?php
     743                    }
     744                ?>
     745
     746            </p>
     747        </div>
     748
     749    <?php
     750    }
     751
     752    /*
     753    * SCHEDULED UPDATE
     754    * Update all posts 'jetpack-post-views' post meta
     755    */
     756    function get_post_views() {
     757        $post_stats = array();
     758        $postdata   = array();
     759
     760        // Hack to break cache suggested by Glisse.
     761        // Since 'limit' is capped at 500, use it to break cache for each interval.
     762        // http://wordpress.org/support/topic/post-views-not-updating
     763        $random = rand( 500, 99999 );
     764
     765        // Get stats using the stats_get_csv function
     766        if ( function_exists('stats_get_csv') && $this->settings['use_stats_get_csv'] ) {
     767
     768            // Get post views for each interval: Unlimited, Day, Week, Month, Year
     769            foreach ($this->interval as $key => $value) {
     770                $args = array(
     771                    'days'      => $value,
     772                    'limit'     => $random,
     773                    'summarize' => 1
     774                );
     775                $post_stats[$key] = stats_get_csv( 'postviews', $args );
     776            }
     777
     778            $this->updateMessages[-2] = "Stats being updated using the stats_get_csv function";
     779        }
     780        // Get the stats using the blog_uri or blog_id
     781        else {
     782            $args            = $this->apiArgs;
     783            $args['api_key'] = $this->settings['api_key'];
     784            $args['limit']   = $random;
     785
     786            // Get the stats using the blog_uri
     787            if ( $this->settings['connect_blog_uri'] && $this->settings['use_blog_uri'] ) {
     788                $args['blog_uri'] = $this->settings['blog_uri'];
     789                $this->updateMessages[-2] = "Stats being updated using blog_uri";
     790            }
     791            // Get the stats using the blog_id
     792            else if ( $this->settings['connect_blog_id'] ) {
     793                $args['blog_id'] = $this->settings['blog_id'];
     794                $this->updateMessages[-2] = "Stats being updated using blog_id";
     795            }
     796            else {
     797                return;
     798            }
     799
     800            // Get post views for each interval: Unlimited, Day, Week, Month, Year
     801            foreach ($this->interval as $key => $value) {
     802                $args['days']     = $value;
     803                $url              = add_query_arg( $args, $this->apiUrl );
     804                $json             = wp_remote_get( $url );
     805                $data             = json_decode( $json['body'], true );
     806                $post_stats[$key] = $data[0]['postviews'];
     807            }
     808        }
     809
     810        $this->updateMessages[-1] = $post_stats;
     811        global $post;
     812
     813        // Create an array indexed by interval and then post_id
     814        foreach ( $post_stats as $key => $value ) {
     815            $postdata[$key] = array();
     816            foreach ( $value as $postinfo ) {
     817                $postdata[$key][$postinfo['post_id']] = strip_tags( $postinfo['views'] );
     818            }
     819        }
     820
     821        // Get all posts and update them
     822        $post_types         = get_post_types( array( '_builtin' => false ), 'names' );
     823        $post_types['post'] = 'post';
     824
     825        $args = array(
     826            'numberposts' => -1,
     827            'post_type'   => $post_types,
     828            'post_status' => 'publish'
     829        );
     830        $allposts = get_posts( $args );
     831        foreach( $allposts as $post) {
     832
     833            // Ensure that the $post-ID exists as a key in the array before trying to update post information.
     834            // This prevents the user from pulling data from another website and trying to add it to their own
     835            // posts.
     836            if ( array_key_exists( $post->ID, $postdata['Unlimited'] ) ) {
     837                $message = "'".get_the_title( $post->ID )."' updated with stats:";
     838
     839                // Cannot save the interval data as an array in a meta key because WP cannot sort post queries by an array.
     840                // Have to store each interval data in it's own meta key.
     841                // http://wordpress.stackexchange.com/questions/99149/wp-query-meta-query-by-array-key
     842                foreach ( $this->interval as $key => $value ) {
     843                    $newViews = intval( $postdata[$key][ $post->ID ] );
     844
     845                    // Unlimited meta key different as to not break sites that used this previously
     846                    if ( $key == 'Unlimited' ) {
     847                        $oldViews = get_post_meta( $post->ID, 'jetpack-post-views', true );
     848
     849                        // Only update posts with new stats. Prevents posts from being updated with '0' views when the API service is down.
     850                        if ( $newViews < $oldViews ) {
     851                            $newViews = $oldViews;
     852                        }
     853
     854                        update_post_meta( $post->ID, 'jetpack-post-views', $newViews );
     855                    }
     856                    else {
     857                        // Always update non-unlimited intervals since they can fluctuate
     858                        update_post_meta( $post->ID, 'jetpack-post-views-'.$key, $newViews );
     859                    }
     860
     861                    $message .= " $key($newViews)";
     862                }
     863
     864                $this->updateMessages[ $post->ID ] = $message;
     865            }
     866            else {
     867                $this->updateMessages[ $post->ID ] = "'".get_the_title( $post->ID )."' failed to update because post->ID is not in postdata.";
     868            }
     869        }
     870    }
     871
     872    /* UPGRADE PLUGIN TO NEW VERSION */
     873    function upgrade() {
     874        global $post;
     875
     876        // Delete old options
     877        delete_option( 'jetpack-post-views_version' );
     878        delete_option( 'jetpack_post_views_wp_api_key' );
     879        delete_option( 'jetpack_post_views_stats_has_run' );
     880
     881        // Add post meta for each post
     882        $this->get_post_views();
     883
     884        define( 'JETPACK_POST_VIEWS_VERSION_NUM', '1.0.9' );
     885    }
     886
     887    // PHP4 compatibility
     888    function Jetpack_Post_Views() {
     889        $this->__construct();
     890    }
    906891}
    907 
    908892
    909893// Register the widget
     
    915899/* SET SCHEDULED EVENT */
    916900function jetpack_post_views_on_activation() {
    917     wp_schedule_event( time() + 3600, 'hourly', 'jetpack_post_views_scheduled_update' );
    918     global $Jetpack_Post_Views;
    919     $Jetpack_Post_Views = new Jetpack_Post_Views();
    920     $Jetpack_Post_Views->get_post_views();
    921 
    922     // Upgrade the plugin if necessary
    923     if ( JETPACK_POST_VIEWS_VERSION_NUM != '1.0.8' ) {
    924         $Jetpack_Post_Views->upgrade();
    925     }
     901    wp_schedule_event( time() + 3600, 'hourly', 'jetpack_post_views_scheduled_update' );
     902    global $Jetpack_Post_Views;
     903    $Jetpack_Post_Views = new Jetpack_Post_Views();
     904    $Jetpack_Post_Views->get_post_views();
     905
     906    // Upgrade the plugin if necessary
     907    if ( JETPACK_POST_VIEWS_VERSION_NUM != '1.0.9' ) {
     908        $Jetpack_Post_Views->upgrade();
     909    }
    926910}
    927911
    928912/* UNSET SCHEDULED EVENT */
    929913function jetpack_post_views_on_deactivation() {
    930     wp_clear_scheduled_hook( 'jetpack_post_views_scheduled_update' );
     914    wp_clear_scheduled_hook( 'jetpack_post_views_scheduled_update' );
    931915}
    932916register_activation_hook( __FILE__, 'jetpack_post_views_on_activation' );
     
    936920 * DISPLAY TOP POSTS
    937921 * Use the Jetpack stats_get_csv() function to create a list of the top posts
    938  * args: days                   - number of days of the desired time frame. '-1' means unlimited
    939  *       limit                  - number of posts to display. '-1' means unlimited. If days is -1, then limit is capped at 500
    940  *       exclude                - comma-separated list of post IDs to exclude from displaying
    941  *      excludeCustomPostTypes - flag to exclude custom post types from displaying
    942  *       displayViews           - flag to display the post views
     922 * args: days                   - number of days of the desired time frame. '-1' means unlimited
     923 *       limit                  - number of posts to display. '-1' means unlimited. If days is -1, then limit is capped at 500
     924 *       exclude                - comma-separated list of post IDs to exclude from displaying
     925 *      excludeCustomPostTypes - flag to exclude custom post types from displaying
     926 *       displayViews           - flag to display the post views
    943927 */
    944928function JPV_display_top_posts( $args = array( 'days' => '-1', 'limit' => '5', 'exclude' => '', 'excludeCustomPostTypes' => fase, 'displayViews' => false ) ) {
    945     // Ensure that the stats_get_csv() function exists and returns posts
    946     if ( function_exists('stats_get_csv') && $posts = stats_get_csv('postviews', 'days='.($args['days'] ? $args['days'] : '-1').'&limit=-1' ) ) {
    947         $count = 0;
    948         $exclude_posts = explode( ',', $args['exclude'] );
    949 
    950         // Print top posts in order
    951         echo "<ul class='JVP-top-posts'>";
    952         foreach( $posts as $post ) {
    953 
    954             // Stop printing posts if we reach the limit
    955             if ( $args['limit'] && $count >= intval( $args['limit'] ) ) {
    956                 break;
    957             }
    958 
    959             // Only display posts
    960             $post_types = array();
    961             if ( !$args['excludeCustomPostTypes'] ) {
    962                 $post_types = get_post_types( array( '_builtin' => false ), 'names' );
    963             }
    964             $post_types['post'] = 'post';
    965 
    966             if ( $post['post_id'] && get_post( $post['post_id'] ) && in_array( get_post_type( $post['post_id'] ), $post_types ) && !in_array( $post['post_id'], $exclude_posts) ) { ?>
    967                 <li><a href="<?php echo get_permalink( $post['post_id'] ) ?>"><?php echo get_the_title( $post['post_id'] ) ?></a>
    968                     <?php if ( $args['displayViews'] ) {
    969                         echo " - ".number_format_i18n( $post['views'] ? $post['views'] : 0 ).__( ' views', 'jetpack-post-views' );
    970                     } ?>
    971                 </li>
    972             <?php
    973                 $count++;
    974             }
    975         }
    976         echo "</ul>";
    977     }
     929    // Ensure that the stats_get_csv() function exists and returns posts
     930    if ( function_exists('stats_get_csv') && $posts = stats_get_csv('postviews', 'days='.($args['days'] ? $args['days'] : '-1').'&limit=-1' ) ) {
     931        $count = 0;
     932        $exclude_posts = explode( ',', $args['exclude'] );
     933
     934        // Print top posts in order
     935        echo "<ul class='JVP-top-posts'>";
     936        foreach( $posts as $post ) {
     937
     938            // Stop printing posts if we reach the limit
     939            if ( $args['limit'] && $count >= intval( $args['limit'] ) ) {
     940                break;
     941            }
     942
     943            // Only display posts
     944            $post_types = array();
     945            if ( !$args['excludeCustomPostTypes'] ) {
     946                $post_types = get_post_types( array( '_builtin' => false ), 'names' );
     947            }
     948            $post_types['post'] = 'post';
     949
     950            if ( $post['post_id'] && get_post( $post['post_id'] ) && in_array( get_post_type( $post['post_id'] ), $post_types ) && !in_array( $post['post_id'], $exclude_posts) ) { ?>
     951                <li><a href="<?php echo get_permalink( $post['post_id'] ) ?>"><?php echo get_the_title( $post['post_id'] ) ?></a>
     952                    <?php if ( $args['displayViews'] ) {
     953                        echo " - ".number_format_i18n( $post['views'] ? $post['views'] : 0 ).__( ' views', 'jetpack-post-views' );
     954                    } ?>
     955                </li>
     956            <?php
     957                $count++;
     958            }
     959        }
     960        echo "</ul>";
     961    }
    978962}
    979963
     
    981965 * SHORTCODE
    982966 * Use the Jetpack stats_get_csv() function to create a list of the top posts
    983  * atts: days                   - number of days of the desired time frame. '-1' means unlimited
    984  *       limit                  - number of posts to display. '-1' means unlimited. If days is -1, then limit is capped at 500
    985  *       exclude                - comma-separated list of post IDs to exclude from displaying
    986  *      excludeCustomPostTypes - flag to exclude custom post types from displaying
    987  *       displayviews           - flag to display the post views
     967 * atts: days                   - number of days of the desired time frame. '-1' means unlimited
     968 *       limit                  - number of posts to display. '-1' means unlimited. If days is -1, then limit is capped at 500
     969 *       exclude                - comma-separated list of post IDs to exclude from displaying
     970 *      excludeCustomPostTypes - flag to exclude custom post types from displaying
     971 *       displayviews           - flag to display the post views
    988972 */
    989973add_shortcode( 'jpv', 'JPV_shortcode' );
    990974function JPV_shortcode( $atts ) {
    991     extract( shortcode_atts( array(
    992         'days' => '-1',
    993         'limit' => '5',
    994         'exclude' => '',
    995         'excludeCustomPostTypes' => false,
    996         'displayviews' => false,
    997     ), $atts ) );
    998 
    999     JPV_display_top_posts( $args = array( 'days' => $days, 'limit' => $limit, 'exclude' => $exclude, 'excludeCustomPostTypes' => $excludeCustomPostTypes, 'displayViews' => $displayviews ) );
     975    extract( shortcode_atts( array(
     976        'days' => '-1',
     977        'limit' => '5',
     978        'exclude' => '',
     979        'excludeCustomPostTypes' => false,
     980        'displayviews' => false,
     981    ), $atts ) );
     982
     983    JPV_display_top_posts( $args = array( 'days' => $days, 'limit' => $limit, 'exclude' => $exclude, 'excludeCustomPostTypes' => $excludeCustomPostTypes, 'displayViews' => $displayviews ) );
    1000984}
  • jetpack-post-views/trunk/readme.txt

    r782585 r817148  
    11=== Jetpack Post Views ===
    2 Contributors: straker503, topher1kenobe
     2Contributors: straker503
    33Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CPUDV9EYETJYJ
    44Tags: jetpack, post views
    55Requires at least: 3.5
    6 Tested up to: 3.6.1
    7 Stable tag: 1.0.8
     6Tested up to: 3.7.1
     7Stable tag: 1.0.9
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    1818
    1919Jetpack Post Views gives you access to this information. This plugin adds a widget that lets you display your top posts by views according to Jetpack stats. As an added bonus, this plugin adds this information to the post meta of each post, allowing you to display those stats anywhere on your site.
    20 
     20a
    2121== Installation ==
    2222
     
    3232
    3333`<?php echo get_post_meta( $post->ID, 'jetpack-post-views', true ); ?>`
     34
     35To display views for a day, week, month, or year, add the appropriate code:
     36
     37`<?php echo get_post_meta( $post->ID, 'jetpack-post-views-Day', true ); ?>`
     38`<?php echo get_post_meta( $post->ID, 'jetpack-post-views-Week', true ); ?>`
     39`<?php echo get_post_meta( $post->ID, 'jetpack-post-views-Month', true ); ?>`
     40`<?php echo get_post_meta( $post->ID, 'jetpack-post-views-Year', true ); ?>`
    3441
    3542Stats are updated hourly only if the plugin is active.
     
    95102== Changelog ==
    96103
     104= 1.0.9 (2013-12-8) =
     105* Filters for post type and category now work for all Time Intervals
     106* Fixed the Total View column error in the "All Posts" page for posts that were not published
     107* Added an option in the Settings page to display Total Views in the "All Posts" page (defaults to off)
     108* Added post meta for each time interval (Day, Week, Month, Year)
     109* Widgets set to display Popular Posts with Time Interval: Day should no longer disappear when stats reset (although post output will likely be random)
     110* Can now disable the use of the Jetpack get_stats_csv function to get popular posts using either Blog URI or Blog ID id desired
     111
    97112= 1.0.8 (2013-10-4) =
    98113* Removed cached widget output as it was causing too many problems
     
    103118* Cached the widget output
    104119* Allowed custom post types to update and display
    105 * Added filters for post type and category to widget output (feature only works for Time Inverval of Unlimited)
     120* Added filters for post type and category to widget output (feature only works for Time Interval of Unlimited)
    106121
    107122= 1.0.6 (2013-05-29) =
  • jetpack-post-views/trunk/uninstall.php

    r666100 r817148  
    1212// Undefine plugin version
    1313
     14
    1415// Delete post meta from each post
    15 $args = array( 'numberposts' => -1, 'post_type' => 'post', 'post_status' => 'publish');
     16$post_types         = get_post_types( array( '_builtin' => false ), 'names' );
     17$post_types['post'] = 'post';
     18
     19$args = array(
     20    'numberposts' => -1,
     21    'post_type'   => $post_types,
     22    'post_status' => 'publish'
     23);
    1624$allposts = get_posts( $args );
    1725foreach( $allposts as $post) {
    18     delete_post_meta( $post->ID, 'jetpack-post-views' );
     26    foreach ( $this->interval as $key => $value ) {
     27        if ( $key == 'Unlimited' ) {
     28            delete_post_meta( $post->ID, 'jetpack-post-views' );
     29        }
     30        else {
     31            delete_post_meta( $post->ID, 'jetpack-post-views-'.$key );
     32        }
     33    }
    1934}
Note: See TracChangeset for help on using the changeset viewer.