Skip to content

Instantly share code, notes, and snippets.

@perifer
Created January 13, 2010 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save perifer/276243 to your computer and use it in GitHub Desktop.
Save perifer/276243 to your computer and use it in GitHub Desktop.
<?php
// Relevant code from running_route.module
/**
* Implementation of hook_autoload_info().
*/
function running_route_autoload_info() {
return array(
'RunningRouteResource' => array(
'file' => 'RunningRouteResource.php',
),
);
}
/**
* Implementation of hook_services_resources().
*/
function running_route_services_resources() {
return array(
'running-route' => array(
'retrieve' => array(
'help' => 'Retrieves a route',
'callback' => 'RunningRouteResource::retrieve',
'access callback' => 'RunningRouteResource::access',
'access arguments' => array('view'),
'access arguments append' => true,
'args' => array(
array(
'name' => 'nid',
'type' => 'int',
'description' => 'The id of the item to get',
'source' => array('path' => '0'),
'optional' => false,
),
),
),
'create' => array(
'help' => 'Creates a content item',
'callback' => 'RunningRouteResource::create',
'access arguments' => array('access content'),
'access arguments append' => false,
'args' => array(
array(
'name' => 'data',
'type' => 'struct',
'description' => '',
'source' => 'data',
'optional' => false,
),
),
),
'update' => array(
'help' => 'Updates a content item',
'callback' => 'RunningRouteResource::update',
'access callback' => 'RunningRouteResource::access',
'access arguments' => array('update'),
'access arguments append' => true,
'args' => array(
array(
'name' => 'nid',
'type' => 'int',
'description' => 'The id of the item to update',
'source' => array('path' => '0'),
'optional' => false,
),
array(
'name' => 'data',
'type' => 'struct',
'description' => 'The item data object',
'source' => 'data',
'optional' => false,
),
),
),
'delete' => array(
'help' => 'Deletes a content item',
'callback' => 'RunningRouteResource::delete',
'access callback' => 'RunningRouteResource::access',
'access arguments' => array('delete'),
'access arguments append' => true,
'args' => array(
array(
'name' => 'nid',
'type' => 'int',
'description' => 'The nid of the content item to delete',
'source' => array('path' => '0'),
'optional' => false,
),
),
),
'index' => array(
'help' => 'Retrieves a listing of content items',
'callback' => 'RunningRouteResource::index',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'access arguments append' => false,
'args' => array(array(
'name' => 'page',
'type' => 'int',
'description' => '',
'source' => array(
'param' => 'page',
),
'optional' => true,
'default value' => 0,
),
array(
'name' => 'fields',
'type' => 'string',
'description' => '',
'source' => array(
'param' => 'fields',
),
'optional' => true,
'default value' => array(),
),
array(
'name' => 'parameters',
'type' => 'array',
'description' => '',
'source' => 'param',
'optional' => true,
'default value' => array(),
),
),
),
),
);
}
/////// NOTE: THIS ENDPOINT DEFINITION IS OUTDATED. THE LATEST VERSION OF SERVICES 3 uses chaostools (i.e, /////// build your endpoint in the admin interface and export it to get a definition to past into code
/**
* Implementation of hook_services_endpoints().
*/
function running_route_services_endpoints() {
return array(
'running-route' => array(
'title' => 'Running Route API',
'server' => 'rest_server',
'path' => 'api',
'resources' => array(
'running-route' => array(
'operations' => array(
'create' => array(
'enabled' => TRUE,
),
'retrieve' => array(
'enabled' => TRUE,
),
'update' => array(
'enabled' => TRUE,
),
'delete' => array(
'enabled' => TRUE,
),
'index' => array(
'enabled' => TRUE,
),
),
),
),
),
);
}
// Example of a REST client to an Services endpoint. This specific example is in JS but could of course be in any language.
var runningRoute = {
'apiPath': '/api/running-route'
};
// REST functions.
runningRoute.create = function(route) {
var obj = {
'vertices': route.toArray(),
'lat': route.polyline.getVertex(0).lat(),
'lng': route.polyline.getVertex(0).lng(),
'length': route.getLength(),
'title': 'TODO: title',
'text': 'TODO: text',
'public': '1'
};
$.ajax({
type: "POST",
url: this.apiPath,
data: JSON.stringify(obj),
dataType: 'json',
contentType: 'application/json',
success: function(response){
alert("Route saved. Nid: " + response.nid);
}
});
};
runningRoute.retreive = function() {
// TODO: GET data from a single route.
};
runningRoute.update = function(route) {
var obj = {
'vertices': route.toArray(),
'lat': route.polyline.getVertex(0).lat(),
'lng': route.polyline.getVertex(0).lng(),
'length': route.getLength(),
'title': 'TODO: title UPDATED',
'text': 'TODO: text UPDATED',
'public': '1'
};
$.ajax({
type: "PUT",
url: this.apiPath + '/' + route.nid,
data: JSON.stringify(obj),
dataType: 'json',
contentType: 'application/json',
success: function(response){
alert("Route updated. Nid: " + response.nid);
}
});
};
runningRoute.del = function(route) {
$.ajax({
type: "DELETE",
url: this.apiPath + '/' + route.nid,
dataType: 'json',
contentType: 'application/json',
success: function(status){
if (status) {
alert("Route deleted.");
}
}
});
};
runningRoute.index = function () {
$.getJSON(this.apiPath, function(data){
$.each(data, function(i, route){
var r = new runningRoute.Route([route.lat, route.lng], route.vertices, route.length, route.nid);
r.drawRouteMarker();
});
});
};
<?php
class RunningRouteResource {
/**
* Creates a running route.
*/
public static function create($data) {
global $user;
// Defaults.
$node = (object)array(
'created' => time(),
'changed' => time(),
'uid' => $user->uid,
'type' => 'running_route',
);
return self::nodeWrite($node, $data);
}
/**
* Retrieves a running route
*
* @param int $nid
* The id of the item to get
* @return object
*
*/
public static function retrieve($nid) {
$node = node_load($nid);
if ($node->type == 'running_route') {
$node->uri = services_resource_uri(array('running-route', $node->nid));
// Whitelisting of data we send out to the client.
return (object)array(
'title' => $node->title,
'text' => $node->body,
'changed' => $node->changed,
'created' => $node->created,
'uid' => $node->uid,
'vertices' => self::verticesToArray($node->vertices),
'lat' => $node->bondgeo_lat,
'lng' => $node->bondgeo_lng,
'length' => $node->length,
);
}
}
/**
* Updates a running route.
*
* @param int $nid
* The id (node id) of the running route to update
* @param object $data
* The data object
* @return object
*
*/
public static function update($nid, $data) {
$node = node_load($nid);
$node->changed = time();
return self::nodeWrite($node, $data);
}
/**
* Deletes a running route.
*
* @param int $nid
* The nid of the content item to delete
* @return bool
*
*/
public static function delete($nid) {
node_delete($nid);
return TRUE;
}
/**
* Retrieves a listing of running routes.
*
* @param int $page
* @param string $fields
* @param array $parameters
* @return array
*
*/
public static function index($page = 0, $fields = array(), $parameters = array()) {
$sql = "SELECT n.nid, n.title, n.created, r.vertices, r.length, b.lat, b.lng FROM node n INNER JOIN {lob_running_route} r ON n.nid = r.nid INNER JOIN {bondgeo_position} b ON n.nid = b.nid";
$res = db_query_range($sql, $page * 20, 20);
$nodes = array();
while ($node = db_fetch_object($res)) {
$node->url = url('node/' . $node->nid, array(
'absolute' => TRUE,
));
$node->uri = services_resource_uri(array('running-route', $node->nid));
$node->vertices = self::verticesToArray($node->vertices);
$node->vertices = ($node->vertices);
$nodes[] = $node;
}
return $nodes;
}
/**
* Helper function that maps incoming data to the proper node attributes
*
* @param object $node
* @param object $data
* @return object
*/
private static function nodeWrite($node, $data) {
$attr = array(
'title' => array('required' => TRUE),
'text' => array(
'to' => 'body',
'required' => TRUE,
),
'lat' => array(
'to' => 'bondgeo_lat',
'required' => TRUE,
),
'lng' => array(
'to' => 'bondgeo_lng',
'required' => TRUE,
),
'vertices' => array(
'to' => 'running_route_vertices',
'required' => TRUE,
'adapt' => 'adaptVertices',
),
'length' => array(
'to' => 'running_route_length',
'required' => TRUE,
),
'public' => array(
'to' => 'running_route_public',
),
);
// Transfer attributes from data
foreach ($attr as $name => $info) {
if (isset($data->$name)) {
$to = $name;
if (!empty($info['to'])) {
$to = $info['to'];
}
$node->$to = $data->$name;
if (isset($info['adapt'])) {
call_user_func('RunningRouteResource::' . $info['adapt'], $node);
}
}
else if ($info['required']) {
return services_error("Missing attribute {$name}", 406);
}
}
node_save($node);
return (object)array(
'nid' => $node->nid,
'uri' => services_resource_uri(array('running-route', $node->nid)),
'url' => url('node/' . $node->nid, array('absolute' => TRUE))
);
}
public static function access($op='view', $args=array()) {
global $user;
if ($op == 'create') {
$node = $args[0];
}
else {
$node = node_load($args[0]);
}
return node_access($op, $node);
}
public static function adaptVertices(&$node) {
$node->running_route_vertices = self::arrayToVertices($node->running_route_vertices);
}
private static function verticesToArray($vertices) {
return explode(',', $vertices);
}
private static function arrayToVertices($vertices) {
return implode($vertices, ',');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment