src/Entity/JournalVolume.php line 87

  1. <?php
  2. namespace App\Entity;
  3. use Doctrine\ORM\Mapping as ORM,
  4.     Doctrine\DBAL\Types\Types,
  5.     Doctrine\Common\Collections\Collection,
  6.     Doctrine\Common\Collections\ArrayCollection;
  7. use Symfony\Component\Serializer\Annotation\Groups,
  8.     Symfony\Component\Validator\Constraints as Assert;
  9. use ApiPlatform\Metadata\ApiResource,
  10.     ApiPlatform\Metadata\ApiProperty,
  11.     ApiPlatform\Metadata\Get,
  12.     ApiPlatform\Metadata\GetCollection,
  13.     ApiPlatform\Metadata\Post,
  14.     ApiPlatform\Metadata\Put,
  15.     ApiPlatform\Metadata\Delete,
  16.     ApiPlatform\Metadata\ApiFilter,
  17.     ApiPlatform\Doctrine\Orm\Filter\OrderFilter,
  18.     ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
  19. use App\Entity\Trait\IdTrait,
  20.     App\Entity\Trait\UuidTrait,
  21.     App\Entity\Trait\OrdStatTrait,
  22.     App\Entity\Trait\TimestampableTrait,
  23.     App\Entity\Trait\TranslatableTrait,
  24.     App\Entity\Trait\Languages\LanguageableChildTrait,
  25.     App\Entity\Trait\ArchivedTrait,
  26.     App\Entity\Trait\EditorialGroupableTrait,
  27.     App\Entity\Trait\ImportIdTrait,
  28.     App\Entity\Interface\TranslatableInterface,
  29.     App\Entity\Interface\OrdStatableInterface,
  30.     App\Entity\Interface\LanguageableChildInterface,
  31.     App\Entity\Interface\ArchivableInterface,
  32.     App\Entity\Interface\EditorialGroupableInterface,
  33.     App\Entity\Interface\CloneableInterface;
  34. use App\Attribute\Sanitizeable,
  35.     App\Enum\JournalDateFormat,
  36.     App\Enum\JournalLicence,
  37.     App\Enum\AuthorProperty,
  38.     App\Doctrine\DBAL\Types\AuthorPropertiesType,
  39.     App\Repository\JournalVolumeRepository,
  40.     App\Security\Voter\ArchivableVoter,
  41.     App\Lib\Actions,
  42.     App\DTO\CloneDTO,
  43.     App\StateProcessor\CloneProcessor,
  44.     App\Security\Voter\CloneVoter,
  45.     App\Filter\IriFilter;
  46. use App\Util\ClassUtils;
  47. #[ApiResource(
  48.     description'Journal volumes',
  49.     normalizationContext: ['groups' => [
  50.         'read',
  51.         'read:' self::class,
  52.         'read:' self::class . 'Translation'
  53.     ]],
  54.     denormalizationContext: ['groups' => ['write']],
  55.     security'is_granted("' Journal::class . '")',
  56.     order: ['ord' => 'desc'],
  57.     operations: [
  58.         new GetCollection(),
  59.         new Post(
  60.             uriTemplate'/journal_volumes/clone',
  61.             inputCloneDTO::class,
  62.             processorCloneProcessor::class,
  63.             security'is_granted("' Actions::CLONE .'")',
  64.             securityMessageCloneVoter::MESSAGE
  65.         ),
  66.         new Post(denormalizationContext: ['groups' => ['write',  'post']]),
  67.         new Get(),
  68.         new Put(),
  69.         new Delete(
  70.             securityPostDenormalize'is_granted("' Actions::DELETE '", object)',
  71.             securityPostDenormalizeMessageArchivableVoter::MESSAGE
  72.         ),
  73.     ],
  74.     extraProperties: ['standard_put' => false],
  75. )]
  76. #[ApiFilter(IriFilter::class, properties: ['parent'])]
  77. #[ApiFilter(BooleanFilter::class, properties: ['isArchived''stat'])]
  78. #[ApiFilter(OrderFilter::class, properties: ['ord'])]
  79. #[ORM\Entity(repositoryClassJournalVolumeRepository::class)]
  80. class JournalVolume implements
  81.     TranslatableInterface,
  82.     OrdStatableInterface,
  83.     LanguageableChildInterface,
  84.     EditorialGroupableInterface,
  85.     ArchivableInterface,
  86.     CloneableInterface
  87. {
  88.     use IdTrait,
  89.         UuidTrait,
  90.         OrdStatTrait,
  91.         TimestampableTrait,
  92.         TranslatableTrait,
  93.         LanguageableChildTrait,
  94.         ArchivedTrait,
  95.         EditorialGroupableTrait,
  96.         ImportIdTrait;
  97.     #[ApiProperty(description'Parent'readableLinkfalsewritableLinkfalse)]
  98.     #[Groups(['read''post'])]
  99.     #[ORM\ManyToOne(targetEntityJournal::class, inversedBy'volumes')]
  100.     #[ORM\JoinColumn(onDelete'cascade'nullablefalse)]
  101.     private Journal $parent;
  102.     #[ApiProperty(description'Planned numbers amount')]
  103.     #[Groups(['read:' self::class, 'write'])]
  104.     #[Assert\Positive]
  105.     #[ORM\Column(typeTypes::INTEGERoptions: ['default' => 1])]
  106.     private int $plannedNumbersAmount 1;
  107.     #[ApiProperty(description'Published at')]
  108.     #[Groups(['read:' self::class, 'write'])]
  109.     #[ORM\Column(typeTypes::DATE_IMMUTABLEnullabletrue)]
  110.     private ?\DateTimeImmutable $publishedAt null;
  111.     #[ApiProperty(description'Is published at visible')]
  112.     #[Groups(['read:' self::class, 'write'])]
  113.     #[ORM\Column(typeTypes::BOOLEANoptions: ['default' => false])]
  114.     private bool $isPublishedAtVisible false;
  115.     #[ApiProperty(description'Published at format'writableLinkfalse)]
  116.     #[Groups(['read:' self::class, 'write'])]
  117.     #[ORM\Column(
  118.         typeTypes::STRING,
  119.         enumTypeJournalDateFormat::class,
  120.         length255,
  121.         options: ['default' => JournalDateFormat::COMPLETE]
  122.     )]
  123.     private JournalDateFormat $publishedAtFormat JournalDateFormat::COMPLETE;
  124.     #[ApiProperty(description'DOI')]
  125.     #[Groups(['read:' self::class, 'write'])]
  126.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  127.     private ?string $doi null;
  128.     #[ApiProperty(description'Is DOI visible')]
  129.     #[Groups(['read:' self::class, 'write'])]
  130.     #[ORM\Column(typeTypes::BOOLEANoptions: ['default' => false])]
  131.     private bool $isDoiVisible false;
  132.     #[ApiProperty(description'Licence'writableLinkfalse)]
  133.     #[Groups(['read:' self::class, 'write'])]
  134.     #[ORM\Column(
  135.         typeTypes::STRING,
  136.         enumTypeJournalLicence::class,
  137.         length255,
  138.         options: ['default' => JournalLicence::CC_BY]
  139.     )]
  140.     private JournalLicence $licence JournalLicence::CC_BY;
  141.     #[ApiProperty(description'Is licence visible')]
  142.     #[Groups(['read:' self::class, 'write'])]
  143.     #[ORM\Column(typeTypes::BOOLEANoptions: ['default' => false])]
  144.     private bool $isLicenceVisible false;
  145.     #[ApiProperty(description'Funding number')]
  146.     #[Groups(['read:' self::class, 'write'])]
  147.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  148.     private ?string $fundingNumber null;
  149.     #[ApiProperty(description'Additional info')]
  150.     #[Groups(['read:' self::class, 'write'])]
  151.     #[Sanitizeable]
  152.     #[ORM\Column(typeTypes::TEXTnullabletrue)]
  153.     private ?string $additionalInfo null;
  154.     #[ApiProperty(description'Meta link')]
  155.     #[Groups(['read:' self::class, 'write'])]
  156.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  157.     private ?string $metaLink null;
  158.     #[ApiProperty(description'Visible editorial group member properties'writableLinkfalse)]
  159.     #[Groups(['read:' self::class, 'write'])]
  160.     #[Assert\Choice(callback: [AuthorProperty::class, 'cases'], multipletrue)]
  161.     #[Assert\Unique]
  162.     #[Assert\Count(min1)]
  163.     #[ORM\Column(typeAuthorPropertiesType::NAME)]
  164.     private array $visibleEditorialGroupMemberProperties = [
  165.         AuthorProperty::PREFIX,
  166.         AuthorProperty::NAME,
  167.         AuthorProperty::SURNAME,
  168.         AuthorProperty::AFFILIATION
  169.     ];
  170.     #[ApiProperty(description'Issues'writableLinkfalse)]
  171.     #[Groups(['read:' self::class])]
  172.     #[ORM\OneToMany(targetEntityJournalIssue::class, mappedBy'volume'cascade: ['persist'])]
  173.     #[ORM\OrderBy(['ord' => 'desc'])]
  174.     private Collection $issues;
  175.     #[ApiProperty(description'Import link')]
  176.     #[Groups(['read:' self::class, 'write'])]
  177.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  178.     private ?string $importLink null;
  179.     #[ApiProperty(description'Import link en')]
  180.     #[Groups(['read:' self::class, 'write'])]
  181.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  182.     private ?string $importLinkEn null;
  183.     public function __construct(Journal $parent)
  184.     {
  185.         $this->setUuid();
  186.         $this->parent $parent;
  187.         $this->translations = new ArrayCollection();
  188.         $this->issues = new ArrayCollection();
  189.         $this->editorialGroups = new ArrayCollection();
  190.         foreach ($this->parent->getLanguages() as $lang) {
  191.             new JournalVolumeTranslation($this$lang);
  192.         }
  193.         foreach($this->parent->getEditorialGroups() as $editorialGroup) {
  194.             $copied JournalVolumeEditorialGroup::constructFrom(parent$thistemplate$editorialGroup);
  195.             $this->addEditorialGroup($copied);
  196.         }
  197.         $this->visibleEditorialGroupMemberProperties $parent->getView()->getVisibleEditorialGroupMemberProperties();
  198.         $this->licence $parent->getData()->getLicence();
  199.         $this->createdAt = new \DateTimeImmutable();
  200.         $this->updatedAt = new \DateTimeImmutable();
  201.         $parent->addVolume($this);
  202.     }
  203.     public function getParent(): Journal
  204.     {
  205.         return $this->parent;
  206.     }
  207.     public function getPlannedNumbersAmount(): int
  208.     {
  209.         return $this->plannedNumbersAmount;
  210.     }
  211.     public function setPlannedNumbersAmount(int $plannedNumbersAmount): self
  212.     {
  213.         $this->plannedNumbersAmount $plannedNumbersAmount;
  214.         return $this;
  215.     }
  216.     #[Groups(['read:' self::class])]
  217.     public function getNumbersRatio(): string
  218.     {
  219.         $issues count($this->issues);
  220.         return "{$issues}/{$this->plannedNumbersAmount}";
  221.     }
  222.     public function getPublishedAt(): ?\DateTimeImmutable
  223.     {
  224.         return $this->publishedAt;
  225.     }
  226.     public function setPublishedAt(?\DateTimeImmutable $publishedAt): self
  227.     {
  228.         $this->publishedAt $publishedAt;
  229.         return $this;
  230.     }
  231.     public function getIsPublishedAtVisible(): bool
  232.     {
  233.         return $this->isPublishedAtVisible;
  234.     }
  235.     public function setIsPublishedAtVisible(bool $isPublishedAtVisible): self
  236.     {
  237.         $this->isPublishedAtVisible $isPublishedAtVisible;
  238.         return $this;
  239.     }
  240.     public function getPublishedAtFormat(): JournalDateFormat
  241.     {
  242.         return $this->publishedAtFormat;
  243.     }
  244.     public function setPublishedAtFormat(JournalDateFormat $publishedAtFormat): self
  245.     {
  246.         $this->publishedAtFormat $publishedAtFormat;
  247.         return $this;
  248.     }
  249.     public function getDoi(): ?string
  250.     {
  251.         return $this->doi;
  252.     }
  253.     public function setDoi(?string $doi): self
  254.     {
  255.         $this->doi $doi;
  256.         return $this;
  257.     }
  258.     public function getIsDoiVisible(): bool
  259.     {
  260.         return $this->isDoiVisible;
  261.     }
  262.     public function setIsDoiVisible(bool $isDoiVisible): self
  263.     {
  264.         $this->isDoiVisible $isDoiVisible;
  265.         return $this;
  266.     }
  267.     public function getLicence(): JournalLicence
  268.     {
  269.         return $this->licence;
  270.     }
  271.     public function setLicence(JournalLicence $licence): self
  272.     {
  273.         $this->licence $licence;
  274.         return $this;
  275.     }
  276.     public function getIsLicenceVisible(): bool
  277.     {
  278.         return $this->isLicenceVisible;
  279.     }
  280.     public function setIsLicenceVisible(bool $isLicenceVisible): self
  281.     {
  282.         $this->isLicenceVisible $isLicenceVisible;
  283.         return $this;
  284.     }
  285.     public function getFundingNumber(): ?string
  286.     {
  287.         return $this->fundingNumber;
  288.     }
  289.     public function setFundingNumber(?string $fundingNumber): self
  290.     {
  291.         $this->fundingNumber $fundingNumber;
  292.         return $this;
  293.     }
  294.     public function getAdditionalInfo(): ?string
  295.     {
  296.         return $this->additionalInfo;
  297.     }
  298.     public function setAdditionalInfo(?string $additionalInfo): self
  299.     {
  300.         $this->additionalInfo $additionalInfo;
  301.         return $this;
  302.     }
  303.     public function getMetaLink(): ?string
  304.     {
  305.         return $this->metaLink;
  306.     }
  307.     public function setMetaLink(?string $metaLink): self
  308.     {
  309.         $this->metaLink $metaLink;
  310.         return $this;
  311.     }
  312.     public function getVisibleEditorialGroupMemberProperties(): array
  313.     {
  314.         return $this->visibleEditorialGroupMemberProperties;
  315.     }
  316.     public function setVisibleEditorialGroupMemberProperties(array $visibleEditorialGroupMemberProperties): self
  317.     {
  318.         $this->visibleEditorialGroupMemberProperties $visibleEditorialGroupMemberProperties;
  319.         return $this;
  320.     }
  321.     /**
  322.      * @return Collection|JournalIssue[]
  323.      */
  324.     public function getIssues(): Collection
  325.     {
  326.         return $this->issues;
  327.     }
  328.     public function addIssue(JournalIssue $issue): self
  329.     {
  330.         if ($this->issues->contains($issue)) {
  331.             return $this;
  332.         }
  333.         $this->issues[] = $issue;
  334.         return $this;
  335.     }
  336.     public function removeIssue(JournalIssue $issue): self
  337.     {
  338.         $this->issues->removeElement($issue);
  339.         return $this;
  340.     }
  341.     public function resetIssues(): self
  342.     {
  343.         $this->issues = new ArrayCollection();
  344.         return $this;
  345.     }
  346.     public function clone(): self
  347.     {
  348.         $clone = clone $this;
  349.         $clone->id null;
  350.         $clone->setUuid();
  351.         $clone->ord 0;
  352.         $clone->stat false;
  353.         $clone->importId null;
  354.         ClassUtils::cloneCollection($this$clone'translations');
  355.         $clone->synchronizeTranslations();
  356.         $nativeLanguage $clone->parent->getNativeLanguage();
  357.         $nativeTranslation $clone->getTranslation($nativeLanguage);
  358.         $nativeTranslation->setTitle($nativeTranslation->getTitle() . ' [KOPIA]');
  359.         ClassUtils::cloneCollection($this$clone'editorialGroups');
  360.         $clone->resetIssues();
  361.         foreach ($this->getIssues() as $issue) {
  362.             $clone->addIssue(
  363.                 $issue->clone(
  364.                     $clone->parent
  365.                 )
  366.             );
  367.         }
  368.         $clone->createdAt = new \DateTimeImmutable();
  369.         $clone->updatedAt = new \DateTimeImmutable();
  370.         return $clone;
  371.     }
  372.     public function getImportLink(): ?string
  373.     {
  374.         return $this->importLink;
  375.     }
  376.     public function setImportLink(?string $importLink): self
  377.     {
  378.         $this->importLink $importLink;
  379.         return $this;
  380.     }
  381.     public function getImportLinkEn(): ?string
  382.     {
  383.         return $this->importLinkEn;
  384.     }
  385.     public function setImportLinkEn(?string $importLinkEn): self
  386.     {
  387.         $this->importLinkEn $importLinkEn;
  388.         return $this;
  389.     }
  390. }