Added JSONP support for JsonView

This commit is contained in:
ADmad 2013-02-02 13:25:27 +05:30
parent 64cf42bf42
commit afb62959ef
2 changed files with 69 additions and 9 deletions

View file

@ -66,6 +66,36 @@ class JsonViewTest extends CakeTestCase {
$this->assertSame('application/json', $Response->type());
}
/**
* testJsonpResponse method
*
* @return void
*/
public function testJsonpResponse() {
$Request = new CakeRequest();
$Response = new CakeResponse();
$Controller = new Controller($Request, $Response);
$data = array('user' => 'fake', 'list' => array('item1', 'item2'));
$Controller->set(array('data' => $data, '_serialize' => 'data', '_jsonp' => true));
$View = new JsonView($Controller);
$output = $View->render(false);
$this->assertSame(json_encode($data), $output);
$this->assertSame('application/json', $Response->type());
$View->request->query = array('callback' => 'jfunc');
$output = $View->render(false);
$expected = 'jfunc(' . json_encode($data) . ')';
$this->assertSame($expected, $output);
$this->assertSame('application/javascript', $Response->type());
$View->request->query = array('jsonCallback' => 'jfunc');
$View->viewVars['_jsonp'] = 'jsonCallback';
$output = $View->render(false);
$expected = 'jfunc(' . json_encode($data) . ')';
$this->assertSame($expected, $output);
}
/**
* testRenderWithView method
*
@ -95,9 +125,19 @@ class JsonViewTest extends CakeTestCase {
$View->helpers = array('Paginator');
$output = $View->render('index');
$expected = json_encode(array('user' => 'fake', 'list' => array('item1', 'item2'), 'paging' => array('page' => 2)));
$this->assertSame($expected, $output);
$expected = array('user' => 'fake', 'list' => array('item1', 'item2'), 'paging' => array('page' => 2));
$this->assertSame(json_encode($expected), $output);
$this->assertSame('application/json', $Response->type());
$View->request->query = array('jsonCallback' => 'jfunc');
$Controller->set('_jsonp', 'jsonCallback');
$View = new JsonView($Controller);
$View->helpers = array('Paginator');
$output = $View->render('index');
$expected['paging']['?']['jsonCallback'] = 'jfunc';
$expected = 'jfunc(' . json_encode($expected) . ')';
$this->assertSame($expected, $output);
$this->assertSame('application/javascript', $Response->type());
}
}

View file

@ -43,6 +43,9 @@ App::uses('View', 'View');
* If you don't use the `_serialize` key, you will need a view. You can use extended
* views to provide layout like functionality.
*
* You can also enable JSONP support by setting parameter `_jsonp` to true or a string to specify
* custom query string paramater name which will contain the callback function name.
*
* @package Cake.View
* @since CakePHP(tm) v 2.1.0
*/
@ -71,22 +74,39 @@ class JsonView extends View {
/**
* Render a JSON view.
*
* Uses the special '_serialize' parameter to convert a set of
* view variables into a JSON response. Makes generating simple
* JSON responses very easy. You can omit the '_serialize' parameter,
* and use a normal view + layout as well.
* ### Special parameters
* `_serialize` To convert a set of view variables into a JSON response.
* It's value can be a string for single variable name or array for multiple names.
* You can omit the`_serialize` parameter, and use a normal view + layout as well.
* `_jsonp` Enables JSONP support and wraps response in callback function provided in query string.
* - Setting it to true enables the default query string parameter "callback".
* - Setting it to a string value, uses the provided query string parameter for finding the
* JSONP callback name.
*
* @param string $view The view being rendered.
* @param string $layout The layout being rendered.
* @return string The rendered view.
*/
public function render($view = null, $layout = null) {
$return = null;
if (isset($this->viewVars['_serialize'])) {
return $this->_serialize($this->viewVars['_serialize']);
$return = $this->_serialize($this->viewVars['_serialize']);
} elseif ($view !== false && $this->_getViewFileName($view)) {
$return = parent::render($view, false);
}
if ($view !== false && $this->_getViewFileName($view)) {
return parent::render($view, false);
if (!empty($this->viewVars['_jsonp'])) {
$jsonpParam = $this->viewVars['_jsonp'];
if ($this->viewVars['_jsonp'] === true) {
$jsonpParam = 'callback';
}
if (isset($this->request->query[$jsonpParam])) {
$return = sprintf('%s(%s)', h($this->request->query[$jsonpParam]), $return);
$this->response->type('js');
}
}
return $return;
}
/**