mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-07-04 07:24:34 +02:00
Added endpoints for attachments
This commit is contained in:
parent
8182e83846
commit
077beb37b1
2 changed files with 38 additions and 2 deletions
|
@ -22,7 +22,13 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Entity\Attachments;
|
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\Repository\AttachmentRepository;
|
||||||
use App\EntityListeners\AttachmentDeleteListener;
|
use App\EntityListeners\AttachmentDeleteListener;
|
||||||
use Doctrine\DBAL\Types\Types;
|
use Doctrine\DBAL\Types\Types;
|
||||||
|
@ -30,6 +36,7 @@ use App\Entity\Base\AbstractNamedDBElement;
|
||||||
use App\Validator\Constraints\Selectable;
|
use App\Validator\Constraints\Selectable;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Serializer\Annotation\Groups;
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
use Symfony\Component\Serializer\Annotation\SerializedName;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
use function in_array;
|
use function in_array;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
@ -55,6 +62,18 @@ use LogicException;
|
||||||
#[ORM\Index(name: 'attachments_idx_class_name_id', columns: ['class_name', 'id'])]
|
#[ORM\Index(name: 'attachments_idx_class_name_id', columns: ['class_name', 'id'])]
|
||||||
#[ORM\Index(name: 'attachment_name_idx', columns: ['name'])]
|
#[ORM\Index(name: 'attachment_name_idx', columns: ['name'])]
|
||||||
#[ORM\Index(name: 'attachment_element_idx', columns: ['class_name', 'element_id'])]
|
#[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
|
abstract class Attachment extends AbstractNamedDBElement
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -102,22 +121,25 @@ abstract class Attachment extends AbstractNamedDBElement
|
||||||
* @var string the name of this element
|
* @var string the name of this element
|
||||||
*/
|
*/
|
||||||
#[Assert\NotBlank(message: 'validator.attachment.name_not_blank')]
|
#[Assert\NotBlank(message: 'validator.attachment.name_not_blank')]
|
||||||
#[Groups(['simple', 'extended', 'full'])]
|
#[Groups(['simple', 'extended', 'full', 'attachment:read', 'attachment:write'])]
|
||||||
protected string $name = '';
|
protected string $name = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ORM mapping is done in subclasses (like PartAttachment).
|
* ORM mapping is done in subclasses (like PartAttachment).
|
||||||
* @phpstan-param T|null $element
|
* @phpstan-param T|null $element
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read:standalone', 'attachment:read'])]
|
||||||
protected ?AttachmentContainingDBElement $element = null;
|
protected ?AttachmentContainingDBElement $element = null;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::BOOLEAN)]
|
#[ORM\Column(type: Types::BOOLEAN)]
|
||||||
|
#[Groups(['attachment:read', 'attachment_write'])]
|
||||||
protected bool $show_in_table = false;
|
protected bool $show_in_table = false;
|
||||||
|
|
||||||
#[Assert\NotNull(message: 'validator.attachment.must_not_be_null')]
|
#[Assert\NotNull(message: 'validator.attachment.must_not_be_null')]
|
||||||
#[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'attachments_with_type')]
|
#[ORM\ManyToOne(targetEntity: AttachmentType::class, inversedBy: 'attachments_with_type')]
|
||||||
#[ORM\JoinColumn(name: 'type_id', nullable: false)]
|
#[ORM\JoinColumn(name: 'type_id', nullable: false)]
|
||||||
#[Selectable()]
|
#[Selectable()]
|
||||||
|
#[Groups(['attachment:read', 'attachment_write'])]
|
||||||
protected ?AttachmentType $attachment_type = null;
|
protected ?AttachmentType $attachment_type = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
@ -147,6 +169,7 @@ abstract class Attachment extends AbstractNamedDBElement
|
||||||
* @return bool * true if the file extension is a picture extension
|
* @return bool * true if the file extension is a picture extension
|
||||||
* * otherwise false
|
* * otherwise false
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read'])]
|
||||||
public function isPicture(): bool
|
public function isPicture(): bool
|
||||||
{
|
{
|
||||||
if ($this->isExternal()) {
|
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.
|
* 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).
|
* If the attachment is external, false is returned (3D Models must be internal).
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read'])]
|
||||||
|
#[SerializedName('3d_model')]
|
||||||
public function is3DModel(): bool
|
public function is3DModel(): bool
|
||||||
{
|
{
|
||||||
//We just assume that 3D Models are internally saved, otherwise we get problems loading them.
|
//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
|
* @return bool true, if the file is saved externally
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read'])]
|
||||||
public function isExternal(): bool
|
public function isExternal(): bool
|
||||||
{
|
{
|
||||||
//When path is empty, this attachment can not be external
|
//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
|
* @return bool true, if the file is secure
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read'])]
|
||||||
|
#[SerializedName('private')]
|
||||||
public function isSecure(): bool
|
public function isSecure(): bool
|
||||||
{
|
{
|
||||||
//After the %PLACEHOLDER% comes a slash, so we can check if we have a placeholder via explode
|
//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
|
* @return bool true if the attachment is using a builtin file
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read'])]
|
||||||
public function isBuiltIn(): bool
|
public function isBuiltIn(): bool
|
||||||
{
|
{
|
||||||
return static::checkIfBuiltin($this->path);
|
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.
|
* 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).
|
* Returns null, if the file is not external (and not builtin).
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:read'])]
|
||||||
|
#[SerializedName('url')]
|
||||||
public function getURL(): ?string
|
public function getURL(): ?string
|
||||||
{
|
{
|
||||||
if (!$this->isExternal() && !$this->isBuiltIn()) {
|
if (!$this->isExternal() && !$this->isBuiltIn()) {
|
||||||
|
@ -417,6 +448,8 @@ abstract class Attachment extends AbstractNamedDBElement
|
||||||
*
|
*
|
||||||
* @return Attachment
|
* @return Attachment
|
||||||
*/
|
*/
|
||||||
|
#[Groups(['attachment:write'])]
|
||||||
|
#[SerializedName('url')]
|
||||||
public function setURL(?string $url): self
|
public function setURL(?string $url): self
|
||||||
{
|
{
|
||||||
//Only set if the URL is not empty
|
//Only set if the URL is not empty
|
||||||
|
|
|
@ -42,6 +42,7 @@ use DateTime;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
||||||
use Symfony\Component\Serializer\Annotation\Groups;
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
use Symfony\Component\Serializer\Annotation\SerializedName;
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
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
|
* @return BigDecimal the price as a bcmath string
|
||||||
*/
|
*/
|
||||||
#[Groups(['pricedetail:read'])]
|
#[Groups(['pricedetail:read'])]
|
||||||
|
#[SerializedName('price_per_unit')]
|
||||||
public function getPricePerUnit(float|string|BigDecimal $multiplier = 1.0): BigDecimal
|
public function getPricePerUnit(float|string|BigDecimal $multiplier = 1.0): BigDecimal
|
||||||
{
|
{
|
||||||
$tmp = BigDecimal::of($multiplier);
|
$tmp = BigDecimal::of($multiplier);
|
||||||
|
@ -256,6 +258,7 @@ class Pricedetail extends AbstractDBElement implements TimeStampableInterface
|
||||||
* @return string|null
|
* @return string|null
|
||||||
*/
|
*/
|
||||||
#[Groups(['pricedetail:read'])]
|
#[Groups(['pricedetail:read'])]
|
||||||
|
#[SerializedName('currency_iso_code')]
|
||||||
public function getCurrencyISOCode(): ?string
|
public function getCurrencyISOCode(): ?string
|
||||||
{
|
{
|
||||||
return $this->currency?->getIsoCode();
|
return $this->currency?->getIsoCode();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue