Files
rspade_system/app/RSpade/CodeQuality/Rules/PHP/RequestQueryInController_CodeQualityRule.php
root 77b4d10af8 Refactor filename naming system and apply convention-based renames
Standardize settings file naming and relocate documentation files
Fix code quality violations from rsx:check
Reorganize user_management directory into logical subdirectories
Move Quill Bundle to core and align with Tom Select pattern
Simplify Site Settings page to focus on core site information
Complete Phase 5: Multi-tenant authentication with login flow and site selection
Add route query parameter rule and synchronize filename validation logic
Fix critical bug in UpdateNpmCommand causing missing JavaScript stubs
Implement filename convention rule and resolve VS Code auto-rename conflict
Implement js-sanitizer RPC server to eliminate 900+ Node.js process spawns
Implement RPC server architecture for JavaScript parsing
WIP: Add RPC server infrastructure for JS parsing (partial implementation)
Update jqhtml terminology from destroy to stop, fix datagrid DOM preservation
Add JQHTML-CLASS-01 rule and fix redundant class names
Improve code quality rules and resolve violations
Remove legacy fatal error format in favor of unified 'fatal' error type
Filter internal keys from window.rsxapp output
Update button styling and comprehensive form/modal documentation
Add conditional fly-in animation for modals
Fix non-deterministic bundle compilation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 19:10:02 +00:00

198 lines
6.4 KiB
PHP
Executable File

<?php
/**
* CODING CONVENTION:
* This file follows the coding convention where variable_names and function_names
* use snake_case (underscore_wherever_possible).
*/
// @ROUTE-EXISTS-01-EXCEPTION
namespace App\RSpade\CodeQuality\Rules\PHP;
use App\RSpade\CodeQuality\Rules\CodeQualityRule_Abstract;
use App\RSpade\Core\Manifest\Manifest;
/**
* RequestQueryInController_CodeQualityRule - Detect $request->query() usage in controllers
*
* This rule detects patterns where $request->query() is used in controller methods.
* Controllers should use the $params array which contains combined values from:
* - Route parameters extracted from the URL (e.g., /myroute/:code)
* - GET query parameters (e.g., ?code=value)
*
* The $params array is automatically populated by the framework and passed to all
* controller methods.
*/
class RequestQueryInController_CodeQualityRule extends CodeQualityRule_Abstract
{
/**
* Get the unique identifier for this rule
*
* @return string
*/
public function get_id(): string
{
return 'PHP-CONTROLLER-REQUEST-01';
}
/**
* Get the default severity level
*
* @return string One of: critical, high, medium, low, convention
*/
public function get_default_severity(): string
{
return 'high';
}
/**
* Get the file patterns this rule applies to
*
* @return array
*/
public function get_file_patterns(): array
{
return ['*.php'];
}
/**
* Get the display name for this rule
*
* @return string
*/
public function get_name(): string
{
return 'Request Query Parameter Detection in Controllers';
}
/**
* Get the description of what this rule checks
*
* @return string
*/
public function get_description(): string
{
return 'Detects $request->query() usage in controller classes and suggests using $params instead';
}
/**
* Check if this rule should be called during manifest scan
*
* This rule runs at manifest-time to catch incorrect parameter access
* immediately in controller methods.
*
* @return bool
*/
public function is_called_during_manifest_scan(): bool
{
return true;
}
/**
* Check the file contents for violations
*
* @param string $file_path The path to the file being checked
* @param string $contents The contents of the file
* @param array $metadata Additional metadata about the file
* @return void
*/
public function check(string $file_path, string $contents, array $metadata = []): void
{
// Only check files in rsx/ directory
if (!str_contains($file_path, '/rsx/')) {
return;
}
// Skip if no class or no FQCN
if (!isset($metadata['fqcn'])) {
return;
}
// Check if this class extends Rsx_Controller_Abstract
if (!$this->is_controller_descendant($metadata['fqcn'])) {
return;
}
// Check for $request->query( usage
$lines = explode("\n", $contents);
foreach ($lines as $line_num => $line) {
// Look for $request->query( pattern
if (preg_match('/\$request\s*->\s*query\s*\(/', $line)) {
// Add violation
$this->add_violation(
$file_path,
$line_num + 1,
"\$request->query() used in controller method",
$line,
"Controller methods should use the \$params array instead of \$request->query().\n\n" .
"The \$params array contains combined values from:\n" .
"- Route parameters extracted from the URL (e.g., /myroute/:code)\n" .
"- GET query parameters (e.g., ?code=value)\n\n" .
"WRONG:\n" .
" public static function index(Request \$request, array \$params = [])\n" .
" {\n" .
" \$code = \$request->query('code');\n" .
" \$page = \$request->query('page');\n" .
" }\n\n" .
"CORRECT:\n" .
" public static function index(Request \$request, array \$params = [])\n" .
" {\n" .
" \$code = \$params['code'] ?? null;\n" .
" \$page = \$params['page'] ?? null;\n" .
" }\n\n" .
"WHY USE \$params:\n" .
"- Works with both route parameters (/users/:id) and query strings (?id=5)\n" .
"- Unified API for all parameter access\n" .
"- Automatically populated by the framework\n" .
"- Consistent with RSX controller conventions"
);
}
}
}
/**
* Check if a class is a descendant of Rsx_Controller_Abstract
*
* @param string $fqcn Fully qualified class name
* @return bool
*/
private function is_controller_descendant(string $fqcn): bool
{
// Check if class is loaded
if (!class_exists($fqcn, false)) {
// Try to load from manifest metadata
try {
$metadata = Manifest::php_get_metadata_by_fqcn($fqcn);
$parent = $metadata['extends'] ?? null;
// Walk up the inheritance chain
while ($parent) {
if ($parent === 'Rsx_Controller_Abstract' ||
$parent === 'App\\RSpade\\Core\\Controller\\Rsx_Controller_Abstract') {
return true;
}
// Try to get parent's metadata
try {
$parent_metadata = Manifest::php_get_metadata_by_class($parent);
$parent = $parent_metadata['extends'] ?? null;
} catch (\Exception $e) {
// Parent not found in manifest
break;
}
}
} catch (\Exception $e) {
// Class not found in manifest
return false;
}
} else {
// Class is loaded, use reflection
$reflection = new \ReflectionClass($fqcn);
return $reflection->isSubclassOf('App\\RSpade\\Core\\Controller\\Rsx_Controller_Abstract');
}
return false;
}
}