Permalink
Browse files

Added JSONP support for JsonView

  • Loading branch information...
ADmad committed Feb 2, 2013
1 parent 64cf42b commit afb62959effde647c18ac03f0afb4a60de133e01
Showing with 69 additions and 9 deletions.
  1. +42 −2 lib/Cake/Test/Case/View/JsonViewTest.php
  2. +27 −7 lib/Cake/View/JsonView.php
@@ -66,6 +66,36 @@ public function testRenderWithoutViewMultiple() {
$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 @@ public function testRenderWithView() {
$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
@@ -43,6 +43,9 @@
* 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 @@ public function __construct(Controller $controller = null) {
/**
* 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;
}
/**

0 comments on commit afb6295

Please sign in to comment.