pre_rules_mvc.py
- Pfad:
/var/www/tools/ki-protokoll/claude-hook/quality/pre_rules_mvc.py - Namespace: claude-hook.quality
- Zeilen: 114 | Größe: 3,318 Bytes
- Geändert: 2025-12-25 16:59:36 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 100
- Dependencies: 100 (25%)
- LOC: 100 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 5
- use re
- use typing.Optional
- use rule_base.GLOBAL_ALLOWLIST
- use rule_base.is_in_allowlist
- use rule_base.block
Funktionen 4
-
p2_1_no_sql_in_controller()Zeile 17 -
p2_2_no_transactions_in_controller()Zeile 38 -
p2_3_no_echo_in_controller()Zeile 59 -
p2_4_no_db_in_usecases()Zeile 80
Code
#!/usr/bin/env python3
"""
Pre-Hook MVC Regeln (BLOCK) - Controller-Reinheit.
P2.x Regeln: MVC-Trennung, keine SQL/Transaktionen/Output in Controller
"""
import re
from typing import Optional
from .rule_base import GLOBAL_ALLOWLIST, is_in_allowlist, block
# =============================================================================
# PRÜFUNG 2: MVC + CRUD
# =============================================================================
def p2_1_no_sql_in_controller(file_path: str, content: str) -> Optional[dict]:
"""P2.1: Keine SQL-Statements in Controller."""
if "/Controller/" not in file_path:
return None
if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):
return None
sql_patterns = [
r"\bSELECT\s+.+\s+FROM\b",
r"\bINSERT\s+INTO\b",
r"\bUPDATE\s+\w+\s+SET\b",
r"\bDELETE\s+FROM\b",
]
for pattern in sql_patterns:
if re.search(pattern, content, re.IGNORECASE):
return block("P2.1", "SQL statement in Controller. Move to Repository.")
return None
def p2_2_no_transactions_in_controller(file_path: str, content: str) -> Optional[dict]:
"""P2.2: Keine Transaktionen in Controller."""
if "/Controller/" not in file_path:
return None
if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):
return None
transaction_patterns = [
r"\bbeginTransaction\s*\(",
r"\bcommit\s*\(",
r"\brollBack\s*\(",
r"\brollback\s*\(",
]
for pattern in transaction_patterns:
if re.search(pattern, content):
return block("P2.2", "Transaction control in Controller. Move to UseCase or Repository.")
return None
def p2_3_no_echo_in_controller(file_path: str, content: str) -> Optional[dict]:
"""P2.3: Kein echo/print in Controller."""
if "/Controller/" not in file_path:
return None
if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):
return None
output_patterns = [
r"\becho\s+",
r"\becho\(",
r"\bprint\s+",
r"\bprint\(",
]
for pattern in output_patterns:
if re.search(pattern, content):
return block("P2.3", "Direct output (echo/print) in Controller. Use Response object.")
return None
def p2_4_no_db_in_usecases(file_path: str, content: str) -> Optional[dict]:
"""P2.4: Keine DB-Artefakte in UseCases."""
if "/UseCases/" not in file_path and "/Application/" not in file_path:
return None
if is_in_allowlist(file_path, GLOBAL_ALLOWLIST):
return None
db_patterns = [
r"\bnew\s+PDO\b",
r"\bPDO::",
r"\bDatabaseFactory::",
r"\bSELECT\s+.+\s+FROM\b",
r"\bINSERT\s+INTO\b",
r"\bUPDATE\s+\w+\s+SET\b",
r"\bDELETE\s+FROM\b",
]
for pattern in db_patterns:
if re.search(pattern, content, re.IGNORECASE):
return block("P2.4", "DB artifact in UseCase/Application. Use Repository interface.")
return None
# =============================================================================
# RULE COLLECTION
# =============================================================================
RULES = [
p2_1_no_sql_in_controller,
p2_2_no_transactions_in_controller,
p2_3_no_echo_in_controller,
p2_4_no_db_in_usecases,
]