vendor/symfony/mime/Header/Headers.php line 22

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\Mime\Header;
  11. use Symfony\Component\Mime\Address;
  12. use Symfony\Component\Mime\Exception\LogicException;
  13. /**
  14.  * A collection of headers.
  15.  *
  16.  * @author Fabien Potencier <fabien@symfony.com>
  17.  */
  18. final class Headers
  19. {
  20.     private const UNIQUE_HEADERS = [
  21.         'date''from''sender''reply-to''to''cc''bcc',
  22.         'message-id''in-reply-to''references''subject',
  23.     ];
  24.     private const HEADER_CLASS_MAP = [
  25.         'date' => DateHeader::class,
  26.         'from' => MailboxListHeader::class,
  27.         'sender' => MailboxHeader::class,
  28.         'reply-to' => MailboxListHeader::class,
  29.         'to' => MailboxListHeader::class,
  30.         'cc' => MailboxListHeader::class,
  31.         'bcc' => MailboxListHeader::class,
  32.         'message-id' => IdentificationHeader::class,
  33.         'in-reply-to' => UnstructuredHeader::class, // `In-Reply-To` and `References` are less strict than RFC 2822 (3.6.4) to allow users entering the original email's ...
  34.         'references' => UnstructuredHeader::class, // ... `Message-ID`, even if that is no valid `msg-id`
  35.         'return-path' => PathHeader::class,
  36.     ];
  37.     /**
  38.      * @var HeaderInterface[][]
  39.      */
  40.     private array $headers = [];
  41.     private int $lineLength 76;
  42.     public function __construct(HeaderInterface ...$headers)
  43.     {
  44.         foreach ($headers as $header) {
  45.             $this->add($header);
  46.         }
  47.     }
  48.     public function __clone()
  49.     {
  50.         foreach ($this->headers as $name => $collection) {
  51.             foreach ($collection as $i => $header) {
  52.                 $this->headers[$name][$i] = clone $header;
  53.             }
  54.         }
  55.     }
  56.     public function setMaxLineLength(int $lineLength)
  57.     {
  58.         $this->lineLength $lineLength;
  59.         foreach ($this->all() as $header) {
  60.             $header->setMaxLineLength($lineLength);
  61.         }
  62.     }
  63.     public function getMaxLineLength(): int
  64.     {
  65.         return $this->lineLength;
  66.     }
  67.     /**
  68.      * @param array<Address|string> $addresses
  69.      *
  70.      * @return $this
  71.      */
  72.     public function addMailboxListHeader(string $name, array $addresses): static
  73.     {
  74.         return $this->add(new MailboxListHeader($nameAddress::createArray($addresses)));
  75.     }
  76.     /**
  77.      * @return $this
  78.      */
  79.     public function addMailboxHeader(string $nameAddress|string $address): static
  80.     {
  81.         return $this->add(new MailboxHeader($nameAddress::create($address)));
  82.     }
  83.     /**
  84.      * @return $this
  85.      */
  86.     public function addIdHeader(string $namestring|array $ids): static
  87.     {
  88.         return $this->add(new IdentificationHeader($name$ids));
  89.     }
  90.     /**
  91.      * @return $this
  92.      */
  93.     public function addPathHeader(string $nameAddress|string $path): static
  94.     {
  95.         return $this->add(new PathHeader($name$path instanceof Address $path : new Address($path)));
  96.     }
  97.     /**
  98.      * @return $this
  99.      */
  100.     public function addDateHeader(string $name\DateTimeInterface $dateTime): static
  101.     {
  102.         return $this->add(new DateHeader($name$dateTime));
  103.     }
  104.     /**
  105.      * @return $this
  106.      */
  107.     public function addTextHeader(string $namestring $value): static
  108.     {
  109.         return $this->add(new UnstructuredHeader($name$value));
  110.     }
  111.     /**
  112.      * @return $this
  113.      */
  114.     public function addParameterizedHeader(string $namestring $value, array $params = []): static
  115.     {
  116.         return $this->add(new ParameterizedHeader($name$value$params));
  117.     }
  118.     /**
  119.      * @return $this
  120.      */
  121.     public function addHeader(string $namemixed $argument, array $more = []): static
  122.     {
  123.         $parts explode('\\'self::HEADER_CLASS_MAP[strtolower($name)] ?? UnstructuredHeader::class);
  124.         $method 'add'.ucfirst(array_pop($parts));
  125.         if ('addUnstructuredHeader' === $method) {
  126.             $method 'addTextHeader';
  127.         } elseif ('addIdentificationHeader' === $method) {
  128.             $method 'addIdHeader';
  129.         }
  130.         return $this->$method($name$argument$more);
  131.     }
  132.     public function has(string $name): bool
  133.     {
  134.         return isset($this->headers[strtolower($name)]);
  135.     }
  136.     /**
  137.      * @return $this
  138.      */
  139.     public function add(HeaderInterface $header): static
  140.     {
  141.         self::checkHeaderClass($header);
  142.         $header->setMaxLineLength($this->lineLength);
  143.         $name strtolower($header->getName());
  144.         if (\in_array($nameself::UNIQUE_HEADERStrue) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) {
  145.             throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.'$header->getName()));
  146.         }
  147.         $this->headers[$name][] = $header;
  148.         return $this;
  149.     }
  150.     public function get(string $name): ?HeaderInterface
  151.     {
  152.         $name strtolower($name);
  153.         if (!isset($this->headers[$name])) {
  154.             return null;
  155.         }
  156.         $values array_values($this->headers[$name]);
  157.         return array_shift($values);
  158.     }
  159.     public function all(string $name null): iterable
  160.     {
  161.         if (null === $name) {
  162.             foreach ($this->headers as $name => $collection) {
  163.                 foreach ($collection as $header) {
  164.                     yield $name => $header;
  165.                 }
  166.             }
  167.         } elseif (isset($this->headers[strtolower($name)])) {
  168.             foreach ($this->headers[strtolower($name)] as $header) {
  169.                 yield $header;
  170.             }
  171.         }
  172.     }
  173.     public function getNames(): array
  174.     {
  175.         return array_keys($this->headers);
  176.     }
  177.     public function remove(string $name): void
  178.     {
  179.         unset($this->headers[strtolower($name)]);
  180.     }
  181.     public static function isUniqueHeader(string $name): bool
  182.     {
  183.         return \in_array(strtolower($name), self::UNIQUE_HEADERStrue);
  184.     }
  185.     /**
  186.      * @throws LogicException if the header name and class are not compatible
  187.      */
  188.     public static function checkHeaderClass(HeaderInterface $header): void
  189.     {
  190.         $name strtolower($header->getName());
  191.         if (($c self::HEADER_CLASS_MAP[$name] ?? null) && !$header instanceof $c) {
  192.             throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").'$header->getName(), $cget_debug_type($header)));
  193.         }
  194.     }
  195.     public function toString(): string
  196.     {
  197.         $string '';
  198.         foreach ($this->toArray() as $str) {
  199.             $string .= $str."\r\n";
  200.         }
  201.         return $string;
  202.     }
  203.     public function toArray(): array
  204.     {
  205.         $arr = [];
  206.         foreach ($this->all() as $header) {
  207.             if ('' !== $header->getBodyAsString()) {
  208.                 $arr[] = $header->toString();
  209.             }
  210.         }
  211.         return $arr;
  212.     }
  213.     public function getHeaderBody(string $name)
  214.     {
  215.         return $this->has($name) ? $this->get($name)->getBody() : null;
  216.     }
  217.     /**
  218.      * @internal
  219.      */
  220.     public function setHeaderBody(string $typestring $namemixed $body): void
  221.     {
  222.         if ($this->has($name)) {
  223.             $this->get($name)->setBody($body);
  224.         } else {
  225.             $this->{'add'.$type.'Header'}($name$body);
  226.         }
  227.     }
  228.     public function getHeaderParameter(string $namestring $parameter): ?string
  229.     {
  230.         if (!$this->has($name)) {
  231.             return null;
  232.         }
  233.         $header $this->get($name);
  234.         if (!$header instanceof ParameterizedHeader) {
  235.             throw new LogicException(sprintf('Unable to get parameter "%s" on header "%s" as the header is not of class "%s".'$parameter$nameParameterizedHeader::class));
  236.         }
  237.         return $header->getParameter($parameter);
  238.     }
  239.     /**
  240.      * @internal
  241.      */
  242.     public function setHeaderParameter(string $namestring $parameter, ?string $value): void
  243.     {
  244.         if (!$this->has($name)) {
  245.             throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not defined.'$parameter$name));
  246.         }
  247.         $header $this->get($name);
  248.         if (!$header instanceof ParameterizedHeader) {
  249.             throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not of class "%s".'$parameter$nameParameterizedHeader::class));
  250.         }
  251.         $header->setParameter($parameter$value);
  252.     }
  253. }