Plugin Directory

Changeset 675057


Ignore:
Timestamp:
03/01/2013 04:58:18 PM (12 years ago)
Author:
derickschaefer
Message:

Adding support for FeedBlitz

Location:
site-sensor/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • site-sensor/trunk/readme.txt

    r669328 r675057  
    44Requires at least: 3.4.2
    55Tested up to: 3.5.1
    6 Stable tag: 0.5.2
     6Stable tag: 0.5.3
    77
    88Site Sensor is a website uptime monitoring service with WordPress specific checks.
     
    2121* WordPress Privacy setting warning check.
    2222* Debug output mode for troubleshooting sitemap and RSS warnings.
     23* Support for RSS feeds hosted by FeedBlitz.
    2324
    2425== Installation ==
     
    6364* Added debug output mode detailed instrumentaiton for detecting causes of WordPress check warnings.
    6465
     66= 0.5.3 =
     67
     68* Added support for FeedBlizt and legacy FeedBurner feeds.
     69
    6570== Support ==
    6671
  • site-sensor/trunk/synthesis-site-sensor.php

    r669328 r675057  
    22
    33/*
    4 Plugin Name: Synthesis Site Sensor
    5 Plugin URI: http://websynthesis.com/site-sensor/
    6 Description: WordPress worker plugin for the Synthesis Site Sensor service
    7 Version: 0.5.2
    8 Author: Copyblogger Media
    9 Author URI: http://www.copyblogger.com
    10 */
     4 Plugin Name: Synthesis Site Sensor
     5 Plugin URI: http://websynthesis.com/site-sensor/
     6 Description: WordPress worker plugin for the Synthesis Site Sensor service
     7 Version: 0.5.3
     8 Author: Copyblogger Media
     9 Author URI: http://www.copyblogger.com
     10 */
    1111
    1212class Synthesis_Site_Sensor {
    1313
    14 const WP_VERSION = 'wordpress_version';
    15 const WP_PRIVACY = 'wordpress_privacy';
    16 const WP_RSS_FEED = 'wordpress_rss_feed';
    17 const WP_XML_SITEMAP = 'wordpress_xml_sitemap';
    18 const SS_FEED_VERSION = 'site_sensor_feed_version';
    19 
    20 const SETTINGS_SLUG = 'synthesis-site-sensor-settings-menu';
    21 const SETTINGS_NONCE = 'synthesis-site-sensor-settings-nonce';
    22 
    23 const TRIGGER_SLUG_OPTION = 'synthesis-site-sensor-trigger-slug';
    24 
    25 const SENSE_WP_VERSION_OPTION = 'synthesis-site-sensor-wp-version';
    26 const SENSE_PRIVACY_SETTINGS_OPTION = 'synthesis-site-sensor-privacy-settings';
    27 const SENSE_RSS_FEEDS_OPTION = 'synthesis-site-sensor-rss-feeds';
    28 const SENSE_XML_SITEMAP_OPTION = 'synthesis-site-sensor-xml-sitemap';
    29 
    30 CONST VERSION = '0.5.2';
    31 CONST FEED_VERSION = '1.0';
    32 
    33 const DEBUG = false;
    34 
    35 static $plugin_name;
    36 
    37 // Trigger Variable to watch for
    38 private static $trigger;
    39 
    40 public static function start() {
    41 
    42 // @todo: load plugin text domain
    43 self::$plugin_name = __( 'Synthesis Site Sensor', 'syn-site-sensor' );
    44 
    45 add_action( 'init', array( __CLASS__, 'check_for_request' ) );
    46 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_styles' ) );
    47 add_action( 'admin_menu', array( __CLASS__, 'add_plugin_options_menu' ) );
    48 add_action( 'plugin_action_links', array( __CLASS__, 'plugin_action_links' ), 10, 2 );
    49 
    50 self::$trigger = get_option( self::TRIGGER_SLUG_OPTION, false );
    51 
    52 if ( !self::$trigger )
    53 add_action( 'admin_notices', array( __CLASS__, 'missing_plugin_settings' ) );
     14    const WP_VERSION = 'wordpress_version';
     15    const WP_PRIVACY = 'wordpress_privacy';
     16    const WP_RSS_FEED = 'wordpress_rss_feed';
     17    const WP_XML_SITEMAP = 'wordpress_xml_sitemap';
     18    const SS_FEED_VERSION = 'site_sensor_feed_version';
     19
     20    const SETTINGS_SLUG = 'synthesis-site-sensor-settings-menu';
     21    const SETTINGS_NONCE = 'synthesis-site-sensor-settings-nonce';
     22
     23    const TRIGGER_SLUG_OPTION = 'synthesis-site-sensor-trigger-slug';
     24
     25    const SENSE_WP_VERSION_OPTION = 'synthesis-site-sensor-wp-version';
     26    const SENSE_PRIVACY_SETTINGS_OPTION = 'synthesis-site-sensor-privacy-settings';
     27    const SENSE_RSS_FEEDS_OPTION = 'synthesis-site-sensor-rss-feeds';
     28    const SENSE_XML_SITEMAP_OPTION = 'synthesis-site-sensor-xml-sitemap';
     29
     30    CONST VERSION = '0.5.3';
     31    CONST FEED_VERSION = '1.0';
     32
     33    const DEBUG = false;
     34
     35    static $plugin_name;
     36
     37    // Trigger Variable to watch for
     38    private static $trigger;
     39
     40    public static function start() {
     41
     42        // @todo: load plugin text domain
     43        self::$plugin_name = __( 'Synthesis Site Sensor', 'syn-site-sensor' );
     44
     45        add_action( 'init', array( __CLASS__, 'check_for_request' ) );
     46        add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_styles' ) );
     47        add_action( 'admin_menu', array( __CLASS__, 'add_plugin_options_menu' ) );
     48        add_action( 'plugin_action_links', array( __CLASS__, 'plugin_action_links' ), 10, 2 );
     49
     50        self::$trigger = get_option( self::TRIGGER_SLUG_OPTION, false );
     51
     52        if ( !self::$trigger )
     53            add_action( 'admin_notices', array( __CLASS__, 'missing_plugin_settings' ) );
     54
     55    }
     56
     57    public static function check_for_request() {
     58
     59        if ( self::$trigger && isset( $_REQUEST[self::$trigger] ) ) {
     60            $response = array(
     61                self::SS_FEED_VERSION => self::FEED_VERSION,
     62                self::WP_VERSION      => self::get_response_message( self::check_wordpress_version() ),
     63                self::WP_PRIVACY      => self::get_response_message( self::check_privacy_settings() ),
     64                self::WP_RSS_FEED     => self::get_response_message( self::check_rss_feed() ),
     65                self::WP_XML_SITEMAP  => self::get_response_message( self::check_xml_sitemap() ),
     66            );
     67
     68            if ( isset( $_REQUEST['d'] ) ) {
     69                self::debug('<strong>Site Check Results:</strong>');
     70                foreach ( $response as $check => $message ) {
     71                    self::debug( $check . ': ' . $message);
     72                }
     73                die();
     74            } else {
     75                die( json_encode( $response ) );
     76            }
     77
     78        } else if ( isset( $_REQUEST[self::SETTINGS_NONCE] ) && wp_verify_nonce( $_REQUEST[self::SETTINGS_NONCE], 'save' ) ) {
     79
     80            if ( isset( $_REQUEST['ssc-url'] ) ) {
     81                $url = trim( $_REQUEST['ssc-url'] );
     82                if ( !empty( $url ) ) {
     83                    update_option( self::TRIGGER_SLUG_OPTION, $url );
     84                }
     85            }
     86
     87            // Update settings.
     88            update_option( self::SENSE_WP_VERSION_OPTION, isset( $_REQUEST['sense-wp-version'] ) );
     89            update_option( self::SENSE_PRIVACY_SETTINGS_OPTION, isset( $_REQUEST['sense-privacy-settings'] ) );
     90            update_option( self::SENSE_RSS_FEEDS_OPTION, isset( $_REQUEST['sense-rss-feeds'] ) );
     91            update_option( self::SENSE_XML_SITEMAP_OPTION, isset( $_REQUEST['sense-xml-sitemap'] ) );
     92        }
     93    }
     94
     95    public static function check_rss_feed() {
     96        // Return true if this check is turned-off
     97        if ( !get_option( self::SENSE_RSS_FEEDS_OPTION, true ) ) {
     98            return true;
     99        }
     100
     101        $latest_post_url = self::get_latest_post_permalink();
     102        if ( !$latest_post_url ) {
     103            return true;
     104        }
     105
     106        $feed = fetch_feed( add_query_arg( array( 'format' => 'xml' ), get_feed_link( 'rss2' ) ) );
     107        if ( is_wp_error( $feed ) ) {
     108            /** @var WP_Error $feed */
     109            return new WP_Error( 'broken-rss-feed', sprintf( __( 'Your site RSS feed has the following error. %s', 'syn-site-sensor' ), $feed->get_error_message() ) );
     110        }
     111
     112        $items = $feed->get_items();
     113        if ( !count( $items ) ) {
     114            return new WP_Error( 'empty-feed', __( 'No items were found on your RSS feed.', 'syn-site-sensor' ) );
     115        }
     116
     117        self::debug('Begin Feed Debug');
     118        self::debug('Latest Post: ' . print_r( $latest_post_url, true ));
     119
     120        foreach ( $items as $item ) {
     121            $item_permalink = $item->get_permalink();
     122            // Grab origin link from Feedburner/FeedBlitz
     123            $orig = $item->get_item_tags('http://rssnamespace.org/feedburner/ext/1.0', 'origLink');
     124            $item_origin_permalink = isset( $orig[0] ) && isset( $orig[0]['data'] ) ? $orig[0]['data'] : '';
     125
     126            self::debug( 'Feed Item: ' . $item->get_permalink() );
     127            self::debug( 'FB Orig Link: ' . $item_origin_permalink );
     128           
     129            if ( $item_permalink == $latest_post_url || $item_origin_permalink == $latest_post_url ) {
     130                return true;
     131            }
     132        }
     133
     134        return new WP_Error( 'latest-post-not-found', sprintf( 'Your latest post was not among the %d items on your RSS feed.', count( $items ) ) );
     135    }
     136
     137    public static function check_xml_sitemap() {
     138
     139        // If sitemap checks are turned off, then bail on all logic.
     140        if ( !get_option( self::SENSE_XML_SITEMAP_OPTION, true ) ) {
     141            self::debug('XML Sitemap detection is disabled');
     142            return true;
     143        }
     144
     145        // See if we're using Yoast's WordPress SEO's sitemap_index.xml
     146        if ( function_exists( 'get_wpseo_options' ) ) {
     147            self::debug( 'Yoast SEO is installed' );
     148            // WordPress SEO is enabled, check to see if sitemap indexes are on.
     149            $options = get_wpseo_options();
     150            $sitemap_index_key = 'enablexmlsitemap';
     151
     152            // Check to see if the option is set, and it's value evaluates to true.
     153            if ( !empty( $options[$sitemap_index_key] ) ) {
     154                // Check our sitemap index for the latest post.
     155                return self::check_yoast_xml_sitemap();
     156            }
     157        }
     158
     159        // Sitemap indexes are not being used. Check the default sitemap.
     160        return self::check_default_xml_sitemap();
     161    }
     162
     163    /**
     164     * Checks the normal sitemap (sitemap.xml) for the latest post.
     165     *
     166     * @return array|bool|WP_Error
     167     */
     168    public static function check_default_xml_sitemap() {
     169        self::debug( 'Begin XML Sitemap Debug');
     170
     171        $latest_post_url = self::get_latest_post_permalink();
     172        self::debug( "Latest Post URL: $latest_post_url" );
     173
     174        $sitemap_url = site_url( 'sitemap.xml' );
     175        $sitemap = self::get_xml_sitemap( $sitemap_url );
     176        self::debug( "Sitemap URL: $sitemap_url");
     177
     178        if ( is_wp_error( $sitemap ) ) {
     179            self::debug( 'Error parsing XML sitemap' );
     180            return $sitemap;
     181        }
     182
     183        foreach ( $sitemap->url as $url ) {
     184            self::debug( 'Sitemap Post URL: ' . $url->loc );
     185            if ( $url->loc == $latest_post_url ) {
     186                return true;
     187            }
     188        }
     189
     190        return new WP_Error( 'latest-post-not-found', __( 'Your latest post was not found in your XML sitemap.', 'syn-site-sensor' ) );
     191    }
     192
     193    public static function check_yoast_xml_sitemap() {
     194        self::debug( 'Begin Sitemap Debug' );
     195        self::debug( 'Checking Yoast XML sitemap' );
     196        // Determine how many posts we store per post-sitemap.xml page
     197        $options = get_wpseo_options();
     198        $sitemap_epp_index_key = 'entries-per-page';
     199        $sitemap_entries_per_page = !empty( $options[$sitemap_epp_index_key] ) ? intval( $options[$sitemap_epp_index_key] ) : 1000;
     200
     201        self::debug( "Yoast Entries Per Page: $sitemap_entries_per_page" );
     202
     203        // Find which post-sitemap{n}.xml page our latest post is on. Note: if there's only one page, {n} is blank.
     204        $post_counts = wp_count_posts();
     205        $published_posts = isset( $post_counts->publish ) ? $post_counts->publish : 0;
     206        $inherit_posts = isset( $post_counts->inherit ) ? $post_counts->inherit : 0;
     207        $post_sitemap_count = ceil( ( $published_posts + $inherit_posts ) / $sitemap_entries_per_page );
     208
     209        self::debug( "Sitemap Number: $post_sitemap_count" );
     210
     211        // If we only have one page of posts, then the sitemap doesn't have a number
     212        if ($post_sitemap_count == 1) {
     213            $post_sitemap_count = '';
     214        }
     215
     216        $sitemap_file = "post-sitemap{$post_sitemap_count}.xml";
     217        $sitemap_url = site_url( $sitemap_file );
     218
     219        self::debug( "Sitemap URL: $sitemap_url" );
     220
     221        // Fetch the latest sitemap
     222        $sitemap = self::get_xml_sitemap( $sitemap_url );
     223
     224        if ( is_wp_error( $sitemap ) ) {
     225            self::debug( 'Error parsing Yoast sitemap' );
     226            return $sitemap;
     227        }
     228
     229        $latest_post_url = self::get_latest_post_permalink();
     230        self::debug( "Latest Post URL: $latest_post_url" );
     231
     232        foreach ( $sitemap->url as $url ) {
     233            self::debug( 'Sitemap Post URL: ' . $url->loc );
     234            if ( $url->loc == $latest_post_url ) {
     235                return true;
     236            }
     237        }
     238
     239        // Return an error if we don't find the latest post in the latest sitemap
     240        return new WP_Error( 'latest-post-not-found', __( 'Your latest post was not found in your XML sitemap.', 'syn-site-sensor' ) );
     241    }
     242
     243    public static function get_xml_sitemap( $url ) {
     244        $sitemap_response = wp_remote_get( $url );
     245
     246        if ( is_wp_error( $sitemap_response ) ) {
     247            return $sitemap_response;
     248        }
     249
     250        if ( $sitemap_response['response']['code'] != 200 ) {
     251            return new WP_Error( 'error-retrieving-xml-sitemap', sprintf( 'Retrieving the XML Sitemap returned the following error: %d - %s', $sitemap_response['response']['code'], esc_html( $sitemap_response['response']['message'] ) ) );
     252        }
     253
     254        $sitemap_content = wp_remote_retrieve_body( $sitemap_response );
     255
     256        try {
     257            $sitemap = @new SimpleXMLElement( $sitemap_content );
     258        } catch ( Exception $e ) {
     259            return new WP_Error( 'error-parsing-sitemap', sprintf( 'Parsing your XML Sitemap caused the folliwing error: %s', esc_html( $e->getMessage() ) ) );
     260        }
     261
     262        return $sitemap;
     263    }
     264
     265    public static function check_privacy_settings() {
     266        // Return true if this check is turned-off
     267        if ( !get_option( self::SENSE_PRIVACY_SETTINGS_OPTION, true ) ) {
     268            return true;
     269        }
     270        if ( '1' == get_option( 'blog_public' ) )
     271            return true;
     272
     273        return new WP_Error( 'site-not-public', 'Your site is configured to block search engines. Unblock them in Settings &rarr; Privacy.' );
     274    }
     275
     276    public static function check_wordpress_version() {
     277        // Return true if this check is turned-off
     278        if ( !get_option( self::SENSE_WP_VERSION_OPTION, true ) ) {
     279            return true;
     280        }
     281
     282        // Include admin to gain access to required update functions
     283        require_once( ABSPATH . 'wp-admin/includes/admin.php' );
     284
     285        $update = get_preferred_from_update_core();
     286        // it's possible that the version has never been checked
     287        if ( $update === false ) {
     288
     289            wp_version_check();
     290            $update = get_preferred_from_update_core();
     291
     292        }
     293
     294        if ( isset( $update->response ) && $update->response == 'latest' )
     295            return true;
     296
     297        return new WP_Error( 'core-out-of-date', 'There is an update available for WordPress. Update your site to keep it secure.' );
     298    }
     299
     300    private static function get_response_message( $response ) {
     301        if ( !self::DEBUG && !isset( $_REQUEST['d'] ) ) {
     302            return is_wp_error( $response ) ? false : true;
     303        }
     304
     305        // If something goes wrong, status checks return a WP_Error
     306        // This pulls out the error message
     307        if ( is_wp_error( $response ) ) {
     308            /** @var WP_Error $response */
     309            return $response->get_error_message();
     310        } else {
     311            //return "ok";
     312            return 'true';
     313        }
     314    }
     315
     316    private static function debug( $message ) {
     317        if ( isset( $_REQUEST['d'] ) ) {
     318            echo $message . "<br />\n";
     319        }
     320    }
     321
     322    private static function get_latest_post_permalink() {
     323
     324        $latest_posts = wp_get_recent_posts( array( 'numberposts' => 1, 'post_status' => 'publish' ) );
     325        if ( empty( $latest_posts ) || !is_array( $latest_posts ) )
     326            return false;
     327
     328        $latest_post = array_shift( $latest_posts );
     329        $post_id = $latest_post['ID'];
     330        $latest_post_url = esc_url( apply_filters( 'the_permalink_rss', get_permalink( $post_id ) ) );
     331
     332        return $latest_post_url;
     333
     334    }
     335
     336    // Callback for "admin_menu"
     337    static function add_plugin_options_menu() {
     338
     339        add_options_page( self::$plugin_name, self::$plugin_name, 'manage_options', self::SETTINGS_SLUG, array( __CLASS__, 'render_settings_page' ) );
     340
     341    }
     342
     343    // Callback to render the settings page.
     344    static function render_settings_page() {
     345
     346        if ( !current_user_can( 'manage_options' ) )
     347            wp_die( __( 'You do not have sufficient permissions to access this page.', 'syn-site-sensor' ) );
     348
     349        // Inputs for the view
     350        $ssc_url = get_option( self::TRIGGER_SLUG_OPTION );
     351        $sense_wp_version = get_option( self::SENSE_WP_VERSION_OPTION, true );
     352        $sense_privacy_settings = get_option( self::SENSE_PRIVACY_SETTINGS_OPTION, true );
     353        $sense_rss_feeds = get_option( self::SENSE_RSS_FEEDS_OPTION, true );
     354        $sense_xml_sitemap = get_option( self::SENSE_XML_SITEMAP_OPTION, true );
     355        include( dirname( __FILE__ ) . '/views/manage-site-sensor.php' );
     356
     357    }
     358
     359    public static function missing_plugin_settings() {
     360
     361        $screen = get_current_screen();
     362        if ( ( !isset( $screen->base ) || 'plugins' != $screen->base ) && current_user_can( 'manage_options' ) ) {
     363            ?>
     364            <div class="error">
     365            <p>
     366                <?php printf( __( '%s has not been configured with an access option. It will not function until it is configured.', 'syn-site-sensor' ), self::$plugin_name ); ?>
     367            </p>
     368            </div>
     369        <?php
     370        }
     371
     372    }
     373
     374    public static function add_styles( $hook ) {
     375
     376        if ( $hook == 'settings_page_synthesis-site-sensor-settings-menu' )
     377            wp_enqueue_style( 'synthesis-site-sensor', plugin_dir_url( __FILE__ ) . '/css/site-sensor.css', array(), self::VERSION );
     378
     379    }
     380
     381    function plugin_action_links( $links, $file ) {
     382
     383        if ( $file != plugin_basename( __FILE__ ) )
     384            return $links;
     385
     386        $settings_link = '<a href="options-general.php?page=' . self::SETTINGS_SLUG . '">' . __( 'Settings', 'wp_mail_smtp' ) . '</a>';
     387
     388        array_unshift( $links, $settings_link );
     389
     390        return $links;
     391
     392    }
    54393
    55394}
    56395
    57 public static function check_for_request() {
    58 
    59 if ( self::$trigger && isset( $_REQUEST[self::$trigger] ) ) {
    60 $response = array(
    61 self::SS_FEED_VERSION => self::FEED_VERSION,
    62 self::WP_VERSION => self::get_response_message( self::check_wordpress_version() ),
    63 self::WP_PRIVACY => self::get_response_message( self::check_privacy_settings() ),
    64 self::WP_RSS_FEED => self::get_response_message( self::check_rss_feed() ),
    65 self::WP_XML_SITEMAP => self::get_response_message( self::check_xml_sitemap() ),
    66 );
    67 
    68 if ( isset( $_REQUEST['d'] ) ) {
    69 self::debug('<strong>Site Check Results:</strong>');
    70 foreach ( $response as $check => $message ) {
    71 self::debug( $check . ': ' . $message);
    72 }
    73 die();
    74 } else {
    75 die( json_encode( $response ) );
    76 }
    77 
    78 } else if ( isset( $_REQUEST[self::SETTINGS_NONCE] ) && wp_verify_nonce( $_REQUEST[self::SETTINGS_NONCE], 'save' ) ) {
    79 
    80 if ( isset( $_REQUEST['ssc-url'] ) ) {
    81 $url = trim( $_REQUEST['ssc-url'] );
    82 if ( !empty( $url ) ) {
    83 update_option( self::TRIGGER_SLUG_OPTION, $url );
    84 }
    85 }
    86 
    87 // Update settings.
    88 update_option( self::SENSE_WP_VERSION_OPTION, isset( $_REQUEST['sense-wp-version'] ) );
    89 update_option( self::SENSE_PRIVACY_SETTINGS_OPTION, isset( $_REQUEST['sense-privacy-settings'] ) );
    90 update_option( self::SENSE_RSS_FEEDS_OPTION, isset( $_REQUEST['sense-rss-feeds'] ) );
    91 update_option( self::SENSE_XML_SITEMAP_OPTION, isset( $_REQUEST['sense-xml-sitemap'] ) );
    92 }
    93 }
    94 
    95 public static function check_rss_feed() {
    96 // Return true if this check is turned-off
    97 if ( !get_option( self::SENSE_RSS_FEEDS_OPTION, true ) ) {
    98 return true;
    99 }
    100 
    101 $latest_post_url = self::get_latest_post_permalink();
    102 if ( !$latest_post_url ) {
    103 return true;
    104         }
    105 
    106 $feed = fetch_feed( add_query_arg( array( 'format' => 'xml' ), get_feed_link( 'rss2' ) ) );
    107 if ( is_wp_error( $feed ) ) {
    108 /** @var WP_Error $feed */
    109 return new WP_Error( 'broken-rss-feed', sprintf( __( 'Your site RSS feed has the following error. %s', 'syn-site-sensor' ), $feed->get_error_message() ) );
    110 }
    111 
    112 $items = $feed->get_items();
    113 if ( !count( $items ) ) {
    114 return new WP_Error( 'empty-feed', __( 'No items were found on your RSS feed.', 'syn-site-sensor' ) );
    115         }
    116 
    117         self::debug('Begin Feed Debug');
    118         self::debug('Latest Post: ' . print_r( $latest_post_url, true ));
    119 
    120 foreach ( $items as $item ) {
    121 $item_permalink = $item->get_permalink();
    122 // We do not support proxy links from burner services. We assume they work returning positive.
    123 // See documentation about using a separate Web check + Keyword to check burner URLs
    124 if ( strpos( $item_permalink, 'feeds.feedblitz.com' ) !== false ) {
    125 self::debug( 'Post URL at feeds.feedblitz.com: ' . $item_permalink );
    126 return true;
    127 }
    128 
    129 if ( strpos( $item_permalink, 'feedproxy.google.com' ) !== false ) {
    130 self::debug( 'Post URL at feedproxy.google.com: ' . $item_permalink );
    131 return true;
    132 }
    133 
    134 self::debug( 'Feed Item: ' . $item->get_permalink() );
    135 
    136 if ( $item_permalink == $latest_post_url ) {
    137 return true;
    138             }
    139 }
    140 
    141 return new WP_Error( 'latest-post-not-found', sprintf( 'Your latest post was not among the %d items on your RSS feed.', count( $items ) ) );
    142 }
    143 
    144 public static function check_xml_sitemap() {
    145 
    146 // If sitemap checks are turned off, then bail on all logic.
    147 if ( !get_option( self::SENSE_XML_SITEMAP_OPTION, true ) ) {
    148 self::debug('XML Sitemap detection is disabled');
    149 return true;
    150 }
    151 
    152 // See if we're using Yoast's WordPress SEO's sitemap_index.xml
    153 if ( function_exists( 'get_wpseo_options' ) ) {
    154 self::debug( 'Yoast SEO is installed' );
    155 // WordPress SEO is enabled, check to see if sitemap indexes are on.
    156 $options = get_wpseo_options();
    157 $sitemap_index_key = 'enablexmlsitemap';
    158 
    159 // Check to see if the option is set, and it's value evaluates to true.
    160 if ( !empty( $options[$sitemap_index_key] ) ) {
    161 // Check our sitemap index for the latest post.
    162 return self::check_yoast_xml_sitemap();
    163 }
    164 }
    165 
    166 // Sitemap indexes are not being used. Check the default sitemap.
    167 return self::check_default_xml_sitemap();
    168 }
    169 
    170 /**
    171 * Checks the normal sitemap (sitemap.xml) for the latest post.
    172 *
    173 * @return array|bool|WP_Error
    174 */
    175 public static function check_default_xml_sitemap() {
    176 self::debug( 'Begin XML Sitemap Debug');
    177 
    178 $latest_post_url = self::get_latest_post_permalink();
    179 self::debug( "Latest Post URL: $latest_post_url" );
    180 
    181 $sitemap_url = site_url( 'sitemap.xml' );
    182 $sitemap = self::get_xml_sitemap( $sitemap_url );
    183 self::debug( "Sitemap URL: $sitemap_url");
    184 
    185 if ( is_wp_error( $sitemap ) ) {
    186 self::debug( 'Error parsing XML sitemap' );
    187 return $sitemap;
    188 }
    189 
    190 foreach ( $sitemap->url as $url ) {
    191 self::debug( 'Sitemap Post URL: ' . $url->loc );
    192 if ( $url->loc == $latest_post_url ) {
    193 return true;
    194 }
    195 }
    196 
    197 return new WP_Error( 'latest-post-not-found', __( 'Your latest post was not found in your XML sitemap.', 'syn-site-sensor' ) );
    198 }
    199 
    200 public static function check_yoast_xml_sitemap() {
    201 self::debug( 'Begin Sitemap Debug' );
    202 self::debug( 'Checking Yoast XML sitemap' );
    203 // Determine how many posts we store per post-sitemap.xml page
    204 $options = get_wpseo_options();
    205 $sitemap_epp_index_key = 'entries-per-page';
    206 $sitemap_entries_per_page = !empty( $options[$sitemap_epp_index_key] ) ? intval( $options[$sitemap_epp_index_key] ) : 1000;
    207 
    208 self::debug( "Yoast Entries Per Page: $sitemap_entries_per_page" );
    209 
    210 // Find which post-sitemap{n}.xml page our latest post is on. Note: if there's only one page, {n} is blank.
    211 $post_counts = wp_count_posts();
    212 $published_posts = isset( $post_counts->publish ) ? $post_counts->publish : 0;
    213 $inherit_posts = isset( $post_counts->inherit ) ? $post_counts->inherit : 0;
    214 $post_sitemap_count = ceil( ( $published_posts + $inherit_posts ) / $sitemap_entries_per_page );
    215 
    216 self::debug( "Sitemap Number: $post_sitemap_count" );
    217 
    218 // If we only have one page of posts, then the sitemap doesn't have a number
    219 if ($post_sitemap_count == 1) {
    220 $post_sitemap_count = '';
    221 }
    222 
    223 $sitemap_file = "post-sitemap{$post_sitemap_count}.xml";
    224 $sitemap_url = site_url( $sitemap_file );
    225 
    226 self::debug( "Sitemap URL: $sitemap_url" );
    227 
    228 // Fetch the latest sitemap
    229 $sitemap = self::get_xml_sitemap( $sitemap_url );
    230 
    231 if ( is_wp_error( $sitemap ) ) {
    232 self::debug( 'Error parsing Yoast sitemap' );
    233 return $sitemap;
    234 }
    235 
    236 $latest_post_url = self::get_latest_post_permalink();
    237 self::debug( "Latest Post URL: $latest_post_url" );
    238 
    239 foreach ( $sitemap->url as $url ) {
    240 self::debug( 'Sitemap Post URL: ' . $url->loc );
    241 if ( $url->loc == $latest_post_url ) {
    242 return true;
    243 }
    244 }
    245 
    246 // Return an error if we don't find the latest post in the latest sitemap
    247 return new WP_Error( 'latest-post-not-found', __( 'Your latest post was not found in your XML sitemap.', 'syn-site-sensor' ) );
    248 }
    249 
    250 public static function get_xml_sitemap( $url ) {
    251 $sitemap_response = wp_remote_get( $url );
    252 
    253 if ( is_wp_error( $sitemap_response ) ) {
    254 return $sitemap_response;
    255 }
    256 
    257 if ( $sitemap_response['response']['code'] != 200 ) {
    258 return new WP_Error( 'error-retrieving-xml-sitemap', sprintf( 'Retrieving the XML Sitemap returned the following error: %d - %s', $sitemap_response['response']['code'], esc_html( $sitemap_response['response']['message'] ) ) );
    259 }
    260 
    261 $sitemap_content = wp_remote_retrieve_body( $sitemap_response );
    262 
    263 try {
    264 $sitemap = @new SimpleXMLElement( $sitemap_content );
    265 } catch ( Exception $e ) {
    266 return new WP_Error( 'error-parsing-sitemap', sprintf( 'Parsing your XML Sitemap caused the folliwing error: %s', esc_html( $e->getMessage() ) ) );
    267 }
    268 
    269 return $sitemap;
    270 }
    271 
    272 public static function check_privacy_settings() {
    273 // Return true if this check is turned-off
    274 if ( !get_option( self::SENSE_PRIVACY_SETTINGS_OPTION, true ) ) {
    275 return true;
    276 }
    277 if ( '1' == get_option( 'blog_public' ) )
    278 return true;
    279 
    280 return new WP_Error( 'site-not-public', 'Your site is configured to block search engines. Unblock them in Settings &rarr; Privacy.' );
    281 }
    282 
    283 public static function check_wordpress_version() {
    284 // Return true if this check is turned-off
    285 if ( !get_option( self::SENSE_WP_VERSION_OPTION, true ) ) {
    286 return true;
    287 }
    288 
    289 // Include admin to gain access to required update functions
    290 require_once( ABSPATH . 'wp-admin/includes/admin.php' );
    291 
    292 $update = get_preferred_from_update_core();
    293 // it's possible that the version has never been checked
    294 if ( $update === false ) {
    295 
    296 wp_version_check();
    297 $update = get_preferred_from_update_core();
    298 
    299 }
    300 
    301 if ( isset( $update->response ) && $update->response == 'latest' )
    302 return true;
    303 
    304 return new WP_Error( 'core-out-of-date', 'There is an update available for WordPress. Update your site to keep it secure.' );
    305 }
    306 
    307 private static function get_response_message( $response ) {
    308 if ( !self::DEBUG && !isset( $_REQUEST['d'] ) ) {
    309 return is_wp_error( $response ) ? false : true;
    310 }
    311 
    312 // If something goes wrong, status checks return a WP_Error
    313 // This pulls out the error message
    314 if ( is_wp_error( $response ) ) {
    315 /** @var WP_Error $response */
    316 return $response->get_error_message();
    317 } else {
    318 //return "ok";
    319 return 'true';
    320 }
    321 }
    322 
    323 private static function debug( $message ) {
    324 if ( isset( $_REQUEST['d'] ) ) {
    325 echo $message . "<br />\n";
    326 }
    327 }
    328 
    329 private static function get_latest_post_permalink() {
    330 
    331 $latest_posts = wp_get_recent_posts( array( 'numberposts' => 1, 'post_status' => 'publish' ) );
    332 if ( empty( $latest_posts ) || !is_array( $latest_posts ) )
    333 return false;
    334 
    335 $latest_post = array_shift( $latest_posts );
    336 $post_id = $latest_post['ID'];
    337 $latest_post_url = esc_url( apply_filters( 'the_permalink_rss', get_permalink( $post_id ) ) );
    338 
    339 return $latest_post_url;
    340 
    341 }
    342 
    343 // Callback for "admin_menu"
    344 static function add_plugin_options_menu() {
    345 
    346 add_options_page( self::$plugin_name, self::$plugin_name, 'manage_options', self::SETTINGS_SLUG, array( __CLASS__, 'render_settings_page' ) );
    347 
    348 }
    349 
    350 // Callback to render the settings page.
    351 static function render_settings_page() {
    352 
    353 if ( !current_user_can( 'manage_options' ) )
    354 wp_die( __( 'You do not have sufficient permissions to access this page.', 'syn-site-sensor' ) );
    355 
    356 // Inputs for the view
    357 $ssc_url = get_option( self::TRIGGER_SLUG_OPTION );
    358 $sense_wp_version = get_option( self::SENSE_WP_VERSION_OPTION, true );
    359 $sense_privacy_settings = get_option( self::SENSE_PRIVACY_SETTINGS_OPTION, true );
    360 $sense_rss_feeds = get_option( self::SENSE_RSS_FEEDS_OPTION, true );
    361 $sense_xml_sitemap = get_option( self::SENSE_XML_SITEMAP_OPTION, true );
    362 include( dirname( __FILE__ ) . '/views/manage-site-sensor.php' );
    363 
    364 }
    365 
    366 public static function missing_plugin_settings() {
    367 
    368 $screen = get_current_screen();
    369 if ( ( !isset( $screen->base ) || 'plugins' != $screen->base ) && current_user_can( 'manage_options' ) ) {
    370 ?>
    371 <div class="error">
    372 <p>
    373 <?php printf( __( '%s has not been configured with an access option. It will not function until it is configured.', 'syn-site-sensor' ), self::$plugin_name ); ?>
    374 </p>
    375 </div>
    376 <?php
    377 }
    378 
    379 }
    380 
    381 public static function add_styles( $hook ) {
    382 
    383 if ( $hook == 'settings_page_synthesis-site-sensor-settings-menu' )
    384 wp_enqueue_style( 'synthesis-site-sensor', plugin_dir_url( __FILE__ ) . '/css/site-sensor.css', array(), self::VERSION );
    385 
    386 }
    387 
    388 function plugin_action_links( $links, $file ) {
    389 
    390 if ( $file != plugin_basename( __FILE__ ) )
    391 return $links;
    392 
    393 $settings_link = '<a href="options-general.php?page=' . self::SETTINGS_SLUG . '">' . __( 'Settings', 'wp_mail_smtp' ) . '</a>';
    394 
    395 array_unshift( $links, $settings_link );
    396 
    397 return $links;
    398 
    399 }
    400 
    401 }
    402 
    403396Synthesis_Site_Sensor::start();
Note: See TracChangeset for help on using the changeset viewer.