Refatoring : Working state

This commit is contained in:
julien
2026-03-16 15:08:48 +01:00
parent 664d74cd69
commit 3ad3c3d0b7
50 changed files with 69 additions and 331 deletions

View File

@@ -22,26 +22,26 @@ use App\Auth\PasswordResetRepositoryInterface;
use App\Auth\Application\PasswordResetApplicationService;
use App\Auth\PasswordResetServiceInterface;
use App\Category\Application\CategoryApplicationService;
use App\Category\CategoryRepository;
use App\Category\CategoryRepositoryInterface;
use App\Category\CategoryService;
use App\Category\CategoryServiceInterface;
use App\Category\Infrastructure\PdoCategoryRepository;
use App\Media\Domain\MediaStorageInterface;
use App\Media\Infrastructure\LocalMediaStorage;
use App\Media\Infrastructure\PdoMediaRepository;
use App\Media\MediaRepository;
use App\Media\MediaRepositoryInterface;
use App\Media\Application\MediaApplicationService;
use App\Media\MediaService;
use App\Media\MediaServiceInterface;
use App\Post\Application\PostApplicationService;
use App\Post\PostRepository;
use App\Post\PostRepositoryInterface;
use App\Post\PostService;
use App\Post\PostServiceInterface;
use App\Post\Infrastructure\PdoPostRepository;
use App\Post\RssController;
use App\Post\Http\RssController;
use App\Shared\Config;
use App\Shared\Extension\AppExtension;
use App\Shared\Html\HtmlPurifierFactory;

View File

@@ -1,12 +1,12 @@
# Architecture
> **Refactor DDD légère — lots 1 à 4**
> **Architecture cible après cleanup final**
>
> `Post/`, `Category/`, `User/`, `Media/` et `Auth/` introduisent maintenant une organisation verticale
> `Application / Infrastructure / Http / Domain` pour alléger la lecture et préparer
> un découpage plus fin par cas d'usage. Les classes historiques à la racine du domaine
> sont conservées comme **ponts de compatibilité** afin de préserver les routes, le conteneur
> DI et la suite de tests pendant la transition.
> `Post/`, `Category/`, `User/`, `Media/` et `Auth/` suivent maintenant une organisation verticale
> `Application / Infrastructure / Http / Domain`. Les anciennes classes de transition
> ont été retirées : routes, conteneur DI et tests pointent directement vers les
> implémentations finales, ce qui réduit la dette de compatibilité tout en conservant
> les mêmes fonctionnalités.
## Domaines PHP
@@ -27,13 +27,13 @@ contrôleur. Les dépendances inter-domaines sont explicites, minimales et toujo
Le projet compte deux dépendances explicites entre domaines métier :
**`Auth/ → User/`** — `AuthService` et `PasswordResetService` consomment `UserRepositoryInterface`
**`Auth/ → User/`** — `AuthApplicationService` et `PasswordResetApplicationService` consomment `UserRepositoryInterface`
pour lire les comptes lors de l'authentification et de la réinitialisation de mot de passe.
Unidirectionnelle : `User/` n'importe rien de `Auth/`.
**`Post/ → Category/`** — `PostController` injecte `CategoryServiceInterface` pour alimenter
la liste des catégories dans le formulaire de création/édition d'article. Dépendance de
présentation uniquement : `PostService` et `PostRepository` ne connaissent pas `Category/`.
présentation uniquement : `PostApplicationService` et `PdoPostRepository` ne connaissent pas `Category/`.
Unidirectionnelle : `Category/` n'importe rien de `Post/`.
### Structure d'un domaine
@@ -89,10 +89,10 @@ final class PostService
| `PasswordResetRepositoryInterface` | `PdoPasswordResetRepository` | `Auth/` |
| `PasswordResetServiceInterface` | `PasswordResetApplicationService` | `Auth/` |
| `AuthServiceInterface` | `AuthApplicationService` | `Auth/` |
| `PostRepositoryInterface` | `PostRepository` | `Post/` |
| `PostServiceInterface` | `PostService` | `Post/` |
| `CategoryRepositoryInterface` | `CategoryRepository` | `Category/`|
| `CategoryServiceInterface` | `CategoryService` | `Category/`|
| `PostRepositoryInterface` | `PdoPostRepository` | `Post/` |
| `PostServiceInterface` | `PostApplicationService` | `Post/` |
| `CategoryRepositoryInterface` | `PdoCategoryRepository` | `Category/`|
| `CategoryServiceInterface` | `CategoryApplicationService` | `Category/`|
| `MediaRepositoryInterface` | `PdoMediaRepository` | `Media/` |
| `MediaServiceInterface` | `MediaApplicationService` | `Media/` |
| `MediaStorageInterface` | `LocalMediaStorage` | `Media/` |
@@ -106,13 +106,13 @@ Les erreurs métier levées intentionnellement utilisent des exceptions dédiée
| Exception | Namespace | Levée par |
|------------------------------|------------------------|--------------------------------------------------------|
| `DuplicateUsernameException` | `App\User\Exception` | `UserService::createUser()` |
| `DuplicateEmailException` | `App\User\Exception` | `UserService::createUser()` |
| `WeakPasswordException` | `App\User\Exception` | `UserService`, `AuthService`, `PasswordResetService` |
| `NotFoundException` | `App\Shared\Exception` | `PostService`, `AuthService` |
| `FileTooLargeException` | `App\Media\Exception` | `MediaService::store()` |
| `InvalidMimeTypeException` | `App\Media\Exception` | `MediaService::store()` |
| `StorageException` | `App\Media\Exception` | `MediaService::store()` |
| `DuplicateUsernameException` | `App\User\Exception` | `UserApplicationService::createUser()` |
| `DuplicateEmailException` | `App\User\Exception` | `UserApplicationService::createUser()` |
| `WeakPasswordException` | `App\User\Exception` | `UserApplicationService`, `AuthApplicationService`, `PasswordResetApplicationService` |
| `NotFoundException` | `App\Shared\Exception` | `PostApplicationService`, `AuthApplicationService` |
| `FileTooLargeException` | `App\Media\Exception` | `MediaApplicationService::store()` |
| `InvalidMimeTypeException` | `App\Media\Exception` | `MediaApplicationService::store()` |
| `StorageException` | `App\Media\Exception` | `MediaApplicationService::store()` |
## Base de données

View File

@@ -429,8 +429,8 @@ Qui assemble les dépendances ? PHP-DI dans `config/container.php`. Il résout a
// Extrait de config/container.php
// Binding interface → implémentation : PHP-DI injecte PostRepository partout où
// PostRepositoryInterface est demandé. PostService lui-même est résolu par autowiring.
PostRepositoryInterface::class => autowire(PostRepository::class),
PostServiceInterface::class => autowire(PostService::class),
PostRepositoryInterface::class => autowire(PdoPostRepository::class),
PostServiceInterface::class => autowire(PostApplicationService::class),
```
> 💡 Pour ajouter un nouveau service : créer la classe avec ses dépendances typées en constructeur, puis déclarer le binding interface → classe dans `config/container.php`. Si toutes les dépendances sont elles-mêmes typées sur des interfaces déjà liées, PHP-DI résout tout automatiquement — aucune factory à écrire.
@@ -873,8 +873,8 @@ Les services dépendent des interfaces, jamais des classes concrètes. Cela appo
```php
// config/container.php
PostRepositoryInterface::class => autowire(PostRepository::class),
PostServiceInterface::class => autowire(PostService::class),
PostRepositoryInterface::class => autowire(PdoPostRepository::class),
PostServiceInterface::class => autowire(PostApplicationService::class),
```
**Factories scalaires** — pour les dépendances qui ont besoin de paramètres issus de `.env` ou du système de fichiers (PDO, Twig, Monolog) :
@@ -979,7 +979,7 @@ DuplicateEmailException — adresse e-mail déjà utilisée
WeakPasswordException — mot de passe inférieur à 8 caractères
```
Elles sont levées par `UserService` (`DuplicateUsernameException`, `DuplicateEmailException`, `WeakPasswordException`) et par `AuthService` et `PasswordResetService` (`WeakPasswordException`), puis attrapées dans les contrôleurs via un seul bloc `catch(\InvalidArgumentException)` : le message de l'exception est transmis directement au flash et affiché dans le formulaire.
Elles sont levées par `UserService` (`DuplicateUsernameException`, `DuplicateEmailException`, `WeakPasswordException`) et par `AuthApplicationService` et `PasswordResetApplicationService` (`WeakPasswordException`), puis attrapées dans les contrôleurs via un seul bloc `catch(\InvalidArgumentException)` : le message de l'exception est transmis directement au flash et affiché dans le formulaire.
### 5.9 Gestion des erreurs et messages flash

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\Auth\Http\AccountController.
*/
final class AccountController extends Http\AccountController
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\Auth\Http\AuthController.
*/
final class AuthController extends Http\AuthController
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
use App\Auth\Application\AuthApplicationService;
/**
* Pont de compatibilité : l'implémentation principale vit désormais dans
* App\Auth\Application\AuthApplicationService.
*/
final class AuthService extends AuthApplicationService implements AuthServiceInterface
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
use App\Auth\Infrastructure\PdoLoginAttemptRepository;
/**
* Pont de compatibilité : l'implémentation PDO principale vit désormais dans
* App\Auth\Infrastructure\PdoLoginAttemptRepository.
*/
final class LoginAttemptRepository extends PdoLoginAttemptRepository implements LoginAttemptRepositoryInterface
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\Auth\Http\PasswordResetController.
*/
final class PasswordResetController extends Http\PasswordResetController
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
use App\Auth\Infrastructure\PdoPasswordResetRepository;
/**
* Pont de compatibilité : l'implémentation PDO principale vit désormais dans
* App\Auth\Infrastructure\PdoPasswordResetRepository.
*/
final class PasswordResetRepository extends PdoPasswordResetRepository implements PasswordResetRepositoryInterface
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Auth;
use App\Auth\Application\PasswordResetApplicationService;
/**
* Pont de compatibilité : l'implémentation principale vit désormais dans
* App\Auth\Application\PasswordResetApplicationService.
*/
final class PasswordResetService extends PasswordResetApplicationService implements PasswordResetServiceInterface
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Category;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\Category\Http\CategoryController.
*/
final class CategoryController extends Http\CategoryController
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Category;
use App\Category\Infrastructure\PdoCategoryRepository;
/**
* Pont de compatibilité : l'implémentation PDO principale vit désormais dans
* App\Category\Infrastructure\PdoCategoryRepository.
*/
final class CategoryRepository extends PdoCategoryRepository implements CategoryRepositoryInterface
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Category;
use App\Category\Application\CategoryApplicationService;
/**
* Pont de compatibilité : l'implémentation métier principale vit désormais dans
* App\Category\Application\CategoryApplicationService.
*/
final class CategoryService extends CategoryApplicationService implements CategoryServiceInterface
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Media;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\Media\Http\MediaController.
*/
final class MediaController extends Http\MediaController
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Media;
use App\Media\Infrastructure\PdoMediaRepository;
/**
* Pont de compatibilité : l'implémentation PDO principale vit désormais dans
* App\Media\Infrastructure\PdoMediaRepository.
*/
final class MediaRepository extends PdoMediaRepository implements MediaRepositoryInterface
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Post;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\Post\Http\PostController.
*/
final class PostController extends Http\PostController
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Post;
/**
* Pont de compatibilité : l'extension Twig principale vit désormais dans
* App\Post\Infrastructure\TwigPostExtension.
*/
final class PostExtension extends Infrastructure\TwigPostExtension
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Post;
use App\Post\Infrastructure\PdoPostRepository;
/**
* Pont de compatibilité : l'implémentation PDO principale vit désormais dans
* App\Post\Infrastructure\PdoPostRepository.
*/
final class PostRepository extends PdoPostRepository implements PostRepositoryInterface
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Post;
use App\Post\Application\PostApplicationService;
/**
* Pont de compatibilité : l'implémentation métier principale vit désormais dans
* App\Post\Application\PostApplicationService.
*/
final class PostService extends PostApplicationService implements PostServiceInterface
{
}

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Post;
/**
* Pont de compatibilité : le contrôleur RSS principal vit désormais dans
* App\Post\Http\RssController.
*/
final class RssController extends Http\RssController
{
}

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace App\Shared;
use App\Post\PostExtension;
use App\Post\Infrastructure\TwigPostExtension;
use App\Shared\Database\DatabaseNotProvisionedException;
use App\Shared\Database\DatabaseReadiness;
use App\Shared\Extension\AppExtension;
@@ -161,7 +161,7 @@ final class Bootstrap
$twig = $this->container->get(Twig::class);
$twig->addExtension($this->container->get(AppExtension::class));
$twig->addExtension($this->container->get(SessionExtension::class));
$twig->addExtension($this->container->get(PostExtension::class));
$twig->addExtension($this->container->get(TwigPostExtension::class));
$this->app->add(TwigMiddleware::create($this->app, $twig));

View File

@@ -3,17 +3,17 @@ declare(strict_types=1);
namespace App\Shared;
use App\Auth\AccountController;
use App\Auth\Http\AccountController;
use App\Auth\Middleware\AdminMiddleware;
use App\Auth\AuthController;
use App\Auth\Http\AuthController;
use App\Auth\Middleware\AuthMiddleware;
use App\Auth\Middleware\EditorMiddleware;
use App\Auth\PasswordResetController;
use App\Category\CategoryController;
use App\Media\MediaController;
use App\Post\PostController;
use App\Post\RssController;
use App\User\UserController;
use App\Auth\Http\PasswordResetController;
use App\Category\Http\CategoryController;
use App\Media\Http\MediaController;
use App\Post\Http\PostController;
use App\Post\Http\RssController;
use App\User\Http\UserController;
use Slim\App;
/**

View File

@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace App\User;
/**
* Pont de compatibilité : le contrôleur HTTP principal vit désormais dans
* App\User\Http\UserController.
*/
final class UserController extends Http\UserController
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\User;
use App\User\Infrastructure\PdoUserRepository;
/**
* Pont de compatibilité : l'implémentation PDO principale vit désormais dans
* App\User\Infrastructure\PdoUserRepository.
*/
final class UserRepository extends PdoUserRepository implements UserRepositoryInterface
{
}

View File

@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace App\User;
use App\User\Application\UserApplicationService;
/**
* Pont de compatibilité : l'implémentation métier principale vit désormais dans
* App\User\Application\UserApplicationService.
*/
final class UserService extends UserApplicationService implements UserServiceInterface
{
}

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\AccountController;
use App\Auth\Http\AccountController as AccountController;
use App\Auth\AuthServiceInterface;
use App\Shared\Http\FlashServiceInterface;
use App\Shared\Http\SessionManagerInterface;

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\AuthController;
use App\Auth\Http\AuthController as AuthController;
use App\Auth\AuthServiceInterface;
use App\Shared\Http\ClientIpResolver;
use App\Shared\Http\FlashServiceInterface;

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\AuthService;
use App\Auth\Application\AuthApplicationService as AuthService;
use App\Auth\LoginAttemptRepositoryInterface;
use App\Shared\Http\SessionManagerInterface;
use App\User\UserRepositoryInterface;

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\AuthService;
use App\Auth\Application\AuthApplicationService as AuthService;
use App\Auth\LoginAttemptRepositoryInterface;
use App\Shared\Exception\NotFoundException;
use App\Shared\Http\SessionManagerInterface;

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\LoginAttemptRepository;
use App\Auth\Infrastructure\PdoLoginAttemptRepository as LoginAttemptRepository;
use PDO;
use PDOStatement;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\AuthServiceInterface;
use App\Auth\PasswordResetController;
use App\Auth\Http\PasswordResetController as PasswordResetController;
use App\Auth\Exception\InvalidResetTokenException;
use App\Auth\PasswordResetServiceInterface;
use App\Shared\Http\ClientIpResolver;

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\PasswordResetRepository;
use App\Auth\Infrastructure\PdoPasswordResetRepository as PasswordResetRepository;
use PDO;
use PDOStatement;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -4,12 +4,12 @@ declare(strict_types=1);
namespace Tests\Auth;
use App\Auth\Exception\InvalidResetTokenException;
use App\Auth\PasswordResetRepository;
use App\Auth\PasswordResetService;
use App\Auth\Infrastructure\PdoPasswordResetRepository as PasswordResetRepository;
use App\Auth\Application\PasswordResetApplicationService as PasswordResetService;
use App\Shared\Database\Migrator;
use App\Shared\Mail\MailServiceInterface;
use App\User\User;
use App\User\UserRepository;
use App\User\Infrastructure\PdoUserRepository as UserRepository;
use PDO;
use PHPUnit\Framework\TestCase;

View File

@@ -5,7 +5,7 @@ namespace Tests\Auth;
use App\Auth\Exception\InvalidResetTokenException;
use App\Auth\PasswordResetRepositoryInterface;
use App\Auth\PasswordResetService;
use App\Auth\Application\PasswordResetApplicationService as PasswordResetService;
use App\Shared\Mail\MailServiceInterface;
use App\User\Exception\WeakPasswordException;
use App\User\User;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\Category;
use App\Category\Category;
use App\Category\CategoryController;
use App\Category\Http\CategoryController as CategoryController;
use App\Category\CategoryServiceInterface;
use App\Shared\Http\FlashServiceInterface;
use App\Shared\Pagination\PaginatedResult;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\Category;
use App\Category\Category;
use App\Category\CategoryRepository;
use App\Category\Infrastructure\PdoCategoryRepository as CategoryRepository;
use PDO;
use PDOStatement;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -5,7 +5,7 @@ namespace Tests\Category;
use App\Category\Category;
use App\Category\CategoryRepositoryInterface;
use App\Category\CategoryService;
use App\Category\Application\CategoryApplicationService as CategoryService;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

