ICanBoogie/HTTP v2.4.0
  • Namespace
  • Class

Namespaces

  • ICanBoogie
    • Exception
    • HTTP
      • Dispatcher
      • Headers
      • Request

Classes

  • ICanBoogie\Exception\RescueEvent
  • ICanBoogie\HTTP\CallableDispatcher
  • ICanBoogie\HTTP\Dispatcher
  • ICanBoogie\HTTP\Dispatcher\BeforeDispatchEvent
  • ICanBoogie\HTTP\Dispatcher\DispatchEvent
  • ICanBoogie\HTTP\File
  • ICanBoogie\HTTP\FileInfo
  • ICanBoogie\HTTP\FileList
  • ICanBoogie\HTTP\Headers
  • ICanBoogie\HTTP\Headers\CacheControl
  • ICanBoogie\HTTP\Headers\ContentDisposition
  • ICanBoogie\HTTP\Headers\ContentType
  • ICanBoogie\HTTP\Headers\Date
  • ICanBoogie\HTTP\Headers\Header
  • ICanBoogie\HTTP\Headers\HeaderParameter
  • ICanBoogie\HTTP\Helpers
  • ICanBoogie\HTTP\RedirectResponse
  • ICanBoogie\HTTP\Request
  • ICanBoogie\HTTP\Request\Context
  • ICanBoogie\HTTP\Response
  • ICanBoogie\HTTP\Status
  • ICanBoogie\HTTP\WeightedDispatcher

Interfaces

  • ICanBoogie\HTTP\DispatcherInterface
  • ICanBoogie\HTTP\Exception

