Skip to content
Browse files

Merge pull request #3482 from weierophinney/feature/rest-delete-repla…

…ce-collection

Feature/rest delete replace collection
  • Loading branch information...
2 parents 0bb9585 + 56e347c commit 21f4850311729ba7659e60fe18bebec21aaa0644 @Freeaqingme Freeaqingme committed Jan 18, 2013
View
95 library/Zend/Mvc/Controller/AbstractRestfulController.php
@@ -72,6 +72,22 @@
abstract public function delete($id);
/**
+ * Delete the entire resource collection
+ *
+ * Not marked as abstract, as that would introduce a BC break
+ * (introduced in 2.1.0); instead, raises an exception if not implemented.
+ *
+ * @return mixed
+ * @throws Exception\RuntimeException
+ */
+ public function deleteList()
+ {
+ throw new Exception\RuntimeException(sprintf(
+ '%s is unimplemented', __METHOD__
+ ));
+ }
+
+ /**
* Return single resource
*
* @param mixed $id
@@ -139,6 +155,23 @@ public function patch($id, $data)
}
/**
+ * Replace an entire resource collection
+ *
+ * Not marked as abstract, as that would introduce a BC break
+ * (introduced in 2.1.0); instead, raises an exception if not implemented.
+ *
+ * @param mixed $data
+ * @return mixed
+ * @throws Exception\RuntimeException
+ */
+ public function replaceList($data)
+ {
+ throw new Exception\RuntimeException(sprintf(
+ '%s is unimplemented', __METHOD__
+ ));
+ }
+
+ /**
* Update an existing resource
*
* @param mixed $id
@@ -229,19 +262,20 @@ public function onDispatch(MvcEvent $e)
break;
// DELETE
case 'delete':
- if (null === $id = $routeMatch->getParam('id')) {
- if (! ($id = $request->getQuery()->get('id', false))) {
- throw new Exception\DomainException(
- 'Missing identifier');
- }
+ $id = $this->getIdentifier($routeMatch, $request);
+ if ($id !== false) {
+ $action = 'delete';
+ $return = $this->delete($id);
+ break;
}
- $action = 'delete';
- $return = $this->delete($id);
+
+ $action = 'deleteList';
+ $return = $this->deleteList();
break;
// GET
case 'get':
$id = $this->getIdentifier($routeMatch, $request);
- if ($id) {
+ if ($id !== false) {
$action = 'get';
$return = $this->get($id);
break;
@@ -252,7 +286,7 @@ public function onDispatch(MvcEvent $e)
// HEAD
case 'head':
$id = $this->getIdentifier($routeMatch, $request);
- if (!$id) {
+ if ($id !== false) {
$id = null;
}
$action = 'head';
@@ -270,8 +304,10 @@ public function onDispatch(MvcEvent $e)
// PATCH
case 'patch':
$id = $this->getIdentifier($routeMatch, $request);
- if (!$id) {
- throw new Exception\DomainException('Missing identifier');
+ if ($id === false) {
+ $response = $e->getResponse();
+ $response->setStatusCode(405);
+ return $response;
}
$data = $this->processBodyContent($request);
$action = 'patch';
@@ -284,12 +320,23 @@ public function onDispatch(MvcEvent $e)
break;
// PUT
case 'put':
- $action = 'update';
- $return = $this->processPutData($request, $routeMatch);
+ $id = $this->getIdentifier($routeMatch, $request);
+ $data = $this->processBodyContent($request);
+
+ if ($id !== false) {
+ $action = 'update';
+ $return = $this->update($id, $data);
+ break;
+ }
+
+ $action = 'replaceList';
+ $return = $this->replaceList($data);
break;
// All others...
default:
- throw new Exception\DomainException('Invalid HTTP method!');
+ $response = $e->getResponse();
+ $response->setStatusCode(405);
+ return $response;
}
$routeMatch->setParam('action', $action);
@@ -315,26 +362,6 @@ public function processPostData(Request $request)
}
/**
- * Process put data and call update
- *
- * @param Request $request
- * @param $routeMatch
- * @return mixed
- * @throws Exception\DomainException
- */
- public function processPutData(Request $request, $routeMatch)
- {
- $id = $this->getIdentifier($routeMatch, $request);
- if (!$id) {
- throw new Exception\DomainException('Missing identifier');
- }
-
- $data = $this->processBodyContent($request);
-
- return $this->update($id, $data);
- }
-
- /**
* Check if request has certain content type
*
* @return boolean
View
48 tests/ZendTest/Mvc/Controller/RestfulControllerTest.php
@@ -90,6 +90,21 @@ public function testDispatchInvokesUpdateMethodWhenNoActionPresentAndPutInvokedW
$this->assertEquals('update', $this->routeMatch->getParam('action'));
}
+ public function testDispatchInvokesReplaceListMethodWhenNoActionPresentAndPutInvokedWithoutIdentifier()
+ {
+ $entities = array(
+ array('id' => uniqid(), 'name' => __FUNCTION__),
+ array('id' => uniqid(), 'name' => __FUNCTION__),
+ array('id' => uniqid(), 'name' => __FUNCTION__),
+ );
+ $string = http_build_query($entities);
+ $this->request->setMethod('PUT')
+ ->setContent($string);
+ $result = $this->controller->dispatch($this->request, $this->response);
+ $this->assertEquals($entities, $result);
+ $this->assertEquals('replaceList', $this->routeMatch->getParam('action'));
+ }
+
public function testDispatchInvokesDeleteMethodWhenNoActionPresentAndDeleteInvokedWithIdentifier()
{
$entity = array('id' => 1, 'name' => __FUNCTION__);
@@ -102,6 +117,16 @@ public function testDispatchInvokesDeleteMethodWhenNoActionPresentAndDeleteInvok
$this->assertEquals('delete', $this->routeMatch->getParam('action'));
}
+ public function testDispatchInvokesDeleteListMethodWhenNoActionPresentAndDeleteInvokedWithoutIdentifier()
+ {
+ $this->request->setMethod('DELETE');
+ $result = $this->controller->dispatch($this->request, $this->response);
+ $this->assertSame($this->response, $result);
+ $this->assertEquals(204, $result->getStatusCode());
+ $this->assertTrue($result->getHeaders()->has('X-Deleted'));
+ $this->assertEquals('deleteList', $this->routeMatch->getParam('action'));
+ }
+
public function testDispatchInvokesOptionsMethodWhenNoActionPresentAndOptionsInvoked()
{
$this->request->setMethod('OPTIONS');
@@ -341,4 +366,27 @@ public function testRequestingContentTypeReturnsFalseForInvalidMatches($contentT
$this->request->getHeaders()->addHeaderLine('Content-Type', $contentType);
$this->assertFalse($this->controller->requestHasContentType($this->request, TestAsset\RestfulTestController::CONTENT_TYPE_JSON));
}
+
+ public function testDispatchViaPatchWithoutIdentifierReturns405Response()
+ {
+ $entity = new stdClass;
+ $entity->name = 'foo';
+ $entity->type = 'standard';
+ $this->controller->entity = $entity;
+ $entity = array('name' => __FUNCTION__);
+ $string = http_build_query($entity);
+ $this->request->setMethod('PATCH')
+ ->setContent($string);
+ $result = $this->controller->dispatch($this->request, $this->response);
+ $this->assertInstanceOf('Zend\Http\Response', $result);
+ $this->assertEquals(405, $result->getStatusCode());
+ }
+
+ public function testDispatchWithUnrecognizedMethodReturns405Response()
+ {
+ $this->request->setMethod('PROPFIND');
+ $result = $this->controller->dispatch($this->request, $this->response);
+ $this->assertInstanceOf('Zend\Http\Response', $result);
+ $this->assertEquals(405, $result->getStatusCode());
+ }
}
View
24 tests/ZendTest/Mvc/Controller/TestAsset/RestfulTestController.php
@@ -41,6 +41,19 @@ public function delete($id)
}
/**
+ * Delete the collection
+ *
+ * @return \Zend\Http\Response
+ */
+ public function deleteList()
+ {
+ $response = $this->getResponse();
+ $response->setStatusCode(204);
+ $response->getHeaders()->addHeaderLine('X-Deleted', 'true');
+ return $response;
+ }
+
+ /**
* Return single resource
*
* @param mixed $id
@@ -99,6 +112,17 @@ public function patch($id, $data)
}
/**
+ * Replace the entire resource collection
+ *
+ * @param array|\Traversable $items
+ * @return array|\Traversable
+ */
+ public function replaceList($items)
+ {
+ return $items;
+ }
+
+ /**
* Update an existing resource
*
* @param mixed $id

0 comments on commit 21f4850

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