View File

@@ -7,7 +7,7 @@ use App\Media\Exception\FileTooLargeException;
use App\Media\Exception\InvalidMimeTypeException;
use App\Media\Exception\StorageException;
use App\Media\Media;
use App\Media\MediaController;
use App\Media\Http\MediaController as MediaController;
use App\Media\MediaServiceInterface;
use App\Shared\Http\FlashServiceInterface;
use App\Shared\Http\SessionManagerInterface;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\Media;
use App\Media\Media;
use App\Media\MediaRepository;
use App\Media\Infrastructure\PdoMediaRepository as MediaRepository;
use PDO;
use PDOStatement;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace Tests\Post;
use App\Post\Post;
use App\Post\PostRepository;
use App\Post\Infrastructure\PdoPostRepository as PostRepository;
use App\Post\PostRepositoryInterface;
use App\Post\PostService;
use App\Post\Application\PostApplicationService as PostService;
use App\Shared\Database\Migrator;
use App\Shared\Exception\NotFoundException;
use App\Shared\Html\HtmlSanitizerInterface;

View File

@@ -6,7 +6,7 @@ namespace Tests\Post;
use App\Category\Category;
use App\Category\CategoryServiceInterface;
use App\Post\Post;
use App\Post\PostController;
use App\Post\Http\PostController as PostController;
use App\Post\PostServiceInterface;
use App\Shared\Exception\NotFoundException;
use App\Shared\Http\FlashServiceInterface;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\Post;
use App\Post\Post;
use App\Post\PostExtension;
use App\Post\Infrastructure\TwigPostExtension as PostExtension;
use PHPUnit\Framework\TestCase;
use Twig\TwigFunction;

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace Tests\Post;
use App\Post\PostRepository;
use App\Post\Infrastructure\PdoPostRepository as PostRepository;
use App\Shared\Database\Migrator;
use PDO;
use PHPUnit\Framework\TestCase;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\Post;
use App\Post\Post;
use App\Post\PostRepository;
use App\Post\Infrastructure\PdoPostRepository as PostRepository;
use PDO;
use PDOStatement;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -5,7 +5,7 @@ namespace Tests\Post;
use App\Post\Post;
use App\Post\PostRepositoryInterface;
use App\Post\PostService;
use App\Post\Application\PostApplicationService as PostService;
use App\Shared\Html\HtmlSanitizerInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

View File

@@ -5,7 +5,7 @@ namespace Tests\Post;
use App\Post\Post;
use App\Post\PostRepositoryInterface;
use App\Post\PostService;
use App\Post\Application\PostApplicationService as PostService;
use App\Shared\Exception\NotFoundException;
use App\Shared\Html\HtmlSanitizerInterface;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -5,7 +5,7 @@ namespace Tests\Post;
use App\Post\Post;
use App\Post\PostServiceInterface;
use App\Post\RssController;
use App\Post\Http\RssController as RssController;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\ControllerTestBase;

View File

@@ -10,7 +10,7 @@ use App\User\Exception\DuplicateEmailException;
use App\User\Exception\DuplicateUsernameException;
use App\User\Exception\WeakPasswordException;
use App\User\User;
use App\User\UserController;
use App\User\Http\UserController as UserController;
use App\User\UserServiceInterface;
use PHPUnit\Framework\MockObject\MockObject;
use Tests\ControllerTestBase;

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Tests\User;
use App\User\User;
use App\User\UserRepository;
use App\User\Infrastructure\PdoUserRepository as UserRepository;
use PDO;
use PDOStatement;
use PHPUnit\Framework\MockObject\MockObject;

View File

@@ -9,7 +9,7 @@ use App\User\Exception\InvalidRoleException;
use App\User\Exception\WeakPasswordException;
use App\User\User;
use App\User\UserRepositoryInterface;
use App\User\UserService;
use App\User\Application\UserApplicationService as UserService;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;