Skip to content

Commit fe3fe2f

Browse files
authored
Merge pull request #358 from wpengine/feature-debug-extensions-unfiltered-lists-rule
feat: UnfilteredLists rule
2 parents c2ef979 + dff45ba commit fe3fe2f

File tree

6 files changed

+404
-218
lines changed

6 files changed

+404
-218
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Interface for a debug extension analyzer item (metric or rule).
4+
*
5+
* @package WPGraphQL\Debug\Analysis\Interfaces
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace WPGraphQL\Debug\Analysis\Interfaces;
11+
12+
use GraphQL\Type\Schema;
13+
14+
interface AnalyzerItemInterface {
15+
/**
16+
* Executes the analysis (calculates metric or evaluates rule).
17+
*
18+
* @param string $query The GraphQL query string.
19+
* @param array<string,mixed> $variables Optional: Variables provided with the query.
20+
* @param Schema|null $schema Optional: The GraphQL schema.
21+
* @return array<string,mixed> An associative array representing the analysis result.
22+
* For metrics, it might contain 'value' and 'note'.
23+
* For rules, it might contain 'triggered' and 'message'.
24+
*/
25+
public function analyze( string $query, array $variables = [], ?Schema $schema = null ): array;
26+
27+
/**
28+
* Returns the key under which this item's result should appear in the 'debugExtensions' output.
29+
* E.g., 'complexity', 'nestedQueryRule', 'excessiveFieldsRule'.
30+
*
31+
* @return string The unique key for the analyzer item.
32+
*/
33+
public function getKey(): string;
34+
}

plugins/wpgraphql-debug-extensions/src/Analysis/Metrics/Complexity.php

Lines changed: 0 additions & 143 deletions
This file was deleted.

plugins/wpgraphql-debug-extensions/src/Analysis/QueryAnalyzer.php

Lines changed: 86 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,113 @@
22
/**
33
* Extends WPGraphQL's Query Analyzer to add custom heuristic rules and metrics.
44
*
5-
* @package WPGraphQL\Debug
5+
* @package WPGraphQL\Debug\Analysis
66
*/
77

88
declare(strict_types=1);
99

1010
namespace WPGraphQL\Debug\Analysis;
1111

12-
use WPGraphQL\Debug\Analysis\Metrics\Complexity;
12+
use WPGraphQL\Debug\Analysis\Interfaces\AnalyzerItemInterface;
1313
use WPGraphQL\Utils\QueryAnalyzer as OriginalQueryAnalyzer;
1414

