restws.entity.inc in RESTful Web Services 7
Same filename and directory in other branches
RESTful web services module integration for entities.
File
restws.entity.incView source
<?php
/**
* @file
* RESTful web services module integration for entities.
*/
/**
* Specifies CRUD and access methods for resources.
*/
interface RestWSResourceControllerInterface {
/**
* Returns the property info for the given resource.
*
* @return array
* An array structured as hook_entity_property_info() is structured for an
* entity type.
*/
public function propertyInfo();
/**
* Returns a metadata wrapper for the resource with the given id.
*
* @return EntityStructureWrapper
* Metadata wrapper of the resource.
*/
public function wrapper($id);
/**
* Create a new resource.
*
* @param array $values
* Array of values for properties of the resource, keyed by property
* name. At least for all required properties values have to be given.
*
* @return int|string
* The id of the newly created resource.
*/
public function create(array $values);
/**
* Returns an existing resource.
*
* @param int|string $id
* The id of the resource that should be returned.
*
* @return
* The internal representation of the resource.
*/
public function read($id);
/**
* Update an existing resource.
*
* @param int|string $id
* The id of the resource that should be updated.
* @param array $values
* An array of values for the properties to be updated, keyed by property
* name.
*/
public function update($id, array $values);
/**
* Delete an existing resource.
*
* @param int|string $id
* The id of the resource that should be deleted.
*/
public function delete($id);
/**
* Determines access for a given operation and resource.
*
* @param string $op
* Either 'create', 'view' (= read), 'update' or 'delete'.
* @param int|string $id
* The id of the resource.
*
* @see entity_access()
*/
public function access($op, $id);
/**
* Returns the name of the resource.
*/
public function resource();
}
/**
* Controller for entity-bases resources.
*/
class RestWSEntityResourceController implements RestWSResourceControllerInterface {
protected $entityType, $entityInfo;
public function __construct($name, $info) {
$this->entityType = $name;
$this->entityInfo = entity_get_info($name);
}
public function propertyInfo() {
return entity_get_property_info($this->entityType);
}
public function wrapper($id) {
return entity_metadata_wrapper($this->entityType, $id);
}
public function read($id) {
return $this
->wrapper($id)
->value();
}
public function create(array $values) {
// Make sure that bundle information is present on entities that have
// bundles.
$entity_info = entity_get_info($this->entityType);
if (isset($entity_info['bundle keys'])) {
foreach ($entity_info['bundle keys'] as $bundle_key) {
if (!array_key_exists($bundle_key, $values)) {
throw new RestWSException('Missing bundle: ' . $bundle_key, 406);
}
}
}
try {
$wrapper = entity_property_values_create_entity($this->entityType, $values);
// Get the ID and bundle property names.
$entity_keys = array_intersect_key($entity_info['entity keys'], array(
'id' => 1,
'bundle' => 1,
));
foreach (array_keys($values) as $name) {
// Don't check access on entity keys for new entities. Otherwise,
// property access checks will fail for, e.g., node type, which
// requires the 'administer nodes' permission to set.
// @see entity_metadata_node_entity_property_info().
if (!in_array($name, $entity_keys)) {
if (!$this
->checkPropertyAccess($wrapper, $name, $wrapper->{$name})) {
throw new RestWSException(t('Not authorized to set property @p', array(
'@p' => $name,
)), 403);
}
}
}
} catch (EntityMetadataWrapperException $e) {
throw new RestWSException($e
->getMessage(), 406);
}
$properties = $wrapper
->getPropertyInfo();
$diff = array_diff_key($values, $properties);
if (!empty($diff)) {
throw new RestWSException('Unknown data properties: ' . implode(' ', array_keys($diff)) . '.', 406);
}
$wrapper
->save();
return $wrapper
->getIdentifier();
}
public function update($id, array $values) {
$wrapper = $this
->wrapper($id);
$entity_info = $wrapper
->entityInfo();
// Get the ID and bundle property names.
$entity_keys = array_intersect_key($entity_info['entity keys'], array(
'id' => 1,
'bundle' => 1,
));
try {
foreach ($values as $name => $value) {
if (in_array($name, $entity_keys)) {
// We don't allow changing the entity ID or bundle.
if ($wrapper->{$name}
->value() != $value) {
throw new RestWSException('Unable to change ' . $name, 422);
}
}
else {
$wrapper->{$name}
->set($value);
if (!$this
->checkPropertyAccess($wrapper, $name, $wrapper->{$name})) {
throw new RestWSException(t('Not authorized to set property @p', array(
'@p' => $name,
)), 403);
}
}
}
} catch (EntityMetadataWrapperException $e) {
throw new RestWSException($e
->getMessage(), 406);
}
$wrapper
->save();
}
public function delete($id) {
entity_delete($this->entityType, $id);
}
public function access($op, $id) {
return entity_access($op, $this->entityType, isset($id) ? $this
->wrapper($id)
->value() : NULL);
}
public function resource() {
return $this->entityType;
}
/**
* Helper method to check access on a property.
*
* @todo Remove this once Entity API properly handles text format access.
*
* @param EntityMetadataWrapper $entity
* The parent entity.
* @param string $property_name
* The property name on the entity.
* @param EntityMetadataWrapper $property
* The property whose access is to be checked.
*
* @return bool
* TRUE if the current user has access to set the property, FALSE otherwise.
*/
protected function checkPropertyAccess($entity, $property_name, $property) {
global $user;
// Special case node author: we allow access if set to the current user.
if ($entity
->type() == 'node' && $property_name == 'author' && $property
->raw() == $GLOBALS['user']->uid) {
return TRUE;
}
elseif ($property
->type() == 'text_formatted' && $property->format
->value()) {
$format = (object) array(
'format' => $property->format
->value(),
);
if (!filter_access($format)) {
return FALSE;
}
}
return $property
->access('edit');
}
}
Classes
Name | Description |
---|---|
RestWSEntityResourceController | Controller for entity-bases resources. |
Interfaces
Name | Description |
---|---|
RestWSResourceControllerInterface | Specifies CRUD and access methods for resources. |