1+ <?php
2+ /**
3+ * Extends WPGraphQL's Query Analyzer to add custom heuristic rules and metrics.
4+ *
5+ * @package WPGraphQL\Debug
6+ */
7+
8+ declare (strict_types=1 );
9+
10+ namespace WPGraphQL \Debug \Analysis ;
11+
12+ use WPGraphQL \Utils \QueryAnalyzer as OriginalQueryAnalyzer ;
13+ use WPGraphQL \Request ;
14+ use GraphQL \Type \Schema ;
15+
16+ /**
17+ * Class QueryAnalyzerExtension
18+ *
19+ * This class hooks into the WPGraphQL Query Analyzer to add custom analysis.
20+ */
21+ class QueryAnalyzer {
22+
23+ /**
24+ * @var QueryAnalyzer The instance of the WPGraphQL Query Analyzer.
25+ */
26+ protected OriginalQueryAnalyzer $ query_analyzer ;
27+
28+ /**
29+ * Constructor for the QueryAnalyzerExtension.
30+ *
31+ * @param OriginalQueryAnalyzer $query_analyzer The instance of the WPGraphQL Query Analyzer.
32+ */
33+ public function __construct ( OriginalQueryAnalyzer $ query_analyzer ) {
34+ $ this ->query_analyzer = $ query_analyzer ;
35+ }
36+
37+ /**
38+ * Initializes the extension by adding necessary WordPress hooks.
39+ */
40+ public function init (): void {
41+ add_filter ( 'graphql_query_analyzer_graphql_keys ' , [ $ this , 'addMetricsToAnalyzerOutput ' ], 10 , 5 );
42+ }
43+
44+ /**
45+ * Adds new metrics and analysis results to the Query Analyzer's output.
46+ * This method is a callback for the 'graphql_query_analyzer_graphql_keys' filter.
47+ *
48+ * @param array<string,mixed> $graphql_keys Existing data from the Query Analyzer.
49+ * @param string $return_keys The keys returned to the X-GraphQL-Keys header.
50+ * @param string $skipped_keys The keys that were skipped.
51+ * @param string[] $return_keys_array The keys returned in array format.
52+ * @param string[] $skipped_keys_array The keys skipped in array format.
53+ * @return array<string,mixed> The modified GraphQL keys with custom metrics.
54+ */
55+ public function addMetricsToAnalyzerOutput (
56+ array $ graphql_keys ,
57+ string $ return_keys ,
58+ string $ skipped_keys ,
59+ array $ return_keys_array ,
60+ array $ skipped_keys_array
61+ ): array {
62+ // Simulate deeply nested queries check
63+ $ hasDeepNesting = $ this ->analyzeNestingDepth ();
64+
65+ // Simulate excessive field selection check
66+ $ hasExcessiveFields = $ this ->analyzeFieldSelection ();
67+
68+ // Simulate a custom complexity score calculation
69+ $ customComplexityScore = $ this ->calculateCustomComplexity ();
70+
71+ // Add your custom data under a new key within the 'queryAnalyzer' extension.
72+ $ graphql_keys ['DebugExtensionsAnalysis ' ] = [
73+ 'heuristicRules ' => [
74+ 'deepNestingDetected ' => $ hasDeepNesting ,
75+ 'excessiveFieldsDetected ' => $ hasExcessiveFields ,
76+ ],
77+ 'performanceMetrics ' => [
78+ 'customComplexityScore ' => $ customComplexityScore ,
79+ 'dummyMemoryUsageKB ' => rand ( 1024 , 8192 ),
80+ 'dummyExecutionTimeMs ' => rand ( 50 , 500 ),
81+ ],
82+ ];
83+
84+ return $ graphql_keys ;
85+ }
86+
87+ /**
88+ * Placeholder method to simulate analysis of nesting depth.
89+ * In a real implementation, this would parse the query AST
90+ * and determine nesting levels.
91+ *
92+ * @return bool True if deep nesting is detected, false otherwise.
93+ */
94+ protected function analyzeNestingDepth (): bool {
95+ // For now, return a random boolean for demonstration.
96+ return (bool ) rand ( 0 , 1 );
97+ }
98+
99+ /**
100+ * Placeholder method to simulate analysis of excessive field selection.
101+ * In a real implementation, this would count fields selected per type
102+ * and compare against a threshold.
103+ *
104+ * @return bool True if excessive fields are detected, false otherwise.
105+ */
106+ protected function analyzeFieldSelection (): bool {
107+ // For now, return a random boolean for demonstration.
108+ return (bool ) rand ( 0 , 1 );
109+ }
110+
111+ /**
112+ * Placeholder method to simulate a custom complexity score calculation.
113+ * This could combine factors like nesting, field count, list fetches, etc.
114+ *
115+ * @return int A dummy complexity score.
116+ */
117+ protected function calculateCustomComplexity (): int {
118+ // For now, return a random integer.
119+ return rand ( 100 , 1000 );
120+ }
121+ }
0 commit comments