diff --git a/plugins/wpgraphql-logging/README.md b/plugins/wpgraphql-logging/README.md
index f1d6ed0b..3a8de27c 100644
--- a/plugins/wpgraphql-logging/README.md
+++ b/plugins/wpgraphql-logging/README.md
@@ -89,7 +89,6 @@ wpgraphql-logging/
- **Monolog-powered logging pipeline**
- Default handler: stores logs in a WordPress table (`{$wpdb->prefix}wpgraphql_logging`).
- - Default processors: Memory usage, memory peak, web request, process ID, and `WPGraphQLQueryProcessor` (adds `wpgraphql_query`, `wpgraphql_operation_name`, `wpgraphql_variables`).
- **Simple developer API**
- `Plugin::on()` to subscribe, `Plugin::emit()` to publish, `Plugin::transform()` to modify payloads.
diff --git a/plugins/wpgraphql-logging/docs/Logging.md b/plugins/wpgraphql-logging/docs/Logging.md
index f703c660..6022859d 100644
--- a/plugins/wpgraphql-logging/docs/Logging.md
+++ b/plugins/wpgraphql-logging/docs/Logging.md
@@ -41,7 +41,7 @@ Processors add extra data to each log record. The plugin includes several defaul
- **MemoryPeakUsageProcessor** - Adds peak memory usage
- **WebProcessor** - Adds web request data (IP, method, URI, etc.)
- **ProcessIdProcessor** - Adds the process ID
-- **WPGraphQLQueryProcessor** - Adds GraphQL query, variables, and operation name
+- **RequestHeadersProcessor** - Adds requests headers
## Default Components
diff --git a/plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php b/plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php
index 664206c4..321de011 100644
--- a/plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php
+++ b/plugins/wpgraphql-logging/src/Admin/View/List/List_Table.php
@@ -128,7 +128,7 @@ public function process_bulk_action(): void {
$nonce_action = 'bulk-' . $this->_args['plural'];
$nonce_value = $_REQUEST['_wpnonce'] ?? '';
-
+
$nonce = is_string( $nonce_value ) ? $nonce_value : '';
$nonce_result = wp_verify_nonce( $nonce, $nonce_action );
@@ -156,42 +156,44 @@ public function process_bulk_action(): void {
$deleted_count = $count_before_delete;
}
- if ( $deleted_count > 0 ) {
- $preserved_filters = [];
- $filter_keys = [ 'level_filter', 'start_date', 'end_date' ];
+ if ( $deleted_count <= 0 ) {
+ return;
+ }
- foreach ( $filter_keys as $key ) {
- $value = $_REQUEST[ $key ] ?? null;
- if ( ! empty( $value ) && is_string( $value ) ) {
- $preserved_filters[ $key ] = sanitize_text_field( wp_unslash( $value ) );
- }
- }
+ $preserved_filters = [];
+ $filter_keys = [ 'level_filter', 'start_date', 'end_date' ];
- $redirect_url = remove_query_arg( [ 'action', 'action2', 'log', '_wpnonce' ] );
- $redirect_url = add_query_arg(
- array_merge(
- [ 'deleted_count' => $deleted_count ],
- $preserved_filters
- ),
- $redirect_url
- );
-
- if ( ! headers_sent() ) {
- wp_safe_redirect( esc_url_raw( $redirect_url ) );
- exit;
- } else {
- echo '';
- printf(
- '
',
- esc_html__( 'Logs deleted successfully.', 'wpgraphql-logging' ),
- esc_url( $redirect_url ),
- esc_html__( 'Return to Logs', 'wpgraphql-logging' )
- );
- exit;
+ foreach ( $filter_keys as $key ) {
+ $value = $_REQUEST[ $key ] ?? null;
+ if ( ! empty( $value ) && is_string( $value ) ) {
+ $preserved_filters[ $key ] = sanitize_text_field( wp_unslash( $value ) );
}
}
+
+ $redirect_url = remove_query_arg( [ 'action', 'action2', 'log', '_wpnonce' ] );
+ $redirect_url = add_query_arg(
+ array_merge(
+ [ 'deleted_count' => $deleted_count ],
+ $preserved_filters
+ ),
+ $redirect_url
+ );
+
+ if ( ! headers_sent() ) {
+ wp_safe_redirect( esc_url_raw( $redirect_url ) );
+ exit;
+ }
+
+ echo '';
+ printf(
+ '',
+ esc_html__( 'Logs deleted successfully.', 'wpgraphql-logging' ),
+ esc_url( $redirect_url ),
+ esc_html__( 'Return to Logs', 'wpgraphql-logging' )
+ );
+ exit;
}
-
+
/**
* Get the columns for the logs table.
*
@@ -475,7 +477,7 @@ protected function display_tablenav( $which ): void {
bulk_actions( $which_position ); ?>
-
+
extra_tablenav( $which );
$this->pagination( $which_position );
diff --git a/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php b/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php
index e56e9744..b35a13a7 100644
--- a/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php
+++ b/plugins/wpgraphql-logging/src/Events/QueryActionLogger.php
@@ -55,11 +55,11 @@ public function __construct( LoggerService $logger, array $config ) {
*
* This method hooks into the `do_graphql_request` action.
*
- * @param string $query
+ * @param string|null $query
* @param string|null $operation_name
* @param array|null $variables
*/
- public function log_pre_request( string $query, ?string $operation_name, ?array $variables ): void {
+ public function log_pre_request( ?string $query, ?string $operation_name, ?array $variables ): void {
try {
if ( ! $this->is_logging_enabled( $this->config, $query ) ) {
return;
@@ -114,7 +114,7 @@ public function log_graphql_before_execute( Request $request ): void {
if ( ! in_array( Events::BEFORE_GRAPHQL_EXECUTION, $selected_events, true ) ) {
return;
}
-
+
$payload = EventManager::transform( Events::BEFORE_GRAPHQL_EXECUTION, [
'context' => $context,
'level' => Level::Info,
@@ -135,7 +135,7 @@ public function log_graphql_before_execute( Request $request ): void {
* @param array|\GraphQL\Executor\ExecutionResult $response
* @param \WPGraphQL\WPSchema $schema
* @param string|null $operation
- * @param string $query
+ * @param string|null $query
* @param array|null $variables
* @param \WPGraphQL\Request $request
* @param string|null $query_id
@@ -145,7 +145,7 @@ public function log_before_response_returned(
array|ExecutionResult $response,
WPSchema $schema,
?string $operation,
- string $query,
+ ?string $query,
?array $variables,
Request $request,
?string $query_id
diff --git a/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php b/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php
index 83132411..d7f14398 100644
--- a/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php
+++ b/plugins/wpgraphql-logging/src/Logger/Database/LogsRepository.php
@@ -115,6 +115,6 @@ public function delete(int $id): bool {
public function delete_all(): void {
global $wpdb;
$table_name = DatabaseEntity::get_table_name();
- $wpdb->query( $wpdb->prepare( "DELETE FROM %i", $table_name ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
+ $wpdb->query( $wpdb->prepare( 'DELETE FROM %i', $table_name ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
}
}
diff --git a/plugins/wpgraphql-logging/src/Logger/LoggerService.php b/plugins/wpgraphql-logging/src/Logger/LoggerService.php
index bdc7d35d..30851de3 100644
--- a/plugins/wpgraphql-logging/src/Logger/LoggerService.php
+++ b/plugins/wpgraphql-logging/src/Logger/LoggerService.php
@@ -13,7 +13,6 @@
use Monolog\Processor\WebProcessor;
use WPGraphQL\Logging\Logger\Handlers\WordPressDatabaseHandler;
use WPGraphQL\Logging\Logger\Processors\RequestHeadersProcessor;
-use WPGraphQL\Logging\Logger\Processors\WPGraphQLQueryProcessor;
/**
* LoggerService class for managing the Monolog logger instance.
@@ -225,7 +224,6 @@ public static function get_default_processors(): array {
new MemoryPeakUsageProcessor(), // Logs memory peak data.
new WebProcessor(), // Logs web request data. e.g. IP address, request method, URI, etc.
new ProcessIdProcessor(), // Logs the process ID.
- new WPGraphQLQueryProcessor(), // Custom processor to capture GraphQL request data.
new RequestHeadersProcessor(), // Custom processor to capture request headers.
];
diff --git a/plugins/wpgraphql-logging/src/Logger/LoggingHelper.php b/plugins/wpgraphql-logging/src/Logger/LoggingHelper.php
index eaaa2eee..83d77685 100644
--- a/plugins/wpgraphql-logging/src/Logger/LoggingHelper.php
+++ b/plugins/wpgraphql-logging/src/Logger/LoggingHelper.php
@@ -18,12 +18,21 @@ trait LoggingHelper {
* phpcs:disable Generic.Metrics.CyclomaticComplexity, SlevomatCodingStandard.Complexity.Cognitive.ComplexityTooHigh
*/
protected function is_logging_enabled( array $config, ?string $query_string = null ): bool {
+ if ( null === $query_string ) {
+ return false;
+ }
+
$is_enabled = true;
// Check the main "Enabled" checkbox.
if ( ! (bool) ( $config[ Basic_Configuration_Tab::ENABLED ] ?? false ) ) {
$is_enabled = false;
}
+ // Do not log the seedQuery for Faust.js
+ if ( $is_enabled && ( 'query GetSeedNode' === trim( $query_string ) ) ) {
+ $is_enabled = false;
+ }
+
// Check if the current user is an admin if that option is enabled.
if ( $is_enabled && ( (bool) ( $config[ Basic_Configuration_Tab::ADMIN_USER_LOGGING ] ?? false ) ) ) {
if ( ! current_user_can( 'manage_options' ) ) {
diff --git a/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php b/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php
deleted file mode 100644
index 9fdfec6a..00000000
--- a/plugins/wpgraphql-logging/src/Logger/Processors/WPGraphQLQueryProcessor.php
+++ /dev/null
@@ -1,102 +0,0 @@
-|null
- */
- protected static ?array $variables = null;
-
- /**
- * The operation name for the current GraphQL request.
- *
- * @var string|null
- */
- protected static ?string $operation_name = null;
-
- /**
- * Constructor for the WPGraphQLQueryProcessor.
- *
- * This constructor sets up the necessary hooks to capture GraphQL request data and clear it after the request is completed.
- */
- public function __construct() {
- /**
- * @psalm-suppress HookNotFound
- */
- add_action( 'graphql_request_data', [ self::class, 'capture_request_data' ], 10, 1 ); // @phpstan-ignore-line
-
- /**
- * @psalm-suppress HookNotFound
- */
- add_action( 'graphql_process_http_request_response', [ self::class, 'clear_request_data' ], 999, 0 );
- }
-
- /**
- * Captures the GraphQL request data.
- *
- * @param array $request_data The raw request data from WPGraphQL.
- *
- * @return array The raw request data from WPGraphQL.
- */
- public static function capture_request_data(array $request_data): array {
- self::$query = $request_data['query'] ?? null;
- self::$variables = $request_data['variables'] ?? null;
- self::$operation_name = $request_data['operationName'] ?? null;
-
- return $request_data;
- }
-
- /**
- * Clears the stored GraphQL request data to ensure it does not persist across requests.
- */
- public static function clear_request_data(): void {
- self::$query = null;
- self::$variables = null;
- self::$operation_name = null;
- }
-
- /**
- * This method is called for each log record. It adds the captured
- * GraphQL data to the record's 'extra' array.
- *
- * @param \Monolog\LogRecord $record The log record to process.
- *
- * @return \Monolog\LogRecord The processed log record.
- */
- public function __invoke(LogRecord $record): LogRecord {
- if ( null !== self::$query ) {
- $record->extra['wpgraphql_query'] = self::$query;
- }
- if ( null !== self::$operation_name ) {
- $record->extra['wpgraphql_operation_name'] = self::$operation_name;
- }
- if ( null !== self::$variables ) {
- $record->extra['wpgraphql_variables'] = self::$variables;
- }
-
- return $record;
- }
-}
diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php
index 7b908d53..568681c3 100644
--- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php
+++ b/plugins/wpgraphql-logging/tests/wpunit/Logger/Handlers/WordPressDatabaseHandlerTest.php
@@ -12,7 +12,7 @@
use WPGraphQL\Logging\Logger\Handlers\WordPressDatabaseHandler;
/**
- * Class WPGraphQLQueryProcessorTest
+ * Class WordPressDatabaseHandlerTest
*
* Tests for the WordPressDatabaseHandler class.
*
diff --git a/plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php b/plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php
deleted file mode 100644
index 6e56b651..00000000
--- a/plugins/wpgraphql-logging/tests/wpunit/Logger/Processors/WPGraphQLQueryProcessorTest.php
+++ /dev/null
@@ -1,135 +0,0 @@
-get_test_record();
-
- $processed_record = $processor($record);
-
- $this->assertEmpty($processed_record->extra, 'Extra array should be empty when no data is captured.');
- }
-
- public function test_invoke_adds_captured_data_to_log_record(): void
- {
- $request_data = [
- 'query' => 'query TestQuery { posts { nodes { id } } }',
- 'variables' => ['first' => 10],
- 'operationName' => 'TestQuery',
- ];
-
- // Manually capture the data to simulate a GraphQL request starting.
- WPGraphQLQueryProcessor::capture_request_data($request_data);
-
- $processor = new WPGraphQLQueryProcessor();
- $record = $this->get_test_record();
-
- $processed_record = $processor($record);
-
- // Assert that the extra array contains the correct GraphQL data.
- $this->assertArrayHasKey('wpgraphql_query', $processed_record->extra);
- $this->assertEquals($request_data['query'], $processed_record->extra['wpgraphql_query']);
-
- $this->assertArrayHasKey('wpgraphql_operation_name', $processed_record->extra);
- $this->assertEquals($request_data['operationName'], $processed_record->extra['wpgraphql_operation_name']);
-
- $this->assertArrayHasKey('wpgraphql_variables', $processed_record->extra);
- $this->assertEquals($request_data['variables'], $processed_record->extra['wpgraphql_variables']);
- }
-
- public function test_clear_request_data_resets_static_properties(): void
- {
- // 1. Capture some data.
- WPGraphQLQueryProcessor::capture_request_data([
- 'query' => 'query Test { posts { nodes { id } } }'
- ]);
-
- // 2. Call the clear method.
- WPGraphQLQueryProcessor::clear_request_data();
-
- // 3. Use reflection to access the private static properties and check their values.
- $query_prop = new ReflectionProperty(WPGraphQLQueryProcessor::class, 'query');
- $query_prop->setAccessible(true);
- $this->assertNull($query_prop->getValue(), 'The static query property should be null after clearing.');
-
- $variables_prop = new ReflectionProperty(WPGraphQLQueryProcessor::class, 'variables');
- $variables_prop->setAccessible(true);
- $this->assertNull($variables_prop->getValue(), 'The static variables property should be null after clearing.');
-
- $operation_name_prop = new ReflectionProperty(WPGraphQLQueryProcessor::class, 'operation_name');
- $operation_name_prop->setAccessible(true);
- $this->assertNull($operation_name_prop->getValue(), 'The static operation_name property should be null after clearing.');
- }
-
- /**
- * @test
- * It should hook into WordPress actions upon instantiation.
- */
- public function test_constructor_hooks_into_wordpress_actions(): void
- {
- // Instantiate the processor to trigger its constructor.
- $processor = new WPGraphQLQueryProcessor();
-
- // Check if the hooks have been added correctly.
- $this->assertNotFalse(
- has_action('graphql_request_data', [WPGraphQLQueryProcessor::class, 'capture_request_data']),
- 'The capture_request_data method should be hooked to graphql_request_data.'
- );
-
- $this->assertNotFalse(
- has_action('graphql_process_http_request_response', [WPGraphQLQueryProcessor::class, 'clear_request_data']),
- 'The clear_request_data method should be hooked to graphql_process_http_request_response.'
- );
-
- // Clean up the hooks after the test.
- remove_action('graphql_request_data', [WPGraphQLQueryProcessor::class, 'capture_request_data'], 10);
- remove_action('graphql_process_http_request_response', [WPGraphQLQueryProcessor::class, 'clear_request_data'], 999);
- }
-
- /**
- * Helper method to get a basic LogRecord for testing.
- */
- private function get_test_record(): LogRecord
- {
- return new LogRecord(
- new DateTimeImmutable(),
- 'test-channel',
- Level::Debug,
- 'This is a test message.'
- );
- }
-}