src/Entity/JournalVolume.php line 91

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