first commit
This commit is contained in:
33
vendor/willdurand/negotiation/CONTRIBUTING.md
vendored
Normal file
33
vendor/willdurand/negotiation/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
First of all, **thank you** for contributing, **you are awesome**!
|
||||
|
||||
Here are a few rules to follow in order to ease code reviews, and discussions before
|
||||
maintainers accept and merge your work.
|
||||
|
||||
You MUST follow the [PSR-1](http://www.php-fig.org/psr/1/) and
|
||||
[PSR-2](http://www.php-fig.org/psr/2/). If you don't know about any of them, you
|
||||
should really read the recommendations. Can't wait? Use the [PHP-CS-Fixer
|
||||
tool](http://cs.sensiolabs.org/).
|
||||
|
||||
You MUST run the test suite.
|
||||
|
||||
You MUST write (or update) unit tests.
|
||||
|
||||
You SHOULD write documentation.
|
||||
|
||||
Please, write [commit messages that make
|
||||
sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
|
||||
and [rebase your branch](http://git-scm.com/book/en/Git-Branching-Rebasing)
|
||||
before submitting your Pull Request.
|
||||
|
||||
One may ask you to [squash your
|
||||
commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html)
|
||||
too. This is used to "clean" your Pull Request before merging it (we don't want
|
||||
commits such as `fix tests`, `fix 2`, `fix 3`, etc.).
|
||||
|
||||
Also, while creating your Pull Request on GitHub, you MUST write a description
|
||||
which gives the context and/or explains why you are creating it.
|
||||
|
||||
Thank you!
|
19
vendor/willdurand/negotiation/LICENSE
vendored
Normal file
19
vendor/willdurand/negotiation/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) William Durand <will+git@drnd.me>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
162
vendor/willdurand/negotiation/README.md
vendored
Normal file
162
vendor/willdurand/negotiation/README.md
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
Negotiation
|
||||
===========
|
||||
|
||||
[](http://travis-ci.org/willdurand/Negotiation)
|
||||
[](https://ci.appveyor.com/project/willdurand/negotiation)
|
||||
[](https://packagist.org/packages/willdurand/Negotiation)
|
||||
[](https://packagist.org/packages/willdurand/Negotiation)
|
||||

|
||||
|
||||
**Negotiation** is a standalone library without any dependencies that allows you
|
||||
to implement [content
|
||||
negotiation](https://tools.ietf.org/html/rfc7231#section-5.3) in your
|
||||
application, whatever framework you use. This library is based on [RFC
|
||||
7231](https://tools.ietf.org/html/rfc7231). Negotiation is easy to use, and
|
||||
extensively unit tested!
|
||||
|
||||
> **Important:** You are browsing the documentation of Negotiation **2.x**.
|
||||
Documentation for version **1.x** is available here: [Negotiation 1.x
|
||||
documentation](https://github.com/willdurand/Negotiation/blob/1.x/README.md#usage).
|
||||
You might also be interested in this: [**What's new in Negotiation 2?**](https://github.com/willdurand/Negotiation/releases/tag/v2.0.0-alpha1)
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The recommended way to install Negotiation is through
|
||||
[Composer](http://getcomposer.org/):
|
||||
|
||||
```bash
|
||||
$ composer require willdurand/negotiation
|
||||
```
|
||||
|
||||
|
||||
Usage Examples
|
||||
--------------
|
||||
|
||||
### Media Type Negotiation
|
||||
|
||||
``` php
|
||||
$negotiator = new \Negotiation\Negotiator();
|
||||
|
||||
$acceptHeader = 'text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8';
|
||||
$priorities = array('text/html; charset=UTF-8', 'application/json', 'application/xml;q=0.5');
|
||||
|
||||
$mediaType = $negotiator->getBest($acceptHeader, $priorities);
|
||||
|
||||
$value = $mediaType->getValue();
|
||||
// $value == 'text/html; charset=UTF-8'
|
||||
```
|
||||
|
||||
The `Negotiator` returns an instance of `Accept`, or `null` if negotiating the
|
||||
best media type has failed.
|
||||
|
||||
### Language Negotiation
|
||||
|
||||
``` php
|
||||
<?php
|
||||
|
||||
$negotiator = new \Negotiation\LanguageNegotiator();
|
||||
|
||||
$acceptLangageHeader = 'en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2';
|
||||
$priorities = array('de', 'fu', 'en');
|
||||
|
||||
$bestLanguage = $negotiator->getBest($acceptLangageHeader, $priorities);
|
||||
|
||||
$type = $bestLanguage->getType();
|
||||
// $type == 'fu';
|
||||
|
||||
$quality = $bestLanguage->getQuality();
|
||||
// $quality == 0.9
|
||||
```
|
||||
|
||||
The `LanguageNegotiator` returns an instance of `AcceptLanguage`.
|
||||
|
||||
### Encoding Negotiation
|
||||
|
||||
``` php
|
||||
<?php
|
||||
|
||||
$negotiator = new \Negotiation\EncodingNegotiator();
|
||||
$encoding = $negotiator->getBest($acceptHeader, $priorities);
|
||||
```
|
||||
|
||||
The `EncodingNegotiator` returns an instance of `AcceptEncoding`.
|
||||
|
||||
### Charset Negotiation
|
||||
|
||||
``` php
|
||||
<?php
|
||||
|
||||
$negotiator = new \Negotiation\CharsetNegotiator();
|
||||
|
||||
$acceptCharsetHeader = 'ISO-8859-1, UTF-8; q=0.9';
|
||||
$priorities = array('iso-8859-1;q=0.3', 'utf-8;q=0.9', 'utf-16;q=1.0');
|
||||
|
||||
$bestCharset = $negotiator->getBest($acceptCharsetHeader, $priorities);
|
||||
|
||||
$type = $bestCharset->getType();
|
||||
// $type == 'utf-8';
|
||||
|
||||
$quality = $bestCharset->getQuality();
|
||||
// $quality == 0.81
|
||||
```
|
||||
|
||||
The `CharsetNegotiator` returns an instance of `AcceptCharset`.
|
||||
|
||||
### `Accept*` Classes
|
||||
|
||||
`Accept` and `Accept*` classes share common methods such as:
|
||||
|
||||
* `getValue()` returns the accept value (e.g. `text/html; z=y; a=b; c=d`)
|
||||
* `getNormalizedValue()` returns the value with parameters sorted (e.g.
|
||||
`text/html; a=b; c=d; z=y`)
|
||||
* `getQuality()` returns the quality if available (`q` parameter)
|
||||
* `getType()` returns the accept type (e.g. `text/html`)
|
||||
* `getParameters()` returns the set of parameters (excluding the `q` parameter
|
||||
if provided)
|
||||
* `getParameter()` allows to retrieve a given parameter by its name. Fallback to
|
||||
a `$default` (nullable) value otherwise.
|
||||
* `hasParameter()` indicates whether a parameter exists.
|
||||
|
||||
|
||||
Unit Tests
|
||||
----------
|
||||
|
||||
Setup the test suite using Composer:
|
||||
|
||||
$ composer install --dev
|
||||
|
||||
Run it using PHPUnit:
|
||||
|
||||
$ phpunit
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
See [CONTRIBUTING](CONTRIBUTING.md) file.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
* Some parts of this library are inspired by:
|
||||
|
||||
* [Symfony](http://github.com/symfony/symfony) framework;
|
||||
* [FOSRest](http://github.com/FriendsOfSymfony/FOSRest);
|
||||
* [PEAR HTTP2](https://github.com/pear/HTTP2).
|
||||
|
||||
* William Durand <will+git@drnd.me>
|
||||
* [@neural-wetware](https://github.com/neural-wetware)
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Negotiation is released under the MIT License. See the bundled LICENSE file for
|
||||
details.
|
118
vendor/willdurand/negotiation/src/Negotiation/AbstractNegotiator.php
vendored
Normal file
118
vendor/willdurand/negotiation/src/Negotiation/AbstractNegotiator.php
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
use Negotiation\Exception\InvalidArgument;
|
||||
use Negotiation\Exception\InvalidHeader;
|
||||
|
||||
abstract class AbstractNegotiator
|
||||
{
|
||||
/**
|
||||
* @param string $header A string containing an `Accept|Accept-*` header.
|
||||
* @param array $priorities A set of server priorities.
|
||||
*
|
||||
* @return AcceptHeader|null best matching type
|
||||
*/
|
||||
public function getBest($header, array $priorities)
|
||||
{
|
||||
if (empty($priorities)) {
|
||||
throw new InvalidArgument('A set of server priorities should be given.');
|
||||
}
|
||||
|
||||
if (!$header) {
|
||||
throw new InvalidArgument('The header string should not be empty.');
|
||||
}
|
||||
|
||||
// Once upon a time, two `array_map` calls were sitting there, but for
|
||||
// some reasons, they triggered `E_WARNING` time to time (because of
|
||||
// PHP bug [55416](https://bugs.php.net/bug.php?id=55416). Now, they
|
||||
// are gone.
|
||||
// See: https://github.com/willdurand/Negotiation/issues/81
|
||||
$acceptedHeaders = array();
|
||||
foreach ($this->parseHeader($header) as $h) {
|
||||
try {
|
||||
$acceptedHeaders[] = $this->acceptFactory($h);
|
||||
} catch (Exception\Exception $e) {
|
||||
// silently skip in case of invalid headers coming in from a client
|
||||
}
|
||||
}
|
||||
$acceptedPriorities = array();
|
||||
foreach ($priorities as $p) {
|
||||
$acceptedPriorities[] = $this->acceptFactory($p);
|
||||
}
|
||||
$matches = $this->findMatches($acceptedHeaders, $acceptedPriorities);
|
||||
$specificMatches = array_reduce($matches, 'Negotiation\Match::reduce', []);
|
||||
|
||||
usort($specificMatches, 'Negotiation\Match::compare');
|
||||
|
||||
$match = array_shift($specificMatches);
|
||||
|
||||
return null === $match ? null : $acceptedPriorities[$match->index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $header accept header part or server priority
|
||||
*
|
||||
* @return AcceptHeader Parsed header object
|
||||
*/
|
||||
abstract protected function acceptFactory($header);
|
||||
|
||||
/**
|
||||
* @param AcceptHeader $header
|
||||
* @param AcceptHeader $priority
|
||||
* @param integer $index
|
||||
*
|
||||
* @return Match|null Headers matched
|
||||
*/
|
||||
protected function match(AcceptHeader $header, AcceptHeader $priority, $index)
|
||||
{
|
||||
$ac = $header->getType();
|
||||
$pc = $priority->getType();
|
||||
|
||||
$equal = !strcasecmp($ac, $pc);
|
||||
|
||||
if ($equal || $ac === '*') {
|
||||
$score = 1 * $equal;
|
||||
|
||||
return new Match($header->getQuality() * $priority->getQuality(), $score, $index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $header A string that contains an `Accept*` header.
|
||||
*
|
||||
* @return AcceptHeader[]
|
||||
*/
|
||||
private function parseHeader($header)
|
||||
{
|
||||
$res = preg_match_all('/(?:[^,"]*+(?:"[^"]*+")?)+[^,"]*+/', $header, $matches);
|
||||
|
||||
if (!$res) {
|
||||
throw new InvalidHeader(sprintf('Failed to parse accept header: "%s"', $header));
|
||||
}
|
||||
|
||||
return array_values(array_filter(array_map('trim', $matches[0])));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AcceptHeader[] $headerParts
|
||||
* @param Priority[] $priorities Configured priorities
|
||||
*
|
||||
* @return Match[] Headers matched
|
||||
*/
|
||||
private function findMatches(array $headerParts, array $priorities)
|
||||
{
|
||||
$matches = [];
|
||||
foreach ($priorities as $index => $p) {
|
||||
foreach ($headerParts as $h) {
|
||||
if (null !== $match = $this->match($h, $p, $index)) {
|
||||
$matches[] = $match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $matches;
|
||||
}
|
||||
}
|
46
vendor/willdurand/negotiation/src/Negotiation/Accept.php
vendored
Normal file
46
vendor/willdurand/negotiation/src/Negotiation/Accept.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
use Negotiation\Exception\InvalidMediaType;
|
||||
|
||||
final class Accept extends BaseAccept implements AcceptHeader
|
||||
{
|
||||
private $basePart;
|
||||
|
||||
private $subPart;
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
parent::__construct($value);
|
||||
|
||||
if ($this->type === '*') {
|
||||
$this->type = '*/*';
|
||||
}
|
||||
|
||||
$parts = explode('/', $this->type);
|
||||
|
||||
if (count($parts) !== 2 || !$parts[0] || !$parts[1]) {
|
||||
throw new InvalidMediaType();
|
||||
}
|
||||
|
||||
$this->basePart = $parts[0];
|
||||
$this->subPart = $parts[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSubPart()
|
||||
{
|
||||
return $this->subPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePart()
|
||||
{
|
||||
return $this->basePart;
|
||||
}
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/AcceptCharset.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/AcceptCharset.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
final class AcceptCharset extends BaseAccept implements AcceptHeader
|
||||
{
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/AcceptEncoding.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/AcceptEncoding.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
final class AcceptEncoding extends BaseAccept implements AcceptHeader
|
||||
{
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/AcceptHeader.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/AcceptHeader.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
interface AcceptHeader
|
||||
{
|
||||
}
|
49
vendor/willdurand/negotiation/src/Negotiation/AcceptLanguage.php
vendored
Normal file
49
vendor/willdurand/negotiation/src/Negotiation/AcceptLanguage.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
use Negotiation\Exception\InvalidLanguage;
|
||||
|
||||
final class AcceptLanguage extends BaseAccept implements AcceptHeader
|
||||
{
|
||||
private $language;
|
||||
private $script;
|
||||
private $region;
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
parent::__construct($value);
|
||||
|
||||
$parts = explode('-', $this->type);
|
||||
|
||||
if (2 === count($parts)) {
|
||||
$this->language = $parts[0];
|
||||
$this->region = $parts[1];
|
||||
} elseif (1 === count($parts)) {
|
||||
$this->language = $parts[0];
|
||||
} elseif (3 === count($parts)) {
|
||||
$this->language = $parts[0];
|
||||
$this->script = $parts[1];
|
||||
$this->region = $parts[2];
|
||||
} else {
|
||||
// TODO: this part is never reached...
|
||||
throw new InvalidLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSubPart()
|
||||
{
|
||||
return $this->region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePart()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
}
|
154
vendor/willdurand/negotiation/src/Negotiation/BaseAccept.php
vendored
Normal file
154
vendor/willdurand/negotiation/src/Negotiation/BaseAccept.php
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
abstract class BaseAccept
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $quality = 1.0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $normalized;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $parameters;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
list($type, $parameters) = $this->parseParameters($value);
|
||||
|
||||
if (isset($parameters['q'])) {
|
||||
$this->quality = (float) $parameters['q'];
|
||||
unset($parameters['q']);
|
||||
}
|
||||
|
||||
$type = trim(strtolower($type));
|
||||
|
||||
$this->value = $value;
|
||||
$this->normalized = $type . ($parameters ? "; " . $this->buildParametersString($parameters) : '');
|
||||
$this->type = $type;
|
||||
$this->parameters = $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNormalizedValue()
|
||||
{
|
||||
return $this->normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getQuality()
|
||||
{
|
||||
return $this->quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getParameter($key, $default = null)
|
||||
{
|
||||
return isset($this->parameters[$key]) ? $this->parameters[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasParameter($key)
|
||||
{
|
||||
return isset($this->parameters[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $acceptPart
|
||||
* @return array
|
||||
*/
|
||||
private function parseParameters($acceptPart)
|
||||
{
|
||||
$parts = explode(';', $acceptPart);
|
||||
$type = array_shift($parts);
|
||||
|
||||
$parameters = [];
|
||||
foreach ($parts as $part) {
|
||||
$part = explode('=', $part);
|
||||
|
||||
if (2 !== count($part)) {
|
||||
continue; // TODO: throw exception here?
|
||||
}
|
||||
|
||||
$key = strtolower(trim($part[0])); // TODO: technically not allowed space around "=". throw exception?
|
||||
$parameters[$key] = trim($part[1], ' "');
|
||||
}
|
||||
|
||||
return [ $type, $parameters ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildParametersString($parameters)
|
||||
{
|
||||
$parts = [];
|
||||
|
||||
ksort($parameters);
|
||||
foreach ($parameters as $key => $val) {
|
||||
$parts[] = sprintf('%s=%s', $key, $val);
|
||||
}
|
||||
|
||||
return implode('; ', $parts);
|
||||
}
|
||||
}
|
14
vendor/willdurand/negotiation/src/Negotiation/CharsetNegotiator.php
vendored
Normal file
14
vendor/willdurand/negotiation/src/Negotiation/CharsetNegotiator.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
class CharsetNegotiator extends AbstractNegotiator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function acceptFactory($accept)
|
||||
{
|
||||
return new AcceptCharset($accept);
|
||||
}
|
||||
}
|
14
vendor/willdurand/negotiation/src/Negotiation/EncodingNegotiator.php
vendored
Normal file
14
vendor/willdurand/negotiation/src/Negotiation/EncodingNegotiator.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
class EncodingNegotiator extends AbstractNegotiator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function acceptFactory($accept)
|
||||
{
|
||||
return new AcceptEncoding($accept);
|
||||
}
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/Exception/Exception.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/Exception/Exception.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation\Exception;
|
||||
|
||||
interface Exception
|
||||
{
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidArgument.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidArgument.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation\Exception;
|
||||
|
||||
class InvalidArgument extends \InvalidArgumentException implements Exception
|
||||
{
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidHeader.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidHeader.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation\Exception;
|
||||
|
||||
class InvalidHeader extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidLanguage.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidLanguage.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation\Exception;
|
||||
|
||||
class InvalidLanguage extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidMediaType.php
vendored
Normal file
7
vendor/willdurand/negotiation/src/Negotiation/Exception/InvalidMediaType.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation\Exception;
|
||||
|
||||
class InvalidMediaType extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
41
vendor/willdurand/negotiation/src/Negotiation/LanguageNegotiator.php
vendored
Normal file
41
vendor/willdurand/negotiation/src/Negotiation/LanguageNegotiator.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
class LanguageNegotiator extends AbstractNegotiator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function acceptFactory($accept)
|
||||
{
|
||||
return new AcceptLanguage($accept);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function match(AcceptHeader $acceptLanguage, AcceptHeader $priority, $index)
|
||||
{
|
||||
if (!$acceptLanguage instanceof AcceptLanguage || !$priority instanceof AcceptLanguage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ab = $acceptLanguage->getBasePart();
|
||||
$pb = $priority->getBasePart();
|
||||
|
||||
$as = $acceptLanguage->getSubPart();
|
||||
$ps = $priority->getSubPart();
|
||||
|
||||
$baseEqual = !strcasecmp($ab, $pb);
|
||||
$subEqual = !strcasecmp($as, $ps);
|
||||
|
||||
if (($ab == '*' || $baseEqual) && ($as === null || $subEqual)) {
|
||||
$score = 10 * $baseEqual + $subEqual;
|
||||
|
||||
return new Match($acceptLanguage->getQuality() * $priority->getQuality(), $score, $index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
62
vendor/willdurand/negotiation/src/Negotiation/Match.php
vendored
Normal file
62
vendor/willdurand/negotiation/src/Negotiation/Match.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
final class Match
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $quality;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $score;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $index;
|
||||
|
||||
public function __construct($quality, $score, $index)
|
||||
{
|
||||
$this->quality = $quality;
|
||||
$this->score = $score;
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Match $a
|
||||
* @param Match $b
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function compare(Match $a, Match $b)
|
||||
{
|
||||
if ($a->quality !== $b->quality) {
|
||||
return $a->quality > $b->quality ? -1 : 1;
|
||||
}
|
||||
|
||||
if ($a->index !== $b->index) {
|
||||
return $a->index > $b->index ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $carry reduced array
|
||||
* @param Match $match match to be reduced
|
||||
*
|
||||
* @return Match[]
|
||||
*/
|
||||
public static function reduce(array $carry, Match $match)
|
||||
{
|
||||
if (!isset($carry[$match->index]) || $carry[$match->index]->score < $match->score) {
|
||||
$carry[$match->index] = $match;
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
}
|
89
vendor/willdurand/negotiation/src/Negotiation/Negotiator.php
vendored
Normal file
89
vendor/willdurand/negotiation/src/Negotiation/Negotiator.php
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Negotiation;
|
||||
|
||||
class Negotiator extends AbstractNegotiator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function acceptFactory($accept)
|
||||
{
|
||||
return new Accept($accept);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function match(AcceptHeader $accept, AcceptHeader $priority, $index)
|
||||
{
|
||||
if (!$accept instanceof Accept || !$priority instanceof Accept) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$acceptBase = $accept->getBasePart();
|
||||
$priorityBase = $priority->getBasePart();
|
||||
|
||||
$acceptSub = $accept->getSubPart();
|
||||
$prioritySub = $priority->getSubPart();
|
||||
|
||||
$intersection = array_intersect_assoc($accept->getParameters(), $priority->getParameters());
|
||||
|
||||
$baseEqual = !strcasecmp($acceptBase, $priorityBase);
|
||||
$subEqual = !strcasecmp($acceptSub, $prioritySub);
|
||||
|
||||
if (($acceptBase === '*' || $baseEqual)
|
||||
&& ($acceptSub === '*' || $subEqual)
|
||||
&& count($intersection) === count($accept->getParameters())
|
||||
) {
|
||||
$score = 100 * $baseEqual + 10 * $subEqual + count($intersection);
|
||||
|
||||
return new Match($accept->getQuality() * $priority->getQuality(), $score, $index);
|
||||
}
|
||||
|
||||
if (!strstr($acceptSub, '+') || !strstr($prioritySub, '+')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Handle "+" segment wildcards
|
||||
list($acceptSub, $acceptPlus) = $this->splitSubPart($acceptSub);
|
||||
list($prioritySub, $priorityPlus) = $this->splitSubPart($prioritySub);
|
||||
|
||||
// If no wildcards in either the subtype or + segment, do nothing.
|
||||
if (!($acceptBase === '*' || $baseEqual)
|
||||
|| !($acceptSub === '*' || $prioritySub === '*' || $acceptPlus === '*' || $priorityPlus === '*')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$subEqual = !strcasecmp($acceptSub, $prioritySub);
|
||||
$plusEqual = !strcasecmp($acceptPlus, $priorityPlus);
|
||||
|
||||
if (($acceptSub === '*' || $prioritySub === '*' || $subEqual)
|
||||
&& ($acceptPlus === '*' || $priorityPlus === '*' || $plusEqual)
|
||||
&& count($intersection) === count($accept->getParameters())
|
||||
) {
|
||||
$score = 100 * $baseEqual + 10 * $subEqual + $plusEqual + count($intersection);
|
||||
|
||||
return new Match($accept->getQuality() * $priority->getQuality(), $score, $index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a subpart into the subpart and "plus" part.
|
||||
*
|
||||
* For media-types of the form "application/vnd.example+json", matching
|
||||
* should allow wildcards for either the portion before the "+" or
|
||||
* after. This method splits the subpart to allow such matching.
|
||||
*/
|
||||
protected function splitSubPart($subPart)
|
||||
{
|
||||
if (!strstr($subPart, '+')) {
|
||||
return [$subPart, ''];
|
||||
}
|
||||
|
||||
return explode('+', $subPart, 2);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user