View source
<?php
interface RestWSFormatInterface {
public function viewResource($resourceController, $id);
public function createResource($resourceController, $data);
public function updateResource($resourceController, $id, $data);
public function deleteResource($resourceController, $id);
public function mimeType();
public function getName();
}
abstract class RestWSBaseFormat implements RestWSFormatInterface {
protected $formatName;
protected $formatInfo;
public function __construct($name, $info) {
$this->formatName = $name;
$this->formatInfo = $info;
}
public function viewResource($resourceController, $id) {
$values = self::getData($resourceController
->wrapper($id));
return $this
->serialize($values);
}
public function createResource($resourceController, $data) {
$values = $this
->unserialize($data);
$id = $resourceController
->create($values);
$ref = self::getResourceReference($resourceController
->resource(), $id);
return $this
->serialize($ref);
}
public function updateResource($resourceController, $id, $data) {
$values = $this
->unserialize($data);
$resourceController
->update($id, $values);
return $this
->serialize(array());
}
public function deleteResource($resourceController, $id) {
$resourceController
->delete($id);
return $this
->serialize(array());
}
public function mimeType() {
return $this->formatInfo['mime type'];
}
public function getName() {
return $this->formatName;
}
public static function getData($wrapper) {
$data = array();
$filtered = restws_property_access_filter($wrapper);
foreach ($filtered as $name => $property) {
try {
if ($property instanceof EntityDrupalWrapper) {
if ($id = $property
->getIdentifier()) {
$data[$name] = self::getResourceReference($property
->type(), $id);
}
}
elseif ($property instanceof EntityValueWrapper) {
$data[$name] = $property
->value();
}
elseif ($property instanceof EntityListWrapper || $property instanceof EntityStructureWrapper) {
$data[$name] = self::getData($property);
}
} catch (EntityMetadataWrapperException $e) {
}
}
return $data;
}
public static function getResourceReference($resource, $id) {
return array(
'uri' => restws_resource_uri($resource, $id),
'id' => $id,
'resource' => $resource,
);
}
}
function restws_property_access_filter($wrapper) {
$filtered = array();
foreach ($wrapper as $name => $property) {
if ($property
->access('view')) {
$filtered[$name] = $property;
}
}
return $filtered;
}
class RestWSFormatJSON extends RestWSBaseFormat {
public function serialize($values) {
return drupal_json_encode($values);
}
public function unserialize($data) {
return drupal_json_decode($data);
}
}
class RestWSFormatXML extends RestWSBaseFormat {
public function viewResource($resourceController, $id) {
$xml = new DOMDocument('1.0', 'utf-8');
$element = $xml
->createElement($resourceController
->resource());
self::addToXML($xml, $element, $resourceController
->wrapper($id));
$xml
->appendChild($element);
return $xml
->saveXML();
}
public function createResource($resourceController, $data) {
$values = $this
->unserialize($data);
$id = $resourceController
->create($values);
$xml = new DOMDocument('1.0', 'utf-8');
$element = $xml
->createElement('uri');
self::setXMLReference($element, $resourceController
->resource(), $id);
$xml
->appendChild($element);
return $xml
->saveXML();
}
public function serialize($data) {
$xml = new DOMDocument('1.0', 'utf-8');
return $xml
->saveXML();
}
public function unserialize($data) {
libxml_disable_entity_loader(TRUE);
$xml = simplexml_load_string($data);
return self::xmlToArray($xml);
}
public static function xmlToArray(SimpleXMLElement $xml) {
$children = $xml
->children();
foreach ($xml
->children() as $name => $element) {
$result[$name] = self::xmlToArray($element);
}
if (!isset($result)) {
$result = ($string = (string) $xml) ? $string : NULL;
}
return $result;
}
public static function addToXML(DOMDocument $doc, DOMNode $parent, $wrapper) {
$filtered = restws_property_access_filter($wrapper);
foreach ($filtered as $name => $property) {
try {
if ($property instanceof EntityDrupalWrapper) {
if ($id = $property
->getIdentifier()) {
$element = $doc
->createElement(is_numeric($name) ? 'item' : $name);
$parent
->appendChild($element);
self::setXMLReference($element, $property
->type(), $id);
}
}
elseif ($property instanceof EntityValueWrapper) {
$escaped = $doc
->createTextNode($property
->value());
$element = $doc
->createElement(is_numeric($name) ? 'item' : $name);
$element
->appendChild($escaped);
$parent
->appendChild($element);
}
elseif ($property instanceof EntityListWrapper || $property instanceof EntityStructureWrapper) {
$element = $doc
->createElement(is_numeric($name) ? 'item' : $name);
$parent
->appendChild($element);
self::addToXML($doc, $element, $property);
}
} catch (EntityMetadataWrapperException $e) {
}
}
}
public static function setXMLReference(DOMElement $node, $resource, $id) {
$node->nodeValue = restws_resource_uri($resource, $id);
$node
->setAttribute('resource', $resource);
$node
->setAttribute('id', $id);
}
}
class RestWSFormatRDF extends RestWSBaseFormat {
protected $namespaces;
public function __construct($name, $info) {
parent::__construct($name, $info);
$this->namespaces = rdf_get_namespaces();
$this->namespaces['rdf'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
}
public function viewResource($resourceController, $id) {
$xml = new DOMDocument('1.0', 'utf-8');
$rdf_element = $xml
->createElementNS($this->namespaces['rdf'], 'rdf:RDF');
$xml
->appendChild($rdf_element);
$element = $xml
->createElementNS($this->namespaces['rdf'], 'rdf:Description');
$element
->setAttributeNS($this->namespaces['rdf'], 'rdf:about', restws_resource_uri($resourceController
->resource(), $id));
$entity = $resourceController
->read($id);
if (!empty($entity->rdf_mapping['rdftype'])) {
foreach ($entity->rdf_mapping['rdftype'] as $rdf_type) {
$type_element = $xml
->createElementNS($this->namespaces['rdf'], 'rdf:type');
list($ns, $name) = explode(':', $rdf_type);
$type_element
->setAttributeNS($this->namespaces['rdf'], 'rdf:resource', $this->namespaces[$ns] . $name);
$element
->appendChild($type_element);
}
}
$this
->addToXML($xml, $element, $resourceController
->wrapper($id));
$rdf_element
->appendChild($element);
return $xml
->saveXML();
}
public function createResource($resourceController, $data) {
throw new RestWSException('Not implemented', 501);
}
public function updateResource($resourceController, $id, $data) {
throw new RestWSException('Not implemented', 501);
}
public function addToXML(DOMDocument $doc, DOMNode $parent, $wrapper) {
$filtered = restws_property_access_filter($wrapper);
foreach ($filtered as $name => $property) {
try {
if ($property instanceof EntityDrupalWrapper) {
if ($id = $property
->getIdentifier()) {
$element = $this
->addRdfElement($doc, $wrapper, $name);
$parent
->appendChild($element);
$this
->addReference($doc, $element, $property
->type(), $id);
}
}
elseif ($property instanceof EntityValueWrapper) {
$element = $this
->addRdfElement($doc, $wrapper, $name);
$parent
->appendChild($element);
$element->nodeValue = $property
->value();
}
elseif ($property instanceof EntityListWrapper || $property instanceof EntityStructureWrapper) {
$element = $this
->addRdfElement($doc, $wrapper, $name);
$parent
->appendChild($element);
$node = $doc
->createElementNS($this->namespaces['rdf'], 'rdf:Description');
$element
->appendChild($node);
$this
->addToXML($doc, $node, $property);
}
} catch (EntityMetadataWrapperException $e) {
}
}
}
public function addReference(DomDocument $doc, DOMElement $node, $resource, $id) {
$element = $doc
->createElementNS($this->namespaces['rdf'], 'rdf:Description');
$element
->setAttributeNS($this->namespaces['rdf'], 'rdf:about', restws_resource_uri($resource, $id));
$node
->appendChild($element);
}
public function addRdfElement(DOMDOcument $doc, EntityMetadataWrapper $wrapper, $name) {
if ($wrapper instanceof EntityDrupalWrapper) {
$entity = $wrapper
->value();
if (!empty($entity->rdf_mapping[$name])) {
$predicate = reset($entity->rdf_mapping[$name]['predicates']);
list($ns, $qname) = explode(':', $predicate);
$element = $doc
->createElementNS($this->namespaces[$ns], $predicate);
if (!empty($entity->rdf_mapping[$name]['datatype'])) {
$element
->setAttributeNS($this->namespaces['rdf'], 'rdf:datatype', $entity->rdf_mapping[$name]['datatype']);
}
}
}
if (!isset($element)) {
$element = $doc
->createElementNS(url('', array(
'absolute' => TRUE,
)), 'site:' . (is_numeric($name) ? 'item' : $name));
}
return $element;
}
}