fix(mcp) : list-projects crash sur client orphelin (FK danglante)
Serializer::project() forçait l'hydratation d'un proxy Doctrine Client via getId()/getName() même quand la FK pointait vers un Client supprimé, ce qui levait EntityNotFoundException et faisait planter tout l'outil (-32603). Extraction d'un helper clientRef() qui catch EntityNotFoundException et renvoie null (sémantique ON DELETE SET NULL). Robustifie aussi get-project, create-project, update-project qui réutilisent ce serializer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,11 +23,13 @@ use App\Module\ProjectManagement\Domain\Entity\TaskPriority;
|
||||
use App\Module\ProjectManagement\Domain\Entity\TaskStatus;
|
||||
use App\Module\ProjectManagement\Domain\Entity\TaskTag;
|
||||
use App\Module\TimeTracking\Domain\Entity\TimeEntry;
|
||||
use App\Shared\Domain\Contract\ClientInterface;
|
||||
use App\Shared\Domain\Contract\ProjectInterface;
|
||||
use App\Shared\Domain\Contract\TaskInterface;
|
||||
use App\Shared\Domain\Contract\TaskTagInterface;
|
||||
use App\Shared\Domain\Contract\UserInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\EntityNotFoundException;
|
||||
|
||||
/**
|
||||
* Shared serialization helpers for MCP tools.
|
||||
@@ -59,11 +61,8 @@ final class Serializer
|
||||
'name' => $project->getName(),
|
||||
'description' => $project->getDescription(),
|
||||
'color' => $project->getColor(),
|
||||
'client' => $project->getClient() ? [
|
||||
'id' => $project->getClient()->getId(),
|
||||
'name' => $project->getClient()->getName(),
|
||||
] : null,
|
||||
'archived' => $project->isArchived(),
|
||||
'client' => self::clientRef($project->getClient()),
|
||||
'archived' => $project->isArchived(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -516,4 +515,31 @@ final class Serializer
|
||||
'initialLeaveBalance' => $u->getInitialLeaveBalance(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely serialize a project's client reference.
|
||||
*
|
||||
* The client association uses ON DELETE SET NULL, but a stale row may leave
|
||||
* a dangling foreign key (e.g. data imported with the constraint disabled).
|
||||
* In that case Doctrine returns an uninitialized proxy whose hydration
|
||||
* throws EntityNotFoundException; we treat such a reference as absent rather
|
||||
* than letting it crash the whole tool.
|
||||
*
|
||||
* @return null|array{id: ?int, name: ?string}
|
||||
*/
|
||||
private static function clientRef(?ClientInterface $client): ?array
|
||||
{
|
||||
if (null === $client) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return [
|
||||
'id' => $client->getId(),
|
||||
'name' => $client->getName(),
|
||||
];
|
||||
} catch (EntityNotFoundException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user