diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 713b4d3..04b76c2 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -8,7 +8,6 @@ use PhpCsFixer\Finder; $finder = Finder::create() ->in('src') ->notName('Kernel.php') - ->notPath('Module/Core/_compat_user_alias.php') ; $rules = [ diff --git a/composer.json b/composer.json index 533bddc..7b9c607 100644 --- a/composer.json +++ b/composer.json @@ -55,10 +55,7 @@ "autoload": { "psr-4": { "App\\": "src/" - }, - "files": [ - "src/Module/Core/_compat_user_alias.php" - ] + } }, "autoload-dev": { "psr-4": { diff --git a/config/services.yaml b/config/services.yaml index 1b039ef..97ad4a6 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -27,9 +27,6 @@ services: # this creates a service per class whose id is the fully-qualified class name App\: resource: '../src/' - # Temporary legacy class_alias bootstrap file (no service): excluded from autowiring scan. - exclude: - - '../src/Module/Core/_compat_user_alias.php' # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones @@ -69,3 +66,5 @@ services: $uploadDir: '%absence_justification_upload_dir%' App\Service\Share\FileSource: '@App\Service\Share\SmbFileSource' + + App\Module\Core\Domain\Repository\UserRepositoryInterface: '@App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository' diff --git a/src/Command/AccrueLeaveCommand.php b/src/Command/AccrueLeaveCommand.php index e241e64..8fe502f 100644 --- a/src/Command/AccrueLeaveCommand.php +++ b/src/Command/AccrueLeaveCommand.php @@ -5,8 +5,8 @@ declare(strict_types=1); namespace App\Command; use App\Enum\AbsenceType; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\AbsenceBalanceRepository; -use App\Repository\UserRepository; use App\Service\AbsenceBalanceService; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; @@ -37,7 +37,7 @@ use function sprintf; class AccrueLeaveCommand extends Command { public function __construct( - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly AbsenceBalanceRepository $balanceRepository, private readonly AbsenceBalanceService $balanceService, private readonly EntityManagerInterface $entityManager, diff --git a/src/Command/GenerateApiTokenCommand.php b/src/Command/GenerateApiTokenCommand.php index a23adce..e6687a0 100644 --- a/src/Command/GenerateApiTokenCommand.php +++ b/src/Command/GenerateApiTokenCommand.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Command; -use App\Repository\UserRepository; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; @@ -22,7 +22,7 @@ use function sprintf; class GenerateApiTokenCommand extends Command { public function __construct( - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly EntityManagerInterface $entityManager, ) { parent::__construct(); diff --git a/src/Controller/Absence/AbsencePreviewController.php b/src/Controller/Absence/AbsencePreviewController.php index c313cc2..32ec5a8 100644 --- a/src/Controller/Absence/AbsencePreviewController.php +++ b/src/Controller/Absence/AbsencePreviewController.php @@ -4,13 +4,13 @@ declare(strict_types=1); namespace App\Controller\Absence; -use App\Entity\User; use App\Enum\AbsenceType; use App\Enum\HalfDay; use App\Repository\AbsenceBalanceRepository; use App\Repository\AbsencePolicyRepository; use App\Service\AbsenceBalanceService; use App\Service\AbsenceDayCalculator; +use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\SecurityBundle\Security; @@ -71,7 +71,7 @@ class AbsencePreviewController extends AbstractController ); $user = $this->security->getUser(); - assert($user instanceof User); + assert($user instanceof UserInterface); $available = null; $projectedAvailable = null; diff --git a/src/Controller/Mail/MailCreateTaskController.php b/src/Controller/Mail/MailCreateTaskController.php index 436b8f7..2231d0e 100644 --- a/src/Controller/Mail/MailCreateTaskController.php +++ b/src/Controller/Mail/MailCreateTaskController.php @@ -9,7 +9,7 @@ use App\Entity\Task; use App\Entity\TaskGroup; use App\Entity\TaskMailLink; use App\Entity\TaskStatus; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use App\Repository\MailMessageRepository; use App\Repository\TaskRepository; use App\Security\MailAccessChecker; diff --git a/src/Controller/MarkAllReadController.php b/src/Controller/MarkAllReadController.php index a745051..453cbbb 100644 --- a/src/Controller/MarkAllReadController.php +++ b/src/Controller/MarkAllReadController.php @@ -4,8 +4,8 @@ declare(strict_types=1); namespace App\Controller; -use App\Entity\User; use App\Repository\NotificationRepository; +use App\Shared\Domain\Contract\UserInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; @@ -21,7 +21,7 @@ class MarkAllReadController extends AbstractController #[IsGranted('IS_AUTHENTICATED_FULLY')] public function __invoke(): Response { - /** @var User $user */ + /** @var UserInterface $user */ $user = $this->getUser(); $this->notificationRepository->markAllReadByUser($user); diff --git a/src/Controller/NotificationUnreadCountController.php b/src/Controller/NotificationUnreadCountController.php index f4c6d82..746299a 100644 --- a/src/Controller/NotificationUnreadCountController.php +++ b/src/Controller/NotificationUnreadCountController.php @@ -4,8 +4,8 @@ declare(strict_types=1); namespace App\Controller; -use App\Entity\User; use App\Repository\NotificationRepository; +use App\Shared\Domain\Contract\UserInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; @@ -21,7 +21,7 @@ class NotificationUnreadCountController extends AbstractController #[IsGranted('IS_AUTHENTICATED_FULLY')] public function __invoke(): JsonResponse { - /** @var User $user */ + /** @var UserInterface $user */ $user = $this->getUser(); $count = $this->notificationRepository->countUnreadByUser($user); diff --git a/src/Controller/RegenerateApiTokenController.php b/src/Controller/RegenerateApiTokenController.php index ca209de..2593811 100644 --- a/src/Controller/RegenerateApiTokenController.php +++ b/src/Controller/RegenerateApiTokenController.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Controller; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; diff --git a/src/Controller/TimeEntryExportController.php b/src/Controller/TimeEntryExportController.php index 0ae7ba5..aa5ba15 100644 --- a/src/Controller/TimeEntryExportController.php +++ b/src/Controller/TimeEntryExportController.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Controller; use App\Entity\Project; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use App\Repository\TimeEntryRepository; use App\Service\TimeEntryExportService; use DateTimeImmutable; diff --git a/src/Controller/UserAvatarController.php b/src/Controller/UserAvatarController.php index 450d2cb..2c586fa 100644 --- a/src/Controller/UserAvatarController.php +++ b/src/Controller/UserAvatarController.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Controller; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\BinaryFileResponse; diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index 0b5de94..b0f3734 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -18,7 +18,6 @@ use App\Entity\TaskRecurrence; use App\Entity\TaskStatus; use App\Entity\TaskTag; use App\Entity\TimeEntry; -use App\Entity\User; use App\Entity\Workflow; use App\Entity\ZimbraConfiguration; use App\Enum\AbsenceStatus; @@ -26,6 +25,7 @@ use App\Enum\AbsenceType; use App\Enum\ContractType; use App\Enum\RecurrenceType; use App\Enum\StatusCategory; +use App\Module\Core\Domain\Entity\User; use DateTimeImmutable; use DateTimeZone; use Doctrine\Bundle\FixturesBundle\Fixture; diff --git a/src/EventListener/TaskNotificationListener.php b/src/EventListener/TaskNotificationListener.php index 1795184..9e32ac8 100644 --- a/src/EventListener/TaskNotificationListener.php +++ b/src/EventListener/TaskNotificationListener.php @@ -6,7 +6,7 @@ namespace App\EventListener; use App\Entity\Notification; use App\Entity\Task; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener; use Doctrine\ORM\Event\OnFlushEventArgs; @@ -18,7 +18,7 @@ use Symfony\Bundle\SecurityBundle\Security; #[AsDoctrineListener(event: Events::postFlush)] final class TaskNotificationListener { - /** @var list */ + /** @var list */ private array $pending = []; public function __construct(private readonly Security $security) {} @@ -26,7 +26,7 @@ final class TaskNotificationListener public function onFlush(OnFlushEventArgs $args): void { $actor = $this->security->getUser(); - if (!$actor instanceof User) { + if (!$actor instanceof UserInterface) { return; } @@ -38,7 +38,7 @@ final class TaskNotificationListener continue; } $assignee = $entity->getAssignee(); - if ($assignee instanceof User && $assignee !== $actor) { + if ($assignee instanceof UserInterface && $assignee !== $actor) { $this->pending[] = ['user' => $assignee, 'type' => 'task_assigned', 'task' => $entity]; } } @@ -53,7 +53,7 @@ final class TaskNotificationListener continue; } $new = $changeSet['assignee'][1]; - if ($new instanceof User && $new !== $actor) { + if ($new instanceof UserInterface && $new !== $actor) { $this->pending[] = ['user' => $new, 'type' => 'task_assigned', 'task' => $entity]; } } @@ -68,7 +68,7 @@ final class TaskNotificationListener continue; } foreach ($collection->getInsertDiff() as $user) { - if ($user instanceof User && $user !== $actor) { + if ($user instanceof UserInterface && $user !== $actor) { $this->pending[] = ['user' => $user, 'type' => 'task_collaborator_added', 'task' => $owner]; } } @@ -91,7 +91,7 @@ final class TaskNotificationListener $em->flush(); } - private function buildNotification(User $user, string $type, Task $task): Notification + private function buildNotification(UserInterface $user, string $type, Task $task): Notification { [$title, $message] = $this->render($type, $task); diff --git a/src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php b/src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php index 8a7af97..5d58d30 100644 --- a/src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php +++ b/src/Mcp/Tool/Absence/CreateAbsenceRequestTool.php @@ -9,9 +9,9 @@ use App\Enum\AbsenceStatus; use App\Enum\AbsenceType; use App\Enum\HalfDay; use App\Mcp\Tool\Serializer; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\AbsencePolicyRepository; use App\Repository\AbsenceRequestRepository; -use App\Repository\UserRepository; use App\Service\AbsenceBalanceService; use App\Service\AbsenceDayCalculator; use DateTimeImmutable; @@ -28,7 +28,7 @@ class CreateAbsenceRequestTool { public function __construct( private readonly EntityManagerInterface $entityManager, - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly AbsencePolicyRepository $policyRepository, private readonly AbsenceRequestRepository $requestRepository, private readonly AbsenceDayCalculator $calculator, diff --git a/src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php b/src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php index f0baf6a..253e0fb 100644 --- a/src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php +++ b/src/Mcp/Tool/Absence/ListAbsenceBalancesTool.php @@ -6,8 +6,8 @@ namespace App\Mcp\Tool\Absence; use App\Enum\AbsenceType; use App\Mcp\Tool\Serializer; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\AbsenceBalanceRepository; -use App\Repository\UserRepository; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; use Symfony\Bundle\SecurityBundle\Security; @@ -20,7 +20,7 @@ class ListAbsenceBalancesTool { public function __construct( private readonly AbsenceBalanceRepository $balanceRepository, - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly Security $security, ) {} diff --git a/src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php b/src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php index 485f730..1f09368 100644 --- a/src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php +++ b/src/Mcp/Tool/Absence/ListAbsenceRequestsTool.php @@ -7,8 +7,8 @@ namespace App\Mcp\Tool\Absence; use App\Enum\AbsenceStatus; use App\Enum\AbsenceType; use App\Mcp\Tool\Serializer; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\AbsenceRequestRepository; -use App\Repository\UserRepository; use DateTimeImmutable; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; @@ -22,7 +22,7 @@ class ListAbsenceRequestsTool { public function __construct( private readonly AbsenceRequestRepository $requestRepository, - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly Security $security, ) {} diff --git a/src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php b/src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php index 1556d8a..d81fb0f 100644 --- a/src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php +++ b/src/Mcp/Tool/Absence/ReviewAbsenceRequestTool.php @@ -4,11 +4,11 @@ declare(strict_types=1); namespace App\Mcp\Tool\Absence; -use App\Entity\User; use App\Enum\AbsenceStatus; use App\Mcp\Tool\Serializer; use App\Repository\AbsenceRequestRepository; use App\Service\AbsenceBalanceService; +use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; @@ -49,7 +49,7 @@ class ReviewAbsenceRequestTool } $admin = $this->security->getUser(); - assert($admin instanceof User); + assert($admin instanceof UserInterface); if ('approve' === $decision) { // Never let an approval push the balance below zero (CP only). diff --git a/src/Mcp/Tool/Reference/GetUserTool.php b/src/Mcp/Tool/Reference/GetUserTool.php index 4ef1791..74d0e55 100644 --- a/src/Mcp/Tool/Reference/GetUserTool.php +++ b/src/Mcp/Tool/Reference/GetUserTool.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Mcp\Tool\Reference; use App\Mcp\Tool\Serializer; -use App\Repository\UserRepository; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use InvalidArgumentException; use Mcp\Capability\Attribute\McpTool; use Symfony\Bundle\SecurityBundle\Security; @@ -17,7 +17,7 @@ use function sprintf; class GetUserTool { public function __construct( - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly Security $security, ) {} diff --git a/src/Mcp/Tool/Reference/ListUsersTool.php b/src/Mcp/Tool/Reference/ListUsersTool.php index e602047..c2badca 100644 --- a/src/Mcp/Tool/Reference/ListUsersTool.php +++ b/src/Mcp/Tool/Reference/ListUsersTool.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Mcp\Tool\Reference; -use App\Repository\UserRepository; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use Mcp\Capability\Attribute\McpTool; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -13,7 +13,7 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; class ListUsersTool { public function __construct( - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly Security $security, ) {} diff --git a/src/Mcp/Tool/Reference/UpdateUserTool.php b/src/Mcp/Tool/Reference/UpdateUserTool.php index c7a3d94..58cf1fb 100644 --- a/src/Mcp/Tool/Reference/UpdateUserTool.php +++ b/src/Mcp/Tool/Reference/UpdateUserTool.php @@ -6,7 +6,7 @@ namespace App\Mcp\Tool\Reference; use App\Enum\ContractType; use App\Mcp\Tool\Serializer; -use App\Repository\UserRepository; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; @@ -20,7 +20,7 @@ use function sprintf; class UpdateUserTool { public function __construct( - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly EntityManagerInterface $entityManager, private readonly Security $security, ) {} diff --git a/src/Mcp/Tool/Serializer.php b/src/Mcp/Tool/Serializer.php index 51a47f0..400f278 100644 --- a/src/Mcp/Tool/Serializer.php +++ b/src/Mcp/Tool/Serializer.php @@ -17,7 +17,7 @@ use App\Entity\TaskPriority; use App\Entity\TaskStatus; use App\Entity\TaskTag; use App\Entity\TimeEntry; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Doctrine\Common\Collections\Collection; /** diff --git a/src/Mcp/Tool/Task/CreateTaskTool.php b/src/Mcp/Tool/Task/CreateTaskTool.php index 651ef11..9067417 100644 --- a/src/Mcp/Tool/Task/CreateTaskTool.php +++ b/src/Mcp/Tool/Task/CreateTaskTool.php @@ -6,6 +6,7 @@ namespace App\Mcp\Tool\Task; use App\Entity\Task; use App\Mcp\Tool\Serializer; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\ProjectRepository; use App\Repository\TaskEffortRepository; use App\Repository\TaskGroupRepository; @@ -13,7 +14,6 @@ use App\Repository\TaskPriorityRepository; use App\Repository\TaskRepository; use App\Repository\TaskStatusRepository; use App\Repository\TaskTagRepository; -use App\Repository\UserRepository; use App\Service\CalDavService; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; @@ -36,7 +36,7 @@ class CreateTaskTool private readonly TaskEffortRepository $taskEffortRepository, private readonly TaskGroupRepository $taskGroupRepository, private readonly TaskTagRepository $taskTagRepository, - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly Security $security, private readonly CalDavService $calDavService, ) {} diff --git a/src/Mcp/Tool/Task/UpdateTaskTool.php b/src/Mcp/Tool/Task/UpdateTaskTool.php index 09c53dc..a345f23 100644 --- a/src/Mcp/Tool/Task/UpdateTaskTool.php +++ b/src/Mcp/Tool/Task/UpdateTaskTool.php @@ -5,13 +5,13 @@ declare(strict_types=1); namespace App\Mcp\Tool\Task; use App\Mcp\Tool\Serializer; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\TaskEffortRepository; use App\Repository\TaskGroupRepository; use App\Repository\TaskPriorityRepository; use App\Repository\TaskRepository; use App\Repository\TaskStatusRepository; use App\Repository\TaskTagRepository; -use App\Repository\UserRepository; use App\Service\CalDavService; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; @@ -33,7 +33,7 @@ class UpdateTaskTool private readonly TaskEffortRepository $taskEffortRepository, private readonly TaskGroupRepository $taskGroupRepository, private readonly TaskTagRepository $taskTagRepository, - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly Security $security, private readonly CalDavService $calDavService, ) {} diff --git a/src/Mcp/Tool/TimeEntry/CreateTimeEntryTool.php b/src/Mcp/Tool/TimeEntry/CreateTimeEntryTool.php index 5f5a223..ced019e 100644 --- a/src/Mcp/Tool/TimeEntry/CreateTimeEntryTool.php +++ b/src/Mcp/Tool/TimeEntry/CreateTimeEntryTool.php @@ -6,11 +6,11 @@ namespace App\Mcp\Tool\TimeEntry; use App\Entity\TimeEntry; use App\Mcp\Tool\Serializer; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\ProjectRepository; use App\Repository\TaskRepository; use App\Repository\TaskTagRepository; use App\Repository\TimeEntryRepository; -use App\Repository\UserRepository; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; @@ -25,7 +25,7 @@ class CreateTimeEntryTool { public function __construct( private readonly EntityManagerInterface $entityManager, - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, private readonly ProjectRepository $projectRepository, private readonly TaskRepository $taskRepository, private readonly TaskTagRepository $taskTagRepository, diff --git a/src/Module/Core/Domain/Entity/User.php b/src/Module/Core/Domain/Entity/User.php index a4a098a..7af2ddc 100644 --- a/src/Module/Core/Domain/Entity/User.php +++ b/src/Module/Core/Domain/Entity/User.php @@ -12,10 +12,10 @@ use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use App\Enum\ContractType; -use App\Repository\UserRepository; +use App\Module\Core\Infrastructure\ApiPlatform\State\MeProvider; +use App\Module\Core\Infrastructure\ApiPlatform\State\UserPasswordHasherProcessor; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Shared\Domain\Contract\UserInterface as SharedUserInterface; -use App\State\MeProvider; -use App\State\UserPasswordHasherProcessor; use DateTimeImmutable; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; @@ -43,7 +43,7 @@ use Symfony\Component\Serializer\Attribute\Groups; ], denormalizationContext: ['groups' => ['user:write']], )] -#[ORM\Entity(repositoryClass: UserRepository::class)] +#[ORM\Entity(repositoryClass: DoctrineUserRepository::class)] #[ORM\Table(name: '`user`')] class User implements UserInterface, PasswordAuthenticatedUserInterface, SharedUserInterface { diff --git a/src/State/MeProvider.php b/src/Module/Core/Infrastructure/ApiPlatform/State/MeProvider.php similarity index 84% rename from src/State/MeProvider.php rename to src/Module/Core/Infrastructure/ApiPlatform/State/MeProvider.php index f2866a7..8e973bb 100644 --- a/src/State/MeProvider.php +++ b/src/Module/Core/Infrastructure/ApiPlatform/State/MeProvider.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace App\State; +namespace App\Module\Core\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\SecurityBundle\Security; /** diff --git a/src/State/UserPasswordHasherProcessor.php b/src/Module/Core/Infrastructure/ApiPlatform/State/UserPasswordHasherProcessor.php similarity index 92% rename from src/State/UserPasswordHasherProcessor.php rename to src/Module/Core/Infrastructure/ApiPlatform/State/UserPasswordHasherProcessor.php index 88e9d1c..7dccd1f 100644 --- a/src/State/UserPasswordHasherProcessor.php +++ b/src/Module/Core/Infrastructure/ApiPlatform/State/UserPasswordHasherProcessor.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace App\State; +namespace App\Module\Core\Infrastructure\ApiPlatform\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; diff --git a/src/Repository/UserRepository.php b/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php similarity index 74% rename from src/Repository/UserRepository.php rename to src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php index df31a3f..c688df0 100644 --- a/src/Repository/UserRepository.php +++ b/src/Module/Core/Infrastructure/Doctrine/DoctrineUserRepository.php @@ -2,9 +2,11 @@ declare(strict_types=1); -namespace App\Repository; +namespace App\Module\Core\Infrastructure\Doctrine; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; +use App\Module\Core\Domain\Repository\UserRepositoryInterface; +use App\Shared\Domain\Contract\UserInterface; use DateTimeInterface; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; @@ -12,7 +14,7 @@ use Doctrine\Persistence\ManagerRegistry; /** * @extends ServiceEntityRepository */ -class UserRepository extends ServiceEntityRepository +class DoctrineUserRepository extends ServiceEntityRepository implements UserRepositoryInterface { public function __construct(ManagerRegistry $registry) { @@ -20,7 +22,7 @@ class UserRepository extends ServiceEntityRepository } /** - * @return User[] + * @return list */ public function findByRole(string $role): array { @@ -43,7 +45,7 @@ class UserRepository extends ServiceEntityRepository /** * Employees active on the given date (hired on/before it, not yet left). * - * @return User[] + * @return list */ public function findActiveEmployees(DateTimeInterface $date): array { @@ -59,4 +61,9 @@ class UserRepository extends ServiceEntityRepository ->getResult() ; } + + public function findOneByUsername(string $username): ?UserInterface + { + return $this->findOneBy(['username' => $username]); + } } diff --git a/src/Module/Core/_compat_user_alias.php b/src/Module/Core/_compat_user_alias.php deleted file mode 100644 index 3529be8..0000000 --- a/src/Module/Core/_compat_user_alias.php +++ /dev/null @@ -1,8 +0,0 @@ -findOneBy([ 'user' => $user, diff --git a/src/Repository/AbsenceRequestRepository.php b/src/Repository/AbsenceRequestRepository.php index ffd8d3f..bca61e3 100644 --- a/src/Repository/AbsenceRequestRepository.php +++ b/src/Repository/AbsenceRequestRepository.php @@ -5,9 +5,9 @@ declare(strict_types=1); namespace App\Repository; use App\Entity\AbsenceRequest; -use App\Entity\User; use App\Enum\AbsenceStatus; use App\Enum\AbsenceType; +use App\Shared\Domain\Contract\UserInterface; use DateTimeInterface; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; @@ -28,7 +28,7 @@ class AbsenceRequestRepository extends ServiceEntityRepository * end_a >= start_b. */ public function hasOverlap( - User $user, + UserInterface $user, DateTimeInterface $startDate, DateTimeInterface $endDate, ?int $excludeId = null, @@ -77,7 +77,7 @@ class AbsenceRequestRepository extends ServiceEntityRepository * @return AbsenceRequest[] */ public function findFiltered( - ?User $user = null, + ?UserInterface $user = null, ?AbsenceStatus $status = null, ?AbsenceType $type = null, ?DateTimeInterface $from = null, diff --git a/src/Repository/NotificationRepository.php b/src/Repository/NotificationRepository.php index 7dba9a8..ada482b 100644 --- a/src/Repository/NotificationRepository.php +++ b/src/Repository/NotificationRepository.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Repository; use App\Entity\Notification; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface as SharedUserInterface; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; @@ -30,7 +30,7 @@ class NotificationRepository extends ServiceEntityRepository ; } - public function countUnreadByUser(User $user): int + public function countUnreadByUser(SharedUserInterface $user): int { return (int) $this->createQueryBuilder('n') ->select('COUNT(n.id)') @@ -42,7 +42,7 @@ class NotificationRepository extends ServiceEntityRepository ; } - public function markAllReadByUser(User $user): int + public function markAllReadByUser(SharedUserInterface $user): int { return $this->createQueryBuilder('n') ->update() diff --git a/src/Repository/TimeEntryRepository.php b/src/Repository/TimeEntryRepository.php index b5865b1..3dd9880 100644 --- a/src/Repository/TimeEntryRepository.php +++ b/src/Repository/TimeEntryRepository.php @@ -6,7 +6,7 @@ namespace App\Repository; use App\Entity\Project; use App\Entity\TimeEntry; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; @@ -21,7 +21,7 @@ class TimeEntryRepository extends ServiceEntityRepository parent::__construct($registry, TimeEntry::class); } - public function findActiveByUser(User $user): ?TimeEntry + public function findActiveByUser(UserInterface $user): ?TimeEntry { return $this->findOneBy([ 'user' => $user, @@ -30,9 +30,9 @@ class TimeEntryRepository extends ServiceEntityRepository } /** - * @param null|User[] $users - * @param null|Project[] $projects - * @param null|int[] $tagIds + * @param null|UserInterface[] $users + * @param null|Project[] $projects + * @param null|int[] $tagIds * * @return TimeEntry[] */ diff --git a/src/Security/ApiTokenAuthenticator.php b/src/Security/ApiTokenAuthenticator.php index 1d091a0..03b1978 100644 --- a/src/Security/ApiTokenAuthenticator.php +++ b/src/Security/ApiTokenAuthenticator.php @@ -4,8 +4,8 @@ declare(strict_types=1); namespace App\Security; -use App\Entity\User; -use App\Repository\UserRepository; +use App\Module\Core\Domain\Entity\User; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -20,7 +20,7 @@ use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPasspor class ApiTokenAuthenticator extends AbstractAuthenticator { public function __construct( - private readonly UserRepository $userRepository, + private readonly DoctrineUserRepository $userRepository, ) {} public function supports(Request $request): ?bool diff --git a/src/Security/MailAccessChecker.php b/src/Security/MailAccessChecker.php index 85b73f8..7055dbc 100644 --- a/src/Security/MailAccessChecker.php +++ b/src/Security/MailAccessChecker.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Security; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface as SharedUserInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\User\UserInterface; @@ -23,7 +23,7 @@ final readonly class MailAccessChecker */ public function ensureCanAccessMail(?UserInterface $user): void { - if (!$user instanceof User) { + if (!$user instanceof SharedUserInterface) { throw new AccessDeniedException('Authentication required'); } @@ -41,7 +41,7 @@ final readonly class MailAccessChecker */ public function ensureIsAdmin(?UserInterface $user): void { - if (!$user instanceof User || !$this->authorizationChecker->isGranted('ROLE_ADMIN')) { + if (!$user instanceof SharedUserInterface || !$this->authorizationChecker->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException('Admin only'); } } diff --git a/src/Service/AbsenceBalanceService.php b/src/Service/AbsenceBalanceService.php index 471bd11..a258b30 100644 --- a/src/Service/AbsenceBalanceService.php +++ b/src/Service/AbsenceBalanceService.php @@ -6,8 +6,8 @@ namespace App\Service; use App\Entity\AbsenceBalance; use App\Entity\AbsenceRequest; -use App\Entity\User; use App\Enum\AbsenceType; +use App\Module\Core\Domain\Entity\User; use App\Repository\AbsenceBalanceRepository; use DateTimeInterface; use Doctrine\ORM\EntityManagerInterface; diff --git a/src/State/AbsenceBalanceProvider.php b/src/State/AbsenceBalanceProvider.php index d155efa..9efa094 100644 --- a/src/State/AbsenceBalanceProvider.php +++ b/src/State/AbsenceBalanceProvider.php @@ -7,7 +7,7 @@ namespace App\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; use App\Entity\AbsenceBalance; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -24,7 +24,7 @@ final readonly class AbsenceBalanceProvider implements ProviderInterface public function provide(Operation $operation, array $uriVariables = [], array $context = []): AbsenceBalance|array|null { $user = $this->security->getUser(); - assert($user instanceof User); + assert($user instanceof UserInterface); $repo = $this->entityManager->getRepository(AbsenceBalance::class); $isAdmin = $this->security->isGranted('ROLE_ADMIN'); diff --git a/src/State/AbsenceRequestProcessor.php b/src/State/AbsenceRequestProcessor.php index e65ec99..2e08eb5 100644 --- a/src/State/AbsenceRequestProcessor.php +++ b/src/State/AbsenceRequestProcessor.php @@ -7,13 +7,13 @@ namespace App\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\Entity\AbsenceRequest; -use App\Entity\User; use App\Enum\AbsenceStatus; use App\Enum\AbsenceType; use App\Repository\AbsencePolicyRepository; use App\Repository\AbsenceRequestRepository; use App\Service\AbsenceBalanceService; use App\Service\AbsenceDayCalculator; +use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -42,7 +42,7 @@ final readonly class AbsenceRequestProcessor implements ProcessorInterface assert($data instanceof AbsenceRequest); $user = $this->security->getUser(); - assert($user instanceof User); + assert($user instanceof UserInterface); $type = $data->getType(); $startDate = $data->getStartDate(); diff --git a/src/State/AbsenceRequestProvider.php b/src/State/AbsenceRequestProvider.php index 0e05508..8287b37 100644 --- a/src/State/AbsenceRequestProvider.php +++ b/src/State/AbsenceRequestProvider.php @@ -7,7 +7,7 @@ namespace App\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; use App\Entity\AbsenceRequest; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -24,7 +24,7 @@ final readonly class AbsenceRequestProvider implements ProviderInterface public function provide(Operation $operation, array $uriVariables = [], array $context = []): AbsenceRequest|array|null { $user = $this->security->getUser(); - assert($user instanceof User); + assert($user instanceof UserInterface); $repo = $this->entityManager->getRepository(AbsenceRequest::class); $isAdmin = $this->security->isGranted('ROLE_ADMIN'); diff --git a/src/State/AbsenceReviewProcessor.php b/src/State/AbsenceReviewProcessor.php index 0eecb1e..4f40863 100644 --- a/src/State/AbsenceReviewProcessor.php +++ b/src/State/AbsenceReviewProcessor.php @@ -7,9 +7,9 @@ namespace App\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\Entity\AbsenceRequest; -use App\Entity\User; use App\Enum\AbsenceStatus; use App\Service\AbsenceBalanceService; +use App\Shared\Domain\Contract\UserInterface; use DateTimeImmutable; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -55,7 +55,7 @@ final readonly class AbsenceReviewProcessor implements ProcessorInterface } $admin = $this->security->getUser(); - assert($admin instanceof User); + assert($admin instanceof UserInterface); if ($isApprove) { // Never let an approval push the balance below zero (CP only): the diff --git a/src/State/TaskDocumentProvider.php b/src/State/TaskDocumentProvider.php index f998d17..62cea2f 100644 --- a/src/State/TaskDocumentProvider.php +++ b/src/State/TaskDocumentProvider.php @@ -7,7 +7,7 @@ namespace App\State; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; use App\Entity\TaskDocument; -use App\Entity\User; +use App\Shared\Domain\Contract\UserInterface; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\SecurityBundle\Security; @@ -24,7 +24,7 @@ final readonly class TaskDocumentProvider implements ProviderInterface public function provide(Operation $operation, array $uriVariables = [], array $context = []): array|TaskDocument|null { $user = $this->security->getUser(); - assert($user instanceof User); + assert($user instanceof UserInterface); $repo = $this->entityManager->getRepository(TaskDocument::class); diff --git a/tests/Functional/Controller/Mail/MailFoldersControllerTest.php b/tests/Functional/Controller/Mail/MailFoldersControllerTest.php index 2266047..49dfa6d 100644 --- a/tests/Functional/Controller/Mail/MailFoldersControllerTest.php +++ b/tests/Functional/Controller/Mail/MailFoldersControllerTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller\Mail; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** diff --git a/tests/Functional/Controller/Mail/MailMessagesControllerTest.php b/tests/Functional/Controller/Mail/MailMessagesControllerTest.php index 041cc21..adbe9ab 100644 --- a/tests/Functional/Controller/Mail/MailMessagesControllerTest.php +++ b/tests/Functional/Controller/Mail/MailMessagesControllerTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller\Mail; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** diff --git a/tests/Functional/Controller/Mail/MailSettingsControllerTest.php b/tests/Functional/Controller/Mail/MailSettingsControllerTest.php index 63c1d0c..8811958 100644 --- a/tests/Functional/Controller/Mail/MailSettingsControllerTest.php +++ b/tests/Functional/Controller/Mail/MailSettingsControllerTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller\Mail; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** diff --git a/tests/Functional/Controller/Mail/MailSyncTriggerControllerTest.php b/tests/Functional/Controller/Mail/MailSyncTriggerControllerTest.php index 4cdc7cf..e947556 100644 --- a/tests/Functional/Controller/Mail/MailSyncTriggerControllerTest.php +++ b/tests/Functional/Controller/Mail/MailSyncTriggerControllerTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller\Mail; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** diff --git a/tests/Functional/Controller/Mail/MailTaskIntegrationControllerTest.php b/tests/Functional/Controller/Mail/MailTaskIntegrationControllerTest.php index ba9e55a..3b7d6e1 100644 --- a/tests/Functional/Controller/Mail/MailTaskIntegrationControllerTest.php +++ b/tests/Functional/Controller/Mail/MailTaskIntegrationControllerTest.php @@ -8,7 +8,7 @@ use App\Entity\MailFolder; use App\Entity\MailMessage; use App\Entity\Project; use App\Entity\Task; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use DateTimeImmutable; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; diff --git a/tests/Functional/Controller/ShareBrowseTest.php b/tests/Functional/Controller/ShareBrowseTest.php index d415f12..397bdf4 100644 --- a/tests/Functional/Controller/ShareBrowseTest.php +++ b/tests/Functional/Controller/ShareBrowseTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; diff --git a/tests/Functional/Controller/ShareSearchTest.php b/tests/Functional/Controller/ShareSearchTest.php index 62e9bbd..ea48784 100644 --- a/tests/Functional/Controller/ShareSearchTest.php +++ b/tests/Functional/Controller/ShareSearchTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; diff --git a/tests/Functional/Controller/ShareSettingsTest.php b/tests/Functional/Controller/ShareSettingsTest.php index b257b08..869d362 100644 --- a/tests/Functional/Controller/ShareSettingsTest.php +++ b/tests/Functional/Controller/ShareSettingsTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Controller; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /** diff --git a/tests/Functional/EventListener/TaskNotificationListenerTest.php b/tests/Functional/EventListener/TaskNotificationListenerTest.php index 158fd17..814fdef 100644 --- a/tests/Functional/EventListener/TaskNotificationListenerTest.php +++ b/tests/Functional/EventListener/TaskNotificationListenerTest.php @@ -6,7 +6,7 @@ namespace App\Tests\Functional\EventListener; use App\Entity\Project; use App\Entity\Task; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use App\Repository\NotificationRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; diff --git a/tests/Functional/Mcp/AbsenceRequestLifecycleTest.php b/tests/Functional/Mcp/AbsenceRequestLifecycleTest.php index 55fa495..1036b6d 100644 --- a/tests/Functional/Mcp/AbsenceRequestLifecycleTest.php +++ b/tests/Functional/Mcp/AbsenceRequestLifecycleTest.php @@ -6,15 +6,15 @@ namespace App\Tests\Functional\Mcp; use App\Entity\AbsenceBalance; use App\Entity\AbsencePolicy; -use App\Entity\User; use App\Enum\AbsenceType; use App\Mcp\Tool\Absence\CancelAbsenceRequestTool; use App\Mcp\Tool\Absence\CreateAbsenceRequestTool; use App\Mcp\Tool\Absence\ReviewAbsenceRequestTool; +use App\Module\Core\Domain\Entity\User; +use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository; use App\Repository\AbsenceBalanceRepository; use App\Repository\AbsencePolicyRepository; use App\Repository\AbsenceRequestRepository; -use App\Repository\UserRepository; use App\Service\AbsenceBalanceService; use App\Service\AbsenceDayCalculator; use Doctrine\ORM\EntityManagerInterface; @@ -216,7 +216,7 @@ class AbsenceRequestLifecycleTest extends KernelTestCase return new CreateAbsenceRequestTool( $c->get(EntityManagerInterface::class), - $c->get(UserRepository::class), + $c->get(DoctrineUserRepository::class), $c->get(AbsencePolicyRepository::class), $c->get(AbsenceRequestRepository::class), $c->get(AbsenceDayCalculator::class), diff --git a/tests/Functional/Shared/SidebarEndpointTest.php b/tests/Functional/Shared/SidebarEndpointTest.php index 9d6058e..bc7c079 100644 --- a/tests/Functional/Shared/SidebarEndpointTest.php +++ b/tests/Functional/Shared/SidebarEndpointTest.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Tests\Functional\Shared; -use App\Entity\User; +use App\Module\Core\Domain\Entity\User; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; /**