From 402cf8872b072c4983083012b4473f1f78054792 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 16 Jan 2017 19:01:40 -0600 Subject: [PATCH 01/15] logging by route, initial commit --- ...class-wp-rest-api-log-admin-list-table.php | 1 - includes/class-wp-rest-api-log-filters.php | 22 +++++++++++++ tests/test-filters.php | 33 +++++++++++++++++++ wp-rest-api-log.php | 10 ++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 includes/class-wp-rest-api-log-filters.php create mode 100644 tests/test-filters.php diff --git a/admin/class-wp-rest-api-log-admin-list-table.php b/admin/class-wp-rest-api-log-admin-list-table.php index 8ba20d3..c52261e 100644 --- a/admin/class-wp-rest-api-log-admin-list-table.php +++ b/admin/class-wp-rest-api-log-admin-list-table.php @@ -28,7 +28,6 @@ public function admin_init() { add_action( 'restrict_manage_posts', array( $this, 'add_method_dropdown' ) ); add_action( 'restrict_manage_posts', array( $this, 'add_status_dropdown' ) ); add_action( 'restrict_manage_posts', array( $this, 'add_source_dropdown' ) ); - } diff --git a/includes/class-wp-rest-api-log-filters.php b/includes/class-wp-rest-api-log-filters.php new file mode 100644 index 0000000..56c1e03 --- /dev/null +++ b/includes/class-wp-rest-api-log-filters.php @@ -0,0 +1,22 @@ +assertEquals( '^/wp/v2/?$', $route_regex ); + + // Wildcard matches. + $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/*/' ); + $this->assertEquals( '^/wp/.*/?$', $route_regex ); + + $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/*' ); + $this->assertEquals( '^/wp/v2/.*', $route_regex ); + + } + + public function test_should_log_route() { + + } + +} diff --git a/wp-rest-api-log.php b/wp-rest-api-log.php index 3d5d8d5..ab18c35 100644 --- a/wp-rest-api-log.php +++ b/wp-rest-api-log.php @@ -24,6 +24,14 @@ define( 'WP_REST_API_LOG_PATH', trailingslashit( plugin_dir_path( __FILE__ ) ) ); } +if ( ! defined( 'WP_REST_API_LOG_FILE' ) ) { + define( 'WP_REST_API_LOG_FILE', __FILE__ ); +} + +if ( ! defined( 'WP_REST_API_LOG_BASENAME' ) ) { + define( 'WP_REST_API_LOG_BASENAME', plugin_basename( WP_REST_API_LOG_FILE ) ); +} + $plugin_class_file = 'wp-rest-api-log'; $includes = array( @@ -40,6 +48,7 @@ 'includes/class-' . $plugin_class_file . '-delete-response.php', 'includes/class-' . $plugin_class_file . '-routes-response.php', 'includes/class-' . $plugin_class_file . '-elasticpress.php', + 'includes/class-' . $plugin_class_file . '-filters.php', 'includes/class-' . $plugin_class_file . '.php', 'includes/settings/class-' . $plugin_class_file . '-settings-base.php', 'includes/settings/class-' . $plugin_class_file . '-settings-general.php', @@ -59,6 +68,7 @@ $class_base . '_Post_Type', $class_base . '_i18n', $class_base . '_Controller', + $class_base . '_Filters', $class_base . '', $class_base . '_Admin', $class_base . '_Admin_List_Table', From e99d8139243e5eced6bf8d2ee2577bfe5fed8872 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 16 Jan 2017 19:10:52 -0600 Subject: [PATCH 02/15] Added route_to_regex() and tests --- includes/class-wp-rest-api-log-filters.php | 12 ++++++++++++ tests/test-filters.php | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/includes/class-wp-rest-api-log-filters.php b/includes/class-wp-rest-api-log-filters.php index 56c1e03..2a29483 100644 --- a/includes/class-wp-rest-api-log-filters.php +++ b/includes/class-wp-rest-api-log-filters.php @@ -13,9 +13,21 @@ class WP_REST_API_Log_Filters { */ public static function route_to_regex( $route_filter ) { + if ( ! empty( $route_filter ) ) { + // Replace wildcard characters with regex. + $route_filter = str_replace( '*', '.*', $route_filter ); + // Add a trailing slash if it doesn't end with one. + if ( '/' !== substr( $route_filter, strlen( $route_filter ) - 1 ) ) { + $route_filter .= '/'; + } + // Add a zero or one match for the trailing slash. + $route_filter .= '?'; + // Add regex start and end params. + $route_filter = '^' . $route_filter . '$'; + } return $route_filter; } diff --git a/tests/test-filters.php b/tests/test-filters.php index fcb2093..36a7b82 100644 --- a/tests/test-filters.php +++ b/tests/test-filters.php @@ -22,12 +22,12 @@ public function test_convert_route_filter() { $this->assertEquals( '^/wp/.*/?$', $route_regex ); $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/*' ); - $this->assertEquals( '^/wp/v2/.*', $route_regex ); + $this->assertEquals( '^/wp/v2/.*/?$', $route_regex ); } public function test_should_log_route() { - + } } From dffe467eb6ac3387e452cac59bec869772dd7893 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 16 Jan 2017 19:29:39 -0600 Subject: [PATCH 03/15] refactored regex code --- includes/class-wp-rest-api-log-filters.php | 30 ++++++++++++++-------- tests/test-filters.php | 9 ++++++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/includes/class-wp-rest-api-log-filters.php b/includes/class-wp-rest-api-log-filters.php index 2a29483..d9e7220 100644 --- a/includes/class-wp-rest-api-log-filters.php +++ b/includes/class-wp-rest-api-log-filters.php @@ -14,19 +14,29 @@ class WP_REST_API_Log_Filters { public static function route_to_regex( $route_filter ) { if ( ! empty( $route_filter ) ) { - // Replace wildcard characters with regex. - $route_filter = str_replace( '*', '.*', $route_filter ); - // Add a trailing slash if it doesn't end with one. - if ( '/' !== substr( $route_filter, strlen( $route_filter ) - 1 ) ) { - $route_filter .= '/'; - } + // If it starts with a carat, treat it as regex and + // make no changes. + if ( '^' === substr( $route_filter, 0, 1 ) ) { + return $route_filter; + } else { + + // Replace wildcard with regex wildcard. + $route_filter = str_replace( '*', '.*', $route_filter ); + + // Add the start of the match. + $route_filter = '^' . $route_filter; - // Add a zero or one match for the trailing slash. - $route_filter .= '?'; + // Add a trailing slash. + $route_filter = trailingslashit( $route_filter ); + + // Add a flag for zero or one trailing slashes. + $route_filter .= '?'; + + // Add the end of the match. + $route_filter .= '$'; + } - // Add regex start and end params. - $route_filter = '^' . $route_filter . '$'; } return $route_filter; diff --git a/tests/test-filters.php b/tests/test-filters.php index 36a7b82..bfdb780 100644 --- a/tests/test-filters.php +++ b/tests/test-filters.php @@ -13,7 +13,7 @@ class WP_REST_API_Log_Test_Filters extends WP_UnitTestCase { public function test_convert_route_filter() { - // Exact match. + // Just a path, adds start and end. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/' ); $this->assertEquals( '^/wp/v2/?$', $route_regex ); @@ -24,6 +24,13 @@ public function test_convert_route_filter() { $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/*' ); $this->assertEquals( '^/wp/v2/.*/?$', $route_regex ); + // Regex should have no changes. + $route_regex = WP_REST_API_Log_Filters::route_to_regex( '^/wp/v2/.*' ); + $this->assertEquals( '^/wp/v2/.*', $route_regex ); + + // This is not treated as regex, so it get mangled. + $route_regex = WP_REST_API_Log_Filters::route_to_regex( '.*/wp/v2/$' ); + $this->assertEquals( '^..*/wp/v2/$/?$', $route_regex ); } public function test_should_log_route() { From f38291c302203296ef4cdf1028237421f90fc856 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 16 Jan 2017 20:09:37 -0600 Subject: [PATCH 04/15] initial work on settings page for route filters --- includes/class-wp-rest-api-log-common.php | 2 +- includes/class-wp-rest-api-log-filters.php | 21 ++++++ .../class-wp-rest-api-log-settings-base.php | 21 ++++-- ...class-wp-rest-api-log-settings-general.php | 8 +-- .../class-wp-rest-api-log-settings-routes.php | 68 ++++++++++++++++++- tests/test-filters.php | 9 +++ 6 files changed, 117 insertions(+), 12 deletions(-) diff --git a/includes/class-wp-rest-api-log-common.php b/includes/class-wp-rest-api-log-common.php index 211ee36..84e1d83 100644 --- a/includes/class-wp-rest-api-log-common.php +++ b/includes/class-wp-rest-api-log-common.php @@ -7,7 +7,7 @@ class WP_REST_API_Log_Common { const PLUGIN_NAME = 'wp-rest-api-log'; - const VERSION = '2016-12-05-01'; + const VERSION = '2017-01-16-01'; const TEXT_DOMAIN = 'wp-rest-api-log'; diff --git a/includes/class-wp-rest-api-log-filters.php b/includes/class-wp-rest-api-log-filters.php index d9e7220..052331c 100644 --- a/includes/class-wp-rest-api-log-filters.php +++ b/includes/class-wp-rest-api-log-filters.php @@ -4,6 +4,19 @@ class WP_REST_API_Log_Filters { + /** + * Returns a list of filtering modes. + * + * @return array + */ + static public function filter_modes() { + return array( + '' => __( 'All', 'wp-rest-api-log' ), + 'log_matches' => __( 'Only Matching Filters', 'wp-rest-api-log' ), + 'exclude_matches' => __( 'Exclude Matching Filters', 'wp-rest-api-log' ), + ); + } + /** * Converts a route filter into regex pattern. @@ -41,4 +54,12 @@ public static function route_to_regex( $route_filter ) { return $route_filter; } + + static public function can_log_route( $route ) { + + // Get the filter mode. + + // Get the route filters. + + } } diff --git a/includes/settings/class-wp-rest-api-log-settings-base.php b/includes/settings/class-wp-rest-api-log-settings-base.php index 012ff7b..70477ec 100644 --- a/includes/settings/class-wp-rest-api-log-settings-base.php +++ b/includes/settings/class-wp-rest-api-log-settings-base.php @@ -182,24 +182,35 @@ static public function settings_check_radio_list( $args ) { static public function settings_textarea( $args ) { - extract( wp_parse_args( $args, + $args = wp_parse_args( $args, array( 'name' => '', 'key' => '', 'rows' => 10, 'cols' => 40, 'after' => '', - ) - ) ); + ) + ); + + $name = $args['name']; + $key = $args['key']; + $rows = $args['rows']; + $cols = $args['cols']; + $after = $args['after']; $option = get_option( $key ); $value = isset( $option[$name] ) ? esc_attr( $option[$name] ) : ''; - echo "
"; + printf( '
', + esc_attr( $name ), + esc_attr( "{$key}[{$name}]" ), + esc_attr( $rows ), + esc_attr( $cols ), + $value + ); self::output_after( $after ); - } diff --git a/includes/settings/class-wp-rest-api-log-settings-general.php b/includes/settings/class-wp-rest-api-log-settings-general.php index b8455ad..f672fad 100644 --- a/includes/settings/class-wp-rest-api-log-settings-general.php +++ b/includes/settings/class-wp-rest-api-log-settings-general.php @@ -40,22 +40,22 @@ static public function register_general_settings() { add_settings_field( 'logging-enabled', __( 'Enabled', 'wp-rest-api-log' ), array( __CLASS__, 'settings_yes_no' ), $key, $section, array( 'key' => $key, 'name' => 'logging-enabled', 'after' => '' ) ); - add_settings_field( 'purge-days', __( 'Days to Retain Old Entries', 'rest-api-toolbox' ), array( __CLASS__, 'settings_input' ), $key, $section, + add_settings_field( 'purge-days', __( 'Days to Retain Old Entries', 'wp-rest-api-log' ), array( __CLASS__, 'settings_input' ), $key, $section, array( 'key' => $key, 'name' => 'purge-days', - 'after' => __( 'Entries older than this will be deleted, leave blank to keep all entries', 'rest-api-toolbox' ), + 'after' => __( 'Entries older than this will be deleted, leave blank to keep all entries', 'wp-rest-api-log' ), 'size' => 3, 'maxlength' => 3, ) ); - add_settings_field( 'ip-address-display', __( 'IP Address Display', 'rest-api-toolbox' ), array( __CLASS__, 'settings_check_radio_list' ), $key, $section, + add_settings_field( 'ip-address-display', __( 'IP Address Display', 'wp-rest-api-log' ), array( __CLASS__, 'settings_check_radio_list' ), $key, $section, array( 'key' => $key, 'name' => 'ip-address-display', 'type' => 'radio', - 'after' => __( 'Sets the IP address displayed in the list of log entries.', 'rest-api-toolbox' ), + 'after' => __( 'Sets the IP address displayed in the list of log entries.', 'wp-rest-api-log' ), 'items' => array( 'ip_address' => __( 'IP Address', 'wp-rest-api-log' ), 'http_x_forwarded_for' => __( 'HTTP X Forwarded For', 'wp-rest-api-log' ), diff --git a/includes/settings/class-wp-rest-api-log-settings-routes.php b/includes/settings/class-wp-rest-api-log-settings-routes.php index 21a98c8..d5f0b24 100644 --- a/includes/settings/class-wp-rest-api-log-settings-routes.php +++ b/includes/settings/class-wp-rest-api-log-settings-routes.php @@ -37,8 +37,72 @@ static public function register_general_settings() { add_settings_section( $section, '', null, $key ); - add_settings_field( 'ignore-core-oembed', __( 'Ignore core oEmbed', 'wp-rest-api-log' ), array( __CLASS__, 'settings_yes_no' ), $key, $section, - array( 'key' => $key, 'name' => 'ignore-core-oembed', 'after' => 'Built-in /oembed/1.0/embed route' ) ); + add_settings_field( + 'ignore-core-oembed', + __( 'Ignore core oEmbed', 'wp-rest-api-log' ), + array( __CLASS__, 'settings_yes_no' ), + $key, + $section, + array( + 'key' => $key, + 'name' => 'ignore-core-oembed', + 'after' => 'Built-in /oembed/1.0/embed route' + ) + ); + + add_settings_field( + 'route-log-matching-mode', + __( 'Route Logging Mode', 'wp-rest-api-log' ), + array( __CLASS__, 'log_matching_mode_dropdown' ), + $key, + $section, + array( + 'key' => $key, + 'name' => 'route-log-matching-mode', + ) + ); + + add_settings_field( + 'route-filters', + __( 'Route Filters', 'wp-rest-api-log' ), + array( __CLASS__, 'settings_textarea' ), + $key, + $section, + array( + 'key' => $key, + 'name' => 'route-filters', + 'after' => 'One route per line, examples
  • Exact Match: /wp/v2/posts
  • Wildcard Match: /wp/v2/*
  • Regex: ^/wp/v2/.*$
Regex matches must start with ^' + ) + ); + } + + /** + * Callback for outputting the log matching mode. + * + * @param array $args + * @return void + */ + static public function log_matching_mode_dropdown( $args ) { + + $args = wp_parse_args( $args, array( + 'key' => '', + 'name' => '', + ) + ); + + $option = get_option( $args['key'] ); + $mode = isset( $option[ $args['name'] ] ) ? $option[ $args['name'] ] : ''; + + // Get the list of filter modes. + $filter_modes = WP_REST_API_Log_Filters::filter_modes(); + + ?> + + assertEquals( '^..*/wp/v2/$/?$', $route_regex ); } + public function test_filter_modes() { + $modes = WP_REST_API_Log_Filters::filter_modes(); + $this->assertArrayHasKey( '', $modes ); + $this->assertArrayHasKey( 'log_matches', $modes ); + $this->assertArrayHasKey( 'exclude_matches', $modes ); + } + public function test_should_log_route() { + + } } From 937c8d3b16a4ecd701d3498ef7a6979ee898bc1c Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Wed, 18 Jan 2017 19:43:22 -0600 Subject: [PATCH 05/15] finished can_log_route() --- includes/class-wp-rest-api-log-filters.php | 45 ++++++++++ tests/test-filters.php | 97 ++++++++++++++++++++-- 2 files changed, 137 insertions(+), 5 deletions(-) diff --git a/includes/class-wp-rest-api-log-filters.php b/includes/class-wp-rest-api-log-filters.php index 052331c..0161e70 100644 --- a/includes/class-wp-rest-api-log-filters.php +++ b/includes/class-wp-rest-api-log-filters.php @@ -48,6 +48,9 @@ public static function route_to_regex( $route_filter ) { // Add the end of the match. $route_filter .= '$'; + + // Convert backslash to literals. + $route_filter = str_replace( '/', "\/", $route_filter ); } } @@ -55,11 +58,53 @@ public static function route_to_regex( $route_filter ) { return $route_filter; } + /** + * Determines if the supplied route can be logged. + * + * @param string $route Route (ex: /wp/v2). + * @return bool + */ static public function can_log_route( $route ) { // Get the filter mode. + $route_logging_mode = apply_filters( 'wp-rest-api-log-setting-get', 'routes', 'route-log-matching-mode' ); + + // If no logging mode is set, we can log the route. + if ( empty( $route_logging_mode ) ) { + return true; + } // Get the route filters. + $route_filters = apply_filters( 'wp-rest-api-log-setting-get', 'routes', 'route-filters' ); + $route_filters = explode( "\n", $route_filters ); + + // If we're set to exclude matching filters, but we have no filters, + // then the route can be logged + if ( 'exclude_matches' === $route_logging_mode && empty( $route_filters ) ) { + return true; + } + + // Loop through the filters and apply each one to the route. + foreach( $route_filters as $route_filter ) { + $regex = self::route_to_regex( $route_filter ); + + //preg_match() returns 1 if the pattern matches given subject, + //0 if it does not, or FALSE if an error occurred. + $match = preg_match( '/' . $regex . '/', $route ); + + // We can log this if the mode is set to log only matches. + if ( 1 === $match && 'log_matches' === $route_logging_mode ) { + return true; + } + + // We cannot log this if the mode is set to exclude matches. + if ( 1 === $match && 'exclude_matches' === $route_logging_mode ) { + return false; + } + } + // At this point, we can only log the match if we're set to exclude + // mode and the loop above did not find a match. + return 'exclude_matches' === $route_logging_mode; } } diff --git a/tests/test-filters.php b/tests/test-filters.php index 2f7605d..e5c80e0 100644 --- a/tests/test-filters.php +++ b/tests/test-filters.php @@ -15,14 +15,14 @@ public function test_convert_route_filter() { // Just a path, adds start and end. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/' ); - $this->assertEquals( '^/wp/v2/?$', $route_regex ); + $this->assertEquals( "^\/wp\/v2\/?$", $route_regex ); // Wildcard matches. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/*/' ); - $this->assertEquals( '^/wp/.*/?$', $route_regex ); + $this->assertEquals( "^\/wp\/.*\/?$", $route_regex ); $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/*' ); - $this->assertEquals( '^/wp/v2/.*/?$', $route_regex ); + $this->assertEquals( "^\/wp\/v2\/.*\/?$", $route_regex ); // Regex should have no changes. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '^/wp/v2/.*' ); @@ -30,7 +30,7 @@ public function test_convert_route_filter() { // This is not treated as regex, so it get mangled. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '.*/wp/v2/$' ); - $this->assertEquals( '^..*/wp/v2/$/?$', $route_regex ); + $this->assertEquals( "^..*\/wp\/v2\/$\/?$", $route_regex ); } public function test_filter_modes() { @@ -40,9 +40,96 @@ public function test_filter_modes() { $this->assertArrayHasKey( 'exclude_matches', $modes ); } - public function test_should_log_route() { + public function test_route_logging_all_routes() { + $option_key = 'wp-rest-api-log-settings-routes'; + // Set the options to log everything. + $option_value = array( + 'route-log-matching-mode' => '', + ); + + update_option( 'wp-rest-api-log-settings-routes', $option_value ); + + // Make sure we can log any route. + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/wp/v2' ) ); + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/wp/v2/posts' ) ); + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/wp/v2/users' ) ); + + } + + + public function test_route_logging_only_matched_routes() { + + $option_key = 'wp-rest-api-log-settings-routes'; + + // Set the options to log only matching routes. + $option_value = array( + 'route-log-matching-mode' => 'log_matches', + 'route-filters' => +"/wp/v2 +/route/wildcard* +^\/route\/regex-exact$ +^\/route\/regex-wildcard.*$" + ); + + update_option( 'wp-rest-api-log-settings-routes', $option_value ); + + // Exact match. + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/wp/v2' ), '/wp/v2' ); + + // Basic wildcard. + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/route/wildcard-route' ), '/route/wildcard-route' ); + + // Exact regex + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/route/regex-exact' ), '/route/regex-exact' ); + + // Wildcard regex + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/route/regex-wildcard/test' ), '/route/regex-wildcard/test' ); + + // Test non-matching routes. + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/some/route' ), '/some/route' ); + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/route/wildercard' ), '/route/wildercard' ); + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/route/exact-regex' ), '/route/exact-regex' ); + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/route/regexwildcard' ), '/route/regexwildcard' ); + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/wp/v2/posts' ), '/wp/v2/posts' ); + + } + + public function test_route_logging_excluded_matched_routes() { + + $option_key = 'wp-rest-api-log-settings-routes'; + + // Set the options to log only matching routes. + $option_value = array( + 'route-log-matching-mode' => 'exclude_matches', + 'route-filters' => +"/wp/v2 +/route/wildcard* +^\/route\/regex-exact$ +^\/route\/regex-wildcard.*$" + ); + + update_option( 'wp-rest-api-log-settings-routes', $option_value ); + + // Exact match. + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/wp/v2' ), '/wp/v2' ); + + // Basic wildcard. + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/route/wildcard-route' ), '/route/wildcard-route' ); + + // Exact regex + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/route/regex-exact' ), '/route/regex-exact' ); + + // Wildcard regex + $this->assertFalse( WP_REST_API_Log_Filters::can_log_route( '/route/regex-wildcard/test' ), '/route/regex-wildcard/test' ); + + // Test non-matching routes, should all be logged. + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/some/route' ), '/some/route' ); + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/route/wildercard' ), '/route/wildercard' ); + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/route/exact-regex' ), '/route/exact-regex' ); + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/route/regexwildcard' ), '/route/regexwildcard' ); + $this->assertTrue( WP_REST_API_Log_Filters::can_log_route( '/wp/v2/posts' ), '/wp/v2/posts' ); } From fb7946da4738a355943a98a89c049791288d231a Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Thu, 19 Jan 2017 21:57:48 -0600 Subject: [PATCH 06/15] fixed some filter issues, made more functions static --- includes/class-wp-rest-api-log-filters.php | 12 ++- includes/class-wp-rest-api-log.php | 79 ++++++++++++------- .../class-wp-rest-api-log-settings.php | 40 ++++++++-- tests/test-filters.php | 8 +- wp-rest-api-log.php | 5 +- 5 files changed, 96 insertions(+), 48 deletions(-) diff --git a/includes/class-wp-rest-api-log-filters.php b/includes/class-wp-rest-api-log-filters.php index 0161e70..653f979 100644 --- a/includes/class-wp-rest-api-log-filters.php +++ b/includes/class-wp-rest-api-log-filters.php @@ -40,12 +40,6 @@ public static function route_to_regex( $route_filter ) { // Add the start of the match. $route_filter = '^' . $route_filter; - // Add a trailing slash. - $route_filter = trailingslashit( $route_filter ); - - // Add a flag for zero or one trailing slashes. - $route_filter .= '?'; - // Add the end of the match. $route_filter .= '$'; @@ -76,7 +70,7 @@ static public function can_log_route( $route ) { // Get the route filters. $route_filters = apply_filters( 'wp-rest-api-log-setting-get', 'routes', 'route-filters' ); - $route_filters = explode( "\n", $route_filters ); + $route_filters = array_values( array_map( 'trim', explode( "\n", $route_filters ) ) ); // If we're set to exclude matching filters, but we have no filters, // then the route can be logged @@ -86,6 +80,10 @@ static public function can_log_route( $route ) { // Loop through the filters and apply each one to the route. foreach( $route_filters as $route_filter ) { + if ( empty( $route_filter ) ) { + continue; + } + $regex = self::route_to_regex( $route_filter ); //preg_match() returns 1 if the pattern matches given subject, diff --git a/includes/class-wp-rest-api-log.php b/includes/class-wp-rest-api-log.php index 62f72eb..b9ac47e 100644 --- a/includes/class-wp-rest-api-log.php +++ b/includes/class-wp-rest-api-log.php @@ -12,28 +12,19 @@ class WP_REST_API_Log { * * @return void */ - public function plugins_loaded() { + static public function plugins_loaded() { - // filter that is called by the REST API right before it sends a response - add_filter( 'rest_pre_serve_request', array( $this, 'log_rest_api_response' ), 9999, 4 ); + // Filter that is called by the REST API right before it sends a response + add_filter( 'rest_pre_serve_request', array( __CLASS__, 'log_rest_api_response' ), 9999, 4 ); - // an example of disabling logging for specific requests - add_filter( 'wp-rest-api-log-bypass-insert', function( $bypass_insert, $result, $request, $rest_server ) { + // Disabling logging for specific requests. + add_filter( 'wp-rest-api-log-bypass-insert', array( __CLASS__, 'bypass_common_routes' ), 10, 4 ); - $ignore_routes = array( - '/wp-rest-api-log', - '/oembed/1.0/embed', - ); + // Create cron job. + add_action( 'admin_init', array( __CLASS__, 'create_purge_cron' ) ); - foreach ( $ignore_routes as $route ) { - if ( stripos( $request->get_route(), $route ) !== false ) { - return true; - } - } - - return $bypass_insert; - - }, 10, 4 ); + // Handler for cron job. + add_action( 'wp-rest-api-log-purge-old-records', array( __CLASS__, 'purge_old_records' ) ); // for local development @@ -50,9 +41,6 @@ public function plugins_loaded() { // } ); - add_action( 'admin_init', array( $this, 'create_purge_cron' ) ); - add_action( 'wp-rest-api-log-purge-old-records', array( $this, 'purge_old_records' ) ); - } @@ -65,7 +53,7 @@ public function plugins_loaded() { * @param object $rest_server REST API server. * @return bool $served */ - public function log_rest_api_response( $served, $result, $request, $rest_server ) { + static public function log_rest_api_response( $served, $result, $request, $rest_server ) { // don't log anything if logging is not enabled $logging_enabled = apply_filters( WP_REST_API_Log_Common::PLUGIN_NAME . '-setting-is-enabled', @@ -79,16 +67,29 @@ public function log_rest_api_response( $served, $result, $request, $rest_server } - // allow specific requests to not be logged + // Allow specific requests to not be logged $bypass_insert = apply_filters( WP_REST_API_Log_Common::PLUGIN_NAME . '-bypass-insert', false, $result, $request, $rest_server ); if ( $bypass_insert ) { return $served; } + // Determine if this route should be logged based on route filters. + $route = $request->get_route(); + $can_log_route = WP_REST_API_Log_Filters::can_log_route( $route ); + + // Allow this to be filtered. + $can_log_route = apply_filters( 'wp-rest-api-log-can-log-route', $can_log_route, $route, $request, $result, $rest_server ); + + + // Exit out if we can't log this route. + if ( ! $can_log_route ) { + return $served; + } + $args = array( 'ip_address' => filter_input( INPUT_SERVER, 'REMOTE_ADDR', FILTER_SANITIZE_STRING ), 'http_x_forwarded_for' => filter_input( INPUT_SERVER, 'HTTP_X_FORWARDED_FOR', FILTER_SANITIZE_STRING ), - 'route' => $request->get_route(), + 'route' => $route, 'method' => $request->get_method(), 'status' => $result->get_status(), 'request' => array( @@ -99,7 +100,7 @@ public function log_rest_api_response( $served, $result, $request, $rest_server ), 'response' => array( 'body' => $result, - 'headers' => $this->get_response_headers( $result ), + 'headers' => self::get_response_headers( $result ), ), ); @@ -110,7 +111,7 @@ public function log_rest_api_response( $served, $result, $request, $rest_server } - private function get_response_headers( $result ) { + static public function get_response_headers( $result ) { // headers_list returns an array of headers like this: Content-Type: application/json; // we want a key/value array if ( function_exists( 'headers_list' ) ) { @@ -134,13 +135,13 @@ private function get_response_headers( $result ) { } } - public function create_purge_cron() { + static public function create_purge_cron() { if ( ! wp_next_scheduled( 'wp-rest-api-log-purge-old-records' ) ) { wp_schedule_event( time() + 60, 'hourly', 'wp-rest-api-log-purge-old-records' ); } } - public function purge_old_records( $days_old = false, $dry_run = false ) { + static public function purge_old_records( $days_old = false, $dry_run = false ) { if ( empty( $days_old ) ) { $days_old = WP_REST_API_Log_Settings_General::setting_get( 'general', 'purge-days' ); @@ -175,6 +176,28 @@ public function purge_old_records( $days_old = false, $dry_run = false ) { } + static public function bypass_common_routes( $bypass_insert, $result, $request, $rest_server ) { + + // Ignore our own plugin. + $ignore_routes = array( + '/wp-rest-api-log', + ); + + // See if the oembed route is ignored. + if ( '1' === apply_filters( 'wp-rest-api-log-setting-get', 'routes', 'ignore-core-oembed' ) ) { + $ignore_routes[] = '/oembed/1.0/embed'; + } + + foreach ( $ignore_routes as $route ) { + if ( stripos( $request->get_route(), $route ) !== false ) { + return true; + } + } + + return $bypass_insert; + + } + } // end class } diff --git a/includes/settings/class-wp-rest-api-log-settings.php b/includes/settings/class-wp-rest-api-log-settings.php index f0d526b..6a5c710 100644 --- a/includes/settings/class-wp-rest-api-log-settings.php +++ b/includes/settings/class-wp-rest-api-log-settings.php @@ -6,7 +6,11 @@ class WP_REST_API_Log_Settings extends WP_REST_API_Log_Settings_Base { - + /** + * Wire up WordPress hooks and filters. + * + * @return void + */ static public function plugins_loaded() { // admin menus add_action( 'admin_menu', array( __CLASS__, 'admin_menu' ) ); @@ -15,10 +19,14 @@ static public function plugins_loaded() { // filters to get plugin settings add_filter( 'wp-rest-api-log-setting-is-enabled', array( __CLASS__, 'filter_setting_is_enabled' ), 10, 3 ); add_filter( 'wp-rest-api-log-setting-get', array( __CLASS__, 'setting_get' ), 10, 3 ); - } + /** + * Displays an admin notice if the plugin was just activated. + * + * @return void + */ static public function activation_admin_notice() { if ( '1' === get_option( 'wp-rest-api-log-plugin-activated' ) ) { ?> @@ -37,20 +45,38 @@ static public function deactivation_hook() { // placeholder in case we need deactivation code } - - + /** + * Creates default settings for the plugin. + * + * @return void + */ static public function create_default_settings() { // create default settings add_option( WP_REST_API_Log_Settings_General::$settings_key, WP_REST_API_Log_Settings_General::get_default_settings(), '', $autoload = 'no' ); add_option( WP_REST_API_Log_Settings_Routes::$settings_key, WP_REST_API_Log_Settings_Routes::get_default_settings(), '', $autoload = 'no' ); } - + /** + * Registers the REST API Log admin menu, + * + * @return void + */ static public function admin_menu() { - add_options_page( 'REST API Log ' . __( 'Settings' ), __( 'REST API Log', 'wp-rest-api-log' ), 'manage_options', self::$settings_page, array( __CLASS__, 'options_page' ), 30 ); + add_options_page( + __( 'REST API Log Settings', 'wp-rest-api-log' ), + __( 'REST API Log', 'wp-rest-api-log' ), + 'manage_options', + self::$settings_page, + array( __CLASS__, 'options_page' ), + 30 + ); } - + /** + * Displays the settings page for the plugin. + * + * @return void + */ static public function options_page() { $tab = self::current_tab(); ?> diff --git a/tests/test-filters.php b/tests/test-filters.php index e5c80e0..dbd9efb 100644 --- a/tests/test-filters.php +++ b/tests/test-filters.php @@ -15,14 +15,14 @@ public function test_convert_route_filter() { // Just a path, adds start and end. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/' ); - $this->assertEquals( "^\/wp\/v2\/?$", $route_regex ); + $this->assertEquals( "^\/wp\/v2$", $route_regex ); // Wildcard matches. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/*/' ); - $this->assertEquals( "^\/wp\/.*\/?$", $route_regex ); + $this->assertEquals( "^\/wp\/.*$", $route_regex ); $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/*' ); - $this->assertEquals( "^\/wp\/v2\/.*\/?$", $route_regex ); + $this->assertEquals( "^\/wp\/v2\/.*$", $route_regex ); // Regex should have no changes. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '^/wp/v2/.*' ); @@ -30,7 +30,7 @@ public function test_convert_route_filter() { // This is not treated as regex, so it get mangled. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '.*/wp/v2/$' ); - $this->assertEquals( "^..*\/wp\/v2\/$\/?$", $route_regex ); + $this->assertEquals( "^..*\/wp\/v2$", $route_regex ); } public function test_filter_modes() { diff --git a/wp-rest-api-log.php b/wp-rest-api-log.php index ab18c35..992269b 100644 --- a/wp-rest-api-log.php +++ b/wp-rest-api-log.php @@ -99,13 +99,14 @@ } } -WP_REST_API_Log_ElasticPress::plugins_loaded(); - +// Wire up hooks and filters in static classes. +WP_REST_API_Log::plugins_loaded(); WP_REST_API_Log_Settings::plugins_loaded(); WP_REST_API_Log_Settings_General::plugins_loaded(); WP_REST_API_Log_Settings_Routes::plugins_loaded(); WP_REST_API_Log_Settings_ElasticPress::plugins_loaded(); WP_REST_API_Log_Settings_Help::plugins_loaded(); +WP_REST_API_Log_ElasticPress::plugins_loaded(); /* Activation hook */ register_activation_hook( __FILE__, function() { From 15d69b7bdb9bc99ae927d646e99728ac93d1e00d Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Thu, 19 Jan 2017 22:15:40 -0600 Subject: [PATCH 07/15] updated after output --- .../settings/class-wp-rest-api-log-settings-base.php | 2 +- .../class-wp-rest-api-log-settings-general.php | 4 ++-- .../class-wp-rest-api-log-settings-routes.php | 12 ++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/includes/settings/class-wp-rest-api-log-settings-base.php b/includes/settings/class-wp-rest-api-log-settings-base.php index 70477ec..c19dd52 100644 --- a/includes/settings/class-wp-rest-api-log-settings-base.php +++ b/includes/settings/class-wp-rest-api-log-settings-base.php @@ -243,7 +243,7 @@ static public function settings_yes_no( $args ) { static public function output_after( $after ) { if ( ! empty( $after ) ) { - echo '

' . wp_kses_post( $after ) . '

'; + echo wp_kses_post( $after ); } } diff --git a/includes/settings/class-wp-rest-api-log-settings-general.php b/includes/settings/class-wp-rest-api-log-settings-general.php index f672fad..580c3ec 100644 --- a/includes/settings/class-wp-rest-api-log-settings-general.php +++ b/includes/settings/class-wp-rest-api-log-settings-general.php @@ -44,7 +44,7 @@ static public function register_general_settings() { array( 'key' => $key, 'name' => 'purge-days', - 'after' => __( 'Entries older than this will be deleted, leave blank to keep all entries', 'wp-rest-api-log' ), + 'after' => '

' . __( 'Entries older than this will be deleted, leave blank to keep all entries', 'wp-rest-api-log' ) . '

', 'size' => 3, 'maxlength' => 3, ) @@ -55,7 +55,7 @@ static public function register_general_settings() { 'key' => $key, 'name' => 'ip-address-display', 'type' => 'radio', - 'after' => __( 'Sets the IP address displayed in the list of log entries.', 'wp-rest-api-log' ), + 'after' => '

' . __( 'Sets the IP address displayed in the list of log entries.', 'wp-rest-api-log' ) . '

', 'items' => array( 'ip_address' => __( 'IP Address', 'wp-rest-api-log' ), 'http_x_forwarded_for' => __( 'HTTP X Forwarded For', 'wp-rest-api-log' ), diff --git a/includes/settings/class-wp-rest-api-log-settings-routes.php b/includes/settings/class-wp-rest-api-log-settings-routes.php index d5f0b24..b0303d9 100644 --- a/includes/settings/class-wp-rest-api-log-settings-routes.php +++ b/includes/settings/class-wp-rest-api-log-settings-routes.php @@ -46,7 +46,7 @@ static public function register_general_settings() { array( 'key' => $key, 'name' => 'ignore-core-oembed', - 'after' => 'Built-in /oembed/1.0/embed route' + 'after' => '

Built-in /oembed/1.0/embed route

' ) ); @@ -71,7 +71,15 @@ static public function register_general_settings() { array( 'key' => $key, 'name' => 'route-filters', - 'after' => 'One route per line, examples
  • Exact Match: /wp/v2/posts
  • Wildcard Match: /wp/v2/*
  • Regex: ^/wp/v2/.*$
Regex matches must start with ^' + 'after' => ' +

One route per line, examples

+
    +
  • Exact Match: /wp/v2/posts
  • +
  • Wildcard Match: /wp/v2/*
  • +
  • Regex: ^/wp/v2/.*$
  • +
+

Regex matches must start with ^

+ ', ) ); } From 61edf46b97ab9adc14af63e07c5e7a1ddac68574 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Fri, 20 Jan 2017 17:05:31 -0600 Subject: [PATCH 08/15] updated plugin version and readme --- readme.md | 6 ++++++ readme.txt | 6 ++++++ wp-rest-api-log.php | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 99831ea..c90f33a 100644 --- a/readme.md +++ b/readme.md @@ -44,6 +44,9 @@ Roadmap ## Changelog ## +### v1.4.0 January 20, 2017 ### +* Added the ability to filter routes for logging, either include or exclude specific routes. + ### v1.3.0 December 5, 2016 ### * Added support for logging HTTP_X_FORWARDED_FOR, useful for servers behind a proxy or load balancer. * Changed plugin name to REST API Log @@ -81,6 +84,9 @@ Roadmap ## Upgrade Notice ## +### v1.4.0 January 20, 2017 ### +* Added the ability to filter routes for logging, either include or exclude specific routes. + ### v1.3.0 December 5, 2016 ### * Added support for logging HTTP_X_FORWARDED_FOR, useful for servers behind a proxy or load balancer. * Changed plugin name to REST API Log diff --git a/readme.txt b/readme.txt index 066ed31..f614137 100644 --- a/readme.txt +++ b/readme.txt @@ -40,6 +40,9 @@ Roadmap == Changelog == += v1.4.0 January 20, 2017 = +* Added the ability to filter routes for logging, either include or exclude specific routes. + = v1.3.0 December 5, 2016 = * Added support for logging HTTP_X_FORWARDED_FOR, useful for servers behind a proxy or load balancer. * Changed plugin name to REST API Log @@ -77,6 +80,9 @@ Roadmap == Upgrade Notice == += v1.4.0 January 20, 2017 = +* Added the ability to filter routes for logging, either include or exclude specific routes. + = v1.3.0 December 5, 2016 = * Added support for logging HTTP_X_FORWARDED_FOR, useful for servers behind a proxy or load balancer. * Changed plugin name to REST API Log diff --git a/wp-rest-api-log.php b/wp-rest-api-log.php index 992269b..f4d7995 100644 --- a/wp-rest-api-log.php +++ b/wp-rest-api-log.php @@ -3,7 +3,7 @@ * Plugin Name: REST API Log * Description: Logs requests and responses for the REST API * Author: Pete Nelson - * Version: 1.3.0 + * Version: 1.4.0 * Plugin URI: https://github.com/petenelson/wp-rest-api-log * Text Domain: wp-rest-api-log * Domain Path: /languages From a84b3a2e5179b3e85238277a47a603fbfc2429bd Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Fri, 20 Jan 2017 18:31:03 -0600 Subject: [PATCH 09/15] fixed some route tests --- tests/test-filters.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test-filters.php b/tests/test-filters.php index dbd9efb..408d565 100644 --- a/tests/test-filters.php +++ b/tests/test-filters.php @@ -14,15 +14,15 @@ class WP_REST_API_Log_Test_Filters extends WP_UnitTestCase { public function test_convert_route_filter() { // Just a path, adds start and end. - $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/' ); + $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2' ); $this->assertEquals( "^\/wp\/v2$", $route_regex ); // Wildcard matches. - $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/*/' ); + $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/*' ); $this->assertEquals( "^\/wp\/.*$", $route_regex ); $route_regex = WP_REST_API_Log_Filters::route_to_regex( '/wp/v2/*' ); - $this->assertEquals( "^\/wp\/v2\/.*$", $route_regex ); + $this->assertEquals( "^\/wp\/v2\/.*$", $route_regex, '/wp/v2/*' ); // Regex should have no changes. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '^/wp/v2/.*' ); @@ -30,7 +30,7 @@ public function test_convert_route_filter() { // This is not treated as regex, so it get mangled. $route_regex = WP_REST_API_Log_Filters::route_to_regex( '.*/wp/v2/$' ); - $this->assertEquals( "^..*\/wp\/v2$", $route_regex ); + $this->assertEquals( "^..*\/wp\/v2\/$$", $route_regex ); } public function test_filter_modes() { From 0785133606710766425f85626ed1b1f47e5ad11e Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 23 Jan 2017 21:17:30 -0600 Subject: [PATCH 10/15] swiched route logging mode to radio buttons --- .codeclimate.yml | 2 ++ includes/class-wp-rest-api-log-common.php | 6 ---- includes/class-wp-rest-api-log-i18n.php | 8 ++--- .../class-wp-rest-api-log-settings-routes.php | 35 ++----------------- readme.txt | 8 ++--- 5 files changed, 11 insertions(+), 48 deletions(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index d0e0c94..832e1f0 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -23,6 +23,8 @@ engines: enabled: false Controversial/CamelCaseMethodName: enabled: false + Controversial/CamelCasePropertyName: + enabled: false CleanCode/ElseExpression: enabled: false CleanCode/StaticAccess: diff --git a/includes/class-wp-rest-api-log-common.php b/includes/class-wp-rest-api-log-common.php index 84e1d83..3b588e3 100644 --- a/includes/class-wp-rest-api-log-common.php +++ b/includes/class-wp-rest-api-log-common.php @@ -10,12 +10,6 @@ class WP_REST_API_Log_Common { const VERSION = '2017-01-16-01'; const TEXT_DOMAIN = 'wp-rest-api-log'; - - public function plugins_loaded() { - - } - - static public function current_milliseconds() { return self::microtime_to_milliseconds( microtime() ); } diff --git a/includes/class-wp-rest-api-log-i18n.php b/includes/class-wp-rest-api-log-i18n.php index cd7309e..f9286bf 100644 --- a/includes/class-wp-rest-api-log-i18n.php +++ b/includes/class-wp-rest-api-log-i18n.php @@ -10,14 +10,10 @@ class WP_REST_API_Log_i18n { public function plugins_loaded() { load_plugin_textdomain( - WP_REST_API_Log_Common::TEXT_DOMAIN, + 'wp-rest-api-log', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' ); - } - - - } // end class - + } } diff --git a/includes/settings/class-wp-rest-api-log-settings-routes.php b/includes/settings/class-wp-rest-api-log-settings-routes.php index b0303d9..e149bd2 100644 --- a/includes/settings/class-wp-rest-api-log-settings-routes.php +++ b/includes/settings/class-wp-rest-api-log-settings-routes.php @@ -53,12 +53,14 @@ static public function register_general_settings() { add_settings_field( 'route-log-matching-mode', __( 'Route Logging Mode', 'wp-rest-api-log' ), - array( __CLASS__, 'log_matching_mode_dropdown' ), + array( __CLASS__, 'settings_check_radio_list' ), $key, $section, array( 'key' => $key, 'name' => 'route-log-matching-mode', + 'type' => 'radio', + 'items' => WP_REST_API_Log_Filters::filter_modes(), ) ); @@ -84,37 +86,6 @@ static public function register_general_settings() { ); } - /** - * Callback for outputting the log matching mode. - * - * @param array $args - * @return void - */ - static public function log_matching_mode_dropdown( $args ) { - - $args = wp_parse_args( $args, array( - 'key' => '', - 'name' => '', - ) - ); - - $option = get_option( $args['key'] ); - $mode = isset( $option[ $args['name'] ] ) ? $option[ $args['name'] ] : ''; - - // Get the list of filter modes. - $filter_modes = WP_REST_API_Log_Filters::filter_modes(); - - ?> - - Date: Mon, 23 Jan 2017 21:28:42 -0600 Subject: [PATCH 11/15] cleaned up the WP_REST_API_Log_Settings_Routes class --- .../class-wp-rest-api-log-settings-routes.php | 65 +++++++++++++++---- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/includes/settings/class-wp-rest-api-log-settings-routes.php b/includes/settings/class-wp-rest-api-log-settings-routes.php index e149bd2..f4fa5ac 100644 --- a/includes/settings/class-wp-rest-api-log-settings-routes.php +++ b/includes/settings/class-wp-rest-api-log-settings-routes.php @@ -8,27 +8,46 @@ class WP_REST_API_Log_Settings_Routes extends WP_REST_API_Log_Settings_Base { static $settings_key = 'wp-rest-api-log-settings-routes'; - + /** + * Hooks up WorPress actions and filters. + * + * @return void + */ static public function plugins_loaded() { - add_action( 'admin_init', array( __CLASS__, 'register_general_settings' ) ); + add_action( 'admin_init', array( __CLASS__, 'register_routes_settings' ) ); add_filter( 'wp-rest-api-log-settings-tabs', array( __CLASS__, 'add_tab') ); } - + /** + * Adds a Routes tab. + * + * @param array $tabs List of tabs. + * @return array + */ static public function add_tab( $tabs ) { $tabs[ self::$settings_key ] = __( 'Routes', 'wp-rest-api-log' ); return $tabs; } - + /** + * Gets the default Routes settings. + * + * @return array + */ static public function get_default_settings() { return array( - 'ignore-core-oembed' => '1', + 'ignore-core-oembed' => '1', + 'route-log-matching-mode' => '', + 'route-filters' => '', ); } - - static public function register_general_settings() { + /** + * Registers settings sections and fields for the Routes tab. + * + * @return void + */ + static public function register_routes_settings() { $key = self::$settings_key; register_setting( $key, $key, array( __CLASS__, 'sanitize_settings') ); @@ -46,7 +65,7 @@ static public function register_general_settings() { array( 'key' => $key, 'name' => 'ignore-core-oembed', - 'after' => '

