From d63188d84d0717750b0dc67e025c43968ea6391e Mon Sep 17 00:00:00 2001 From: Dries Date: Fri, 21 Dec 2012 12:18:28 -0500 Subject: [PATCH] Issue #1839366 by klausi: Added REST module: PUT/update. --- .../Plugin/rest/resource/EntityResource.php | 37 ++++++++++ .../rest/lib/Drupal/rest/Tests/UpdateTest.php | 73 +++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php index bf8c7c1c020..19ef39a48d6 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php @@ -85,6 +85,43 @@ class EntityResource extends ResourceBase { } } + /** + * Responds to entity PUT requests. + * + * @param mixed $id + * The entity ID. + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity. + * + * @return \Drupal\rest\ResourceResponse + * The HTTP response object. + * + * @throws \Symfony\Component\HttpKernel\Exception\HttpException + */ + public function put($id, EntityInterface $entity) { + if (empty($id)) { + throw new NotFoundHttpException(); + } + $definition = $this->getDefinition(); + $original_entity = entity_load($definition['entity_type'], $id); + // We don't support creating entities with PUT, so we throw an error if + // there is no existing entity. + if ($original_entity == FALSE) { + throw new NotFoundHttpException(); + } + $info = $entity->entityInfo(); + // Make sure that the entity ID is the one provided in the URL. + $entity->{$info['entity_keys']['id']} = $id; + try { + $entity->save(); + // Update responses have an empty body. + return new ResourceResponse(NULL, 204); + } + catch (EntityStorageException $e) { + throw new HttpException(500, 'Internal Server Error', $e); + } + } + /** * Responds to entity PATCH requests. * diff --git a/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php b/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php index eed2b2ff744..83729aab824 100644 --- a/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php +++ b/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php @@ -96,4 +96,77 @@ class UpdateTest extends RESTTestBase { $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PATCH', $serialized, 'application/vnd.drupal.ld+json'); $this->assertResponse(404); } + + /** + * Tests several valid and invalid PUT update requests on test entities. + */ + public function testPutUpdate() { + $serializer = drupal_container()->get('serializer'); + // @todo once EntityNG is implemented for other entity types test all other + // entity types here as well. + $entity_type = 'entity_test'; + + $this->enableService('entity:' . $entity_type); + // Create a user account that has the required permissions to create + // resources via the web API. + $account = $this->drupalCreateUser(array('restful put entity:' . $entity_type)); + $this->drupalLogin($account); + + // Create an entity and save it to the database. + $entity = $this->entityCreate($entity_type); + $entity->save(); + + // Create a second entity that will overwrite the original. + $update_values = $this->entityValues($entity_type); + $update_entity = entity_create($entity_type, $update_values); + // Copy the identifier properties over from the original. + $update_entity->uuid->value = $entity->uuid(); + $update_entity->id->value = $entity->id(); + + $serialized = $serializer->serialize($update_entity, 'drupal_jsonld'); + // Update the entity over the web API. + $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json'); + $this->assertResponse(204); + + // Re-load the updated entity from the database. + $entity = entity_load($entity_type, $entity->id(), TRUE); + // @todo Don't check the user reference field for now until deserialization + // for entity references is implemented. + unset($update_values['user_id']); + foreach ($update_values as $property => $value) { + $update_value = $update_entity->{$property}->value; + $stored_value = $entity->{$property}->value; + $this->assertEqual($stored_value, $update_value, 'Updated property ' . $property . ' expected: ' . $update_value . ', actual: ' . $stored_value); + } + + // Try to delete a property. + unset($update_entity->field_test_text); + $serialized = $serializer->serialize($update_entity, 'drupal_jsonld'); + $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json'); + $this->assertResponse(204); + + // Re-load the updated entity from the database. + $entity = entity_load($entity_type, $entity->id(), TRUE); + $this->assertTrue($entity->field_test_text->isEmpty(), 'Property has been deleted.'); + + // Try to create an entity with ID 9999. + $this->httpRequest('entity/' . $entity_type . '/9999', 'PUT', $serialized, 'application/vnd.drupal.ld+json'); + $this->assertResponse(404); + $loaded_entity = entity_load($entity_type, 9999, TRUE); + $this->assertFalse($loaded_entity, 'Entity 9999 was not created.'); + + // Try to update an entity without proper permissions. + $this->drupalLogout(); + $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json'); + $this->assertResponse(403); + + // Try to update a resource which is not web API enabled. + $this->enableService(FALSE); + // Reset cURL here because it is confused from our previously used cURL + // options. + unset($this->curlHandle); + $this->drupalLogin($account); + $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json'); + $this->assertResponse(404); + } }