From 7f0c07b90fd37996aaf811d754bac2b603bb5b15 Mon Sep 17 00:00:00 2001 From: julien Date: Sun, 22 Mar 2026 12:51:14 +0100 Subject: [PATCH] Minor changes --- assets/js/media-admin.js | 14 ++- docker-compose.yml | 12 +-- docker/nginx/default.conf | 2 + docker/php/entrypoint.sh | 18 +--- docker/php/php.ini | 2 +- .../Application/PostApplicationService.php | 2 +- src/Post/Application/PostServiceInterface.php | 97 ------------------- src/Post/Infrastructure/dependencies.php | 4 +- src/Post/UI/Http/PostController.php | 4 +- src/Post/UI/Http/RssController.php | 4 +- tests/Post/PostControllerTest.php | 8 +- tests/Post/RssControllerTest.php | 8 +- 12 files changed, 40 insertions(+), 135 deletions(-) mode change 100644 => 100755 docker/php/entrypoint.sh delete mode 100644 src/Post/Application/PostServiceInterface.php diff --git a/assets/js/media-admin.js b/assets/js/media-admin.js index 36d7798..4232631 100644 --- a/assets/js/media-admin.js +++ b/assets/js/media-admin.js @@ -103,10 +103,20 @@ } }); - var payload = await response.json(); + var contentType = response.headers.get('content-type') || ''; + var raw = await response.text(); + var payload = {}; + + if (contentType.indexOf('application/json') !== -1) { + try { + payload = JSON.parse(raw); + } catch (parseError) { + payload = {}; + } + } if (!response.ok) { - throw new Error(payload.error || 'Le téléversement a échoué.'); + throw new Error(payload.error || ('HTTP ' + response.status + (raw ? ' - ' + raw.slice(0, 180) : ''))); } setFeedback('Image téléversée. Rafraîchissement…', false); diff --git a/docker-compose.yml b/docker-compose.yml index 666569f..37ce64a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,9 +6,9 @@ services: dockerfile: docker/php/Dockerfile restart: unless-stopped volumes: - # Répertoire de travail de l'entrypoint : reçoit public/ compilé, - # puis partagé avec Nginx via le mount ci-dessous. - - ./data:/data + # Répertoire public partagé : reçoit les assets versionnés copiés par + # l'entrypoint, puis sert de racine statique à Nginx. + - ./data/public:/data/public # Base SQLite et migrations : persistés entre redéploiements. - ./data/database:/var/www/app/database @@ -33,8 +33,8 @@ services: TRUSTED_PROXIES: ${TRUSTED_PROXIES:-*} # bash /dev/tcp est disponible sur l'image Debian php:8.4-fpm sans dépendance - # supplémentaire. start_period laisse le temps à entrypoint.sh de terminer - # (sync public/, permissions, caches) avant que les échecs ne comptent. + # supplémentaire. start_period laisse le temps à entrypoint.sh de préparer + # les répertoires runtime et de synchroniser les assets publics. healthcheck: test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/9000'"] interval: 10s @@ -63,7 +63,7 @@ services: # Même environnement/fichiers que le runtime PHP pour provisionner exactement # la même base SQLite persistée. volumes: - - ./data:/data + - ./data/public:/data/public - ./data/database:/var/www/app/database - ./data/var:/var/www/app/var - ./data/public/media:/var/www/app/public/media diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf index dd33aa6..6cc904e 100644 --- a/docker/nginx/default.conf +++ b/docker/nginx/default.conf @@ -2,6 +2,8 @@ server { listen 80; server_name _; + client_max_body_size 8M; + root /var/www/app/public; index index.php; diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh old mode 100644 new mode 100755 index d876d80..7ec77fa --- a/docker/php/entrypoint.sh +++ b/docker/php/entrypoint.sh @@ -2,19 +2,11 @@ set -eu # Prépare les répertoires runtime/persistants. -mkdir -p \ - /data/public \ - /var/www/app/database \ - /var/www/app/public/media \ - /var/www/app/var/cache/twig \ - /var/www/app/var/cache/htmlpurifier \ - /var/www/app/var/cache/di \ - /var/www/app/var/logs +mkdir -p /data/public /data/public/media /var/www/app/database /var/www/app/public/media /var/www/app/var/cache/twig /var/www/app/var/cache/htmlpurifier /var/www/app/var/cache/di /var/www/app/var/logs -# Synchronise les fichiers publics versionnés (index.php, assets compilés, etc.) -# vers le volume partagé. Le répertoire media est exclu car il contient les -# uploads utilisateurs et est géré séparément. -mkdir -p /data/public/media +# Synchronise uniquement les fichiers publics versionnés (index.php, assets +# compilés, favicon, etc.) vers le répertoire partagé avec Nginx. Le dossier +# media est préservé car il contient les uploads persistants. find /data/public -mindepth 1 -maxdepth 1 ! -name media -exec rm -rf {} + for item in /var/www/app/public/*; do @@ -26,7 +18,7 @@ done # Permissions sur les répertoires persistants. Doit s'exécuter en root avant # le démarrage de PHP-FPM. -chown -R www-data:www-data /data /var/www/app/database /var/www/app/var /var/www/app/public/media +chown -R www-data:www-data /data/public /var/www/app/database /var/www/app/var /var/www/app/public/media # Invalide les caches compilés à chaque déploiement. rm -rf /var/www/app/var/cache/twig/* diff --git a/docker/php/php.ini b/docker/php/php.ini index abbe5ac..7267128 100644 --- a/docker/php/php.ini +++ b/docker/php/php.ini @@ -13,5 +13,5 @@ error_log = /dev/stderr ; La valeur doit être synchronisée avec session_name() dans public/index.php si modifiée. session.name = sid -; En production, journaliser les erreurs sans les injecter dans les réponses HTTP +; Ne pas injecter les warnings/notices dans les réponses HTTP de prod display_errors = Off diff --git a/src/Post/Application/PostApplicationService.php b/src/Post/Application/PostApplicationService.php index fbf42f8..116c476 100644 --- a/src/Post/Application/PostApplicationService.php +++ b/src/Post/Application/PostApplicationService.php @@ -14,7 +14,7 @@ use App\Post\Domain\Repository\PostRepositoryInterface; use Netig\Netslim\Kernel\Pagination\Application\PaginatedResult; use Netig\Netslim\Kernel\Support\Exception\NotFoundException; -final class PostApplicationService implements PostServiceInterface +class PostApplicationService { public function __construct( private readonly PostRepositoryInterface $postRepository, diff --git a/src/Post/Application/PostServiceInterface.php b/src/Post/Application/PostServiceInterface.php deleted file mode 100644 index 903c220..0000000 --- a/src/Post/Application/PostServiceInterface.php +++ /dev/null @@ -1,97 +0,0 @@ - - */ - public function findAll(?int $categoryId = null): array; - - /** - * Retourne une page d'articles, éventuellement filtrés par catégorie. - * - * @return PaginatedResult - */ - public function findPaginated(int $page, int $perPage, ?int $categoryId = null): PaginatedResult; - - /** - * Retourne les articles les plus récents. - * - * @return list - */ - public function findRecent(int $limit = 20): array; - - /** - * Retourne les articles d'un auteur, éventuellement filtrés par catégorie. - * - * @return list - */ - public function findByUserId(int $userId, ?int $categoryId = null): array; - - /** - * Retourne une page d'articles pour un auteur, éventuellement filtrés par catégorie. - * - * @return PaginatedResult - */ - public function findByUserIdPaginated(int $userId, int $page, int $perPage, ?int $categoryId = null): PaginatedResult; - - /** - * Retourne un article par slug. - * - * @throws NotFoundException Si aucun article ne correspond au slug fourni. - */ - public function findBySlug(string $slug): Post; - - /** - * Retourne un article par identifiant. - * - * @throws NotFoundException Si aucun article ne correspond à l'identifiant fourni. - */ - public function findById(int $id): Post; - - /** - * Recherche des articles selon une requête textuelle et des filtres optionnels. - * - * @return list - */ - public function search(string $query, ?int $categoryId = null, ?int $authorId = null): array; - - /** - * Retourne une page de résultats de recherche. - * - * @return PaginatedResult - */ - public function searchPaginated(string $query, int $page, int $perPage, ?int $categoryId = null, ?int $authorId = null): PaginatedResult; - - /** - * Crée un article et retourne son identifiant persistant. - */ - public function create(string $title, string $content, int $authorId, ?int $categoryId = null): int; - - /** - * Met à jour un article existant. - * - * @throws NotFoundException Si l'article n'existe pas. - */ - public function update(int $id, string $title, string $content, string $slug = '', ?int $categoryId = null): void; - - /** - * Supprime un article existant. - * - * @throws NotFoundException Si l'article n'existe pas. - */ - public function delete(int $id): void; -} diff --git a/src/Post/Infrastructure/dependencies.php b/src/Post/Infrastructure/dependencies.php index 067058f..61514a5 100644 --- a/src/Post/Infrastructure/dependencies.php +++ b/src/Post/Infrastructure/dependencies.php @@ -3,7 +3,6 @@ declare(strict_types=1); use App\Post\Application\PostApplicationService; -use App\Post\Application\PostServiceInterface; use App\Post\Application\UseCase\CreatePost; use App\Post\Application\UseCase\DeletePost; use App\Post\Application\UseCase\UpdatePost; @@ -25,7 +24,6 @@ use Netig\Netslim\Media\Contracts\MediaUsageReaderInterface; use Netig\Netslim\Taxonomy\Contracts\TaxonUsageCheckerInterface; return [ - PostServiceInterface::class => autowire(PostApplicationService::class), PostRepositoryInterface::class => autowire(PdoPostRepository::class), PostMediaUsageRepositoryInterface::class => autowire(PdoPostMediaUsageRepository::class), PostMediaReferenceExtractorInterface::class => autowire(HtmlPostMediaReferenceExtractor::class), @@ -35,7 +33,7 @@ return [ UpdatePost::class => autowire(), DeletePost::class => autowire(), MediaUsageReaderInterface::class => autowire(PostMediaUsageReader::class), - RssController::class => factory(function (PostServiceInterface $postService): RssController { + RssController::class => factory(function (PostApplicationService $postService): RssController { return new RssController( $postService, rtrim($_ENV['APP_URL'] ?? 'http://localhost', '/'), diff --git a/src/Post/UI/Http/PostController.php b/src/Post/UI/Http/PostController.php index 1f80d39..56d9a6f 100644 --- a/src/Post/UI/Http/PostController.php +++ b/src/Post/UI/Http/PostController.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Post\UI\Http; -use App\Post\Application\PostServiceInterface; +use App\Post\Application\PostApplicationService; use App\Post\Domain\Entity\Post; use App\Post\UI\Http\Request\PostFormRequest; use Netig\Netslim\AuditLog\Contracts\AuditLoggerInterface; @@ -29,7 +29,7 @@ final class PostController { public function __construct( private readonly Twig $view, - private readonly PostServiceInterface $postService, + private readonly PostApplicationService $postService, private readonly TaxonomyReaderInterface $taxonomyReader, private readonly SettingsReaderInterface $settings, private readonly AuthorizationServiceInterface $authorization, diff --git a/src/Post/UI/Http/RssController.php b/src/Post/UI/Http/RssController.php index dd39d58..8d7c001 100644 --- a/src/Post/UI/Http/RssController.php +++ b/src/Post/UI/Http/RssController.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Post\UI\Http; -use App\Post\Application\PostServiceInterface; +use App\Post\Application\PostApplicationService; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -16,7 +16,7 @@ class RssController private const FEED_LIMIT = 20; public function __construct( - private readonly PostServiceInterface $postService, + private readonly PostApplicationService $postService, private readonly string $appUrl, private readonly string $appName, ) {} diff --git a/tests/Post/PostControllerTest.php b/tests/Post/PostControllerTest.php index 201da36..9b98a9f 100644 --- a/tests/Post/PostControllerTest.php +++ b/tests/Post/PostControllerTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace Tests\Post; -use App\Post\Application\PostServiceInterface; +use App\Post\Application\PostApplicationService; use App\Post\Domain\Entity\Post; use App\Post\UI\Http\PostController; use Netig\Netslim\AuditLog\Contracts\AuditLoggerInterface; @@ -39,8 +39,8 @@ final class PostControllerTest extends ControllerTestBase /** @var \Slim\Views\Twig&MockObject */ private \Slim\Views\Twig $view; - /** @var PostServiceInterface&MockObject */ - private PostServiceInterface $postService; + /** @var PostApplicationService&MockObject */ + private PostApplicationService $postService; /** @var TaxonomyReaderInterface&MockObject */ private TaxonomyReaderInterface $taxonomyReader; @@ -65,7 +65,7 @@ final class PostControllerTest extends ControllerTestBase protected function setUp(): void { $this->view = $this->makeTwigMock(); - $this->postService = $this->createMock(PostServiceInterface::class); + $this->postService = $this->createMock(PostApplicationService::class); $this->taxonomyReader = $this->createMock(TaxonomyReaderInterface::class); $this->settings = $this->createMock(SettingsReaderInterface::class); $this->authorization = $this->createMock(AuthorizationServiceInterface::class); diff --git a/tests/Post/RssControllerTest.php b/tests/Post/RssControllerTest.php index 911b7f2..85441a9 100644 --- a/tests/Post/RssControllerTest.php +++ b/tests/Post/RssControllerTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace Tests\Post; -use App\Post\Application\PostServiceInterface; +use App\Post\Application\PostApplicationService; use App\Post\Domain\Entity\Post; use App\Post\UI\Http\RssController; use PHPUnit\Framework\MockObject\MockObject; @@ -23,8 +23,8 @@ use Tests\ControllerTestBase; #[\PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations] final class RssControllerTest extends ControllerTestBase { - /** @var PostServiceInterface&MockObject */ - private PostServiceInterface $postService; + /** @var PostApplicationService&MockObject */ + private PostApplicationService $postService; private RssController $controller; @@ -33,7 +33,7 @@ final class RssControllerTest extends ControllerTestBase protected function setUp(): void { - $this->postService = $this->createMock(PostServiceInterface::class); + $this->postService = $this->createMock(PostApplicationService::class); $this->controller = new RssController( $this->postService,