AcceptHeader.php 3.5 KB

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