Skip to content

Commit

Permalink
Update input parsing to work with PATCH & DELETE.
Browse files Browse the repository at this point in the history
  • Loading branch information
markstory committed Jul 4, 2012
1 parent d3a41a9 commit 2b35abe
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 77 deletions.
25 changes: 17 additions & 8 deletions lib/Cake/Network/Request.php
Expand Up @@ -43,9 +43,8 @@ class Request implements \ArrayAccess {

/**
* Array of POST data. Will contain form data as well as uploaded files.
* Inputs prefixed with 'data' will have the data prefix removed. If there is
* overlap between an input prefixed with data and one without, the 'data' prefixed
* value will take precedence.
* In PUT/PATCH/DELETE requests this property will contain the form-urlencoded
* data.
*
* @var array
*/
Expand Down Expand Up @@ -133,6 +132,9 @@ class Request implements \ArrayAccess {
/**
* Wrapper method to create a new request from PHP superglobals.
*
* Uses the $_GET, $_POST, $_FILES, $_COOKIE and php://input data to construct
* the request.
*
* @return Cake\Network\Request
*/
public static function createFromGlobals() {
Expand Down Expand Up @@ -163,6 +165,8 @@ public static function createFromGlobals() {
* - `url` The url without the base path for the request.
* - `base` The base url for the request.
* - `webroot` The webroot directory for the request.
* - `input` The data that would come from php://input this is useful for simulating
* requests with put, patch or delete data.
*
* @param string|array $config An array of request data to create a request with.
*/
Expand All @@ -179,6 +183,7 @@ public function __construct($config = array()) {
'url' => '',
'base' => '',
'webroot' => '',
'input' => null,
);
$this->_setConfig($config);
}
Expand All @@ -200,6 +205,9 @@ protected function _setConfig($config) {
$this->here = $this->base . '/' . $this->url;
$this->webroot = $config['webroot'];

if (isset($config['input'])) {
$this->_input = $config['input'];
}
$config['post'] = $this->_processPost($config['post']);
$this->data = $this->_processFiles($config['post'], $config['files']);
$this->query = $this->_processGet($config['query']);
Expand All @@ -214,11 +222,12 @@ protected function _setConfig($config) {
* @return array
*/
protected function _processPost($data) {
if ($this->is('put')) {
$data = $this->_readInput();
if (env('CONTENT_TYPE') === 'application/x-www-form-urlencoded') {
parse_str($data, $data);
}
if (
in_array(env('REQUEST_METHOD'), array('PUT', 'DELETE', 'PATCH')) &&
env('CONTENT_TYPE') === 'application/x-www-form-urlencoded'
) {
$data = $this->input();
parse_str($data, $data);
}
if (env('HTTP_X_HTTP_METHOD_OVERRIDE')) {
$data['_method'] = env('HTTP_X_HTTP_METHOD_OVERRIDE');
Expand Down
86 changes: 17 additions & 69 deletions lib/Cake/Test/TestCase/Network/RequestTest.php
Expand Up @@ -20,28 +20,6 @@
use Cake\TestSuite\TestCase;
use Cake\Utility\Xml;

class TestRequest extends Request {

public function reConstruct($url = 'some/path', $parseEnvironment = true) {
$this->_base();
if (empty($url)) {
$url = $this->_url();
}
if ($url[0] == '/') {
$url = substr($url, 1);
}
$this->url = $url;

if ($parseEnvironment) {
$this->_processPost();
$this->_processGet();
$this->_processFiles();
}
$this->here = $this->base . '/' . $this->url;
}

}

class RequestTest extends TestCase {

/**
Expand Down Expand Up @@ -201,68 +179,38 @@ public function testPutParsing() {
$_SERVER['REQUEST_METHOD'] = 'PUT';
$_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';

$data = array('data' => array(
$data = array(
'Article' => array('title')
);
$request = new Request(array(
'input' => 'Article[]=title'
));

$request = $this->getMock(__NAMESPACE__ . '\TestRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][]=title'));
$request->reConstruct();
$this->assertEquals($data['data'], $request->data);
$this->assertEquals($data, $request->data);

$data = array('one' => 1, 'two' => 'three');
$request = $this->getMock(__NAMESPACE__ . '\TestRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('one=1&two=three'));
$request->reConstruct();
$request = new Request(array(
'input' => 'one=1&two=three'
));
$this->assertEquals($data, $request->data);

$data = array(
'data' => array(
'Article' => array('title' => 'Testing'),
),
'action' => 'update'
);
$request = $this->getMock(__NAMESPACE__ . '\TestRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][title]=Testing&action=update'));
$request->reConstruct();
$_SERVER['REQUEST_METHOD'] = 'DELETE';
$request = new Request(array(
'input' => 'Article[title]=Testing&action=update'
));
$expected = array(
'Article' => array('title' => 'Testing'),
'action' => 'update'
);
$this->assertEquals($expected, $request->data);

$_SERVER['REQUEST_METHOD'] = 'DELETE';
$data = array('data' => array(
$_SERVER['REQUEST_METHOD'] = 'PATCH';
$data = array(
'Article' => array('title'),
'Tag' => array('Tag' => array(1, 2))
));
$request = $this->getMock(__NAMESPACE__ . '\TestRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][]=title&Tag[Tag][]=1&Tag[Tag][]=2'));
$request->reConstruct();
$this->assertEquals($data['data'], $request->data);

$data = array('data' => array(
'Article' => array('title' => 'some title'),
'Tag' => array('Tag' => array(1, 2))
));
$request = $this->getMock(__NAMESPACE__ . '\TestRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('data[Article][title]=some%20title&Tag[Tag][]=1&Tag[Tag][]=2'));
$request->reConstruct();
$this->assertEquals($data['data'], $request->data);

$data = array(
'a' => array(1, 2),
'b' => array(1, 2)
);
$request = $this->getMock(__NAMESPACE__ . '\TestRequest', array('_readInput'));
$request->expects($this->at(0))->method('_readInput')
->will($this->returnValue('a[]=1&a[]=2&b[]=1&b[]=2'));
$request->reConstruct();
$request = new Request(array(
'input' => 'Article[]=title&Tag[Tag][]=1&Tag[Tag][]=2'
));
$this->assertEquals($data, $request->data);
}

Expand Down

0 comments on commit 2b35abe

Please sign in to comment.