ResponseHeaderBag.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. namespace Symfony\Component\HttpFoundation;
  3. /*
  4. * This file is part of the Symfony package.
  5. *
  6. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. /**
  12. * ResponseHeaderBag is a container for Response HTTP headers.
  13. *
  14. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  15. */
  16. class ResponseHeaderBag extends HeaderBag
  17. {
  18. protected $computedCacheControl = array();
  19. /**
  20. * {@inheritdoc}
  21. */
  22. public function replace(array $headers = array())
  23. {
  24. parent::replace($headers);
  25. if (!isset($this->headers['cache-control'])) {
  26. $this->set('cache-control', '');
  27. }
  28. }
  29. /**
  30. * {@inheritdoc}
  31. */
  32. public function set($key, $values, $replace = true)
  33. {
  34. parent::set($key, $values, $replace);
  35. // ensure the cache-control header has sensible defaults
  36. if ('cache-control' === strtr(strtolower($key), '_', '-')) {
  37. $computed = $this->computeCacheControlValue();
  38. $this->headers['cache-control'] = array($computed);
  39. $this->computedCacheControl = $this->parseCacheControl($computed);
  40. }
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. public function remove($key)
  46. {
  47. parent::remove($key);
  48. if ('cache-control' === strtr(strtolower($key), '_', '-')) {
  49. $this->computedCacheControl = array();
  50. }
  51. }
  52. /**
  53. * {@inheritdoc}
  54. */
  55. public function setCookie($name, $value, $domain = null, $expires = null, $path = '/', $secure = false, $httponly = true)
  56. {
  57. $this->validateCookie($name, $value);
  58. $cookie = sprintf('%s=%s', $name, urlencode($value));
  59. if (null !== $expires) {
  60. if (is_numeric($expires)) {
  61. $expires = (int) $expires;
  62. } elseif ($expires instanceof \DateTime) {
  63. $expires = $expires->getTimestamp();
  64. } else {
  65. $expires = strtotime($expires);
  66. if (false === $expires || -1 == $expires) {
  67. throw new \InvalidArgumentException(sprintf('The "expires" cookie parameter is not valid.', $expires));
  68. }
  69. }
  70. $cookie .= '; expires='.substr(\DateTime::createFromFormat('U', $expires, new \DateTimeZone('UTC'))->format('D, d-M-Y H:i:s T'), 0, -5);
  71. }
  72. if ($domain) {
  73. $cookie .= '; domain='.$domain;
  74. }
  75. $cookie .= '; path='.$path;
  76. if ($secure) {
  77. $cookie .= '; secure';
  78. }
  79. if ($httponly) {
  80. $cookie .= '; httponly';
  81. }
  82. $this->set('Set-Cookie', $cookie, false);
  83. }
  84. /**
  85. * {@inheritdoc}
  86. */
  87. public function hasCacheControlDirective($key)
  88. {
  89. return array_key_exists($key, $this->computedCacheControl);
  90. }
  91. /**
  92. * {@inheritdoc}
  93. */
  94. public function getCacheControlDirective($key)
  95. {
  96. return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null;
  97. }
  98. /**
  99. * Returns the calculated value of the cache-control header.
  100. *
  101. * This considers several other headers and calculates or modifies the
  102. * cache-control header to a sensible, conservative value.
  103. *
  104. * @return string
  105. */
  106. protected function computeCacheControlValue()
  107. {
  108. if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) {
  109. return 'no-cache';
  110. }
  111. if (!$this->cacheControl) {
  112. // conservative by default
  113. return 'private, max-age=0, must-revalidate';
  114. }
  115. $header = $this->getCacheControlHeader();
  116. if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
  117. return $header;
  118. }
  119. // public if s-maxage is defined, private otherwise
  120. if (!isset($this->cacheControl['s-maxage'])) {
  121. return $header.', private';
  122. }
  123. return $header;
  124. }
  125. }