Skip to content

Commit c61606e

Browse files
committed
Refactored is_logging_enabled into a rule builder to reduce complexity.
1 parent d785067 commit c61606e

File tree

10 files changed

+351
-66
lines changed

10 files changed

+351
-66
lines changed

plugins/wpgraphql-logging/src/Events/QueryFilterLogger.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab;
1010
use WPGraphQL\Logging\Logger\LoggerService;
1111
use WPGraphQL\Logging\Logger\LoggingHelper;
12+
use WPGraphQL\Logging\Logger\Rules\EnabledRule;
1213
use WPGraphQL\Request;
1314

1415
/**
@@ -62,10 +63,6 @@ public function __construct( LoggerService $logger, array $config ) {
6263
*/
6364
public function log_graphql_request_data( array $query_data ): array {
6465
try {
65-
if ( ! $this->is_logging_enabled( $this->config ) ) {
66-
return $query_data;
67-
}
68-
6966
$selected_events = $this->config[ Basic_Configuration_Tab::EVENT_LOG_SELECTION ] ?? [];
7067
if ( ! is_array( $selected_events ) || empty( $selected_events ) ) {
7168
return $query_data;
@@ -74,8 +71,13 @@ public function log_graphql_request_data( array $query_data ): array {
7471
return $query_data;
7572
}
7673

74+
$query_string = $query_data['query'] ?? null;
75+
if ( ! $this->is_logging_enabled( $this->config, $query_string ) ) {
76+
return $query_data;
77+
}
78+
7779
$context = [
78-
'query' => $query_data['query'] ?? null,
80+
'query' => $query_string,
7981
'variables' => $query_data['variables'] ?? null,
8082
'operation_name' => $query_data['operationName'] ?? null,
8183
];
@@ -115,7 +117,7 @@ public function log_graphql_request_results(
115117
?string $query_id
116118
): array|ExecutionResult {
117119
try {
118-
if ( ! $this->is_logging_enabled( $this->config ) ) {
120+
if ( ! $this->is_logging_enabled( $this->config, $query ) ) {
119121
return $response;
120122
}
121123

@@ -169,7 +171,9 @@ public function log_graphql_request_results(
169171
* @return array<string, string> The filtered array of headers.
170172
*/
171173
public function add_logging_headers( array $headers ): array {
172-
if ( ! $this->is_logging_enabled( $this->config ) ) {
174+
175+
$rule = new EnabledRule();
176+
if ( ! $rule->passes( $this->config ) ) {
173177
return $headers;
174178
}
175179

plugins/wpgraphql-logging/src/Logger/LoggingHelper.php

Lines changed: 41 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,59 @@
44

55
namespace WPGraphQL\Logging\Logger;
66

7-
use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab;
7+
use WPGraphQL\Logging\Logger\Rules\AdminUserRule;
8+
use WPGraphQL\Logging\Logger\Rules\EnabledRule;
9+
use WPGraphQL\Logging\Logger\Rules\IntrospectionQueryRule;
10+
use WPGraphQL\Logging\Logger\Rules\IpRestrictionsRule;
11+
use WPGraphQL\Logging\Logger\Rules\QueryNullRule;
12+
use WPGraphQL\Logging\Logger\Rules\RuleManager;
13+
use WPGraphQL\Logging\Logger\Rules\SamplingRateRule;
814

915
/**
1016
* Trait for shared logging helper methods.
17+
*
18+
* @package WPGraphQL\Logging
19+
*
20+
* @since 0.0.1
1121
*/
1222
trait LoggingHelper {
1323
/**
14-
* Checks if logging is enabled based on user settings.
15-
*
16-
* @param array<string, mixed> $config The logging configuration.
24+
* The rule manager instance.
1725
*
18-
* phpcs:disable Generic.Metrics.CyclomaticComplexity, SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
26+
* @var \WPGraphQL\Logging\Logger\Rules\RuleManager|null
1927
*/
20-
protected function is_logging_enabled( array $config, ?string $query_string = null ): bool {
21-
if ( null === $query_string ) {
22-
return false;
23-
}
24-
25-
$is_enabled = true;
26-
// Check the main "Enabled" checkbox.
27-
if ( ! (bool) ( $config[ Basic_Configuration_Tab::ENABLED ] ?? false ) ) {
28-
$is_enabled = false;
29-
}
28+
protected ?RuleManager $rule_manager = null;
3029

31-
// Do not log the seedQuery for Faust.js.
32-
if ( $is_enabled && ( 'query GetSeedNode' === trim( $query_string ) ) ) {
33-
$is_enabled = false;
34-
}
35-
36-
// Check if the current user is an admin if that option is enabled.
37-
if ( $is_enabled && ( (bool) ( $config[ Basic_Configuration_Tab::ADMIN_USER_LOGGING ] ?? false ) ) ) {
38-
if ( ! current_user_can( 'manage_options' ) ) {
39-
$is_enabled = false;
40-
}
41-
}
42-
43-
// Check for IP restrictions.
44-
$ip_restrictions = $config[ Basic_Configuration_Tab::IP_RESTRICTIONS ] ?? '';
45-
if ( $is_enabled && ! empty( $ip_restrictions ) ) {
46-
$allowed_ips = array_map( 'trim', explode( ',', $ip_restrictions ) );
47-
$remote_addr = $_SERVER['REMOTE_ADDR'] ?? ''; // @phpcs:ignore
48-
if ( ! in_array( $remote_addr, $allowed_ips, true ) ) {
49-
$is_enabled = false;
50-
}
30+
/**
31+
* Get the rule manager, initializing it if necessary.
32+
*/
33+
protected function get_rule_manager(): RuleManager {
34+
if ( null !== $this->rule_manager ) {
35+
return $this->rule_manager;
5136
}
37+
$this->rule_manager = new RuleManager();
38+
$this->rule_manager->add_rule( new QueryNullRule() );
39+
$this->rule_manager->add_rule( new SamplingRateRule() );
40+
$this->rule_manager->add_rule( new EnabledRule() );
41+
$this->rule_manager->add_rule( new AdminUserRule() );
42+
$this->rule_manager->add_rule( new IpRestrictionsRule() );
43+
$this->rule_manager->add_rule( new IntrospectionQueryRule() );
44+
apply_filters( 'wpgraphql_logging_rule_manager', $this->rule_manager );
45+
return $this->rule_manager;
46+
}
5247

53-
// Check the data sampling rate.
54-
if ( $is_enabled ) {
55-
$sampling_rate = (int) ( $config[ Basic_Configuration_Tab::DATA_SAMPLING ] ?? 100 );
56-
if ( wp_rand( 0, 100 ) >= $sampling_rate ) {
57-
$is_enabled = false;
58-
}
59-
}
48+
/**
49+
* Checks if logging is enabled based on user settings.
50+
*
51+
* @param array<string, mixed> $config The logging configuration.
52+
*/
53+
protected function is_logging_enabled( array $config, ?string $query_string = null ): bool {
6054

61-
// Check if the query is an introspection query and skip logging if it is.
62-
if ( $is_enabled && $this->is_introspection_query( $query_string ) ) {
63-
$is_enabled = false;
64-
}
55+
$is_enabled = $this->get_rule_manager()->all_rules_pass( $config, $query_string );
56+
wp_send_json_error( [
57+
'is_enabled' => $is_enabled,
58+
'query_string' => $query_string,
59+
], 200 );
6560

6661
/**
6762
* Filter the final decision on whether to log a request.
@@ -71,17 +66,4 @@ protected function is_logging_enabled( array $config, ?string $query_string = nu
7166
*/
7267
return apply_filters( 'wpgraphql_logging_is_enabled', $is_enabled, $config );
7368
}
74-
75-
/**
76-
* Checks if a query is an introspection query.
77-
*
78-
* @param string|null $query_string The GraphQL query string.
79-
*/
80-
protected function is_introspection_query( ?string $query_string ): bool {
81-
if ( null === $query_string ) {
82-
return false;
83-
}
84-
85-
return strpos( $query_string, '__schema' ) !== false;
86-
}
8769
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WPGraphQL\Logging\Logger\Rules;
6+
7+
use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab;
8+
9+
/**
10+
* Rule to check if logging should occur based on admin user setting.
11+
*
12+
* @package WPGraphQL\Logging
13+
*
14+
* @since 0.0.1
15+
*/
16+
class AdminUserRule implements LoggingRuleInterface {
17+
/**
18+
* Check if the rule passes.
19+
*
20+
* @param array<string, mixed> $config The logging configuration.
21+
* @param string|null $query_string The GraphQL query string.
22+
*
23+
* @return bool True if the rule passes (logging should continue).
24+
*/
25+
public function passes(array $config, ?string $query_string = null): bool {
26+
27+
$is_admin_user = (bool) ( $config[ Basic_Configuration_Tab::ADMIN_USER_LOGGING ] ?? false );
28+
if ( ! $is_admin_user ) {
29+
return true;
30+
}
31+
32+
return current_user_can( 'manage_options' );
33+
}
34+
35+
/**
36+
* Get the rule name for debugging.
37+
*/
38+
public function get_name(): string {
39+
return 'admin_user_rule';
40+
}
41+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WPGraphQL\Logging\Logger\Rules;
6+
7+
use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab;
8+
9+
/**
10+
* Rule to check if logging is enabled.
11+
*
12+
* @package WPGraphQL\Logging
13+
*
14+
* @since 0.0.1
15+
*/
16+
class EnabledRule implements LoggingRuleInterface {
17+
/**
18+
* Check if the rule passes.
19+
*
20+
* @param array<string, mixed> $config The logging configuration.
21+
* @param string|null $query_string The GraphQL query string.
22+
*
23+
* @return bool True if the rule passes (logging should continue).
24+
*/
25+
public function passes(array $config, ?string $query_string = null): bool {
26+
return (bool) ( $config[ Basic_Configuration_Tab::ENABLED ] ?? false );
27+
}
28+
29+
/**
30+
* Get the rule name for debugging.
31+
*/
32+
public function get_name(): string {
33+
return 'enabled_rule';
34+
}
35+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WPGraphQL\Logging\Logger\Rules;
6+
7+
/**
8+
* Rule to check if the query is an introspection query.
9+
*
10+
* @package WPGraphQL\Logging
11+
*
12+
* @since 0.0.1
13+
*/
14+
class IntrospectionQueryRule implements LoggingRuleInterface {
15+
/**
16+
* Check if the rule passes.
17+
*
18+
* @param array<string, mixed> $config The logging configuration.
19+
* @param string|null $query_string The GraphQL query string.
20+
*
21+
* @return bool True if the rule passes (logging should continue).
22+
*/
23+
public function passes(array $config, ?string $query_string = null): bool {
24+
return strpos( $query_string, '__schema' ) === false;
25+
}
26+
27+
/**
28+
* Get the rule name for debugging.
29+
*/
30+
public function get_name(): string {
31+
return 'introspection_query_rule';
32+
}
33+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WPGraphQL\Logging\Logger\Rules;
6+
7+
use WPGraphQL\Logging\Admin\Settings\Fields\Tab\Basic_Configuration_Tab;
8+
9+
/**
10+
* Rule to check if logging should occur based on IP restrictions.
11+
*
12+
* @package WPGraphQL\Logging
13+
*
14+
* @since 0.0.1
15+
*/
16+
class IpRestrictionsRule implements LoggingRuleInterface {
17+
/**
18+
* Check if the rule passes.
19+
*
20+
* @param array<string, mixed> $config The logging configuration.
21+
* @param string|null $query_string The GraphQL query string.
22+
*
23+
* @return bool True if the rule passes (logging should continue).
24+
*/
25+
public function passes(array $config, ?string $query_string = null): bool {
26+
27+
$ip_restrictions = $config[ Basic_Configuration_Tab::IP_RESTRICTIONS ] ?? '';
28+
if ( empty( $ip_restrictions ) ) {
29+
return true;
30+
}
31+
$allowed_ips = array_map( 'trim', explode( ',', $ip_restrictions ) );
32+
if ( empty( $allowed_ips ) ) {
33+
return true;
34+
}
35+
if ( ! isset( $_SERVER['REMOTE_ADDR'] ) ) { // @phpcs:ignore WordPressVIPMinimum.Variables.ServerVariables.UserControlledHeaders
36+
return false;
37+
}
38+
39+
$remote_addr = filter_var( $_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP ); // @phpcs:ignore WordPressVIPMinimum.Variables.ServerVariables.UserControlledHeaders, WordPressVIPMinimum.Variables.RestrictedVariables.cache_constraints___SERVER__REMOTE_ADDR__
40+
if ( false === $remote_addr ) {
41+
return false;
42+
}
43+
return in_array( $remote_addr, $allowed_ips, true );
44+
}
45+
46+
/**
47+
* Get the rule name for debugging.
48+
*/
49+
public function get_name(): string {
50+
return 'ip_restrictions_rule';
51+
}
52+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WPGraphQL\Logging\Logger\Rules;
6+
7+
/**
8+
* Interface for logging rules.
9+
*
10+
* @package WPGraphQL\Logging
11+
*
12+
* @since 0.0.1
13+
*/
14+
interface LoggingRuleInterface {
15+
/**
16+
* Check if the rule passes.
17+
*
18+
* @param array<string, mixed> $config The logging configuration.
19+
* @param string|null $query_string The GraphQL query string.
20+
*
21+
* @return bool True if the rule passes (logging should continue).
22+
*/
23+
public function passes(array $config, ?string $query_string = null): bool;
24+
25+
/**
26+
* Get the rule name for debugging.
27+
*/
28+
public function get_name(): string;
29+
}

0 commit comments

Comments
 (0)