Last active
June 13, 2022 14:36
-
-
Save laradevitt/6ab86bf7ebbd3215b20b to your computer and use it in GitHub Desktop.
Extends Drupal Services module to handle requests on node resource containing path alias instead of node id.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name = Services Node Alias to System Path | |
description = Uses the Services API to convert requests containing a node path alias to a system path (e.g., 'node/5'). | |
core = 7.x | |
version = 7.x-1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @file | |
* Code for the Services Node Alias to System Path module. | |
*/ | |
/** | |
* Implements hook_services_resources_alter(). | |
* | |
* In order to handle aliases with multiple parts (e.g. about/media), the | |
* string in the request should have slashes converted to triple dashes (---). | |
*/ | |
function services_node_alias_to_system_path_services_resources_alter(&$resources, &$endpoint) { | |
$args = array( | |
'name' => 'alias', | |
'optional' => FALSE, | |
'source' => array('path' => 0), | |
'type' => 'string', | |
'description' => 'The alias node to get', | |
); | |
$resources['node']['operations']['retrieve']['args'] = array($args); | |
$resources['node']['operations']['retrieve']['callback'] = '_services_node_alias_to_system_path_retrieve'; | |
$resources['node']['operations']['retrieve']['access callback'] = '_services_node_alias_to_system_path_node_resource_access'; | |
$resources['node']['operations']['retrieve']['access arguments append'] = TRUE; | |
} | |
function _services_node_alias_to_system_path_retrieve($alias){ | |
$nid = _services_node_alias_to_system_path_find_nid($alias); | |
if ($nid) { | |
return _node_resource_retrieve($nid); | |
} | |
return FALSE; | |
} | |
function _services_node_alias_to_system_path_node_resource_access($op, $alias) { | |
$nid = _services_node_alias_to_system_path_find_nid($alias[0]); | |
if ($nid) { | |
return _node_resource_access($op, array($nid)); | |
} | |
return services_error(t('Content could not be found.'), 404); | |
} | |
/** | |
* Helper function. | |
*/ | |
function _services_node_alias_to_system_path_find_nid($alias) { | |
// Convert dashes to slashes. | |
$alias = str_replace('---', '/', $alias); | |
// Look up internal path. | |
$path = drupal_get_normal_path($alias); | |
// If drupal_get_normal_path() returns the alias, equate this to FALSE (no | |
// internal path available). | |
$is_node = $path !== $alias; | |
if ($is_node && ctype_digit($nid = str_replace('node/', '', $path))) { | |
return $nid; | |
} | |
return FALSE; | |
} |
I know it might be a bit late, but I thought I'd share.
I got something working based on your gist.
Basically, I added more arg to the resource alteration to make it work with the node path alias.
The number of arguments to add depends on your URL patterns (5 in the code below)
Query URL: GET <root domain> / <endpoint> / node / <path alias>
example.com/endpoint/node/pathalias1/pathalias2/.../titlenode
function YOUR_MODULE_services_resources_alter(&$resources, &$endpoint) {
if (isset($endpoint) && $endpoint->name == 'YOUR_ENDPOINT_PATH') {
if (isset($resources['node']['operations']['retrieve'])) {
$resources['node']['operations']['retrieve'] = array(
'help' => 'Retrieve a node with a path !',
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'),
'callback' => 'YOUR_MODULE_node_resource_retrieve',
// Add as many arg as needed depending on URL patterns
'args' => array(
array(
'name' => 'arg0',
'optional' => TRUE,
'source' => array(
'path' => '0'
),
'type' => 'string',
'description' => 'The argument 0 of the path of the node to retrieve',
),
array(
'name' => 'arg1',
'optional' => TRUE,
'source' => array(
'path' => '1'
),
'type' => 'string',
'description' => 'The argument 1 of the path of the node to retrieve',
),
array(
'name' => 'arg2',
'optional' => TRUE,
'source' => array(
'path' => '2'
),
'type' => 'string',
'description' => 'The argument 2 of the path of the node to retrieve',
),
array(
'name' => 'arg3',
'optional' => TRUE,
'source' => array(
'path' => '3'
),
'type' => 'string',
'description' => 'The argument 3 of the path of the node to retrieve',
),
array(
'name' => 'arg4',
'optional' => TRUE,
'source' => array(
'path' => '4'
),
'type' => 'string',
'description' => 'The argument 4 of the path of the node to retrieve',
),
),
'access callback' => 'YOUR_MODULE_node_resource_access',
'access arguments' => array('view'),
'access arguments append' => TRUE,
);
}
}
}
function YOUR_MODULE_node_resource_access($op = 'view', $args = array()) {
// Access logic here
// In the module services, _node_resource_access expects node/$nid
return true;
}
function YOUR_MODULE_node_resource_retrieve($arg0, $arg1, $arg2, $arg3, $arg4) {
// Retrieve path by joining arguments
$alias = join('/', array_filter(array($arg0, $arg1, $arg2, $arg3, $arg4)));
// Look up internal path.
$path = drupal_get_normal_path($alias);
// Check if the alias exists and the current user has access to it.
if (!drupal_valid_path($path)) {
return FALSE;
}
// If drupal_get_normal_path() returns the alias, equate this to FALSE (no
// internal path available).
$is_node = $path !== $alias;
if ($is_node && ctype_digit($nid = str_replace('node/', '', $path))) {
$node = node_load($nid);
if ($node) {
$uri = entity_uri('node', $node);
$node->path = url($uri['path'], array('absolute' => TRUE));
// Unset uri as it has complete entity and this
// cause never ending recursion in rendering.
unset($node->uri);
}
//Lets check field_permissions
$node = services_field_permissions_clean('view', 'node', $node);
return $node;
}
return FALSE;
}
@cavla Thanks for sharing!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Original gist only worked on single-argument aliases (e.g., media, not about/media). Revised code expects separating slashes to be converted to triple dashes (---):
I would prefer to handle this with a query parameter rather than path argument, which wouldn't require converting the slashes, but I couldn't get it to work. If anyone has a suggestion in this regard, please comment!
With parameters (doesn't work):
Request: