diff options
author | minstel <minstel@yandex.ru> | 2016-10-20 16:41:17 +0300 |
---|---|---|
committer | minstel <minstel@yandex.ru> | 2016-10-20 16:41:17 +0300 |
commit | 5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1 (patch) | |
tree | 5e3e78c7964feff7315284c34d1022f874d4356a | |
parent | 298f38a4347b8b29e3d145f8b5a0a24ea5775640 (diff) | |
download | controller-5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1.zip controller-5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1.tar.gz controller-5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1.tar.bz2 |
Controller::encodeData method
-rw-r--r-- | src/Controller.php | 66 | ||||
-rw-r--r-- | tests/ControllerTest.php | 159 |
2 files changed, 221 insertions, 4 deletions
diff --git a/src/Controller.php b/src/Controller.php index ddec2c0..73d1ad9 100644 --- a/src/Controller.php +++ b/src/Controller.php @@ -118,8 +118,72 @@ abstract class Controller public function isError() { return $this->isClientError() || $this->isServerError(); - } + } + + /** + * Encode data to send to client + * + * @param mixed $data + * @return string + */ + public function encodeData($data) + { + $response = $this->getResponse(); + $invalid = !$response || + !($type = $response->getHeaderLine('Content-Type')) || + !in_array($type, ['application/json', 'text/xml', 'application/xml'], true); + + if ($invalid) { + throw new \RuntimeException("Valid content type is not set in response for encoding data"); + } + + switch ($type) { + case 'application/json': + return $this->encodeDataAsJson($data); + case 'text/xml': + case 'application/xml': + return $this->encodeDataAsXml($data); + } + } + + /** + * Encode data as xml + * + * @param \SimpleXMLElement $data + * @return string + */ + protected function encodeDataAsXml(\SimpleXMLElement $data) + { + return $data->asXML(); + } + + /** + * Encode data as json + * + * @param mixed + * @return string + */ + protected function encodeDataAsJson($data) + { + $data = json_encode($data); + + return $this->isJsonp() ? + $this->getRequest()->getQueryParams()['callback'] . '(' . $data . ')' : + $data; + } + + /** + * Check if we should respond with jsonp + * + * @return boolean + */ + protected function isJsonp() + { + $request = $this->getRequest(); + return $request && !empty($request->getQueryParams()['callback']); + } + /** * Get status code of response * diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index 8cdbf7d..53a122a 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -11,7 +11,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase */ public function testInvoke() { - $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass(); + $controller = $this->getController(); list($request, $response) = $this->getRequests(); $controller->expects($this->once())->method('run')->will($this->returnValue($response)); @@ -28,7 +28,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase */ public function testResponseStatusEmptyResponse() { - $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass(); + $controller = $this->getController(); $data = $this->getStatusCodesMap(null); foreach ($data as $func => $value) { @@ -44,7 +44,7 @@ class ControllerTest extends PHPUnit_Framework_TestCase */ public function testResponseStatus($code) { - $controller = $this->getMockBuilder(Controller::class)->disableOriginalConstructor()->getMockForAbstractClass(); + $controller = $this->getController(); list($request, $response) = $this->getRequests(); $response->method('getStatusCode')->will($this->returnValue($code)); @@ -76,6 +76,159 @@ class ControllerTest extends PHPUnit_Framework_TestCase } /** + * Test encodeData method, positive tests + * + * @dataProvider encodeDataPositiveProvider + * @param mixed $data + * @param string $contentType + * @param string $type + * @param string $callback Callback name for testing jsonp request + */ + public function testEncodeDataPositive($data, $contentType, $type, $callback = '') + { + $controller = $this->getController(['getRequest', 'getResponse']); + list($request, $response) = $this->getRequests(); + + $response->method('getHeaderLine')->with($this->equalTo('Content-Type'))->will($this->returnValue($contentType)); + if ($type === 'jsonp') { + $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback])); + } + + $controller->method('getRequest')->will($this->returnValue($request)); + $controller->method('getResponse')->will($this->returnValue($response)); + + $result = $controller->encodeData($data); + $expect = null; + + if ($type === 'json') { + $expect = json_encode($data); + } elseif ($type === 'jsonp') { + $expect = $callback . '(' . json_encode($data) . ')'; + } else { + $expect = $data->asXML(); + } + + $this->assertNotEmpty($result); + $this->assertEquals($expect, $result); + } + + /** + * Provide data for testing encodeData method + * + * @return array + */ + public function encodeDataPositiveProvider() + { + $xml = simplexml_load_string( + "<?xml version='1.0'?> + <document> + <tag1>Test tag</tag1> + <tag2>Test</tag2> + </document>" + ); + + return [ + [['testKey' => 'testValue'], 'application/json', 'json'], + [['testKey' => 'testValue'], 'application/json', 'jsonp', 'test_callback'], + ['', 'application/json', 'json'], + ['', 'application/json', 'jsonp', 'test_callback'], + [$xml, 'text/xml', 'xml'], + [$xml, 'application/xml', 'xml'] + ]; + } + + /** + * Test encodeData method, negative tests + * + * @dataProvider encodeDataNegativeProvider + * @param mixed $data + * @param string $contentType + * @param string $type + * @param string $callback Callback name for testing jsonp request + */ + public function testEncodeDataNegative($data, $contentType, $type, $callback = '', $exception = true) + { + $controller = $this->getController(['getRequest', 'getResponse']); + list($request, $response) = $this->getRequests(); + + $response->method('getHeaderLine')->with($this->equalTo('Content-Type'))->will($this->returnValue($contentType)); + if ($type === 'jsonp') { + $request->method('getQueryParams')->will($this->returnValue(['callback' => $callback])); + } + + $controller->method('getRequest')->will($this->returnValue($request)); + $controller->method('getResponse')->will($this->returnValue($response)); + + if ($exception) $this->expectException(\RuntimeException::class); + + $result = $controller->encodeData($data); + $expect = null; + + if ($type === 'json') { + $expect = json_encode($data); + } elseif ($type === 'jsonp') { + $expect = $callback . '(' . json_encode($data) . ')'; + } else { + $expect = $data->asXML(); + } + + $this->assertNotEquals($expect, $result); + } + + /** + * Provide data for testing encodeData method + * + * @return array + */ + public function encodeDataNegativeProvider() + { + $xml = simplexml_load_string( + "<?xml version='1.0'?> + <document> + <tag1>Test tag</tag1> + <tag2>Test</tag2> + </document>" + ); + + return [ + [['testKey' => 'testValue'], '', 'json'], + [['testKey' => 'testValue'], 'json', 'json'], + [['testKey' => 'testValue'], 'application/json', 'jsonp', '', false], + [['testKey' => 'testValue'], 'application/jsonp', 'jsonp', 'test_callback'], + [$xml, '', 'xml'], + [$xml, 'xml', 'xml'] + ]; + } + + /** + * Test encoding data when response is not set + */ + public function testEncodeDataNoResponse() + { + $controller = $this->getController(); + + $this->expectException(\RuntimeException::class); + + $result = $controller->encodeData(['test' => 'test']); + } + + /** + * Get mock for controller + * + * @param array $methods Methods to mock + * @return Controller + */ + public function getController($methods = []) + { + $builder = $this->getMockBuilder(Controller::class)->disableOriginalConstructor(); + if ($methods) { + $builder->setMethods($methods); + } + + return $builder->getMockForAbstractClass(); + } + + /** * Get map of status codes to states * * @param int $code |