src/JanusHercules/ContentDistributionFeedCreation/Domain/Entity/WorkOnRecurrentJobResult.php line 17

Open in your IDE?
  1. <?php
  2. namespace JanusHercules\ContentDistributionFeedCreation\Domain\Entity;
  3. use App\Entity\ContentDistribution\ContentDistributorFeed;
  4. use App\Entity\RecurrentJob;
  5. use App\Utility\DatabaseIdGenerator;
  6. use Doctrine\DBAL\Types\Types;
  7. use Doctrine\ORM\Mapping as ORM;
  8. use Doctrine\ORM\Mapping\Column;
  9. use JanusHercules\HighVolumeProcess\Domain\Entity\HighVolumeProcessTask;
  10. use JanusHercules\HighVolumeProcess\Domain\Entity\HighVolumeProcessTaskResultInterface;
  11. use ValueError;
  12. #[ORM\Entity]
  13. #[ORM\Table(name: 'work_on_recurrent_job_results')]
  14. class WorkOnRecurrentJobResult implements HighVolumeProcessTaskResultInterface
  15. {
  16. public const MAX_XML_SECTION_LENGTH = 65536;
  17. #[ORM\Id]
  18. #[ORM\GeneratedValue(strategy: 'CUSTOM')]
  19. #[ORM\CustomIdGenerator(class: DatabaseIdGenerator::class)]
  20. #[Column(
  21. type : Types::GUID,
  22. unique: true
  23. )]
  24. private ?string $id = null;
  25. public function getId(): ?string
  26. {
  27. return $this->id;
  28. }
  29. #[ORM\ManyToOne(targetEntity: RecurrentJob::class)]
  30. #[ORM\JoinColumn(
  31. name : 'recurrent_jobs_id',
  32. referencedColumnName: 'id',
  33. nullable : false,
  34. onDelete : 'CASCADE'
  35. )]
  36. private RecurrentJob $recurrentJob;
  37. public function getRecurrentJob(): RecurrentJob
  38. {
  39. return $this->recurrentJob;
  40. }
  41. public function setRecurrentJob(RecurrentJob $recurrentJob): void
  42. {
  43. $this->recurrentJob = $recurrentJob;
  44. }
  45. #[Column(
  46. type: Types::TEXT,
  47. )]
  48. private string $xmlSection;
  49. public function getXMLSection(): string
  50. {
  51. return $this->xmlSection;
  52. }
  53. public function setXMLSection(string $xmlSection): void
  54. {
  55. if (mb_strlen($xmlSection) > self::MAX_XML_SECTION_LENGTH) {
  56. throw new ValueError('The XML section cannot exceed ' . self::MAX_XML_SECTION_LENGTH . ' characters.');
  57. }
  58. // Ensure proper UTF-8 handling for regex
  59. mb_regex_encoding('UTF-8');
  60. // Extract first XML tag - using /u modifier for UTF-8 support
  61. if (!preg_match('/<([a-zA-Z][a-zA-Z0-9_:-]*)[^>]*>/u', $xmlSection, $openingTagMatch)) {
  62. throw new ValueError('Invalid XML: No opening tag found.');
  63. }
  64. $tagName = $openingTagMatch[1];
  65. // Check if it properly closes - using mb_ereg_replace for multibyte safety
  66. $expectedClosingTag = "</{$tagName}>";
  67. $trimmedXml = mb_ereg_replace('^\s+|\s+$', '', $xmlSection);
  68. if (!is_string($trimmedXml) || !str_ends_with($trimmedXml, $expectedClosingTag)) {
  69. throw new ValueError("Invalid XML: Opening tag <{$tagName}> does not have a matching closing tag.");
  70. }
  71. $this->xmlSection = $xmlSection;
  72. }
  73. #[ORM\ManyToOne(
  74. targetEntity: HighVolumeProcessTask::class,
  75. )]
  76. #[ORM\JoinColumn(
  77. name : 'high_volume_process_tasks_id',
  78. referencedColumnName: 'id',
  79. nullable : false,
  80. onDelete : 'CASCADE'
  81. )]
  82. private HighVolumeProcessTask $task;
  83. public function getTask(): HighVolumeProcessTask
  84. {
  85. return $this->task;
  86. }
  87. public function setTask(HighVolumeProcessTask $task): void
  88. {
  89. $this->task = $task;
  90. }
  91. #[ORM\ManyToOne(targetEntity: ContentDistributorFeed::class)]
  92. #[ORM\JoinColumn(
  93. name : 'content_distributor_feeds_id',
  94. referencedColumnName: 'id',
  95. nullable : false,
  96. onDelete : 'CASCADE'
  97. )]
  98. private ContentDistributorFeed $contentDistributorFeed;
  99. public function getContentDistributorFeed(): ContentDistributorFeed
  100. {
  101. return $this->contentDistributorFeed;
  102. }
  103. public function setContentDistributorFeed(ContentDistributorFeed $contentDistributorFeed): void
  104. {
  105. $this->contentDistributorFeed = $contentDistributorFeed;
  106. }
  107. }