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\OffsetNotDefined;
 15 use ICanBoogie\PropertyNotDefined;
 16 
 17 /**
 18  * Base class for header fields.
 19  *
 20  * Classes that extend the class and support attributes must defined them during construct:
 21  *
 22  * <pre>
 23  * <?php
 24  *
 25  * namespace ICanBoogie\HTTP\Headers;
 26  *
 27  * class ContentDisposition extends Header
 28  * {
 29  *     public function __construct($value=null, array $attributes=[])
 30  *     {
 31  *         $this->parameters['filename'] = new HeaderParameter('filename');
 32  *
 33  *         parent::__construct($value, $attributes);
 34  *     }
 35  * }
 36  * </pre>
 37  *
 38  * Magic properties are automatically mapped to parameters. The value of a parameter is accessed
 39  * through its corresponding property:
 40  *
 41  * <pre>
 42  * <?php
 43  *
 44  * $cd = new ContentDisposition;
 45  * $cd->filename = "Statistics.csv";
 46  * echo $cd->filename;
 47  * // "Statistics.csv"
 48  * </pre>
 49  *
 50  * The instance of the parameter itself is accessed using the header as an array:
 51  *
 52  * <pre>
 53  * <?php
 54  *
 55  * $cd = new ContentDisposition;
 56  * $cd['filename']->value = "Statistics.csv";
 57  * $cd['filename']->language = "en";
 58  * </pre>
 59  *
 60  * An alias to the {@link $value} property can be defined by using the `VALUE_ALIAS` constant. The
 61  * following code defines `type` as an alias:
 62  *
 63  * <pre>
 64  * <?php
 65  *
 66  * class ContentDisposition extends Header
 67  * {
 68  *     const VALUE_ALIAS = 'type';
 69  * }
 70  * </pre>
 71  */
 72 abstract class Header implements \ArrayAccess
 73 {
 74     const VALUE_ALIAS = null;
 75 
 76     /**
 77      * The value of the header.
 78      *
 79      * @var string
 80      */
 81     public $value;
 82 
 83     /**
 84      * The parameters supported by the header.
 85      *
 86      * @var HeaderParameter[]
 87      */
 88     protected $parameters = [];
 89 
 90     /**
 91      * Creates a {@link Header} instance from the provided source.
 92      *
 93      * @param string|Header $source The source to create the instance from. If the source is
 94      * an instance of {@link Header} it is returned as is.
 95      *
 96      * @return Header
 97      */
 98     static public function from($source)
 99     {
100         if ($source instanceof self)
101         {
102             return $source;
103         }
104 
105         if ($source === null)
106         {
107             return new static;
108         }
109 
110         list($value, $parameters) = static::parse($source);
111 
112         return new static($value, $parameters);
113     }
114 
115     /**
116      * Parse the provided source and extract its value and parameters.
117      *
118      * @param string $source The source to create the instance from.
119      *
120      * @throws \InvalidArgumentException if `$source` is not a string nor an object implementing
121      * `__toString()`.
122      *
123      * @return array
124      */
125     static protected function parse($source)
126     {
127         if (is_object($source) && method_exists($source, '__toString'))
128         {
129             $source = (string) $source;
130         }
131 
132         if (!is_string($source))
133         {
134             throw new \InvalidArgumentException(\ICanBoogie\format
135             (
136                 "%var must be a string or an object implementing __toString(). Given: !data", [
137 
138                     'var' => 'source',
139                     'data' => $source
140 
141                 ]
142             ));
143         }
144 
145         $value_end = strpos($source, ';');
146         $parameters = [];
147 
148         if ($value_end !== false)
149         {
150             $value = substr($source, 0, $value_end);
151             $attributes = trim(substr($source, $value_end + 1));
152 
153             if ($attributes)
154             {
155                 $a = explode(';', $attributes);
156                 $a = array_map('trim', $a);
157 
158                 foreach ($a as $attribute)
159                 {
160                     $parameter = HeaderParameter::from($attribute);
161                     $parameters[$parameter->attribute] = $parameter;
162                 }
163             }
164         }
165         else
166         {
167             $value = $source;
168         }
169 
170         return [ $value, $parameters ];
171     }
172 
173     /**
174      * Checks if a parameter exists.
175      *
176      * @param string $attribute
177      *
178      * @return bool
179      */
180     public function offsetExists($attribute)
181     {
182         return isset($this->parameters[$attribute]);
183     }
184 
185     /**
186      * Sets the value of a parameter to `null`.
187      *
188      * @param string $attribute
189      */
190     public function offsetUnset($attribute)
191     {
192         $this->parameters[$attribute]->value = null;
193     }
194 
195     /**
196      * Sets the value of a parameter.
197      *
198      * If the value is an instance of {@link HeaderParameter} then the parameter is replaced,
199      * otherwise the value of the current parameter is updated and its language is set to `null`.
200      *
201      * @param string $attribute
202      * @param mixed $value
203      *
204      * @throws OffsetNotDefined in attempt to access a parameter that is not defined.
205      */
206     public function offsetSet($attribute, $value)
207     {
208         if (!$this->offsetExists($attribute))
209         {
210             throw new OffsetNotDefined([ $attribute, $this ]);
211         }
212 
213         if ($value instanceof HeaderParameter)
214         {
215             $this->parameters[$attribute] = $value;
216         }
217         else
218         {
219             $this->parameters[$attribute]->value = $value;
220             $this->parameters[$attribute]->language = null;
221         }
222     }
223 
224     /**
225      * Returns a {@link HeaderParameter} instance.
226      *
227      * @param string $attribute
228      *
229      * @return HeaderParameter
230      *
231      * @throws OffsetNotDefined in attempt to access a parameter that is not defined.
232      */
233     public function offsetGet($attribute)
234     {
235         if (!$this->offsetExists($attribute))
236         {
237             throw new OffsetNotDefined([ $attribute, $this ]);
238         }
239 
240         return $this->parameters[$attribute];
241     }
242 
243     /**
244      * Initializes the {@link $name}, {@link $value} and {@link $parameters} properties.
245      *
246      * To enable future extensions, unrecognized parameters are ignored. Supported parameters must
247      * be defined by a child class before it calls its parent.
248      *
249      * @param string $value
250      * @param array $parameters
251      */
252     public function __construct($value=null, array $parameters=[])
253     {
254         $this->value = $value;
255 
256         $parameters = array_intersect_key($parameters, $this->parameters);
257 
258         foreach ($parameters as $attribute => $value)
259         {
260             $this[$attribute] = $value;
261         }
262     }
263 
264     /**
265      * Returns the value of a defined parameter.
266      *
267      * The method also handles the alias of the {@link $value} property.
268      *
269      * @param string $property
270      *
271      * @throws PropertyNotDefined in attempt to access a parameter that is not defined.
272      *
273      * @return mixed
274      */
275     public function __get($property)
276     {
277         if ($property === static::VALUE_ALIAS)
278         {
279             return $this->value;
280         }
281 
282         if ($this->offsetExists($property))
283         {
284             return $this[$property]->value;
285         }
286 
287         throw new PropertyNotDefined([ $property, $this ]);
288     }
289 
290     /**
291      * Sets the value of a supported parameter.
292      *
293      * The method also handles the alias of the {@link $value} property.
294      *
295      * @param string $property
296      * @param mixed $value
297      *
298      * @throws PropertyNotDefined in attempt to access a parameter that is not defined.
299      */
300     public function __set($property, $value)
301     {
302         if ($property === static::VALUE_ALIAS)
303         {
304             $this->value = $value;
305 
306             return;
307         }
308 
309         if ($this->offsetExists($property))
310         {
311             $this[$property]->value = $value;
312 
313             return;
314         }
315 
316         throw new PropertyNotDefined([ $property, $this ]);
317     }
318 
319     /**
320      * Unsets the matching parameter.
321      *
322      * @param string $property
323      *
324      * @throws PropertyNotDefined in attempt to access a parameter that is not defined.
325      */
326     public function __unset($property)
327     {
328         if (!isset($this->parameters[$property]))
329         {
330             return;
331         }
332 
333         unset($this[$property]);
334     }
335 
336     /**
337      * Renders the instance's value and parameters into a string.
338      *
339      * @return string
340      */
341     public function __toString()
342     {
343         $value = $this->value;
344 
345         if (!$value && $value !== 0)
346         {
347             return '';
348         }
349 
350         foreach ($this->parameters as $attribute)
351         {
352             $rendered_attribute = $attribute->render();
353 
354             if (!$rendered_attribute)
355             {
356                 continue;
357             }
358 
359             $value .= '; ' . $rendered_attribute;
360         }
361 
362         return $value;
363     }
364 }
365 
ICanBoogie/HTTP v2.4.0 API documentation generated by ApiGen