# Classes/AGENTS.md **Scope:** PHP backend components (Controllers, EventListeners, DataHandling, Utils) **Parent:** [../AGENTS.md](../AGENTS.md) ## 📋 Overview PHP backend implementation for TYPO3 CKEditor Image extension. Components: ### Controllers - **SelectImageController** - Image browser wizard, file selection, image info API - **ImageRenderingController** - Image rendering and processing for frontend - **ImageLinkRenderingController** - Link-wrapped image rendering ### EventListeners - **RteConfigurationListener** - PSR-14 event for RTE configuration injection ### DataHandling - **RteImagesDbHook** - Database hooks for image magic reference handling - **RteImageSoftReferenceParser** - Soft reference parsing for RTE images ### Backend Components - **RteImagePreviewRenderer** - Backend preview rendering ### Utilities - **ProcessedFilesHandler** - File processing and manipulation utilities ## 🏗️ Architecture Patterns ### TYPO3 Patterns - **FAL (File Abstraction Layer):** All file operations via ResourceFactory - **PSR-7 Request/Response:** HTTP message interfaces for controllers - **PSR-14 Events:** Event-driven configuration and hooks - **Dependency Injection:** Constructor-based DI (TYPO3 v13+) - **Service Configuration:** `Configuration/Services.yaml` for DI registration ### File Structure ``` Classes/ ├── Backend/ │ └── Preview/ │ └── RteImagePreviewRenderer.php ├── Controller/ │ ├── ImageLinkRenderingController.php │ ├── ImageRenderingController.php │ └── SelectImageController.php ├── DataHandling/ │ └── SoftReference/ │ └── RteImageSoftReferenceParser.php ├── Database/ │ └── RteImagesDbHook.php ├── EventListener/ │ └── RteConfigurationListener.php └── Utils/ └── ProcessedFilesHandler.php ``` ## 🔧 Build & Tests ```bash # PHP-specific quality checks make lint # All linters (syntax + PHPStan + Rector + style) composer ci:test:php:lint # PHP syntax check composer ci:test:php:phpstan # Static analysis composer ci:test:php:rector # Rector modernization check composer ci:test:php:cgl # Code style check # Fixes make format # Auto-fix code style composer ci:cgl # Alternative: fix style composer ci:rector # Apply Rector changes # Full CI make ci # Complete pipeline ``` ## 📝 Code Style ### Required Patterns **1. Strict Types (Always First)** ```php 'value', // Align on => 'longer' => 'another', ]; ``` ## 🔒 Security ### FAL (File Abstraction Layer) - **Always use FAL:** Never direct file system access - **ResourceFactory:** For retrieving files by UID - **File validation:** Check isDeleted(), isMissing() - **ProcessedFile:** Use process() for image manipulation ```php // ✅ Good: FAL usage $file = $this->resourceFactory->getFileObject($id); if ($file->isDeleted() || $file->isMissing()) { throw new \Exception('File not found'); } // ❌ Bad: Direct file access $file = file_get_contents('/var/www/uploads/' . $filename); ``` ### Input Validation - **Type cast superglobals:** `(int)($request->getQueryParams()['id'] ?? 0)` - **Validate before use:** Check ranges, formats, existence - **Exit on error:** Use HTTP status codes with `HttpUtility::HTTP_STATUS_*` ### XSS Prevention - **Fluid templates:** Auto-escaping enabled by default - **JSON responses:** Use `JsonResponse` class - **Localization:** Via `LocalizationUtility::translate()` ## ✅ PR/Commit Checklist ### PHP-Specific Checks 1. ✅ **Strict types:** `declare(strict_types=1);` in all files 2. ✅ **Type hints:** All parameters and return types declared 3. ✅ **PHPStan:** Zero errors (`composer ci:test:php:phpstan`) 4. ✅ **Code style:** PSR-12/PER-CS2.0 compliant (`make format`) 5. ✅ **Rector:** No modernization suggestions (`composer ci:test:php:rector`) 6. ✅ **FAL usage:** No direct file system access 7. ✅ **DI pattern:** Constructor injection, no `new ClassName()` 8. ✅ **PSR-7:** Request/Response for controllers 9. ✅ **Documentation:** PHPDoc for public methods ## 🎓 Good vs Bad Examples ### ✅ Good: Controller Pattern ```php getQueryParams()['fileId'] ?? 0); if ($fileUid <= 0) { return new JsonResponse(['error' => 'Invalid file ID'], 400); } $file = $this->resourceFactory->getFileObject($fileUid); return new JsonResponse([ 'uid' => $file->getUid(), 'width' => $file->getProperty('width'), 'height' => $file->getProperty('height'), ]); } } ``` ### ❌ Bad: Anti-patterns ```php getFileObject($fileUid); // ❌ Manual JSON encoding header('Content-Type: application/json'); echo json_encode(['uid' => $file->getUid()]); exit; } } ``` ### ✅ Good: EventListener Pattern ```php getConfiguration(); $configuration['style']['typo3image'] = [ 'routeUrl' => (string)$this->uriBuilder->buildUriFromRoute('rteckeditorimage_wizard_select_image'), ]; $event->setConfiguration($configuration); } } ``` ### ❌ Bad: EventListener Anti-pattern ```php getConfiguration(); $config['style']['typo3image']['routeUrl'] = $uriBuilder->buildUriFromRoute('rteckeditorimage_wizard_select_image'); $event->setConfiguration($config); } } ``` ### ✅ Good: FAL Usage ```php protected function getImage(int $id): File { try { $file = $this->resourceFactory->getFileObject($id); if ($file->isDeleted() || $file->isMissing()) { throw new FileNotFoundException('File not found or deleted', 1234567890); } } catch (\Exception $e) { throw new FileNotFoundException('Could not load file', 1234567891, $e); } return $file; } ``` ### ❌ Bad: Direct File Access ```php // ❌ Multiple issues protected function getImage($id) // Missing return type, no type hint { // ❌ Direct file system access, bypassing FAL $path = '/var/www/html/fileadmin/' . $id; // ❌ No validation, no error handling if (file_exists($path)) { return file_get_contents($path); } return null; // ❌ Should throw exception or return typed null } ``` ## 🆘 When Stuck ### Documentation - **API Reference:** [docs/API/Controllers.md](../docs/API/Controllers.md) - Controller APIs - **Event Listeners:** [docs/API/EventListeners.md](../docs/API/EventListeners.md) - PSR-14 events - **Data Handling:** [docs/API/DataHandling.md](../docs/API/DataHandling.md) - Database hooks - **Architecture:** [docs/Architecture/Overview.md](../docs/Architecture/Overview.md) - System design ### TYPO3 Resources - **FAL Documentation:** https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Fal/Index.html - **PSR-14 Events:** https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Events/Index.html - **Dependency Injection:** https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/DependencyInjection/Index.html - **Controllers:** https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ApiOverview/Backend/Controllers/Index.html ### Common Issues - **ResourceFactory errors:** Check file exists, not deleted, proper UID - **DI not working:** Verify `Configuration/Services.yaml` registration - **PHPStan errors:** Update baseline: `composer ci:test:php:phpstan:baseline` - **Type errors:** Enable strict_types, add all type hints ## 📐 House Rules ### Controllers - **Extend framework controllers:** ElementBrowserController for browsers - **Final by default:** Use `final class` unless inheritance required - **PSR-7 types:** ServerRequestInterface → ResponseInterface - **JSON responses:** Use `JsonResponse` class - **Validation first:** Validate all input parameters at method start ### EventListeners - **Invokable:** Use `__invoke()` method signature - **Event type hints:** Type-hint specific event classes - **Immutability aware:** Get, modify, set configuration/state - **Final classes:** Event listeners should be final ### DataHandling - **Soft references:** Implement soft reference parsing for data integrity - **Database hooks:** Use for maintaining referential integrity - **Transaction safety:** Consider rollback scenarios ### Dependencies - **Constructor injection:** All dependencies via constructor - **Readonly properties:** Use `readonly` for immutable dependencies - **Interface over implementation:** Depend on interfaces when available - **GeneralUtility::makeInstance:** Only for factories or when DI unavailable ### Error Handling - **Type-specific exceptions:** Use TYPO3 exception hierarchy - **HTTP status codes:** Via HttpUtility constants - **Meaningful messages:** Include context in exception messages - **Log important errors:** Use TYPO3 logging framework ### Testing - **Functional tests:** For controllers, database operations - **Unit tests:** For utilities, isolated logic - **Mock FAL:** Use TYPO3 testing framework FAL mocks - **Test location:** `Tests/Functional/` and `Tests/Unit/` ## 🔗 Related - **[Resources/AGENTS.md](../Resources/AGENTS.md)** - JavaScript/CKEditor integration - **[Tests/AGENTS.md](../Tests/AGENTS.md)** - Testing patterns - **[Configuration/Services.yaml](../Configuration/Services.yaml)** - DI container configuration - **[docs/API/](../docs/API/)** - Complete API documentation