Exceptions

  • ICanBoogie\HTTP\DispatcherNotDefined
  • ICanBoogie\HTTP\ForceRedirect
  • ICanBoogie\HTTP\MethodNotSupported
  • ICanBoogie\HTTP\NotFound
  • ICanBoogie\HTTP\ServiceUnavailable
  • ICanBoogie\HTTP\StatusCodeNotValid
  1 <?php
  2 
  3 /*
  4  * This file is part of the ICanBoogie package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.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 namespace ICanBoogie\HTTP\Headers;
 13 
 14 use ICanBoogie\Accessor\AccessorTrait;
 15 
 16 /**
 17  * Representation of the `Cache-Control` header field.
 18  *
 19  * <pre>
 20  * <?php
 21  *
 22  * use ICanBoogie\HTTP\Headers\CacheControl;
 23  *
 24  * $cc = CacheControl::from('public, max-age=3600');
 25  * echo $cc->cacheable;           // true
 26  * echo $cc->max_age;             // 3600
 27  *
 28  * $cc->cacheable = 'no-cache';
 29  * $cc->max_age = null;
 30  * $cc->no_store = true;
 31  * $cc->must_revalidate = true;
 32  * echo $cc;                      // no-cache, no-store, must-revalidate
 33  * </pre>
 34  *
 35  * @property bool $cacheable
 36  *
 37  * @see http://tools.ietf.org/html/rfc2616#section-14.9
 38  */
 39 class CacheControl
 40 {
 41     use AccessorTrait;
 42 
 43     static protected $cacheable_values = [
 44 
 45         'private',
 46         'public',
 47         'no-cache'
 48 
 49     ];
 50 
 51     static protected $booleans = [
 52 
 53         'no-store',
 54         'no-transform',
 55         'only-if-cached',
 56         'must-revalidate',
 57         'proxy-revalidate'
 58 
 59     ];
 60 
 61     static protected $placeholder = [
 62 
 63         'cacheable'
 64 
 65     ];
 66 
 67     /**
 68      * Returns the default values of the instance.
 69      *
 70      * @return array
 71      */
 72     static protected function get_default_values()
 73     {
 74         return [
 75 
 76             'no_store' => false,
 77             'max_age' => null,
 78             's_maxage' => null,
 79             'max_stale' => null,
 80             'min_fresh' => null,
 81             'no_transform' => false,
 82             'only_if_cached' => false,
 83             'must_revalidate' => false,
 84             'proxy_revalidate' => false,
 85             'extensions' => []
 86 
 87         ];
 88     }
 89 
 90     /**
 91      * Parses the provided cache directive.
 92      *
 93      * @param string $cache_directive
 94      *
 95      * @return array Returns an array made of the properties and extensions.
 96      */
 97     static protected function parse($cache_directive)
 98     {
 99         $directives = explode(',', $cache_directive);
100         $directives = array_map('trim', $directives);
101 
102         $properties = self::get_default_values();
103         $extensions = [];
104 
105         foreach ($directives as $value)
106         {
107             if (in_array($value, self::$booleans))
108             {
109                 $property = strtr($value, '-', '_');
110                 $properties[$property] = true;
111             }
112             if (in_array($value, self::$cacheable_values))
113             {
114                 $properties['cacheable'] = $value;
115             }
116             else if (preg_match('#^([^=]+)=(.+)$#', $value, $matches))
117             {
118                 list(, $directive, $value) = $matches;
119 
120                 $property = strtr($directive, '-', '_');
121 
122                 if (is_numeric($value))
123                 {
124                     $value = 0 + $value;
125                 }
126 
127                 if (!array_key_exists($property, $properties))
128                 {
129                     $extensions[$property] = $value;
130 
131                     continue;
132                 }
133 
134                 $properties[$property] = $value;
135             }
136         }
137 
138         return [ $properties, $extensions ];
139     }
140 
141     /**
142      * Create an instance from the provided source.
143      *
144      * @param string $source
145      *
146      * @return CacheControl
147      */
148     static public function from($source)
149     {
150         if ($source instanceof self)
151         {
152             return $source;
153         }
154 
155         return new static($source);
156     }
157 
158     /**
159      * Whether the request/response is cacheable. The following properties are supported: `public`,
160      * `private` and `no-cache`. The variable may be empty in which case the cacheability of the
161      * request/response is unspecified.
162      *
163      * Scope: request, response.
164      *
165      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
166      *
167      * @var string
168      */
169     private $cacheable;
170 
171     /**
172      * @return string
173      */
174     protected function get_cacheable()
175     {
176         return $this->cacheable;
177     }
178 
179     /**
180      * @param $value
181      */
182     protected function set_cacheable($value)
183     {
184         if ($value === false)
185         {
186             $value = 'no-cache';
187         }
188 
189         if ($value !== null && !in_array($value, self::$cacheable_values))
190         {
191             throw new \InvalidArgumentException(\ICanBoogie\format
192             (
193                 "%var must be one of: public, private, no-cache. Give: %value", [
194 
195                     'var' => 'cacheable',
196                     'value' => $value
197 
198                 ]
199             ));
200         }
201 
202         $this->cacheable = $value;
203     }
204 
205     /**
206      * Whether the request/response is can be stored.
207      *
208      * Scope: request, response.
209      *
210      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.2
211      *
212      * @var bool
213      */
214     public $no_store = false;
215 
216     /**
217      * Indicates that the client is willing to accept a response whose age is no greater than the
218      * specified time in seconds. Unless `max-stale` directive is also included, the client is not
219      * willing to accept a stale response.
220      *
221      * Scope: request.
222      *
223      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3
224      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
225      *
226      * @var int
227      */
228     public $max_age;
229 
230     /**
231      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3
232      *
233      * @var int
234      */
235     public $s_maxage;
236 
237     /**
238      * Indicates that the client is willing to accept a response that has exceeded its expiration
239      * time. If max-stale is assigned a value, then the client is willing to accept a response
240      * that has exceeded its expiration time by no more than the specified number of seconds. If
241      * no value is assigned to max-stale, then the client is willing to accept a stale response
242      * of any age.
243      *
244      * Scope: request.
245      *
246      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3
247      *
248      * @var string
249      */
250     public $max_stale;
251 
252     /**
253      * Indicates that the client is willing to accept a response whose freshness lifetime is no
254      * less than its current age plus the specified time in seconds. That is, the client wants a
255      * response that will still be fresh for at least the specified number of seconds.
256      *
257      * Scope: request.
258      *
259      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.3
260      *
261      * @var int
262      */
263     public $min_fresh;
264 
265     /**
266      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5
267      *
268      * Scope: request, response.
269      *
270      * @var bool
271      */
272     public $no_transform = false;
273 
274     /**
275      * Scope: request.
276      *
277      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
278      *
279      * @var bool
280      */
281     public $only_if_cached = false;
282 
283     /**
284      * Scope: response.
285      *
286      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
287      *
288      * @var bool
289      */
290     public $must_revalidate = false;
291 
292     /**
293      * Scope: response.
294      *
295      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
296      *
297      * @var bool
298      */
299     public $proxy_revalidate = false;
300 
301     /**
302      * Scope: request, response.
303      *
304      * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.6
305      *
306      * @var array
307      */
308     public $extensions = [];
309 
310     /**
311      * If they are defined, the object is initialized with the cache directives.
312      *
313      * @param string $cache_directives Cache directives.
314      */
315     public function __construct($cache_directives=null)
316     {
317         if ($cache_directives)
318         {
319             $this->modify($cache_directives);
320         }
321     }
322 
323     /**
324      * Returns cache directives.
325      *
326      * @return string
327      */
328     public function __toString()
329     {
330         $cache_directive = '';
331 
332         foreach (get_object_vars($this) as $directive => $value)
333         {
334             $directive = strtr($directive, '_', '-');
335 
336             if (in_array($directive, self::$booleans))
337             {
338                 if (!$value)
339                 {
340                     continue;
341                 }
342 
343                 $cache_directive .= ', ' . $directive;
344             }
345             else if (in_array($directive, self::$placeholder))
346             {
347                 if (!$value)
348                 {
349                     continue;
350                 }
351 
352                 $cache_directive .= ', ' . $value;
353             }
354             else if (is_array($value))
355             {
356                 // TODO: 20120831: extentions
357 
358                 continue;
359             }
360             else if ($value !== null && $value !== false)
361             {
362                 $cache_directive .= ", $directive=$value";
363             }
364         }
365 
366         return $cache_directive ? substr($cache_directive, 2) : '';
367     }
368 
369     /**
370      * Sets the cache directives, updating the properties of the object.
371      *
372      * Unknown directives are stashed in the {@link $extensions} property.
373      *
374      * @param string $cache_directive
375      */
376     public function modify($cache_directive)
377     {
378         list($properties, $extensions) = static::parse($cache_directive);
379 
380         foreach ($properties as $property => $value)
381         {
382             $this->$property = $value;
383         }
384 
385         $this->extensions = $extensions;
386     }
387 }
388 
ICanBoogie/HTTP v2.4.0 API documentation generated by ApiGen