AcceptHeader.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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\HttpFoundation;
  11. /**
  12. * Represents an Accept-* header.
  13. *
  14. * An accept header is compound with a list of items,
  15. * sorted by descending quality.
  16. *
  17. * @author Jean-François Simon <contact@jfsimon.fr>
  18. */
  19. class AcceptHeader
  20. {
  21. /**
  22. * @var AcceptHeaderItem[]
  23. */
  24. private $items = [];
  25. /**
  26. * @var bool
  27. */
  28. private $sorted = true;
  29. /**
  30. * @param AcceptHeaderItem[] $items
  31. */
  32. public function __construct(array $items)
  33. {
  34. foreach ($items as $item) {
  35. $this->add($item);
  36. }
  37. }
  38. /**
  39. * Builds an AcceptHeader instance from a string.
  40. *
  41. * @param string $headerValue
  42. *
  43. * @return self
  44. */
  45. public static function fromString($headerValue)
  46. {
  47. $index = 0;
  48. return new self(array_map(function ($itemValue) use (&$index) {
  49. $item = AcceptHeaderItem::fromString($itemValue);
  50. $item->setIndex($index++);
  51. return $item;
  52. }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)));
  53. }
  54. /**
  55. * Returns header value's string representation.
  56. *
  57. * @return string
  58. */
  59. public function __toString()
  60. {
  61. return implode(',', $this->items);
  62. }
  63. /**
  64. * Tests if header has given value.
  65. *
  66. * @param string $value
  67. *
  68. * @return bool
  69. */
  70. public function has($value)
  71. {
  72. return isset($this->items[$value]);
  73. }
  74. /**
  75. * Returns given value's item, if exists.
  76. *
  77. * @param string $value
  78. *
  79. * @return AcceptHeaderItem|null
  80. */
  81. public function get($value)
  82. {
  83. return isset($this->items[$value]) ? $this->items[$value] : null;
  84. }
  85. /**
  86. * Adds an item.
  87. *
  88. * @return $this
  89. */
  90. public function add(AcceptHeaderItem $item)
  91. {
  92. $this->items[$item->getValue()] = $item;
  93. $this->sorted = false;
  94. return $this;
  95. }
  96. /**
  97. * Returns all items.
  98. *
  99. * @return AcceptHeaderItem[]
  100. */
  101. public function all()
  102. {
  103. $this->sort();
  104. return $this->items;
  105. }
  106. /**
  107. * Filters items on their value using given regex.
  108. *
  109. * @param string $pattern
  110. *
  111. * @return self
  112. */
  113. public function filter($pattern)
  114. {
  115. return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) {
  116. return preg_match($pattern, $item->getValue());
  117. }));
  118. }
  119. /**
  120. * Returns first item.
  121. *
  122. * @return AcceptHeaderItem|null
  123. */
  124. public function first()
  125. {
  126. $this->sort();
  127. return !empty($this->items) ? reset($this->items) : null;
  128. }
  129. /**
  130. * Sorts items by descending quality.
  131. */
  132. private function sort()
  133. {
  134. if (!$this->sorted) {
  135. uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) {
  136. $qA = $a->getQuality();
  137. $qB = $b->getQuality();
  138. if ($qA === $qB) {
  139. return $a->getIndex() > $b->getIndex() ? 1 : -1;
  140. }
  141. return $qA > $qB ? -1 : 1;
  142. });
  143. $this->sorted = true;
  144. }
  145. }
  146. }