feat(mail) : migrate Mail integration into module (back)
LST-67 (2.5) backend. Behaviour-preserving move of the IMAP mail integration into src/Module/Mail/. All /api/mail/* routes, securities (ROLE_CLIENT still excluded via MailAccessChecker) and the async sync are unchanged. - 4 entities + 4 repositories (Domain interfaces + Doctrine impls, bound). TaskMailLink.task now references TaskInterface (contract) instead of the concrete PM Task. Link/unlink/list-mails controllers load tasks via TaskRepositoryInterface; MailCreateTaskController keeps the concrete Task (instantiation) — documented Mail->PM coupling. - Domain (MailProviderInterface, exception), Application (5 DTOs, MailSyncService, MailSyncRequested message + handler), Infrastructure (ImapMailProvider + MimeHeaderDecoder, MailAccessChecker, 2 console commands, 12 controllers, ApiPlatform state + MailSettings resource). TokenEncryptor stays shared. - doctrine mapping Mail; messenger routing repointed; services.yaml repo + provider bindings; MailModule registered (id mail, mail.access/configure). - #[Auditable] + Timestampable on MailConfiguration only (additive migration); IMAP data entities keep their own sync timestamps. 163 tests green, mapping valid, no route regression, cs-fixer clean.
This commit is contained in:
@@ -10,6 +10,7 @@ declare(strict_types=1);
|
||||
use App\Module\Absence\AbsenceModule;
|
||||
use App\Module\Core\CoreModule;
|
||||
use App\Module\Directory\DirectoryModule;
|
||||
use App\Module\Mail\MailModule;
|
||||
use App\Module\ProjectManagement\ProjectManagementModule;
|
||||
use App\Module\TimeTracking\TimeTrackingModule;
|
||||
|
||||
@@ -19,4 +20,5 @@ return [
|
||||
ProjectManagementModule::class,
|
||||
AbsenceModule::class,
|
||||
DirectoryModule::class,
|
||||
MailModule::class,
|
||||
];
|
||||
|
||||
@@ -58,6 +58,11 @@ doctrine:
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src/Module/Directory/Domain/Entity'
|
||||
prefix: 'App\Module\Directory\Domain\Entity'
|
||||
Mail:
|
||||
type: attribute
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src/Module/Mail/Domain/Entity'
|
||||
prefix: 'App\Module\Mail\Domain\Entity'
|
||||
controller_resolver:
|
||||
auto_mapping: false
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ framework:
|
||||
# messenger:consume à maintenir. La sync de fond reste assurée par le cron OS
|
||||
# (app:mail:sync, synchrone, indépendant du bus). Repasser à `async` + worker si
|
||||
# la boîte grossit au point que la sync à la demande approche le timeout PHP.
|
||||
'App\Message\MailSyncRequested': sync
|
||||
'App\Module\Mail\Application\Message\MailSyncRequested': sync
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
|
||||
@@ -103,4 +103,14 @@ services:
|
||||
|
||||
App\Module\Directory\Domain\Repository\ProspectRepositoryInterface: '@App\Module\Directory\Infrastructure\Doctrine\DoctrineProspectRepository'
|
||||
|
||||
App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface: '@App\Module\Mail\Infrastructure\Doctrine\DoctrineMailConfigurationRepository'
|
||||
|
||||
App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface: '@App\Module\Mail\Infrastructure\Doctrine\DoctrineMailFolderRepository'
|
||||
|
||||
App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface: '@App\Module\Mail\Infrastructure\Doctrine\DoctrineMailMessageRepository'
|
||||
|
||||
App\Module\Mail\Domain\Repository\TaskMailLinkRepositoryInterface: '@App\Module\Mail\Infrastructure\Doctrine\DoctrineTaskMailLinkRepository'
|
||||
|
||||
App\Module\Mail\Domain\Provider\MailProviderInterface: '@App\Module\Mail\Infrastructure\Imap\ImapMailProvider'
|
||||
|
||||
App\Shared\Domain\Contract\NotifierInterface: '@App\Module\Core\Infrastructure\Notifier'
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Mail module: add Timestampable + Blamable tracking on mail_configuration.
|
||||
*
|
||||
* Purely additive — adds nullable audit columns to an existing table:
|
||||
* created_at / updated_at (Timestampable)
|
||||
* created_by / updated_by -> "user"(id) ON DELETE SET NULL (Blamable)
|
||||
* No DROP/ALTER on existing data. Columns are lowercase snake_case.
|
||||
* Hand-written to mirror the schema dump and guarantee zero destructive
|
||||
* instruction. down() drops the new columns and their FKs/indexes.
|
||||
*/
|
||||
final class Version20260620200000 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Mail: add Timestampable/Blamable columns on mail_configuration (additive)';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE mail_configuration ADD created_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE mail_configuration ADD updated_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE mail_configuration ADD created_by INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE mail_configuration ADD updated_by INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE mail_configuration ADD CONSTRAINT FK_BFC0A7DBDE12AB56 FOREIGN KEY (created_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('ALTER TABLE mail_configuration ADD CONSTRAINT FK_BFC0A7DB16FE72E1 FOREIGN KEY (updated_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE');
|
||||
$this->addSql('CREATE INDEX IDX_BFC0A7DBDE12AB56 ON mail_configuration (created_by)');
|
||||
$this->addSql('CREATE INDEX IDX_BFC0A7DB16FE72E1 ON mail_configuration (updated_by)');
|
||||
$this->addSql("COMMENT ON COLUMN mail_configuration.created_at IS 'Creation timestamp (Timestampable, set on prePersist)'");
|
||||
$this->addSql("COMMENT ON COLUMN mail_configuration.updated_at IS 'Last update timestamp (Timestampable, set on prePersist/preUpdate)'");
|
||||
$this->addSql("COMMENT ON COLUMN mail_configuration.created_by IS 'User who created the entry (Blamable, FK user.id, SET NULL on delete)'");
|
||||
$this->addSql("COMMENT ON COLUMN mail_configuration.updated_by IS 'User who last updated the entry (Blamable, FK user.id, SET NULL on delete)'");
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE mail_configuration DROP CONSTRAINT FK_BFC0A7DBDE12AB56');
|
||||
$this->addSql('ALTER TABLE mail_configuration DROP CONSTRAINT FK_BFC0A7DB16FE72E1');
|
||||
$this->addSql('DROP INDEX IDX_BFC0A7DBDE12AB56');
|
||||
$this->addSql('DROP INDEX IDX_BFC0A7DB16FE72E1');
|
||||
$this->addSql('ALTER TABLE mail_configuration DROP created_at');
|
||||
$this->addSql('ALTER TABLE mail_configuration DROP updated_at');
|
||||
$this->addSql('ALTER TABLE mail_configuration DROP created_by');
|
||||
$this->addSql('ALTER TABLE mail_configuration DROP updated_by');
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\DataFixtures;
|
||||
|
||||
use App\Entity\MailConfiguration;
|
||||
use App\Entity\ZimbraConfiguration;
|
||||
use App\Enum\ContractType;
|
||||
use App\Module\Absence\Domain\Entity\AbsenceBalance;
|
||||
@@ -17,6 +16,7 @@ use App\Module\Core\Domain\Entity\User;
|
||||
use App\Module\Directory\Domain\Entity\Client;
|
||||
use App\Module\Directory\Domain\Entity\Prospect;
|
||||
use App\Module\Directory\Domain\Enum\ProspectStatus;
|
||||
use App\Module\Mail\Domain\Entity\MailConfiguration;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Project;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Module\ProjectManagement\Domain\Entity\TaskEffort;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail\Dto;
|
||||
namespace App\Module\Mail\Application\Dto;
|
||||
|
||||
final readonly class MailAttachmentDto
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail\Dto;
|
||||
namespace App\Module\Mail\Application\Dto;
|
||||
|
||||
final readonly class MailFolderDto
|
||||
{
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail\Dto;
|
||||
namespace App\Module\Mail\Application\Dto;
|
||||
|
||||
final readonly class MailMessageDetailDto
|
||||
{
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail\Dto;
|
||||
namespace App\Module\Mail\Application\Dto;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail\Dto;
|
||||
namespace App\Module\Mail\Application\Dto;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Message;
|
||||
namespace App\Module\Mail\Application\Message;
|
||||
|
||||
final readonly class MailSyncRequested
|
||||
{
|
||||
+5
-5
@@ -2,11 +2,11 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\MessageHandler;
|
||||
namespace App\Module\Mail\Application\MessageHandler;
|
||||
|
||||
use App\Message\MailSyncRequested;
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Service\MailSyncService;
|
||||
use App\Module\Mail\Application\Message\MailSyncRequested;
|
||||
use App\Module\Mail\Application\Service\MailSyncService;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
|
||||
use Throwable;
|
||||
@@ -16,7 +16,7 @@ final readonly class MailSyncRequestedHandler
|
||||
{
|
||||
public function __construct(
|
||||
private MailSyncService $mailSyncService,
|
||||
private MailFolderRepository $folderRepository,
|
||||
private MailFolderRepositoryInterface $folderRepository,
|
||||
private LoggerInterface $logger,
|
||||
) {}
|
||||
|
||||
+12
-12
@@ -2,16 +2,16 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Service;
|
||||
namespace App\Module\Mail\Application\Service;
|
||||
|
||||
use App\Entity\MailFolder;
|
||||
use App\Entity\MailMessage;
|
||||
use App\Mail\Dto\MailSyncReport;
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Module\Mail\Application\Dto\MailSyncReport;
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Entity\MailMessage;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
@@ -27,9 +27,9 @@ final class MailSyncService
|
||||
|
||||
public function __construct(
|
||||
private readonly MailProviderInterface $provider,
|
||||
private readonly MailConfigurationRepository $configRepository,
|
||||
private readonly MailFolderRepository $folderRepository,
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailConfigurationRepositoryInterface $configRepository,
|
||||
private readonly MailFolderRepositoryInterface $folderRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LockFactory $lockFactory,
|
||||
private readonly LoggerInterface $logger,
|
||||
+11
-4
@@ -2,15 +2,22 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
namespace App\Module\Mail\Domain\Entity;
|
||||
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Module\Mail\Infrastructure\Doctrine\DoctrineMailConfigurationRepository;
|
||||
use App\Shared\Domain\Attribute\Auditable;
|
||||
use App\Shared\Domain\Contract\BlamableInterface;
|
||||
use App\Shared\Domain\Contract\TimestampableInterface;
|
||||
use App\Shared\Domain\Trait\TimestampableBlamableTrait;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MailConfigurationRepository::class)]
|
||||
#[Auditable]
|
||||
#[ORM\Entity(repositoryClass: DoctrineMailConfigurationRepository::class)]
|
||||
#[ORM\Table(name: 'mail_configuration')]
|
||||
class MailConfiguration
|
||||
class MailConfiguration implements TimestampableInterface, BlamableInterface
|
||||
{
|
||||
use TimestampableBlamableTrait;
|
||||
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
namespace App\Module\Mail\Domain\Entity;
|
||||
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Module\Mail\Infrastructure\Doctrine\DoctrineMailFolderRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MailFolderRepository::class)]
|
||||
#[ORM\Entity(repositoryClass: DoctrineMailFolderRepository::class)]
|
||||
#[ORM\Table(name: 'mail_folder')]
|
||||
#[ORM\Index(columns: ['parent_path'], name: 'idx_mail_folder_parent_path')]
|
||||
class MailFolder
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
namespace App\Module\Mail\Domain\Entity;
|
||||
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Module\Mail\Infrastructure\Doctrine\DoctrineMailMessageRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: MailMessageRepository::class)]
|
||||
#[ORM\Entity(repositoryClass: DoctrineMailMessageRepository::class)]
|
||||
#[ORM\Table(name: 'mail_message')]
|
||||
#[ORM\UniqueConstraint(name: 'uq_mail_message_folder_uid', columns: ['folder_id', 'uid'])]
|
||||
#[ORM\Index(columns: ['sent_at'], name: 'idx_mail_message_sent_at')]
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
namespace App\Module\Mail\Domain\Entity;
|
||||
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Repository\TaskMailLinkRepository;
|
||||
use App\Module\Mail\Infrastructure\Doctrine\DoctrineTaskMailLinkRepository;
|
||||
use App\Shared\Domain\Contract\TaskInterface;
|
||||
use App\Shared\Domain\Contract\UserInterface;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: TaskMailLinkRepository::class)]
|
||||
#[ORM\Entity(repositoryClass: DoctrineTaskMailLinkRepository::class)]
|
||||
#[ORM\Table(name: 'task_mail_link')]
|
||||
#[ORM\UniqueConstraint(name: 'uq_task_mail_link', columns: ['task_id', 'mail_message_id'])]
|
||||
class TaskMailLink
|
||||
@@ -20,9 +20,9 @@ class TaskMailLink
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: Task::class)]
|
||||
#[ORM\ManyToOne(targetEntity: TaskInterface::class)]
|
||||
#[ORM\JoinColumn(name: 'task_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
private Task $task;
|
||||
private TaskInterface $task;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: MailMessage::class)]
|
||||
#[ORM\JoinColumn(name: 'mail_message_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
|
||||
@@ -40,12 +40,12 @@ class TaskMailLink
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getTask(): Task
|
||||
public function getTask(): TaskInterface
|
||||
{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
public function setTask(Task $task): static
|
||||
public function setTask(TaskInterface $task): static
|
||||
{
|
||||
$this->task = $task;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail\Exception;
|
||||
namespace App\Module\Mail\Domain\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
+5
-5
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail;
|
||||
namespace App\Module\Mail\Domain\Provider;
|
||||
|
||||
use App\Mail\Dto\MailFolderDto;
|
||||
use App\Mail\Dto\MailMessageDetailDto;
|
||||
use App\Mail\Dto\MailMessageHeaderDto;
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Module\Mail\Application\Dto\MailFolderDto;
|
||||
use App\Module\Mail\Application\Dto\MailMessageDetailDto;
|
||||
use App\Module\Mail\Application\Dto\MailMessageHeaderDto;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
|
||||
interface MailProviderInterface
|
||||
{
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Mail\Domain\Repository;
|
||||
|
||||
use App\Module\Mail\Domain\Entity\MailConfiguration;
|
||||
|
||||
interface MailConfigurationRepositoryInterface
|
||||
{
|
||||
public function findSingleton(): ?MailConfiguration;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Mail\Domain\Repository;
|
||||
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
|
||||
interface MailFolderRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return list<MailFolder>
|
||||
*/
|
||||
public function findAllOrderedByPath(): array;
|
||||
|
||||
public function findByPath(string $path): ?MailFolder;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Mail\Domain\Repository;
|
||||
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Entity\MailMessage;
|
||||
|
||||
interface MailMessageRepositoryInterface
|
||||
{
|
||||
public function findById(int $id): ?MailMessage;
|
||||
|
||||
/**
|
||||
* @return list<MailMessage>
|
||||
*/
|
||||
public function findAll(): array;
|
||||
|
||||
public function findByMessageId(string $messageId): ?MailMessage;
|
||||
|
||||
public function findByFolderAndUid(MailFolder $folder, int $uid): ?MailMessage;
|
||||
|
||||
/**
|
||||
* @return list<MailMessage>
|
||||
*/
|
||||
public function findByFolderPaginated(MailFolder $folder, int $limit, int $offset): array;
|
||||
|
||||
public function countUnreadByFolder(MailFolder $folder): int;
|
||||
|
||||
public function findMaxUidInFolder(MailFolder $folder): int;
|
||||
|
||||
/**
|
||||
* @return list<MailMessage>
|
||||
*/
|
||||
public function findLastNByFolder(MailFolder $folder, int $limit): array;
|
||||
|
||||
/**
|
||||
* @return list<int>
|
||||
*/
|
||||
public function findAllUidsByFolder(MailFolder $folder): array;
|
||||
|
||||
/**
|
||||
* Pagination cursor : retourne $limit messages apres le cursor (sentAt DESC, id DESC).
|
||||
* Cursor format : base64url(sentAt_iso8601:id) - null pour la premiere page.
|
||||
*
|
||||
* @return array{messages: list<MailMessage>, nextCursor: ?string}
|
||||
*/
|
||||
public function findByFolderCursor(MailFolder $folder, int $limit, ?string $cursor): array;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Mail\Domain\Repository;
|
||||
|
||||
use App\Module\Mail\Domain\Entity\MailMessage;
|
||||
use App\Module\Mail\Domain\Entity\TaskMailLink;
|
||||
use App\Shared\Domain\Contract\TaskInterface;
|
||||
|
||||
interface TaskMailLinkRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return list<TaskMailLink>
|
||||
*/
|
||||
public function findByTask(TaskInterface $task): array;
|
||||
|
||||
public function findByTaskAndMessage(TaskInterface $task, MailMessage $message): ?TaskMailLink;
|
||||
|
||||
/**
|
||||
* @return list<TaskMailLink>
|
||||
*/
|
||||
public function findByMessage(MailMessage $message): array;
|
||||
}
|
||||
+3
-3
@@ -2,13 +2,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\ApiResource;
|
||||
namespace App\Module\Mail\Infrastructure\ApiPlatform\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use App\State\Mail\MailSettingsProcessor;
|
||||
use App\State\Mail\MailSettingsProvider;
|
||||
use App\Module\Mail\Infrastructure\ApiPlatform\State\MailSettingsProcessor;
|
||||
use App\Module\Mail\Infrastructure\ApiPlatform\State\MailSettingsProvider;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
|
||||
#[ApiResource(
|
||||
+5
-5
@@ -2,13 +2,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\State\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\ApiPlatform\State;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use App\ApiResource\MailSettings;
|
||||
use App\Entity\MailConfiguration;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
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 Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
@@ -16,7 +16,7 @@ final readonly class MailSettingsProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $em,
|
||||
private MailConfigurationRepository $configRepository,
|
||||
private MailConfigurationRepositoryInterface $configRepository,
|
||||
private TokenEncryptor $tokenEncryptor,
|
||||
) {}
|
||||
|
||||
+4
-4
@@ -2,17 +2,17 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\State\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\ApiPlatform\State;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\ApiResource\MailSettings;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\ApiPlatform\Resource\MailSettings;
|
||||
|
||||
final readonly class MailSettingsProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private MailConfigurationRepository $configRepository,
|
||||
private MailConfigurationRepositoryInterface $configRepository,
|
||||
) {}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): MailSettings
|
||||
+4
-4
@@ -2,10 +2,10 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
namespace App\Module\Mail\Infrastructure\Console;
|
||||
|
||||
use App\Mail\MimeHeaderDecoder;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Imap\MimeHeaderDecoder;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
@@ -21,7 +21,7 @@ use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
final class MailRedecodeHeadersCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
) {
|
||||
parent::__construct();
|
||||
+6
-6
@@ -2,11 +2,11 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
namespace App\Module\Mail\Infrastructure\Console;
|
||||
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Service\MailSyncService;
|
||||
use App\Module\Mail\Application\Service\MailSyncService;
|
||||
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@@ -22,8 +22,8 @@ final class MailSyncCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailSyncService $mailSyncService,
|
||||
private readonly MailConfigurationRepository $configRepository,
|
||||
private readonly MailFolderRepository $folderRepository,
|
||||
private readonly MailConfigurationRepositoryInterface $configRepository,
|
||||
private readonly MailFolderRepositoryInterface $folderRepository,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
+7
-7
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
@@ -20,7 +20,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailAttachmentDownloadController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly MailProviderInterface $mailProvider,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
) {}
|
||||
@@ -37,7 +37,7 @@ class MailAttachmentDownloadController extends AbstractController
|
||||
[$messageDbIdStr, $partNumber] = explode(':', $decoded, 2);
|
||||
$messageDbId = (int) $messageDbIdStr;
|
||||
|
||||
$message = $this->messageRepository->find($messageDbId);
|
||||
$message = $this->messageRepository->findById($messageDbId);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
+6
-6
@@ -2,17 +2,17 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Entity\TaskMailLink;
|
||||
use App\Module\Core\Domain\Entity\User;
|
||||
use App\Module\Mail\Domain\Entity\TaskMailLink;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Project;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Module\ProjectManagement\Domain\Entity\TaskGroup;
|
||||
use App\Module\ProjectManagement\Domain\Entity\TaskStatus;
|
||||
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -28,7 +28,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailCreateTaskController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
private readonly TaskRepositoryInterface $taskRepository,
|
||||
@@ -38,7 +38,7 @@ class MailCreateTaskController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
$message = $this->messageRepository->findById($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
+4
-4
@@ -2,10 +2,10 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use DateTimeInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -17,7 +17,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailFoldersListController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailFolderRepository $folderRepository,
|
||||
private readonly MailFolderRepositoryInterface $folderRepository,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
) {}
|
||||
|
||||
+11
-10
@@ -2,13 +2,13 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Entity\TaskMailLink;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Repository\TaskMailLinkRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Entity\TaskMailLink;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\TaskMailLinkRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -24,8 +24,9 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailLinkTaskController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly TaskMailLinkRepository $linkRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly TaskMailLinkRepositoryInterface $linkRepository,
|
||||
private readonly TaskRepositoryInterface $taskRepository,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
) {}
|
||||
@@ -34,7 +35,7 @@ class MailLinkTaskController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
$message = $this->messageRepository->findById($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
@@ -46,7 +47,7 @@ class MailLinkTaskController extends AbstractController
|
||||
throw new UnprocessableEntityHttpException('taskId is required');
|
||||
}
|
||||
|
||||
$task = $this->em->getRepository(Task::class)->find($taskId);
|
||||
$task = $this->taskRepository->findById((int) $taskId);
|
||||
if (null === $task) {
|
||||
throw new NotFoundHttpException('Task not found');
|
||||
}
|
||||
+7
-7
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use DateTimeInterface;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -22,7 +22,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailMessageDetailController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly MailProviderInterface $mailProvider,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
private readonly CacheItemPoolInterface $cache,
|
||||
@@ -32,7 +32,7 @@ class MailMessageDetailController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
$message = $this->messageRepository->findById($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
+7
-7
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -21,7 +21,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailMessageFlagController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly MailProviderInterface $mailProvider,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
@@ -31,7 +31,7 @@ class MailMessageFlagController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
$message = $this->messageRepository->findById($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
+7
-7
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -21,7 +21,7 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailMessageReadController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly MailProviderInterface $mailProvider,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
@@ -31,7 +31,7 @@ class MailMessageReadController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
$message = $this->messageRepository->findById($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
+6
-6
@@ -2,11 +2,11 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use DateTimeInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -20,8 +20,8 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailMessagesListController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailFolderRepository $folderRepository,
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly MailFolderRepositoryInterface $folderRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
) {}
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Message\MailSyncRequested;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Application\Message\MailSyncRequested;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
+10
-9
@@ -2,12 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Repository\TaskMailLinkRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\TaskMailLinkRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
@@ -21,8 +21,9 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class MailUnlinkTaskController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MailMessageRepository $messageRepository,
|
||||
private readonly TaskMailLinkRepository $linkRepository,
|
||||
private readonly MailMessageRepositoryInterface $messageRepository,
|
||||
private readonly TaskMailLinkRepositoryInterface $linkRepository,
|
||||
private readonly TaskRepositoryInterface $taskRepository,
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
) {}
|
||||
@@ -31,12 +32,12 @@ class MailUnlinkTaskController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$message = $this->messageRepository->find($id);
|
||||
$message = $this->messageRepository->findById($id);
|
||||
if (null === $message) {
|
||||
throw new NotFoundHttpException('Message not found');
|
||||
}
|
||||
|
||||
$task = $this->em->getRepository(Task::class)->find($taskId);
|
||||
$task = $this->taskRepository->findById($taskId);
|
||||
if (null === $task) {
|
||||
throw new NotFoundHttpException('Task not found');
|
||||
}
|
||||
+7
-8
@@ -2,13 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Controller;
|
||||
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Repository\TaskMailLinkRepository;
|
||||
use App\Security\MailAccessChecker;
|
||||
use App\Module\Mail\Domain\Repository\TaskMailLinkRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Security\MailAccessChecker;
|
||||
use App\Module\ProjectManagement\Domain\Repository\TaskRepositoryInterface;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@@ -20,8 +19,8 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
class TaskMailsListController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $em,
|
||||
private readonly TaskMailLinkRepository $linkRepository,
|
||||
private readonly TaskRepositoryInterface $taskRepository,
|
||||
private readonly TaskMailLinkRepositoryInterface $linkRepository,
|
||||
private readonly MailAccessChecker $accessChecker,
|
||||
) {}
|
||||
|
||||
@@ -29,7 +28,7 @@ class TaskMailsListController extends AbstractController
|
||||
{
|
||||
$this->accessChecker->ensureCanAccessMail($this->getUser());
|
||||
|
||||
$task = $this->em->getRepository(Task::class)->find($id);
|
||||
$task = $this->taskRepository->findById($id);
|
||||
if (null === $task) {
|
||||
throw new NotFoundHttpException('Task not found');
|
||||
}
|
||||
+7
-3
@@ -2,13 +2,17 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
namespace App\Module\Mail\Infrastructure\Doctrine;
|
||||
|
||||
use App\Entity\MailConfiguration;
|
||||
use App\Module\Mail\Domain\Entity\MailConfiguration;
|
||||
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
class MailConfigurationRepository extends ServiceEntityRepository
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MailConfiguration>
|
||||
*/
|
||||
class DoctrineMailConfigurationRepository extends ServiceEntityRepository implements MailConfigurationRepositoryInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
+7
-3
@@ -2,13 +2,17 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
namespace App\Module\Mail\Infrastructure\Doctrine;
|
||||
|
||||
use App\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
class MailFolderRepository extends ServiceEntityRepository
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MailFolder>
|
||||
*/
|
||||
class DoctrineMailFolderRepository extends ServiceEntityRepository implements MailFolderRepositoryInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
+13
-4
@@ -2,22 +2,31 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
namespace App\Module\Mail\Infrastructure\Doctrine;
|
||||
|
||||
use App\Entity\MailFolder;
|
||||
use App\Entity\MailMessage;
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Entity\MailMessage;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
class MailMessageRepository extends ServiceEntityRepository
|
||||
/**
|
||||
* @extends ServiceEntityRepository<MailMessage>
|
||||
*/
|
||||
class DoctrineMailMessageRepository extends ServiceEntityRepository implements MailMessageRepositoryInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, MailMessage::class);
|
||||
}
|
||||
|
||||
public function findById(int $id): ?MailMessage
|
||||
{
|
||||
return $this->find($id);
|
||||
}
|
||||
|
||||
public function findByMessageId(string $messageId): ?MailMessage
|
||||
{
|
||||
return $this->findOneBy(['messageId' => $messageId]);
|
||||
+11
-7
@@ -2,15 +2,19 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository;
|
||||
namespace App\Module\Mail\Infrastructure\Doctrine;
|
||||
|
||||
use App\Entity\MailMessage;
|
||||
use App\Entity\TaskMailLink;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use App\Module\Mail\Domain\Entity\MailMessage;
|
||||
use App\Module\Mail\Domain\Entity\TaskMailLink;
|
||||
use App\Module\Mail\Domain\Repository\TaskMailLinkRepositoryInterface;
|
||||
use App\Shared\Domain\Contract\TaskInterface;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
class TaskMailLinkRepository extends ServiceEntityRepository
|
||||
/**
|
||||
* @extends ServiceEntityRepository<TaskMailLink>
|
||||
*/
|
||||
class DoctrineTaskMailLinkRepository extends ServiceEntityRepository implements TaskMailLinkRepositoryInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
@@ -20,7 +24,7 @@ class TaskMailLinkRepository extends ServiceEntityRepository
|
||||
/**
|
||||
* @return list<TaskMailLink>
|
||||
*/
|
||||
public function findByTask(Task $task): array
|
||||
public function findByTask(TaskInterface $task): array
|
||||
{
|
||||
return $this->createQueryBuilder('l')
|
||||
->andWhere('l.task = :task')
|
||||
@@ -31,7 +35,7 @@ class TaskMailLinkRepository extends ServiceEntityRepository
|
||||
;
|
||||
}
|
||||
|
||||
public function findByTaskAndMessage(Task $task, MailMessage $message): ?TaskMailLink
|
||||
public function findByTaskAndMessage(TaskInterface $task, MailMessage $message): ?TaskMailLink
|
||||
{
|
||||
return $this->findOneBy(['task' => $task, 'mailMessage' => $message]);
|
||||
}
|
||||
+9
-8
@@ -2,14 +2,15 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Imap;
|
||||
|
||||
use App\Mail\Dto\MailAttachmentDto;
|
||||
use App\Mail\Dto\MailFolderDto;
|
||||
use App\Mail\Dto\MailMessageDetailDto;
|
||||
use App\Mail\Dto\MailMessageHeaderDto;
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Module\Mail\Application\Dto\MailAttachmentDto;
|
||||
use App\Module\Mail\Application\Dto\MailFolderDto;
|
||||
use App\Module\Mail\Application\Dto\MailMessageDetailDto;
|
||||
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 DateTimeImmutable;
|
||||
use Psr\Log\LoggerInterface;
|
||||
@@ -24,7 +25,7 @@ final class ImapMailProvider implements MailProviderInterface
|
||||
private ?Client $client = null;
|
||||
|
||||
public function __construct(
|
||||
private readonly MailConfigurationRepository $configRepository,
|
||||
private readonly MailConfigurationRepositoryInterface $configRepository,
|
||||
private readonly TokenEncryptor $tokenEncryptor,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Mail;
|
||||
namespace App\Module\Mail\Infrastructure\Imap;
|
||||
|
||||
use const ICONV_MIME_DECODE_CONTINUE_ON_ERROR;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Security;
|
||||
namespace App\Module\Mail\Infrastructure\Security;
|
||||
|
||||
use App\Shared\Domain\Contract\UserInterface as SharedUserInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Module\Mail;
|
||||
|
||||
use App\Shared\Domain\Module\ModuleInterface;
|
||||
|
||||
final class MailModule implements ModuleInterface
|
||||
{
|
||||
public static function id(): string
|
||||
{
|
||||
return 'mail';
|
||||
}
|
||||
|
||||
public static function label(): string
|
||||
{
|
||||
return 'Messagerie';
|
||||
}
|
||||
|
||||
public static function isRequired(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permissions RBAC fin du Module Mail.
|
||||
*
|
||||
* Additif : alimente le catalogue RBAC. La sécurité des opérations API
|
||||
* reste en ROLE_USER/ROLE_ADMIN (non recâblée ici).
|
||||
*
|
||||
* @return list<array{code: string, label: string}>
|
||||
*/
|
||||
public static function permissions(): array
|
||||
{
|
||||
return [
|
||||
['code' => 'mail.access', 'label' => 'Accéder à la messagerie'],
|
||||
['code' => 'mail.configure', 'label' => 'Configurer la messagerie'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Mail;
|
||||
|
||||
use App\Entity\MailFolder;
|
||||
use App\Entity\MailMessage;
|
||||
use App\Module\Core\Domain\Entity\User;
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Entity\MailMessage;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Project;
|
||||
use App\Module\ProjectManagement\Domain\Entity\Task;
|
||||
use DateTimeImmutable;
|
||||
|
||||
@@ -4,10 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Mail;
|
||||
|
||||
use App\Entity\MailConfiguration;
|
||||
use App\Mail\Exception\MailProviderException;
|
||||
use App\Mail\ImapMailProvider;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Module\Mail\Domain\Entity\MailConfiguration;
|
||||
use App\Module\Mail\Domain\Exception\MailProviderException;
|
||||
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
|
||||
use App\Module\Mail\Infrastructure\Imap\ImapMailProvider;
|
||||
use App\Service\TokenEncryptor;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\NullLogger;
|
||||
@@ -22,7 +22,7 @@ class ImapMailProviderTest extends TestCase
|
||||
$config = new MailConfiguration();
|
||||
$config->setEnabled(false);
|
||||
|
||||
$repo = $this->createMock(MailConfigurationRepository::class);
|
||||
$repo = $this->createMock(MailConfigurationRepositoryInterface::class);
|
||||
$repo->method('findSingleton')->willReturn($config);
|
||||
|
||||
$provider = new ImapMailProvider($repo, $this->makeEncryptor(), new NullLogger());
|
||||
@@ -33,7 +33,7 @@ class ImapMailProviderTest extends TestCase
|
||||
|
||||
public function testThrowsWhenConfigMissing(): void
|
||||
{
|
||||
$repo = $this->createMock(MailConfigurationRepository::class);
|
||||
$repo = $this->createMock(MailConfigurationRepositoryInterface::class);
|
||||
$repo->method('findSingleton')->willReturn(null);
|
||||
|
||||
$provider = new ImapMailProvider($repo, $this->makeEncryptor(), new NullLogger());
|
||||
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Mail;
|
||||
|
||||
use App\Mail\Dto\MailSyncReport;
|
||||
use App\Module\Mail\Application\Dto\MailSyncReport;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Mail;
|
||||
|
||||
use App\Mail\MimeHeaderDecoder;
|
||||
use App\Module\Mail\Infrastructure\Imap\MimeHeaderDecoder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Repository;
|
||||
|
||||
use App\Entity\MailConfiguration;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Module\Mail\Domain\Entity\MailConfiguration;
|
||||
use App\Module\Mail\Infrastructure\Doctrine\DoctrineMailConfigurationRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
@@ -14,14 +14,14 @@ use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
*/
|
||||
class MailConfigurationRepositoryTest extends KernelTestCase
|
||||
{
|
||||
private MailConfigurationRepository $repository;
|
||||
private DoctrineMailConfigurationRepository $repository;
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$container = static::getContainer();
|
||||
$this->repository = $container->get(MailConfigurationRepository::class);
|
||||
$this->repository = $container->get(DoctrineMailConfigurationRepository::class);
|
||||
$this->em = $container->get('doctrine.orm.entity_manager');
|
||||
$this->em->getConnection()->executeStatement('TRUNCATE TABLE mail_configuration RESTART IDENTITY CASCADE');
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Service;
|
||||
|
||||
use App\Entity\MailConfiguration;
|
||||
use App\Entity\MailFolder;
|
||||
use App\Mail\Dto\MailFolderDto;
|
||||
use App\Mail\MailProviderInterface;
|
||||
use App\Repository\MailConfigurationRepository;
|
||||
use App\Repository\MailFolderRepository;
|
||||
use App\Repository\MailMessageRepository;
|
||||
use App\Service\MailSyncService;
|
||||
use App\Module\Mail\Application\Dto\MailFolderDto;
|
||||
use App\Module\Mail\Application\Service\MailSyncService;
|
||||
use App\Module\Mail\Domain\Entity\MailConfiguration;
|
||||
use App\Module\Mail\Domain\Entity\MailFolder;
|
||||
use App\Module\Mail\Domain\Provider\MailProviderInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailConfigurationRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailFolderRepositoryInterface;
|
||||
use App\Module\Mail\Domain\Repository\MailMessageRepositoryInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -29,12 +29,12 @@ class MailSyncServiceTest extends TestCase
|
||||
$config = new MailConfiguration();
|
||||
$config->setEnabled(false);
|
||||
|
||||
$configRepo = $this->createMock(MailConfigurationRepository::class);
|
||||
$configRepo = $this->createMock(MailConfigurationRepositoryInterface::class);
|
||||
$configRepo->method('findSingleton')->willReturn($config);
|
||||
|
||||
$provider = $this->createMock(MailProviderInterface::class);
|
||||
$folderRepo = $this->createMock(MailFolderRepository::class);
|
||||
$messageRepo = $this->createMock(MailMessageRepository::class);
|
||||
$folderRepo = $this->createMock(MailFolderRepositoryInterface::class);
|
||||
$messageRepo = $this->createMock(MailMessageRepositoryInterface::class);
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$lockFactory = $this->makeLockFactory();
|
||||
|
||||
@@ -62,12 +62,12 @@ class MailSyncServiceTest extends TestCase
|
||||
$config = new MailConfiguration();
|
||||
$config->setEnabled(true);
|
||||
|
||||
$configRepo = $this->createMock(MailConfigurationRepository::class);
|
||||
$configRepo = $this->createMock(MailConfigurationRepositoryInterface::class);
|
||||
$configRepo->method('findSingleton')->willReturn($config);
|
||||
|
||||
$provider = $this->createMock(MailProviderInterface::class);
|
||||
$folderRepo = $this->createMock(MailFolderRepository::class);
|
||||
$messageRepo = $this->createMock(MailMessageRepository::class);
|
||||
$folderRepo = $this->createMock(MailFolderRepositoryInterface::class);
|
||||
$messageRepo = $this->createMock(MailMessageRepositoryInterface::class);
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$lockFactory = $this->makeLockFactory(false);
|
||||
|
||||
@@ -93,7 +93,7 @@ class MailSyncServiceTest extends TestCase
|
||||
$config = new MailConfiguration();
|
||||
$config->setEnabled(true);
|
||||
|
||||
$configRepo = $this->createMock(MailConfigurationRepository::class);
|
||||
$configRepo = $this->createMock(MailConfigurationRepositoryInterface::class);
|
||||
$configRepo->method('findSingleton')->willReturn($config);
|
||||
|
||||
$folderDto = new MailFolderDto(
|
||||
@@ -107,11 +107,11 @@ class MailSyncServiceTest extends TestCase
|
||||
$provider = $this->createMock(MailProviderInterface::class);
|
||||
$provider->method('listFolders')->willReturn([$folderDto]);
|
||||
|
||||
$folderRepo = $this->createMock(MailFolderRepository::class);
|
||||
$folderRepo = $this->createMock(MailFolderRepositoryInterface::class);
|
||||
$folderRepo->method('findByPath')->willReturn(null);
|
||||
$folderRepo->method('findAllOrderedByPath')->willReturn([]);
|
||||
|
||||
$messageRepo = $this->createMock(MailMessageRepository::class);
|
||||
$messageRepo = $this->createMock(MailMessageRepositoryInterface::class);
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$em->expects(self::once())->method('persist');
|
||||
$em->expects(self::once())->method('flush');
|
||||
@@ -137,13 +137,13 @@ class MailSyncServiceTest extends TestCase
|
||||
$config = new MailConfiguration();
|
||||
$config->setEnabled(true);
|
||||
|
||||
$configRepo = $this->createMock(MailConfigurationRepository::class);
|
||||
$configRepo = $this->createMock(MailConfigurationRepositoryInterface::class);
|
||||
$configRepo->method('findSingleton')->willReturn($config);
|
||||
|
||||
$folder = new MailFolder();
|
||||
$folder->setPath('INBOX');
|
||||
|
||||
$messageRepo = $this->createMock(MailMessageRepository::class);
|
||||
$messageRepo = $this->createMock(MailMessageRepositoryInterface::class);
|
||||
$messageRepo->method('findMaxUidInFolder')->willReturn(10);
|
||||
$messageRepo->method('findAllUidsByFolder')->willReturn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
$messageRepo->method('findLastNByFolder')->willReturn([]);
|
||||
@@ -151,7 +151,7 @@ class MailSyncServiceTest extends TestCase
|
||||
$provider = $this->createMock(MailProviderInterface::class);
|
||||
$provider->method('listMessages')->willReturn([]);
|
||||
|
||||
$folderRepo = $this->createMock(MailFolderRepository::class);
|
||||
$folderRepo = $this->createMock(MailFolderRepositoryInterface::class);
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$em->expects(self::never())->method('remove');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user