1515
/**
16-
* Class QueryAnalyzerExtension
16+
* Class QueryAnalyzer
1717
*
1818
* This class hooks into the WPGraphQL Query Analyzer to add custom analysis.
1919
*/
2020
class QueryAnalyzer {
2121

22-
/**
23-
* @var QueryAnalyzer The instance of the WPGraphQL Query Analyzer.
24-
*/
25-
protected OriginalQueryAnalyzer $query_analyzer;
22+
/**
23+
* @var OriginalQueryAnalyzer The instance of the WPGraphQL Query Analyzer from the core plugin.
24+
*/
25+
protected OriginalQueryAnalyzer $query_analyzer;
2626

27-
/**
28-
* @var string|null The GraphQL query string for the current request.
29-
*/
30-
protected ?string $currentQuery = null;
27+
/**
28+
* @var AnalyzerItemInterface[] An array of registered analyzer items (metrics and rules).
29+
*/
30+
protected array $analyzerItems = [];
3131

32-
/**
33-
* @var array<string,mixed> The variables for the current GraphQL request.
34-
*/
35-
protected array $currentVariables = [];
32+
/**
33+
* Constructor for the QueryAnalyzerExtension.
34+
*
35+
* @param OriginalQueryAnalyzer $query_analyzer The instance of the WPGraphQL Query Analyzer.
36+
*/
37+
public function __construct( OriginalQueryAnalyzer $query_analyzer ) {
38+
$this->query_analyzer = $query_analyzer;
39+
}
3640

37-
/**
38-
* Constructor for the QueryAnalyzerExtension.
39-
*
40-
* @param OriginalQueryAnalyzer $query_analyzer The instance of the WPGraphQL Query Analyzer.
41-
*/
42-
public function __construct( OriginalQueryAnalyzer $query_analyzer ) {
43-
$this->query_analyzer = $query_analyzer;
44-
}
41+
/**
42+
* Adds an AnalyzerItem (metric or rule) to be processed.
43+
*
44+
* @param AnalyzerItemInterface $item The item to add.
45+
* @return void
46+
*/
47+
public function addAnalyzerItem( AnalyzerItemInterface $item ): void {
48+
$this->analyzerItems[] = $item;
49+
}
4550

46-
/**
47-
* Initializes the extension by adding necessary WordPress hooks.
48-
*/
49-
public function init(): void {
50-
add_filter( 'graphql_query_analyzer_graphql_keys', [ $this, 'addMetricsToAnalyzerOutput' ], 10, 5 );
51-
}
51+
/**
52+
* Initializes the extension by adding necessary WordPress hooks.
53+
*/
54+
public function init(): void {
55+
// This filter allows us to inject custom data into the 'debugExtensions' part of the GraphQL response.
56+
add_filter( 'graphql_query_analyzer_graphql_keys', [ $this, 'addAnalysisToOutput' ], 10, 5 );
57+
}
5258

53-
/**
54-
* Adds new metrics and analysis results to the Query Analyzer's output.
55-
* This method is a callback for the 'graphql_query_analyzer_graphql_keys' filter.
56-
*
57-
* @param array<string,mixed> $graphql_keys Existing data from the Query Analyzer.
58-
* @param string $return_keys The keys returned to the X-GraphQL-Keys header.
59-
* @param string $skipped_keys The keys that were skipped.
60-
* @param string[] $return_keys_array The keys returned in array format.
61-
* @param string[] $skipped_keys_array The keys skipped in array format.
62-
* @return array<string,mixed> The modified GraphQL keys with custom metrics.
63-
*/
64-
public function addMetricsToAnalyzerOutput(
65-
array $graphql_keys,
66-
string $return_keys,
67-
string $skipped_keys,
68-
array $return_keys_array,
69-
array $skipped_keys_array
70-
): array {
71-
$complexityValue = null;
72-
$complexityNote = 'Could not compute complexity';
59+
/**
60+
* Adds new metrics and analysis results to the Query Analyzer's output.
61+
* This method is a callback for the 'graphql_query_analyzer_graphql_keys' filter.
62+
*
63+
* @param array<string,mixed> $graphql_keys Existing data from the Query Analyzer.
64+
* @param string $return_keys The keys returned to the X-GraphQL-Keys header. (unused here)
65+
* @param string $skipped_keys The keys that were skipped. (unused here)
66+
* @param string[] $return_keys_array The keys returned in array format. (unused here)
67+
* @param string[] $skipped_keys_array The keys skipped in array format. (unused here)
68+
* @return array<string,mixed> The modified GraphQL keys with custom metrics.
69+
*/
70+
public function addAnalysisToOutput(
71+
array $graphql_keys,
72+
string $return_keys, // Keep for filter signature, but not used.
73+
string $skipped_keys, // Keep for filter signature, but not used.
74+
array $return_keys_array, // Keep for filter signature, but not used.
75+
array $skipped_keys_array // Keep for filter signature, but not used.
76+
): array {
77+
if ( ! isset( $graphql_keys['debugExtensions'] ) ) {
78+
$graphql_keys['debugExtensions'] = [];
79+
}
7380

74-
$request = $this->query_analyzer->get_request();
75-
$currentQuery = $request->params->query ?? null;
76-
$currentVariables = (array) ( $request->params->variables ?? [] );
81+
$request = $this->query_analyzer->get_request();
82+
$currentQuery = $request->params->query ?? null;
83+
$currentVariables = (array) ( $request->params->variables ?? [] );
84+
$schema = $this->query_analyzer->get_schema();
7785

78-
// Add some logging to debug.
79-
error_log( 'QueryAnalyzerExtension: addCustomMetricsToAnalyzerOutput called.' );
80-
error_log( 'QueryAnalyzerExtension: Retrieved Query: ' . ( $currentQuery ?? 'NULL' ) );
81-
error_log( 'QueryAnalyzerExtension: Retrieved Variables: ' . print_r( $currentVariables, true ) );
82-
if ( ! empty( $currentQuery ) ) {
83-
try {
84-
$complexityMetrics = new Complexity();
85-
$schema = $this->query_analyzer->get_schema();
86-
$complexityValue = $complexityMetrics->calculate( $currentQuery, $currentVariables, $schema );
86+
foreach ( $this->analyzerItems as $item ) {
87+
try {
88+
if ( ! empty( $currentQuery ) ) {
89+
$result = $item->analyze( $currentQuery, $currentVariables, $schema );
90+
} else {
91+
$result = [
92+
'value' => null,
93+
'note' => 'No query provided for analysis.',
94+
];
95+
}
96+
} catch ( \Exception $e ) {
97+
error_log( sprintf(
98+
'WPGraphQL Debug Extensions: Analysis item "%s" failed: %s',
99+
$item->getKey(),
100+
$e->getMessage()
101+
) );
102+
$result = [
103+
'value' => null,
104+
'note' => 'Analysis failed: ' . $e->getMessage(),
105+
'error' => true,
106+
];
107+
}
87108

88-
} catch (\Exception $e) {
89-
error_log( 'WPGraphQL Debug Extensions: Complexity calculation failed: ' . $e->getMessage() );
90-
$complexityNote .= ': ' . $e->getMessage();
91-
}
92-
}
93-
if ( ! isset( $graphql_keys['debugExtensions'] ) ) {
94-
$graphql_keys['debugExtensions'] = [];
95-
}
96-
$graphql_keys['debugExtensions']['complexity'] = $complexityValue;
109+
$graphql_keys['debugExtensions'][ $item->getKey() ] = $result;
110+
}
97111

98-
return $graphql_keys;
99-
}
112+
return $graphql_keys;
113+
}
100114
}

0 commit comments

Comments
 (0)