Changeset 675057
- Timestamp:
- 03/01/2013 04:58:18 PM (12 years ago)
- Location:
- site-sensor/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
site-sensor/trunk/readme.txt
r669328 r675057 4 4 Requires at least: 3.4.2 5 5 Tested up to: 3.5.1 6 Stable tag: 0.5. 26 Stable tag: 0.5.3 7 7 8 8 Site Sensor is a website uptime monitoring service with WordPress specific checks. … … 21 21 * WordPress Privacy setting warning check. 22 22 * Debug output mode for troubleshooting sitemap and RSS warnings. 23 * Support for RSS feeds hosted by FeedBlitz. 23 24 24 25 == Installation == … … 63 64 * Added debug output mode detailed instrumentaiton for detecting causes of WordPress check warnings. 64 65 66 = 0.5.3 = 67 68 * Added support for FeedBlizt and legacy FeedBurner feeds. 69 65 70 == Support == 66 71 -
site-sensor/trunk/synthesis-site-sensor.php
r669328 r675057 2 2 3 3 /* 4 Plugin Name: Synthesis Site Sensor5 Plugin URI: http://websynthesis.com/site-sensor/6 Description: WordPress worker plugin for the Synthesis Site Sensor service7 Version: 0.5.2 8 Author: Copyblogger Media9 Author URI: http://www.copyblogger.com10 */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 */ 11 11 12 12 class Synthesis_Site_Sensor { 13 13 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 → 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 } 54 393 55 394 } 56 395 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-off97 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 URLs124 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.xml153 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_Error174 */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 page204 $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 number219 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 sitemap229 $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 sitemap247 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-off274 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 → Privacy.' );281 }282 283 public static function check_wordpress_version() {284 // Return true if this check is turned-off285 if ( !get_option( self::SENSE_WP_VERSION_OPTION, true ) ) {286 return true;287 }288 289 // Include admin to gain access to required update functions290 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 checked294 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_Error313 // This pulls out the error message314 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 view357 $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 <?php377 }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 403 396 Synthesis_Site_Sensor::start();
Note: See TracChangeset
for help on using the changeset viewer.