File manager - Edit - /var/www/payraty/helpdesk/public/storage/branding_media/images/negotiation.tar
Back
tests/Negotiation/Tests/EncodingNegotiatorTest.php 0000755 00000004560 00000000000 0016374 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\EncodingNegotiator; class EncodingNegotiatorTest extends TestCase { /** * @var EncodingNegotiator */ private $negotiator; protected function setUp(): void { $this->negotiator = new EncodingNegotiator(); } public function testGetBestReturnsNullWithUnmatchedHeader() { $this->assertNull($this->negotiator->getBest('foo, bar, yo', array('baz'))); } /** * @dataProvider dataProviderForTestGetBest */ public function testGetBest($accept, $priorities, $expected) { $accept = $this->negotiator->getBest($accept, $priorities); if (null === $accept) { $this->assertNull($expected); } else { $this->assertInstanceOf('Negotiation\AcceptEncoding', $accept); $this->assertEquals($expected, $accept->getValue()); } } public static function dataProviderForTestGetBest() { return array( array('gzip;q=1.0, identity; q=0.5, *;q=0', array('identity'), 'identity'), array('gzip;q=0.5, identity; q=0.5, *;q=0.7', array('bzip', 'foo'), 'bzip'), array('gzip;q=0.7, identity; q=0.5, *;q=0.7', array('gzip', 'foo'), 'gzip'), # Quality of source factors array('gzip;q=0.7,identity', array('identity;q=0.5', 'gzip;q=0.9'), 'gzip;q=0.9'), ); } public function testGetBestRespectsQualityOfSource() { $accept = $this->negotiator->getBest('gzip;q=0.7,identity', array('identity;q=0.5', 'gzip;q=0.9')); $this->assertInstanceOf('Negotiation\AcceptEncoding', $accept); $this->assertEquals('gzip', $accept->getType()); } /** * @dataProvider dataProviderForTestParseAcceptHeader */ public function testParseAcceptHeader($header, $expected) { $accepts = $this->call_private_method('Negotiation\Negotiator', 'parseHeader', $this->negotiator, array($header)); $this->assertSame($expected, $accepts); } public static function dataProviderForTestParseAcceptHeader() { return array( array('gzip,deflate,sdch', array('gzip', 'deflate', 'sdch')), array("gzip, deflate\t,sdch", array('gzip', 'deflate', 'sdch')), array('gzip;q=1.0, identity; q=0.5, *;q=0', array('gzip;q=1.0', 'identity; q=0.5', '*;q=0')), ); } } tests/Negotiation/Tests/CharsetNegotiatorTest.php 0000755 00000010711 00000000000 0016232 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\CharsetNegotiator; class CharsetNegotiatorTest extends TestCase { /** * @var CharsetNegotiator */ private $negotiator; protected function setUp(): void { $this->negotiator = new CharsetNegotiator(); } public function testGetBestReturnsNullWithUnmatchedHeader() { $this->assertNull($this->negotiator->getBest('foo, bar, yo', array('baz'))); } /** * 'bu' has the highest quality rating, but is non-existent, * so we expect the next highest rated 'fr' content to be returned. * * See: http://svn.apache.org/repos/asf/httpd/test/framework/trunk/t/modules/negotiation.t */ public function testGetBestIgnoresNonExistentContent() { $acceptCharset = 'en; q=0.1, fr; q=0.4, bu; q=1.0'; $accept = $this->negotiator->getBest($acceptCharset, array('en', 'fr')); $this->assertInstanceOf('Negotiation\AcceptCharset', $accept); $this->assertEquals('fr', $accept->getValue()); } /** * @dataProvider dataProviderForTestGetBest */ public function testGetBest($accept, $priorities, $expected) { if (is_null($expected)) $this->expectException('Negotiation\Exception\InvalidArgument'); $accept = $this->negotiator->getBest($accept, $priorities); if (null === $accept) { $this->assertNull($expected); } else { $this->assertInstanceOf('Negotiation\AcceptCharset', $accept); $this->assertSame($expected, $accept->getValue()); } } public static function dataProviderForTestGetBest() { $pearCharset = 'ISO-8859-1, Big5;q=0.6,utf-8;q=0.7, *;q=0.5'; $pearCharset2 = 'ISO-8859-1, Big5;q=0.6,utf-8;q=0.7'; return array( array($pearCharset, array( 'utf-8', 'big5', 'iso-8859-1', 'shift-jis',), 'iso-8859-1'), array($pearCharset, array( 'utf-8', 'big5', 'shift-jis',), 'utf-8'), array($pearCharset, array( 'Big5', 'shift-jis',), 'Big5'), array($pearCharset, array( 'shift-jis',), 'shift-jis'), array($pearCharset2, array( 'utf-8', 'big5', 'iso-8859-1', 'shift-jis',), 'iso-8859-1'), array($pearCharset2, array( 'utf-8', 'big5', 'shift-jis',), 'utf-8'), array($pearCharset2, array( 'Big5', 'shift-jis',), 'Big5'), array('utf-8;q=0.6,iso-8859-5;q=0.9', array( 'iso-8859-5', 'utf-8',), 'iso-8859-5'), array('', array( 'iso-8859-5', 'utf-8',), null), array('en, *;q=0.9', array('fr'), 'fr'), # Quality of source factors array($pearCharset, array('iso-8859-1;q=0.5', 'utf-8', 'utf-16;q=1.0'), 'utf-8'), array($pearCharset, array('iso-8859-1;q=0.8', 'utf-8', 'utf-16;q=1.0'), 'iso-8859-1;q=0.8'), ); } public function testGetBestRespectsPriorities() { $accept = $this->negotiator->getBest('foo, bar, yo', array('yo')); $this->assertInstanceOf('Negotiation\AcceptCharset', $accept); $this->assertEquals('yo', $accept->getValue()); } public function testGetBestDoesNotMatchPriorities() { $acceptCharset = 'en, de'; $priorities = array('fr'); $this->assertNull($this->negotiator->getBest($acceptCharset, $priorities)); } public function testGetBestRespectsQualityOfSource() { $accept = $this->negotiator->getBest('utf-8;q=0.5,iso-8859-1', array('iso-8859-1;q=0.3', 'utf-8;q=0.9', 'utf-16;q=1.0')); $this->assertInstanceOf('Negotiation\AcceptCharset', $accept); $this->assertEquals('utf-8', $accept->getType()); } /** * @dataProvider dataProviderForTestParseHeader */ public function testParseHeader($header, $expected) { $accepts = $this->call_private_method('Negotiation\CharsetNegotiator', 'parseHeader', $this->negotiator, array($header)); $this->assertSame($expected, $accepts); } public static function dataProviderForTestParseHeader() { return array( array('*;q=0.3,ISO-8859-1,utf-8;q=0.7', array('*;q=0.3', 'ISO-8859-1', 'utf-8;q=0.7')), array('*;q=0.3,ISO-8859-1;q=0.7,utf-8;q=0.7', array('*;q=0.3', 'ISO-8859-1;q=0.7', 'utf-8;q=0.7')), array('*;q=0.3,utf-8;q=0.7,ISO-8859-1;q=0.7', array('*;q=0.3', 'utf-8;q=0.7', 'ISO-8859-1;q=0.7')), array('iso-8859-5, unicode-1-1;q=0.8', array('iso-8859-5', 'unicode-1-1;q=0.8')), ); } } tests/Negotiation/Tests/NegotiatorTest.php 0000755 00000030707 00000000000 0014727 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\Exception\InvalidArgument; use Negotiation\Exception\InvalidMediaType; use Negotiation\Negotiator; use Negotiation\Accept; use Negotiation\AcceptMatch; class NegotiatorTest extends TestCase { /** * @var Negotiator */ private $negotiator; protected function setUp(): void { $this->negotiator = new Negotiator(); } /** * @dataProvider dataProviderForTestGetBest */ public function testGetBest($header, $priorities, $expected) { try { $acceptHeader = $this->negotiator->getBest($header, $priorities); } catch (\Exception $e) { $this->assertEquals($expected, $e); return; } if ($acceptHeader === null) { $this->assertNull($expected); return; } $this->assertInstanceOf('Negotiation\Accept', $acceptHeader); $this->assertSame($expected[0], $acceptHeader->getType()); $this->assertSame($expected[1], $acceptHeader->getParameters()); } public static function dataProviderForTestGetBest() { $pearAcceptHeader = 'text/html,application/xhtml+xml,application/xml;q=0.9,text/*;q=0.7,*/*,image/gif; q=0.8, image/jpeg; q=0.6, image/*'; $rfcHeader = 'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5'; return array( # exceptions array('/qwer', array('f/g'), null), array('/qwer,f/g', array('f/g'), array('f/g', array())), array('foo/bar', array('/qwer'), new InvalidMediaType()), array('', array('foo/bar'), new InvalidArgument('The header string should not be empty.')), array('*/*', array(), new InvalidArgument('A set of server priorities should be given.')), # See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html array($rfcHeader, array('text/html;level=1'), array('text/html', array('level' => '1'))), array($rfcHeader, array('text/html'), array('text/html', array())), array($rfcHeader, array('text/plain'), array('text/plain', array())), array($rfcHeader, array('image/jpeg',), array('image/jpeg', array())), array($rfcHeader, array('text/html;level=2'), array('text/html', array('level' => '2'))), array($rfcHeader, array('text/html;level=3'), array('text/html', array( 'level' => '3'))), array('text/*;q=0.7, text/html;q=0.3, */*;q=0.5, image/png;q=0.4', array('text/html', 'image/png'), array('image/png', array())), array('image/png;q=0.1, text/plain, audio/ogg;q=0.9', array('image/png', 'text/plain', 'audio/ogg'), array('text/plain', array())), array('image/png, text/plain, audio/ogg', array('baz/asdf'), null), array('image/png, text/plain, audio/ogg', array('audio/ogg'), array('audio/ogg', array())), array('image/png, text/plain, audio/ogg', array('YO/SuP'), null), array('text/html; charset=UTF-8, application/pdf', array('text/html; charset=UTF-8'), array('text/html', array('charset' => 'UTF-8'))), array('text/html; charset=UTF-8, application/pdf', array('text/html'), null), array('text/html, application/pdf', array('text/html; charset=UTF-8'), array('text/html', array('charset' => 'UTF-8'))), # PEAR HTTP2 tests - have been altered from original! array($pearAcceptHeader, array('image/gif', 'image/png', 'application/xhtml+xml', 'application/xml', 'text/html', 'image/jpeg', 'text/plain',), array('image/png', array())), array($pearAcceptHeader, array('image/gif', 'application/xhtml+xml', 'application/xml', 'image/jpeg', 'text/plain',), array('application/xhtml+xml', array())), array($pearAcceptHeader, array('image/gif', 'application/xml', 'image/jpeg', 'text/plain',), array('application/xml', array())), array($pearAcceptHeader, array('image/gif', 'image/jpeg', 'text/plain'), array('image/gif', array())), array($pearAcceptHeader, array('text/plain', 'image/png', 'image/jpeg'), array('image/png', array())), array($pearAcceptHeader, array('image/jpeg', 'image/gif',), array('image/gif', array())), array($pearAcceptHeader, array('image/png',), array('image/png', array())), array($pearAcceptHeader, array('audio/midi',), array('audio/midi', array())), array('text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', array( 'application/rss+xml'), array('application/rss+xml', array())), # LWS / case sensitivity array('text/* ; q=0.3, TEXT/html ;Q=0.7, text/html ; level=1, texT/Html ;leVel = 2 ;q=0.4, */* ; q=0.5', array( 'text/html; level=2'), array('text/html', array( 'level' => '2'))), array('text/* ; q=0.3, text/html;Q=0.7, text/html ;level=1, text/html; level=2;q=0.4, */*;q=0.5', array( 'text/HTML; level=3'), array('text/html', array( 'level' => '3'))), # Incompatible array('text/html', array( 'application/rss'), null), # IE8 Accept header array('image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, */*', array( 'text/html', 'application/xhtml+xml'), array('text/html', array())), # Quality of source factors array($rfcHeader, array('text/html;q=0.4', 'text/plain'), array('text/plain', array())), # Wildcard "plus" parts (e.g., application/vnd.api+json) array('application/vnd.api+json', array('application/json', 'application/*+json'), array('application/*+json', array())), array('application/json;q=0.7, application/*+json;q=0.7', array('application/hal+json', 'application/problem+json'), array('application/hal+json', array())), array('application/json;q=0.7, application/problem+*;q=0.7', array('application/hal+xml', 'application/problem+xml'), array('application/problem+xml', array())), array($pearAcceptHeader, array('application/*+xml'), array('application/*+xml', array())), # @see https://github.com/willdurand/Negotiation/issues/93 array('application/hal+json', array('application/ld+json', 'application/hal+json', 'application/xml', 'text/xml', 'application/json', 'text/html'), array('application/hal+json', array())), ); } /** * @dataProvider dataProviderForTestGetOrderedElements */ public function testGetOrderedElements($header, $expected) { try { $elements = $this->negotiator->getOrderedElements($header); } catch (\Exception $e) { $this->assertEquals($expected, $e); return; } if (empty($elements)) { $this->assertNull($expected); return; } $this->assertInstanceOf('Negotiation\Accept', $elements[0]); foreach ($expected as $key => $item) { $this->assertSame($item, $elements[$key]->getValue()); } } public static function dataProviderForTestGetOrderedElements() { return array( // error cases array('', new InvalidArgument('The header string should not be empty.')), array('/qwer', null), // first one wins as no quality modifiers array('text/html, text/xml', array('text/html', 'text/xml')), // ordered by quality modifier array( 'text/html;q=0.3, text/html;q=0.7', array('text/html;q=0.7', 'text/html;q=0.3') ), // ordered by quality modifier - the one with no modifier wins, level not taken into account array( 'text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5', array('text/html;level=1', 'text/html;q=0.7', '*/*;q=0.5', 'text/html;level=2;q=0.4', 'text/*;q=0.3') ), ); } public function testGetBestRespectsQualityOfSource() { $accept = $this->negotiator->getBest('text/html,text/*;q=0.7', array('text/html;q=0.5', 'text/plain;q=0.9')); $this->assertInstanceOf('Negotiation\Accept', $accept); $this->assertEquals('text/plain', $accept->getType()); } public function testGetBestInvalidMediaType() { $this->expectException(\Negotiation\Exception\InvalidMediaType::class); $header = 'sdlfkj20ff; wdf'; $priorities = array('foo/qwer'); $this->negotiator->getBest($header, $priorities, true); } /** * @dataProvider dataProviderForTestParseHeader */ public function testParseHeader($header, $expected) { $accepts = $this->call_private_method('Negotiation\Negotiator', 'parseHeader', $this->negotiator, array($header)); $this->assertSame($expected, $accepts); } public static function dataProviderForTestParseHeader() { return array( array('text/html ; q=0.9', array('text/html ; q=0.9')), array('text/html,application/xhtml+xml', array('text/html', 'application/xhtml+xml')), array(',,text/html;q=0.8 , , ', array('text/html;q=0.8')), array('text/html;charset=utf-8; q=0.8', array('text/html;charset=utf-8; q=0.8')), array('text/html; foo="bar"; q=0.8 ', array('text/html; foo="bar"; q=0.8')), array('text/html; foo="bar"; qwer="asdf", image/png', array('text/html; foo="bar"; qwer="asdf"', "image/png")), array('text/html ; quoted_comma="a,b ,c,",application/xml;q=0.9,*/*;charset=utf-8; q=0.8', array('text/html ; quoted_comma="a,b ,c,"', 'application/xml;q=0.9', '*/*;charset=utf-8; q=0.8')), array('text/html, application/json;q=0.8, text/csv;q=0.7', array('text/html', 'application/json;q=0.8', 'text/csv;q=0.7')) ); } /** * @dataProvider dataProviderForTestFindMatches */ public function testFindMatches($headerParts, $priorities, $expected) { $neg = new Negotiator(); $matches = $this->call_private_method('Negotiation\Negotiator', 'findMatches', $neg, array($headerParts, $priorities)); $this->assertEquals($expected, $matches); } public static function dataProviderForTestFindMatches() { return array( array( array(new Accept('text/html; charset=UTF-8'), new Accept('image/png; foo=bar; q=0.7'), new Accept('*/*; foo=bar; q=0.4')), array(new Accept('text/html; charset=UTF-8'), new Accept('image/png; foo=bar'), new Accept('application/pdf')), array( new AcceptMatch(1.0, 111, 0), new AcceptMatch(0.7, 111, 1), new AcceptMatch(0.4, 1, 1), ) ), array( array(new Accept('text/html'), new Accept('image/*; q=0.7')), array(new Accept('text/html; asfd=qwer'), new Accept('image/png'), new Accept('application/pdf')), array( new AcceptMatch(1.0, 110, 0), new AcceptMatch(0.7, 100, 1), ) ), array( # https://tools.ietf.org/html/rfc7231#section-5.3.2 array(new Accept('text/*; q=0.3'), new Accept('text/html; q=0.7'), new Accept('text/html; level=1'), new Accept('text/html; level=2; q=0.4'), new Accept('*/*; q=0.5')), array(new Accept('text/html; level=1'), new Accept('text/html'), new Accept('text/plain'), new Accept('image/jpeg'), new Accept('text/html; level=2'), new Accept('text/html; level=3')), array( new AcceptMatch(0.3, 100, 0), new AcceptMatch(0.7, 110, 0), new AcceptMatch(1.0, 111, 0), new AcceptMatch(0.5, 0, 0), new AcceptMatch(0.3, 100, 1), new AcceptMatch(0.7, 110, 1), new AcceptMatch(0.5, 0, 1), new AcceptMatch(0.3, 100, 2), new AcceptMatch(0.5, 0, 2), new AcceptMatch(0.5, 0, 3), new AcceptMatch(0.3, 100, 4), new AcceptMatch(0.7, 110, 4), new AcceptMatch(0.4, 111, 4), new AcceptMatch(0.5, 0, 4), new AcceptMatch(0.3, 100, 5), new AcceptMatch(0.7, 110, 5), new AcceptMatch(0.5, 0, 5), ) ) ); } } tests/Negotiation/Tests/AcceptLanguageTest.php 0000755 00000002267 00000000000 0015457 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\AcceptLanguage; class AcceptLanguageTest extends TestCase { /** * @dataProvider dataProviderForGetType */ public function testGetType($header, $expected) { $accept = new AcceptLanguage($header); $actual = $accept->getType(); $this->assertEquals($expected, $actual); } public static function dataProviderForGetType() { return array( array('en;q=0.7', 'en'), array('en-GB;q=0.8', 'en-gb'), array('da', 'da'), array('en-gb;q=0.8', 'en-gb'), array('es;q=0.7', 'es'), array('fr ; q= 0.1', 'fr'), array('', null), array(null, null), ); } /** * @dataProvider dataProviderForGetValue */ public function testGetValue($header, $expected) { $accept = new AcceptLanguage($header); $actual = $accept->getValue(); $this->assertEquals($expected, $actual); } public static function dataProviderForGetValue() { return array( array('en;q=0.7', 'en;q=0.7'), array('en-GB;q=0.8', 'en-GB;q=0.8'), ); } } tests/Negotiation/Tests/BaseAcceptTest.php 0000755 00000004215 00000000000 0014601 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\BaseAccept; class BaseAcceptTest extends TestCase { /** * @dataProvider dataProviderForParseParameters */ public function testParseParameters($value, $expected) { $accept = new DummyAccept($value); $parameters = $accept->getParameters(); // TODO: hack-ish... this is needed because logic in BaseAccept //constructor drops the quality from the parameter set. if (false !== strpos($value, 'q')) { $parameters['q'] = $accept->getQuality(); } $this->assertCount(count($expected), $parameters); foreach ($expected as $key => $value) { $this->assertArrayHasKey($key, $parameters); $this->assertEquals($value, $parameters[$key]); } } public static function dataProviderForParseParameters() { return array( array( 'application/json ;q=1.0; level=2;foo= bar', array( 'q' => 1.0, 'level' => 2, 'foo' => 'bar', ), ), array( 'application/json ;q = 1.0; level = 2; FOO = bAr', array( 'q' => 1.0, 'level' => 2, 'foo' => 'bAr', ), ), array( 'application/json;q=1.0', array( 'q' => 1.0, ), ), array( 'application/json;foo', array(), ), ); } /** * @dataProvider dataProviderBuildParametersString */ public function testBuildParametersString($value, $expected) { $accept = new DummyAccept($value); $this->assertEquals($expected, $accept->getNormalizedValue()); } public static function dataProviderBuildParametersString() { return array( array('media/type; xxx = 1.0;level=2;foo=bar', 'media/type; foo=bar; level=2; xxx=1.0'), ); } } class DummyAccept extends BaseAccept { } tests/Negotiation/Tests/TestCase.php 0000755 00000000577 00000000000 0013471 0 ustar 00 <?php namespace Negotiation\Tests; use PHPUnit\Framework\TestCase as PHPUnitTestCase; abstract class TestCase extends PHPUnitTestCase { protected function call_private_method($class, $method, $object, $params) { $method = new \ReflectionMethod($class, $method); $method->setAccessible(true); return $method->invokeArgs($object, $params); } } tests/Negotiation/Tests/AcceptTest.php 0000755 00000005177 00000000000 0014016 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\Accept; class AcceptTest extends TestCase { public function testGetParameter() { $accept = new Accept('foo/bar; q=1; hello=world'); $this->assertTrue($accept->hasParameter('hello')); $this->assertEquals('world', $accept->getParameter('hello')); $this->assertFalse($accept->hasParameter('unknown')); $this->assertNull($accept->getParameter('unknown')); $this->assertFalse($accept->getParameter('unknown', false)); $this->assertSame('world', $accept->getParameter('hello', 'goodbye')); } /** * @dataProvider dataProviderForTestGetNormalizedValue */ public function testGetNormalizedValue($header, $expected) { $accept = new Accept($header); $actual = $accept->getNormalizedValue(); $this->assertEquals($expected, $actual); } public static function dataProviderForTestGetNormalizedValue() { return array( array('text/html; z=y; a=b; c=d', 'text/html; a=b; c=d; z=y'), array('application/pdf; q=1; param=p', 'application/pdf; param=p') ); } /** * @dataProvider dataProviderForGetType */ public function testGetType($header, $expected) { $accept = new Accept($header); $actual = $accept->getType(); $this->assertEquals($expected, $actual); } public static function dataProviderForGetType() { return array( array('text/html;hello=world', 'text/html'), array('application/pdf', 'application/pdf'), array('application/xhtml+xml;q=0.9', 'application/xhtml+xml'), array('text/plain; q=0.5', 'text/plain'), array('text/html;level=2;q=0.4', 'text/html'), array('text/html ; level = 2 ; q = 0.4', 'text/html'), array('text/*', 'text/*'), array('text/* ;q=1 ;level=2', 'text/*'), array('*/*', '*/*'), array('*', '*/*'), array('*/* ; param=555', '*/*'), array('* ; param=555', '*/*'), array('TEXT/hTmL;leVel=2; Q=0.4', 'text/html'), ); } /** * @dataProvider dataProviderForGetValue */ public function testGetValue($header, $expected) { $accept = new Accept($header); $actual = $accept->getValue(); $this->assertEquals($expected, $actual); } public static function dataProviderForGetValue() { return array( array('text/html;hello=world ;q=0.5', 'text/html;hello=world ;q=0.5'), array('application/pdf', 'application/pdf'), ); } } tests/Negotiation/Tests/LanguageNegotiatorTest.php 0000755 00000006762 00000000000 0016377 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\Exception\InvalidArgument; use Negotiation\LanguageNegotiator; class LanguageNegotiatorTest extends TestCase { /** * @var LanguageNegotiator */ private $negotiator; protected function setUp(): void { $this->negotiator = new LanguageNegotiator(); } /** * @dataProvider dataProviderForTestGetBest */ public function testGetBest($accept, $priorities, $expected) { try { $accept = $this->negotiator->getBest($accept, $priorities); if (null === $accept) { $this->assertNull($expected); } else { $this->assertInstanceOf('Negotiation\AcceptLanguage', $accept); $this->assertEquals($expected, $accept->getValue()); } } catch (\Exception $e) { $this->assertEquals($expected, $e); } } public static function dataProviderForTestGetBest() { return array( array('en, de', array('fr'), null), array('foo, bar, yo', array('baz', 'biz'), null), array('fr-FR, en;q=0.8', array('en-US', 'de-DE'), 'en-US'), array('en, *;q=0.9', array('fr'), 'fr'), array('foo, bar, yo', array('yo'), 'yo'), array('en; q=0.1, fr; q=0.4, bu; q=1.0', array('en', 'fr'), 'fr'), array('en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2', array('en', 'fu'), 'fu'), array('', array('en', 'fu'), new InvalidArgument('The header string should not be empty.')), array('fr, zh-Hans-CN;q=0.3', array('fr'), 'fr'), # Quality of source factors array('en;q=0.5,de', array('de;q=0.3', 'en;q=0.9'), 'en;q=0.9'), # Generic fallback array('fr-FR, en-US;q=0.8', array('fr'), 'fr'), array('fr-FR, en-US;q=0.8', array('fr', 'en-US'), 'fr'), array('fr-FR, en-US;q=0.8', array('fr-CA', 'en'), 'en'), ); } public function testGetBestRespectsQualityOfSource() { $accept = $this->negotiator->getBest('en;q=0.5,de', array('de;q=0.3', 'en;q=0.9')); $this->assertInstanceOf('Negotiation\AcceptLanguage', $accept); $this->assertEquals('en', $accept->getType()); } /** * @dataProvider dataProviderForTestParseHeader */ public function testParseHeader($header, $expected) { $accepts = $this->call_private_method('Negotiation\Negotiator', 'parseHeader', $this->negotiator, array($header)); $this->assertSame($expected, $accepts); } public static function dataProviderForTestParseHeader() { return array( array('en; q=0.1, fr; q=0.4, bu; q=1.0', array('en; q=0.1', 'fr; q=0.4', 'bu; q=1.0')), array('en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2', array('en; q=0.1', 'fr; q=0.4', 'fu; q=0.9', 'de; q=0.2')), ); } /** * Given a accept header containing specific languages (here 'en-US', 'fr-FR') * And priorities containing a generic version of that language * Then the best language is mapped to the generic one here 'fr' */ public function testSpecificLanguageAreMappedToGeneric() { $acceptLanguageHeader = 'fr-FR, en-US;q=0.8'; $priorities = array('fr'); $acceptHeader = $this->negotiator->getBest($acceptLanguageHeader, $priorities); $this->assertInstanceOf('Negotiation\AcceptHeader', $acceptHeader); $this->assertEquals('fr', $acceptHeader->getValue()); } } tests/Negotiation/Tests/MatchTest.php 0000755 00000003363 00000000000 0013646 0 ustar 00 <?php namespace Negotiation\Tests; use Negotiation\AcceptMatch; class MatchTest extends TestCase { /** * @dataProvider dataProviderForTestCompare */ public function testCompare($match1, $match2, $expected) { $this->assertEquals($expected, AcceptMatch::compare($match1, $match2)); } public static function dataProviderForTestCompare() { return array( array(new AcceptMatch(1.0, 110, 1), new AcceptMatch(1.0, 111, 1), 0), array(new AcceptMatch(0.1, 10, 1), new AcceptMatch(0.1, 10, 2), -1), array(new AcceptMatch(0.5, 110, 5), new AcceptMatch(0.5, 11, 4), 1), array(new AcceptMatch(0.4, 110, 1), new AcceptMatch(0.6, 111, 3), 1), array(new AcceptMatch(0.6, 110, 1), new AcceptMatch(0.4, 111, 3), -1), ); } /** * @dataProvider dataProviderForTestReduce */ public function testReduce($carry, $match, $expected) { $this->assertEquals($expected, AcceptMatch::reduce($carry, $match)); } public static function dataProviderForTestReduce() { return array( array( array(1 => new AcceptMatch(1.0, 10, 1)), new AcceptMatch(0.5, 111, 1), array(1 => new AcceptMatch(0.5, 111, 1)), ), array( array(1 => new AcceptMatch(1.0, 110, 1)), new AcceptMatch(0.5, 11, 1), array(1 => new AcceptMatch(1.0, 110, 1)), ), array( array(0 => new AcceptMatch(1.0, 10, 1)), new AcceptMatch(0.5, 111, 1), array(0 => new AcceptMatch(1.0, 10, 1), 1 => new AcceptMatch(0.5, 111, 1)), ), ); } } tests/bootstrap.php 0000755 00000000534 00000000000 0010402 0 ustar 00 <?php if (! ($loader = @include __DIR__ . '/../vendor/autoload.php')) { die(<<<EOT You need to install the project dependencies using Composer: $ wget http://getcomposer.org/composer.phar OR $ curl -s https://getcomposer.org/installer | php $ php composer.phar install --dev $ phpunit EOT ); } $loader->add('Negotiation\Tests', __DIR__); README.md 0000755 00000012340 00000000000 0005767 0 ustar 00 Negotiation =========== [](https://github.com/willdurand/Negotiation/actions?query=workflow%3A%22ci%22+branch%3Amaster) [](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 **3.x**+. > > Documentation for version **1.x** is available here: [Negotiation 1.x > documentation](https://github.com/willdurand/Negotiation/blob/1.x/README.md#usage). > > Documentation for version **2.x** is available here: [Negotiation 2.x > documentation](https://github.com/willdurand/Negotiation/blob/2.x/README.md#usage). 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(); $acceptLanguageHeader = 'en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2'; $priorities = array('de', 'fu', 'en'); $bestLanguage = $negotiator->getBest($acceptLanguageHeader, $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. Versioning ---------- Negotiation follows [Semantic Versioning](http://semver.org/). ### End Of Life #### 1.x As of October 2016, [branch `1.x`](https://github.com/willdurand/Negotiation/tree/1.x) is not supported anymore, meaning major version `1` reached end of life. Last version is: [1.5.0](https://github.com/willdurand/Negotiation/releases/tag/1.5.0). #### 2.x As of November 2020, [branch `2.x`](https://github.com/willdurand/Negotiation/tree/2.x) is not supported anymore, meaning major version `2` reached end of life. Last version is: [2.3.1](https://github.com/willdurand/Negotiation/releases/tag/v2.3.1). ### Stable Version #### 3.x (and `dev-master`) Negotiation [3.0](https://github.com/willdurand/Negotiation/releases/tag/3.0.0) has been released on November 26th, 2020. This is the **current stable version** and it is in sync with the main branch (a.k.a. `master`). 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](https://github.com/willdurand) * [@neural-wetware](https://github.com/neural-wetware) License ------- Negotiation is released under the MIT License. See the bundled LICENSE file for details. src/Negotiation/AcceptMatch.php 0000755 00000002256 00000000000 0012451 0 ustar 00 <?php namespace Negotiation; final class AcceptMatch { /** * @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 AcceptMatch $a * @param AcceptMatch $b * * @return int */ public static function compare(AcceptMatch $a, AcceptMatch $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 AcceptMatch $match match to be reduced * * @return AcceptMatch[] */ public static function reduce(array $carry, AcceptMatch $match) { if (!isset($carry[$match->index]) || $carry[$match->index]->score < $match->score) { $carry[$match->index] = $match; } return $carry; } } src/Negotiation/Exception/InvalidHeader.php 0000755 00000000160 00000000000 0014722 0 ustar 00 <?php namespace Negotiation\Exception; class InvalidHeader extends \RuntimeException implements Exception { } src/Negotiation/Exception/InvalidMediaType.php 0000755 00000000163 00000000000 0015416 0 ustar 00 <?php namespace Negotiation\Exception; class InvalidMediaType extends \RuntimeException implements Exception { } src/Negotiation/Exception/InvalidArgument.php 0000755 00000000172 00000000000 0015317 0 ustar 00 <?php namespace Negotiation\Exception; class InvalidArgument extends \InvalidArgumentException implements Exception { } src/Negotiation/Exception/InvalidLanguage.php 0000755 00000000162 00000000000 0015257 0 ustar 00 <?php namespace Negotiation\Exception; class InvalidLanguage extends \RuntimeException implements Exception { } src/Negotiation/Exception/Exception.php 0000755 00000000101 00000000000 0014154 0 ustar 00 <?php namespace Negotiation\Exception; interface Exception { } src/Negotiation/CharsetNegotiator.php 0000755 00000000340 00000000000 0013712 0 ustar 00 <?php namespace Negotiation; class CharsetNegotiator extends AbstractNegotiator { /** * {@inheritdoc} */ protected function acceptFactory($accept) { return new AcceptCharset($accept); } } src/Negotiation/LanguageNegotiator.php 0000755 00000002063 00000000000 0014050 0 ustar 00 <?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((string)$ab, (string)$pb); $subEqual = !strcasecmp((string)$as, (string)$ps); if (($ab == '*' || $baseEqual) && ($as === null || $subEqual || null === $ps)) { $score = 10 * $baseEqual + $subEqual; return new AcceptMatch($acceptLanguage->getQuality() * $priority->getQuality(), $score, $index); } return null; } } src/Negotiation/AcceptCharset.php 0000755 00000000150 00000000000 0012775 0 ustar 00 <?php namespace Negotiation; final class AcceptCharset extends BaseAccept implements AcceptHeader { } src/Negotiation/AbstractNegotiator.php 0000755 00000012000 00000000000 0014060 0 ustar 00 <?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, $strict = false) { 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) { if ($strict) { throw $e; } } } $acceptedPriorities = array(); foreach ($priorities as $p) { $acceptedPriorities[] = $this->acceptFactory($p); } $matches = $this->findMatches($acceptedHeaders, $acceptedPriorities); $specificMatches = array_reduce($matches, 'Negotiation\AcceptMatch::reduce', []); usort($specificMatches, 'Negotiation\AcceptMatch::compare'); $match = array_shift($specificMatches); return null === $match ? null : $acceptedPriorities[$match->index]; } /** * @param string $header A string containing an `Accept|Accept-*` header. * * @return AcceptHeader[] An ordered list of accept header elements */ public function getOrderedElements($header) { if (!$header) { throw new InvalidArgument('The header string should not be empty.'); } $elements = array(); $orderKeys = array(); foreach ($this->parseHeader($header) as $key => $h) { try { $element = $this->acceptFactory($h); $elements[] = $element; $orderKeys[] = [$element->getQuality(), $key, $element->getValue()]; } catch (Exception\Exception $e) { // silently skip in case of invalid headers coming in from a client } } // sort based on quality and then original order. This is necessary as // to ensure that the first in the list for two items with the same // quality stays in that order in both PHP5 and PHP7. uasort($orderKeys, function ($a, $b) { $qA = $a[0]; $qB = $b[0]; if ($qA == $qB) { return $a[1] <=> $b[1]; } return ($qA > $qB) ? -1 : 1; }); $orderedElements = []; foreach ($orderKeys as $key) { $orderedElements[] = $elements[$key[1]]; } return $orderedElements; } /** * @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 AcceptMatch|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 AcceptMatch($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 AcceptMatch[] 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; } } src/Negotiation/AcceptHeader.php 0000755 00000000072 00000000000 0012577 0 ustar 00 <?php namespace Negotiation; interface AcceptHeader { } src/Negotiation/EncodingNegotiator.php 0000755 00000000342 00000000000 0014051 0 ustar 00 <?php namespace Negotiation; class EncodingNegotiator extends AbstractNegotiator { /** * {@inheritdoc} */ protected function acceptFactory($accept) { return new AcceptEncoding($accept); } } src/Negotiation/BaseAccept.php 0000755 00000005715 00000000000 0012272 0 ustar 00 <?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|null $acceptPart * @return array */ private function parseParameters($acceptPart) { if ($acceptPart === null) { return ['', []]; } $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); } } src/Negotiation/AcceptEncoding.php 0000755 00000000151 00000000000 0013133 0 ustar 00 <?php namespace Negotiation; final class AcceptEncoding extends BaseAccept implements AcceptHeader { } src/Negotiation/Accept.php 0000755 00000001471 00000000000 0011472 0 ustar 00 <?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; } } src/Negotiation/Negotiator.php 0000755 00000005501 00000000000 0012404 0 ustar 00 <?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 AcceptMatch($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 AcceptMatch($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); } } src/Negotiation/AcceptLanguage.php 0000755 00000002047 00000000000 0013136 0 ustar 00 <?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; } } .github/workflows/ci.yaml 0000755 00000001220 00000000000 0011357 0 ustar 00 name: ci on: pull_request: push: branches: - master jobs: phpunit: runs-on: "ubuntu-20.04" strategy: fail-fast: false matrix: php-version: - "7.4" - "8.0" - "8.1" steps: - uses: actions/checkout@v2 - name: "Install PHP ${{ matrix.php-version }}" uses: "shivammathur/setup-php@v2" with: php-version: "${{ matrix.php-version }}" coverage: "pcov" - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v1" - name: "Run PHPUnit" run: "vendor/bin/simple-phpunit --coverage-text" composer.json 0000755 00000001440 00000000000 0007231 0 ustar 00 { "name": "willdurand/negotiation", "description": "Content Negotiation tools for PHP provided as a standalone library.", "keywords": [ "content", "negotiation", "format", "accept", "header" ], "license": "MIT", "homepage": "http://williamdurand.fr/Negotiation/", "authors": [ { "name": "William Durand", "email": "will+git@drnd.me" } ], "require": { "php": ">=7.1.0" }, "autoload": { "psr-4": { "Negotiation\\": "src/Negotiation" } }, "autoload-dev": { "psr-4": { "Negotiation\\Tests\\": "tests/Negotiation/Tests" } }, "extra": { "branch-alias": { "dev-master": "3.0-dev" } }, "require-dev": { "symfony/phpunit-bridge": "^5.0" } } LICENSE 0000755 00000002060 00000000000 0005513 0 ustar 00 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. CONTRIBUTING.md 0000755 00000002302 00000000000 0006736 0 ustar 00 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! .gitignore 0000755 00000000055 00000000000 0006500 0 ustar 00 /vendor/ composer.lock .phpunit.result.cache phpunit.xml.dist 0000755 00000001355 00000000000 0007667 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/bootstrap.php" > <testsuites> <testsuite name="Negotiation Test Suite"> <directory>./tests/</directory> </testsuite> </testsuites> <coverage> <include> <directory>./src/Negotiation/</directory> </include> </coverage> </phpunit>
| ver. 1.4 |
Github
|
.
| PHP 8.3.30 | Generation time: 0.01 |
proxy
|
phpinfo
|
Settings