Added endpoints for attachments

This commit is contained in:
Jan Böhmer 2023-09-18 21:57:17 +02:00
parent 8182e83846
commit 077beb37b1
2 changed files with 38 additions and 2 deletions

View file

@ -22,7 +22,13 @@ declare(strict_types=1);
namespace App\Entity\Attachments;
use App\Entity\Parts\PartTraits\ProjectTrait;
use ApiPlatform\Metadata\ApiProperty;
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\AttachmentRepository;
use App\EntityListeners\AttachmentDeleteListener;
use Doctrine\DBAL\Types\Types;
@ -30,6 +36,7 @@ use App\Entity\Base\AbstractNamedDBElement;
use App\Validator\Constraints\Selectable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Validator\Constraints as Assert;
use function in_array;
use InvalidArgumentException;
@ -55,6 +62,18 @@ use LogicException;
#[ORM\Index(name: 'attachments_idx_class_name_id', columns: ['class_name', 'id'])]
#[ORM\Index(name: 'attachment_name_idx', columns: ['name'])]
#[ORM\Index(name: 'attachment_element_idx', columns: ['class_name', 'element_id'])]
#[ApiResource(
operations: [
new Get(security: 'is_granted("read", object)'),
new GetCollection(security: 'is_granted("@attachments.list_attachments")'),
new Post(securityPostDenormalize: 'is_granted("create", object)'),
new Patch(security: 'is_granted("edit", object)'),
new Delete(security: 'is_granted("delete", object)'),
],
normalizationContext: ['groups' => ['attachment:read', 'attachment:read:standalone', 'api:basic:read'], 'openapi_definition_name' => 'Read'],
denormalizationContext: ['groups' => ['attachment:write', 'api:basic:write'], 'openapi_definition_name' => 'Write'],
)]
abstract class Attachment extends AbstractNamedDBElement
{
/**
@ -102,22 +121,25 @@ abstract class Attachment extends AbstractNamedDBElement
* @var string the name of this element
*/
#[Assert\NotBlank(message: 'validator.attachment.name_not_blank')]
#[Groups(['simple', 'extended', 'full'])]
#[Groups(['simple', 'extended', 'full', 'attachment:read', 'attachment:write'])]
protected string $name = '';
/**
* ORM mapping is done in subclasses (like PartAttachment).
* @phpstan-param T|null $element
*/
#[Groups(['attachment:read:standalone', 'attachment:read'])]
protected ?AttachmentContainingDBElement $element = null;
#[ORM\Column(type: Types::BOOLEAN)]
#[Groups(['attachment:read', 'attachment_write'])]
protected bool $show_in_table = false;
#[Assert\NotNull(message: 'validator.attachment.must_not_be_null')]
#[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'attachments_with_type')]
#[ORM\JoinColumn(name: 'type_id', nullable: false)]
#[Selectable()]
#[Groups(['attachment:read', 'attachment_write'])]
protected ?AttachmentType $attachment_type = null;
public function __construct()
@ -147,6 +169,7 @@ abstract class Attachment extends AbstractNamedDBElement
* @return bool * true if the file extension is a picture extension
* * otherwise false
*/
#[Groups(['attachment:read'])]
public function isPicture(): bool
{
if ($this->isExternal()) {
@ -171,6 +194,8 @@ abstract class Attachment extends AbstractNamedDBElement
* Check if this attachment is a 3D model and therefore can be directly shown to user.
* If the attachment is external, false is returned (3D Models must be internal).
*/
#[Groups(['attachment:read'])]
#[SerializedName('3d_model')]
public function is3DModel(): bool
{
//We just assume that 3D Models are internally saved, otherwise we get problems loading them.
@ -188,6 +213,7 @@ abstract class Attachment extends AbstractNamedDBElement
*
* @return bool true, if the file is saved externally
*/
#[Groups(['attachment:read'])]
public function isExternal(): bool
{
//When path is empty, this attachment can not be external
@ -207,6 +233,8 @@ abstract class Attachment extends AbstractNamedDBElement
*
* @return bool true, if the file is secure
*/
#[Groups(['attachment:read'])]
#[SerializedName('private')]
public function isSecure(): bool
{
//After the %PLACEHOLDER% comes a slash, so we can check if we have a placeholder via explode
@ -221,6 +249,7 @@ abstract class Attachment extends AbstractNamedDBElement
*
* @return bool true if the attachment is using a builtin file
*/
#[Groups(['attachment:read'])]
public function isBuiltIn(): bool
{
return static::checkIfBuiltin($this->path);
@ -267,6 +296,8 @@ abstract class Attachment extends AbstractNamedDBElement
* The URL to the external file, or the path to the built-in file.
* Returns null, if the file is not external (and not builtin).
*/
#[Groups(['attachment:read'])]
#[SerializedName('url')]
public function getURL(): ?string
{
if (!$this->isExternal() && !$this->isBuiltIn()) {
@ -417,6 +448,8 @@ abstract class Attachment extends AbstractNamedDBElement
*
* @return Attachment
*/
#[Groups(['attachment:write'])]
#[SerializedName('url')]
public function setURL(?string $url): self
{
//Only set if the URL is not empty

View file

@ -42,6 +42,7 @@ use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\SerializedName;
use Symfony\Component\Validator\Constraints as Assert;
/**
@ -189,6 +190,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
* @return BigDecimal the price as a bcmath string
*/
#[Groups(['pricedetail:read'])]
#[SerializedName('price_per_unit')]
public function getPricePerUnit(float|string|BigDecimal $multiplier = 1.0): BigDecimal
{
$tmp = BigDecimal::of($multiplier);
@ -256,6 +258,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
* @return string|null
*/
#[Groups(['pricedetail:read'])]
#[SerializedName('currency_iso_code')]
public function getCurrencyISOCode(): ?string
{
return $this->currency?->getIsoCode();