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
88declare (strict_types=1 );
99
1010namespace WPGraphQL \Debug \Analysis ;
1111
12- use WPGraphQL \Debug \Analysis \Metrics \ Complexity ;
12+ use WPGraphQL \Debug \Analysis \Interfaces \ AnalyzerItemInterface ;
1313use 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 */
2020class 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