columns.php
10 years ago
counter.php
10 years ago
cron.php
10 years ago
frontend.php
10 years ago
functions.php
10 years ago
query.php
10 years ago
settings.php
10 years ago
update.php
10 years ago
widgets.php
10 years ago
counter.php
494 lines
| 1 | <?php |
| 2 | if ( ! defined( 'ABSPATH' ) ) |
| 3 | exit; |
| 4 | |
| 5 | new Post_Views_Counter_Counter(); |
| 6 | |
| 7 | class Post_Views_Counter_Counter { |
| 8 | |
| 9 | const GROUP = 'pvc'; |
| 10 | const NAME_ALLKEYS = 'cached_key_names'; |
| 11 | const CACHE_KEY_SEPARATOR = '.'; |
| 12 | |
| 13 | private $cookie = array( |
| 14 | 'exists' => false, |
| 15 | 'visited_posts' => array(), |
| 16 | 'expiration' => 0 |
| 17 | ); |
| 18 | |
| 19 | public function __construct() { |
| 20 | // set instance |
| 21 | Post_Views_Counter()->add_instance( 'counter', $this ); |
| 22 | |
| 23 | // actions |
| 24 | add_action( 'plugins_loaded', array( &$this, 'check_cookie' ), 1 ); |
| 25 | add_action( 'wp', array( &$this, 'check_post' ) ); |
| 26 | add_action( 'deleted_post', array( &$this, 'delete_post_views' ) ); |
| 27 | add_action( 'wp_ajax_pvc-check-post', array( &$this, 'check_post_ajax' ) ); |
| 28 | add_action( 'wp_ajax_nopriv_pvc-check-post', array( &$this, 'check_post_ajax' ) ); |
| 29 | } |
| 30 | |
| 31 | /** |
| 32 | * Remove post views from database when post is deleted. |
| 33 | */ |
| 34 | public function delete_post_views( $post_id ) { |
| 35 | global $wpdb; |
| 36 | |
| 37 | $wpdb->delete( $wpdb->prefix . 'post_views', array( 'id' => $post_id ), array( '%d' ) ); |
| 38 | } |
| 39 | |
| 40 | /** |
| 41 | * Check whether user has excluded roles. |
| 42 | */ |
| 43 | public function is_user_roles_excluded( $option ) { |
| 44 | $user = wp_get_current_user(); |
| 45 | |
| 46 | if ( empty( $user ) ) |
| 47 | return false; |
| 48 | |
| 49 | $roles = (array) $user->roles; |
| 50 | |
| 51 | if ( ! empty( $roles ) ) { |
| 52 | foreach ( $roles as $role ) { |
| 53 | if ( in_array( $role, $option, true ) ) |
| 54 | return true; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | return false; |
| 59 | } |
| 60 | |
| 61 | /** |
| 62 | * Get timestamp convertion. |
| 63 | */ |
| 64 | public function get_timestamp( $type, $number, $timestamp = true ) { |
| 65 | $converter = array( |
| 66 | 'minutes' => 60, |
| 67 | 'hours' => 3600, |
| 68 | 'days' => 86400, |
| 69 | 'weeks' => 604800, |
| 70 | 'months' => 2592000, |
| 71 | 'years' => 946080000 |
| 72 | ); |
| 73 | |
| 74 | return ($timestamp ? current_time( 'timestamp', true ) : 0) + $number * $converter[$type]; |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Check whether to count visit via AJAX request. |
| 79 | */ |
| 80 | public function check_post_ajax() { |
| 81 | if ( isset( $_POST['action'], $_POST['post_id'], $_POST['pvc_nonce'], $_POST['post_type'] ) && $_POST['action'] === 'pvc-check-post' && ($post_id = (int) $_POST['post_id']) > 0 && wp_verify_nonce( $_POST['pvc_nonce'], 'pvc-check-post' ) !== false && Post_Views_Counter()->get_attribute( 'options', 'general', 'counter_mode' ) === 'js' ) { |
| 82 | // get countable post types |
| 83 | $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' ); |
| 84 | |
| 85 | // get post type |
| 86 | $post_type = get_post_type( $post_id ); |
| 87 | |
| 88 | // whether to count this post type or not |
| 89 | if ( empty( $post_types ) || empty( $post_type ) || $post_type !== $_POST['post_type'] || ! in_array( $post_type, $post_types, true ) ) |
| 90 | exit; |
| 91 | |
| 92 | // get excluded ips |
| 93 | $excluded_ips = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude_ips' ); |
| 94 | |
| 95 | // whether to count this ip or not |
| 96 | if ( ! empty( $excluded_ips ) && filter_var( preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) && in_array( $_SERVER['REMOTE_ADDR'], $excluded_ips, true ) ) |
| 97 | exit; |
| 98 | |
| 99 | // get groups to check them faster |
| 100 | $groups = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'groups' ); |
| 101 | |
| 102 | // whether to count this user |
| 103 | if ( is_user_logged_in() ) { |
| 104 | // exclude logged in users? |
| 105 | if ( in_array( 'users', $groups, true ) ) |
| 106 | exit; |
| 107 | // exclude specific roles? |
| 108 | elseif ( in_array( 'roles', $groups, true ) && $this->is_user_roles_excluded( Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'roles' ) ) ) |
| 109 | exit; |
| 110 | } |
| 111 | // exclude guests? |
| 112 | elseif ( in_array( 'guests', $groups, true ) ) |
| 113 | exit; |
| 114 | |
| 115 | // whether to count robots |
| 116 | if ( $this->is_robot() ) |
| 117 | exit; |
| 118 | |
| 119 | // cookie already existed? |
| 120 | if ( $this->cookie['exists'] ) { |
| 121 | // post already viewed but not expired? |
| 122 | if ( in_array( $post_id, array_keys( $this->cookie['visited_posts'] ), true ) && current_time( 'timestamp', true ) < $this->cookie['visited_posts'][$post_id] ) { |
| 123 | // updates cookie but do not count visit |
| 124 | $this->save_cookie( $post_id, $this->cookie, false ); |
| 125 | |
| 126 | exit; |
| 127 | } else |
| 128 | // updates cookie |
| 129 | $this->save_cookie( $post_id, $this->cookie ); |
| 130 | } else { |
| 131 | // set new cookie |
| 132 | $this->save_cookie( $post_id ); |
| 133 | } |
| 134 | |
| 135 | // count visit |
| 136 | $this->count_visit( $post_id ); |
| 137 | } |
| 138 | |
| 139 | exit; |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Check whether to count visit. |
| 144 | */ |
| 145 | public function check_post() { |
| 146 | // do not count admin entries |
| 147 | if ( is_admin() ) |
| 148 | return; |
| 149 | |
| 150 | // do we use PHP as counter? |
| 151 | if ( Post_Views_Counter()->get_attribute( 'options', 'general', 'counter_mode' ) === 'php' ) { |
| 152 | $post_types = Post_Views_Counter()->get_attribute( 'options', 'general', 'post_types_count' ); |
| 153 | |
| 154 | // whether to count this post type |
| 155 | if ( empty( $post_types ) || ! is_singular( $post_types ) ) |
| 156 | return; |
| 157 | |
| 158 | $ips = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude_ips' ); |
| 159 | |
| 160 | // whether to count this ip |
| 161 | if ( ! empty( $ips ) && filter_var( preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) && in_array( $_SERVER['REMOTE_ADDR'], $ips, true ) ) |
| 162 | return; |
| 163 | |
| 164 | // get groups to check them faster |
| 165 | $groups = Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'groups' ); |
| 166 | |
| 167 | // whether to count this user |
| 168 | if ( is_user_logged_in() ) { |
| 169 | // exclude logged in users? |
| 170 | if ( in_array( 'users', $groups, true ) ) |
| 171 | return; |
| 172 | // exclude specific roles? |
| 173 | elseif ( in_array( 'roles', $groups, true ) && $this->is_user_roles_excluded( Post_Views_Counter()->get_attribute( 'options', 'general', 'exclude', 'roles' ) ) ) |
| 174 | return; |
| 175 | } |
| 176 | // exclude guests? |
| 177 | elseif ( in_array( 'guests', $groups, true ) ) |
| 178 | return; |
| 179 | |
| 180 | // whether to count robots |
| 181 | if ( $this->is_robot() ) |
| 182 | return; |
| 183 | |
| 184 | // get post id |
| 185 | $id = get_the_ID(); |
| 186 | |
| 187 | // cookie already existed? |
| 188 | if ( $this->cookie['exists'] ) { |
| 189 | // post already viewed but not expired? |
| 190 | if ( in_array( $id, array_keys( $this->cookie['visited_posts'] ), true ) && current_time( 'timestamp', true ) < $this->cookie['visited_posts'][$id] ) { |
| 191 | // update cookie but do not count visit |
| 192 | $this->save_cookie( $id, $this->cookie, false ); |
| 193 | |
| 194 | return; |
| 195 | } else |
| 196 | // update cookie |
| 197 | $this->save_cookie( $id, $this->cookie ); |
| 198 | } else |
| 199 | // set new cookie |
| 200 | $this->save_cookie( $id ); |
| 201 | |
| 202 | // count visit |
| 203 | $this->count_visit( $id ); |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Initialize cookie session. |
| 209 | */ |
| 210 | public function check_cookie() { |
| 211 | // do not run in admin except for ajax requests |
| 212 | if ( is_admin() && ! (defined( 'DOING_AJAX' ) && DOING_AJAX) ) |
| 213 | return; |
| 214 | |
| 215 | // is cookie set? |
| 216 | if ( isset( $_COOKIE['pvc_visits'] ) && ! empty( $_COOKIE['pvc_visits'] ) ) { |
| 217 | $visited_posts = $expirations = array(); |
| 218 | |
| 219 | foreach ( $_COOKIE['pvc_visits'] as $content ) { |
| 220 | // is cookie valid? |
| 221 | if ( preg_match( '/^(([0-9]+b[0-9]+a?)+)$/', $content ) === 1 ) { |
| 222 | // get single id with expiration |
| 223 | $expiration_ids = explode( 'a', $content ); |
| 224 | |
| 225 | // check every expiration => id pair |
| 226 | foreach ( $expiration_ids as $pair ) { |
| 227 | $pair = explode( 'b', $pair ); |
| 228 | $expirations[] = (int) $pair[0]; |
| 229 | $visited_posts[(int) $pair[1]] = (int) $pair[0]; |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | $this->cookie = array( |
| 235 | 'exists' => true, |
| 236 | 'visited_posts' => $visited_posts, |
| 237 | 'expiration' => max( $expirations ) |
| 238 | ); |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | /** |
| 243 | * Save cookie function. |
| 244 | */ |
| 245 | private function save_cookie( $id, $cookie = array(), $expired = true ) { |
| 246 | $expiration = $this->get_timestamp( Post_Views_Counter()->get_attribute( 'options', 'general', 'time_between_counts', 'type' ), Post_Views_Counter()->get_attribute( 'options', 'general', 'time_between_counts', 'number' ) ); |
| 247 | |
| 248 | // is this a new cookie? |
| 249 | if ( empty( $cookie ) ) { |
| 250 | // set cookie |
| 251 | setcookie( 'pvc_visits[0]', $expiration . 'b' . $id, $expiration, COOKIEPATH, COOKIE_DOMAIN, (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ? true : false ), true ); |
| 252 | } else { |
| 253 | if ( $expired ) { |
| 254 | // add new id or chang expiration date if id already exists |
| 255 | $cookie['visited_posts'][$id] = $expiration; |
| 256 | } |
| 257 | |
| 258 | // create copy for better foreach performance |
| 259 | $visited_posts_expirations = $cookie['visited_posts']; |
| 260 | |
| 261 | // get current gmt time |
| 262 | $time = current_time( 'timestamp', true ); |
| 263 | |
| 264 | // check whether viewed id has expired - no need to keep it in cookie (less size) |
| 265 | foreach ( $visited_posts_expirations as $post_id => $post_expiration ) { |
| 266 | if ( $time > $post_expiration ) |
| 267 | unset( $cookie['visited_posts'][$post_id] ); |
| 268 | } |
| 269 | |
| 270 | // set new last expiration date if needed |
| 271 | $cookie['expiration'] = max( $cookie['visited_posts'] ); |
| 272 | |
| 273 | $cookies = $imploded = array(); |
| 274 | |
| 275 | // create pairs |
| 276 | foreach ( $cookie['visited_posts'] as $id => $exp ) { |
| 277 | $imploded[] = $exp . 'b' . $id; |
| 278 | } |
| 279 | |
| 280 | // split cookie into chunks (4000 bytes to make sure it is safe for every browser) |
| 281 | $chunks = str_split( implode( 'a', $imploded ), 4000 ); |
| 282 | |
| 283 | // more then one chunk? |
| 284 | if ( count( $chunks ) > 1 ) { |
| 285 | $last_id = ''; |
| 286 | |
| 287 | foreach ( $chunks as $chunk_id => $chunk ) { |
| 288 | // new chunk |
| 289 | $chunk_c = $last_id . $chunk; |
| 290 | |
| 291 | // is it full-length chunk? |
| 292 | if ( strlen( $chunk ) === 4000 ) { |
| 293 | // get last part |
| 294 | $last_part = strrchr( $chunk_c, 'a' ); |
| 295 | |
| 296 | // get last id |
| 297 | $last_id = substr( $last_part, 1 ); |
| 298 | |
| 299 | // add new full-lenght chunk |
| 300 | $cookies[$chunk_id] = substr( $chunk_c, 0, strlen( $chunk_c ) - strlen( $last_part ) ); |
| 301 | } else { |
| 302 | // add last chunk |
| 303 | $cookies[$chunk_id] = $chunk_c; |
| 304 | } |
| 305 | } |
| 306 | } else { |
| 307 | // only one chunk |
| 308 | $cookies[] = $chunks[0]; |
| 309 | } |
| 310 | |
| 311 | foreach ( $cookies as $key => $value ) { |
| 312 | // set cookie |
| 313 | setcookie( 'pvc_visits[' . $key . ']', $value, $cookie['expiration'], COOKIEPATH, COOKIE_DOMAIN, (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ? true : false ), true ); |
| 314 | } |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | /** |
| 319 | * Check if object cache is in use. |
| 320 | */ |
| 321 | public function using_object_cache( $using = null ) { |
| 322 | $using = wp_using_ext_object_cache( $using ); |
| 323 | |
| 324 | if ( $using ) { |
| 325 | // check if explicitly disabled by flush_interval setting/option <= 0 |
| 326 | $flush_interval_number = Post_Views_Counter()->get_attribute( 'options', 'general', 'flush_interval', 'number' ); |
| 327 | $using = ( $flush_interval_number <= 0 ) ? false : true; |
| 328 | } |
| 329 | |
| 330 | return $using; |
| 331 | } |
| 332 | |
| 333 | /** |
| 334 | * Count visit function. |
| 335 | */ |
| 336 | private function count_visit( $id ) { |
| 337 | global $wpdb; |
| 338 | |
| 339 | $cache_key_names = array(); |
| 340 | $using_object_cache = $this->using_object_cache(); |
| 341 | |
| 342 | // get day, week, month and year |
| 343 | $date = explode( '-', date( 'W-d-m-Y', current_time( 'timestamp' ) ) ); |
| 344 | |
| 345 | foreach ( array( |
| 346 | 0 => $date[3] . $date[2] . $date[1], // day like 20140324 |
| 347 | 1 => $date[3] . $date[0], // week like 201439 |
| 348 | 2 => $date[3] . $date[2], // month like 201405 |
| 349 | 3 => $date[3], // year like 2014 |
| 350 | 4 => 'total' // total views |
| 351 | ) as $type => $period ) { |
| 352 | if ( $using_object_cache ) { |
| 353 | $cache_key = $id . self::CACHE_KEY_SEPARATOR . $type . self::CACHE_KEY_SEPARATOR . $period; |
| 354 | wp_cache_add( $cache_key, 0, self::GROUP ); |
| 355 | wp_cache_incr( $cache_key, 1, self::GROUP ); |
| 356 | $cache_key_names[] = $cache_key; |
| 357 | } else { |
| 358 | // hit the db directly |
| 359 | // @TODO: investigate queueing these queries on the 'shutdown' hook instead instead of running them instantly? |
| 360 | $this->db_insert( $id, $type, $period, 1 ); |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | // update the list of cache keys to be flushed |
| 365 | if ( $using_object_cache && ! empty( $cache_key_names ) ) { |
| 366 | $this->update_cached_keys_list_if_needed( $cache_key_names ); |
| 367 | } |
| 368 | |
| 369 | do_action( 'pvc_after_count_visit', $id ); |
| 370 | |
| 371 | return true; |
| 372 | } |
| 373 | |
| 374 | /** |
| 375 | * Update the single cache key which holds a list of all the cache keys |
| 376 | * that need to be flushed to the db. |
| 377 | * |
| 378 | * The value of that special cache key is a giant string containing key names separated with the `|` character. |
| 379 | * Each such key name then consists of 3 elements: $id, $type, $period (separated by a `.` character). |
| 380 | * Examples: |
| 381 | * 62053.0.20150327|62053.1.201513|62053.2.201503|62053.3.2015|62053.4.total|62180.0.20150327|62180.1.201513|62180.2.201503|62180.3.2015|62180.4.total |
| 382 | * A single key is `62053.0.20150327` and that key's data is: $id = 62053, $type = 0, $period = 20150327 |
| 383 | * |
| 384 | * This data format proved more efficient (avoids the (un)serialization overhead completely + duplicates filtering is a string search now) |
| 385 | */ |
| 386 | private function update_cached_keys_list_if_needed( $key_names = array() ) { |
| 387 | $existing_list = wp_cache_get( self::NAME_ALLKEYS, self::GROUP ); |
| 388 | if ( ! $existing_list ) { |
| 389 | $existing_list = ''; |
| 390 | } |
| 391 | |
| 392 | $list_modified = false; |
| 393 | |
| 394 | // modify the list contents if/when needed |
| 395 | if ( empty( $existing_list ) ) { |
| 396 | // the simpler case of an empty initial list where we just |
| 397 | // transform the specified key names into a string |
| 398 | $existing_list = implode( '|', $key_names ); |
| 399 | $list_modified = true; |
| 400 | } else { |
| 401 | // search each specified key name and append it if it's not found |
| 402 | foreach ( $key_names as $key_name ) { |
| 403 | if ( false === strpos( $existing_list, $key_name ) ) { |
| 404 | $existing_list .= '|' . $key_name; |
| 405 | $list_modified = true; |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | |
| 410 | // save modified list back in cache |
| 411 | if ( $list_modified ) { |
| 412 | wp_cache_set( self::NAME_ALLKEYS, $existing_list, self::GROUP ); |
| 413 | } |
| 414 | } |
| 415 | |
| 416 | /** |
| 417 | * Flush views data stored in the persistent object cache into |
| 418 | * our custom table and clear the object cache keys when done |
| 419 | */ |
| 420 | public function flush_cache_to_db() { |
| 421 | global $wpdb; |
| 422 | |
| 423 | $key_names = wp_cache_get( self::NAME_ALLKEYS, self::GROUP ); |
| 424 | |
| 425 | if ( ! $key_names ) { |
| 426 | $key_names = array(); |
| 427 | } else { |
| 428 | // create an array out of a string that's stored in the cache |
| 429 | $key_names = explode( '|', $key_names ); |
| 430 | } |
| 431 | |
| 432 | foreach ( $key_names as $key_name ) { |
| 433 | // get values stored within the key name itself |
| 434 | list( $id, $type, $period ) = explode( self::CACHE_KEY_SEPARATOR, $key_name ); |
| 435 | // get the cached count value |
| 436 | $count = wp_cache_get( $key_name, self::GROUP ); |
| 437 | |
| 438 | // store cached value in the db |
| 439 | $this->db_insert( $id, $type, $period, $count ); |
| 440 | |
| 441 | // clear the cache key we just flushed |
| 442 | wp_cache_delete( $key_name, self::GROUP ); |
| 443 | } |
| 444 | |
| 445 | // delete the key holding the list itself after we've successfully flushed it |
| 446 | if ( ! empty( $key_names ) ) { |
| 447 | wp_cache_delete( self::NAME_ALLKEYS, self::GROUP ); |
| 448 | } |
| 449 | |
| 450 | return true; |
| 451 | } |
| 452 | |
| 453 | /* |
| 454 | * Insert or update views count. |
| 455 | */ |
| 456 | private function db_insert( $id, $type, $period, $count = 1 ) { |
| 457 | global $wpdb; |
| 458 | |
| 459 | $count = (int) $count; |
| 460 | |
| 461 | if ( ! $count ) { |
| 462 | $count = 1; |
| 463 | } |
| 464 | |
| 465 | return $wpdb->query( |
| 466 | $wpdb->prepare( " |
| 467 | INSERT INTO " . $wpdb->prefix . "post_views (id, type, period, count) |
| 468 | VALUES (%d, %d, %s, %d) |
| 469 | ON DUPLICATE KEY UPDATE count = count + %d", $id, $type, $period, $count, $count |
| 470 | ) |
| 471 | ); |
| 472 | } |
| 473 | |
| 474 | /** |
| 475 | * Check whether visitor is a bot. |
| 476 | */ |
| 477 | private function is_robot() { |
| 478 | if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) || (isset( $_SERVER['HTTP_USER_AGENT'] ) && trim( $_SERVER['HTTP_USER_AGENT'] ) === '') ) |
| 479 | return false; |
| 480 | |
| 481 | $robots = array( |
| 482 | 'bot', 'b0t', 'Acme.Spider', 'Ahoy! The Homepage Finder', 'Alkaline', 'Anthill', 'Walhello appie', 'Arachnophilia', 'Arale', 'Araneo', 'ArchitextSpider', 'Aretha', 'ARIADNE', 'arks', 'AskJeeves', 'ASpider (Associative Spider)', 'ATN Worldwide', 'AURESYS', 'BackRub', 'Bay Spider', 'Big Brother', 'Bjaaland', 'BlackWidow', 'Die Blinde Kuh', 'Bloodhound', 'BSpider', 'CACTVS Chemistry Spider', 'Calif', 'Cassandra', 'Digimarc Marcspider/CGI', 'ChristCrawler.com', 'churl', 'cIeNcIaFiCcIoN.nEt', 'CMC/0.01', 'Collective', 'Combine System', 'Web Core / Roots', 'Cusco', 'CyberSpyder Link Test', 'CydralSpider', 'Desert Realm Spider', 'DeWeb(c) Katalog/Index', 'DienstSpider', 'Digger', 'Direct Hit Grabber', 'DownLoad Express', 'DWCP (Dridus\' Web Cataloging Project)', 'e-collector', 'EbiNess', 'Emacs-w3 Search Engine', 'ananzi', 'esculapio', 'Esther', 'Evliya Celebi', 'FastCrawler', 'Felix IDE', 'Wild Ferret Web Hopper #1, #2, #3', 'FetchRover', 'fido', 'KIT-Fireball', 'Fish search', 'Fouineur', 'Freecrawl', 'FunnelWeb', 'gammaSpider, FocusedCrawler', 'gazz', 'GCreep', 'GetURL', 'Golem', 'Grapnel/0.01 Experiment', 'Griffon', 'Gromit', 'Northern Light Gulliver', 'Harvest', 'havIndex', 'HI (HTML Index) Search', 'Hometown Spider Pro', 'ht://Dig', 'HTMLgobble', 'Hyper-Decontextualizer', 'IBM_Planetwide', 'Popular Iconoclast', 'Ingrid', 'Imagelock', 'IncyWincy', 'Informant', 'Infoseek Sidewinder', 'InfoSpiders', 'Inspector Web', 'IntelliAgent', 'Iron33', 'Israeli-search', 'JavaBee', 'JCrawler', 'Jeeves', 'JumpStation', 'image.kapsi.net', 'Katipo', 'KDD-Explorer', 'Kilroy', 'LabelGrabber', 'larbin', 'legs', 'Link Validator', 'LinkScan', 'LinkWalker', 'Lockon', 'logo.gif Crawler', 'Lycos', 'Mac WWWWorm', 'Magpie', 'marvin/infoseek', 'Mattie', 'MediaFox', 'MerzScope', 'NEC-MeshExplorer', 'MindCrawler', 'mnoGoSearch search engine software', 'moget', 'MOMspider', 'Monster', 'Motor', 'Muncher', 'Muninn', 'Muscat Ferret', 'Mwd.Search', 'Internet Shinchakubin', 'NDSpider', 'Nederland.zoek', 'NetCarta WebMap Engine', 'NetMechanic', 'NetScoop', 'newscan-online', 'NHSE Web Forager', 'Nomad', 'nzexplorer', 'ObjectsSearch', 'Occam', 'HKU WWW Octopus', 'OntoSpider', 'Openfind data gatherer', 'Orb Search', 'Pack Rat', 'PageBoy', 'ParaSite', 'Patric', 'pegasus', 'The Peregrinator', 'PerlCrawler 1.0', 'Phantom', 'PhpDig', 'PiltdownMan', 'Pioneer', 'html_analyzer', 'Portal Juice Spider', 'PGP Key Agent', 'PlumtreeWebAccessor', 'Poppi', 'PortalB Spider', 'GetterroboPlus Puu', 'Raven Search', 'RBSE Spider', 'RoadHouse Crawling System', 'ComputingSite Robi/1.0', 'RoboCrawl Spider', 'RoboFox', 'Robozilla', 'RuLeS', 'Scooter', 'Sleek', 'Search.Aus-AU.COM', 'SearchProcess', 'Senrigan', 'SG-Scout', 'ShagSeeker', 'Shai\'Hulud', 'Sift', 'Site Valet', 'SiteTech-Rover', 'Skymob.com', 'SLCrawler', 'Inktomi Slurp', 'Smart Spider', 'Snooper', 'Spanner', 'Speedy Spider', 'spider_monkey', 'Spiderline Crawler', 'SpiderMan', 'SpiderView(tm)', 'Site Searcher', 'Suke', 'suntek search engine', 'Sven', 'Sygol', 'TACH Black Widow', 'Tarantula', 'tarspider', 'Templeton', 'TeomaTechnologies', 'TITAN', 'TitIn', 'TLSpider', 'UCSD Crawl', 'UdmSearch', 'URL Check', 'URL Spider Pro', 'Valkyrie', 'Verticrawl', 'Victoria', 'vision-search', 'Voyager', 'W3M2', 'WallPaper (alias crawlpaper)', 'the World Wide Web Wanderer', 'w@pSpider by wap4.com', 'WebBandit Web Spider', 'WebCatcher', 'WebCopy', 'webfetcher', 'Webinator', 'weblayers', 'WebLinker', 'WebMirror', 'The Web Moose', 'WebQuest', 'Digimarc MarcSpider', 'WebReaper', 'webs', 'Websnarf', 'WebSpider', 'WebVac', 'webwalk', 'WebWalker', 'WebWatch', 'Wget', 'whatUseek Winona', 'Wired Digital', 'Weblog Monitor', 'w3mir', 'WebStolperer', 'The Web Wombat', 'The World Wide Web Worm', 'WWWC Ver 0.2.5', 'WebZinger', 'XGET' |
| 483 | ); |
| 484 | |
| 485 | foreach ( $robots as $robot ) { |
| 486 | if ( stripos( $_SERVER['HTTP_USER_AGENT'], $robot ) !== false ) |
| 487 | return true; |
| 488 | } |
| 489 | |
| 490 | return false; |
| 491 | } |
| 492 | |
| 493 | } |
| 494 |