Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Plugin: Rank Math - 404 Monitor
|
||||
* URL: https://rankmath.com/wordpress/plugin/seo-suite/
|
||||
* Name: 404-monitor.css
|
||||
*/.metabox-prefs legend+label{display:none}
|
@@ -0,0 +1 @@
|
||||
!function(){"use strict";var t,e={n:function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,{a:n}),n},d:function(t,n){for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},n=jQuery;(t=e.n(n)())((function(){var e=this;e.wrap=t(".rank-math-404-monitor-wrap"),e.wrap.on("click",".rank-math-404-delete",(function(e){e.preventDefault();var n=t(this),r=n.attr("href").replace("admin.php","admin-ajax.php").replace("action=delete","action=rank_math_delete_log").replace("page=","math=");t.ajax({url:r,type:"GET",success:function(e){e&&e.success&&n.closest("tr").fadeOut(800,(function(){t(this).remove()}))}})})),e.wrap.on("click",".rank-math-clear-logs",(function(e){if(e.preventDefault(),!confirm(rankMath.logConfirmClear))return!1;t(this).closest("form").append('<input type="hidden" name="action" value="clear_log">').submit()})),t("#doaction, #doaction2").on("click",(function(){"redirect"===t("#bulk-action-selector-top").val()&&t(this).closest("form").attr("action",rankMath.redirectionsUri)}))}))}();
|
@@ -0,0 +1,11 @@
|
||||
// compileCompressed: $1.css
|
||||
/*!
|
||||
* Plugin: Rank Math - 404 Monitor
|
||||
* URL: https://rankmath.com/wordpress/plugin/seo-suite/
|
||||
* Name: 404-monitor.css
|
||||
*/
|
||||
|
||||
|
||||
.metabox-prefs legend + label {
|
||||
display: none;
|
||||
}
|
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
/**
|
||||
* The admin-side code for the 404 Monitor module.
|
||||
*
|
||||
* @since 0.9.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Monitor;
|
||||
|
||||
use RankMath\KB;
|
||||
use RankMath\Helper;
|
||||
use RankMath\Module\Base;
|
||||
use RankMath\Admin\Page;
|
||||
use RankMath\Helpers\Arr;
|
||||
use RankMath\Helpers\Param;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Admin class.
|
||||
*/
|
||||
class Admin extends Base {
|
||||
|
||||
/**
|
||||
* Module directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $directory;
|
||||
|
||||
/**
|
||||
* WP_List_Table class name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $table;
|
||||
|
||||
/**
|
||||
* Screen options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $screen_options = [];
|
||||
|
||||
/**
|
||||
* Page object.
|
||||
*
|
||||
* @var Page
|
||||
*/
|
||||
public $page;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$directory = dirname( __FILE__ );
|
||||
$this->config(
|
||||
[
|
||||
'id' => '404-monitor',
|
||||
'directory' => $directory,
|
||||
'table' => 'RankMath\Monitor\Table',
|
||||
'screen_options' => [
|
||||
'id' => 'rank_math_404_monitor_per_page',
|
||||
'default' => 100,
|
||||
],
|
||||
]
|
||||
);
|
||||
parent::__construct();
|
||||
|
||||
if ( $this->page->is_current_page() ) {
|
||||
$this->action( 'init', 'init' );
|
||||
}
|
||||
|
||||
if ( Helper::has_cap( '404_monitor' ) ) {
|
||||
$this->filter( 'rank_math/settings/general', 'add_settings' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*/
|
||||
public function init() {
|
||||
$action = Helper::get_request_action();
|
||||
if ( false === $action || ! in_array( $action, [ 'delete', 'clear_log' ], true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! check_admin_referer( 'bulk-events' ) ) {
|
||||
check_admin_referer( '404_delete_log', 'security' );
|
||||
}
|
||||
|
||||
$action = 'do_' . $action;
|
||||
$this->$action();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete selected log.
|
||||
*/
|
||||
protected function do_delete() {
|
||||
$log = Param::request( 'log', '', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
||||
if ( empty( $log ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$count = DB::delete_log( $log );
|
||||
if ( $count > 0 ) {
|
||||
Helper::add_notification(
|
||||
/* translators: delete counter */
|
||||
sprintf( esc_html__( '%d log(s) deleted.', 'rank-math' ), $count ),
|
||||
[ 'type' => 'success' ]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all 404 logs, by truncating the log table.
|
||||
* Fired with the `$this->$action();` line inside the `init()` method.
|
||||
*/
|
||||
protected function do_clear_log() {
|
||||
$count = DB::get_count();
|
||||
DB::clear_logs();
|
||||
|
||||
Helper::add_notification(
|
||||
/* translators: delete counter */
|
||||
sprintf( esc_html__( 'Log cleared - %d items deleted.', 'rank-math' ), $count ),
|
||||
[ 'type' => 'success' ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the 404 Monitor admin page.
|
||||
*/
|
||||
public function register_admin_page() {
|
||||
|
||||
$dir = $this->directory . '/views/';
|
||||
$uri = untrailingslashit( plugin_dir_url( __FILE__ ) );
|
||||
|
||||
$this->page = new Page(
|
||||
'rank-math-404-monitor',
|
||||
esc_html__( '404 Monitor', 'rank-math' ),
|
||||
[
|
||||
'position' => 30,
|
||||
'parent' => 'rank-math',
|
||||
'capability' => 'rank_math_404_monitor',
|
||||
'render' => $dir . 'main.php',
|
||||
'help' => [
|
||||
'404-overview' => [
|
||||
'title' => esc_html__( 'Overview', 'rank-math' ),
|
||||
'view' => $dir . 'help-tab-overview.php',
|
||||
],
|
||||
'404-screen-content' => [
|
||||
'title' => esc_html__( 'Screen Content', 'rank-math' ),
|
||||
'view' => $dir . 'help-tab-screen-content.php',
|
||||
],
|
||||
'404-actions' => [
|
||||
'title' => esc_html__( 'Available Actions', 'rank-math' ),
|
||||
'view' => $dir . 'help-tab-actions.php',
|
||||
],
|
||||
'404-bulk' => [
|
||||
'title' => esc_html__( 'Bulk Actions', 'rank-math' ),
|
||||
'view' => $dir . 'help-tab-bulk.php',
|
||||
],
|
||||
],
|
||||
'assets' => [
|
||||
'styles' => [
|
||||
'rank-math-common' => '',
|
||||
'rank-math-404-monitor' => $uri . '/assets/css/404-monitor.css',
|
||||
],
|
||||
'scripts' => [ 'rank-math-404-monitor' => $uri . '/assets/js/404-monitor.js' ],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
if ( $this->page->is_current_page() ) {
|
||||
Helper::add_json( 'logConfirmClear', esc_html__( 'Are you sure you wish to delete all 404 error logs?', 'rank-math' ) );
|
||||
Helper::add_json( 'redirectionsUri', Helper::get_admin_url( 'redirections' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add module settings tab in the General Settings.
|
||||
*
|
||||
* @param array $tabs Array of option panel tabs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_settings( $tabs ) {
|
||||
|
||||
Arr::insert(
|
||||
$tabs,
|
||||
[
|
||||
'404-monitor' => [
|
||||
'icon' => 'rm-icon rm-icon-404',
|
||||
'title' => esc_html__( '404 Monitor', 'rank-math' ),
|
||||
/* translators: 1. Link to KB article 2. Link to redirection setting scree */
|
||||
'desc' => sprintf( esc_html__( 'Monitor broken pages that ruin user-experience and affect SEO. %s.', 'rank-math' ), '<a href="' . KB::get( '404-monitor-settings', 'Options Panel 404 Monitor Tab' ) . '" target="_blank">' . esc_html__( 'Learn more', 'rank-math' ) . '</a>' ),
|
||||
'file' => $this->directory . '/views/options.php',
|
||||
],
|
||||
],
|
||||
7
|
||||
);
|
||||
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output page title actions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function page_title_actions() {
|
||||
$actions = [
|
||||
'settings' => [
|
||||
'class' => 'page-title-action',
|
||||
'href' => Helper::get_admin_url( 'options-general#setting-panel-404-monitor' ),
|
||||
'label' => __( 'Settings', 'rank-math' ),
|
||||
],
|
||||
'learn_more' => [
|
||||
'class' => 'page-title-action',
|
||||
'href' => KB::get( '404-monitor', '404 Page Learn More Button' ),
|
||||
'label' => __( 'Learn More', 'rank-math' ),
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Filters the title actions available on the 404 Monitor page.
|
||||
*
|
||||
* @param array $actions Multidimensional array of actions to show.
|
||||
*/
|
||||
$actions = $this->do_filter( '404_monitor/page_title_actions', $actions );
|
||||
|
||||
foreach ( $actions as $action_name => $action ) {
|
||||
?>
|
||||
<a class="<?php echo esc_attr( $action['class'] ); ?> rank-math-404-monitor-<?php echo esc_attr( $action_name ); ?>" href="<?php echo esc_attr( $action['href'] ); ?>" target="_blank"><?php echo esc_attr( $action['label'] ); ?></a>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/**
|
||||
* The database operations for the 404 Monitor module.
|
||||
*
|
||||
* @since 0.9.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Monitor;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Admin\Database\Database;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* DB class.
|
||||
*/
|
||||
class DB {
|
||||
|
||||
/**
|
||||
* Get query builder.
|
||||
*
|
||||
* @return Query_Builder
|
||||
*/
|
||||
private static function table() {
|
||||
return Database::table( 'rank_math_404_logs' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error log items.
|
||||
*
|
||||
* @param array $args Array of arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_logs( $args ) {
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
[
|
||||
'orderby' => 'id',
|
||||
'order' => 'DESC',
|
||||
'limit' => 10,
|
||||
'paged' => 1,
|
||||
'search' => '',
|
||||
'ids' => [],
|
||||
'uri' => '',
|
||||
]
|
||||
);
|
||||
|
||||
$args = apply_filters( 'rank_math/404_monitor/get_logs_args', $args );
|
||||
|
||||
$table = self::table()->found_rows()->page( $args['paged'] - 1, $args['limit'] );
|
||||
|
||||
if ( ! empty( $args['search'] ) ) {
|
||||
$table->whereLike( 'uri', rawurlencode( $args['search'] ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['ids'] ) ) {
|
||||
$table->whereIn( 'id', (array) $args['ids'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['uri'] ) ) {
|
||||
$table->where( 'uri', $args['uri'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['orderby'] ) && in_array( $args['orderby'], [ 'id', 'uri', 'accessed', 'times_accessed' ], true ) ) {
|
||||
$table->orderBy( $args['orderby'], $args['order'] );
|
||||
}
|
||||
|
||||
return [
|
||||
'logs' => $table->get( ARRAY_A ),
|
||||
'count' => $table->get_found_rows(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a record.
|
||||
*
|
||||
* @param array $args Values to insert.
|
||||
*/
|
||||
public static function add( $args ) {
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
[
|
||||
'uri' => '',
|
||||
'accessed' => current_time( 'mysql' ),
|
||||
'times_accessed' => '1',
|
||||
'referer' => '',
|
||||
'user_agent' => '',
|
||||
]
|
||||
);
|
||||
|
||||
// Maybe delete logs if record exceed defined limit.
|
||||
$limit = absint( Helper::get_settings( 'general.404_monitor_limit' ) );
|
||||
if ( $limit && self::get_count() >= $limit ) {
|
||||
self::clear_logs();
|
||||
}
|
||||
|
||||
return self::table()->insert( $args, [ '%s', '%s', '%d', '%s', '%s', '%s' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a record.
|
||||
*
|
||||
* @param array $args Values to update.
|
||||
*/
|
||||
public static function update( $args ) {
|
||||
$row = self::table()->where( 'uri', $args['uri'] )->one( ARRAY_A );
|
||||
|
||||
if ( $row ) {
|
||||
return self::update_counter( $row );
|
||||
}
|
||||
|
||||
return self::add( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a record.
|
||||
*
|
||||
* @param array $ids Array of IDs to delete.
|
||||
*
|
||||
* @return int Number of records deleted.
|
||||
*/
|
||||
public static function delete_log( $ids ) {
|
||||
return self::table()->whereIn( 'id', (array) $ids )->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total number of log items (number of rows in the DB table).
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_count() {
|
||||
return self::table()->selectCount()->getVar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear logs completely.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function clear_logs() {
|
||||
return self::table()->truncate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stats for dashboard widget.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_stats() {
|
||||
return self::table()->selectCount( '*', 'total' )->selectSum( 'times_accessed', 'hits' )->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update if URL is matched and hit.
|
||||
*
|
||||
* @param object $row Record to update.
|
||||
*
|
||||
* @return int|false The number of rows updated, or false on error.
|
||||
*/
|
||||
private static function update_counter( $row ) {
|
||||
$update_data = [
|
||||
'accessed' => current_time( 'mysql' ),
|
||||
'times_accessed' => absint( $row['times_accessed'] ) + 1,
|
||||
];
|
||||
|
||||
return self::table()->set( $update_data )->where( 'id', absint( $row['id'] ) )->update();
|
||||
}
|
||||
}
|
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
/**
|
||||
* The 404 Monitor Module.
|
||||
*
|
||||
* @since 0.9.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Monitor;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Helpers\Str;
|
||||
use RankMath\Helpers\Param;
|
||||
use RankMath\Traits\Ajax;
|
||||
use RankMath\Traits\Hooker;
|
||||
use donatj\UserAgent\UserAgentParser;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Monitor class.
|
||||
*/
|
||||
class Monitor {
|
||||
|
||||
use Hooker, Ajax;
|
||||
|
||||
/**
|
||||
* Admin object.
|
||||
*
|
||||
* @var Admin
|
||||
*/
|
||||
public $admin;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( is_admin() ) {
|
||||
$this->admin = new Admin();
|
||||
}
|
||||
|
||||
if ( Helper::is_ajax() ) {
|
||||
$this->ajax( 'delete_log', 'delete_log' );
|
||||
}
|
||||
|
||||
if ( Helper::has_cap( '404_monitor' ) && Helper::is_rest() ) {
|
||||
$this->action( 'rank_math/dashboard/widget', 'dashboard_widget', 11 );
|
||||
}
|
||||
|
||||
$this->action( $this->get_hook(), 'capture_404' );
|
||||
|
||||
if ( Helper::has_cap( '404_monitor' ) ) {
|
||||
$this->action( 'rank_math/admin_bar/items', 'admin_bar_items', 11 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add stats in the admin dashboard widget.
|
||||
*/
|
||||
public function dashboard_widget() {
|
||||
$data = DB::get_stats();
|
||||
?>
|
||||
<h3>
|
||||
<?php esc_html_e( '404 Monitor', 'rank-math' ); ?>
|
||||
<a href="<?php echo esc_url( Helper::get_admin_url( '404-monitor' ) ); ?>" class="rank-math-view-report" title="<?php esc_html_e( 'View Report', 'rank-math' ); ?>"><i class="dashicons dashicons-chart-bar"></i></a>
|
||||
</h3>
|
||||
<div class="rank-math-dashboard-block">
|
||||
<div>
|
||||
<h4>
|
||||
<?php esc_html_e( 'Log Count', 'rank-math' ); ?>
|
||||
<span class="rank-math-tooltip"><em class="dashicons-before dashicons-editor-help"></em><span><?php esc_html_e( 'Total number of 404 pages opened by the users.', 'rank-math' ); ?></span></span>
|
||||
</h4>
|
||||
<strong class="text-large"><?php echo esc_html( Str::human_number( $data->total ) ); ?></strong>
|
||||
</div>
|
||||
<div>
|
||||
<h4>
|
||||
<?php esc_html_e( 'URL Hits', 'rank-math' ); ?>
|
||||
<span class="rank-math-tooltip"><em class="dashicons-before dashicons-editor-help"></em><span><?php esc_html_e( 'Total number visits received on all the 404 pages.', 'rank-math' ); ?></span></span>
|
||||
</h4>
|
||||
<strong class="text-large"><?php echo esc_html( Str::human_number( $data->hits ) ); ?></strong>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Add admin bar item.
|
||||
*
|
||||
* @param Admin_Bar_Menu $menu Menu class instance.
|
||||
*/
|
||||
public function admin_bar_items( $menu ) {
|
||||
$menu->add_sub_menu(
|
||||
'404-monitor',
|
||||
[
|
||||
'title' => esc_html__( '404 Monitor', 'rank-math' ),
|
||||
'href' => Helper::get_admin_url( '404-monitor' ),
|
||||
'meta' => [ 'title' => esc_html__( 'Review 404 errors on your site', 'rank-math' ) ],
|
||||
'priority' => 50,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a log item.
|
||||
*/
|
||||
public function delete_log() {
|
||||
|
||||
check_ajax_referer( '404_delete_log', 'security' );
|
||||
|
||||
$this->has_cap_ajax( '404_monitor' );
|
||||
|
||||
$id = Param::request( 'log' );
|
||||
if ( ! $id ) {
|
||||
$this->error( esc_html__( 'No valid id found.', 'rank-math' ) );
|
||||
}
|
||||
|
||||
DB::delete_log( $id );
|
||||
$this->success( esc_html__( 'Log item successfully deleted.', 'rank-math' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the request details when is_404() is true and WP's response code is *not* 410 or 451.
|
||||
*/
|
||||
public function capture_404() {
|
||||
if ( ! is_404() || in_array( http_response_code(), [ 410, 451 ], true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$uri = untrailingslashit( Helper::get_current_page_url( Helper::get_settings( 'general.404_monitor_ignore_query_parameters' ) ) );
|
||||
$uri = str_replace( Helper::get_home_url( '/' ), '', $uri );
|
||||
|
||||
// Check if excluded.
|
||||
if ( $this->is_url_excluded( $uri ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mode = simple.
|
||||
if ( 'simple' === Helper::get_settings( 'general.404_monitor_mode' ) ) {
|
||||
DB::update( [ 'uri' => $uri ] );
|
||||
return;
|
||||
}
|
||||
|
||||
// Mode = advanced.
|
||||
DB::add(
|
||||
[
|
||||
'uri' => $uri,
|
||||
'referer' => Param::server( 'HTTP_REFERER', '' ),
|
||||
'user_agent' => $this->get_user_agent(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if given URL is excluded.
|
||||
*
|
||||
* @param string $uri The URL to check for exclusion.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function is_url_excluded( $uri ) {
|
||||
$excludes = Helper::get_settings( 'general.404_monitor_exclude' );
|
||||
if ( ! is_array( $excludes ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $excludes as $rule ) {
|
||||
$rule['exclude'] = empty( $rule['exclude'] ) ? '' : $this->sanitize_exclude_pattern( $rule['exclude'], $rule['comparison'] );
|
||||
|
||||
if ( ! empty( $rule['exclude'] ) && Str::comparison( $rule['exclude'], $uri, $rule['comparison'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if regex pattern has delimiters or not, and add them if not.
|
||||
*
|
||||
* @param string $pattern The pattern to check.
|
||||
* @param string $comparison The comparison type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function sanitize_exclude_pattern( $pattern, $comparison ) {
|
||||
if ( 'regex' !== $comparison ) {
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
if ( preg_match( '[^(?:([^a-zA-Z0-9\\\\]).*\\1|\\(.*\\)|\\{.*\\}|\\[.*\\]|<.*>)[imsxADSUXJu]*$]', $pattern ) ) {
|
||||
return $pattern;
|
||||
}
|
||||
|
||||
return '[' . addslashes( $pattern ) . ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-agent header.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_user_agent() {
|
||||
$u_agent = Param::server( 'HTTP_USER_AGENT' );
|
||||
if ( empty( $u_agent ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$parsed = $this->parse_user_agent( $u_agent );
|
||||
$nice_ua = '';
|
||||
if ( ! empty( $parsed['browser'] ) ) {
|
||||
$nice_ua .= $parsed['browser'];
|
||||
}
|
||||
if ( ! empty( $parsed['version'] ) ) {
|
||||
$nice_ua .= ' ' . $parsed['version'];
|
||||
}
|
||||
|
||||
return $nice_ua . ' | ' . $u_agent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a user-agent string into its parts.
|
||||
*
|
||||
* @link https://github.com/donatj/PhpUserAgent
|
||||
*
|
||||
* @param string $u_agent User agent string to parse or null. Uses $_SERVER['HTTP_USER_AGENT'] on NULL.
|
||||
*
|
||||
* @return string[] an array with browser, version and platform keys
|
||||
*/
|
||||
private function parse_user_agent( $u_agent ) {
|
||||
if ( ! $u_agent ) {
|
||||
return [
|
||||
'platform' => null,
|
||||
'browser' => null,
|
||||
'version' => null,
|
||||
];
|
||||
}
|
||||
|
||||
$parser = new UserAgentParser();
|
||||
$agent = $parser->parse( $u_agent );
|
||||
|
||||
return [
|
||||
'platform' => $agent->platform(),
|
||||
'browser' => $agent->browser(),
|
||||
'version' => $agent->browserVersion(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the hook name depending on the theme.
|
||||
*
|
||||
* @return string WP hook.
|
||||
*/
|
||||
private function get_hook() {
|
||||
if ( defined( 'CT_VERSION' ) ) {
|
||||
return 'oxygen_enqueue_frontend_scripts';
|
||||
}
|
||||
|
||||
if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) {
|
||||
return 'wp_head';
|
||||
}
|
||||
|
||||
return 'get_header';
|
||||
}
|
||||
}
|
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
/**
|
||||
* The WP List Table class for the 404 Monitor module.
|
||||
*
|
||||
* @since 0.9.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Monitor;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Redirections\DB as RedirectionsDB;
|
||||
use RankMath\Redirections\Cache as RedirectionsCache;
|
||||
use RankMath\Admin\List_Table;
|
||||
use RankMath\Monitor\Admin;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Table class.
|
||||
*/
|
||||
class Table extends List_Table {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* The Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
[
|
||||
'screen' => Admin::get_screen(),
|
||||
'singular' => 'event',
|
||||
'plural' => 'events',
|
||||
'no_items' => esc_html__( 'The 404 error log is empty.', 'rank-math' ),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the list of items for displaying.
|
||||
*/
|
||||
public function prepare_items() {
|
||||
global $per_page;
|
||||
|
||||
$per_page = $this->get_items_per_page( 'rank_math_404_monitor_per_page', 100 );
|
||||
$search = $this->get_search();
|
||||
|
||||
$data = DB::get_logs(
|
||||
[
|
||||
'limit' => $per_page,
|
||||
'order' => $this->get_order(),
|
||||
'orderby' => $this->get_orderby( 'accessed' ),
|
||||
'paged' => $this->get_pagenum(),
|
||||
'search' => $search ? $search : '',
|
||||
]
|
||||
);
|
||||
|
||||
$this->items = $data['logs'];
|
||||
|
||||
foreach ( $this->items as $i => $item ) {
|
||||
$this->items[ $i ]['uri_decoded'] = urldecode( $item['uri'] );
|
||||
}
|
||||
|
||||
$this->set_pagination_args(
|
||||
[
|
||||
'total_items' => $data['count'],
|
||||
'per_page' => $per_page,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra controls to be displayed between bulk actions and pagination.
|
||||
*
|
||||
* @param string $which Where to show nav.
|
||||
*/
|
||||
protected function extra_tablenav( $which ) {
|
||||
if ( empty( $this->items ) ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="alignleft actions">
|
||||
<input type="button" class="button button-link-delete action rank-math-clear-logs" value="<?php esc_attr_e( 'Clear Log', 'rank-math' ); ?>">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the checkbox column output.
|
||||
*
|
||||
* @param object $item The current item.
|
||||
*/
|
||||
public function column_cb( $item ) {
|
||||
$out = sprintf( '<input type="checkbox" name="log[]" value="%s" />', $item['id'] );
|
||||
return $this->do_filter( '404_monitor/list_table_column', $out, $item, 'cb' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the URI column.
|
||||
*
|
||||
* @param object $item The current item.
|
||||
*/
|
||||
protected function column_uri( $item ) {
|
||||
$link = '<a href="' . esc_url( home_url( $item['uri'] ) ) . '" target="_blank" title="' . esc_attr__( 'View', 'rank-math' ) . '">' . esc_html( $item['uri_decoded'] ) . '</a>';
|
||||
$out = $link . $this->column_actions( $item );
|
||||
return $this->do_filter( '404_monitor/list_table_column', $out, $item, 'uri' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the referer column.
|
||||
*
|
||||
* @param object $item The current item.
|
||||
*/
|
||||
protected function column_referer( $item ) {
|
||||
$out = '<a href="' . esc_url( $item['referer'] ) . '" target="_blank">' . esc_html( $item['referer'] ) . '</a>';
|
||||
return $this->do_filter( '404_monitor/list_table_column', $out, $item, 'referer' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the default column output.
|
||||
*
|
||||
* @param object $item The current item.
|
||||
* @param string $column_name The current column name.
|
||||
*/
|
||||
public function column_default( $item, $column_name ) {
|
||||
$out = '';
|
||||
if ( in_array( $column_name, [ 'times_accessed', 'accessed', 'user_agent' ], true ) ) {
|
||||
$out = esc_html( $item[ $column_name ] );
|
||||
}
|
||||
|
||||
return $this->do_filter( '404_monitor/list_table_column', $out, $item, $column_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate row actions div.
|
||||
*
|
||||
* @param object $item The current item.
|
||||
*/
|
||||
public function column_actions( $item ) {
|
||||
$actions = [];
|
||||
|
||||
$actions['view'] = sprintf(
|
||||
'<a href="%s" target="_blank">' . esc_html__( 'View', 'rank-math' ) . '</a>',
|
||||
esc_url( home_url( $item['uri'] ) )
|
||||
);
|
||||
|
||||
if ( Helper::get_module( 'redirections' ) ) {
|
||||
$this->add_redirection_actions( $item, $actions );
|
||||
}
|
||||
|
||||
$actions['delete'] = sprintf(
|
||||
'<a href="%s" class="rank-math-404-delete">' . esc_html__( 'Delete', 'rank-math' ) . '</a>',
|
||||
Helper::get_admin_url(
|
||||
'404-monitor',
|
||||
[
|
||||
'action' => 'delete',
|
||||
'log' => $item['id'],
|
||||
'security' => wp_create_nonce( '404_delete_log' ),
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
return $this->row_actions( $actions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add redirection actions.
|
||||
*
|
||||
* @param object $item The current item.
|
||||
* @param array $actions Array of actions.
|
||||
*/
|
||||
private function add_redirection_actions( $item, &$actions ) {
|
||||
$redirection = RedirectionsCache::get_by_url( $item['uri_decoded'] );
|
||||
|
||||
if ( ! $redirection ) {
|
||||
$redirection = RedirectionsDB::match_redirections( $item['uri_decoded'] );
|
||||
}
|
||||
|
||||
if ( $redirection ) {
|
||||
$redirection_array = (array) $redirection;
|
||||
$url = esc_url(
|
||||
Helper::get_admin_url(
|
||||
'redirections',
|
||||
[
|
||||
'redirection' => isset( $redirection_array['redirection_id'] ) ? $redirection_array['redirection_id'] : $redirection_array['id'],
|
||||
'security' => wp_create_nonce( 'redirection_list_action' ),
|
||||
'action' => 'edit',
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$actions['view_redirection'] = sprintf( '<a href="%s" target="_blank">' . esc_html__( 'View Redirection', 'rank-math' ) . '</a>', $url );
|
||||
return;
|
||||
}
|
||||
|
||||
$url = esc_url(
|
||||
Helper::get_admin_url(
|
||||
'redirections',
|
||||
[
|
||||
'url' => $item['uri_decoded'],
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$actions['redirect'] = sprintf(
|
||||
'<a href="%1$s" class="rank-math-404-redirect-btn">%2$s</a>',
|
||||
$url,
|
||||
esc_html__( 'Redirect', 'rank-math' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
$columns = [
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'uri' => esc_html__( 'URI', 'rank-math' ),
|
||||
'referer' => esc_html__( 'Referer', 'rank-math' ),
|
||||
'user_agent' => esc_html__( 'User-Agent', 'rank-math' ),
|
||||
'times_accessed' => esc_html__( 'Hits', 'rank-math' ),
|
||||
'accessed' => esc_html__( 'Access Time', 'rank-math' ),
|
||||
];
|
||||
|
||||
$columns = $this->filter_columns( $columns );
|
||||
return $this->do_filter( '404_monitor/list_table_columns', $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter columns.
|
||||
*
|
||||
* @param array $columns Original columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function filter_columns( $columns ) {
|
||||
if ( 'simple' === Helper::get_settings( 'general.404_monitor_mode' ) ) {
|
||||
unset( $columns['referer'], $columns['user_agent'] );
|
||||
return $columns;
|
||||
}
|
||||
|
||||
unset( $columns['times_accessed'] );
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of sortable columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
$sortable = [
|
||||
'uri' => [ 'uri', false ],
|
||||
'times_accessed' => [ 'times_accessed', false ],
|
||||
'accessed' => [ 'accessed', false ],
|
||||
];
|
||||
|
||||
return $this->do_filter( '404_monitor/list_table_sortable_columns', $sortable );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an associative array ( option_name => option_title ) with the list
|
||||
* of bulk actions available on this table.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_bulk_actions() {
|
||||
$actions = [
|
||||
'redirect' => esc_html__( 'Redirect', 'rank-math' ),
|
||||
'delete' => esc_html__( 'Delete', 'rank-math' ),
|
||||
];
|
||||
|
||||
if ( ! Helper::get_module( 'redirections' ) ) {
|
||||
unset( $actions['redirect'] );
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
<?php // Silence is golden.
|
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* 404 Monitor inline help: "Available Actions" tab.
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'Hovering over a row in the list will display action links that allow you to manage the item. You can perform the following actions:', 'rank-math' ); ?>
|
||||
</p>
|
||||
<ul>
|
||||
<li><?php echo wp_kses_post( __( '<strong>View Details</strong> shows details about the 404 requests.', 'rank-math' ) ); ?></li>
|
||||
<li><?php echo wp_kses_post( __( '<strong>Redirect</strong> takes you to the Redirections manager to redirect the 404 URL.', 'rank-math' ) ); ?></li>
|
||||
<li><?php echo wp_kses_post( __( '<strong>Delete</strong> permanently removes the item from the list.', 'rank-math' ) ); ?></li>
|
||||
</ul>
|
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* 404 Monitor inline help: "Bulk Actions" tab.
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'You can also redirect or delete multiple items at once. Selecting multiple items to redirect allows you to redirect them to a single URL.', 'rank-math' ); ?>
|
||||
</p>
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* 404 Monitor inline help: "Overview" tab.
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
*/
|
||||
|
||||
use RankMath\KB;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
|
||||
<p>
|
||||
<?php esc_html_e( 'With the 404 monitor you can see where users and search engines are unable to find your content.', 'rank-math' ); ?>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<?php esc_html_e( 'Knowledge Base Articles:', 'rank-math' ); ?>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="<?php echo KB::get( '404-monitor', '404 Monitor Help Toggle' ); ?>" target="_blank">
|
||||
<?php esc_html_e( '404 Monitor', 'rank-math' ); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?php echo KB::get( '404-monitor-settings', '404 Monitor Help Toggle' ); ?>" target="_blank">
|
||||
<?php esc_html_e( '404 Monitor Settings', 'rank-math' ); ?>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?php echo KB::get( 'fix-404', '404 Monitor Help Toggle Fix link' ); ?>" target="_blank">
|
||||
<?php esc_html_e( 'Fix 404 Errors', 'rank-math' ); ?>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* 404 Monitor inline help: "Screen Content" tab.
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<p>
|
||||
<?php esc_html_e( 'You can customize the display of this screen\'s contents in a number of ways:', 'rank-math' ); ?>
|
||||
</p>
|
||||
<ul>
|
||||
<li><?php esc_html_e( 'You can hide/display columns based on your needs.', 'rank-math' ); ?></li>
|
||||
<li><?php esc_html_e( 'You can decide how many items to list per screen using the Screen Options tab.', 'rank-math' ); ?></li>
|
||||
<li><?php esc_html_e( 'You can search items using the search form at the top.', 'rank-math' ); ?></li>
|
||||
<li><?php esc_html_e( 'You can reorder the list by clicking on the column headings. ', 'rank-math' ); ?></li>
|
||||
</ul>
|
@@ -0,0 +1 @@
|
||||
<?php // Silence is golden.
|
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Main template for 404 monitor
|
||||
*
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
*/
|
||||
|
||||
use RankMath\Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$monitor = Helper::get_module( '404-monitor' )->admin;
|
||||
$monitor->table->prepare_items();
|
||||
?>
|
||||
<div class="wrap rank-math-404-monitor-wrap">
|
||||
|
||||
<h2>
|
||||
<?php echo esc_html( get_admin_page_title() ); ?>
|
||||
<?php $monitor->page_title_actions(); ?>
|
||||
</h2>
|
||||
|
||||
<?php \do_action( 'rank_math/404_monitor/before_list_table', $monitor ); ?>
|
||||
|
||||
<form method="get">
|
||||
<input type="hidden" name="page" value="rank-math-404-monitor">
|
||||
<?php $monitor->table->search_box( esc_html__( 'Search', 'rank-math' ), 's' ); ?>
|
||||
</form>
|
||||
<form method="post">
|
||||
<?php $monitor->table->display(); ?>
|
||||
</form>
|
||||
|
||||
</div>
|
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* 404 Monitor general settings.
|
||||
*
|
||||
* @since 0.9.0
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Monitor
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
use RankMath\Helper;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => '404_advanced_monitor',
|
||||
'type' => 'notice',
|
||||
'what' => 'error',
|
||||
'content' => esc_html__( 'If you have hundreds of 404 errors, your error log might increase quickly. Only choose this option if you have a very few 404s and are unable to replicate the 404 error on a particular URL from your end.', 'rank-math' ),
|
||||
'dep' => [ [ '404_monitor_mode', 'advanced' ] ],
|
||||
]
|
||||
);
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => '404_monitor_mode',
|
||||
'type' => 'radio_inline',
|
||||
'name' => esc_html__( 'Mode', 'rank-math' ),
|
||||
'desc' => esc_html__( 'The Simple mode only logs URI and access time, while the Advanced mode creates detailed logs including additional information such as the Referer URL.', 'rank-math' ),
|
||||
'options' => [
|
||||
'simple' => esc_html__( 'Simple', 'rank-math' ),
|
||||
'advanced' => esc_html__( 'Advanced', 'rank-math' ),
|
||||
],
|
||||
'default' => 'simple',
|
||||
]
|
||||
);
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => '404_monitor_limit',
|
||||
'type' => 'text',
|
||||
'name' => esc_html__( 'Log Limit', 'rank-math' ),
|
||||
'desc' => esc_html__( 'Sets the max number of rows in a log. Set to 0 to disable the limit.', 'rank-math' ),
|
||||
'default' => '100',
|
||||
'attributes' => [ 'type' => 'number' ],
|
||||
]
|
||||
);
|
||||
|
||||
$monitor_exclude = $cmb->add_field(
|
||||
[
|
||||
'id' => '404_monitor_exclude',
|
||||
'type' => 'group',
|
||||
'name' => esc_html__( 'Exclude Paths', 'rank-math' ),
|
||||
'desc' => esc_html__( 'Enter URIs or keywords you wish to prevent from getting logged by the 404 monitor.', 'rank-math' ),
|
||||
'options' => [
|
||||
'add_button' => esc_html__( 'Add another', 'rank-math' ),
|
||||
'remove_button' => esc_html__( 'Remove', 'rank-math' ),
|
||||
],
|
||||
'classes' => 'cmb-group-text-only',
|
||||
]
|
||||
);
|
||||
|
||||
$cmb->add_group_field(
|
||||
$monitor_exclude,
|
||||
[
|
||||
'id' => 'exclude',
|
||||
'type' => 'text',
|
||||
]
|
||||
);
|
||||
|
||||
$cmb->add_group_field(
|
||||
$monitor_exclude,
|
||||
[
|
||||
'id' => 'comparison',
|
||||
'type' => 'select',
|
||||
'options' => Helper::choices_comparison_types(),
|
||||
]
|
||||
);
|
||||
|
||||
$cmb->add_field(
|
||||
[
|
||||
'id' => '404_monitor_ignore_query_parameters',
|
||||
'type' => 'toggle',
|
||||
'name' => esc_html__( 'Ignore Query Parameters', 'rank-math' ),
|
||||
'desc' => esc_html__( 'Turn ON to ignore all query parameters (the part after a question mark in a URL) when logging 404 errors.', 'rank-math' ),
|
||||
'default' => 'off',
|
||||
]
|
||||
);
|
Reference in New Issue
Block a user