summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorminstel <minstel@yandex.ru>2016-10-20 16:41:17 +0300
committerminstel <minstel@yandex.ru>2016-10-20 16:41:17 +0300
commit5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1 (patch)
tree5e3e78c7964feff7315284c34d1022f874d4356a
parent298f38a4347b8b29e3d145f8b5a0a24ea5775640 (diff)
downloadcontroller-5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1.zip
controller-5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1.tar.gz
controller-5ed5b76550fe8d0a2ec75f75db8cfc7ae71d43c1.tar.bz2
Controller::encodeData method
-rw-r--r--src/Controller.php66
-rw-r--r--tests/ControllerTest.php159
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