$line) { // Pattern to match: Rsx::Route(...) . '?' or Rsx::Route(...) . "?" // This regex matches: // - Rsx::Route // - Opening parenthesis // - Any content (including nested parentheses) // - Closing parenthesis // - Optional whitespace // - Concatenation operator (.) // - Optional whitespace // - Single or double quote // - Question mark // Use a simpler pattern that looks for the specific sequence // We need to match Rsx::Route(...) followed by . '? or . "? // First, check if line contains both "Rsx::Route" and concatenation with query if (!str_contains($line, 'Rsx::Route')) { continue; } // Look for the pattern: Rsx::Route(...) . '?' or Rsx::Route(...) . "?" // This is a complex pattern because we need to match nested parentheses // Strategy: Find all occurrences of Rsx::Route on the line, then check what follows $pattern = '/Rsx::Route\s*\([^)]*(?:\([^)]*\)[^)]*)*\)\s*\.\s*[\'"][?]/'; if (preg_match($pattern, $line, $matches, PREG_OFFSET_CAPTURE)) { $matched_text = $matches[0][0]; $position = $matches[0][1]; // Add violation $this->add_violation( $file_path, $line_num + 1, "Query string concatenated onto Rsx::Route() call", $line, "Query parameters should be passed as the third argument to Rsx::Route() as an array.\n\n" . "WRONG:\n" . " Rsx::Route('Controller', 'method') . '?param=value&other=test'\n\n" . "CORRECT:\n" . " Rsx::Route('Controller', 'method', ['param' => 'value', 'other' => 'test'])\n\n" . "The framework will automatically URL-encode the parameters and construct the query string properly." ); } } } }