Client.id/name and Project.id/name were missing the user:list group, causing them to be serialized as IRI strings instead of embedded objects. This broke the user edit form which expected object properties. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
237 lines
6.0 KiB
PHP
237 lines
6.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Entity;
|
|
|
|
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
|
|
use ApiPlatform\Metadata\ApiFilter;
|
|
use ApiPlatform\Metadata\ApiResource;
|
|
use ApiPlatform\Metadata\Delete;
|
|
use ApiPlatform\Metadata\Get;
|
|
use ApiPlatform\Metadata\GetCollection;
|
|
use ApiPlatform\Metadata\Patch;
|
|
use ApiPlatform\Metadata\Post;
|
|
use App\Repository\ProjectRepository;
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
use Doctrine\Common\Collections\Collection;
|
|
use Doctrine\ORM\Mapping as ORM;
|
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|
use Symfony\Component\Serializer\Attribute\Groups;
|
|
use Symfony\Component\Validator\Constraints as Assert;
|
|
|
|
#[ApiResource(
|
|
operations: [
|
|
new GetCollection(security: "is_granted('ROLE_USER') or is_granted('ROLE_CLIENT')"),
|
|
new Get(security: "is_granted('ROLE_USER') or is_granted('ROLE_CLIENT')"),
|
|
new Post(
|
|
security: "is_granted('ROLE_ADMIN')",
|
|
denormalizationContext: ['groups' => ['project:write', 'project:create']],
|
|
),
|
|
new Patch(security: "is_granted('ROLE_ADMIN')"),
|
|
new Delete(security: "is_granted('ROLE_ADMIN')"),
|
|
],
|
|
normalizationContext: ['groups' => ['project:read']],
|
|
denormalizationContext: ['groups' => ['project:write']],
|
|
order: ['name' => 'ASC'],
|
|
)]
|
|
#[ApiFilter(BooleanFilter::class, properties: ['archived'])]
|
|
#[ORM\Entity(repositoryClass: ProjectRepository::class)]
|
|
#[UniqueEntity(fields: ['code'], message: 'Ce code de projet est déjà utilisé.')]
|
|
class Project
|
|
{
|
|
#[ORM\Id]
|
|
#[ORM\GeneratedValue]
|
|
#[ORM\Column]
|
|
#[Groups(['project:read', 'time_entry:read', 'task:read', 'me:read', 'user:list'])]
|
|
private ?int $id = null;
|
|
|
|
#[ORM\Column(length: 10, unique: true)]
|
|
#[Groups(['project:read', 'project:create', 'task:read'])]
|
|
#[Assert\NotBlank]
|
|
#[Assert\Regex(pattern: '/^[A-Z]{2,10}$/', message: 'Le code doit contenir entre 2 et 10 lettres majuscules.')]
|
|
private ?string $code = null;
|
|
|
|
#[ORM\Column(length: 255)]
|
|
#[Groups(['project:read', 'project:write', 'time_entry:read', 'task:read', 'me:read', 'user:list'])]
|
|
private ?string $name = null;
|
|
|
|
#[ORM\Column(type: 'text', nullable: true)]
|
|
#[Groups(['project:read', 'project:write'])]
|
|
private ?string $description = null;
|
|
|
|
#[ORM\Column(length: 7)]
|
|
#[Groups(['project:read', 'project:write', 'time_entry:read', 'task:read'])]
|
|
private ?string $color = '#222783';
|
|
|
|
#[ORM\ManyToOne(targetEntity: Client::class, inversedBy: 'projects')]
|
|
#[ORM\JoinColumn(nullable: true, onDelete: 'SET NULL')]
|
|
#[Groups(['project:read', 'project:write'])]
|
|
private ?Client $client = null;
|
|
|
|
#[ORM\Column(length: 255, nullable: true)]
|
|
#[Groups(['project:read', 'project:write', 'task:read'])]
|
|
private ?string $giteaOwner = null;
|
|
|
|
#[ORM\Column(length: 255, nullable: true)]
|
|
#[Groups(['project:read', 'project:write', 'task:read'])]
|
|
private ?string $giteaRepo = null;
|
|
|
|
#[ORM\Column(nullable: true)]
|
|
#[Groups(['project:read', 'project:write', 'task:read'])]
|
|
private ?int $bookstackShelfId = null;
|
|
|
|
#[ORM\Column(length: 255, nullable: true)]
|
|
#[Groups(['project:read', 'project:write'])]
|
|
private ?string $bookstackShelfName = null;
|
|
|
|
#[ORM\Column]
|
|
#[Groups(['project:read', 'project:write'])]
|
|
private bool $archived = false;
|
|
|
|
/** @var Collection<int, Task> */
|
|
#[ORM\OneToMany(targetEntity: Task::class, mappedBy: 'project')]
|
|
private Collection $tasks;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->tasks = new ArrayCollection();
|
|
}
|
|
|
|
public function getId(): ?int
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
public function getCode(): ?string
|
|
{
|
|
return $this->code;
|
|
}
|
|
|
|
public function setCode(string $code): static
|
|
{
|
|
$this->code = $code;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getName(): ?string
|
|
{
|
|
return $this->name;
|
|
}
|
|
|
|
public function setName(string $name): static
|
|
{
|
|
$this->name = $name;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getDescription(): ?string
|
|
{
|
|
return $this->description;
|
|
}
|
|
|
|
public function setDescription(?string $description): static
|
|
{
|
|
$this->description = $description;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getColor(): ?string
|
|
{
|
|
return $this->color;
|
|
}
|
|
|
|
public function setColor(string $color): static
|
|
{
|
|
$this->color = $color;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getClient(): ?Client
|
|
{
|
|
return $this->client;
|
|
}
|
|
|
|
public function setClient(?Client $client): static
|
|
{
|
|
$this->client = $client;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getGiteaOwner(): ?string
|
|
{
|
|
return $this->giteaOwner;
|
|
}
|
|
|
|
public function setGiteaOwner(?string $giteaOwner): static
|
|
{
|
|
$this->giteaOwner = $giteaOwner;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getGiteaRepo(): ?string
|
|
{
|
|
return $this->giteaRepo;
|
|
}
|
|
|
|
public function setGiteaRepo(?string $giteaRepo): static
|
|
{
|
|
$this->giteaRepo = $giteaRepo;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function hasGiteaRepo(): bool
|
|
{
|
|
return null !== $this->giteaOwner && null !== $this->giteaRepo;
|
|
}
|
|
|
|
public function isArchived(): bool
|
|
{
|
|
return $this->archived;
|
|
}
|
|
|
|
public function setArchived(bool $archived): static
|
|
{
|
|
$this->archived = $archived;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getBookstackShelfId(): ?int
|
|
{
|
|
return $this->bookstackShelfId;
|
|
}
|
|
|
|
public function setBookstackShelfId(?int $bookstackShelfId): static
|
|
{
|
|
$this->bookstackShelfId = $bookstackShelfId;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getBookstackShelfName(): ?string
|
|
{
|
|
return $this->bookstackShelfName;
|
|
}
|
|
|
|
public function setBookstackShelfName(?string $bookstackShelfName): static
|
|
{
|
|
$this->bookstackShelfName = $bookstackShelfName;
|
|
|
|
return $this;
|
|
}
|
|
|
|
#[Groups(['project:read'])]
|
|
public function getTaskCount(): int
|
|
{
|
|
return $this->tasks->count();
|
|
}
|
|
}
|