View source
<?php
define('SERVICES_REQUIRED_CTOOLS_API', '1.7');
function services_help($path, $arg) {
$output = NULL;
switch ($path) {
case 'admin/help#services':
$output = '<p>' . t('Visit the <a href="@handbook_url">Services Handbook</a> for help and information.', array(
'@handbook_url' => 'http://drupal.org/node/109782',
)) . '</p>';
break;
case 'admin/build/services':
$output = '<p>' . t('Services are collections of methods available to remote applications. They are defined in modules, and may be accessed in a number of ways through server modules. Visit the <a href="@handbook_url">Services Handbook</a> for help and information.', array(
'@handbook_url' => 'http://drupal.org/node/109782',
)) . '</p>';
$output .= '<p>' . t('All enabled services are shown. Click on any method to view information or test.') . '</p>';
break;
}
return $output;
}
function services_perm() {
return array(
'administer services',
'get taxonomy tree',
'get any binary files',
'get own binary files',
'save file information',
'get a system variable',
'set a system variable',
'perform unlimited index queries',
);
}
function services_menu() {
$items = array();
if (module_exists('ctools')) {
$endpoints = services_endpoint_load_all();
foreach ($endpoints as $endpoint) {
if (empty($endpoint->disabled)) {
$items[$endpoint->path] = array(
'title' => 'Services endpoint',
'access callback' => 'services_access_menu',
'page callback' => 'services_endpoint_callback',
'page arguments' => array(
$endpoint->name,
),
'type' => MENU_CALLBACK,
);
}
}
}
return $items;
}
function services_ctools_plugin_api($module, $api) {
if ($module == 'services' && $api == 'plugins') {
return array(
'version' => 3,
);
}
}
function services_ctools_plugin_directory($module, $type) {
if (!module_invoke('ctools', 'api_version', SERVICES_REQUIRED_CTOOLS_API)) {
return;
}
if ($type == 'export_ui') {
return 'plugins/export_ui';
}
}
function services_access_menu() {
return TRUE;
}
function services_theme() {
return array(
'services_endpoint_index' => array(
'template' => 'services_endpoint_index',
'arguments' => array(
'endpoints' => NULL,
),
),
'services_resource_table' => array(
'render element' => 'table',
'file' => 'services.admin.inc',
),
);
}
function services_get_servers() {
static $servers;
if (!$servers) {
$servers = array();
foreach (module_implements('server_info') as $module) {
$servers[$module] = call_user_func($module . '_server_info');
}
}
return $servers;
}
function services_endpoint_callback($endpoint_name) {
module_load_include('runtime.inc', 'services');
$endpoint = services_endpoint_load($endpoint_name);
$server = $endpoint->server;
if (function_exists($server . '_server')) {
if ($endpoint->debug) {
watchdog('services', 'Calling server: %server', array(
'%server' => $server . '_server',
), WATCHDOG_DEBUG);
}
services_set_server_info_from_array(array(
'module' => $server,
'endpoint' => $endpoint_name,
'endpoint_path' => $endpoint->path,
'debug' => $endpoint->debug,
'settings' => $endpoint->server_settings,
));
if ($endpoint->debug) {
watchdog('services', 'Server info main object: <pre>@info</pre>', array(
'@info' => print_r(services_server_info_object(), TRUE),
), WATCHDOG_DEBUG);
}
print call_user_func($server . '_server');
drupal_page_footer();
exit;
}
drupal_not_found();
}
function services_endpoint_new() {
ctools_include('export');
return ctools_export_new_object('services_endpoint');
}
function services_endpoint_load($name) {
ctools_include('export');
$result = ctools_export_load_object('services_endpoint', 'names', array(
$name,
));
if (isset($result[$name])) {
return $result[$name];
}
return FALSE;
}
function services_endpoint_load_all() {
ctools_include('export');
return ctools_export_load_object('services_endpoint');
}
function services_endpoint_save($endpoint) {
if (is_array($endpoint) && isset($endpoint['build_info'])) {
$endpoint = $endpoint['build_info']['args'][0];
}
foreach (array(
'server_settings',
'resources',
'authentication',
) as $endpoint_field) {
if (empty($endpoint->{$endpoint_field})) {
$endpoint->{$endpoint_field} = array();
}
}
ctools_export_crud_save('services_endpoint', $endpoint);
ctools_export_load_object_reset('services_endpoint');
menu_rebuild();
cache_clear_all('services:' . $endpoint->name . ':', 'cache', TRUE);
}
function services_endpoint_delete($endpoint) {
ctools_export_crud_delete('services_endpoint', $endpoint);
ctools_export_load_object_reset('services_endpoint');
menu_rebuild();
cache_clear_all('services:' . $endpoint->name . ':', 'cache', TRUE);
}
function services_endpoint_export($endpoint, $indent = '') {
ctools_include('export');
return ctools_export_object('services_endpoint', $endpoint, $indent);
}
function services_get_resources($endpoint_name = '') {
$cache_key = 'services:' . $endpoint_name . ':resources';
$resources = array();
if (($cache = cache_get($cache_key)) && isset($cache->data)) {
$resources = $cache->data;
}
else {
module_load_include('resource_build.inc', 'services');
$resources = _services_build_resources($endpoint_name);
cache_set($cache_key, $resources);
}
return $resources;
}
function services_resource_api_version_info() {
$info = array(
'default_version' => 3001,
'versions' => array(
3002,
),
);
$info['current_version'] = max($info['versions']);
return $info;
}
function services_services_resources() {
module_load_include('resource_build.inc', 'services');
return _services_core_resources();
}
function services_services_authentication_info() {
return array(
'title' => t('Session authentication'),
'description' => t("Uses Drupal's built in sessions to authenticate."),
'authenticate_call' => '_services_sessions_authenticate_call',
);
}
function _services_sessions_authenticate_call() {
$arg = func_get_args();
global $user;
$original_user = services_get_server_info('original_user');
if (strpos($arg[1]['callback'], 'login') !== FALSE) {
if ($original_user->uid != 0) {
$user = $original_user;
}
}
if (strpos($arg[1]['callback'], 'login') === FALSE) {
$user = $original_user;
}
}
function services_operation_class_info() {
return array(
'operations' => array(
'title' => t('CRUD operations'),
'name' => t('CRUD operation'),
'class_singular' => 'operation',
),
'actions' => array(
'title' => t('Actions'),
'name' => t('action'),
'class_singular' => 'action',
),
'relationships' => array(
'title' => t('Relationships'),
'name' => t('relationship'),
'class_singular' => 'relationship',
),
'targeted_actions' => array(
'title' => t('Targeted actions'),
'name' => t('targeted action'),
'class_singular' => 'targeted_action',
),
);
}
function services_controllers_list($endpoint) {
$controllers = array();
$class_info = services_operation_class_info();
$resources = services_get_resources($endpoint);
foreach ($resources as $resource_name => $resource) {
foreach ($class_info as $class_name => $class) {
if (empty($resource[$class_name])) {
continue;
}
foreach ($resource[$class_name] as $op_name => $op) {
$method = "{$resource_name}.{$op_name}";
if (empty($controllers[$method])) {
$controllers[$method] = $method;
}
else {
watchdog('services', 'Naming collision when listing controllers as methods. The %class %operation is not included in the listing.', array(
'%class' => $class['name'],
'%operation' => $op_name,
), WATCHDOG_WARNING);
}
}
}
}
return $controllers;
}
function services_controller_get($name, $endpoint) {
list($resource_name, $method) = explode('.', $name);
$resources = services_get_resources($endpoint);
if (isset($resources[$resource_name])) {
$res = $resources[$resource_name];
if (isset($res[$method])) {
return $res[$method];
}
else {
$class_info = services_operation_class_info();
foreach ($class_info as $class => $info) {
if (isset($res[$class]) && isset($res[$class][$method])) {
return $res[$class][$method];
}
}
}
}
}
function services_resources_as_procedures($resource, $resource_name) {
$methods = array();
$class_info = services_operation_class_info();
foreach ($class_info as $class_name => $class) {
if (empty($resource[$class_name])) {
continue;
}
foreach ($resource[$class_name] as $op_name => $op) {
$method_name = "{$resource_name}.{$op_name}";
if (empty($methods[$method_name])) {
$methods[$method_name] = array(
'method' => $method_name,
) + $op;
}
else {
watchdog('services', 'Naming collision when listing controllers as methods. The %class %operation wont be available for RPC-style servers.', array(
'%class' => $class['name'],
'%operation' => $op_name,
), WATCHDOG_WARNING);
}
}
}
return $methods;
}
function services_resource_build_index_query($schema, $order, $page, $fields, $service_params = array(), $primary_table, $primary_field, $page_size, $resource) {
$where = array();
$query_params = array();
$fields = db_escape_string($fields);
if ($fields_array = explode(',', $fields)) {
foreach ($fields_array as &$field) {
$field = $primary_table . '.' . trim($field);
}
$fields = implode(',', $fields_array);
}
$schema = db_escape_string($schema);
$table = $schema;
$schema = drupal_get_schema($schema);
if (is_array($service_params)) {
foreach ($service_params as $param_field => $param_value) {
if (!$schema['fields'][$param_field]) {
services_error('Parameter "' . $param_field . '" is not valid.');
}
$in_placeholders = array();
foreach (services_str_getcsv($param_value) as $single_value) {
$in_placeholders[] = db_type_placeholder($schema['fields'][$param_field]['type']);
$query_params[] = $single_value;
}
$where[] = $primary_table . '.' . $param_field . ' IN (' . implode(',', $in_placeholders) . ')';
}
}
$where = !empty($where) ? ' WHERE ' . implode(' AND ', $where) : '';
$default_limit = variable_get("services_{$resource}_index_page_size", 20);
if (!user_access('perform unlimited index queries') && $page_size > $default_limit) {
$page_size = $default_limit;
}
$sql = "SELECT {$fields} FROM {{$table}} AS {$primary_table} {$where} ORDER BY {$order}";
$sql = db_rewrite_sql($sql, $primary_table, $primary_field);
$result = db_query_range($sql, $query_params, $page * $page_size, $page_size);
return $result;
}
function services_str_getcsv($input, $delimiter = ',', $enclosure = '"', $escape = '\\') {
$ret = array();
if (!function_exists('str_getcsv')) {
$temp = fopen("php://memory", "rw");
fwrite($temp, $input);
fseek($temp, 0);
$ret = fgetcsv($temp, 0, $delimiter, $enclosure);
fclose($temp);
}
else {
$ret = str_getcsv($input, $delimiter, $enclosure, $escape);
}
return $ret;
}
function services_resource_build_index_list($results, $type, $field) {
$items = array();
foreach ($results as $result) {
if ($uri = services_resource_uri(array(
$type,
$result->{$field},
))) {
$result->uri = $uri;
if ($type == 'user') {
services_remove_user_data($result);
}
}
$items[] = $result;
}
return $items;
}
function services_remove_user_data(&$account) {
unset($account->pass);
if (!user_access('administer users')) {
unset($account->mail);
unset($account->init);
}
drupal_alter('services_account_object', $account);
}