Built-in /oembed/1.0/embed route

' + 'after' => '

' . __( 'Built-in /oembed/1.0/embed route', 'wp-rest-api-log' ) . '

', ) ); @@ -61,6 +80,7 @@ static public function register_general_settings() { 'name' => 'route-log-matching-mode', 'type' => 'radio', 'items' => WP_REST_API_Log_Filters::filter_modes(), + 'default' => array( '' ), ) ); @@ -74,20 +94,37 @@ static public function register_general_settings() { 'key' => $key, 'name' => 'route-filters', 'after' => ' -

One route per line, examples

+

' . __( 'One route per line, examples', 'wp-rest-api-log' ) . '

    -
  • Exact Match: /wp/v2/posts
  • -
  • Wildcard Match: /wp/v2/*
  • -
  • Regex: ^/wp/v2/.*$
  • +
  • ' . __( 'Exact Match', 'wp-rest-api-log' ) . ': /wp/v2/posts
  • +
  • ' . __( 'Wildcard Match', 'wp-rest-api-log' ) . ': /wp/v2/*
  • +
  • ' . __( 'Regex', 'wp-rest-api-log' ) . ': ^/wp/v2/.*$
-

Regex matches must start with ^

- ', +

' . __( 'Regex matches must start with ^', 'wp-rest-api-log' ) . '

', ) ); } + /** + * Sanitzes the route settings. + * + * @param array $settings List of settings. + * @return array + */ static public function sanitize_settings( $settings ) { + // Sanitize string fields. + $string_fields = array( + 'ignore-core-oembed', + 'route-log-matching-mode', + ); + + foreach( $string_fields as $field ) { + if ( isset( $settings[ $field ] ) ) { + $settings[ $field ] = filter_var( $settings[ $field ], FILTER_SANITIZE_STRING ); + } + } + return $settings; } From e56ebcba363c4b08ec1b9b4c70201f372bc22520 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 23 Jan 2017 21:34:39 -0600 Subject: [PATCH 12/15] switch WP_REST_API_Log_Controller to static methods --- includes/class-wp-rest-api-log-controller.php | 38 +++++++++---------- wp-rest-api-log.php | 1 + 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/includes/class-wp-rest-api-log-controller.php b/includes/class-wp-rest-api-log-controller.php index 1ee6da7..ec87f7f 100644 --- a/includes/class-wp-rest-api-log-controller.php +++ b/includes/class-wp-rest-api-log-controller.php @@ -7,17 +7,17 @@ class WP_REST_API_Log_Controller { - public function plugins_loaded() { - add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) ); + static function plugins_loaded() { + add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) ); } - public function register_rest_routes() { + static public function register_rest_routes() { register_rest_route( WP_REST_API_Log_Common::PLUGIN_NAME, '/entries', array( 'methods' => array( WP_REST_Server::READABLE ), - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_permissions_check' ), + 'callback' => array( __CLASS__, 'get_items' ), + 'permission_callback' => array( __CLASS__, 'get_permissions_check' ), 'args' => array( 'from' => array( 'default' => '', @@ -66,12 +66,12 @@ public function register_rest_routes() { register_rest_route( WP_REST_API_Log_Common::PLUGIN_NAME, '/entry/(?P[\d]+)', array( 'methods' => array( WP_REST_Server::READABLE ), - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_permissions_check' ), + 'callback' => array( __CLASS__, 'get_item' ), + 'permission_callback' => array( __CLASS__, 'get_permissions_check' ), 'args' => array( 'id' => array( 'sanitize_callback' => 'absint', - 'validate_callback' => array( $this, 'validate_entry_id' ), + 'validate_callback' => array( __CLASS__, 'validate_entry_id' ), 'default' => 0, ), ), @@ -80,8 +80,8 @@ public function register_rest_routes() { register_rest_route( WP_REST_API_Log_Common::PLUGIN_NAME, '/entry', array( 'methods' => array( WP_REST_Server::DELETABLE ), - 'callback' => array( $this, 'delete_items' ), - 'permission_callback' => array( $this, 'delete_items_permissions_check' ), + 'callback' => array( __CLASS__, 'delete_items' ), + 'permission_callback' => array( __CLASS__, 'delete_items_permissions_check' ), 'args' => array( // TODO refator delete, this won't work with $_REQUESTs 'older-than-seconds' => array( 'sanitize_callback' => 'absint', // TODO add validate callback @@ -93,14 +93,14 @@ public function register_rest_routes() { register_rest_route( WP_REST_API_Log_Common::PLUGIN_NAME, '/routes', array( 'methods' => array( WP_REST_Server::READABLE ), - 'callback' => array( $this, 'get_routes' ), - 'permission_callback' => array( $this, 'get_permissions_check' ), + 'callback' => array( __CLASS__, 'get_routes' ), + 'permission_callback' => array( __CLASS__, 'get_permissions_check' ), ) ); } - public function get_items( WP_REST_Request $request ) { + static public function get_items( WP_REST_Request $request ) { $args = array( 'id' => $request['id'], @@ -125,7 +125,7 @@ public function get_items( WP_REST_Request $request ) { } - public function get_item( WP_REST_Request $request ) { + static public function get_item( WP_REST_Request $request ) { $post = get_post( $request['id'] ); $entry = new WP_REST_API_Log_Entry( $args['id'] ); @@ -139,7 +139,7 @@ public function get_item( WP_REST_Request $request ) { } - public function validate_entry_id( $id ) { + static public function validate_entry_id( $id ) { if ( $id < 1 ) { return new WP_Error( 'invalid_entry_id', sprintf( __( 'Invalid REST API Log ID %d.', 'wp-rest-api-log' ), $args['id'] ), array( 'status' => 404 ) ); } else { @@ -147,7 +147,7 @@ public function validate_entry_id( $id ) { } } - public function get_routes( WP_REST_Request $request ) { + static public function get_routes( WP_REST_Request $request ) { global $wpdb; @@ -161,7 +161,7 @@ public function get_routes( WP_REST_Request $request ) { } - public function delete_items( WP_REST_Request $request ) { + static public function delete_items( WP_REST_Request $request ) { // TODO refactor $args = array( 'older_than_seconds' => $request['older-than-seconds'], @@ -172,12 +172,12 @@ public function delete_items( WP_REST_Request $request ) { } - public function get_permissions_check() { + static public function get_permissions_check() { return apply_filters( WP_REST_API_Log_Common::PLUGIN_NAME . '-can-view-entries', current_user_can( 'read_' . WP_REST_API_Log_DB::POST_TYPE ) ); } - public function delete_items_permissions_check() { + static public function delete_items_permissions_check() { return apply_filters( WP_REST_API_Log_Common::PLUGIN_NAME . '-can-delete-entries', current_user_can( 'delete_' . WP_REST_API_Log_DB::POST_TYPE ) ); } diff --git a/wp-rest-api-log.php b/wp-rest-api-log.php index f4d7995..6dfe57a 100644 --- a/wp-rest-api-log.php +++ b/wp-rest-api-log.php @@ -106,6 +106,7 @@ WP_REST_API_Log_Settings_Routes::plugins_loaded(); WP_REST_API_Log_Settings_ElasticPress::plugins_loaded(); WP_REST_API_Log_Settings_Help::plugins_loaded(); +WP_REST_API_Log_Controller::plugins_loaded(); WP_REST_API_Log_ElasticPress::plugins_loaded(); /* Activation hook */ From d754bf61ac0bf409b1d316d6ece960599c45bb1f Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 23 Jan 2017 21:42:05 -0600 Subject: [PATCH 13/15] fixed regex example in Routes settings --- includes/class-wp-rest-api-log-post-type.php | 31 +++++++------------ .../class-wp-rest-api-log-settings-routes.php | 2 +- wp-rest-api-log.php | 1 + 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/includes/class-wp-rest-api-log-post-type.php b/includes/class-wp-rest-api-log-post-type.php index f1cadc0..eda0110 100644 --- a/includes/class-wp-rest-api-log-post-type.php +++ b/includes/class-wp-rest-api-log-post-type.php @@ -2,26 +2,25 @@ if ( ! defined( 'ABSPATH' ) ) die( 'restricted access' ); -if ( ! class_exists( 'WP_REST_API_Log_Post_type' ) ) { +if ( ! class_exists( 'WP_REST_API_Log_Post_Type' ) ) { - class WP_REST_API_Log_Post_type { + class WP_REST_API_Log_Post_Type { - public function plugins_loaded() { - add_action( 'init', array( $this, 'register_custom_post_types' ) ); - add_action( 'init', array( $this, 'register_custom_taxonomies' ) ); + static public function plugins_loaded() { + add_action( 'init', array( __CLASS__, 'register_custom_post_types' ) ); + add_action( 'init', array( __CLASS__, 'register_custom_taxonomies' ) ); } - public function register_custom_post_types() { + static public function register_custom_post_types() { - $args = $this->get_post_type_args(); + $args = self::get_post_type_args(); register_post_type( WP_REST_API_Log_DB::POST_TYPE, $args ); - } - public function get_post_type_labels() { + static public function get_post_type_labels() { $labels = array( 'name' => esc_html__( 'REST API Log Entries', 'ms-research' ), @@ -41,10 +40,10 @@ public function get_post_type_labels() { } - public function get_post_type_args() { + static public function get_post_type_args() { $args = array( - 'labels' => $this->get_post_type_labels(), + 'labels' => self::get_post_type_labels(), 'show_in_rest' => true, 'rest_base' => WP_REST_API_Log_DB::POST_TYPE, // allows the CPT to show up in the native API 'hierarchical' => false, @@ -75,7 +74,7 @@ public function get_post_type_args() { } - public function register_custom_taxonomies() { + static public function register_custom_taxonomies() { // HTTP Method @@ -112,12 +111,6 @@ public function register_custom_taxonomies() { $args['labels']['singular_name'] = __( 'Log Sources', 'wp-rest-api-log' ); register_taxonomy( WP_REST_API_Log_DB::TAXONOMY_SOURCE, array( WP_REST_API_Log_DB::POST_TYPE ), $args ); - - // namespace? - } - - } - -} \ No newline at end of file +} diff --git a/includes/settings/class-wp-rest-api-log-settings-routes.php b/includes/settings/class-wp-rest-api-log-settings-routes.php index f4fa5ac..6eb4896 100644 --- a/includes/settings/class-wp-rest-api-log-settings-routes.php +++ b/includes/settings/class-wp-rest-api-log-settings-routes.php @@ -98,7 +98,7 @@ static public function register_routes_settings() {
  • ' . __( 'Exact Match', 'wp-rest-api-log' ) . ': /wp/v2/posts
  • ' . __( 'Wildcard Match', 'wp-rest-api-log' ) . ': /wp/v2/*
  • -
  • ' . __( 'Regex', 'wp-rest-api-log' ) . ': ^/wp/v2/.*$
  • +
  • ' . __( 'Regex', 'wp-rest-api-log' ) . ': ^\/wp\/v2\/.*$

' . __( 'Regex matches must start with ^', 'wp-rest-api-log' ) . '

', ) diff --git a/wp-rest-api-log.php b/wp-rest-api-log.php index 6dfe57a..725e154 100644 --- a/wp-rest-api-log.php +++ b/wp-rest-api-log.php @@ -106,6 +106,7 @@ WP_REST_API_Log_Settings_Routes::plugins_loaded(); WP_REST_API_Log_Settings_ElasticPress::plugins_loaded(); WP_REST_API_Log_Settings_Help::plugins_loaded(); +WP_REST_API_Log_Post_Type::plugins_loaded(); WP_REST_API_Log_Controller::plugins_loaded(); WP_REST_API_Log_ElasticPress::plugins_loaded(); From 1ea93e6bc4e3db60b633db1b229c09e68bdc9e59 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 23 Jan 2017 21:43:37 -0600 Subject: [PATCH 14/15] updated WP_REST_API_Log_i18n::plugins_loaded() to static --- includes/class-wp-rest-api-log-i18n.php | 2 +- wp-rest-api-log.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/class-wp-rest-api-log-i18n.php b/includes/class-wp-rest-api-log-i18n.php index f9286bf..9eb1696 100644 --- a/includes/class-wp-rest-api-log-i18n.php +++ b/includes/class-wp-rest-api-log-i18n.php @@ -7,7 +7,7 @@ class WP_REST_API_Log_i18n { - public function plugins_loaded() { + static public function plugins_loaded() { load_plugin_textdomain( 'wp-rest-api-log', diff --git a/wp-rest-api-log.php b/wp-rest-api-log.php index 725e154..463ef00 100644 --- a/wp-rest-api-log.php +++ b/wp-rest-api-log.php @@ -100,6 +100,7 @@ } // Wire up hooks and filters in static classes. +WP_REST_API_Log_i18n::plugins_loaded(); WP_REST_API_Log::plugins_loaded(); WP_REST_API_Log_Settings::plugins_loaded(); WP_REST_API_Log_Settings_General::plugins_loaded(); From 6a6e974617c042aaf679e5f2973ea0593db3110e Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 23 Jan 2017 21:57:34 -0600 Subject: [PATCH 15/15] updated readme --- readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index c90f33a..b27b53f 100644 --- a/readme.md +++ b/readme.md @@ -1,10 +1,10 @@ # REST API Log # **Contributors:** gungeekatx -**Tags:** wp rest api, rest api, wp api, api, json, log, logging +**Tags:** wp rest api, rest api, wp api, api, json, json api, log, logging, elasticpress, elasticsearch **Donate link:** https://github.com/petenelson/wp-rest-api-log **Requires at least:** 4.4 **Tested up to:** 4.7 -**Stable tag:** 1.3.0 +**Stable tag:** 1.4.0 **License:** GPLv2 or later **License URI:** http://www.gnu.org/licenses/gpl-2.0.html @@ -44,7 +44,7 @@ Roadmap ## Changelog ## -### v1.4.0 January 20, 2017 ### +### v1.4.0 January 23, 2017 ### * Added the ability to filter routes for logging, either include or exclude specific routes. ### v1.3.0 December 5, 2016 ### @@ -84,7 +84,7 @@ Roadmap ## Upgrade Notice ## -### v1.4.0 January 20, 2017 ### +### v1.4.0 January 23, 2017 ### * Added the ability to filter routes for logging, either include or exclude specific routes. ### v1.3.0 December 5, 2016 ###