PluginProbe
RSFirewall! / trunk
RSFirewall! vtrunk
rsfirewall / models / exceptions.php

exceptions.php in RSFirewall! trunk, at models/exceptions.php

574 lines 21.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package RSFirewall!
4 * @copyright (c) 2018 RSJoomla!
5 * @link https://www.rsjoomla.com
6 * @license GNU General Public License http://www.gnu.org/licenses/gpl-3.0.en.html
7 */
8
9 if ( ! defined( 'WPINC' ) ) {
10 die;
11 }
12
13 class RSFirewall_Model_Exceptions extends RSFirewall_Post
14 {
15 /**
16 * Create a custom post type to hold the exceptions
17 */
18 public function init()
19 {
20 // Set UI labels for Custom Post Type
21 $labels = array(
22 'name' => _x( 'Exceptions', 'Post Type General Name', 'rsfirewall' ),
23 'singular_name' => _x( 'Exception', 'Post Type Singular Name', 'rsfirewall' ),
24 'menu_name' => esc_html__( 'Exception', 'rsfirewall' ),
25 'add_new' => esc_html__( 'Add New Exception', 'rsfirewall' ),
26 'add_new_item' => esc_html__( 'Add New Exception', 'rsfirewall' ),
27 'all_items' => esc_html__( 'All Exceptions', 'rsfirewall' ),
28 'view_item' => esc_html__( 'View Exception', 'rsfirewall' ),
29 'edit_item' => esc_html__( 'Edit Exception', 'rsfirewall' ),
30 'update_item' => esc_html__( 'Update Exception', 'rsfirewall' ),
31 'search_items' => esc_html__( 'Search Exception', 'rsfirewall' ),
32 'not_found' => esc_html__( 'Not Found', 'rsfirewall' ),
33 'not_found_in_trash' => esc_html__( 'Not found in Trash', 'rsfirewall' ),
34 );
35
36 // Set other options for Custom Post Type
37 $args = array(
38 'label' => esc_html__( 'Exceptions', 'rsfirewall' ),
39 'description' => esc_html__( 'Exceptions added on your website', 'rsfirewall' ),
40 'labels' => $labels,
41 'supports' => false,
42 'hierarchical' => false,
43 'show_ui' => true,
44 'show_in_menu' => false,
45 'show_in_nav_menus' => false,
46 'show_in_admin_bar' => true,
47 'menu_position' => 5,
48 'can_export' => true,
49 'has_archive' => true,
50 'exclude_from_search' => true,
51 'publicly_queryable' => false,
52 'rewrite' => array( "slug" => $this->prefix."exceptions" ),
53 'capabilities' => array(
54 'create_posts' => true,
55 'delete_posts' => true,
56 'delete_post' => true,
57 // Removes support for the "Add New" function ( use 'do_not_allow' instead of false for multisite set ups )
58 ),
59 'map_meta_cap' => true,
60 'register_meta_box_cb' => array( $this, 'add_metabox' )
61 );
62
63 // Registering your Custom Post Type
64 register_post_type( $this->prefix.'exceptions', $args );
65
66 // Show the current ip when adding
67 add_action( 'admin_notices', array($this, 'admin_notice') );
68
69 // Since we do not use the title or description, need to hide the body-content div
70 add_action( 'admin_head', array($this, 'remove_content_div') );
71
72 // Remove the publishing
73 add_action( 'admin_menu', array($this, 'remove_meta_box'));
74
75 // Remove the screen options to avoid selecting the slug box
76 add_filter('screen_options_show_screen', array($this, 'remove_screen_options'));
77
78 // Set the Layout column mode for the add/edit to 1 column
79 add_filter('get_user_option_screen_layout_'.$this->prefix.'exceptions', function (){return 1;} );
80
81 // Modify the search so that results are shown
82 add_filter('pre_get_posts', array($this, 'refine_query'));
83
84 // Modify the get_search_query for proper display
85 add_filter('get_search_query', array($this, 'get_search_query'));
86
87 // Modify the standard messages when updating/publishing
88 add_filter('post_updated_messages', array($this, 'updated_messages'));
89
90 if (function_exists('wp_untrash_post_set_previous_status'))
91 {
92 // When restoring a keep last post status
93 add_filter('wp_untrash_post_status', 'wp_untrash_post_set_previous_status', 10, 3);
94 }
95
96 // Add custom filters
97 add_action( 'restrict_manage_posts', array($this, 'add_filters') );
98 }
99
100 public function remove_meta_box() {
101 remove_meta_box( 'submitdiv', $this->prefix.'exceptions', 'side' );
102 }
103
104 public function enqueue_styles($pagenow) {
105 $screen_id = RSFirewall_Helper::get_current_screen();
106 if (($pagenow != 'post-new.php' || $pagenow != 'post.php') && $screen_id != $this->prefix.'exceptions') {
107 return;
108 }
109
110 wp_enqueue_style( 'switchery', RSFIREWALL_URL . 'assets/js/vendors/switchery.min.css', array(), $this->version, 'all' );
111 }
112
113 public function enqueue_scripts($pagenow) {
114 $screen_id = RSFirewall_Helper::get_current_screen();
115
116 if (($pagenow != 'post-new.php' || $pagenow != 'post.php') && $screen_id != $this->prefix.'exceptions') {
117 return;
118 }
119
120 wp_enqueue_script('switchery', RSFIREWALL_URL . 'assets/js/vendors/switchery.min.js', array('jquery'), $this->version, false);
121 }
122
123 public function remove_content_div(){
124 global $pagenow, $typenow;
125 if (($pagenow == 'post-new.php' || $pagenow == 'post.php') && $typenow == $this->prefix.'exceptions') {
126 echo '<style type="text/css"> #post-body-content { display:none; }</style>';
127 }
128 }
129
130 public function remove_screen_options($options) {
131 global $pagenow, $typenow;
132 if (($pagenow == 'post-new.php' || $pagenow == 'post.php') && $typenow == $this->prefix.'exceptions') {
133 return false;
134 }
135
136 return $options;
137 }
138
139 /**
140 * Function used in the filter of changing the messages
141 */
142 public function updated_messages($messages) {
143 $messages['exceptions'] = $messages['post'];
144
145 $messages['exceptions'][1] = __('The Exception has been updated!', 'rsfirewall');
146 $messages['exceptions'][4] = __('The Exception has been updated!', 'rsfirewall');
147 $messages['exceptions'][6] = __('The Exception has been added!', 'rsfirewall');
148
149 return $messages;
150 }
151
152 /**
153 * Function to add the filters
154 */
155 function add_filters(){
156 global $pagenow, $typenow;
157
158 if ($pagenow == 'edit.php' && $typenow == $this->prefix.'exceptions') {
159 $filters = array(
160 'exception_type' => array(
161 esc_attr__('Select Type', 'rsfirewall') => 'all',
162 esc_attr__('User Agent', 'rsfirewall') => 'ua',
163 esc_attr__('URL', 'rsfirewall') => 'url',
164 esc_attr__('Plugin', 'rsfirewall') => 'plug',
165 )
166 );
167
168 foreach ($filters as $filter => $options) {
169 ?>
170 <select name="rsf_filter[<?php echo esc_attr($filter);?>]">
171 <?php
172 $current_v = (isset($_GET['rsf_filter']) && isset($_GET['rsf_filter'][$filter])) ? $_GET['rsf_filter'][$filter] : '';
173 foreach ($options as $label => $value) {
174 printf
175 (
176 '<option value="%s"%s>%s</option>',
177 $value,
178 $value == $current_v ? ' selected="selected"' : '',
179 $label
180 );
181 }
182 ?>
183 </select>
184 <?php
185 }
186 }
187 }
188
189 /**
190 * Function used for handling the
191 */
192 public function refine_query($query) {
193 global $pagenow, $typenow;
194
195 if ($pagenow == 'edit.php' && $typenow == $this->prefix.'exceptions') {
196 $custom_fields = array(
197 "rsfirewall_match",
198 "rsfirewall_reason"
199 );
200 // Handle the search term
201 $searchterm = $query->query_vars['s'];
202
203 // unset the 's' value from the query, because we do not need it anymore and interferes with our query
204 $query->query_vars['s'] = "";
205
206 $meta_query_search = array('relation' => 'OR');
207 if (strlen($searchterm) != 0) {
208 foreach($custom_fields as $cf) {
209 array_push($meta_query_search, array(
210 'key' => $cf,
211 'value' => esc_sql($searchterm),
212 'compare' => 'LIKE'
213 ));
214 }
215 };
216
217 // Handle our own filter values
218 $meta_query_filters = array('relation' => 'AND');
219 if (isset($_GET['rsf_filter']) && !empty($_GET['rsf_filter'])) {
220 foreach ($_GET['rsf_filter'] as $field => $value){
221 // in case the default value of a filter is set to 'all'
222 if ($value == 'all') {
223 continue;
224 }
225
226 array_push($meta_query_filters, array(
227 'key' => 'rsfirewall_' . esc_sql($field),
228 'value' => esc_sql($value),
229 'compare' => '='
230 ));
231
232 }
233 }
234
235 $is_search = count($meta_query_search) > 1 ? 1 : 0;
236 $is_filters = count($meta_query_filters) > 1 ? 3 : 0;
237
238 $meta_query = array();
239 switch ($combine = ($is_search + $is_filters)) {
240 // when only the search is used
241 case 1:
242 $meta_query = $meta_query_search;
243 break;
244
245 // when only the filters are used
246 case 3:
247 $meta_query = $meta_query_filters;
248 break;
249
250 // when both filters and search are used
251 case 4:
252 array_push($meta_query_filters, $meta_query_search);
253 $meta_query = $meta_query_filters;
254 break;
255 }
256
257 if (!empty($meta_query)) {
258 $query->set('meta_query', $meta_query);
259 }
260 }
261 }
262
263 /**
264 * Function used for handling the text of the query that is outputed in the "Search results for" statement
265 */
266 public function get_search_query($search_term) {
267 global $pagenow, $typenow;
268
269 if ($pagenow == 'edit.php' && $typenow == $this->prefix.'exceptions') {
270 // Empty the search term in case there is a value
271 $search_term = '';
272
273 if (isset($_GET['s']) && !empty($_GET['s'])) {
274 $search_term = esc_attr($_GET['s']);
275 }
276 }
277
278 return $search_term;
279 }
280
281 /**
282 * Build the proper metabox
283 */
284 public function add_metabox() {
285 add_meta_box( 'rsfirewall_exceptions_metaboxes', esc_html__( 'Exception', 'rsfirewall' ), array(
286 $this,
287 'show_metabox'
288 ), $this->prefix.'exceptions', 'normal', 'default' );
289
290 // Publish metabox
291 add_meta_box( 'rsfirewall_submitdiv', __( 'Publish', 'rsfirewall' ), array($this, 'show_metabox_publish'), $this->prefix.'exceptions', 'normal', 'core' );
292 }
293
294 /**
295 * Actual Content of the metabox
296 */
297 public function show_metabox() {
298 global $post;
299 ?>
300 <table class="form-table">
301 <?php
302 foreach ( $this->form->section->field as $field ) {
303 $callback = array( 'RSFirewall_Helper_Fields', (string) $field->attributes()->type );
304 $args = array(
305 'field' => $field,
306 'section' => (string) $this->form->section->attributes()->name,
307 'value' => metadata_exists( 'post', $post->ID, (string) $field->attributes()->name ) ? get_post_meta( $post->ID, (string) $field->attributes()->name, true ) : (string) $field->attributes()->default
308 );
309
310 if ( is_callable( $callback ) ) {
311 ?>
312 <tr>
313 <th scope="row"><?php echo RSFirewall_Helper_Fields::label_for($field); ?></th>
314 <td><?php call_user_func( $callback, $args ); ?></td>
315 </tr>
316 <?php
317 }
318 }
319 ?>
320 </table>
321 <?php
322 }
323
324 /**
325 * Actual Content of the publish metabox
326 */
327 public function show_metabox_publish() {
328 global $post;
329
330 $post_type = $post->post_type;
331 $post_type_object = get_post_type_object($post_type);
332 $can_publish = current_user_can($post_type_object->cap->publish_posts);
333 $back_url = admin_url( 'edit.php?post_type='.$this->prefix.'exceptions');
334
335 ?>
336 <div id="back-action" style="float:left;">
337 <a class="button button-primary" href="<?php echo $back_url; ?>"><?php echo __('Back to the list', 'rsfirewall'); ?></a>
338 </div>
339
340 <div id="publishing-action">
341 <?php if ( !in_array( $post->post_status, array('publish', 'future', 'private') ) || 0 == $post->ID ) {
342 // We will only use the publish action
343 if ( $can_publish ) { ?>
344 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish') ?>"/>
345 <?php submit_button(__('Publish'), 'primary large', 'publish', false); ?>
346 <?php } else { ?>
347 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review') ?>"/>
348 <?php submit_button(__('Submit for Review'), 'primary large', 'publish', false); ?>
349 <?php
350 }
351 } else { ?>
352 <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Update') ?>" />
353 <input name="save" type="submit" class="button button-primary button-large" id="publish" value="<?php esc_attr_e( 'Update' ) ?>" />
354 <?php } ?>
355 </div>
356 <div id="delete-action" style="float:right; margin-right:50px">
357 <?php
358 if ( current_user_can( "delete_post", $post->ID ) ) {
359 if ( !EMPTY_TRASH_DAYS )
360 $delete_text = __('Delete Permanently', 'rsfirewall');
361 else
362 $delete_text = __('Move to Trash', 'rsfirewall');
363 ?>
364 <a class="submitdelete deletion" href="<?php echo get_delete_post_link($post->ID); ?>"><?php echo $delete_text; ?></a><?php
365 }
366 ?>
367 </div>
368 <div class="clear"></div>
369 <?php
370 }
371
372 /**
373 * Display bulk actions.
374 *
375 * @param $actions
376 *
377 * @return array
378 */
379 public function bulk_actions($actions)
380 {
381 // Remove the edit action
382 if (isset($actions['edit'])) {
383 unset($actions['edit']);
384 }
385
386 return $actions;
387 }
388
389 /**
390 * Save post.
391 *
392 * @param $post_id
393 * @param $post
394 *
395 * @return int|void
396 */
397 public function save( $post_id, $post ) {
398 if (isset($_POST['data'])) {
399 $is_update = $this->check_if_update($post);
400
401 if (strlen($_POST['data']['rsfirewall_match'])) {
402 parent::save($post_id, $post);
403 } else {
404 // If the Match field is empty show this error
405 $this->set_message(__('You must enter a Match!', 'rsfirewall'));
406
407 if (!$is_update) {
408 // Get and delete other auto-saves/revisions if any
409 if ($revisions = wp_get_post_revisions($post_id)) {
410 foreach($revisions as $rev_post) {
411 wp_delete_post($rev_post->ID);
412 }
413 }
414
415 // Finally delete the post itself
416 wp_delete_post($post->ID);
417
418 // Redirect to the form
419 wp_redirect( wp_get_referer() );
420 exit();
421 } else {
422 wp_redirect(get_edit_post_link($post_id, 'url'));
423 exit();
424 }
425 }
426 }
427 }
428
429 /**
430 * Function to check if the post is an update or an insert.
431 */
432 protected function check_if_update($post){
433 return strtotime($post->post_date_gmt) != strtotime($post->post_modified_gmt);
434 }
435
436 /**
437 * Add Columns to the Threat Tables
438 *
439 * @param $columns
440 *
441 * @return array
442 */
443 public function columns( $columns ) {
444 $columns = array(
445 'cb' => '<input type="checkbox" />',
446 'date' => esc_html__( 'Date Added', 'rsfirewall' ),
447 'rsfirewall_match' => esc_html__( 'Match', 'rsfirewall' ),
448 'rsfirewall_reason' => esc_html__( 'Reason', 'rsfirewall' ),
449 'rsfirewall_exception_type' => esc_html__( 'Exception Type', 'rsfirewall' ),
450 'actions' => esc_html__( 'Change Status', 'rsfirewall' )
451 );
452
453 return $columns;
454 }
455
456 /**
457 * Display data in the backend table
458 *
459 * @param $column
460 * @param $post_id
461 */
462 public function column( $column, $post_id ) {
463 $value = get_post_meta( $post_id, $column, true );
464
465 switch ( $column ) {
466 case 'rsfirewall_match':
467 $value = '<a href="'.get_edit_post_link(($post_id)).'">'.esc_html($value).'</a>';
468 break;
469
470 case 'rsfirewall_exception_type':
471 if ( $value == 'ua' ) {
472 $value = esc_html__( 'User Agent', 'rsfirewall' );
473 } else if ($value == 'url') {
474 $value = esc_html__( 'Url', 'rsfirewall' );
475 } else if ($value == 'plug') {
476 $value = esc_html__( 'Plugin', 'rsfirewall' );
477 }
478 break;
479
480 case 'rsfirewall_reason':
481 $value = esc_html($value);
482 break;
483
484 case 'actions':
485 if ($status = get_post_status($post_id)) {
486 $edit_url = admin_url( 'edit.php?post_type='.$this->prefix.'exceptions');
487 if ($status == 'publish' || $status == 'trash') {
488 $value = '<a href="' . wp_nonce_url($edit_url, 'rsfirewall', 'rsf-actions') . '&handler=exceptions&task=change_status&id=' . $post_id . '" class="rsfirewall-btn' . ($status == 'publish' ? ' danger' : '') . ' small" type="button" id="rsf-list-status" data-pid="' . $post_id . '">' . __(($status == 'publish' ? 'Add to trash' : 'Publish'), 'rsfirewall') . '</a>';
489 }
490 else if ($status == 'draft')
491 {
492 $value = '<a href="' . wp_nonce_url($edit_url, 'rsfirewall', 'rsf-actions') . '&handler=exceptions&task=change_status&id=' . $post_id . '" class="rsfirewall-btn small" type="button" id="rsf-list-status" data-pid="' . $post_id . '">'.__('Publish', 'rsfirewall').'</a>';
493 }
494 else
495 {
496 $value = __($status, 'rsfirewall');
497 }
498 }
499 break;
500 }
501 if ( ! empty( $value ) ) {
502 echo $value;
503 }
504 }
505
506 /**
507 * Function to change the current status of the selected post
508 */
509 public function change_status() {
510 $post_id = (int) (isset($_GET['id']) ? $_GET['id'] : 0);
511 $back_url = wp_get_referer();
512
513 $change_status = true;
514 // Check if the id is not empty (0)
515 if (empty($post_id)) {
516 $this->set_message(__('The post id is not correct!', 'rsfirewall'));
517 $change_status = false;
518 }
519
520 // Check if the id is available
521 if (!get_post_status($post_id)) {
522 $this->set_message(__('This post does not exist!', 'rsfirewall'));
523 $change_status = false;
524 }
525
526 // change post status
527 if ($change_status ) {
528 $current_status = get_post_status($post_id);
529 $new_status = $current_status == 'publish' ? 'trash' : 'publish';
530
531 if ($new_status == 'trash')
532 {
533 wp_trash_post($post_id);
534 }
535 else
536 {
537 wp_update_post(array('ID' => $post_id, 'post_status' => $new_status));
538 }
539 }
540
541 // Redirect to the list
542 RSFirewall_Helper::redirect($back_url);
543 }
544
545 /**
546 * Make columns sortable
547 *
548 * @param $columns
549 *
550 * @return mixed
551 */
552 public function sortable_columns( $columns ) {
553 $columns['rsfirewall_match'] = 'rsfirewall_match';
554 $columns['rsfirewall_reason'] = 'rsfirewall_reason';
555 $columns['rsfirewall_exception_type'] = 'rsfirewall_exception_type';
556
557 return $columns;
558 }
559
560 /**
561 * Function to display notices
562 */
563 public function admin_notice() {
564 $screen_id = RSFirewall_Helper::get_current_screen();
565
566 if ($screen_id == $this->prefix.'exceptions') {
567 ?>
568 <div class="notice notice-warning is-dismissible">
569 <p><?php echo wp_kses_post(__('Your IP address is currently detected as '.RSFirewall_Helper::get_ip().'.', 'rsfirewall')); ?></p>
570 </div>
571 <?php
572 }
573 }
574 }