Skip to content
Browse files

Automatically handle PUT requests

make the following "just work"

    curl -X PUT -d foo=bar http://...
  • Loading branch information...
1 parent d1475b1 commit b509bdb04bb19914c3bee8baafa64059e2f80d43 @AD7six AD7six committed
Showing with 110 additions and 2 deletions.
  1. +8 −1 lib/Cake/Network/CakeRequest.php
  2. +102 −1 lib/Cake/Test/Case/Network/CakeRequestTest.php
View
9 lib/Cake/Network/CakeRequest.php
@@ -161,7 +161,14 @@ public function __construct($url = null, $parseEnvironment = true) {
* @return void
*/
protected function _processPost() {
- $this->data = $_POST;
+ if ($_POST) {
+ $this->data = $_POST;
+ } elseif ($this->is('put')) {
+ $this->data = $this->_readInput();
+ if (env('CONTENT_TYPE') === 'application/x-www-form-urlencoded') {
+ parse_str($this->data, $this->data);
+ }
+ }
if (ini_get('magic_quotes_gpc') === '1') {
$this->data = stripslashes_deep($this->data);
}
View
103 lib/Cake/Test/Case/Network/CakeRequestTest.php
@@ -21,6 +21,34 @@
App::uses('Xml', 'Utility');
App::uses('CakeRequest', 'Network');
+class TestCakeRequest extends CakeRequest {
+
+ public $input;
+
+ 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;
+ }
+
+ protected function _readInput() {
+ return $this->input;
+ }
+
+}
+
class CakeRequestTest extends CakeTestCase {
/**
@@ -41,7 +69,7 @@ public function setUp() {
}
/**
- * tearDown-
+ * tearDown
*
* @return void
*/
@@ -205,6 +233,79 @@ public function testPostParsing() {
}
/**
+ * test parsing PUT data into the object.
+ *
+ * @return void
+ */
+ public function testPutParsing() {
+ $_SERVER['REQUEST_METHOD'] = 'PUT';
+ $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+
+ $data = array('data' => array(
+ 'Article' => array('title')
+ ));
+
+ $request = $this->getMock('TestCakeRequest', array('_readInput'));
+ $request->expects($this->at(0))->method('_readInput')
+ ->will($this->returnValue('data[Article][]=title'));
+ $request->reConstruct();
+ $this->assertEquals($data['data'], $request->data);
+
+ $data = array('one' => 1, 'two' => 'three');
+ $request = $this->getMock('TestCakeRequest', array('_readInput'));
+ $request->expects($this->at(0))->method('_readInput')
+ ->will($this->returnValue('one=1&two=three'));
+ $request->reConstruct();
+ $this->assertEquals($data, $request->data);
+
+ $data = array(
+ 'data' => array(
+ 'Article' => array('title' => 'Testing'),
+ ),
+ 'action' => 'update'
+ );
+ $request = $this->getMock('TestCakeRequest', array('_readInput'));
+ $request->expects($this->at(0))->method('_readInput')
+ ->will($this->returnValue('data[Article][title]=Testing&action=update'));
+ $request->reConstruct();
+ $expected = array(
+ 'Article' => array('title' => 'Testing'),
+ 'action' => 'update'
+ );
+ $this->assertEquals($expected, $request->data);
+
+ $data = array('data' => array(
+ 'Article' => array('title'),
+ 'Tag' => array('Tag' => array(1, 2))
+ ));
+ $request = $this->getMock('TestCakeRequest', 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('TestCakeRequest', 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('TestCakeRequest', array('_readInput'));
+ $request->expects($this->at(0))->method('_readInput')
+ ->will($this->returnValue('a[]=1&a[]=2&b[]=1&b[]=2'));
+ $request->reConstruct();
+ $this->assertEquals($data, $request->data);
+ }
+
+/**
* test parsing of FILES array
*
* @return void

5 comments on commit b509bdb

@markstory
CakePHP member

When merging and rebasing this code into my router/request branch for 3.0, I added support for PATCH and DELETE. Might make sense to add that to 2.2 as well. markstory/cakephp@e8680f6

@lorenzo
CakePHP member

+1 to add it to 2.2

@markstory
CakePHP member

I added PUT/DELETE in 5467902 and updated the docs. :)

@AD7six
CakePHP member

win!

Why leave out patch though?

Are we going to get into semantic debates with users in the future as to why we aren't using PATCH for (partial) edit actions I wonder..

@markstory
CakePHP member

I have patch in for 3.0, I guess we could add a is('patch') detector too. I hope we don't have that fight, its really not worth the time and effort.

Please sign in to comment.
Something went wrong with that request. Please try again.