Files
rspade_system/app/RSpade/CodeQuality/Rules/Jqhtml/JqhtmlComponentNaming_CodeQualityRule.php
root 9ebcc359ae Fix code quality violations and enhance ROUTE-EXISTS-01 rule
Implement JQHTML function cache ID system and fix bundle compilation
Implement underscore prefix for system tables
Fix JS syntax linter to support decorators and grant exception to Task system
SPA: Update planning docs and wishlists with remaining features
SPA: Document Navigation API abandonment and future enhancements
Implement SPA browser integration with History API (Phase 1)
Convert contacts view page to SPA action
Convert clients pages to SPA actions and document conversion procedure
SPA: Merge GET parameters and update documentation
Implement SPA route URL generation in JavaScript and PHP
Implement SPA bootstrap controller architecture
Add SPA routing manual page (rsx:man spa)
Add SPA routing documentation to CLAUDE.md
Phase 4 Complete: Client-side SPA routing implementation
Update get_routes() consumers for unified route structure
Complete SPA Phase 3: PHP-side route type detection and is_spa flag
Restore unified routes structure and Manifest_Query class
Refactor route indexing and add SPA infrastructure
Phase 3 Complete: SPA route registration in manifest
Implement SPA Phase 2: Extract router code and test decorators
Rename Jqhtml_Component to Component and complete SPA foundation setup

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 17:48:15 +00:00

172 lines
6.0 KiB
PHP
Executable File

<?php
namespace App\RSpade\CodeQuality\Rules\Jqhtml;
use App\RSpade\CodeQuality\Rules\CodeQualityRule_Abstract;
use App\RSpade\Core\Manifest\Manifest;
/**
* JQHTML Component Naming Rule
*
* Enforces that all jqhtml component names start with an uppercase letter.
* This is a hard requirement of the jqhtml library.
*/
class JqhtmlComponentNaming_CodeQualityRule extends CodeQualityRule_Abstract
{
/**
* Get the unique identifier for this rule
*/
public function get_id(): string
{
return 'JQHTML-NAMING-01';
}
/**
* Get the human-readable name of this rule
*/
public function get_name(): string
{
return 'JQHTML Component Names Must Start Uppercase';
}
/**
* Get the description of what this rule checks
*/
public function get_description(): string
{
return 'Ensures all jqhtml component names start with an uppercase letter (library requirement)';
}
/**
* Get file patterns this rule should check
*/
public function get_file_patterns(): array
{
return ['*.jqhtml', '*.js'];
}
/**
* This rule should run at manifest-time for immediate feedback
* since incorrect naming would break the jqhtml library
*/
public function is_called_during_manifest_scan(): bool
{
return true; // Critical library requirement
}
/**
* Check the file for violations
*/
public function check(string $file_path, string $contents, array $metadata = []): void
{
// Check .jqhtml files for Define: tags
if (str_ends_with($file_path, '.jqhtml')) {
$this->check_jqhtml_file($file_path, $contents);
}
// Check .js files for classes extending Component
if (str_ends_with($file_path, '.js')) {
$this->check_javascript_file($file_path, $contents, $metadata);
}
}
/**
* Check jqhtml template files
*/
private function check_jqhtml_file(string $file_path, string $contents): void
{
$lines = explode("\n", $contents);
$line_number = 0;
foreach ($lines as $line) {
$line_number++;
// Look for <Define:ComponentName> tags
if (preg_match('/<Define:([a-zA-Z_][a-zA-Z0-9_]*)>/', $line, $matches)) {
$component_name = $matches[1];
// Check if first character is not uppercase
if (!ctype_upper($component_name[0])) {
$this->add_violation(
$file_path,
$line_number,
"JQHTML component name '{$component_name}' must start with an uppercase letter",
trim($line),
"Change '{$component_name}' to '" . ucfirst($component_name) . "'. This is a hard requirement of the jqhtml library - component names MUST start with an uppercase letter.",
'critical'
);
}
}
}
}
/**
* Check JavaScript files for Component subclasses
*/
private function check_javascript_file(string $file_path, string $contents, array $metadata = []): void
{
$lines = explode("\n", $contents);
$line_number = 0;
// Get JavaScript class from manifest metadata
$js_classes = [];
if (isset($metadata['class']) && isset($metadata['extension']) && $metadata['extension'] === 'js') {
$js_classes = [$metadata['class']];
}
// If no classes in metadata, nothing to check for class definitions
if (!empty($js_classes)) {
// Find line numbers for each class
$class_definitions = [];
foreach ($js_classes as $class_name) {
// Find where this class is defined in the source
foreach ($lines as $idx => $line) {
if (preg_match('/class\s+' . preg_quote($class_name, '/') . '\s+/', $line)) {
$class_definitions[$class_name] = $idx + 1;
break;
}
}
}
// Check each class to see if it's a JQHTML component
foreach ($class_definitions as $class_name => $line_num) {
// Use Manifest to check if this is a JQHTML component (handles indirect inheritance)
if (Manifest::js_is_subclass_of($class_name, 'Component')) {
// Check if first character is not uppercase
if (!ctype_upper($class_name[0])) {
$this->add_violation(
$file_path,
$line_num,
"JQHTML component class '{$class_name}' must start with an uppercase letter",
trim($lines[$line_num - 1]),
"Change '{$class_name}' to '" . ucfirst($class_name) . "'. This is a hard requirement of the jqhtml library - component names MUST start with an uppercase letter.",
'critical'
);
}
}
}
}
// Still check for component registration patterns
foreach ($lines as $line) {
$line_number++;
// Also check for component registration patterns
if (preg_match('/jqhtml\.component\([\'"]([a-zA-Z_][a-zA-Z0-9_]*)[\'"]/', $line, $matches)) {
$component_name = $matches[1];
if (!ctype_upper($component_name[0])) {
$this->add_violation(
$file_path,
$line_number,
"JQHTML component registration '{$component_name}' must use uppercase name",
trim($line),
"Change '{$component_name}' to '" . ucfirst($component_name) . "'. This is a hard requirement of the jqhtml library - component names MUST start with an uppercase letter.",
'critical'
);
}
}
}
}
}