# AcceptHeader

class AcceptHeader

Represents an Accept-* header.

An accept header is compound with a list of items, sorted by descending quality.

## Methods

`public` | `` | `__construct(array $items)` | No description |
`public static` | `AcceptHeader` | `fromString(string $headerValue)` | Builds an AcceptHeader instance from a string. |
`public` | `string` | `__toString()` | Returns header value's string representation. |
`public` | `bool` | `has(string $value)` | Tests if header has given value. |
`public` | `AcceptHeaderItem|null` | `get(string $value)` | Returns given value's item, if exists. |
`public` | `$this` | `add(AcceptHeaderItem $item)` | Adds an item. |
`public` | `AcceptHeaderItem[]` | `all()` | Returns all items. |
`public` | `AcceptHeader` | `filter(string $pattern)` | Filters items on their value using given regex. |
`public` | `AcceptHeaderItem|null` | `first()` | Returns first item. |

## Details

at line 37

### `__construct()`

`public __construct(array $items)`

#### Parameters

`array` | `$items` |

at line 51

### `fromString()`

`public static AcceptHeader fromString(string $headerValue)`

Builds an AcceptHeader instance from a string.

#### Parameters

`string` | `$headerValue` |

#### Return Value

`AcceptHeader` |

at line 68

### `__toString()`

`public string __toString()`

Returns header value's string representation.

#### Return Value

`string` |

at line 80

### `has()`

`public bool has(string $value)`

Tests if header has given value.

#### Parameters

`string` | `$value` |

#### Return Value

`bool` |

at line 92

### `get()`

`public AcceptHeaderItem|null get(string $value)`

Returns given value's item, if exists.

#### Parameters

`string` | `$value` |

#### Return Value

`AcceptHeaderItem|null` |

at line 102

### `add()`

`public $this add(AcceptHeaderItem $item)`

Adds an item.

#### Parameters

`AcceptHeaderItem` | `$item` |

#### Return Value

`$this` |

at line 115

### `all()`

`public AcceptHeaderItem[] all()`

Returns all items.

#### Return Value

`AcceptHeaderItem[]` |

at line 129

### `filter()`

`public AcceptHeader filter(string $pattern)`

Filters items on their value using given regex.

#### Parameters

`string` | `$pattern` |

#### Return Value

`AcceptHeader` |

at line 141

### `first()`

`public AcceptHeaderItem|null first()`

Returns first item.

#### Return Value

`AcceptHeaderItem|null` |

## Source code

    <?php

    /*
     * This file is part of the Symfony package.
     *
     * (c) Fabien Potencier <fabien@symfony.com>
     *
     * For the full copyright and license information, please view the LICENSE
     * file that was distributed with this source code.
     */

    namespace App\Khan\Component\HttpFoundation;

    /**
     * Represents an Accept-* header.
     *
     * An accept header is compound with a list of items,
     * sorted by descending quality.
     *
     * @author Jean-François Simon <contact@jfsimon.fr>
     */
    class AcceptHeader
    {
        /**
         * @var AcceptHeaderItem[]
         */
        private $items = array();

        /**
         * @var bool
         */
        private $sorted = true;

        /**
         * @param AcceptHeaderItem[] $items
         */
        public function __construct(array $items)
        {
            foreach ($items as $item) {
                $this->add($item);
            }
        }

        /**
         * Builds an AcceptHeader instance from a string.
         *
         * @param string $headerValue
         *
         * @return self
         */
        public static function fromString($headerValue)
        {
            $index = 0;

            return new self(array_map(function ($itemValue) use (&$index) {
                $item = AcceptHeaderItem::fromString($itemValue);
                $item->setIndex($index++);

                return $item;
            }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)));
        }

        /**
         * Returns header value's string representation.
         *
         * @return string
         */
        public function __toString()
        {
            return implode(',', $this->items);
        }

        /**
         * Tests if header has given value.
         *
         * @param string $value
         *
         * @return bool
         */
        public function has($value)
        {
            return isset($this->items[$value]);
        }

        /**
         * Returns given value's item, if exists.
         *
         * @param string $value
         *
         * @return AcceptHeaderItem|null
         */
        public function get($value)
        {
            return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null;
        }

        /**
         * Adds an item.
         *
         * @return $this
         */
        public function add(AcceptHeaderItem $item)
        {
            $this->items[$item->getValue()] = $item;
            $this->sorted = false;

            return $this;
        }

        /**
         * Returns all items.
         *
         * @return AcceptHeaderItem[]
         */
        public function all()
        {
            $this->sort();

            return $this->items;
        }

        /**
         * Filters items on their value using given regex.
         *
         * @param string $pattern
         *
         * @return self
         */
        public function filter($pattern)
        {
            return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) {
                return preg_match($pattern, $item->getValue());
            }));
        }

        /**
         * Returns first item.
         *
         * @return AcceptHeaderItem|null
         */
        public function first()
        {
            $this->sort();

            return !empty($this->items) ? reset($this->items) : null;
        }

        /**
         * Sorts items by descending quality.
         */
        private function sort()
        {
            if (!$this->sorted) {
                uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) {
                    $qA = $a->getQuality();
                    $qB = $b->getQuality();

                    if ($qA === $qB) {
                        return $a->getIndex() > $b->getIndex() ? 1 : -1;
                    }

                    return $qA > $qB ? -1 : 1;
                });

                $this->sorted = true;
            }
        }
    }