| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- <?php
- if (!class_exists('TemplateFactory')) {
- class TemplateFactory
- {
- private static $cache = null;
- /**
- * Scanne le dossier mapModels pour découvrir les modèles disponibles
- * Retourne un tableau id => ['id'=>..., 'name'=>..., 'description'=>..., 'class'=>...]
- * @return array
- */
- public static function listAvailable(): array
- {
- if (self::$cache !== null) return self::$cache;
- $base = __DIR__ . '/../../mapModels';
- $results = [];
- if (is_dir($base)) {
- $dirs = scandir($base);
- foreach ($dirs as $d) {
- if ($d === '.' || $d === '..') continue;
- $modelJson = $base . '/' . $d . '/model.json';
- if (file_exists($modelJson)) {
- $raw = file_get_contents($modelJson);
- $meta = json_decode($raw, true) ?: [];
- $id = $meta['id'] ?? $d;
- $name = $meta['name'] ?? $id;
- $desc = $meta['description'] ?? '';
- // tenter de charger un fichier PHP depuis le dossier du modèle (sécurisé)
- $modelDir = realpath($base . '/' . $d);
- $entry = $meta['entry'] ?? 'template.php';
- $entryPath = $modelDir ? $modelDir . DIRECTORY_SEPARATOR . $entry : null;
- $loadedClass = null;
- $loadedFromModel = false;
- if ($entryPath && is_file($entryPath) && pathinfo($entryPath, PATHINFO_EXTENSION) === 'php') {
- // protection : s'assurer que le fichier est bien dans le dossier mapModels
- $realEntry = realpath($entryPath);
- if ($realEntry !== false && strpos($realEntry, realpath($base)) === 0) {
- // inclure le fichier. utiliser require_once pour éviter double inclusion
- try {
- require_once $realEntry;
- $loadedFromModel = true;
- // détecter automatiquement une classe qui implémente MapTemplateInterface
- foreach (get_declared_classes() as $decl) {
- if (is_subclass_of($decl, 'MapTemplateInterface')) {
- $loadedClass = $decl;
- break;
- }
- }
- // fallback : nom conventionnel
- if ($loadedClass === null) {
- $canon = ucfirst($id) . 'Template';
- if (class_exists($canon)) $loadedClass = $canon;
- }
- } catch (Throwable $e) {
- // ne pas interrompre la discovery sur erreur de template utilisateur
- $loadedClass = null;
- }
- }
- }
- // s'il n'y a pas de fichier dans mapModels, tenter la classe interne comme avant
- if ($loadedClass === null) {
- $classFile = __DIR__ . '/' . ucfirst($id) . 'Template.php';
- $className = ucfirst($id) . 'Template';
- if (file_exists($classFile)) {
- require_once $classFile;
- if (class_exists($className)) $loadedClass = $className;
- }
- }
- $results[$id] = [
- 'id' => $id,
- 'name' => $name,
- 'description' => $desc,
- 'class' => $loadedClass,
- 'entry' => $entryPath,
- 'loadedFromModel' => $loadedFromModel
- ];
- }
- }
- }
- // Always ensure neutral exists as fallback
- if (!isset($results['neutral'])) {
- // try to include NeutralTemplate
- $neutralFile = __DIR__ . '/NeutralTemplate.php';
- if (file_exists($neutralFile)) require_once $neutralFile;
- $results['neutral'] = [
- 'id' => 'neutral',
- 'name' => 'Neutre',
- 'description' => 'Template neutre',
- 'class' => class_exists('NeutralTemplate') ? 'NeutralTemplate' : null
- ];
- }
- self::$cache = $results;
- return $results;
- }
- /**
- * Retourne la classe du template demandé (ou NeutralTemplate)
- * @param string|null $id
- * @return string|null
- */
- public static function get(string $id = null): ?string
- {
- $list = self::listAvailable();
- if ($id && isset($list[$id]) && !empty($list[$id]['class'])) return $list[$id]['class'];
- return $list['neutral']['class'] ?? null;
- }
- }
- }
|