refactor(core) : final legacy cleanup — app is 100% modular

LST-60 (3.3). Closes the modular-monolith migration. src/Entity was already
empty; this removes the last legacy residue.

- Doctrine: drop the legacy "App" mapping (empty src/Entity). resolve_target_
  entities already targets modules only.
- MCP User tools (Reference/) -> Core/Infrastructure/Mcp/Tool; MCP Serializer
  -> Shared/Infrastructure/Mcp (33 usages repointed).
- Controllers (mark-all-read, notification unread-count, regenerate-api-token,
  user-avatar) -> Core/Infrastructure/Controller. TokenEncryptor -> Shared/
  Infrastructure/Service (11 usages). AppVersion resource+provider -> Shared.
  ContractType enum -> Core/Domain/Enum.
- src/{Entity,State,Controller,Service,Enum,ApiResource} now empty; routes,
  MCP tool names and public API unchanged.

180 tests green, mapping valid, no route regression, cs-fixer clean.
Note: final Malio visual harmonisation (subjective) left to the PO.
This commit is contained in:
Matthieu
2026-06-21 01:25:19 +02:00
parent 0cce586a1f
commit da3d190216
58 changed files with 62 additions and 68 deletions
@@ -4,10 +4,10 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Application\Service\AbsenceBalanceService;
use App\Module\Absence\Domain\Enum\AbsenceStatus;
use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Application\Service\AbsenceBalanceService;
use App\Module\Absence\Domain\Entity\AbsenceRequest;
use App\Module\Absence\Domain\Enum\AbsenceStatus;
@@ -14,6 +13,7 @@ use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface;
use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use App\Module\Absence\Domain\Service\AbsenceDayCalculator;
use App\Module\Core\Domain\Repository\UserRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,10 +4,10 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Domain\Enum\AbsenceType;
use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface;
use App\Module\Core\Domain\Repository\UserRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -4,11 +4,11 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Domain\Enum\AbsenceStatus;
use App\Module\Absence\Domain\Enum\AbsenceType;
use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use App\Module\Core\Domain\Repository\UserRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,11 +4,11 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Application\Service\AbsenceBalanceService;
use App\Module\Absence\Domain\Enum\AbsenceStatus;
use App\Module\Absence\Domain\Repository\AbsenceRequestRepositoryInterface;
use App\Shared\Domain\Contract\UserInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Domain\Repository\AbsenceBalanceRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Absence\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Absence\Domain\Repository\AbsencePolicyRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
+1 -1
View File
@@ -11,7 +11,7 @@ use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Enum\ContractType;
use App\Module\Core\Domain\Enum\ContractType;
use App\Module\Core\Infrastructure\ApiPlatform\State\MeProvider;
use App\Module\Core\Infrastructure\ApiPlatform\State\Processor\UserRbacProcessor;
use App\Module\Core\Infrastructure\ApiPlatform\State\UserPasswordHasherProcessor;
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Domain\Enum;
enum ContractType: string
{
case Cdi = 'CDI';
case Cdd = 'CDD';
case Internship = 'STAGE';
case Apprentice = 'ALTERNANCE';
case Other = 'AUTRE';
public function label(): string
{
return match ($this) {
self::Cdi => 'CDI',
self::Cdd => 'CDD',
self::Internship => 'Stage',
self::Apprentice => 'Alternance',
self::Other => 'Autre',
};
}
}
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Controller;
use App\Module\Core\Infrastructure\Doctrine\DoctrineNotificationRepository;
use App\Shared\Domain\Contract\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class MarkAllReadController extends AbstractController
{
public function __construct(
private readonly DoctrineNotificationRepository $notificationRepository,
) {}
#[Route('/api/notifications/mark-all-read', name: 'notification_mark_all_read', methods: ['POST'], priority: 1)]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function __invoke(): Response
{
/** @var UserInterface $user */
$user = $this->getUser();
$this->notificationRepository->markAllReadByUser($user);
return new Response(null, Response::HTTP_NO_CONTENT);
}
}
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Controller;
use App\Module\Core\Infrastructure\Doctrine\DoctrineNotificationRepository;
use App\Shared\Domain\Contract\UserInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class NotificationUnreadCountController extends AbstractController
{
public function __construct(
private readonly DoctrineNotificationRepository $notificationRepository,
) {}
#[Route('/api/notifications/unread-count', name: 'notification_unread_count', methods: ['GET'], priority: 1)]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function __invoke(): JsonResponse
{
/** @var UserInterface $user */
$user = $this->getUser();
$count = $this->notificationRepository->countUnreadByUser($user);
return new JsonResponse(['count' => $count]);
}
}
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Controller;
use App\Module\Core\Domain\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use function bin2hex;
use function random_bytes;
class RegenerateApiTokenController extends AbstractController
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
) {}
#[Route('/api/me/regenerate-api-token', name: 'me_regenerate_api_token', methods: ['POST'], priority: 1)]
#[IsGranted('ROLE_USER')]
public function __invoke(): JsonResponse
{
/** @var User $user */
$user = $this->getUser();
$token = bin2hex(random_bytes(32));
$user->setApiToken($token);
$this->entityManager->flush();
return new JsonResponse(['apiToken' => $token]);
}
}
@@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Controller;
use App\Module\Core\Domain\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Uid\Uuid;
class UserAvatarController extends AbstractController
{
private const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5 MB
private const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly string $avatarUploadDir,
) {}
#[Route('/api/users/{id}/avatar', name: 'user_avatar_upload', methods: ['POST'], priority: 1)]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function upload(int $id, Request $request): JsonResponse
{
$user = $this->findUserOrFail($id);
$this->assertCanManageAvatar($user);
$file = $request->files->get('file');
if (null === $file || !$file->isValid()) {
throw new BadRequestHttpException('No valid file uploaded.');
}
if ($file->getSize() > self::MAX_FILE_SIZE) {
throw new BadRequestHttpException('File size exceeds 5 MB limit.');
}
$mimeType = $file->getMimeType();
if (!in_array($mimeType, self::ALLOWED_MIME_TYPES, true)) {
throw new BadRequestHttpException('Invalid file type. Allowed: JPEG, PNG, WebP, GIF.');
}
// Delete previous avatar file if exists
$this->deleteAvatarFile($user);
$extension = $file->guessExtension() ?? 'bin';
$fileName = Uuid::v4()->toRfc4122().'.'.$extension;
if (!is_dir($this->avatarUploadDir)) {
mkdir($this->avatarUploadDir, 0o775, true);
}
$file->move($this->avatarUploadDir, $fileName);
$user->setAvatarFileName($fileName);
$this->entityManager->flush();
return new JsonResponse(['avatarUrl' => $user->getAvatarUrl()]);
}
#[Route('/api/users/{id}/avatar', name: 'user_avatar_serve', methods: ['GET'], priority: 1)]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function serve(int $id): BinaryFileResponse
{
$user = $this->findUserOrFail($id);
if (null === $user->getAvatarFileName()) {
throw new NotFoundHttpException('No avatar set.');
}
$filePath = $this->avatarUploadDir.'/'.$user->getAvatarFileName();
if (!file_exists($filePath)) {
throw new NotFoundHttpException('Avatar file not found on disk.');
}
$response = new BinaryFileResponse($filePath);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, $user->getAvatarFileName());
$extension = pathinfo($user->getAvatarFileName(), PATHINFO_EXTENSION);
$mimeMap = ['jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'webp' => 'image/webp', 'gif' => 'image/gif'];
$response->headers->set('Content-Type', $mimeMap[$extension] ?? 'application/octet-stream');
$response->headers->set('Cache-Control', 'public, max-age=86400');
return $response;
}
#[Route('/api/users/{id}/avatar', name: 'user_avatar_delete', methods: ['DELETE'], priority: 1)]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
public function delete(int $id): Response
{
$user = $this->findUserOrFail($id);
$this->assertCanManageAvatar($user);
$this->deleteAvatarFile($user);
$user->setAvatarFileName(null);
$this->entityManager->flush();
return new Response(null, Response::HTTP_NO_CONTENT);
}
private function findUserOrFail(int $id): User
{
$user = $this->entityManager->getRepository(User::class)->find($id);
if (null === $user) {
throw new NotFoundHttpException('User not found.');
}
return $user;
}
private function assertCanManageAvatar(User $user): void
{
$currentUser = $this->getUser();
if ($currentUser !== $user && !$this->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedHttpException('You can only manage your own avatar.');
}
}
private function deleteAvatarFile(User $user): void
{
if (null === $user->getAvatarFileName()) {
return;
}
$filePath = $this->avatarUploadDir.'/'.$user->getAvatarFileName();
if (file_exists($filePath)) {
unlink($filePath);
}
}
}
@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Mcp\Tool;
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use function sprintf;
#[McpTool(name: 'get-user', description: 'Get a user by ID with full HR profile (employee flag, hire/end date, contract, work-time ratio, leave entitlement, reference period, family situation).')]
class GetUserTool
{
public function __construct(
private readonly DoctrineUserRepository $userRepository,
private readonly Security $security,
) {}
public function __invoke(int $id): string
{
if (!$this->security->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException('Access denied: ROLE_ADMIN required.');
}
$user = $this->userRepository->find($id);
if (null === $user) {
throw new InvalidArgumentException(sprintf('User with ID %d not found.', $id));
}
return json_encode(Serializer::userFull($user));
}
}
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Mcp\Tool;
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
#[McpTool(name: 'list-users', description: 'List all users with their IDs and usernames. Use this to discover valid user IDs for assignee or time entry parameters.')]
class ListUsersTool
{
public function __construct(
private readonly DoctrineUserRepository $userRepository,
private readonly Security $security,
) {}
public function __invoke(): string
{
if (!$this->security->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException('Access denied: ROLE_ADMIN required.');
}
$users = $this->userRepository->findBy([], ['username' => 'ASC']);
return json_encode(array_map(fn ($user) => [
'id' => $user->getId(),
'username' => $user->getUsername(),
], $users));
}
}
@@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
namespace App\Module\Core\Infrastructure\Mcp\Tool;
use App\Module\Core\Domain\Enum\ContractType;
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use function sprintf;
#[McpTool(name: 'update-user', description: 'Update a user HR/profile fields (admin). Does NOT change password or roles. contractType = CDI|CDD|STAGE|ALTERNANCE|AUTRE. hireDate/endDate as YYYY-MM-DD. referencePeriodStart as MM-DD (e.g. 06-01).')]
class UpdateUserTool
{
public function __construct(
private readonly DoctrineUserRepository $userRepository,
private readonly EntityManagerInterface $entityManager,
private readonly Security $security,
) {}
public function __invoke(
int $id,
?bool $isEmployee = null,
?string $hireDate = null,
?string $endDate = null,
?string $contractType = null,
?float $workTimeRatio = null,
?float $annualLeaveDays = null,
?string $referencePeriodStart = null,
?float $initialLeaveBalance = null,
): string {
if (!$this->security->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException('Access denied: ROLE_ADMIN required.');
}
$user = $this->userRepository->find($id);
if (null === $user) {
throw new InvalidArgumentException(sprintf('User with ID %d not found.', $id));
}
if (null !== $isEmployee) {
$user->setIsEmployee($isEmployee);
}
if (null !== $hireDate) {
$user->setHireDate(new DateTimeImmutable($hireDate));
}
if (null !== $endDate) {
$user->setEndDate(new DateTimeImmutable($endDate));
}
if (null !== $contractType) {
$user->setContractType(
ContractType::tryFrom($contractType)
?? throw new InvalidArgumentException(sprintf('Unknown contract type "%s".', $contractType)),
);
}
if (null !== $workTimeRatio) {
$user->setWorkTimeRatio($workTimeRatio);
}
if (null !== $annualLeaveDays) {
$user->setAnnualLeaveDays($annualLeaveDays);
}
if (null !== $referencePeriodStart) {
$user->setReferencePeriodStart($referencePeriodStart);
}
if (null !== $initialLeaveBalance) {
$user->setInitialLeaveBalance($initialLeaveBalance);
}
$this->entityManager->flush();
return json_encode(Serializer::userFull($user));
}
}
@@ -4,10 +4,10 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Entity\Client;
use App\Module\Directory\Domain\Enum\ProspectStatus;
use App\Module\Directory\Domain\Repository\ProspectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Entity\Client;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Entity\Prospect;
use App\Module\Directory\Domain\Enum\ProspectStatus;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Repository\ClientRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Repository\ProspectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Enum\ProspectStatus;
use App\Module\Directory\Domain\Repository\ProspectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Repository\ClientRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\Directory\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Enum\ProspectStatus;
use App\Module\Directory\Domain\Repository\ProspectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -9,7 +9,7 @@ use ApiPlatform\State\ProcessorInterface;
use App\Module\Integration\Domain\Entity\BookStackConfiguration;
use App\Module\Integration\Domain\Repository\BookStackConfigurationRepositoryInterface;
use App\Module\Integration\Infrastructure\ApiPlatform\Resource\BookStackSettings;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Doctrine\ORM\EntityManagerInterface;
final readonly class BookStackSettingsProcessor implements ProcessorInterface
@@ -9,7 +9,7 @@ use ApiPlatform\State\ProcessorInterface;
use App\Module\Integration\Domain\Entity\GiteaConfiguration;
use App\Module\Integration\Domain\Repository\GiteaConfigurationRepositoryInterface;
use App\Module\Integration\Infrastructure\ApiPlatform\Resource\GiteaSettings;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Doctrine\ORM\EntityManagerInterface;
final readonly class GiteaSettingsProcessor implements ProcessorInterface
@@ -9,7 +9,7 @@ use ApiPlatform\State\ProcessorInterface;
use App\Module\Integration\Domain\Entity\ShareConfiguration;
use App\Module\Integration\Domain\Repository\ShareConfigurationRepositoryInterface;
use App\Module\Integration\Infrastructure\ApiPlatform\Resource\ShareSettings;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Doctrine\ORM\EntityManagerInterface;
final readonly class ShareSettingsProcessor implements ProcessorInterface
@@ -9,7 +9,7 @@ use ApiPlatform\State\ProcessorInterface;
use App\Module\Integration\Domain\Entity\ZimbraConfiguration;
use App\Module\Integration\Domain\Repository\ZimbraConfigurationRepositoryInterface;
use App\Module\Integration\Infrastructure\ApiPlatform\Resource\ZimbraSettings;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Doctrine\ORM\EntityManagerInterface;
final readonly class ZimbraSettingsProcessor implements ProcessorInterface
@@ -7,7 +7,7 @@ namespace App\Module\Integration\Infrastructure\Service;
use App\Module\Integration\Domain\Entity\BookStackConfiguration;
use App\Module\Integration\Domain\Exception\BookStackApiException;
use App\Module\Integration\Domain\Repository\BookStackConfigurationRepositoryInterface;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
@@ -9,7 +9,7 @@ use App\Module\Integration\Domain\Exception\GiteaApiException;
use App\Module\Integration\Domain\Repository\GiteaConfigurationRepositoryInterface;
use App\Module\ProjectManagement\Domain\Entity\Project;
use App\Module\ProjectManagement\Domain\Entity\Task;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Symfony\Component\String\Slugger\AsciiSlugger;
use Symfony\Component\String\Slugger\SluggerInterface;
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
@@ -12,7 +12,7 @@ use App\Module\Integration\Domain\Service\FileEntry;
use App\Module\Integration\Domain\Service\FileSource;
use App\Module\Integration\Domain\Service\SharePathResolver;
use App\Module\Integration\Domain\Service\ShareTestResult;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Icewind\SMB\BasicAuth;
use Icewind\SMB\IFileInfo;
use Icewind\SMB\IShare;
@@ -9,7 +9,7 @@ use ApiPlatform\State\ProcessorInterface;
use App\Module\Mail\Domain\Entity\MailConfiguration;
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
use App\Module\Mail\Infrastructure\ApiPlatform\Resource\MailSettings;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use Doctrine\ORM\EntityManagerInterface;
final readonly class MailSettingsProcessor implements ProcessorInterface
@@ -11,7 +11,7 @@ use App\Module\Mail\Application\Dto\MailMessageHeaderDto;
use App\Module\Mail\Domain\Exception\MailProviderException;
use App\Module\Mail\Domain\Provider\MailProviderInterface;
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use DateTimeImmutable;
use Psr\Log\LoggerInterface;
use SodiumException;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Project;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Repository\ClientRepositoryInterface;
use App\Module\ProjectManagement\Domain\Entity\Project;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Project;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Project;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Project;
use App\Mcp\Tool\Serializer;
use App\Module\Directory\Domain\Repository\ClientRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Task;
use App\Mcp\Tool\Serializer;
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
use App\Module\ProjectManagement\Domain\Entity\Task;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
@@ -15,6 +14,7 @@ use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskStatusRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskTagRepositoryInterface;
use App\Module\ProjectManagement\Infrastructure\Service\CalDavService;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Task;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Task;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\Task;
use App\Mcp\Tool\Serializer;
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
use App\Module\ProjectManagement\Domain\Repository\TaskEffortRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskGroupRepositoryInterface;
@@ -13,6 +12,7 @@ use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskStatusRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskTagRepositoryInterface;
use App\Module\ProjectManagement\Infrastructure\Service\CalDavService;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\TaskMeta;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Entity\TaskGroup;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\TaskMeta;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\TaskGroupRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\ProjectManagement\Infrastructure\Mcp\Tool\TaskMeta;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\TaskGroupRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
use Mcp\Capability\Attribute\McpTool;
@@ -8,7 +8,7 @@ use App\Module\Integration\Domain\Repository\ZimbraConfigurationRepositoryInterf
use App\Module\ProjectManagement\Domain\Entity\Task;
use App\Module\ProjectManagement\Domain\Entity\TaskRecurrence;
use App\Module\ProjectManagement\Domain\Enum\RecurrenceType;
use App\Service\TokenEncryptor;
use App\Shared\Infrastructure\Service\TokenEncryptor;
use DateTimeZone;
use Psr\Log\LoggerInterface;
use Sabre\VObject\Component\VCalendar;
@@ -4,13 +4,13 @@ declare(strict_types=1);
namespace App\Module\TimeTracking\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\Core\Infrastructure\Doctrine\DoctrineUserRepository;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskTagRepositoryInterface;
use App\Module\TimeTracking\Domain\Entity\TimeEntry;
use App\Module\TimeTracking\Domain\Repository\TimeEntryRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;
@@ -4,8 +4,8 @@ declare(strict_types=1);
namespace App\Module\TimeTracking\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\TimeTracking\Domain\Repository\TimeEntryRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Mcp\Capability\Attribute\McpTool;
use Symfony\Bundle\SecurityBundle\Security;
@@ -4,11 +4,11 @@ declare(strict_types=1);
namespace App\Module\TimeTracking\Infrastructure\Mcp\Tool;
use App\Mcp\Tool\Serializer;
use App\Module\ProjectManagement\Domain\Repository\ProjectRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
use App\Module\ProjectManagement\Domain\Repository\TaskTagRepositoryInterface;
use App\Module\TimeTracking\Domain\Repository\TimeEntryRepositoryInterface;
use App\Shared\Infrastructure\Mcp\Serializer;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use InvalidArgumentException;