Changeset 450793
- Timestamp:
- 10/13/2011 09:27:39 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
wypiekacz/trunk/wypiekacz.php
r259125 r450793 5 5 Description: Checks if posts submitted for review and posted satisfies set of rules. 6 6 Author: Daniel Frużyński 7 Version: 2. 1.17 Version: 2.2 8 8 Author URI: http://www.poradnik-webmastera.com/ 9 9 Text Domain: wypiekacz 10 License: GPL2 10 11 */ 11 12 12 /* Copyright 2009-201 0Daniel Frużyński (email : daniel [A-T] poradnik-webmastera.com)13 /* Copyright 2009-2011 Daniel Frużyński (email : daniel [A-T] poradnik-webmastera.com) 13 14 14 15 This program is free software; you can redistribute it and/or modify 15 it under the terms of the GNU General Public License as published by 16 the Free Software Foundation; either version 2 of the License, or 17 (at your option) any later version. 16 it under the terms of the GNU General Public License, version 2, as 17 published by the Free Software Foundation. 18 18 19 19 This program is distributed in the hope that it will be useful, … … 28 28 29 29 30 if ( !class_exists( 'WyPiekacz' ) || ( defined( 'WP_DEBUG') && WP_DEBUG ) ) { 30 if ( !class_exists( 'WyPiekacz' ) || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) { 31 32 /*// Include compatibility file if WP version is not current (WP 3.2.x) 33 if ( version_compare( $wp_version, '3.2', '<' ) ) { 34 include( dirname( __FILE__ ) . '/compat.php' ); 35 }*/ 31 36 32 37 class WyPiekacz { … … 37 42 // Link counter - used by RX for removing links 38 43 var $link_counter = 0; 44 // Number of initial links to remove - used by RX for removing links 45 var $links_to_remove = 0; 39 46 // List of supported post types 40 47 var $post_types = array(); 48 // Flag if we are deleting orphaned posts, to avoid infinite recursion 49 var $deleting_orphaned_posts = false; 41 50 42 51 // WP versions 52 var $has_wp_28 = false; 53 var $has_wp_29 = false; 43 54 var $has_wp_30 = false; 55 56 // True if User Locker 1.2+ is active 57 var $has_user_locker = false; 44 58 45 59 // Constructor 46 60 function WyPiekacz() { 47 61 global $wp_version; 48 $this->has_wp_30 = version_compare( $wp_version, '2.999', '>' ); 62 $this->has_wp_28 = version_compare( $wp_version, '2.7.999', '>' ); 63 $this->has_wp_29 = version_compare( $wp_version, '2.8.999', '>' ); 64 $this->has_wp_30 = version_compare( $wp_version, '2.9.999', '>' ); 49 65 50 66 // Initialise plugin … … 85 101 // Default post template handling 86 102 add_action( 'submitpost_box', array( &$this, 'submitpost_box' ) ); 103 104 // Unload autosave script if needed 105 if ( get_option( 'wypiekacz_autosave_interval' ) == 0 ) { 106 add_action( 'wp_print_scripts', array( &$this, 'wp_print_scripts' ) ); 107 } 87 108 } 88 109 } … … 91 112 function init() { 92 113 load_plugin_textdomain( 'wypiekacz', false, dirname( plugin_basename( __FILE__ ) ).'/lang' ); 114 115 // Check if User Locker 1.2+ is active 116 if ( function_exists( 'user_locker_lock_user' ) ) { 117 $this->has_user_locker = true; 118 119 // Register hooks for filters and actions which depends on User Locker 120 add_action( 'user_locker_unlock_user', array( &$this, 'user_locker_unlock_user' ) ); 121 add_action( 'user_locker_enable_user', array( &$this, 'user_locker_unlock_user' ) ); 122 123 if ( is_admin() ) { 124 // Add new column to the user list 125 add_filter( 'manage_users_columns', array( &$this, 'manage_users_columns' ) ); 126 add_filter( 'manage_users_custom_column', array( &$this, 'manage_users_custom_column' ), 10, 3 ); 127 } 128 } 93 129 } 94 130 … … 123 159 register_setting( 'wypiekacz', 'wypiekacz_min_len', array( &$this, 'sanitize_nonnegative' ) ); 124 160 register_setting( 'wypiekacz', 'wypiekacz_min_len_words', array( &$this, 'sanitize_nonnegative' ) ); 161 register_setting( 'wypiekacz', 'wypiekacz_min_links', array( &$this, 'sanitize_nonnegative' ) ); 125 162 register_setting( 'wypiekacz', 'wypiekacz_max_links', array( &$this, 'sanitize_nonnegative' ) ); 163 register_setting( 'wypiekacz', 'wypiekacz_link_after', array( &$this, 'sanitize_nonnegative' ) ); 164 register_setting( 'wypiekacz', 'wypiekacz_link_after_words', array( &$this, 'sanitize_nonnegative' ) ); 126 165 register_setting( 'wypiekacz', 'wypiekacz_min_title_len', array( &$this, 'sanitize_nonnegative' ) ); 127 166 register_setting( 'wypiekacz', 'wypiekacz_min_title_len_words', array( &$this, 'sanitize_nonnegative' ) ); … … 139 178 register_setting( 'wypiekacz', 'wypiekacz_pass_reset_email', array( &$this, 'sanitize_01' ) ); 140 179 register_setting( 'wypiekacz', 'wypiekacz_right_now_stats', array( &$this, 'sanitize_01' ) ); 180 register_setting( 'wypiekacz', 'wypiekacz_post_menu_links', array( &$this, 'sanitize_01' ) ); 141 181 register_setting( 'wypiekacz', 'wypiekacz_badwords', array( &$this, 'sanitize_stringlist' ) ); 142 182 register_setting( 'wypiekacz', 'wypiekacz_check_badwords_title', array( &$this, 'sanitize_01' ) ); 143 183 register_setting( 'wypiekacz', 'wypiekacz_check_badwords_content', array( &$this, 'sanitize_01' ) ); 184 register_setting( 'wypiekacz', 'wypiekacz_check_badwords_tags', array( &$this, 'sanitize_01' ) ); 144 185 register_setting( 'wypiekacz', 'wypiekacz_goodwords', array( &$this, 'sanitize_stringlist' ) ); 186 register_setting( 'wypiekacz', 'wypiekacz_post_thumbnail', array( &$this, 'sanitize_01' ) ); 145 187 register_setting( 'wypiekacz', 'wypiekacz_enforce_links', array( &$this, 'sanitize_01' ) ); 188 register_setting( 'wypiekacz', 'wypiekacz_enforce_link_positions', array( &$this, 'sanitize_01' ) ); 146 189 register_setting( 'wypiekacz', 'wypiekacz_enforce_title', array( &$this, 'sanitize_01' ) ); 147 190 register_setting( 'wypiekacz', 'wypiekacz_enforce_add_dots', array( &$this, 'sanitize_01' ) ); … … 150 193 register_setting( 'wypiekacz', 'wypiekacz_allow_skip_rules', array( &$this, 'sanitize_01' ) ); 151 194 register_setting( 'wypiekacz', 'wypiekacz_post_types', array( &$this, 'sanitize_post_types' ) ); 195 register_setting( 'wypiekacz', 'wypiekacz_dont_save_invalid_post', array( &$this, 'sanitize_01' ) ); 196 register_setting( 'wypiekacz', 'wypiekacz_autosave_interval', array( &$this, 'sanitize_nonnegative' ) ); 197 register_setting( 'wypiekacz', 'wypiekacz_post_revisions', array( &$this, 'sanitize_nonnegative_or_minus1' ) ); 198 register_setting( 'wypiekacz', 'wypiekacz_empty_trash_days', array( &$this, 'sanitize_nonnegative' ) ); 199 register_setting( 'wypiekacz', 'wypiekacz_delete_orphaned_drafts', array( &$this, 'sanitize_nonnegative' ) ); 200 register_setting( 'wypiekacz', 'wypiekacz_force_delete_orphaned_drafts', array( &$this, 'sanitize_01' ) ); 201 202 // Do not register these options if User Locker is not active - otherwise WP would clear them when options are saved 203 if ( $this->has_user_locker ) { 204 register_setting( 'wypiekacz', 'wypiekacz_lock_account', array( &$this, 'sanitize_01' ) ); 205 register_setting( 'wypiekacz', 'wypiekacz_lock_account_after', array( &$this, 'sanitize_positive' ) ); 206 register_setting( 'wypiekacz', 'wypiekacz_lock_method', array( &$this, 'sanitize_01' ) ); 207 register_setting( 'wypiekacz', 'wypiekacz_lock_reason', 'trim' ); 208 register_setting( 'wypiekacz', 'wypiekacz_lock_show_details', array( &$this, 'sanitize_01' ) ); 209 } 152 210 } 153 211 … … 163 221 'WyPiekacz', 'manage_options', __FILE__, array( &$this, 'options_panel' ) ); 164 222 223 // Add links to Posts menu 224 if ( get_option( 'wypiekacz_post_menu_links' ) ) { 225 $can_edit = current_user_can( 'edit_posts' ); 226 $can_publish = current_user_can('publish_posts'); 227 if ( $can_edit || $can_publish ) { 228 $num_posts = wp_count_posts( 'post' ); 229 230 $drafts = $num_posts->draft; 231 add_submenu_page( 'edit.php', __('Drafts', 'wypiekacz'), 232 sprintf( __('Drafts %s', 'wypiekacz'), "<span class='awaiting-mod count-$drafts'><span class='pending-count'>" . 233 number_format_i18n( $drafts ) . "</span></span>" ), 234 'edit_posts', 'edit.php?post_status=draft' ); 235 236 $pending = $num_posts->pending; 237 add_submenu_page( 'edit.php', __('Pending', 'wypiekacz'), 238 sprintf( __('Pending %s', 'wypiekacz'), "<span class='awaiting-mod count-$pending'><span class='pending-count'>" . 239 number_format_i18n( $pending ) . "</span></span>" ), 240 'edit_posts', 'edit.php?post_status=pending' ); 241 } 242 } 243 165 244 // Add metabox to edit post page 166 245 foreach ( $this->post_types as $post_type ) { … … 181 260 global $post; 182 261 $meta = ''; 183 if ( $this->post_page && is_object( $post ) ) {262 if ( $this->post_page && is_object( $post ) ) { 184 263 $meta = get_post_meta($post->ID, 'WyPiekacz_msg', true); 185 264 } … … 187 266 // Display error message 188 267 echo '<div id="notice" class="error"><p>', $meta, 189 '<br />', __('Post Status has been changed to Draft.', 'wypiekacz'), '</p></div>', "\n"; 268 '<br />', __('Post Status has been changed to Draft.', 'wypiekacz'); 269 if ( isset( $_GET['message'] ) && ( $_GET['message'] == '85614' ) ) { 270 echo '<br />', __('Post was *NOT* saved.', 'wypiekacz'); 271 } 272 echo '</p></div>', "\n"; 273 190 274 // Remove this message 191 275 delete_post_meta( $post->ID, 'WyPiekacz_msg' ); 192 // Change WP message to 'Post saved' 193 if ( isset( $_GET['message'] ) ) { 194 if ( '6' == $_GET['message'] ) { 195 $_GET['message'] = '7'; 276 277 // redirect_post_location filter is supported starting from WP2.9 278 if ( !$this->has_wp_29 ) { // 2.8 and below 279 // Change WP message to 'Post saved' 280 if ( isset( $_GET['message'] ) ) { 281 if ( '6' == $_GET['message'] ) { 282 $_GET['message'] = '7'; 283 } elseif ( '85614' == $_GET['message'] ) { 284 unset( $_GET['message'] ); 285 } 196 286 } 197 287 } … … 203 293 if ( count( $this->errors ) > 0 ) { 204 294 $location = remove_query_arg( 'message', $location ); 205 $location = add_query_arg( 'message', '10', $location ); 295 // When invalid post was not saved, WyPiekacz will display appropriate message 296 if ( get_option( 'wypiekacz_dont_save_invalid_post' ) ) { 297 $location = add_query_arg( 'message', '85614', $location ); 298 } else { 299 $location = add_query_arg( 'message', '10', $location ); 300 } 206 301 } 207 302 return $location; … … 210 305 // Check submitted post data 211 306 function wp_insert_post( $data, $post_arr ) { 307 // Skip post revisions and auto-drafts 308 if ( ( $data['post_type'] == 'revision' ) || ( $data['post_status'] == 'auto-draft' ) ) { 309 return $data; 310 } 311 312 // TODO: although it is possible to stop creation of auto drafts from here by breaking the query, 313 // it does not work as expected - there are many PHP warnings in debug mode, and finally 314 // "You are not allowed to edit this post." error on next post save attempt. 315 // WP Core must be fixed first in order to make this work. 316 317 318 // Delete orphaned post drafts 319 if ( $this->deleting_orphaned_posts ) { // Avoid infinite recursion 320 return $data; 321 } else { 322 $this->deleting_orphaned_posts = true; 323 $this->delete_orphaned_drafts(); 324 $this->deleting_orphaned_posts = false; 325 } 326 212 327 if ( 213 // Check only for posts328 // Check selected post types only 214 329 in_array( $data['post_type'], $this->post_types ) 215 // Check only if status is Published or Pending Review 330 // Check only if status is Published or Pending Review or Future 216 331 && ( in_array( $data['post_status'], array( 'publish', 'pending', 'future' ) ) ) 217 332 // Editors (and above) can have limits too … … 240 355 241 356 if ( !$skip_check ) { 357 // Enforce some rules before checking them 242 358 $data = $this->enforce_rules( $data ); 243 359 360 // Check rules 244 361 $result = $this->check_precel_post( $data['post_content'], $data['post_title'], $post_arr ); 245 362 if ( true !== $result ) { … … 259 376 return new WP_Error( 'edit_refused', implode( '; ', $errors ) ); 260 377 }*/ 378 379 // Do not save invalid post if user asked for this. So far the only way is to break SQL query, so register new filter to do this. 380 if ( get_option( 'wypiekacz_dont_save_invalid_post' ) ) { 381 // save_post hook will not be called later, so need to perform some extra steps here 382 383 // Save errors to post meta 384 if ( isset( $post_arr['ID'] ) ) { 385 delete_post_meta( $post_arr['ID'], 'WyPiekacz_msg' ); 386 add_post_meta( $post_arr['ID'], 'WyPiekacz_msg', $this->pack_errors( '<br />' ), true ); 387 } 388 389 // Lock user account if needed 390 $this->lock_user_account( isset( $post_arr['ID'] ) ? $post_arr['ID'] : 0, false ); 391 392 // Do not want to execute any extra SQL queries - just proceeded to INSERT/UPDATE query for current post 393 remove_all_actions( 'pre_post_update' ); 394 395 // Now we can add the filter 396 add_filter( 'query', array( &$this, 'kill_sql_query' ) ); 397 398 // Do not execute any extra code beyond this point - return data only 399 return $data; 400 } 261 401 } 262 402 } … … 264 404 265 405 return $data; 406 } 407 408 // Replace INSERT/UPDATE query with some junk. This filter is used to prevent creating/updating invalid post 409 function kill_sql_query( $query ) { 410 if ( preg_match( '/^\s*(insert|update:?)\s/i', $query ) ) { 411 return 'xxx'; 412 } else { 413 return $query; 414 } 415 } 416 417 // Delete orphaned post drafts 418 function delete_orphaned_drafts() { 419 $interval = get_option( 'wypiekacz_delete_orphaned_drafts', 0 ); 420 if ( $interval == 0 ) { // Feature disabled 421 return; 422 } 423 $force = get_option( 'wypiekacz_force_delete_orphaned_drafts' ) ? true : false; 424 425 global $wpdb; 426 $orphaned_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'draft' AND DATE_SUB( NOW(), INTERVAL $interval DAY ) > post_date" ); 427 foreach ( (array) $orphaned_posts as $delete ) { 428 wp_delete_post( $delete, $force ); 429 } 430 } 431 432 // Lock/disable user account if needed 433 function lock_user_account( $post_id, $check_result ) { 434 if ( !$this->has_user_locker || !get_option( 'wypiekacz_lock_account' ) ) { 435 return; 436 } 437 438 if ( $post_id <= 0 ) { // Make sure post_id == -1 if it is unknown (new post) 439 $post_id = -1; 440 } 441 442 $current_user = wp_get_current_user(); 443 $user_id = $current_user->ID; 444 445 $last_post_id = get_user_option( '_wypiekacz_last_post', $user_id, false ); 446 $bad_post_count = get_user_option( '_wypiekacz_bad_posts', $user_id, false ); 447 if ( empty( $last_post_id ) ) { 448 $last_post_id = 0; 449 } 450 if ( empty( $bad_post_count ) ) { 451 $bad_post_count = 0; 452 } 453 454 if ( $check_result ) { // Rule check succeeded 455 $bad_post_count = 0; // Reset bad post count 456 } else { // Rule check failed 457 // Following cases are not checked here (do nothing for them): 458 // id > 0, last_id == -1 : most probably last failed publish attempt was for the same post (new post), so do nothing 459 // id == last_id > 0 : another failed publish attempt for the same post 460 461 if ( $post_id < 0 ) { // Post ID is not known (new post) 462 ++$bad_post_count; 463 } elseif ( $last_post_id == 0 ) { // No user meta yet, treat this as a new post 464 ++$bad_post_count; 465 } elseif ( ( $last_post_id > 0 ) && ( $last_post_id != $post_id ) ) { // Post ID has changed 466 ++$bad_post_count; 467 } 468 } 469 470 update_user_option( $user_id, '_wypiekacz_last_post', $post_id, false ); 471 update_user_option( $user_id, '_wypiekacz_bad_posts', $bad_post_count, false ); 472 473 $max_count = get_option( 'wypiekacz_lock_account_after' ); 474 if ( $bad_post_count > $max_count ) { 475 $reason = get_option( 'wypiekacz_lock_reason' ); 476 if ( get_option( 'wypiekacz_lock_method' ) == 0 ) { 477 user_locker_lock_user( $user_id, $reason ); 478 } else { 479 user_locker_disable_user( $user_id, $reason ); 480 } 481 482 // Force logout 483 wp_logout(); 484 } 485 } 486 487 // User Locker plugin unlocks/enable user account 488 function user_locker_unlock_user( $user_id ) { 489 // Clear our data 490 update_user_option( $user_id, '_wypiekacz_last_post', 0, false ); 491 update_user_option( $user_id, '_wypiekacz_bad_posts', 0, false ); 266 492 } 267 493 268 494 // Called after post is saved - save error messages too 269 495 function save_post( $post_ID ) { 496 $post = get_post( $post_ID ); 497 498 // Skip post revisions and auto-drafts 499 if ( ( $post->post_type == 'revision' ) || ( $post->post_status == 'auto-draft' ) ) { 500 return; 501 } 502 270 503 // Check if 'Skip rule check' option was checked 271 // verify this came from the our screen and with proper authori sation,504 // verify this came from the our screen and with proper authorization, 272 505 // because save_post can be triggered at other times 273 506 if ( get_option( 'wypiekacz_allow_skip_rules' ) && isset( $_POST['wypiekacz_nonce'] ) && … … 287 520 if ( count( $this->errors ) > 0 ) { 288 521 delete_post_meta( $post_ID, 'WyPiekacz_msg' ); 289 add_post_meta( $post_ID, 'WyPiekacz_msg', implode( '<br />', $this->errors ), true ); 522 add_post_meta( $post_ID, 'WyPiekacz_msg', $this->pack_errors( '<br />' ), true ); 523 524 // Lock user account if needed 525 $this->lock_user_account( $post_ID, false ); 526 } 527 528 // Lock/unlock user account if needed 529 $autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE; 530 if ( !$autosave ) { 531 $this->lock_user_account( $post_ID, count( $this->errors ) == 0 ); 290 532 } 291 533 } … … 310 552 _e('OK', 'wypiekacz'); 311 553 } else { 312 echo '<span style="color:red">', implode( '<br />', $this->errors), "</span>\n";554 echo '<span style="color:red">', $this->pack_errors( '<br />' ), "</span>\n"; 313 555 $this->errors = array(); 314 556 } … … 319 561 // Callback - remove extra links 320 562 function rx_remove_links( $matches ) { 563 // Remove links placed too early first 564 if ( $this->links_to_remove > 0 ) { 565 --$this->links_to_remove; 566 return $matches[2]; 567 } 568 569 // Remove links above limit 321 570 ++$this->link_counter; 322 571 if ( $this->link_counter > get_option( 'wypiekacz_max_links' ) ) { … … 348 597 // Enforce rules for posts 349 598 function enforce_rules( $data ) { 350 // Enforce max link count 351 if ( get_option( 'wypiekacz_enforce_links' ) ) { 599 // Find how many initial links should be removed 600 $this->links_to_remove = 0; 601 if ( get_option( 'wypiekacz_enforce_link_positions' ) ) { 602 $first_link_after_chars = get_option( 'wypiekacz_link_after' ); 603 $first_link_after_words = get_option( 'wypiekacz_link_after_words' ); 604 605 $cnt = preg_match_all( '/<\s*a\s/i', $data['post_content'], $matches, PREG_OFFSET_CAPTURE ); 606 for ( $n = 0; $n < $cnt; ++$n ) { 607 // $matches[0][N][1] contains match offsets for links 608 $link_pos = $matches[0][$n][1]; 609 $text_before_link = substr( $data['post_content'], 0, $link_pos ); 610 611 // Check position of link (in characters) 612 $text2 = preg_replace( '/\s\s+/', ' ', ltrim( wp_strip_all_tags( $text_before_link ) ) ); 613 $len = strlen( $text2 ); 614 if ( $len < $first_link_after_chars ) { 615 // Need to remove this link 616 ++$this->links_to_remove; 617 continue; 618 } 619 620 // Check position of link (in words) 621 $count = $this->count_words( $text_before_link ); 622 if ( $count < $first_link_after_words ) { 623 // Need to remove this link 624 ++$this->links_to_remove; 625 continue; 626 } 627 628 // Link is in correct place - next links will be too, so exit loop 629 break; 630 } 631 } 632 633 // Enforce max link count and link positions 634 if ( ( $this->links_to_remove > 0 ) || get_option( 'wypiekacz_enforce_links' ) ) { 352 635 $this->link_counter = 0; 353 636 $data['post_content'] = preg_replace_callback( '#(<a [^>]*href\s*=\s*[^>]+[^>]*>)(.*?)(</a>)#', … … 409 692 /*if ( get_option( 'wypiekacz_enforce_tags' ) ) { 410 693 }*/ 694 695 // Allow other plugins to enforce additional rules 696 $data = apply_filters( 'wypiekacz_enforce_rules', $data ); 411 697 412 698 return $data; … … 604 890 // Check length (in characters) 605 891 $min_len = get_option( 'wypiekacz_min_len' ); 606 $text2 = preg_replace( '/\s\s+/', ' ', trim( strip_tags( $text ) ) );892 $text2 = preg_replace( '/\s\s+/', ' ', trim( wp_strip_all_tags( $text ) ) ); 607 893 $len = strlen( $text2 ); 608 894 if ( $len < $min_len ) { 609 $this->errors[] = sprintf( __('Post is too short (minimum is %1$s chars, your post has %2$s).', 'wypiekacz'),610 $min_len, $len ) ;895 $this->errors[] = array( 'min_len_chars', sprintf( __('Post is too short (minimum is %1$s chars, your post has %2$s).', 'wypiekacz'), 896 $min_len, $len ) ); 611 897 } 612 898 … … 615 901 $count = $this->count_words( $text ); 616 902 if ( $count < $min_len ) { 617 $this->errors[] = sprintf( __('Post is too short (minimum is %1$s words, your post has %2$s).', 'wypiekacz'),618 $min_len, $count ) ;903 $this->errors[] = array( 'min_len_words', sprintf( __('Post is too short (minimum is %1$s words, your post has %2$s).', 'wypiekacz'), 904 $min_len, $count ) ); 619 905 } 620 906 621 907 // Check links 908 $min_links = get_option( 'wypiekacz_min_links' ); 622 909 $max_links = get_option( 'wypiekacz_max_links' ); 623 $cnt = preg_match_all( '/<\s*a\s/i', $text, $matches ); 624 if ( $cnt > $max_links ) { 625 $this->errors[] = sprintf( __('Post contains too many links (maximum is %1$s, your post has %2$s).', 'wypiekacz'), 626 $max_links, $cnt ); 910 $cnt = preg_match_all( '/<\s*a\s/i', $text, $matches, PREG_OFFSET_CAPTURE ); 911 if ( $cnt < $min_links ) { 912 $this->errors[] = array( 'min_links', sprintf( __('Post contains too few links (minimum is %1$s, your post has %2$s).', 'wypiekacz'), 913 $max_links, $cnt ) ); 914 } elseif ( $cnt > $max_links ) { 915 $this->errors[] = array( 'max_links', sprintf( __('Post contains too many links (maximum is %1$s, your post has %2$s).', 'wypiekacz'), 916 $max_links, $cnt ) ); 917 } 918 919 if ( $cnt > 0 ) { 920 // $matches[0][N][1] contains match offsets for links 921 $link_pos = $matches[0][0][1]; 922 $text_before_link = substr( $text, 0, $link_pos ); 923 924 // Check position of first link (in characters) 925 $first_link_after = get_option( 'wypiekacz_link_after' ); 926 $text2 = preg_replace( '/\s\s+/', ' ', ltrim( wp_strip_all_tags( $text_before_link ) ) ); 927 $len = strlen( $text2 ); 928 if ( $len < $first_link_after ) { 929 $this->errors[] = array( 'link_after_chars', sprintf( __('First link is too close to the beginning (minimum is after %1$s chars, your link is after %2$s).', 'wypiekacz'), 930 $first_link_after, $len ) ); 931 } 932 933 // Check position of first link (in words) 934 $first_link_after = get_option( 'wypiekacz_link_after_words' ); 935 $count = $this->count_words( $text_before_link ); 936 if ( $count < $first_link_after ) { 937 $this->errors[] = array( 'link_after_words', sprintf( __('First link is too close to the beginning (minimum is after %1$s words, your link is after %2$s).', 'wypiekacz'), 938 $first_link_after, $count ) ); 939 } 627 940 } 628 941 … … 633 946 $len = strlen( $text2 ); 634 947 if ( $len < $min_len ) { 635 $this->errors[] = sprintf( __('Post Title is too short (minimum is %1$s chars, your Title has %2$s).', 'wypiekacz'),636 $min_len, $len ) ;948 $this->errors[] = array( 'min_title_len_chars', sprintf( __('Post Title is too short (minimum is %1$s chars, your Title has %2$s).', 'wypiekacz'), 949 $min_len, $len ) ); 637 950 } 638 951 elseif ( ( $max_len > 0 ) && ( $len > $max_len ) ) { 639 $this->errors[] = sprintf( __('Post Title is too long (maximum is %1$s chars, your Title has %2$s).', 'wypiekacz'),640 $max_len, $len ) ;952 $this->errors[] = array( 'max_title_len_chars', sprintf( __('Post Title is too long (maximum is %1$s chars, your Title has %2$s).', 'wypiekacz'), 953 $max_len, $len ) ); 641 954 } 642 955 … … 646 959 $count = $this->count_words( $title ); 647 960 if ( $count < $min_len ) { 648 $this->errors[] = sprintf( __('Post Title is too short (minimum is %1$s words, your Title has %2$s).', 'wypiekacz'),649 $min_len, $count ) ;961 $this->errors[] = array( 'min_title_len_words', sprintf( __('Post Title is too short (minimum is %1$s words, your Title has %2$s).', 'wypiekacz'), 962 $min_len, $count ) ); 650 963 } 651 964 elseif ( ( $max_len > 0 ) && ( $count > $max_len ) ) { 652 $this->errors[] = sprintf( __('Post Title is too long (maximum is %1$s words, your Title has %2$s).', 'wypiekacz'),653 $max_len, $count ) ;965 $this->errors[] = array( 'max_title_len_words', sprintf( __('Post Title is too long (maximum is %1$s words, your Title has %2$s).', 'wypiekacz'), 966 $max_len, $count ) ); 654 967 } 655 968 … … 687 1000 $use_default_cat = get_option( 'wypiekacz_use_def_cat' ); 688 1001 if ( !$use_default_cat && $has_default_cat ) { 689 $this->errors[] = sprintf( __('Cannot add posts to the default category (%s).', 'wypiekacz'),690 get_cat_name( $default_cat ) ) ;1002 $this->errors[] = array( 'no_def_cat', sprintf( __('Cannot add posts to the default category (%s).', 'wypiekacz'), 1003 get_cat_name( $default_cat ) ) ); 691 1004 } 692 1005 … … 700 1013 $max_cats = get_option( 'wypiekacz_max_cats' ); 701 1014 if ( $post_cat_cnt < $min_cats ) { 702 $this->errors[] = sprintf( __('Too few categories selected (minimum is %1$s, your post has %2$s).', 'wypiekacz'),703 $min_cats, $post_cat_cnt ) ;1015 $this->errors[] = array( 'min_cats', sprintf( __('Too few categories selected (minimum is %1$s, your post has %2$s).', 'wypiekacz'), 1016 $min_cats, $post_cat_cnt ) ); 704 1017 } else if ( $post_cat_cnt > $max_cats ) { 705 $this->errors[] = sprintf( __('Too many categories selected (maximum is %1$s, your post has %2$s).', 'wypiekacz'),706 $max_cats, $post_cat_cnt ) ;1018 $this->errors[] = array( 'max_cats', sprintf( __('Too many categories selected (maximum is %1$s, your post has %2$s).', 'wypiekacz'), 1019 $max_cats, $post_cat_cnt ) ); 707 1020 } 708 1021 709 1022 if ( is_array( $post_data ) ) { 710 //var_dump($post_data);die;711 1023 $post_tag_cnt = 0; 712 1024 $tags = array(); … … 750 1062 751 1063 if ( $post_tag_cnt < $min_tags ) { 752 $this->errors[] = sprintf( __('Too few tags (minimum is %1$s, your post has %2$s).', 'wypiekacz'),753 $min_tags, $post_tag_cnt ) ;1064 $this->errors[] = array( 'min_tags', sprintf( __('Too few tags (minimum is %1$s, your post has %2$s).', 'wypiekacz'), 1065 $min_tags, $post_tag_cnt ) ); 754 1066 } else if ($post_tag_cnt > $max_tags) { 755 $this->errors[] = sprintf( __('Too many tags (maximum is %1$s, your post has %2$s).', 'wypiekacz'),756 $max_tags, $post_tag_cnt ) ;1067 $this->errors[] = array( 'max_tags', sprintf( __('Too many tags (maximum is %1$s, your post has %2$s).', 'wypiekacz'), 1068 $max_tags, $post_tag_cnt ) ); 757 1069 } 758 1070 … … 761 1073 $words_found = $this->check_badwords( $title ); 762 1074 if ( count( $words_found ) > 0 ) { 763 $this->errors[] = sprintf( __('Forbidden word(s) in title: %s', 'wypiekacz'),764 implode( ', ', $words_found ) ) ;1075 $this->errors[] = array( 'badwords_title', sprintf( __('Forbidden word(s) in title: %s', 'wypiekacz'), 1076 implode( ', ', $words_found ) ) ); 765 1077 } 766 1078 } … … 770 1082 $words_found = $this->check_badwords( $text ); 771 1083 if ( count( $words_found ) > 0 ) { 772 $this->errors[] = sprintf( __('Forbidden word(s) in content: %s', 'wypiekacz'), 773 implode( ', ', $words_found ) ); 774 } 775 } 1084 $this->errors[] = array( 'badwords_content', sprintf( __('Forbidden word(s) in content: %s', 'wypiekacz'), 1085 implode( ', ', $words_found ) ) ); 1086 } 1087 } 1088 1089 // Check forbidden words in tags 1090 if ( get_option( 'wypiekacz_check_badwords_tags' ) ) { 1091 // Convert objects to string if needed 1092 if ( ( count( $tags ) > 0 ) && is_object( $tags[0] ) ) { 1093 $tags_to_check = array(); 1094 foreach ( $tags as $tag ) { 1095 $tags_to_check[] = $tag->name; 1096 } 1097 } else { 1098 $tags_to_check = $tags; 1099 } 1100 1101 $words_found = $this->check_badwords( implode( ',', $tags_to_check ) ); 1102 if ( count( $words_found ) > 0 ) { 1103 $this->errors[] = array( 'badwords_tags', sprintf( __('Forbidden word(s) in tags: %s', 'wypiekacz'), 1104 implode( ', ', $words_found ) ) ); 1105 } 1106 } 1107 1108 // Check post thumbnail 1109 if ( get_option( 'wypiekacz_post_thumbnail' ) ) { 1110 $post_id = 0; 1111 if ( is_array( $post_data ) ) { 1112 // Get ID from POST data 1113 if ( isset( $post_data['ID'] ) ) { 1114 $post_id = (int)$post_data['ID']; 1115 } 1116 } else { 1117 // Get ID from Post object 1118 $post_id = $post_data->ID; 1119 } 1120 1121 $has_thumbnail = false; 1122 if ( ( $post_id > 0 ) && function_exists( 'has_post_thumbnail' ) ) { 1123 $has_thumbnail = has_post_thumbnail( $post_id ); 1124 } 1125 1126 $has_thumbnail = apply_filters( 'wypiekacz_check_thumbnail', $has_thumbnail, $post_id, $post_data ); 1127 1128 if ( !$has_thumbnail ) { 1129 $this->errors[] = array( 'post_thumbnail', __('Post thumbnail (Featured image) is required.', 'wypiekacz') ); 1130 } 1131 } 1132 1133 // Allow other plugins to check additional rules 1134 $this->errors = apply_filters( 'wypiekacz_check_post', $this->errors, $text, $title, $post_data ); 776 1135 777 1136 return count( $this->errors ) == 0; … … 851 1210 } 852 1211 1212 // Convert error array to displayable form 1213 function pack_errors( $separator ) { 1214 $ret = ''; 1215 $first = true; 1216 foreach ( $this->errors as $error ) { 1217 if ( $first ) { 1218 $first = false; 1219 } else { 1220 $ret .= $separator; 1221 } 1222 $ret .= $error[1]; 1223 } 1224 return $ret; 1225 } 1226 1227 // Unload autosave script if needed 1228 function wp_print_scripts() { 1229 wp_deregister_script( 'autosave' ); 1230 } 1231 1232 // Add new column to the user list page 1233 function manage_users_columns( $columns ) { 1234 // This requires WP 2.8+ 1235 global $wp_version; 1236 if ( $this->has_wp_28 && $this->has_user_locker && get_option( 'wypiekacz_lock_show_details' ) ) { 1237 $columns['wypiekacz'] = 'WyPiekacz'; 1238 } 1239 return $columns; 1240 } 1241 1242 // Add column content for each user on user list 1243 function manage_users_custom_column( $value, $column_name, $user_id ) { 1244 if ( $column_name == 'wypiekacz' ) { 1245 $last_post_id = get_user_option( '_wypiekacz_last_post', $user_id, false ); 1246 $bad_post_count = get_user_option( '_wypiekacz_bad_posts', $user_id, false ); 1247 if ( empty( $last_post_id ) ) { 1248 $last_post_id = 0; 1249 } 1250 if ( empty( $bad_post_count ) ) { 1251 $bad_post_count = 0; 1252 } 1253 1254 $value = sprintf( __('Bad Posts: %1$s, Last Post ID: %2$s', 'wypiekacz'), $bad_post_count, $last_post_id ); 1255 } 1256 1257 return $value; 1258 } 1259 853 1260 // Handle options panel 854 1261 function options_panel() { … … 869 1276 </th> 870 1277 <td> 871 <input type="text" maxlength="6" size="10" id="wypiekacz_min_len" name="wypiekacz_min_len" value="<?php echo stripcslashes( get_option( 'wypiekacz_min_len' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set minimum word count to zero.', 'wypiekacz'); ?>1278 <input type="text" maxlength="6" size="10" id="wypiekacz_min_len" name="wypiekacz_min_len" value="<?php echo esc_attr( get_option( 'wypiekacz_min_len' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set minimum word count to zero.', 'wypiekacz'); ?> 872 1279 </td> 873 1280 </tr> … … 878 1285 </th> 879 1286 <td> 880 <input type="text" maxlength="6" size="10" id="wypiekacz_min_len_words" name="wypiekacz_min_len_words" value="<?php echo stripcslashes( get_option( 'wypiekacz_min_len_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set minimum character count to zero.', 'wypiekacz'); ?> 1287 <input type="text" maxlength="6" size="10" id="wypiekacz_min_len_words" name="wypiekacz_min_len_words" value="<?php echo esc_attr( get_option( 'wypiekacz_min_len_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set minimum character count to zero.', 'wypiekacz'); ?> 1288 </td> 1289 </tr> 1290 1291 <tr> 1292 <th scope="row" style="text-align:right; vertical-align:top;"> 1293 <label for="wypiekacz_min_links"><?php _e('Minimum link count in post:', 'wypiekacz'); ?></label> 1294 </th> 1295 <td> 1296 <input type="text" maxlength="4" size="10" id="wypiekacz_min_links" name="wypiekacz_min_links" value="<?php echo esc_attr( get_option( 'wypiekacz_min_links' ) ); ?>" /> 881 1297 </td> 882 1298 </tr> … … 887 1303 </th> 888 1304 <td> 889 <input type="text" maxlength="2" size="10" id="wypiekacz_max_links" name="wypiekacz_max_links" value="<?php echo stripcslashes( get_option( 'wypiekacz_max_links' ) ); ?>" /> 1305 <input type="text" maxlength="4" size="10" id="wypiekacz_max_links" name="wypiekacz_max_links" value="<?php echo esc_attr( get_option( 'wypiekacz_max_links' ) ); ?>" /> 1306 </td> 1307 </tr> 1308 1309 <tr> 1310 <th scope="row" style="text-align:right; vertical-align:top;"> 1311 <label for="wypiekacz_link_after"><?php _e('First link is allowed after N initial characters:', 'wypiekacz'); ?></label> 1312 </th> 1313 <td> 1314 <input type="text" maxlength="6" size="10" id="wypiekacz_link_after" name="wypiekacz_link_after" value="<?php echo esc_attr( get_option( 'wypiekacz_link_after' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set minimum word count to zero.', 'wypiekacz'); ?> 1315 </td> 1316 </tr> 1317 1318 <tr> 1319 <th scope="row" style="text-align:right; vertical-align:top;"> 1320 <label for="wypiekacz_link_after_words"><?php _e('First link is allowed after N initial words:', 'wypiekacz'); ?></label> 1321 </th> 1322 <td> 1323 <input type="text" maxlength="6" size="10" id="wypiekacz_link_after_words" name="wypiekacz_link_after_words" value="<?php echo esc_attr( get_option( 'wypiekacz_link_after_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set minimum character count to zero.', 'wypiekacz'); ?> 1324 </td> 1325 </tr> 1326 1327 <tr> 1328 <th scope="row" style="text-align:right; vertical-align:top;"> 1329 <label for="wypiekacz_post_thumbnail"><?php _e('Post thumbnail (Featured image) is required:', 'wypiekacz'); ?></label> 1330 </th> 1331 <td> 1332 <input type="checkbox" id="wypiekacz_post_thumbnail" name="wypiekacz_post_thumbnail" value="yes" <?php checked( 1, get_option( 'wypiekacz_post_thumbnail' ) ); ?> /> 1333 <br /><?php _e('Note: WyPiekacz supports WordPress Featured image by default. You can also provide your own function to check if Post thumbnail is present - see FAQ for more details.', 'wypiekacz'); ?> 890 1334 </td> 891 1335 </tr> … … 898 1342 </th> 899 1343 <td> 900 <input type="text" maxlength="3" size="10" id="wypiekacz_min_title_len" name="wypiekacz_min_title_len" value="<?php echo stripcslashes( get_option( 'wypiekacz_min_title_len' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set minimum word count to zero.', 'wypiekacz'); ?>1344 <input type="text" maxlength="3" size="10" id="wypiekacz_min_title_len" name="wypiekacz_min_title_len" value="<?php echo esc_attr( get_option( 'wypiekacz_min_title_len' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set minimum word count to zero.', 'wypiekacz'); ?> 901 1345 </td> 902 1346 </tr> … … 907 1351 </th> 908 1352 <td> 909 <input type="text" maxlength="3" size="10" id="wypiekacz_min_title_len_words" name="wypiekacz_min_title_len_words" value="<?php echo stripcslashes( get_option( 'wypiekacz_min_title_len_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set minimum character count to zero.', 'wypiekacz'); ?>1353 <input type="text" maxlength="3" size="10" id="wypiekacz_min_title_len_words" name="wypiekacz_min_title_len_words" value="<?php echo esc_attr( get_option( 'wypiekacz_min_title_len_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set minimum character count to zero.', 'wypiekacz'); ?> 910 1354 </td> 911 1355 </tr> … … 916 1360 </th> 917 1361 <td> 918 <input type="text" maxlength="3" size="10" id="wypiekacz_max_title_len" name="wypiekacz_max_title_len" value="<?php echo stripcslashes( get_option( 'wypiekacz_max_title_len' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set maximum word count to zero.', 'wypiekacz'); ?>1362 <input type="text" maxlength="3" size="10" id="wypiekacz_max_title_len" name="wypiekacz_max_title_len" value="<?php echo esc_attr( get_option( 'wypiekacz_max_title_len' ) ); ?>" /><br /><?php _e('Note: if you want to check character count only, set maximum word count to zero.', 'wypiekacz'); ?> 919 1363 </td> 920 1364 </tr> … … 925 1369 </th> 926 1370 <td> 927 <input type="text" maxlength="3" size="10" id="wypiekacz_max_title_len_words" name="wypiekacz_max_title_len_words" value="<?php echo stripcslashes( get_option( 'wypiekacz_max_title_len_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set maximum character count to zero.', 'wypiekacz'); ?>1371 <input type="text" maxlength="3" size="10" id="wypiekacz_max_title_len_words" name="wypiekacz_max_title_len_words" value="<?php echo esc_attr( get_option( 'wypiekacz_max_title_len_words' ) ); ?>" /><br /><?php _e('Note: if you want to check word count only, set maximum character count to zero.', 'wypiekacz'); ?> 928 1372 </td> 929 1373 </tr> … … 945 1389 </th> 946 1390 <td> 947 <input type="text" maxlength="3" size="10" id="wypiekacz_min_cats" name="wypiekacz_min_cats" value="<?php echo stripcslashes( get_option( 'wypiekacz_min_cats' ) ); ?>" />1391 <input type="text" maxlength="3" size="10" id="wypiekacz_min_cats" name="wypiekacz_min_cats" value="<?php echo esc_attr( get_option( 'wypiekacz_min_cats' ) ); ?>" /> 948 1392 </td> 949 1393 </tr> … … 954 1398 </th> 955 1399 <td> 956 <input type="text" maxlength="3" size="10" id="wypiekacz_max_cats" name="wypiekacz_max_cats" value="<?php echo stripcslashes( get_option( 'wypiekacz_max_cats' ) ); ?>" />1400 <input type="text" maxlength="3" size="10" id="wypiekacz_max_cats" name="wypiekacz_max_cats" value="<?php echo esc_attr( get_option( 'wypiekacz_max_cats' ) ); ?>" /> 957 1401 </td> 958 1402 </tr> … … 965 1409 </th> 966 1410 <td> 967 <input type="text" maxlength="3" size="10" id="wypiekacz_min_tags" name="wypiekacz_min_tags" value="<?php echo stripcslashes( get_option( 'wypiekacz_min_tags' ) ); ?>" />1411 <input type="text" maxlength="3" size="10" id="wypiekacz_min_tags" name="wypiekacz_min_tags" value="<?php echo esc_attr( get_option( 'wypiekacz_min_tags' ) ); ?>" /> 968 1412 </td> 969 1413 </tr> … … 974 1418 </th> 975 1419 <td> 976 <input type="text" maxlength="3" size="10" id="wypiekacz_max_tags" name="wypiekacz_max_tags" value="<?php echo stripcslashes( get_option( 'wypiekacz_max_tags' ) ); ?>" />1420 <input type="text" maxlength="3" size="10" id="wypiekacz_max_tags" name="wypiekacz_max_tags" value="<?php echo esc_attr( get_option( 'wypiekacz_max_tags' ) ); ?>" /> 977 1421 </td> 978 1422 </tr> … … 1000 1444 <tr> 1001 1445 <th scope="row" style="text-align:right; vertical-align:top;"> 1446 <label for="wypiekacz_check_badwords_tags"><?php _e('Check for forbidden words in tags:', 'wypiekacz'); ?></label> 1447 </th> 1448 <td> 1449 <input type="checkbox" id="wypiekacz_check_badwords_tags" name="wypiekacz_check_badwords_tags" value="yes" <?php checked( 1, get_option( 'wypiekacz_check_badwords_tags' ) ); ?> /> 1450 </td> 1451 </tr> 1452 1453 <tr> 1454 <th scope="row" style="text-align:right; vertical-align:top;"> 1002 1455 <label for="wypiekacz_badwords"><?php _e('Forbidden words list:', 'wypiekacz'); ?></label> 1003 1456 </th> 1004 1457 <td> 1005 <textarea id="wypiekacz_badwords" name="wypiekacz_badwords" rows="5" cols="30"><?php echo htmlspecialchars( implode( 1006 "\n", get_option( 'wypiekacz_badwords', array() ) ) ); ?></textarea><br /> 1458 <textarea id="wypiekacz_badwords" name="wypiekacz_badwords" rows="5" cols="30"><?php echo esc_html( implode( "\n", get_option( 'wypiekacz_badwords', array() ) ) ); ?></textarea><br /> 1007 1459 <?php _e('Put one word per line', 'wypiekacz'); ?> 1008 1460 </td> … … 1014 1466 </th> 1015 1467 <td> 1016 <textarea id="wypiekacz_goodwords" name="wypiekacz_goodwords" rows="5" cols="30"><?php echo htmlspecialchars( implode( 1017 "\n", get_option( 'wypiekacz_goodwords', array() ) ) ); ?></textarea><br /> 1468 <textarea id="wypiekacz_goodwords" name="wypiekacz_goodwords" rows="5" cols="30"><?php echo esc_html( implode( "\n", get_option( 'wypiekacz_goodwords', array() ) ) ); ?></textarea><br /> 1018 1469 <?php _e('Put one word per line', 'wypiekacz'); ?><br /><?php _e('When WyPiekacz will found any word from Forbidden Word List in text, it will check if it part of any word from Allowed Words List (e.g. <b>fly</b> - forbidden, <b>butterfly</b> - allowed)', 'wypiekacz'); ?> 1019 1470 </td> 1020 1471 </tr> 1021 1472 1473 <tr><th colspan="2"><h3><?php _e('Post Thumbnail:', 'wypiekacz'); ?></h3></th></tr> 1474 1475 <tr> 1476 <th scope="row" style="text-align:right; vertical-align:top;"> 1477 <label for="wypiekacz_post_thumbnail"><?php _e('Post thumbnail (Featured image) is required:', 'wypiekacz'); ?></label> 1478 </th> 1479 <td> 1480 <input type="checkbox" id="wypiekacz_post_thumbnail" name="wypiekacz_post_thumbnail" value="yes" <?php checked( 1, get_option( 'wypiekacz_post_thumbnail' ) ); ?> /> 1481 <br /><?php _e('Note: WyPiekacz supports WordPress Featured image by default. You can also provide your own function to check if Post thumbnail is present - see FAQ for more details.', 'wypiekacz'); ?> 1482 </td> 1483 </tr> 1484 1022 1485 <tr><th colspan="2"><h3><?php _e('Rule enforcement:', 'wypiekacz'); ?></h3></th></tr> 1023 1486 … … 1033 1496 <tr> 1034 1497 <th scope="row" style="text-align:right; vertical-align:top;"> 1498 <label for="wypiekacz_enforce_link_positions"><?php _e('Enforce link positions:', 'wypiekacz'); ?></label> 1499 </th> 1500 <td> 1501 <input type="checkbox" id="wypiekacz_enforce_link_positions" name="wypiekacz_enforce_link_positions" value="yes" <?php checked( 1, get_option( 'wypiekacz_enforce_link_positions' ) ); ?> /><br /><?php _e('Links inserted too close to the beginning of post content will be automatically removed', 'wypiekacz'); ?> 1502 </td> 1503 </tr> 1504 1505 <tr> 1506 <th scope="row" style="text-align:right; vertical-align:top;"> 1035 1507 <label for="wypiekacz_enforce_title"><?php _e('Enforce max title length:', 'wypiekacz'); ?></label> 1036 1508 </th> … … 1067 1539 </tr> 1068 1540 1541 <tr><th colspan="2"><h3><?php _e('Invalid Posts:', 'wypiekacz'); ?></h3></th></tr> 1542 1543 <tr> 1544 <th scope="row" style="text-align:right; vertical-align:top;"> 1545 <label for="wypiekacz_dont_save_invalid_post"><?php _e('Do not save posts which do not satisfy all rules:', 'wypiekacz'); ?></label> 1546 </th> 1547 <td> 1548 <input type="checkbox" id="wypiekacz_dont_save_invalid_post" name="wypiekacz_dont_save_invalid_post" value="yes" <?php checked( 1, get_option( 'wypiekacz_dont_save_invalid_post' ) ); ?> /> 1549 <br /><?php _e('When this option is enabled, posts submitted for review or publishing will not be saved if they do not satisfy all rules. This can negatively affect user experience, so enable it if you have to deal with lots of automated spam only.', 'wypiekacz'); ?> 1550 <br /><?php _e('Note: this option does not prevent creation of auto drafts - so far there are too many dependencies in WordPress code to make it work correctly. Autosave and normal post saving as draft (without attempt to publish or send it for review) will work too.', 'wypiekacz'); ?> 1551 </td> 1552 </tr> 1553 1554 <tr> 1555 <th scope="row" style="text-align:right; vertical-align:top;"> 1556 <label for="wypiekacz_delete_orphaned_drafts"><?php _e('Delete orphaned post drafts interval (days):', 'wypiekacz'); ?></label> 1557 </th> 1558 <td> 1559 <input type="text" maxlength="4" size="10" id="wypiekacz_delete_orphaned_drafts" name="wypiekacz_delete_orphaned_drafts" value="<?php echo esc_attr( get_option( 'wypiekacz_delete_orphaned_drafts' ) ); ?>" /><br /><?php _e('Default is 0 days - disabled. When Trash is enabled, drafts will be moved to Trash.', 'wypiekacz'); ?> 1560 </td> 1561 </tr> 1562 1563 <tr> 1564 <th scope="row" style="text-align:right; vertical-align:top;"> 1565 <label for="wypiekacz_force_delete_orphaned_drafts"><?php _e('Force deletion of orphaned post drafts:', 'wypiekacz'); ?></label> 1566 </th> 1567 <td> 1568 <input type="checkbox" id="wypiekacz_force_delete_orphaned_drafts" name="wypiekacz_force_delete_orphaned_drafts" value="yes" <?php checked( 1, get_option( 'wypiekacz_force_delete_orphaned_drafts' ) ); ?> /><br /><?php _e('Do not move orphaned post drafts to Trash - delete them immediately.', 'wypiekacz'); ?> 1569 </td> 1570 </tr> 1571 1572 <tr><th colspan="2"><h3><?php _e('Build-in WordPress functionalities:', 'wypiekacz'); ?></h3></th></tr> 1573 1574 <tr> 1575 <th scope="row" style="text-align:right; vertical-align:top;"> 1576 <label for="wypiekacz_autosave_interval"><?php _e('Post autosave interval (seconds):', 'wypiekacz'); ?></label> 1577 </th> 1578 <td> 1579 <input type="text" maxlength="4" size="10" id="wypiekacz_autosave_interval" name="wypiekacz_autosave_interval" value="<?php echo esc_attr( get_option( 'wypiekacz_autosave_interval' ) ); ?>" /><br /><?php _e('Default is 60 seconds. Enter 0 to disable autosave.', 'wypiekacz'); ?> 1580 </td> 1581 </tr> 1582 1583 <tr> 1584 <th scope="row" style="text-align:right; vertical-align:top;"> 1585 <label for="wypiekacz_post_revisions"><?php _e('Maximum post revisions count:', 'wypiekacz'); ?></label> 1586 </th> 1587 <td> 1588 <input type="text" maxlength="4" size="10" id="wypiekacz_post_revisions" name="wypiekacz_post_revisions" value="<?php echo esc_attr( get_option( 'wypiekacz_post_revisions' ) ); ?>" /><br /><?php _e('Default is -1 (no limit). Enter 0 to disable post revisions.', 'wypiekacz'); ?> 1589 </td> 1590 </tr> 1591 1592 <tr> 1593 <th scope="row" style="text-align:right; vertical-align:top;"> 1594 <label for="wypiekacz_empty_trash_days"><?php _e('Empty trash interval (days):', 'wypiekacz'); ?></label> 1595 </th> 1596 <td> 1597 <input type="text" maxlength="4" size="10" id="wypiekacz_empty_trash_days" name="wypiekacz_empty_trash_days" value="<?php echo esc_attr( get_option( 'wypiekacz_empty_trash_days' ) ); ?>" /><br /><?php _e('Default is 30 days. Enter 0 to disable Trash.', 'wypiekacz'); ?> 1598 </td> 1599 </tr> 1600 1069 1601 <tr><th colspan="2"><h3><?php _e('Special:', 'wypiekacz'); ?></h3></th></tr> 1070 1602 … … 1093 1625 <td> 1094 1626 <input type="checkbox" id="wypiekacz_right_now_stats" name="wypiekacz_right_now_stats" value="yes" <?php checked( 1, get_option( 'wypiekacz_right_now_stats' ) ); ?> /> 1627 </td> 1628 </tr> 1629 1630 <tr> 1631 <th scope="row" style="text-align:right; vertical-align:top;"> 1632 <label for="wypiekacz_post_menu_links"><?php _e('Add links to Draft and Pending Posts lists to Posts menu:', 'wypiekacz'); ?></label> 1633 </th> 1634 <td> 1635 <input type="checkbox" id="wypiekacz_post_menu_links" name="wypiekacz_post_menu_links" value="yes" <?php checked( 1, get_option( 'wypiekacz_post_menu_links' ) ); ?> /> 1095 1636 </td> 1096 1637 </tr> … … 1110 1651 foreach ( $post_types as $post_type => $post_type_label ) { 1111 1652 ?> 1112 <label><input type="checkbox" id="wypiekacz_post_types_<?php print $post_type; ?>" name="wypiekacz_post_types[]" value="<?php print $post_type; ?>" <?php checked( true, in_array( $post_type, $selected_post_types ) ); ?> /> <?php print $post_type_label; ?></label><br />1653 <label><input type="checkbox" id="wypiekacz_post_types_<?php echo esc_attr( $post_type ); ?>" name="wypiekacz_post_types[]" value="<?php echo esc_attr( $post_type ); ?>" <?php checked( true, in_array( $post_type, $selected_post_types ) ); ?> /> <?php echo esc_html( $post_type_label ); ?></label><br /> 1113 1654 <?php 1114 1655 } … … 1126 1667 </th> 1127 1668 <td> 1128 <input type="text" size="59" id="wypiekacz_def_title" name="wypiekacz_def_title" value="<?php echo stripcslashes( get_option( 'wypiekacz_def_title' ) ); ?>" />1669 <input type="text" size="59" id="wypiekacz_def_title" name="wypiekacz_def_title" value="<?php echo esc_attr( get_option( 'wypiekacz_def_title' ) ); ?>" /> 1129 1670 </td> 1130 1671 </tr> … … 1135 1676 </th> 1136 1677 <td> 1137 <textarea rows="5" cols="57" id="wypiekacz_def_text" name="wypiekacz_def_text"><?php echo stripcslashes( get_option( 'wypiekacz_def_text' ) ); ?></textarea>1678 <textarea rows="5" cols="57" id="wypiekacz_def_text" name="wypiekacz_def_text"><?php echo esc_textarea( get_option( 'wypiekacz_def_text' ) ); ?></textarea> 1138 1679 </td> 1139 1680 </tr> … … 1158 1699 </td> 1159 1700 </tr> 1701 1702 <tr><th colspan="2"><h3><?php _e('Account locking:', 'wypiekacz'); ?></h3></th></tr> 1703 1704 <tr> 1705 <th scope="row" style="text-align:right; vertical-align:top;"> 1706 1707 </th> 1708 <td> 1709 <?php printf( __('Current WyPiekacz version is integrated with the <a href="%s" target="_blank">User Locker</a> plugin (version 1.2 or newer). It can lock or disable user account when he/she will send too many invalid posts for review or attempt to publish it and abandon them. Multiple failed attempts for the same post in a row are counted only once. Every successful submission resets the counter. Users will be able to unlock locked account by requesting new password or asking admin for help; disabled accounts can be enabled by admin only.', 'wypiekacz'), 'http://wordpress.org/extend/plugins/user-locker/' ); ?> 1710 </td> 1711 </tr> 1712 1713 <tr> 1714 <th scope="row" style="text-align:right; vertical-align:top;"> 1715 1716 </th> 1717 <td> 1718 <?php 1719 if ( $this->has_user_locker ) { 1720 _e('User Locker 1.2+ is installed and active.', 'wypiekacz'); 1721 } else { 1722 _e('User Locker 1.2+ is not active. You need to install and activate it first.', 'wypiekacz'); 1723 } 1724 ?> 1725 </td> 1726 </tr> 1727 1728 <?php if ( $this->has_user_locker ): ?> 1729 1730 <tr> 1731 <th scope="row" style="text-align:right; vertical-align:top;"> 1732 <label for="wypiekacz_lock_account"><?php _e('Enable account locking/disabling:', 'wypiekacz'); ?></label> 1733 </th> 1734 <td> 1735 <input type="checkbox" id="wypiekacz_lock_account" name="wypiekacz_lock_account" value="yes" <?php checked( 1, get_option( 'wypiekacz_lock_account' ) ); ?> /> 1736 </td> 1737 </tr> 1738 1739 <tr> 1740 <th scope="row" style="text-align:right; vertical-align:top;"> 1741 <label for="wypiekacz_lock_account_after"><?php _e('Maximum allowed number of abandoned invalid posts:', 'wypiekacz'); ?></label> 1742 </th> 1743 <td> 1744 <input type="text" maxlength="4" size="10" id="wypiekacz_lock_account_after" name="wypiekacz_lock_account_after" value="<?php echo esc_attr( get_option( 'wypiekacz_lock_account_after' ) ); ?>" /><br /><?php _e('Multiple failed attempts for the same post in a row are counted only once. Every successful submission resets the counter.', 'wypiekacz'); ?> 1745 </td> 1746 </tr> 1747 1748 <tr> 1749 <th scope="row" style="text-align:right; vertical-align:top;"> 1750 <label for="wypiekacz_lock_method"><?php _e('Account lock method:', 'wypiekacz'); ?></label> 1751 </th> 1752 <td> 1753 <?php $wypiekacz_lock_method = get_option( 'wypiekacz_lock_method' ); ?> 1754 <select id="wypiekacz_lock_method" name="wypiekacz_lock_method"> 1755 <option value="0" <?php selected( $wypiekacz_lock_method, 0 ); ?>><?php _e('Lock', 'wypiekacz'); ?></option> 1756 <option value="1" <?php selected( $wypiekacz_lock_method, 1 ); ?>><?php _e('Disable', 'wypiekacz'); ?></option> 1757 </select><br /><?php _e('Users will be able to unlock locked account by requesting new password or asking admin for help. Disabled accounts can be enabled by admin only.', 'wypiekacz'); ?> 1758 </td> 1759 </tr> 1760 1761 <tr> 1762 <th scope="row" style="text-align:right; vertical-align:top;"> 1763 <label for="wypiekacz_lock_reason"><?php _e('Lock/Disable reason:', 'wypiekacz'); ?></label> 1764 </th> 1765 <td> 1766 <input type="text" maxlength="500" size="80" id="wypiekacz_lock_reason" name="wypiekacz_lock_reason" value="<?php echo esc_attr( get_option( 'wypiekacz_lock_reason' ) ); ?>" /> 1767 <br /><?php _e('Reason text can be displayed after unsuccessful login attempt, and on User List. Make sure you enabled appropriate options in User Locker settings.', 'wypiekacz'); ?> 1768 <br /><?php _e('Note: start text with \'@\' (AT sign) to keep it private.', 'wypiekacz'); ?> 1769 </td> 1770 </tr> 1771 1772 <tr> 1773 <th scope="row" style="text-align:right; vertical-align:top;"> 1774 <label for="wypiekacz_lock_show_details"><?php _e('Show details on User List:', 'wypiekacz'); ?></label> 1775 </th> 1776 <td> 1777 <input type="checkbox" id="wypiekacz_lock_show_details" name="wypiekacz_lock_show_details" value="yes" <?php checked( 1, get_option( 'wypiekacz_lock_show_details' ) ); ?> /> 1778 <br /><?php _e('Enable this option to add extra column to User List with Bad Posts count and last Post ID.', 'wypiekacz'); ?> 1779 </td> 1780 </tr> 1781 1782 <?php endif; /* if ( $this->has_user_locker ): */ ?> 1160 1783 1161 1784 </table> … … 1193 1816 } 1194 1817 1818 function sanitize_nonnegative_or_minus1( $value ) { 1819 $value = (int)$value; 1820 if ( $value < -1 ) { 1821 $value = -1; 1822 } 1823 return $value; 1824 } 1825 1826 function sanitize_positive( $value ) { 1827 $value = (int)$value; 1828 if ( $value <= 0 ) { 1829 $value = 1; 1830 } 1831 return $value; 1832 } 1833 1195 1834 function sanitize_stringlist( $value ) { 1196 1835 $value = explode( "\n", (string)$value ); … … 1232 1871 // Sanitize list of post types 1233 1872 function sanitize_post_types( $types ) { 1873 // For pre-WP 3.0 return predefined value - otherwise WP will save empty array when 1874 // options are updated, causing mysterious problem after upgrade to WP 3.0+. 1875 if ( !$this->has_wp_30 ) { 1876 return array( 'post' ); 1877 } 1878 1234 1879 $post_types = $this->get_post_types(); 1235 1880 $ret = array(); … … 1246 1891 add_option( 'wypiekacz_min_len', 1000 ); // Minimum post length (characters) 1247 1892 add_option( 'wypiekacz_min_len_words', 0 ); // Minimum post length (words) 1893 add_option( 'wypiekacz_min_links', 0 ); // Minimum links per post 1248 1894 add_option( 'wypiekacz_max_links', 3 ); // Maximum links per post 1895 add_option( 'wypiekacz_link_after', 0 ); // First link allowed after N characters 1896 add_option( 'wypiekacz_link_after_words', 0 ); // First link allowed after N words 1249 1897 add_option( 'wypiekacz_min_title_len', 5 ); // Minimum title length (characters) 1250 1898 add_option( 'wypiekacz_min_title_len_words', 0 ); // Minimum title length (words) … … 1262 1910 add_option( 'wypiekacz_pass_reset_email', 1 ); // Send notification of password resets to admin 1263 1911 add_option( 'wypiekacz_right_now_stats', 1 ); // Show number of Drafts and Pending Posts in Dashboard 1912 add_option( 'wypiekacz_post_menu_links', 1 ); // Add Drafts/Pending links to Posts menu 1264 1913 add_option( 'wypiekacz_badwords', array() ); // List of forbidden words 1265 1914 add_option( 'wypiekacz_check_badwords_title', 0 ); // Check for forbidden words in title 1266 1915 add_option( 'wypiekacz_check_badwords_content', 0 ); // Check for forbidden words in content 1916 add_option( 'wypiekacz_check_badwords_tags', 0 ); // Check for forbidden words in tags 1267 1917 add_option( 'wypiekacz_goodwords', array() ); // List of allowed words 1918 add_option( 'wypiekacz_post_thumbnail', 0 ); // Check post thumbnail 1268 1919 add_option( 'wypiekacz_enforce_links', 0 ); // Enforce max link count 1920 add_option( 'wypiekacz_enforce_link_positions', 0 ); // Enforce link positions 1269 1921 add_option( 'wypiekacz_enforce_title', 0 ); // Enforce max title length 1270 1922 add_option( 'wypiekacz_enforce_add_dots', 1 ); // Enforce max title length … … 1273 1925 add_option( 'wypiekacz_allow_skip_rules', 1 ); // Allow Editors and Administrators to skip rule check 1274 1926 add_option( 'wypiekacz_post_types', array( 'post' ) ); // List of post types supported by default 1927 add_option( 'wypiekacz_dont_save_invalid_post', 0 ); // Save post even it has not passed validation 1928 add_option( 'wypiekacz_autosave_interval', 60 ); // Post autosave interval (60 = default, 0 to disable (need special handling)) 1929 add_option( 'wypiekacz_post_revisions', -1 ); // Post revisions count (-1/true = default, 0/false to disable) 1930 add_option( 'wypiekacz_empty_trash_days', 30 ); // Empty trash days (30 = default, 0 to disable) 1931 add_option( 'wypiekacz_delete_orphaned_drafts', 0 ); // Delete orphaned_drafts interval (days, 0 = disable) 1932 add_option( 'wypiekacz_force_delete_orphaned_drafts', 0 ); // Force delete orphaned_drafts (otherwise they may end in Trash) 1933 add_option( 'wypiekacz_lock_account', 0 ); // Lock/disable user account when user submits too many invalid posts for review/publish and do not correct them 1934 add_option( 'wypiekacz_lock_account_after', 5 ); // How many invalid posts can be submitted before locking user 1935 add_option( 'wypiekacz_lock_method', 0 ); // 0 - lock account, 1 - disable account 1936 add_option( 'wypiekacz_lock_reason', '' ); // Lock reason 1937 add_option( 'wypiekacz_lock_show_details', 1 ); // Add extra column to User List with details 1275 1938 1276 1939 $wp_wypiekacz = new WyPiekacz(); 1940 // TODO: try to call this from 'init' hook (at this point user is authenticated), and do not enforce rules if checking is skipped for user or by option 1277 1941 $wp_wypiekacz->enforce_rules_POST(); 1278 1942 … … 1309 1973 } 1310 1974 1975 // Define some special defines 1976 if ( !defined( 'AUTOSAVE_INTERVAL' ) ) { // 60 = default 1977 $val = get_option( 'wypiekacz_autosave_interval' ); 1978 if ( $val == 0 ) { 1979 // Use some big value to make sure autosave will not start if autosave script will be loaded (should not be) 1980 $val = 999999999; 1981 } 1982 define( 'AUTOSAVE_INTERVAL', $val ); 1983 } 1984 1985 if ( !defined( 'WP_POST_REVISIONS' ) ) { // -1 = default 1986 $val = get_option( 'wypiekacz_post_revisions' ); 1987 define( 'WP_POST_REVISIONS', $val ); 1988 } 1989 1990 if ( !defined( 'EMPTY_TRASH_DAYS' ) ) { // 30 = default 1991 $val = get_option( 'wypiekacz_empty_trash_days' ); 1992 define( 'EMPTY_TRASH_DAYS', $val ); 1993 } 1994 1995 // Add functions from WP2.8 for previous WP versions 1996 if ( !function_exists( 'esc_html' ) ) { 1997 function esc_html( $text ) { 1998 return wp_specialchars( $text ); 1999 } 2000 } 2001 if ( !function_exists( 'esc_attr' ) ) { 2002 function esc_attr( $text ) { 2003 return attribute_escape( $text ); 2004 } 2005 } 2006 2007 // Add functions from WP2.9 for previous WP versions 2008 if ( !function_exists( 'wp_strip_all_tags' ) ) { 2009 function wp_strip_all_tags($string, $remove_breaks = false) { 2010 $string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string ); 2011 $string = strip_tags($string); 2012 2013 if ( $remove_breaks ) 2014 $string = preg_replace('/[\r\n\t ]+/', ' ', $string); 2015 2016 return trim($string); 2017 } 2018 } 2019 2020 // Add functions from WP3.1 for previous WP versions 2021 if ( !function_exists( 'esc_textarea' ) ) { 2022 function esc_textarea( $text ) { 2023 $safe_text = htmlspecialchars( $text, ENT_QUOTES ); 2024 return apply_filters( 'esc_textarea', $safe_text, $text ); 2025 } 2026 } 2027 1311 2028 } // END 1312 2029
Note: See TracChangeset
for help on using the changeset viewer.