diff --git a/README.md b/README.md index 18a68f2..5c8f158 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,72 @@ [![Build Status](https://travis-ci.org/fracture/http.png?branch=master)](https://travis-ci.org/fracture/http) [![Code Coverage](https://scrutinizer-ci.com/g/fracture/http/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/fracture/http/?branch=master) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/fracture/http/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/fracture/http/?branch=master) +[![Scrutinizer](https://img.shields.io/scrutinizer/g/fracture/http.svg)](https://scrutinizer-ci.com/g/fracture/http/?branch=master) +[![Packagist](https://img.shields.io/packagist/v/fracture/http.svg)](https://packagist.org/packages/fracture/http) ## Introduction -The primary goal is to create a simple abstraction for handling the HTTP interaction. +A simple abstraction for handling the HTTP request and responses. Library is made for interacting with [Fracture\Routing](https://github.com/fracture/http) and provides simple object-oriented abstractions. -Library is made for interacting with Fracture\Routing. In addition to the implemented interface, -it also provides object-oriented abstractions for the following functionality: +## Installation -- file uploads -- cookies -- headers (some of them) +You can add the library to your project using composer with following command: -## Instalation +```sh + composer require fracture/http +``` -Since the library is still in development, the recommended version to install would be "the latest". You can do it by running following command: - composer require fracture/http:dev-master +##Usage + +All of the following code will assume that the Composer's autoloader has already been included. + +###Basic request initialization + +While initializing a new `Request` instance manually is possible, for the instance to be fully prepared, it require several additional steps. For this reason it's better to use the `RequestBuider`, that will those steps: + +```php +create([ + 'get' => $_GET, + 'files' => $_FILES, + 'server' => $_SERVER, + 'post' => $_POST, + 'cookies'=> $_COOKIE, +]); +``` + +Use of this code fragment is sufficient for any basic website and will produces a ready-to-use `Request` instance. + +###Requests and REST + +When creating a site, that provides REST API, a common practice is to implement API versioning via HTTP Accept and Content-Type headers. To retrieve data, which was sent with a custom Content-Type header, you define a parser, which, if the media type matches, is executed to supplement the `Request` instance with additional parameters. + +```php +addContentParser('application/json', function () { + $data = json_decode(file_get_contents('php://input'), true); + + if ($data === null) { + $data = []; + } + + return $data; +}); +$request = $builder->create([ + 'server' => $_SERVER, + 'cookies'=> $_COOKIE, +]); +``` + +The parser itself is defined as an anonymous function, which will be called with `Fracture\Http\Headers\ContentType` as the parameter and is expected to return an array of `name => value` pairs for parameters. + +```php +array function([Fracture\Http\Headers\ContentType $header]) +``` diff --git a/src/Fracture/Http/Cookie.php b/src/Fracture/Http/Cookie.php deleted file mode 100755 index 0dc940a..0000000 --- a/src/Fracture/Http/Cookie.php +++ /dev/null @@ -1,33 +0,0 @@ -name = $name; - $this->value = $value; - } - - - public function setValue($value) - { - $this->value = $value; - } - - public function getValue() - { - return $this->value; - } - - - public function getName() - { - return $this->name; - } -} diff --git a/src/Fracture/Http/CookieBuilder.php b/src/Fracture/Http/CookieBuilder.php deleted file mode 100755 index 032a89c..0000000 --- a/src/Fracture/Http/CookieBuilder.php +++ /dev/null @@ -1,13 +0,0 @@ -cookie = $cookie; + $this->cookieName = $name; + $this->cookieValue = $value; $this->options = $options; } @@ -98,8 +100,8 @@ public function getName() public function getValue() { - $name = urlencode($this->cookie->getName()); - $value = urlencode($this->cookie->getValue()); + $name = urlencode($this->cookieName); + $value = urlencode($this->cookieValue); $result = "{$name}={$value}" . $this->collectFormatedOptions(); diff --git a/src/Fracture/Http/Request.php b/src/Fracture/Http/Request.php index b9577cb..66147da 100644 --- a/src/Fracture/Http/Request.php +++ b/src/Fracture/Http/Request.php @@ -155,10 +155,9 @@ public function getUpload($name) } - public function addCookie($cookie) + public function addCookie($name, $value) { - $name = $cookie->getName(); - $this->cookies[$name] = $cookie; + $this->cookies[$name] = $value; } diff --git a/src/Fracture/Http/RequestBuilder.php b/src/Fracture/Http/RequestBuilder.php index e8f8dd6..cde324d 100644 --- a/src/Fracture/Http/RequestBuilder.php +++ b/src/Fracture/Http/RequestBuilder.php @@ -18,7 +18,7 @@ class RequestBuilder /** * @param array[] $params - * @return \Fracture\Routing\Routable + * @return Routable */ public function create($params) { @@ -68,22 +68,26 @@ protected function applyContentParsers($instance) return; } - foreach ($this->parsers as $value => $parser) { - if ($header->contains($value)) { - $parameters += $this->alterParameters($parser, $value, $header); + foreach ($this->parsers as $type => $parser) { + if ($header->contains($type)) { + $parameters += $this->alterParameters($parser, $type, $header); } } $instance->setParameters($parameters, true); } - - private function alterParameters($parser, $value, $header) + /** + * @param callable $parser + * @param string $type + * @param Headers\ContentType $header + */ + private function alterParameters($parser, $type, $header) { $result = call_user_func($parser, $header); if (false === is_array($result)) { - $message = "Parser for '$value' did not return a 'name => value' array of parameters"; + $message = "Parser for '$type' did not return a 'name => value' array of parameters"; trigger_error($message, \E_USER_WARNING); } @@ -104,7 +108,7 @@ protected function applyParams($instance, $params) $this->applyWebContext($instance, $params['server']); foreach ($params['cookies'] as $name => $value) { - $instance->addCookie(new Cookie($name, $value)); + $instance->addCookie($name, $value); } } @@ -128,7 +132,7 @@ protected function applyWebContext($instance, $params) * @param Request $instance * @param array $params */ - public function applyHeaders($instance, $params) + protected function applyHeaders($instance, $params) { if (array_key_exists('HTTP_ACCEPT', $params)) { $header = new Headers\Accept($params['HTTP_ACCEPT']); diff --git a/src/Fracture/Http/Response.php b/src/Fracture/Http/Response.php index 954559b..91e8440 100755 --- a/src/Fracture/Http/Response.php +++ b/src/Fracture/Http/Response.php @@ -48,18 +48,17 @@ public function getBody() } - public function addCookie(Cookie $cookie, $options = []) + public function addCookie($name, $value, $options = []) { - $header = new Headers\SetCookie($cookie, $options); + $header = new Headers\SetCookie($name, $value, $options); $header->prepare(); - $this->cookies[$cookie->getName()] = $header; + $this->cookies[$name] = $header; } public function removeCookie($name, $options = []) { - $cookie = new Cookie($name, 'deleted'); - $this->addCookie($cookie, ['expires' => 0] + $options); + $this->addCookie($name, 'deleted', ['expires' => 0] + $options); } diff --git a/tests/unit/Fracture/Http/CookieBuilderTest.php b/tests/unit/Fracture/Http/CookieBuilderTest.php deleted file mode 100755 index 39025bd..0000000 --- a/tests/unit/Fracture/Http/CookieBuilderTest.php +++ /dev/null @@ -1,35 +0,0 @@ -create('foo', 'bar'); - $this->assertInstanceOf('Fracture\Http\Cookie' , $cookie); - } - - - /** - * @covers Fracture\Http\CookieBuilder::create - */ - public function testValueAndNameOfCreateCookie() - { - $instance = new CookieBuilder; - $cookie = $instance->create('foo', 'bar'); - $this->assertSame('foo' , $cookie->getName()); - $this->assertSame('bar' , $cookie->getValue()); - } -} diff --git a/tests/unit/Fracture/Http/CookieTest.php b/tests/unit/Fracture/Http/CookieTest.php deleted file mode 100755 index 954b1b4..0000000 --- a/tests/unit/Fracture/Http/CookieTest.php +++ /dev/null @@ -1,39 +0,0 @@ -assertSame('name', $instance->getName()); - $this->assertSame('value', $instance->getValue()); - } - - - /** - * @covers Fracture\Http\Cookie::__construct - * @covers Fracture\Http\Cookie::setValue - * @covers Fracture\Http\Cookie::getValue - */ - public function testChangingValue() - { - $instance = new Cookie('name', 'value'); - $instance->setValue('new value'); - $this->assertSame('new value', $instance->getValue()); - } -} diff --git a/tests/unit/Fracture/Http/Headers/SetCookieTest.php b/tests/unit/Fracture/Http/Headers/SetCookieTest.php index 7339171..728344c 100755 --- a/tests/unit/Fracture/Http/Headers/SetCookieTest.php +++ b/tests/unit/Fracture/Http/Headers/SetCookieTest.php @@ -16,9 +16,7 @@ class SetCookieTest extends PHPUnit_Framework_TestCase */ public function testIsFinalResponse() { - $cookieMock = $this->getMock('Fracture\Http\Cookie', [], [], '', false); - - $instance = new SetCookie($cookieMock); + $instance = new SetCookie(null, null); $this->assertTrue($instance->isFinal()); } @@ -29,9 +27,7 @@ public function testIsFinalResponse() */ public function testHeaderName() { - $cookieMock = $this->getMock('Fracture\Http\Cookie', [], [], '', false); - - $instance = new SetCookie($cookieMock); + $instance = new SetCookie(null, null); $this->assertSame('Set-Cookie', $instance->getName()); } @@ -43,8 +39,7 @@ public function testHeaderName() */ public function testInvalidOptions() { - $cookieMock = $this->getMock('Fracture\Http\Cookie', [], [], '', false); - $instance = new SetCookie($cookieMock, ['foo' => 'bar']); + $instance = new SetCookie(null, null, ['foo' => 'bar']); $instance->prepare(); } @@ -66,15 +61,7 @@ public function testInvalidOptions() */ public function testHeaderValue($options, $expected) { - $cookieMock = $this->getMock('Fracture\Http\Cookie', ['getName', 'getValue'], [], '', false); - $cookieMock->expects($this->once()) - ->method('getName') - ->will($this->returnValue('alpha')); - $cookieMock->expects($this->once()) - ->method('getValue') - ->will($this->returnValue('beta')); - - $instance = new SetCookie($cookieMock, $options); + $instance = new SetCookie('alpha', 'beta', $options); $instance->prepare(); $this->assertSame($expected, $instance->getValue()); @@ -141,15 +128,7 @@ public function provideHeaderValue() */ public function testHeaderExpireValue($options, $expected) { - $cookieMock = $this->getMock('Fracture\Http\Cookie', ['getName', 'getValue'], [], '', false); - $cookieMock->expects($this->once()) - ->method('getName') - ->will($this->returnValue('alpha')); - $cookieMock->expects($this->once()) - ->method('getValue') - ->will($this->returnValue('beta')); - - $instance = new SetCookie($cookieMock, $options); + $instance = new SetCookie('alpha', 'beta', $options); $instance->prepare(); $this->assertSame($expected, $instance->getValue()); @@ -183,15 +162,7 @@ public function provideHeaderExpireValues() */ public function testHeaderExpireValueAsDateTime($string, $expected) { - $cookieMock = $this->getMock('Fracture\Http\Cookie', ['getName', 'getValue'], [], '', false); - $cookieMock->expects($this->once()) - ->method('getName') - ->will($this->returnValue('alpha')); - $cookieMock->expects($this->once()) - ->method('getValue') - ->will($this->returnValue('beta')); - - $instance = new SetCookie($cookieMock, [ + $instance = new SetCookie('alpha', 'beta', [ 'expires' => new \DateTime($string), ]); $instance->prepare(); diff --git a/tests/unit/Fracture/Http/RequestBuilderTest.php b/tests/unit/Fracture/Http/RequestBuilderTest.php index a6e0184..a0ecb6a 100644 --- a/tests/unit/Fracture/Http/RequestBuilderTest.php +++ b/tests/unit/Fracture/Http/RequestBuilderTest.php @@ -424,6 +424,6 @@ public function testWithCookieAddition() $builder = new RequestBuilder; $instance = $builder->create($input); - $this->assertInstanceOf('Fracture\Http\Cookie', $instance->getCookie('name')); + $this->assertEquals('value', $instance->getCookie('name')); } } diff --git a/tests/unit/Fracture/Http/RequestTest.php b/tests/unit/Fracture/Http/RequestTest.php index 00e7d53..39ea97e 100644 --- a/tests/unit/Fracture/Http/RequestTest.php +++ b/tests/unit/Fracture/Http/RequestTest.php @@ -330,16 +330,11 @@ public function testGetterAndSetterForAcceptHeaderWithManualAcceotValue() */ public function testAddedCookie() { - $cookieMock = $this->getMock('Fracture\Http\Cookie', ['getName'], [], '', false); - $cookieMock->expects($this->any()) - ->method('getName') - ->will($this->returnValue('alpha')); - $request = new Request; $this->assertNull($request->getCookie('alpha')); - $request->addCookie($cookieMock); - $this->assertInstanceOf('Fracture\Http\Cookie', $request->getCookie('alpha')); + $request->addCookie('alpha', 'value'); + $this->assertEquals('value', $request->getCookie('alpha')); } /** @@ -349,22 +344,15 @@ public function testAddedCookie() */ public function testAllCookiesReturned() { - $first = $this->getMock('Fracture\Http\Cookie', ['getName'], [], '', false); - $first->expects($this->any()) - ->method('getName') - ->will($this->returnValue('alpha')); - - $second = $this->getMock('Fracture\Http\Cookie', ['getName'], [], '', false); - $second->expects($this->any()) - ->method('getName') - ->will($this->returnValue('alpha')); - $request = new Request; $this->assertEmpty($request->getAllCookies()); - $request->addCookie($first); - $request->addCookie($second); + $request->addCookie('first', 'foo'); + $request->addCookie('second', 'bar'); - $this->assertContainsOnlyInstancesOf('Fracture\Http\Cookie', $request->getAllCookies()); + $this->assertEquals([ + 'first' => 'foo', + 'second' => 'bar', + ], $request->getAllCookies()); } } diff --git a/tests/unit/Fracture/Http/ResponseTest.php b/tests/unit/Fracture/Http/ResponseTest.php index a520da7..80f1747 100755 --- a/tests/unit/Fracture/Http/ResponseTest.php +++ b/tests/unit/Fracture/Http/ResponseTest.php @@ -278,16 +278,8 @@ public function testMoreComplicatedSimpleRemoveCookie() */ public function testAddCookie() { - $cookieMock = $this->getMock('Fracture\Http\Cookie', ['getName', 'getValue'], [], '', false); - $cookieMock->expects($this->exactly(2)) - ->method('getName') - ->will($this->returnValue('alpha')); - $cookieMock->expects($this->once()) - ->method('getValue') - ->will($this->returnValue('beta')); - $instance = new Response; - $instance->addCookie($cookieMock); + $instance->addCookie('alpha', 'beta'); $this->assertEquals([ [