Created
November 28, 2011 21:30
-
-
Save arturo-c/1402160 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
diff --git a/plugins/export_ui/services_ctools_export_ui.class.php b/plugins/export_ui/services_ctools_export_ui.class.php | |
index fe4a51d..99de0c4 100644 | |
--- a/plugins/export_ui/services_ctools_export_ui.class.php | |
+++ b/plugins/export_ui/services_ctools_export_ui.class.php | |
@@ -23,6 +23,14 @@ class services_ctools_export_ui extends ctools_export_ui { | |
return drupal_get_form('services_edit_form_endpoint_authentication', $item); | |
} | |
+ /** | |
+ * Page callback for the server page. | |
+ */ | |
+ function server_page($js, $input, $item) { | |
+ drupal_set_title($this->get_page_title('server', $item)); | |
+ return drupal_get_form('services_edit_form_endpoint_server', $item); | |
+ } | |
+ | |
// Avoid standard submit of edit form by ctools. | |
function edit_save_form($form_state) { } | |
@@ -58,8 +66,7 @@ function services_edit_form_endpoint_authentication($form_state) { | |
$form['message'] = array( | |
'#type' => 'item', | |
'#title' => t('Authentication'), | |
- '#description' => t('No authentication modules are installed, standard ' . | |
- 'Drupal session based security will be used.'), | |
+ '#description' => t('No authentication modules are installed, all requests will be anonymous.'), | |
); | |
return $form; | |
} | |
@@ -67,8 +74,7 @@ function services_edit_form_endpoint_authentication($form_state) { | |
$form['message'] = array( | |
'#type' => 'item', | |
'#title' => t('Authentication'), | |
- '#description' => t('No authentication modules are enabled, standard ' . | |
- 'Drupal session based security will be used.'), | |
+ '#description' => t('No authentication modules are enabled, all requests will be anonymous.'), | |
); | |
return $form; | |
} | |
@@ -115,6 +121,79 @@ function services_edit_form_endpoint_authentication_submit($form, $form_state) { | |
services_endpoint_save($endpoint); | |
} | |
+function services_edit_form_endpoint_server($form, $form_state) { | |
+ $form = array(); | |
+ $endpoint = $form_state; | |
+ $servers = services_get_servers(); | |
+ | |
+ $server = !empty($servers[$endpoint->server]) ? $servers[$endpoint->server] : FALSE; | |
+ | |
+ $form['endpoint_object'] = array( | |
+ '#type' => 'value', | |
+ '#value' => $endpoint, | |
+ ); | |
+ | |
+ if (!$server) { | |
+ $form['message'] = array( | |
+ '#type' => 'item', | |
+ '#title' => t('Unknown server @name', array('@name' => $endpoint->server)), | |
+ '#description' => t('No server matching the one used in the endpoint.'), | |
+ ); | |
+ } | |
+ else if (empty($server['settings'])) { | |
+ $form['message'] = array( | |
+ '#type' => 'item', | |
+ '#title' => t('@name has no settings', array('@name' => $endpoint->server)), | |
+ '#description' => t("The server doesn't have any settings that needs to be configured."), | |
+ ); | |
+ } | |
+ else { | |
+ $definition = $server['settings']; | |
+ | |
+ $settings = isset($endpoint->server_settings[$endpoint->server]) ? $endpoint->server_settings[$endpoint->server] : array(); | |
+ | |
+ if (!empty($definition['file'])) { | |
+ call_user_func_array('module_load_include', $definition['file']); | |
+ } | |
+ | |
+ $form[$endpoint->server] = array( | |
+ '#type' => 'fieldset', | |
+ '#title' => $server['name'], | |
+ '#tree' => TRUE, | |
+ ); | |
+ call_user_func_array($definition['form'], array(&$form[$endpoint->server], $endpoint, $settings)); | |
+ | |
+ $form['submit'] = array( | |
+ '#type' => 'submit', | |
+ '#value' => 'Save', | |
+ ); | |
+ } | |
+ | |
+ return $form; | |
+} | |
+ | |
+function services_edit_form_endpoint_server_submit($form, $form_state) { | |
+ $endpoint = $form_state['values']['endpoint_object']; | |
+ $servers = services_get_servers(); | |
+ $definition = $servers[$endpoint->server]['settings']; | |
+ | |
+ $values = $form_state['values'][$endpoint->server]; | |
+ | |
+ // Allow the server to alter the submitted values before they're stored | |
+ // as settings. | |
+ if (!empty($definition['submit'])) { | |
+ if (!empty($definition['file'])) { | |
+ call_user_func_array('module_load_include', $definition['file']); | |
+ } | |
+ $values = call_user_func($definition['submit'], $endpoint, $values); | |
+ } | |
+ | |
+ // Store the settings in the endpoint | |
+ $endpoint->server_settings[$endpoint->server] = $values; | |
+ services_endpoint_save($endpoint); | |
+ | |
+ drupal_set_message(t('Your server settings have been saved.')); | |
+} | |
/** | |
* services_edit_endpoint_resources function. | |
@@ -140,7 +219,7 @@ function services_edit_endpoint_resources($endpoint) { | |
* @param object $endpoint | |
* @return Form | |
*/ | |
-function services_edit_form_endpoint_resources($form, &$form_state) { | |
+function services_edit_form_endpoint_resources(&$form_state, $endpoint) { | |
module_load_include('resource_build.inc', 'services'); | |
$form = array(); | |
@@ -148,7 +227,6 @@ function services_edit_form_endpoint_resources($form, &$form_state) { | |
drupal_add_js('misc/tableselect.js'); | |
drupal_add_js(drupal_get_path('module', 'services') . '/js/services.admin.js'); | |
drupal_add_css(drupal_get_path('module', 'services') . '/css/services.admin.css'); | |
- $endpoint = $form_state; | |
$form['endpoint_object'] = array( | |
'#type' => 'value', | |
'#value' => $endpoint, | |
@@ -179,7 +257,7 @@ function services_edit_form_endpoint_resources($form, &$form_state) { | |
'#theme' => 'services_resource_table', | |
); | |
- $ignoreArray = array('actions', 'relationships', 'endpoint', 'name', 'file'); | |
+ $ignoreArray = array('actions', 'relationships', 'endpoint', 'name', 'file', 'targeted_actions'); | |
// Generate the list of methods arranged by resource. | |
foreach ($resources as $resource => $methods) { | |
$form['resources']['table'][$resource] = array( | |
@@ -258,7 +336,7 @@ function services_edit_form_endpoint_resources($form, &$form_state) { | |
* @param array $form_state | |
* @return void | |
*/ | |
-function services_edit_form_endpoint_resources_validate($form, $form_state) { | |
+function services_edit_form_endpoint_resources_validate($form, &$form_state) { | |
$input = $form_state['values']['endpoint_object']; | |
// Validate aliases. | |
@@ -280,7 +358,7 @@ function services_edit_form_endpoint_resources_validate($form, $form_state) { | |
* @param array $form_state | |
* @return void | |
*/ | |
-function services_edit_form_endpoint_resources_submit($form, $form_state) { | |
+function services_edit_form_endpoint_resources_submit($form, &$form_state) { | |
$endpoint = $form_state['values']['endpoint_object']; | |
$existing_resources = _services_build_resources(); | |
@@ -312,4 +390,4 @@ function services_edit_form_endpoint_resources_submit($form, $form_state) { | |
$endpoint->resources = $final_resource; | |
services_endpoint_save($endpoint); | |
drupal_set_message('Resources have been saved'); | |
-} | |
\ No newline at end of file | |
+} | |
diff --git a/plugins/export_ui/services_ctools_export_ui.inc b/plugins/export_ui/services_ctools_export_ui.inc | |
index cb33c63..d4ec02b 100644 | |
--- a/plugins/export_ui/services_ctools_export_ui.inc | |
+++ b/plugins/export_ui/services_ctools_export_ui.inc | |
@@ -17,7 +17,16 @@ $plugin = array( | |
'load arguments' => array('services_ctools_export_ui'), | |
'access arguments' => array('administer services'), | |
'type' => MENU_LOCAL_TASK, | |
- | |
+ ), | |
+ 'server' => array( | |
+ 'path' => 'list/%ctools_export_ui/server', | |
+ 'title' => 'Server', | |
+ 'page callback' => 'ctools_export_ui_switcher_page', | |
+ 'page arguments' => array('services_ctools_export_ui', 'server', 4), | |
+ 'load arguments' => array('services_ctools_export_ui'), | |
+ 'access arguments' => array('administer services'), | |
+ 'type' => MENU_LOCAL_TASK, | |
+ 'weight' => -1, | |
), | |
'authentication' => array( | |
'path' => 'list/%ctools_export_ui/authentication', | |
@@ -34,6 +43,7 @@ $plugin = array( | |
// Add our custom operations. | |
'allowed operations' => array( | |
'resources' => array('title' => t('Edit Resources')), | |
+ 'server' => array('title' => t('Edit Server')), | |
'authentication' => array('title' => t('Edit Authentication')), | |
), | |
'form' => array( | |
@@ -71,15 +81,6 @@ function services_ctools_export_ui_form(&$form, &$form_state) { | |
'#value' => $endpoint, | |
); | |
- $form['title'] = array( | |
- '#type' => 'textfield', | |
- '#size' => 24, | |
- '#maxlength' => 255, | |
- '#default_value' => $endpoint->title, | |
- '#title' => t('Endpoint title'), | |
- '#required' => TRUE, | |
- ); | |
- | |
$servers = services_get_servers(); | |
$server_opts = array( | |
'' => t('-- Select a server'), | |
@@ -138,17 +139,14 @@ function services_ctools_export_ui_form(&$form, &$form_state) { | |
'#options' => $auth_options, | |
'#default_value' => $default_values, | |
'#title' => t('Authentication'), | |
- '#description' => t('Choose which authentication schemes that should ' . | |
- 'be used with your endpoint. If no authentication method is selected ' . | |
- 'the standard Drupal session security is used.'), | |
+ '#description' => t('Choose which authentication schemes that should be used with your endpoint. If no authentication method is selected all requests will be done by an anonymous user.'), | |
); | |
} | |
else { | |
$form['authentication'] = array( | |
'#type' => 'item', | |
'#title' => t('Authentication'), | |
- '#description' => t('No authentication modules are installed, standard ' . | |
- 'Drupal session based security will be used.'), | |
+ '#description' => t('No authentication modules are installed, all requests will be done by an anonymous user.'), | |
); | |
} | |
@@ -182,10 +180,12 @@ function services_ctools_export_ui_form_validate(&$form, &$form_state) { | |
* Submit handler for endpoint. | |
*/ | |
function services_ctools_export_ui_form_submit(&$form, &$form_state) { | |
+ | |
+ variable_set('services_use_content_permissions', $form_state['values']['services_use_content_permissions']); | |
+ | |
$endpoint = $form_state['values']['endpoint_object']; | |
$endpoint->name = $form_state['values']['name']; | |
- $endpoint->title = $form_state['values']['title']; | |
$endpoint->server = $form_state['values']['server']; | |
$endpoint->path = $form_state['values']['path']; | |
$endpoint->debug = $form_state['values']['debug']; | |
diff --git a/resources/comment_resource.inc b/resources/comment_resource.inc | |
index 0270cb2..dc61c2a 100644 | |
--- a/resources/comment_resource.inc | |
+++ b/resources/comment_resource.inc | |
@@ -130,7 +130,7 @@ function _comment_resource_definition() { | |
'name' => 'nid', | |
'type' => 'int', | |
'description' => t('The node id to count all comments.'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'nid'), | |
'optional' => FALSE, | |
), | |
), | |
@@ -146,15 +146,15 @@ function _comment_resource_definition() { | |
'name' => 'nid', | |
'type' => 'int', | |
'description' => t('The node id to load comments for.'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'nid'), | |
'optional' => FALSE, | |
), | |
array( | |
- 'name' => 'since', | |
- 'type' => 'int', | |
- 'optional' => TRUE, | |
- 'description' => t('Timestamp to count from (defaults to time of last user acces to node).'), | |
- 'source' => 'data', | |
+ 'name' => 'since', | |
+ 'type' => 'int', | |
+ 'optional' => TRUE, | |
+ 'description' => t('Timestamp to count from (defaults to time of last user acces to node).'), | |
+ 'source' => array('data' => 'since'), | |
'optional' => TRUE, | |
'default value' => 0, | |
), | |
@@ -194,7 +194,7 @@ function _comment_resource_index($page, $fields, $parameters) { | |
if (!user_access('administer comments')) { | |
$parameters['status'] = 1; | |
} | |
- $query = services_resource_build_index_query('comments', 'timestamp DESC', $page, $fields, $parameters); | |
+ $query = services_resource_build_index_query('comments', 'c.timestamp DESC', $page, $fields, $parameters, 'c', 'cid'); | |
// Put together array of matching nodes to return. | |
$results = array(); | |
while ($comments = db_fetch_object($query)) { | |
@@ -214,6 +214,10 @@ function _comment_resource_index($page, $fields, $parameters) { | |
*/ | |
function _comment_resource_create($comment) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($comment['comment']) && !isset($comment['subject'])) { | |
+ $comment = $comment['comment']; | |
+ } | |
// Setup form_state | |
$form_state = array(); | |
@@ -265,6 +269,10 @@ function _comment_resource_retrieve($cid) { | |
*/ | |
function _comment_resource_update($cid, $comment) { | |
$comment['cid'] = $cid; | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($comment['data']) && !isset($comment['subject'])) { | |
+ $comment = $comment['data']; | |
+ } | |
$old_comment = (array) _comment_load($cid); | |
if (empty($old_comment)) { | |
@@ -344,6 +352,11 @@ function _comment_resource_count_new($nid, $since = 0) { | |
* Access check callback for comment controllers. | |
*/ | |
function _comment_resource_access($op = 'view', $args = array()) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($args[0]['comment']) || isset($args[0]['data'])) { | |
+ $args[0] = $args[0]['comment'] ? $args[0]['comment'] : $args[0]['data']; | |
+ } | |
+ | |
if ($op == 'view' && !isset($args[0])) { | |
return user_access('access comments'); | |
} | |
diff --git a/resources/file_resource.inc b/resources/file_resource.inc | |
index 0b0a96b..0a0c784 100644 | |
--- a/resources/file_resource.inc | |
+++ b/resources/file_resource.inc | |
@@ -130,9 +130,9 @@ function _file_resource_definition() { | |
* @see _node_resource_index() for more notes | |
**/ | |
function _file_resource_index($page, $fields, $parameters) { | |
- services_resource_build_index_query('files', 'timestamp DESC', $page, $fields, $parameters); | |
+ services_resource_build_index_query('files', 'f.timestamp DESC', $page, $fields, $parameters, 'f', 'fid'); | |
- $query = services_resource_build_index_query('files', 'timestamp', $page, $fields, $parameters); | |
+ $query = services_resource_build_index_query('files', 'f.timestamp', $page, $fields, $parameters, 'f', 'fid'); | |
// Put together array of matching nodes to return. | |
$results = array(); | |
while ($comments = db_fetch_object($query)) { | |
@@ -152,6 +152,11 @@ function _file_resource_index($page, $fields, $parameters) { | |
* Unique identifier for the file (fid) or errors if there was a problem. | |
*/ | |
function _file_resource_create($file) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($file['file']) && count($file) == 1) { | |
+ $file = $file['file']; | |
+ } | |
+ | |
global $user; | |
// If the file data is empty then bail. | |
@@ -237,7 +242,7 @@ function _file_resource_create($file) { | |
* @return | |
* The file | |
*/ | |
-function _file_resource_retrieve($fid, $file_contents = TRUE) { | |
+function _file_resource_retrieve($fid, $file_contents) { | |
if ($file = db_fetch_array(db_query('SELECT * FROM {files} WHERE fid = %d', $fid))) { | |
if ($file_contents) { | |
$binaryfile = fopen($file['filepath'], 'rb'); | |
@@ -247,6 +252,7 @@ function _file_resource_retrieve($fid, $file_contents = TRUE) { | |
$file['file'] = base64_encode(fread($binaryfile, filesize($file['filepath']))); | |
fclose($binaryfile); | |
} | |
+ $file['uri'] = services_resource_uri(array('file', $file['fid'])); | |
return $file; | |
} | |
return services_error(t('There is no file with the given ID.')); | |
@@ -313,6 +319,11 @@ function _file_resource_delete($fid) { | |
* Access check callback for file controllers. | |
*/ | |
function _file_resource_access($op = 'view', $args = array()) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($args[0]['file']) && count($args[0]) == 1) { | |
+ $args[0] = $args[0]['file']; | |
+ } | |
+ | |
global $user; | |
if (user_access('administer files')) { | |
return TRUE; | |
diff --git a/resources/node_resource.inc b/resources/node_resource.inc | |
index d6c5786..6d0ba8f 100644 | |
--- a/resources/node_resource.inc | |
+++ b/resources/node_resource.inc | |
@@ -105,28 +105,28 @@ function _node_resource_definition() { | |
'access arguments' => array('access content'), | |
), | |
'relationships' => array( | |
- 'nodeFiles' => array( | |
- 'help' => t('This method returns the files on a given node.'), | |
+ 'files' => array( | |
'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'help' => t('This method returns files associated with a node.'), | |
'access callback' => '_node_resource_access', | |
'access arguments' => array('view'), | |
'access arguments append' => TRUE, | |
'callback' => '_node_resource_load_node_files', | |
'args' => array( | |
array( | |
- 'name' => 'nid', | |
- 'type' => 'int', | |
- 'description' => t('The node id to load files for.'), | |
- 'source' => 'data', | |
- 'optional' => FALSE, | |
+ 'name' => 'nid', | |
+ 'optional' => FALSE, | |
+ 'source' => array('path' => 0), | |
+ 'type' => 'int', | |
+ 'description' => 'The nid of the node whose files we are getting', | |
), | |
array( | |
- 'name' => 'file_contents', | |
- 'type' => 'int', | |
+ 'name' => 'file_contents', | |
+ 'type' => 'int', | |
'description' => t('To return file contents or not.'), | |
- 'source' => 'data', | |
- 'optional' => FALSE, | |
- 'default value' => TRUE, | |
+ 'source' => array('path' => 2), | |
+ 'optional' => TRUE, | |
+ 'default value' => false, | |
), | |
), | |
), | |
@@ -245,6 +245,11 @@ function _node_resource_retrieve($nid) { | |
* @see drupal_execute() | |
*/ | |
function _node_resource_create($node) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($node['node'])) { | |
+ $node = $node['node']; | |
+ } | |
+ | |
if (!isset($node['type'])) { | |
return services_error('Missing node type', 406); | |
} | |
@@ -299,6 +304,11 @@ function _node_resource_create($node) { | |
* @see drupal_execute() | |
*/ | |
function _node_resource_update($nid, $node) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($node['node'])) { | |
+ $node = $node['node']; | |
+ } | |
+ | |
$node['nid'] = $nid; | |
$old_node = node_load($nid); | |
@@ -374,7 +384,7 @@ function _node_resource_index($page, $fields, $parameters) { | |
if (!user_access('administer nodes')) { | |
$parameters['status'] = 1; | |
} | |
- $query = services_resource_build_index_query('node', 'sticky DESC, created DESC', $page, $fields, $parameters); | |
+ $query = services_resource_build_index_query('node', 'n.sticky DESC, n.created DESC', $page, $fields, $parameters, 'n', 'nid'); | |
// Put together array of matching nodes to return. | |
$results = array(); | |
while ($node = db_fetch_object($query)) { | |
@@ -394,7 +404,7 @@ function _node_resource_index($page, $fields, $parameters) { | |
* @return | |
* Array. A list of all files from the given node | |
*/ | |
-function _node_resource_load_node_files($nid, $include_file_contents = TRUE) { | |
+function _node_resource_load_node_files($nid, $include_file_contents) { | |
module_load_include('inc', 'services', 'resources/file_resource'); | |
$node = node_load($nid); | |
if (!isset($node->files)) { | |
@@ -407,21 +417,7 @@ function _node_resource_load_node_files($nid, $include_file_contents = TRUE) { | |
if (!$file->list) { | |
continue; | |
} | |
- $return[$file->fid] = array( | |
- 'filename' => $file->filename, | |
- 'uid' => $file->uid, | |
- 'filemime' => $file->filemime, | |
- 'filesize' => $file->filesize, | |
- 'status' => $file->status, | |
- 'timestamp' => $file->timestamp | |
- ); | |
- // If to add content of the file. | |
- if ($file_include_contents) { | |
- $filepath = file_create_path($file->filepath); | |
- $binaryfile = fopen($filepath, 'rb'); | |
- $return[$file->fid]['file'] = base64_encode(fread($binaryfile, filesize($filepath))); | |
- fclose($binaryfile); | |
- } | |
+ $return[$file->fid] = _file_resource_retrieve($file->fid, $include_file_contents); | |
} | |
return $return; | |
@@ -439,6 +435,11 @@ function _node_resource_load_node_files($nid, $include_file_contents = TRUE) { | |
* @see node_access() | |
*/ | |
function _node_resource_access($op = 'view', $args = array()) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($args[0]['node'])) { | |
+ $args[0] = $args[0]['node']; | |
+ } | |
+ | |
// Make sure we have an object or this all fails, some servers can | |
// mess up the types. | |
if (is_array($args[0])) { | |
diff --git a/resources/system_resource.inc b/resources/system_resource.inc | |
index 6d626f5..8b63362 100644 | |
--- a/resources/system_resource.inc | |
+++ b/resources/system_resource.inc | |
@@ -24,14 +24,14 @@ function _system_resource_definition() { | |
array( | |
'name' => 'name', | |
'optional' => TRUE, | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'name'), | |
'description' => t('The name of the variable to return.'), | |
'type' => 'string', | |
), | |
array( | |
'name' => 'default', | |
'optional' => FALSE, | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'default'), | |
'description' => t('The default value to use if this variable has never been set.'), | |
'type' => 'string', | |
), | |
@@ -47,14 +47,14 @@ function _system_resource_definition() { | |
array( | |
'name' => 'name', | |
'optional' => FALSE, | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'name'), | |
'description' => t('The name of the variable to set.'), | |
'type' => 'string', | |
), | |
array( | |
'name' => 'value', | |
'optional' => FALSE, | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'value'), | |
'description' => t('The value to set.'), | |
'type' => 'string', | |
), | |
@@ -70,7 +70,7 @@ function _system_resource_definition() { | |
array( | |
'name' => 'name', | |
'optional' => FALSE, | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'name'), | |
'description' => t('The name of the variable to delete.'), | |
'type' => 'string', | |
), | |
diff --git a/resources/taxonomy_resource.inc b/resources/taxonomy_resource.inc | |
index 00b93e0..14c1780 100644 | |
--- a/resources/taxonomy_resource.inc | |
+++ b/resources/taxonomy_resource.inc | |
@@ -124,14 +124,14 @@ function _taxonomy_resource_definition() { | |
'name' => 'tids', | |
'type' => 'string', | |
'description' => t('The vocabulary ids to retrieve, separated by comma.'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'tids'), | |
'optional' => FALSE, | |
), | |
array( | |
'name' => 'fields', | |
'type' => 'string', | |
'description' => t('The fields to retrieve, separated by comma.'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'fields'), | |
'optional' => TRUE, | |
'default value' => array(), | |
), | |
@@ -139,7 +139,7 @@ function _taxonomy_resource_definition() { | |
'name' => 'operator', | |
'type' => 'string', | |
'description' => t('How to interpret multiple IDs in the array. Can be "or" or "and".'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'operator'), | |
'optional' => TRUE, | |
'default value' => 'or', | |
), | |
@@ -147,7 +147,7 @@ function _taxonomy_resource_definition() { | |
'name' => 'depth', | |
'type' => 'int', | |
'description' => t('How many levels deep to traverse the taxonomy tree. Can be a nonnegative integer or "all".'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'depth'), | |
'optional' => TRUE, | |
'default value' => 0, | |
), | |
@@ -155,7 +155,7 @@ function _taxonomy_resource_definition() { | |
'name' => 'pager', | |
'type' => 'int', | |
'description' => t('Whether the nodes are to be used with a pager (the case on most Drupal pages) or not (in an XML feed, for example).'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'pager'), | |
'optional' => TRUE, | |
'default value' => TRUE, | |
), | |
@@ -163,7 +163,7 @@ function _taxonomy_resource_definition() { | |
'name' => 'order', | |
'type' => 'string', | |
'description' => t('The order clause for the query that retrieve the nodes.'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'order'), | |
'optional' => TRUE, | |
'default value' => 'n.sticky DESC, n.created DESC', | |
), | |
@@ -286,24 +286,24 @@ function _taxonomy_resource_definition() { | |
'name' => 'vid', | |
'type' => 'int', | |
'description' => t('The vocabulary id to retrieve.'), | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'vid'), | |
'optional' => FALSE, | |
), | |
array( | |
- 'name' => 'parent', | |
- 'type' => 'int', | |
- 'description' => t('The term ID under which to generate the tree. If 0, generate the tree for the entire vocabulary.'), | |
- 'source' => 'data', | |
- 'default value' => 0, | |
- 'optional' => TRUE, | |
+ 'name' => 'parent', | |
+ 'type' => 'int', | |
+ 'description' => t('The term ID under which to generate the tree. If 0, generate the tree for the entire vocabulary.'), | |
+ 'source' => array('data' => 'parent'), | |
+ 'default value' => 0, | |
+ 'optional' => TRUE, | |
), | |
array( | |
- 'name' => 'maxdepth', | |
- 'type' => 'int', | |
- 'description' => t('The number of levels of the tree to return. Leave NULL to return all levels.'), | |
- 'source' => 'data', | |
- 'optional' => TRUE, | |
- 'default value' => NULL, | |
+ 'name' => 'maxdepth', | |
+ 'type' => 'int', | |
+ 'description' => t('The number of levels of the tree to return. Leave NULL to return all levels.'), | |
+ 'source' => array('data' => 'maxdepth'), | |
+ 'default value' => NULL, | |
+ 'optional' => TRUE, | |
), | |
), | |
), | |
@@ -334,7 +334,7 @@ function _taxonomy_resource_definition() { | |
* @see _node_resource_index() for more notes | |
**/ | |
function _taxonomy_term_resource_index($page, $fields, $parameters) { | |
- $query = services_resource_build_index_query('term_data', 'vid DESC, weight DESC, name DESC', $page, $fields, $parameters); | |
+ $query = services_resource_build_index_query('term_data', 't.vid DESC, t.weight DESC, t.name DESC', $page, $fields, $parameters, 't', 'tid'); | |
$results = array(); | |
while ($taxonomy = db_fetch_object($query)) { | |
@@ -369,7 +369,7 @@ function _taxonomy_term_resource_index($page, $fields, $parameters) { | |
* @see _node_resource_index() for more notes | |
**/ | |
function _taxonomy_vocabulary_resource_index($page, $fields, $parameters) { | |
- $query = services_resource_build_index_query('vocabulary', 'weight DESC, name DESC', $page, $fields, $parameters); | |
+ $query = services_resource_build_index_query('vocabulary', 'v.weight DESC, v.name DESC', $page, $fields, $parameters, 'v', 'vid'); | |
$results = array(); | |
while ($taxonomy = db_fetch_object($query)) { | |
@@ -403,6 +403,11 @@ function _taxonomy_term_resource_retrieve($tid) { | |
* @see taxonomy_save_term() | |
*/ | |
function _taxonomy_term_resource_create($term) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($term['term'])) { | |
+ $term = $term['term']; | |
+ } | |
+ | |
return taxonomy_save_term($term); | |
} | |
@@ -419,6 +424,11 @@ function _taxonomy_term_resource_create($term) { | |
* @see taxonomy_save_term() | |
*/ | |
function _taxonomy_term_resource_update($tid, $term) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($term['term'])) { | |
+ $term = $term['term']; | |
+ } | |
+ | |
$term['tid'] = $tid; | |
return _taxonomy_term_resource_create($term); | |
} | |
@@ -482,7 +492,12 @@ function _taxonomy_vocabulary_resource_retrieve($vid) { | |
* @see taxonomy_save_vocabulary() | |
*/ | |
function _taxonomy_vocabulary_resource_create($vocabulary) { | |
- return taxonomy_save_vocabulary($vocabulary); | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($vocabulary['vocabulary'])) { | |
+ $vocabulary = $vocabulary['vocabulary']; | |
+ } | |
+ taxonomy_save_vocabulary($vocabulary); | |
+ return $vocabulary; | |
} | |
/** | |
@@ -498,6 +513,11 @@ function _taxonomy_vocabulary_resource_create($vocabulary) { | |
* @see taxonomy_save_vocabulary() | |
*/ | |
function _taxonomy_vocabulary_resource_update($vid, $vocabulary) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($vocabulary['vocabulary'])) { | |
+ $vocabulary = $vocabulary['vocabulary']; | |
+ } | |
+ | |
$vocabulary['vid'] = $vid; | |
return _taxonomy_vocabulary_resource_create($vocabulary); | |
} | |
@@ -559,7 +579,7 @@ function taxonomy_service_select_nodes($tids, $fields, $operator, $depth, $pager | |
} | |
function _taxonomy_resource_access($op = 'view', $args = array()) { | |
- if (user_access('administer taxonomy')) { | |
+ if (user_access('administer taxonomy') || user_access('get taxonomy tree')) { | |
return TRUE; | |
} | |
// TODO - check perms of user to return ability to interact with terms / vocabulary | |
diff --git a/resources/user_resource.inc b/resources/user_resource.inc | |
index cd46157..5a497fc 100644 | |
--- a/resources/user_resource.inc | |
+++ b/resources/user_resource.inc | |
@@ -121,14 +121,14 @@ function _user_resource_definition() { | |
'name' => 'username', | |
'type' => 'string', | |
'description' => 'A valid username', | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'username'), | |
'optional' => FALSE, | |
), | |
array( | |
'name' => 'password', | |
'type' => 'string', | |
'description' => 'A valid password', | |
- 'source' => 'data', | |
+ 'source' => array('data' => 'password'), | |
'optional' => FALSE, | |
), | |
), | |
@@ -211,6 +211,11 @@ function _user_resource_retrieve($uid) { | |
* The user object of the newly created user. | |
*/ | |
function _user_resource_create($account) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($account['account'])) { | |
+ $account = $account['account']; | |
+ } | |
+ | |
// Load the required includes for saving profile information | |
// with drupal_execute(). | |
module_load_include('inc', 'user', 'user.pages'); | |
@@ -254,7 +259,13 @@ function _user_resource_create($account) { | |
* The modified user object. | |
*/ | |
function _user_resource_update($uid, $account) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($account['data'])) { | |
+ $account = $account['data']; | |
+ } | |
+ | |
$account['uid'] = $uid; | |
+ $user = user_load($uid); | |
// Load the required includes for saving profile information | |
// with drupal_execute(). | |
@@ -287,8 +298,14 @@ function _user_resource_update($uid, $account) { | |
$form_state['values']['op'] = 'Save'; | |
$form_state['values']['_category'] = $category; | |
$form_state['values']['_account'] = (object)$account; | |
+ if (isset($account['pass'])) { | |
+ $form_state['values']['pass'] = array( | |
+ 'pass1' => $account['pass'], | |
+ 'pass2' => $account['pass'], | |
+ ); | |
+ } | |
- $ret = drupal_execute('user_profile_form', $form_state, (object)$account, $category); | |
+ $ret = drupal_execute('user_profile_form', $form_state, $user, $category); | |
// Error if needed. | |
if ($errors = form_get_errors()) { | |
@@ -370,7 +387,8 @@ function _user_resource_logout() { | |
// Destroy the current session: | |
session_destroy(); | |
- module_invoke_all('user', 'logout', NULL, $user); | |
+ $null = NULL; // Only variables can be passed by reference workaround | |
+ user_module_invoke('logout', $null, $user ); | |
// Load the anonymous user | |
$user = drupal_anonymous_user(); | |
@@ -404,7 +422,7 @@ function _user_resource_index($page, $fields, $parameters) { | |
if (!user_access('administer users')) { | |
$parameters['active'] = 1; | |
} | |
- $query = services_resource_build_index_query('users', 'created DESC', $page, $fields, $parameters); | |
+ $query = services_resource_build_index_query('users', 'u.created DESC', $page, $fields, $parameters, 'u', 'uid'); | |
$results = array(); | |
while ($user = db_fetch_object($query)) { | |
@@ -417,6 +435,11 @@ function _user_resource_index($page, $fields, $parameters) { | |
* Access check callback for user resource. | |
*/ | |
function _user_resource_access($op = 'view', $args = array()) { | |
+ // Adds backwards compatability with regression fixed in #1083242 | |
+ if (isset($args[0]['account']) || isset($args[0]['data'])) { | |
+ $args[0] = $args[0]['account'] ? $args[0]['account'] : $args[0]['data']; | |
+ } | |
+ | |
global $user; | |
switch ($op) { | |
case 'view': | |
diff --git a/servers/rest_server/includes/RESTServer.inc b/servers/rest_server/includes/RESTServer.inc | |
index f1ab017..b67bf34 100755 | |
--- a/servers/rest_server/includes/RESTServer.inc | |
+++ b/servers/rest_server/includes/RESTServer.inc | |
@@ -53,6 +53,15 @@ class RESTServer { | |
} | |
$endpoint = services_get_server_info('endpoint', ''); | |
+ | |
+ $endpoint_definition = services_endpoint_load($endpoint); | |
+ | |
+ // Get the server settings from the endpoint. | |
+ $this->settings = !empty($endpoint_definition->server_settings['rest_server']) ? $endpoint_definition->server_settings['rest_server'] : array(); | |
+ // Normalize the settings so that we get the expected structure | |
+ // and sensible defaults. | |
+ $this->settings = rest_server_setup_settings($this->settings); | |
+ | |
$resources = services_get_resources($endpoint); | |
$controller = FALSE; | |
if (!empty($resource_name) && isset($resources[$resource_name])) { | |
@@ -83,7 +92,6 @@ class RESTServer { | |
// Negotiate response format based on accept-headers if we | |
// don't have a response format | |
if (empty($response_format)) { | |
- module_load_include('php', 'rest_server', 'lib/mimeparse'); | |
$mime_candidates = array(); | |
$mime_map = array(); | |
@@ -99,7 +107,7 @@ class RESTServer { | |
// Get the best matching format, default to json | |
if (isset($_SERVER['HTTP_ACCEPT'])) { | |
- $mime = new Mimeparse(); | |
+ $mime = $this->mimeParse(); | |
$mime_type = $mime->best_match($mime_candidates, $_SERVER['HTTP_ACCEPT']); | |
} | |
@@ -152,7 +160,7 @@ class RESTServer { | |
$result = services_controller_execute($controller, $arguments); | |
} catch (ServicesException $e) { | |
$errors = $this->handleException($e); | |
- drupal_alter('rest_server_exectue_errors', $errors, $controller, $arguments); | |
+ drupal_alter('rest_server_execute_errors', $errors, $controller, $arguments); | |
$result = $errors; | |
} | |
$formatter = $formats[$response_format]; | |
@@ -218,16 +226,15 @@ class RESTServer { | |
} | |
} | |
else { | |
- if (isset($sources[$info['source']][$info['name']])) { | |
- $arguments[$i] = $sources[$info['source']][$info['name']]; | |
- } | |
+ if (isset($sources[$info['source']])) { | |
+ $arguments[$i] = $sources[$info['source']]; | |
+ } | |
} | |
// Convert to array if argument expected to be array. | |
if ($info['type'] == 'array' && isset($arguments[$i])) { | |
$arguments[$i] = (array)$arguments[$i]; | |
} | |
} | |
- | |
// When argument isn't set, insert default value if provided or | |
// throw a exception if the argument isn't optional. | |
if (!isset($arguments[$i])) { | |
@@ -249,15 +256,11 @@ class RESTServer { | |
} | |
private function parseRequest($method, $controller) { | |
- if (($method == 'POST' || $method == 'PUT') && isset($_SERVER['CONTENT_TYPE'])) { | |
- $type = self::parseContentHeader($_SERVER['CONTENT_TYPE']); | |
- } | |
+ | |
switch ($method) { | |
case 'POST': | |
- if (isset($type['value']) && $type['value'] == 'application/x-www-form-urlencoded') { | |
- return $_POST; | |
- } | |
case 'PUT': | |
+ $type = self::parseContentHeader($_SERVER['CONTENT_TYPE']); | |
// Get the mime type for the request, default to form-urlencoded | |
if (isset($type['value'])) { | |
$mime = $type['value']; | |
@@ -267,7 +270,7 @@ class RESTServer { | |
} | |
// Get the parser for the mime type | |
- $parser = $this->requestParsers($mime, $controller); | |
+ $parser = $this->requestParser($mime, $controller); | |
if (!$parser) { | |
throw new ServicesException(t('Unsupported request content type !mime', array( | |
'!mime' => $mime, | |
@@ -400,32 +403,34 @@ class RESTServer { | |
return $view->render(); | |
} | |
- private function requestParsers($mime=NULL, $controller=NULL) { | |
- static $parsers; | |
- | |
+ private function requestParser($mime = NULL, $controller = NULL) { | |
+ // Check if the controller has declared support for parsing the mime type. | |
if ($mime && $controller && !empty($controller['rest request parsers'])) { | |
- $parser = $this->matchParser($mime, $controller['rest request parsers']); | |
+ $parser = $this->matchParser($mime, $controller['rest request parsers'], TRUE); | |
if ($parser) { | |
return $parser; | |
} | |
} | |
- if (!$parsers) { | |
- $parsers = array( | |
- 'application/x-www-form-urlencoded' => 'RESTServer::parseURLEncoded', | |
- 'application/x-yaml' => 'RESTServer::parseYAML', | |
- 'application/json' => 'RESTServer::parseJSON', | |
- 'application/vnd.php.serialized' => 'RESTServer::parsePHP', | |
- ); | |
- drupal_alter('rest_server_request_parsers', $parsers); | |
- } | |
if ($mime) { | |
+ $parsers = rest_server_request_parsers(); | |
+ | |
+ // Remove parsers that have been disabled for this endpoint. | |
+ foreach (array_keys($parsers) as $key) { | |
+ if (!$this->settings['parsers'][$key]) { | |
+ unset($parsers[$key]); | |
+ } | |
+ } | |
return $this->matchParser($mime, $parsers); | |
} | |
- return $parsers; | |
+ return FALSE; | |
} | |
- | |
+ /** | |
+ * Create a instance of the Mimeparse utility class. | |
+ * | |
+ * @return Mimeparse | |
+ */ | |
private function mimeParse() { | |
static $mimeparse; | |
if (!$mimeparse) { | |
@@ -435,12 +440,10 @@ class RESTServer { | |
return $mimeparse; | |
} | |
- private function matchParser($mime, $parsers) { | |
+ private function matchParser($mime, $parsers, $allow_all_parsers = FALSE) { | |
$mimeparse = $this->mimeParse(); | |
$mime_type = $mimeparse->best_match(array_keys($parsers), $mime); | |
- if ($mime_type) { | |
- return $parsers[$mime_type]; | |
- } | |
+ return ($mime_type) ? $parsers[$mime_type] : FALSE; | |
} | |
public static function parseURLEncoded($handle) { | |
@@ -462,52 +465,18 @@ class RESTServer { | |
} | |
private function responseFormatters($format=NULL) { | |
- static $formatters; | |
- | |
- if (!$formatters) { | |
- $formatters = array( | |
- 'xml' => array( | |
- 'mime types' => array('application/xml', 'text/xml'), | |
- 'view' => 'RESTServerViewBuiltIn', | |
- 'view arguments' => array('format' => 'xml'), | |
- ), | |
- 'json' => array( | |
- 'mime types' => array('application/json'), | |
- 'view' => 'RESTServerViewBuiltIn', | |
- 'view arguments' => array('format' => 'json'), | |
- ), | |
- 'jsonp' => array( | |
- 'mime types' => array('text/javascript', 'application/javascript'), | |
- 'view' => 'RESTServerViewBuiltIn', | |
- 'view arguments' => array('format' => 'jsonp'), | |
- ), | |
- 'php' => array( | |
- 'mime types' => array('application/vnd.php.serialized'), | |
- 'view' => 'RESTServerViewBuiltIn', | |
- 'view arguments' => array('format' => 'php'), | |
- ), | |
- 'yaml' => array( | |
- 'mime types' => array('text/plain', 'application/x-yaml', 'text/yaml'), | |
- 'view' => 'RESTServerViewBuiltIn', | |
- 'view arguments' => array('format' => 'yaml'), | |
- ), | |
- 'bencode' => array( | |
- 'mime types' => array('application/x-bencode'), | |
- 'view' => 'RESTServerViewBuiltIn', | |
- 'view arguments' => array('format' => 'bencode'), | |
- ), | |
- 'rss' => array( | |
- 'model' => 'ResourceFeedModel', | |
- 'mime types' => array('text/xml'), | |
- 'view' => 'RssFormatView', | |
- ), | |
- ); | |
- drupal_alter('rest_server_response_formatters', $formatters); | |
- } | |
+ $formatters = rest_server_response_formatters(); | |
+ // Remove formatters that have been disabled for this endpoint. | |
+ foreach (array_keys($formatters) as $key) { | |
+ if (!$this->settings['formatters'][$key]) { | |
+ unset($formatters[$key]); | |
+ } | |
+ } | |
if ($format) { | |
return isset($formatters[$format]) ? $formatters[$format] : FALSE; | |
} | |
+ | |
return $formatters; | |
} | |
@@ -589,7 +558,7 @@ class RESTServer { | |
} | |
// Detect action requests targeted at specific resources | |
elseif ($pc >= 2 && $method == 'POST') { | |
- $action = $resource['targeted actions'][$path[1]]; | |
+ $action = $resource['targeted_actions'][$path[1]]; | |
return $action; | |
} | |
} | |
diff --git a/servers/rest_server/rest_server.api.php b/servers/rest_server/rest_server.api.php | |
index 7e0217f..23b1d26 100644 | |
--- a/servers/rest_server/rest_server.api.php | |
+++ b/servers/rest_server/rest_server.api.php | |
@@ -11,22 +11,51 @@ | |
*/ | |
/** | |
- * ... | |
+ * Triggered when the REST server request a list of available request parsers. | |
* | |
+ * @param array $parsers | |
+ * An associative array of parser callbacks keyed by mime-type. | |
+ * @return void | |
*/ | |
-function hook_rest_server_request_parsers_alter() { | |
- return array( | |
- 'name' => 'REST', | |
- ); | |
+function hook_rest_server_request_parsers_alter(&$parsers) { | |
+ $parsers['application/json'] = 'RESTServer::parseJSON'; | |
+ unset($parsers['application/x-www-form-urlencoded']); | |
} | |
/** | |
- * ... | |
+ * Triggered when the REST server request a list of supported response formats. | |
* | |
+ * @param array $formatters | |
+ * An associative array of formatter info arrays keyed by type extension. The | |
+ * formatter info specifies an array of 'mime types' that corresponds to the | |
+ * output format; a 'view' class that is a subclass of RESTServerView; and | |
+ * 'view arguments' that should be passed to the view when it is created; | |
+ * a 'model' can also be specified which the controller then must declare | |
+ * support for to be able to serve data in that format. | |
+ * @return void | |
*/ | |
-function hook_rest_server_response_formatters_alter() { | |
- return array( | |
- 'name' => 'REST', | |
+function hook_rest_server_response_formatters_alter(&$formatters) { | |
+ /* | |
+ * Sample modifications of the formatters array. Both yaml and | |
+ * rss are formats that already are supported, so the changes are | |
+ * nonsensical but illustrates the proper use of this hook. | |
+ */ | |
+ | |
+ // Add a Yaml response format. | |
+ $formatters['yaml'] = array( | |
+ 'mime types' => array('text/plain', 'application/x-yaml', 'text/yaml'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'yaml'), | |
); | |
+ | |
+ // Add a Rss response format. | |
+ $formatters['rss'] = array( | |
+ 'model' => 'ResourceFeedModel', | |
+ 'mime types' => array('text/xml'), | |
+ 'view' => 'RssFormatView', | |
+ ); | |
+ | |
+ // Remove the jsonp response format. | |
+ unset($formatters['jsonp']); | |
} | |
diff --git a/servers/rest_server/rest_server.inc b/servers/rest_server/rest_server.inc | |
index 462a8ac..563f06f 100644 | |
--- a/servers/rest_server/rest_server.inc | |
+++ b/servers/rest_server/rest_server.inc | |
@@ -2,9 +2,93 @@ | |
/** | |
* @file | |
- * Autoload classes. | |
+ * Autoload classes and server settings. | |
*/ | |
+/** | |
+ * REST server settings form. Generates the form fragment for configuring the REST server | |
+ * for an endpoint. | |
+ * | |
+ * @param array $form | |
+ * The form fragment from services that we should add our fields to. | |
+ * @param object $endpoint | |
+ * The endpoint that we're configuring the REST server for. | |
+ * @param array $settings | |
+ * The current settings. | |
+ * @return void | |
+ */ | |
+function _rest_server_settings(&$form, $endpoint, $settings) { | |
+ $settings = rest_server_setup_settings($settings); | |
+ | |
+ $form['formatters'] = array( | |
+ '#type' => 'checkboxes', | |
+ '#title' => t('Response formatters'), | |
+ '#required' => TRUE, | |
+ '#description' => t('Select the response formats you want to enable for the rest server.'), | |
+ ) + _rest_server_settings_checkboxes_attributes($settings['formatters']); | |
+ | |
+ $form['parsers'] = array( | |
+ '#type' => 'checkboxes', | |
+ '#title' => t('Request parsing'), | |
+ '#required' => TRUE, | |
+ '#description' => t('Select the request parser types you want to enable for the rest server.'), | |
+ ) + _rest_server_settings_checkboxes_attributes($settings['parsers']); | |
+} | |
+ | |
+/** | |
+ * Utility function that creates attributes for a checkboxes-type form | |
+ * element from a rest server settings array. | |
+ * | |
+ * @param array $settings | |
+ * @return array | |
+ */ | |
+function _rest_server_settings_checkboxes_attributes($settings) { | |
+ $keys = array_keys($settings); | |
+ $options = array_combine($keys, $keys); | |
+ $default = array(); | |
+ foreach ($settings as $key => $enabled) { | |
+ if ($enabled) { | |
+ $default[] = $key; | |
+ } | |
+ } | |
+ return array( | |
+ '#options' => $options, | |
+ '#default_value' => $default, | |
+ ); | |
+} | |
+ | |
+/** | |
+ * Submit handler for the services REST server settings form. | |
+ * | |
+ * @param object $endpoint | |
+ * The endpoint that's being configured. | |
+ * @param array $values | |
+ * The partial form-state from services. | |
+ * @return array | |
+ * The settings for the REST server in this endpoint. | |
+ */ | |
+function _rest_server_settings_submit($endpoint, $values) { | |
+ $values['formatters'] = array_map('_rest_server_settings_not_zero', $values['formatters']); | |
+ $values['parsers'] = array_map('_rest_server_settings_not_zero', $values['parsers']); | |
+ return $values; | |
+} | |
+ | |
+/** | |
+ * Utility function intended for use with array_map to change everything that | |
+ * isn't === 0 into TRUE. | |
+ * | |
+ * @param string $value | |
+ * The value to map. | |
+ * @return bool | |
+ * FALSE if the $value is === 0 otherwise TRUE is returned. | |
+ */ | |
+function _rest_server_settings_not_zero($value) { | |
+ return $value !== 0; | |
+} | |
+ | |
+/** | |
+ * Actual implementation of hook_autoload_info(). | |
+ */ | |
function _rest_server_autoload_info() { | |
return array( | |
'RESTServer' => array( | |
diff --git a/servers/rest_server/rest_server.module b/servers/rest_server/rest_server.module | |
index d7e4669..127e1f0 100755 | |
--- a/servers/rest_server/rest_server.module | |
+++ b/servers/rest_server/rest_server.module | |
@@ -4,6 +4,11 @@ function rest_server_server_info() { | |
return array( | |
'name' => 'REST', | |
'path' => 'rest', | |
+ 'settings' => array( | |
+ 'file' => array('inc', 'rest_server'), | |
+ 'form' => '_rest_server_settings', | |
+ 'submit' => '_rest_server_settings_submit', | |
+ ), | |
); | |
} | |
@@ -43,7 +48,135 @@ function rest_server_server() { | |
} | |
/** | |
- * Implementation of hook_services_resources_alter(). | |
+ * Builds a list of request parsers that are available to the RESTServer. | |
+ * | |
+ * @return array | |
+ * An associative array of parser callbacks keyed by mime-type. | |
+ */ | |
+function rest_server_request_parsers() { | |
+ static $parsers = NULL; | |
+ if (!$parsers) { | |
+ $parsers = array( | |
+ 'application/x-www-form-urlencoded' => 'RESTServer::parseURLEncoded', | |
+ 'application/x-yaml' => 'RESTServer::parseYAML', | |
+ 'application/json' => 'RESTServer::parseJSON', | |
+ 'application/vnd.php.serialized' => 'RESTServer::parsePHP', | |
+ ); | |
+ drupal_alter('rest_server_request_parsers', $parsers); | |
+ } | |
+ return $parsers; | |
+} | |
+ | |
+/** | |
+ * Builds a list of response formatters that are available to the RESTServer. | |
+ * | |
+ * @return array | |
+ * An associative array of formatter info arrays keyed by type extension. The | |
+ * formatter info specifies an array of 'mime types' that corresponds to the | |
+ * output format; a 'view' class that is a subclass of RESTServerView; and | |
+ * 'view arguments' that should be passed to the view when it is created; | |
+ * a 'model' can also be specified which the controller then must declare | |
+ * support for to be able to serve data in that format. | |
+ */ | |
+function rest_server_response_formatters() { | |
+ static $formatters = NULL; | |
+ if (!$formatters) { | |
+ $formatters = array( | |
+ 'xml' => array( | |
+ 'mime types' => array('application/xml', 'text/xml'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'xml'), | |
+ ), | |
+ 'json' => array( | |
+ 'mime types' => array('application/json'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'json'), | |
+ ), | |
+ 'jsonp' => array( | |
+ 'mime types' => array('text/javascript', 'application/javascript'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'jsonp'), | |
+ ), | |
+ 'php' => array( | |
+ 'mime types' => array('application/vnd.php.serialized'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'php'), | |
+ ), | |
+ 'yaml' => array( | |
+ 'mime types' => array('text/plain', 'application/x-yaml', 'text/yaml'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'yaml'), | |
+ ), | |
+ 'bencode' => array( | |
+ 'mime types' => array('application/x-bencode'), | |
+ 'view' => 'RESTServerViewBuiltIn', | |
+ 'view arguments' => array('format' => 'bencode'), | |
+ ), | |
+ 'rss' => array( | |
+ 'model' => 'ResourceFeedModel', | |
+ 'mime types' => array('text/xml'), | |
+ 'view' => 'RssFormatView', | |
+ ), | |
+ ); | |
+ drupal_alter('rest_server_response_formatters', $formatters); | |
+ } | |
+ return $formatters; | |
+} | |
+ | |
+/** | |
+ * Set up settings for a rest server endpoint, fills the settings | |
+ * array with defaults. This is done to ensure that the default state | |
+ * is consistent between what's shown by default in the settings form | |
+ * and used by default by the REST server if it hasn't been configured. | |
+ * | |
+ * @param array $settings | |
+ * @return array | |
+ * The standardized settings array. | |
+ */ | |
+function rest_server_setup_settings($settings = array()) { | |
+ // Apply defaults | |
+ $settings = $settings + array( | |
+ 'formatters' => array('jsonp' => FALSE), | |
+ 'parsers' => array('application/x-www-form-urlencoded' => FALSE), | |
+ ); | |
+ | |
+ // Get all available parsers and formatters. | |
+ $parsers = rest_server_request_parsers(); | |
+ $formatters = rest_server_response_formatters(); | |
+ | |
+ _rest_server_add_default_and_remove_unknown($settings['parsers'], array_keys($parsers), TRUE); | |
+ _rest_server_add_default_and_remove_unknown($settings['formatters'], array_keys($formatters), TRUE); | |
+ | |
+ return $settings; | |
+} | |
+ | |
+/** | |
+ * Utility function set set up an array with default values for a set | |
+ * of keys and remove all entries that does not match a key in the set. | |
+ * | |
+ * @param array $array | |
+ * The array to modify. | |
+ * @param array $keys | |
+ * An array of keys. | |
+ * @param mixed $default | |
+ * A default value. | |
+ * @return void | |
+ */ | |
+function _rest_server_add_default_and_remove_unknown(&$array, $keys, $default) { | |
+ foreach ($keys as $k) { | |
+ if (!isset($array[$k])) { | |
+ $array[$k] = TRUE; | |
+ } | |
+ } | |
+ foreach (array_keys($array) as $key) { | |
+ if (!in_array($key, $keys)) { | |
+ unset($array[$key]); | |
+ } | |
+ } | |
+} | |
+ | |
+/** | |
+ * Implements hook_services_resources_alter(). | |
*/ | |
function rest_server_services_resources_alter($resources, $endpoint) { | |
// Set the default models for the retrieve and index controllers in the node | |
diff --git a/services.install b/services.install | |
index 31ccc19..447c6ca 100644 | |
--- a/services.install | |
+++ b/services.install | |
@@ -26,12 +26,6 @@ function services_schema() { | |
'length' => 255, | |
'not null' => TRUE, | |
), | |
- 'title' => array( | |
- 'description' => 'The title of the endpoint.', | |
- 'type' => 'varchar', | |
- 'length' => 255, | |
- 'not null' => TRUE, | |
- ), | |
'server' => array( | |
'description' => 'The name of the server used in this endpoint.', | |
'type' => 'varchar', | |
@@ -52,6 +46,13 @@ function services_schema() { | |
'serialize' => TRUE, | |
'object default' => array(), | |
), | |
+ 'server_settings' => array( | |
+ 'description' => 'The server settings for the endpoint.', | |
+ 'type' => 'blob', | |
+ 'size' => 'big', | |
+ 'not null' => TRUE, | |
+ 'serialize' => TRUE | |
+ ), | |
'resources' => array( | |
'description' => 'Information about the resources exposed in this endpoint.', | |
'type' => 'text', | |
@@ -87,7 +88,37 @@ function services_schema() { | |
return $schema; | |
} | |
+ /** | |
+ * Implements hook_requirements(). | |
+ */ | |
+function services_requirements($phase) { | |
+ $requirements = array(); | |
+ $t = get_t(); | |
+ // Warn users of the possible threat. | |
+ if ($phase == 'runtime') { | |
+ //Pull endpoints that do not have services authentication enabled | |
+ $result = db_query('SELECT * FROM {services_endpoint} AS se WHERE se.authentication NOT LIKE "%s"', '%services%'); | |
+ $items = array(); | |
+ $has_endpoint = FALSE; | |
+ while ($endpoint = db_fetch_object($result)) { | |
+ $has_endpoint = TRUE; | |
+ $items[] = l($endpoint->name, 'admin/build/services/list/'. $endpoint->name); | |
+ } | |
+ // theme the endpoints list | |
+ $endpoints = theme('item_list', array('items' => $items)); | |
+ // Only display the list if we have at least one endpoint without services authentication. | |
+ if ($has_endpoint) { | |
+ $requirements['services'] = array( | |
+ 'description' => $t('Services authentication mechanismhas not been enabled for the following endpoints. Requests to these endpoints will always be anonymous.'), | |
+ 'severity' => REQUIREMENT_ERROR, | |
+ 'value' => $endpoints, | |
+ 'title' => 'Services Authentication Mechanism', | |
+ ); | |
+ } | |
+ } | |
+ return $requirements; | |
+} | |
/** | |
* Implementation of hook_install(). | |
*/ | |
@@ -266,24 +297,27 @@ function services_update_6302() { | |
} | |
/** | |
- * Implements hook_requirements(). | |
- * | |
- * Check version of ctools. | |
+ * Update 6303 adds the possibility to configure server settings on a per-endpoint basis. | |
+ * and sets upgrades all new servers to have at least services session enabled. | |
*/ | |
-function services_requirements($phase) { | |
- $t = get_t(); | |
- $requirements = array(); | |
- $ctools_info = db_fetch_array(db_query('SELECT info FROM {system} WHERE name = "%s"', 'ctools')); | |
- $ctools_info = unserialize($ctools_info['info']); | |
- // Check whether version of ctools is minimum alpha3 | |
- // as we need patch applied from http://drupal.org/node/933946 | |
- if ($ctools_info['datestamp'] < 1299715446) { | |
- $requirements['ctools'] = array( | |
- 'title' => 'CTools', | |
- 'value' => $ctools_info['version'], | |
- 'severity' => REQUIREMENT_ERROR, | |
- 'description' => $t('Please update CTools module to latest stable version (minimum 6.x-dev March 09).'), | |
- ); | |
- } | |
- return $requirements; | |
+function services_update_6303() { | |
+ $ret = array(); | |
+ // Add the new server settings field. | |
+ $new_field = array( | |
+ 'description' => 'The server settings for the endpoint.', | |
+ 'type' => 'blob', | |
+ 'size' => 'big', | |
+ 'not null' => TRUE, | |
+ 'serialize' => TRUE | |
+ ); | |
+ db_add_field($ret, 'services_endpoint', 'server_settings', $new_field); | |
+ return $ret; | |
+} | |
+/** | |
+ * Update 6304 removes title functionality as it is no longer used. | |
+ */ | |
+function services_update_6304() { | |
+ $ret = array(); | |
+ db_drop_field($ret, 'services_endpoint', 'title'); | |
+ return $ret; | |
} | |
\ No newline at end of file | |
diff --git a/services.module b/services.module | |
index 46e4ead..bdb1281 100644 | |
--- a/services.module | |
+++ b/services.module | |
@@ -35,6 +35,7 @@ function services_help($path, $arg) { | |
function services_perm() { | |
return array( | |
'administer services', | |
+ 'get taxonomy tree', | |
// File resource permissions | |
'get any binary files', | |
'get own binary files', | |
@@ -301,6 +302,27 @@ function services_services_resources() { | |
return array_merge(_services_core_resources(), _services_legacy_services_as_resources()); | |
} | |
+ /** | |
+ * Implementation of hook_services_authentication(). | |
+ */ | |
+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', | |
+ ); | |
+} | |
+ | |
+/** | |
+ * Authenticates a call using Drupal's built in sessions | |
+ * | |
+ * @return void | |
+ */ | |
+function _services_sessions_authenticate_call() { | |
+ global $user; | |
+ $user = services_get_server_info('original_user'); | |
+} | |
+ | |
/** | |
* Returns all the controller names for a endpoint. | |
* | |
@@ -405,7 +427,7 @@ function services_resources_as_procedures($resource) { | |
* | |
* @param $resource | |
* The resource being converted (node, user, etc.) | |
- * @param $name | |
+ * @param $name | |
* The method name (retrieve, create, etc.) | |
* @param $controller | |
* Associative array defining the method's properties and callbacks. | |
@@ -432,9 +454,18 @@ function _services_resource_controller_as_procedure($resource, $name, $controlle | |
* @param $parameter | |
* Array parameters to add to the index query. | |
*/ | |
-function services_resource_build_index_query($schema, $order, $page, $fields, $parameters = array()) { | |
+function services_resource_build_index_query($schema, $order, $page, $fields, $parameters = array(), $primary_table, $primary_field) { | |
$where = array(); | |
$fields = db_escape_string($fields); | |
+ | |
+ // need to append table prefix | |
+ 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); | |
@@ -442,7 +473,7 @@ function services_resource_build_index_query($schema, $order, $page, $fields, $p | |
// db_query(). | |
if(is_array($parameters)) { | |
foreach ($parameters as $field => $value) { | |
- $where[] = $field . ' = ' . db_type_placeholder($schema['fields'][$field]['type']); | |
+ $where[] = $primary_table . '.' . $field . ' = ' . db_type_placeholder($schema['fields'][$field]['type']); | |
} | |
} | |
@@ -450,8 +481,8 @@ function services_resource_build_index_query($schema, $order, $page, $fields, $p | |
$where = !empty($where) ? ' WHERE '. implode(' AND ', $where) : ''; | |
// Run through db_rewrite_sql to make sure proper access checks are applied. | |
- $sql = "SELECT $fields FROM {$table} $where ORDER BY $order"; | |
- $sql = db_rewrite_sql($sql); | |
+ $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, $parameters, $page * 20, 20); | |
return $result; | |
} | |
diff --git a/services.resource_build.inc b/services.resource_build.inc | |
index 0a25baf..b5937d4 100644 | |
--- a/services.resource_build.inc | |
+++ b/services.resource_build.inc | |
@@ -110,7 +110,7 @@ function _services_apply_endpoint(&$resources, $endpoint, $strict = TRUE) { | |
} | |
} | |
- $classes = array('targeted actions', 'actions', 'relationships'); | |
+ $classes = array('targeted_actions', 'actions', 'relationships'); | |
foreach ($classes as $class) { | |
if (!empty($resource[$class])) { | |
foreach ($resource[$class] as $op => $def) { | |
@@ -168,9 +168,9 @@ function _services_process_resource($name, &$resource, $controllers) { | |
} | |
} | |
- if (isset($resource['targeted actions'])) { | |
- foreach ($resource['targeted actions'] as $actname => $act) { | |
- $controllers[$name . '/targeted_action/' . $actname] = &$resource['actions'][$actname]; | |
+ if (isset($resource['targeted_actions'])) { | |
+ foreach ($resource['targeted_actions'] as $actname => $act) { | |
+ $controllers[$name . '/targeted_actions/' . $actname] = &$resource['actions'][$actname]; | |
} | |
} | |
return $controllers; | |
diff --git a/services.runtime.inc b/services.runtime.inc | |
index 643547c..9d31cfe 100644 | |
--- a/services.runtime.inc | |
+++ b/services.runtime.inc | |
@@ -94,7 +94,8 @@ class ServicesArgumentException extends ServicesException { | |
* services-specific authentication checks. Access checks will always be | |
* made. | |
*/ | |
-function services_controller_execute($controller, $args = array(), $auth_args = array(), $options = array()) { | |
+function services_controller_execute($controller, $args = array(), $options = array()) { | |
+ global $user; | |
// Check for missing arguments. | |
$server_info = services_server_info_object(); | |
if ($server_info->debug) { | |
@@ -102,13 +103,20 @@ function services_controller_execute($controller, $args = array(), $auth_args = | |
watchdog('services', 'Passed arguments: <pre>@arguments</pre>', array('@arguments' => print_r($args, TRUE)), WATCHDOG_DEBUG); | |
} | |
+ $original_user = $user; | |
+ $old_state = session_save_session(); | |
+ session_save_session(FALSE); | |
+ $user = drupal_anonymous_user(); | |
+ | |
+ services_set_server_info('original_user', $original_user); | |
+ | |
// Check authentication | |
if (!isset($options['skip_authentication']) || !$options['skip_authentication']) { | |
$endpoint_name = services_get_server_info('endpoint'); | |
$endpoint = services_endpoint_load($endpoint_name); | |
foreach ($endpoint->authentication as $auth_module => $settings) { | |
- if (isset($settings) && $auth_error = services_auth_invoke($auth_module, 'authenticate_call', $settings, $controller, $args, $auth_args)) { | |
+ if (isset($settings) && $auth_error = services_auth_invoke($auth_module, 'authenticate_call', $settings, $controller, $args)) { | |
return services_error($auth_error, 401); | |
} | |
} | |
@@ -168,7 +176,11 @@ function services_controller_execute($controller, $args = array(), $auth_args = | |
$result = call_user_func_array($callable, array($args, $controller, $result)); | |
} | |
} | |
- | |
+ | |
+ if (session_save_session($user) === FALSE) { | |
+ $user = $original_user; | |
+ session_save_session($old_state); | |
+ } | |
return $result; | |
} | |
@@ -243,6 +255,14 @@ function services_auth_invoke($module, $method, &$arg1 = NULL, &$arg2 = NULL, &$ | |
* Returns the formatted resource uri, or NULL if no formatter has been registered. | |
*/ | |
function services_resource_uri($path) { | |
+ //We need to use the alias if it exists. | |
+ $endpoint_name = services_get_server_info('endpoint'); | |
+ $endpoint = services_endpoint_load($endpoint_name); | |
+ if (isset($endpoint) && !empty($endpoint)) { | |
+ if (is_array($endpoint->resources) && is_array($path) && isset($path[0]) && isset($endpoint->resources[$path[0]]['alias'])) { | |
+ $path[0] = $endpoint->resources[$path[0]]['alias']; | |
+ } | |
+ } | |
$formatter = services_get_server_info('resource_uri_formatter'); | |
if ($formatter) { | |
return call_user_func($formatter, $path); | |
diff --git a/services.servers.api.php b/services.servers.api.php | |
index dff762b..f5978ef 100644 | |
--- a/services.servers.api.php | |
+++ b/services.servers.api.php | |
@@ -17,10 +17,17 @@ | |
* An associative array with the following keys. | |
* | |
* - name: The display name of this server. | |
+ * - settings: an assoc array containing settings information per endpoint that this server is enabled. | |
*/ | |
function hook_server_info() { | |
return array( | |
'name' => 'REST', | |
+ 'path' => 'rest', | |
+ 'settings' => array( | |
+ 'file' => array('inc', 'rest_server'), | |
+ 'form' => '_rest_server_settings', | |
+ 'submit' => '_rest_server_settings_submit', | |
+ ), | |
); | |
} | |
@@ -32,5 +39,16 @@ function hook_server_info() { | |
* servers. | |
*/ | |
function hook_server() { | |
- | |
+ $endpoint_path = services_get_server_info('endpoint_path', 'services/rest'); | |
+ $canonical_path = trim(drupal_substr($_GET['q'], drupal_strlen($endpoint_path)), '/'); | |
+ $canonical_path = explode('/', $_GET['q']); | |
+ $endpoint_path_count = count(explode('/', $endpoint_path)); | |
+ for ($x = 0; $x < $endpoint_path_count; $x++) { | |
+ array_shift($canonical_path); | |
+ } | |
+ $canonical_path = implode('/', $canonical_path); | |
+ if (empty($canonical_path)) { | |
+ return ''; | |
+ } | |
+ //Handle server based on $canonical_path | |
} | |
\ No newline at end of file | |
diff --git a/services.services.api.php b/services.services.api.php | |
index 784b93c..031f7a4 100644 | |
--- a/services.services.api.php | |
+++ b/services.services.api.php | |
@@ -18,7 +18,7 @@ | |
* @return | |
* An associative array which defines available resources. | |
* | |
- * The associative array which defines services has six possible top | |
+ * The associative array which defines services has seven possible top | |
* level keys: | |
* | |
* - create | |
@@ -26,10 +26,12 @@ | |
* - update | |
* - delete | |
* - actions | |
- * - targeted actions | |
+ * - targeted_actions | |
+ * - relationships | |
+ * | |
* | |
* The first four (the CRUD functions) define the indvidual service | |
- * callbacks for each function. However 'actions' and 'targeted actions' | |
+ * callbacks for each function. However 'actions' and 'targeted_actions' | |
* can contain multiple callbacks. | |
* | |
* For those familiar with Services 2.x, these callbacks are created | |
@@ -62,57 +64,171 @@ | |
* - default value: this is a value that will be passed to the method for this particular argument if no argument value is passed | |
*/ | |
function hook_services_resources() { | |
- return array( | |
- 'user' => array( | |
- 'file' => array('type' => 'inc', 'module' => 'user_resource'), | |
+$node_resource = array( | |
+ 'node' => array( | |
'retrieve' => array( | |
- 'help' => 'Retrieves a user', | |
- 'callback' => '_user_resource_retrieve', | |
- 'access arguments' => array('access user profiles'), // this is probably not enough, doesn't block things like pass and email | |
- 'access arguments append' => TRUE, | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'callback' => '_node_resource_retrieve', | |
'args' => array( | |
array( | |
- 'name' => 'uid', | |
+ 'name' => 'nid', | |
+ 'optional' => FALSE, | |
+ 'source' => array('path' => 0), | |
'type' => 'int', | |
- 'description' => 'The uid of the user to retrieve.', | |
- 'source' => array('path' => '0'), | |
+ 'description' => 'The nid of the node to get', | |
+ ), | |
+ ), | |
+ 'access callback' => '_node_resource_access', | |
+ 'access arguments' => array('view'), | |
+ 'access arguments append' => TRUE, | |
+ ), | |
+ 'create' => array( | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'callback' => '_node_resource_create', | |
+ 'args' => array( | |
+ array( | |
+ 'name' => 'node', | |
'optional' => FALSE, | |
- 'default value' => NULL, | |
+ 'source' => 'data', | |
+ 'description' => 'The node data to create', | |
+ 'type' => 'array', | |
), | |
), | |
+ 'access callback' => '_node_resource_access', | |
+ 'access arguments' => array('create'), | |
+ 'access arguments append' => TRUE, | |
), | |
- ), | |
- | |
- 'actions' => array( | |
- 'login' => array( | |
- 'help' => 'Login a user for a new session', | |
- 'callback' => '_user_resource_login', | |
+ 'update' => array( | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'callback' => '_node_resource_update', | |
'args' => array( | |
array( | |
- 'name' => 'username', | |
- 'type' => 'string', | |
- 'description' => 'A valid username', | |
- 'source' => array('data'), | |
+ 'name' => 'nid', | |
'optional' => FALSE, | |
+ 'source' => array('path' => 0), | |
+ 'type' => 'int', | |
+ 'description' => 'The nid of the node to get', | |
), | |
array( | |
- 'name' => 'password', | |
- 'type' => 'string', | |
- 'description' => 'A valid password', | |
- 'source' => array('data'), | |
+ 'name' => 'node', | |
'optional' => FALSE, | |
+ 'source' => 'data', | |
+ 'description' => 'The node data to update', | |
+ 'type' => 'array', | |
), | |
), | |
+ 'access callback' => '_node_resource_access', | |
+ 'access arguments' => array('update'), | |
+ 'access arguments append' => TRUE, | |
), | |
- | |
- 'logout' => array( | |
- 'help' => 'Logout a user session', | |
- 'callback' => '_user_resource_logout', | |
+ 'delete' => array( | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'callback' => '_node_resource_delete', | |
+ 'args' => array( | |
+ array( | |
+ 'name' => 'nid', | |
+ 'optional' => FALSE, | |
+ 'source' => array('path' => 0), | |
+ 'type' => 'int', | |
+ ), | |
+ ), | |
+ 'access callback' => '_node_resource_access', | |
+ 'access arguments' => array('delete'), | |
+ 'access arguments append' => TRUE, | |
+ ), | |
+ 'index' => array( | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'callback' => '_node_resource_index', | |
'args' => array( | |
array( | |
+ 'name' => 'page', | |
+ 'optional' => TRUE, | |
+ 'type' => 'int', | |
+ 'description' => 'The zero-based index of the page to get, defaults to 0.', | |
+ 'default value' => 0, | |
+ 'source' => array('param' => 'page'), | |
+ ), | |
+ array( | |
+ 'name' => 'fields', | |
+ 'optional' => TRUE, | |
+ 'type' => 'string', | |
+ 'description' => 'The fields to get.', | |
+ 'default value' => '*', | |
+ 'source' => array('param' => 'fields'), | |
+ ), | |
+ array( | |
+ 'name' => 'parameters', | |
+ 'optional' => TRUE, | |
+ 'type' => 'array', | |
+ 'description' => 'Parameters array', | |
+ 'default value' => array(), | |
+ 'source' => array('param' => 'parameters'), | |
+ ), | |
+ ), | |
+ 'access arguments' => array('access content'), | |
+ ), | |
+ 'relationships' => array( | |
+ 'files' => array( | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'help' => t('This method returns files associated with a node.'), | |
+ 'access callback' => '_node_resource_access', | |
+ 'access arguments' => array('view'), | |
+ 'access arguments append' => TRUE, | |
+ 'callback' => '_node_resource_load_node_files', | |
+ 'args' => array( | |
+ array( | |
+ 'name' => 'nid', | |
+ 'optional' => FALSE, | |
+ 'source' => array('path' => 0), | |
+ 'type' => 'int', | |
+ 'description' => 'The nid of the node whose files we are getting', | |
+ ), | |
+ array( | |
+ 'name' => 'file_contents', | |
+ 'type' => 'int', | |
+ 'description' => t('To return file contents or not.'), | |
+ 'source' => array('path' => 2), | |
+ 'optional' => TRUE, | |
+ 'default value' => TRUE, | |
+ ), | |
), | |
), | |
), | |
), | |
); | |
+ if (module_exists('comment')) { | |
+ $comments = array( | |
+ 'file' => array('type' => 'inc', 'module' => 'services', 'name' => 'resources/node_resource'), | |
+ 'help' => t('This method returns the number of new comments on a given node.'), | |
+ 'access callback' => 'user_access', | |
+ 'access arguments' => array('access comments'), | |
+ 'access arguments append' => FALSE, | |
+ 'callback' => '_node_resource_load_node_comments', | |
+ 'args' => array( | |
+ array( | |
+ 'name' => 'nid', | |
+ 'type' => 'int', | |
+ 'description' => t('The node id to load comments for.'), | |
+ 'source' => array('path' => 0), | |
+ 'optional' => FALSE, | |
+ ), | |
+ array( | |
+ 'name' => 'count', | |
+ 'type' => 'int', | |
+ 'description' => t('Number of comments to load.'), | |
+ 'source' => array('param' => 'count'), | |
+ 'optional' => TRUE, | |
+ ), | |
+ array( | |
+ 'name' => 'offset', | |
+ 'type' => 'int', | |
+ 'description' => t('If count is set to non-zero value, you can pass also non-zero value for start. For example to get comments from 5 to 15, pass count=10 and start=5.'), | |
+ 'source' => array('param' => 'offset'), | |
+ 'optional' => TRUE, | |
+ ), | |
+ ), | |
+ ); | |
+ $node_resource['node']['relationships']['comments'] = $comments; | |
+ } | |
+ return $node_resource; | |
} | |
diff --git a/tests/functional/ServicesEndpointTests.test b/tests/functional/ServicesEndpointTests.test | |
index 3e3dba6..5172299 100644 | |
--- a/tests/functional/ServicesEndpointTests.test | |
+++ b/tests/functional/ServicesEndpointTests.test | |
@@ -83,34 +83,6 @@ class ServicesEndpointTests extends ServicesWebTestCase { | |
$this->assertText('Path to endpoint field is required.', | |
t('Endpoint path missing error message.')) ; | |
- $this->assertFieldByName('title', $edit['title'], | |
- t('Title field remains.')) ; | |
- $this->assertFieldByName('server', 'rest_server', | |
- t('Server is rest server')) ; | |
- $this->assertFieldChecked('edit-services-use-content-permissions', | |
- t('Storage use content permission is checked.')) ; | |
- } | |
- | |
- /** | |
- * Test missing title for endpoint causes an error. | |
- */ | |
- public function testMissingTitle() { | |
- $edit = $this->populateEndpointFAPI() ; | |
- unset($edit['title']) ; | |
- // Create and log in our privileged user. | |
- $this->privilegedUser = $this->drupalCreateUser(array( | |
- 'administer services', | |
- 'administer nodes', | |
- 'administer site configuration', | |
- )); | |
- $this->drupalLogin($this->privilegedUser); | |
- $this->drupalPost('admin/build/services/add', $edit, t('Save')) ; | |
- $this->assertResponse('200', 'expected 200'); | |
- | |
- $this->assertText('Endpoint title field is required.', | |
- t('Endpoint title missing error message.')) ; | |
- $this->assertFieldByName('name', $edit['name'], | |
- t('Name field remains.')) ; | |
$this->assertFieldByName('server', 'rest_server', | |
t('Server is rest server')) ; | |
$this->assertFieldChecked('edit-services-use-content-permissions', | |
@@ -138,8 +110,6 @@ class ServicesEndpointTests extends ServicesWebTestCase { | |
t('Server missing error message.')); | |
$this->assertFieldByName('name', $edit['name'], | |
t('Name field remains.')); | |
- $this->assertFieldByName('title', $edit['title'], | |
- t('Title field remains.')); | |
$this->assertFieldChecked('edit-services-use-content-permissions', | |
t('Storage use content permission is checked.')) ; | |
} | |
@@ -159,7 +129,6 @@ class ServicesEndpointTests extends ServicesWebTestCase { | |
public function populateEndpointFAPI() { | |
return array( | |
'name' => 'machinename', | |
- 'title' => $this->randomName(20), | |
'path' => $this->randomName(10), | |
'server' => 'rest_server', | |
'services_use_content_permissions' => TRUE, | |
@@ -172,7 +141,6 @@ class ServicesEndpointTests extends ServicesWebTestCase { | |
$endpoint->disabled = FALSE; /* Edit this to true to make a default endpoint disabled initially */ | |
$endpoint->api_version = 3; | |
$endpoint->name = $edit['name']; | |
- $endpoint->title = $edit['title']; | |
$endpoint->server = $edit['server']; | |
$endpoint->path = $edit['path']; | |
$endpoint->authentication = array( | |
diff --git a/tests/functional/ServicesParserTests.test b/tests/functional/ServicesParserTests.test | |
new file mode 100644 | |
index 0000000..183feed | |
--- /dev/null | |
+++ b/tests/functional/ServicesParserTests.test | |
@@ -0,0 +1,103 @@ | |
+<?php | |
+ | |
+/** | |
+ * @file | |
+ * Call the endpoint tests when no authentication is being used. | |
+ * | |
+ */ | |
+ | |
+/** | |
+ * Run test cases for the endpoint with no authentication turned on. | |
+ * | |
+ */ | |
+class ServicesParserTests extends ServicesWebTestCase { | |
+ // Class variables | |
+ protected $privilegedUser = NULL ; | |
+ // Endpoint details. | |
+ protected $endpoint = NULL; | |
+ | |
+ /** | |
+ * Implementation of setUp(). | |
+ */ | |
+ public function setUp() { | |
+ parent::setUp( | |
+ 'ctools', | |
+ 'services', | |
+ 'rest_server' | |
+ ); | |
+ // Set up endpoint with disabled 'application/x-www-form-urlencoded' parser. | |
+ $edit = $this->populateEndpointFAPI() ; | |
+ $endpoint = new stdClass; | |
+ $endpoint->disabled = FALSE; | |
+ $endpoint->api_version = 3; | |
+ $endpoint->name = $edit['name']; | |
+ $endpoint->title = $edit['title']; | |
+ $endpoint->server = $edit['server']; | |
+ $endpoint->path = $edit['path']; | |
+ $endpoint->authentication = array( | |
+ 'services' => 'services', | |
+ ); | |
+ $endpoint->server_settings = array( | |
+ 'rest_server' => array( | |
+ 'formatters' => array( | |
+ 'php' => TRUE, | |
+ ), | |
+ 'parsers' => array( | |
+ 'application/x-yaml' => TRUE, | |
+ 'application/json' => TRUE, | |
+ 'application/vnd.php.serialized' => TRUE, | |
+ 'application/plist' => TRUE, | |
+ 'application/plist+xml' => TRUE, | |
+ 'application/x-www-form-urlencoded' => FALSE, | |
+ ), | |
+ ), | |
+ ); | |
+ $endpoint->resources = array( | |
+ 'user' => array( | |
+ 'actions' => array( | |
+ 'login' => array( | |
+ 'enabled' => 1, | |
+ ), | |
+ 'logout' => array( | |
+ 'enabled' => 1, | |
+ ), | |
+ ), | |
+ ), | |
+ ); | |
+ $endpoint->debug = 1; | |
+ $endpoint->export_type = FALSE; | |
+ services_endpoint_save($endpoint); | |
+ $endpoint = services_endpoint_load($endpoint->name); | |
+ $this->assertTrue($endpoint->name == $edit['name'], t('Endpoint successfully created')); | |
+ $this->endpoint = $endpoint; | |
+ } | |
+ | |
+ /** | |
+ * Implementation of getInfo(). | |
+ */ | |
+ public static function getInfo() { | |
+ return array( | |
+ 'name' => t('Parser'), | |
+ 'description' => t('Test the Parser functionality.'), | |
+ 'group' => t('Services'), | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Testing parser functionality. | |
+ */ | |
+ public function testParser() { | |
+ $account = $this->drupalCreateUser(); | |
+ | |
+ // Logout first. | |
+ $this->drupalLogout(); | |
+ | |
+ // Try to login. By default servicesPost uses | |
+ // 'application/x-www-form-urlencoded' type. So it should be refused. | |
+ $response = $this->servicesPost($this->endpoint->path . '/user/login', array('username' => $account->name, 'password' => $account->pass_raw)); | |
+ | |
+ $this->assertTrue(strpos($response['header'], '406 Not Acceptable: Unsupported request content type application/x-www-form-urlencoded') !== FALSE, | |
+ t('Do not accept application/x-www-form-urlencoded if disabled.'), 'Parser'); | |
+ } | |
+ | |
+} | |
\ No newline at end of file | |
diff --git a/tests/functional/ServicesResourceCommentTests.test b/tests/functional/ServicesResourceCommentTests.test | |
index c2e093b..86cac39 100644 | |
--- a/tests/functional/ServicesResourceCommentTests.test | |
+++ b/tests/functional/ServicesResourceCommentTests.test | |
@@ -66,7 +66,7 @@ class ServicesResourceCommentTests extends ServicesWebtestCase { | |
'subject' => $this->randomString(), | |
'comment' => $this->randomString(), | |
); | |
- $response = $this->servicesPost($path . '/comment', array('comment' => $comment)); | |
+ $response = $this->servicesPost($path . '/comment', $comment); | |
$cid = $response['body']['cid']; | |
$comment['cid'] = $cid; | |
@@ -85,10 +85,54 @@ class ServicesResourceCommentTests extends ServicesWebtestCase { | |
// Full HTML format. | |
'format' => 2, | |
); | |
+ $response_array = $this->servicesPost($this->endpoint->path . '/comment', $comment); | |
+ | |
+ $new_comment = _comment_load($response_array['body']['cid']); | |
+ $this->assertNotEqual($new_comment->format, $comment['format'], t('Full HTML format has not been applied.'), 'CommentResource: Create'); | |
+ } | |
+ | |
+ /** | |
+ * Test create comment (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testCommentCreateLegacy() { | |
+ $path = $this->endpoint->path; | |
+ | |
+ // Create node with commenting. | |
+ $settings = array('comment' => COMMENT_NODE_READ_WRITE); | |
+ $node = $this->drupalCreateNode($settings); | |
+ | |
+ $comment = array( | |
+ 'uid' => $this->privileged_user->uid, | |
+ 'nid' => $node->nid, | |
+ 'subject' => $this->randomString(), | |
+ 'comment' => $this->randomString(), | |
+ ); | |
+ $response = $this->servicesPost($path . '/comment', array('comment' => $comment)); | |
+ | |
+ $cid = $response['body']['cid']; | |
+ $comment['cid'] = $cid; | |
+ | |
+ $comment_load = (array)_comment_load($cid); | |
+ $comment_intersect = array_intersect_assoc($comment_load, $comment); | |
+ | |
+ $this->assertEqual($comment, $comment_intersect, t('Comment created properly.'), 'CommentResource: Create (Legacy)'); | |
+ | |
+ // Try to create node with not allowed filter. | |
+ $comment = array( | |
+ 'uid' => $this->privileged_user->uid, | |
+ 'nid' => $node->nid, | |
+ 'subject' => $this->randomString(), | |
+ 'comment' => $this->randomString(), | |
+ // Full HTML format. | |
+ 'format' => 2, | |
+ ); | |
$response_array = $this->servicesPost($this->endpoint->path . '/comment', array('comment' => $comment)); | |
$new_comment = _comment_load($response_array['body']['cid']); | |
- $this->assertNotEqual($new_comment->format, $comment->format, t('Full HTML format has not been applied.'), 'CommentResource: Create'); | |
+ $this->assertNotEqual($new_comment->format, $comment['format'], t('Full HTML format has not been applied.'), 'CommentResource: Create (Legacy)'); | |
} | |
/** | |
@@ -144,7 +188,7 @@ class ServicesResourceCommentTests extends ServicesWebtestCase { | |
$comment_update['subject'] = $this->randomString(); | |
$comment_update['comment'] = $this->randomString(); | |
- $response = $this->servicesPut($path . '/comment/' . $cid, array('data' => $comment_update)); | |
+ $response = $this->servicesPut($path . '/comment/' . $cid, $comment_update); | |
$comment_load = (array)_comment_load($cid); | |
@@ -154,9 +198,12 @@ class ServicesResourceCommentTests extends ServicesWebtestCase { | |
} | |
/** | |
- * Test delete method. | |
+ * Test update method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
*/ | |
- function testCommentDelete() { | |
+ function testCommentUpdateLegacy() { | |
$path = $this->endpoint->path; | |
// Create node with commenting. | |
@@ -173,65 +220,44 @@ class ServicesResourceCommentTests extends ServicesWebtestCase { | |
$cid = comment_save((array) $comment); | |
$comment['cid'] = $cid; | |
- $response = $this->servicesDelete($path . '/comment/' . $cid); | |
+ $comment_update = $comment; | |
+ $comment_update['subject'] = $this->randomString(); | |
+ $comment_update['comment'] = $this->randomString(); | |
- $comment_load = _comment_load($cid); | |
+ $response = $this->servicesPut($path . '/comment/' . $cid, array('data' => $comment_update)); | |
- $this->assertTrue(empty($comment_load), t('Comment deleted properly.'), 'CommentResource: Delete'); | |
+ $comment_load = (array)_comment_load($cid); | |
+ | |
+ $comment_intersect = array_intersect_assoc($comment_load, $comment_update); | |
+ | |
+ $this->assertEqual($comment_update, $comment_intersect, t('Comment updated properly.'), 'CommentResource: Update (legacy)'); | |
} | |
/** | |
- * Test loadNodeComments method. | |
+ * Test delete method. | |
*/ | |
- function testCommentLoadNodeComments() { | |
+ function testCommentDelete() { | |
$path = $this->endpoint->path; | |
// Create node with commenting. | |
$settings = array('comment' => COMMENT_NODE_READ_WRITE); | |
$node = $this->drupalCreateNode($settings); | |
- $nid = $node->nid; | |
- | |
- // Generate 15 comments for node. | |
- $comments = array(); | |
- for ($i = 0; $i < 15; $i++) { | |
- $comment = array( | |
- 'uid' => $this->privileged_user->uid, | |
- 'nid' => $nid, | |
- 'subject' => $this->randomString(), | |
- 'comment' => $this->randomString(), | |
- ); | |
- | |
- $cid = comment_save((array) $comment); | |
- | |
- $comments[] = _comment_load($cid); | |
- } | |
- $comments = array_reverse($comments); | |
- // Generate some comments for another node. | |
- $settings = array('comment' => COMMENT_NODE_READ_WRITE); | |
- $node2 = $this->drupalCreateNode($settings); | |
- for ($i = 0; $i < 5; $i++) { | |
- $comment = array( | |
- 'uid' => $this->privileged_user->uid, | |
- 'nid' => $node2->nid, | |
- 'subject' => $this->randomString(), | |
- 'comment' => $this->randomString(), | |
- ); | |
+ $comment = array( | |
+ 'uid' => $this->privileged_user->uid, | |
+ 'nid' => $node->nid, | |
+ 'subject' => $this->randomString(), | |
+ 'comment' => $this->randomString(), | |
+ ); | |
- $cid = comment_save((array) $comment); | |
- } | |
+ $cid = comment_save((array) $comment); | |
+ $comment['cid'] = $cid; | |
- // Load all comments of the first node. | |
- $response = $this->servicesPost($path . '/comment/loadNodeComments', array('nid' => $nid)); | |
- $this->assertEqual(array_slice($comments, 0, 10), $response['body'], t('Received all 15 comments.'), 'CommentResource: loadNodeComments'); | |
+ $response = $this->servicesDelete($path . '/comment/' . $cid); | |
- // Load only 5 comments of the first node. | |
- $response = $this->servicesPost($path . '/comment/loadNodeComments', array('nid' => $nid, 'count' => 5)); | |
- $this->assertEqual(array_slice($comments, 0, 5), $response['body'], t('Received last 5 comments.'), 'CommentResource: loadNodeComments'); | |
+ $comment_load = _comment_load($cid); | |
- // Load only 5 comments of the first node starting from fifth comment. | |
- $response = $this->servicesPost($path . '/comment/loadNodeComments', array('nid' => $nid, 'count' => 5, 'start' => 5)); | |
- $this->assertEqual(array_slice($comments, 5, 5), $response['body'], t('Received 5 comments starting from fifth comment.'), 'CommentResource: loadNodeComments'); | |
+ $this->assertTrue(empty($comment_load), t('Comment deleted properly.'), 'CommentResource: Delete'); | |
} | |
/** | |
diff --git a/tests/functional/ServicesResourceFileTests.test b/tests/functional/ServicesResourceFileTests.test | |
index f2e750f..5d762be 100644 | |
--- a/tests/functional/ServicesResourceFileTests.test | |
+++ b/tests/functional/ServicesResourceFileTests.test | |
@@ -77,7 +77,7 @@ class ServicesResourceFileTests extends ServicesWebTestCase { | |
); | |
// Create file with call. | |
- $result = $this->servicesPost($this->endpoint->path . '/file', array('file' => $file)); | |
+ $result = $this->servicesPost($this->endpoint->path . '/file', $file); | |
$this->assertEqual($result['code'], 200, t('File created.'), 'FileResource: Create'); | |
// Load file and assert that it exists. | |
@@ -88,7 +88,7 @@ class ServicesResourceFileTests extends ServicesWebTestCase { | |
// Lets create another file with the same details | |
// and ensure name and path are changed automatically. | |
- $result = $this->servicesPost($this->endpoint->path . '/file', array('file' => $file)); | |
+ $result = $this->servicesPost($this->endpoint->path . '/file', $file); | |
$dbresult = db_query('SELECT * FROM {files} WHERE fid = %d', $result['body']['fid']); | |
$file1 = db_fetch_object($dbresult); | |
$file2 = db_fetch_object($dbresult); | |
@@ -97,6 +97,41 @@ class ServicesResourceFileTests extends ServicesWebTestCase { | |
} | |
/** | |
+ * Test create method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ public function testResourceFileCreateLegacy() { | |
+ // Create file argument with data. | |
+ $file = array( | |
+ 'filesize' => filesize($this->testfiles[0]->filename), | |
+ 'filename' => $this->testfiles[0]->filename, | |
+ 'file' => base64_encode(file_get_contents($this->testfiles[0]->filename)), | |
+ 'uid' => $this->privileged_user->uid, | |
+ ); | |
+ | |
+ // Create file with call. | |
+ $result = $this->servicesPost($this->endpoint->path . '/file', array('file' => $file)); | |
+ $this->assertEqual($result['code'], 200, t('File created.'), 'FileResource: Create (Legacy)'); | |
+ | |
+ // Load file and assert that it exists. | |
+ //$file_load = file_load($result['body']['fid']); | |
+ $dbresult = db_query('SELECT * FROM {files} WHERE fid = %d', $result['body']['fid']); | |
+ $file_load = db_fetch_object($dbresult); | |
+ $this->assertTrue(is_file($file_load->filepath), t('New file saved to disk.'), 'FileResource: Create (Legacy)'); | |
+ | |
+ // Lets create another file with the same details | |
+ // and ensure name and path are changed automatically. | |
+ $result = $this->servicesPost($this->endpoint->path . '/file', array('file' => $file)); | |
+ $dbresult = db_query('SELECT * FROM {files} WHERE fid = %d', $result['body']['fid']); | |
+ $file1 = db_fetch_object($dbresult); | |
+ $file2 = db_fetch_object($dbresult); | |
+ $this->assertTrue($file1->filename != $file2->filename && $file1->filepath != $file2->filepath, | |
+ t('Two identical files created end up with different names.'), 'FileResource: Create (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test retrieve method. | |
*/ | |
public function testResourceFileRetrieve() { | |
diff --git a/tests/functional/ServicesResourceNodeTests.test b/tests/functional/ServicesResourceNodeTests.test | |
index 76275f2..d93568f 100644 | |
--- a/tests/functional/ServicesResourceNodeTests.test | |
+++ b/tests/functional/ServicesResourceNodeTests.test | |
@@ -98,7 +98,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
'name' => $this->privilegedUser->name, | |
); | |
- $responseArray = $this->servicesPost($this->endpoint->path . '/node', array('node' => $node)); | |
+ $responseArray = $this->servicesPost($this->endpoint->path . '/node', $node); | |
$nodeResourceCreateReturn = $responseArray['body']; | |
$this->assertTrue(isset($nodeResourceCreateReturn['nid']), t('Node was successfully created'), 'NodeResource: Create'); | |
@@ -110,6 +110,37 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Testing node_resource Create (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ public function testEndpointResourceNodeCreateLegacy() { | |
+ // Create and log in our privileged user. | |
+ $this->privilegedUser = $this->drupalCreateUser(array( | |
+ 'administer services', | |
+ 'administer nodes', | |
+ )); | |
+ $this->drupalLogin($this->privilegedUser); | |
+ $node = array( | |
+ 'title' => 'testing', | |
+ 'body' => 'bodytest', | |
+ 'type' => 'story', | |
+ 'name' => $this->privilegedUser->name, | |
+ ); | |
+ | |
+ $responseArray = $this->servicesPost($this->endpoint->path . '/node', array('node' => $node)); | |
+ $nodeResourceCreateReturn = $responseArray['body']; | |
+ | |
+ $this->assertTrue(isset($nodeResourceCreateReturn['nid']), t('Node was successfully created'), 'NodeResource: Create (Legacy)'); | |
+ if (isset($nodeResourceCreateReturn['nid'])) { | |
+ $newNode = node_load($nodeResourceCreateReturn['nid']); | |
+ $this->assertTrue($newNode->title = $node['title'], t('Title was the same'), 'NodeResource: Create (Legacy)'); | |
+ $this->assertTrue($newNode->body = $node['body'], t('Body was the same'), 'NodeResource: Create (Legacy)'); | |
+ } | |
+ } | |
+ | |
+ /** | |
* testing node_resource Created make ure it fails with no perms | |
*/ | |
public function testEndpointResourceNodeCreateFail() { | |
@@ -125,7 +156,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
'name' => $this->privilegedUser->name, | |
); | |
- $responseArray = $this->servicesPost($this->endpoint->path . '/node', array('node' => $node)); | |
+ $responseArray = $this->servicesPost($this->endpoint->path . '/node', $node); | |
$this->assertTrue($responseArray['code'] == 401, t('User with not sufficient permissions cannot create node'), 'NodeResource: Create'); | |
} | |
@@ -148,7 +179,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
'type' => 'page', | |
); | |
- $responseArray = $this->servicesPost($this->endpoint->path . '/node', array('node' => $node)); | |
+ $responseArray = $this->servicesPost($this->endpoint->path . '/node', $node); | |
$nodeResourceUpdateReturn = $responseArray['body']; | |
$nodeAfterUpdate = node_load($nodeResourceUpdateReturn); | |
@@ -195,7 +226,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
)), | |
); | |
- $response = $this->servicesPost($this->endpoint->path . '/node', array('node' => $node)); | |
+ $response = $this->servicesPost($this->endpoint->path . '/node', $node); | |
// Get number of attached taxonomy terms from this node. We do it manually | |
// as we cannot get terms on node_load as as empty array is statically | |
@@ -303,9 +334,10 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
$this->assertTrue(isset($result['body'][$testfile1['fid']]) && isset($result['body'][$testfile2['fid']]) && !isset($result['body'][$testfile3['fid']]), | |
t('Attached files listed.'), 'FileResource: nodeFiles'); | |
} | |
+ | |
/** | |
- * testing node_resource Update | |
- */ | |
+ * Testing node_resource Update | |
+ */ | |
public function testEndpointResourceNodeUpdate() { | |
// Create and log in our privileged user. | |
$this->privilegedUser = $this->drupalCreateUser(array( | |
@@ -321,7 +353,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
'name' => $this->privilegedUser->name, | |
); | |
- $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, array('node' => $node_update)); | |
+ $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, $node_update); | |
$nodeAfterUpdate = node_load($responseArray['body']['nid']); | |
$this->assertTrue(isset($nodeAfterUpdate->nid), t('Node was successfully updated'), 'NodeResource: Updated'); | |
if (isset($nodeAfterUpdate->nid)) { | |
@@ -331,6 +363,36 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Testing node_resource Update (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ public function testEndpointResourceNodeUpdateLegacy() { | |
+ // Create and log in our privileged user. | |
+ $this->privilegedUser = $this->drupalCreateUser(array( | |
+ 'administer services', | |
+ 'administer nodes', | |
+ )); | |
+ $this->drupalLogin($this->privilegedUser); | |
+ $node = $this->drupalCreateNode(); | |
+ $node_update = array( | |
+ 'title' => 'testing', | |
+ 'body' => 'bodytest', | |
+ 'type' => 'story', | |
+ 'name' => $this->privilegedUser->name, | |
+ ); | |
+ | |
+ $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, array('node' => $node_update)); | |
+ $nodeAfterUpdate = node_load($responseArray['body']['nid']); | |
+ $this->assertTrue(isset($nodeAfterUpdate->nid), t('Node was successfully updated'), 'NodeResource: Updated (Legacy)'); | |
+ if (isset($nodeAfterUpdate->nid)) { | |
+ $this->assertTrue($nodeAfterUpdate->title == $node_update['title'], t('Title was the same'), 'NodeResource: Update (Legacy)'); | |
+ $this->assertTrue($nodeAfterUpdate->body == $node_update['body'], t('Body was the same'), 'NodeResource: Update (Legacy)'); | |
+ } | |
+ } | |
+ | |
+ /** | |
* testing node_resource Update fail with no permissions | |
*/ | |
public function testEndpointResourceNodeUpdatePermFail() { | |
@@ -352,7 +414,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
'body' => 'bodytest', | |
'type' => 'story', | |
); | |
- $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, array('node' => $node_update)); | |
+ $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, $node_update); | |
$this->assertTrue(strpos($responseArray['status'], 'Access denied for user'), t('Updating the node failed without needed permissions. This is good!'), 'NodeResource: Update'); | |
} | |
@@ -375,7 +437,7 @@ class ServicesResourceNodetests extends ServicesWebtestCase { | |
'type' => 'story', | |
); | |
- $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, array('node' => $node_update)); | |
+ $responseArray = $this->servicesPut($this->endpoint->path . '/node/' . $node->nid, $node_update); | |
$this->assertTrue(strpos($responseArray['status'], 'Title field is required.'), t('Node was not updated without title.'), 'NodeResource: Update'); | |
} | |
diff --git a/tests/functional/ServicesResourceTaxonomyTests.test b/tests/functional/ServicesResourceTaxonomyTests.test | |
index 1bbf87e..3aecac0 100644 | |
--- a/tests/functional/ServicesResourceTaxonomyTests.test | |
+++ b/tests/functional/ServicesResourceTaxonomyTests.test | |
@@ -67,7 +67,7 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
'weight' => 0, | |
); | |
- $response = $this->servicesPost($path . '/taxonomy_vocabulary', array('vocabulary' => $vocabulary)); | |
+ $response = $this->servicesPost($path . '/taxonomy_vocabulary', $vocabulary); | |
$vid = db_result(db_query('SELECT vid FROM {vocabulary} WHERE name = "%s"', $vocabulary['name'])); | |
@@ -78,6 +78,36 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Test taxonomy vocabulary create method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testVocabularyCreateLegacy() { | |
+ $path = $this->endpoint->path; | |
+ | |
+ $vocabulary = array( | |
+ 'name' => $this->randomName(), | |
+ 'description' => $this->randomString(), | |
+ 'help' => $this->randomString(), | |
+ 'relations' => 1, | |
+ 'hierarchy' => 1, | |
+ 'multiple' => 1, | |
+ 'required' => 0, | |
+ 'module' => 'services', | |
+ 'weight' => 0, | |
+ ); | |
+ | |
+ $response = $this->servicesPost($path . '/taxonomy_vocabulary', array('vocabulary' => $vocabulary)); | |
+ | |
+ $vid = db_result(db_query('SELECT vid FROM {vocabulary} WHERE name = "%s"', $vocabulary['name'])); | |
+ | |
+ $vocabulary_load = (array)taxonomy_vocabulary_load($vid); | |
+ $vocabulary_intersect = array_intersect_assoc($response['body'], $vocabulary_load); | |
+ $this->assertEqual($vocabulary['name'], $response['body']['name'], t('Taxonomy vocabulary created properly.'), 'TaxonomyVocabularyResource: Create (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test taxonomy vocabulry retrieve method. | |
*/ | |
function testVocabularyRetrieve() { | |
@@ -106,7 +136,7 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
$vocabulary['name'] = $this->randomName(); | |
$vocabulary['description'] = $this->randomString(); | |
- $response = $this->servicesPUT($path . '/taxonomy_vocabulary/' . $vid, array('vocabulary' => $vocabulary)); | |
+ $response = $this->servicesPUT($path . '/taxonomy_vocabulary/' . $vid, $vocabulary); | |
$vocabulary_load = (array)taxonomy_vocabulary_load($vid, TRUE); | |
@@ -115,6 +145,29 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Test taxonomy vocabulary update (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testVocabularyUpdateLegacy() { | |
+ $path = $this->endpoint->path; | |
+ | |
+ $vocabulary = $this->createVocabulary(); | |
+ $vid = $vocabulary['vid']; | |
+ | |
+ $vocabulary['name'] = $this->randomName(); | |
+ $vocabulary['description'] = $this->randomString(); | |
+ | |
+ $response = $this->servicesPUT($path . '/taxonomy_vocabulary/' . $vid, array('vocabulary' => $vocabulary)); | |
+ | |
+ $vocabulary_load = (array)taxonomy_vocabulary_load($vid, TRUE); | |
+ | |
+ $vocabulary_intersect = array_intersect_assoc($vocabulary, $vocabulary_load); | |
+ $this->assertEqual($vocabulary, $vocabulary_intersect, t('Taxonomy vocabulary updated properly.'), 'TaxonomyVocabularyResource: Update (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test taxonomy vocabulary delete method. | |
*/ | |
function testVocabularyDelete() { | |
@@ -198,7 +251,7 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
'parent' => NULL, | |
); | |
- $response = $this->servicesPost($path . '/taxonomy_term', array('term' => $term)); | |
+ $response = $this->servicesPost($path . '/taxonomy_term', $term); | |
// Load term by name. | |
$term_by_name = (array)current(taxonomy_get_term_by_name($term['name'])); | |
@@ -212,6 +265,38 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Test taxonomy term create method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testTermCreateLegacy() { | |
+ $path = $this->endpoint->path; | |
+ | |
+ $vocabulary = $this->createVocabulary(); | |
+ | |
+ $term = array( | |
+ 'vid' => $vocabulary['vid'], | |
+ 'name' => $this->randomName(), | |
+ 'description' => $this->randomString(), | |
+ 'weight' => rand(0, 100), | |
+ 'parent' => NULL, | |
+ ); | |
+ | |
+ $response = $this->servicesPost($path . '/taxonomy_term', array('term' => $term)); | |
+ | |
+ // Load term by name. | |
+ $term_by_name = (array)current(taxonomy_get_term_by_name($term['name'])); | |
+ $term_intersect = array_intersect_assoc($term, $term_by_name); | |
+ | |
+ // As term_intersect will not have parent, we unset this property. | |
+ $term_data = $term; | |
+ unset($term_data['parent']); | |
+ | |
+ $this->assertEqual($term_data, $term_intersect, t('Taxonomy term created properly.'), 'TaxonomyTermResource: Create (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test taxonomy term retrieve method. | |
*/ | |
function testTermRetrieve() { | |
@@ -241,7 +326,7 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
'weight' => rand(0, 100), | |
); | |
- $this->servicesPut($path . '/taxonomy_term/' . $term['tid'], array('term' => $term_update_data)); | |
+ $this->servicesPut($path . '/taxonomy_term/' . $term['tid'], $term_update_data); | |
$term_update = (array)current(taxonomy_get_term_by_name($term_update_data['name'])); | |
@@ -250,6 +335,32 @@ class ServicesResourceTaxonomyTests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Test taxonomy term update method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testTermUpdateLegacy() { | |
+ $path = $this->endpoint->path; | |
+ | |
+ $vocabulary = $this->createVocabulary(); | |
+ $term = $this->createTerm($vocabulary['vid']); | |
+ | |
+ $term_update_data = array( | |
+ 'name' => $this->randomName(), | |
+ 'description' => $this->randomString(), | |
+ 'weight' => rand(0, 100), | |
+ ); | |
+ | |
+ $this->servicesPut($path . '/taxonomy_term/' . $term['tid'], array('term' => $term_update_data)); | |
+ | |
+ $term_update = (array)current(taxonomy_get_term_by_name($term_update_data['name'])); | |
+ | |
+ // Ensure that terms have different names but same tid. | |
+ $this->assertTrue(($term['tid'] == $term_update['tid']) && ($term['name'] != $term_update['name']), t('Taxonomy term updated properly.'), 'TaxonomyTermResource: Update (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test taxonomy term delete method. | |
*/ | |
function testTermDelete() { | |
diff --git a/tests/functional/ServicesResourceUserTests.test b/tests/functional/ServicesResourceUserTests.test | |
index a800a3f..bfc7f3a 100644 | |
--- a/tests/functional/ServicesResourceUserTests.test | |
+++ b/tests/functional/ServicesResourceUserTests.test | |
@@ -61,7 +61,7 @@ class ServicesResourceUsertests extends ServicesWebtestCase { | |
$user['pass'] = user_password(); | |
$user['status'] = 1; | |
- $response = $this->servicesPost($this->endpoint->path . '/user', array('account' => $user)); | |
+ $response = $this->servicesPost($this->endpoint->path . '/user', $user); | |
$account = $response['body']; | |
$this->assertTrue(!empty($account['uid']), t('User has been create successfully.'), 'UserResource: Create'); | |
@@ -74,11 +74,42 @@ class ServicesResourceUsertests extends ServicesWebtestCase { | |
$user['name'] = $this->randomName(); | |
$user['pass'] = user_password(); | |
$user['status'] = 1; | |
- $response = $this->servicesPost($this->endpoint->path . '/user', array('account' => $user)); | |
+ $response = $this->servicesPost($this->endpoint->path . '/user', $user); | |
$this->assertTrue(strpos($response['status'], 'E-mail address field is required') !== FALSE, t('It is not possible to create user without email.'), 'UserResource: Create'); | |
} | |
/** | |
+ * Test create method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testCreateUserLegacy() { | |
+ // Create user. | |
+ $user = array(); | |
+ $user['name'] = $this->randomName(); | |
+ $user['mail'] = $user['name'] . '@example.com'; | |
+ $user['pass'] = user_password(); | |
+ $user['status'] = 1; | |
+ | |
+ $response = $this->servicesPost($this->endpoint->path . '/user', array('account' => $user)); | |
+ $account = $response['body']; | |
+ $this->assertTrue(!empty($account['uid']), t('User has been create successfully.'), 'UserResource: Create (Legacy)'); | |
+ | |
+ // Load user. | |
+ $user_load = user_load($account['uid']); | |
+ $this->assertTrue(!empty($user_load), t('Newly created user has been loaded successfully.'), 'UserResource: Create (Legacy)'); | |
+ | |
+ // Try to create user without email. | |
+ $user = array(); | |
+ $user['name'] = $this->randomName(); | |
+ $user['pass'] = user_password(); | |
+ $user['status'] = 1; | |
+ $response = $this->servicesPost($this->endpoint->path . '/user', array('account' => $user)); | |
+ $this->assertTrue(strpos($response['status'], 'E-mail address field is required') !== FALSE, t('It is not possible to create user without email.'), 'UserResource: Create (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test register method. | |
* | |
* Register user, load user. | |
@@ -91,7 +122,7 @@ class ServicesResourceUsertests extends ServicesWebtestCase { | |
$user['pass'] = user_password(); | |
$user['status'] = 1; | |
- $response = $this->servicesPost($this->endpoint->path . '/user/register', array('account' => $user)); | |
+ $response = $this->servicesPost($this->endpoint->path . '/user/register', $user); | |
//Verify logged in users cannnot create accounts | |
$code = $response['code']; | |
@@ -100,7 +131,7 @@ class ServicesResourceUsertests extends ServicesWebtestCase { | |
//Verify logged out state can create users | |
$this->drupalLogout(); | |
- $response = $this->servicesPost($this->endpoint->path . '/user/register', array('account' => $user)); | |
+ $response = $this->servicesPost($this->endpoint->path . '/user/register', $user); | |
$account = $response['body']; | |
$this->assertTrue(!empty($account['uid']), t('User has been create successfully.'), 'UserResource: Create'); | |
@@ -112,6 +143,40 @@ class ServicesResourceUsertests extends ServicesWebtestCase { | |
} | |
/** | |
+ * Test register method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testRegisterUserLegacy() { | |
+ // Create user. | |
+ $user = array(); | |
+ $user['name'] = $this->randomName(); | |
+ $user['mail'] = $user['name'] . '@example.com'; | |
+ $user['pass'] = user_password(); | |
+ $user['status'] = 1; | |
+ | |
+ $response = $this->servicesPost($this->endpoint->path . '/user/register', array('account' => $user)); | |
+ | |
+ //Verify logged in users cannnot create accounts | |
+ $code = $response['code']; | |
+ $this->assertEqual($code, '401', t('Verify permission denied 401'), 'UserResource: Create (Legacy)'); | |
+ | |
+ //Verify logged out state can create users | |
+ $this->drupalLogout(); | |
+ | |
+ $response = $this->servicesPost($this->endpoint->path . '/user/register', array('account' => $user)); | |
+ $account = $response['body']; | |
+ | |
+ $this->assertTrue(!empty($account['uid']), t('User has been create successfully.'), 'UserResource: Create (Legacy)'); | |
+ | |
+ // Load user. | |
+ $user_load = user_load($account['uid']); | |
+ $this->assertTrue(!empty($user_load), t('Newly created user has been loaded successfully.'), 'UserResource: Create (Legacy)'); | |
+ $this->drupalLogin($this->privileged_user); | |
+ } | |
+ | |
+ /** | |
* Test retrieve method. | |
*/ | |
function testRetrieveUser() { | |
@@ -141,13 +206,37 @@ class ServicesResourceUsertests extends ServicesWebtestCase { | |
'roles' => $account->roles, | |
'mail' => $this->randomName() . '@example.com', | |
); | |
- $response = $this->servicesPut($this->endpoint->path . '/user/' . $account->uid, array('data' => $updated_account)); | |
+ $response = $this->servicesPut($this->endpoint->path . '/user/' . $account->uid, $updated_account); | |
$user_load = user_load($account->uid); | |
$this->assertEqual($updated_account['mail'], $user_load->mail, t('User details have been updated successfully'), 'UserResource: Update'); | |
} | |
/** | |
+ * Test update method (Legacy). | |
+ * | |
+ * TODO: To be removed in future version. | |
+ * @see http://drupal.org/node/1083242 | |
+ */ | |
+ function testUpdateUserLegacy() { | |
+ // Create user. | |
+ $account = $this->drupalCreateUser(); | |
+ | |
+ // Update mail of the user. Note: roles is required attribute as update | |
+ // method does drupal_execute of user_profile_form form. | |
+ $updated_account = array( | |
+ 'uid' => $account->uid, | |
+ 'name' => $account->name, | |
+ 'roles' => $account->roles, | |
+ 'mail' => $this->randomName() . '@example.com', | |
+ ); | |
+ $response = $this->servicesPut($this->endpoint->path . '/user/' . $account->uid, array('data' => $updated_account)); | |
+ | |
+ $user_load = user_load($account->uid); | |
+ $this->assertEqual($updated_account['mail'], $user_load->mail, t('User details have been updated successfully'), 'UserResource: Update (Legacy)'); | |
+ } | |
+ | |
+ /** | |
* Test delete method. | |
*/ | |
function testDeleteUser() { | |
diff --git a/tests/functional/ServicesWebTestCase.php b/tests/functional/ServicesWebTestCase.php | |
index 70f012f..b6547ea 100644 | |
--- a/tests/functional/ServicesWebTestCase.php | |
+++ b/tests/functional/ServicesWebTestCase.php | |
@@ -156,7 +156,7 @@ class ServicesWebTestCase extends DrupalWebTestCase { | |
} | |
public function saveNewEndpoint() { | |
- $edit = $this->populateEndpointFAPI() ; | |
+ $edit = $this->populateEndpointFAPI(); | |
$endpoint = new stdClass; | |
$endpoint->disabled = FALSE; /* Edit this to true to make a default endpoint disabled initially */ | |
$endpoint->api_version = 3; | |
@@ -165,11 +165,33 @@ class ServicesWebTestCase extends DrupalWebTestCase { | |
$endpoint->server = $edit['server']; | |
$endpoint->path = $edit['path']; | |
$endpoint->authentication = array( | |
- 'services_sessauth' => array(), | |
+ 'services' => 'services', | |
+ ); | |
+ $endpoint->server_settings = array( | |
+ 'rest_server' => array( | |
+ 'formatters' => array( | |
+ 'json' => TRUE, | |
+ 'bencode' => TRUE, | |
+ 'rss' => TRUE, | |
+ 'plist' => TRUE, | |
+ 'xmlplist' => TRUE, | |
+ 'php' => TRUE, | |
+ 'yaml' => TRUE, | |
+ 'jsonp' => FALSE, | |
+ 'xml' => FALSE, | |
+ ), | |
+ 'parsers' => array( | |
+ 'application/x-yaml' => TRUE, | |
+ 'application/json' => TRUE, | |
+ 'application/vnd.php.serialized' => TRUE, | |
+ 'application/plist' => TRUE, | |
+ 'application/plist+xml' => TRUE, | |
+ 'application/x-www-form-urlencoded' => TRUE, | |
+ ), | |
+ ), | |
); | |
$endpoint->resources = array( | |
- 'node' => array( | |
- 'alias' => '', | |
+ 'comment' => array( | |
'operations' => array( | |
'create' => array( | |
'enabled' => 1, | |
@@ -187,39 +209,37 @@ class ServicesWebTestCase extends DrupalWebTestCase { | |
'enabled' => 1, | |
), | |
), | |
- 'relationships' => array( | |
- 'nodefiles' => array( | |
+ 'actions' => array( | |
+ 'countAll' => array( | |
'enabled' => 1, | |
), | |
- 'comments' => array( | |
+ 'countNew' => array( | |
'enabled' => 1, | |
), | |
), | |
), | |
- 'system' => array( | |
- 'alias' => '', | |
- 'actions' => array( | |
- 'connect' => array( | |
+ 'file' => array( | |
+ 'operations' => array( | |
+ 'create' => array( | |
'enabled' => 1, | |
), | |
- 'get_variable' => array( | |
+ 'retrieve' => array( | |
'enabled' => 1, | |
), | |
- 'set_variable' => array( | |
+ 'delete' => array( | |
'enabled' => 1, | |
), | |
- 'del_variable' => array( | |
+ 'index' => array( | |
'enabled' => 1, | |
), | |
), | |
), | |
- 'taxonomy_term' => array( | |
- 'alias' => '', | |
+ 'node' => array( | |
'operations' => array( | |
- 'create' => array( | |
+ 'retrieve' => array( | |
'enabled' => 1, | |
), | |
- 'retrieve' => array( | |
+ 'create' => array( | |
'enabled' => 1, | |
), | |
'update' => array( | |
@@ -228,42 +248,41 @@ class ServicesWebTestCase extends DrupalWebTestCase { | |
'delete' => array( | |
'enabled' => 1, | |
), | |
- ), | |
- 'actions' => array( | |
- 'selectNodes' => array( | |
+ 'index' => array( | |
'enabled' => 1, | |
), | |
), | |
- ), | |
- 'taxonomy_vocabulary' => array( | |
- 'alias' => '', | |
- 'operations' => array( | |
- 'create' => array( | |
+ 'relationships' => array( | |
+ 'files' => array( | |
'enabled' => 1, | |
), | |
- 'retrieve' => array( | |
+ 'comments' => array( | |
'enabled' => 1, | |
), | |
- 'update' => array( | |
+ ), | |
+ ), | |
+ 'system' => array( | |
+ 'actions' => array( | |
+ 'connect' => array( | |
'enabled' => 1, | |
), | |
- 'delete' => array( | |
+ 'get_variable' => array( | |
'enabled' => 1, | |
), | |
- ), | |
- 'actions' => array( | |
- 'getTree' => array( | |
+ 'set_variable' => array( | |
+ 'enabled' => 1, | |
+ ), | |
+ 'del_variable' => array( | |
'enabled' => 1, | |
), | |
), | |
), | |
- 'user' => array( | |
- 'alias' => '', | |
+ 'taxonomy_term' => array( | |
'operations' => array( | |
- 'create' => array( | |
+ 'retrieve' => array( | |
'enabled' => 1, | |
), | |
- 'retrieve' => array( | |
+ 'create' => array( | |
'enabled' => 1, | |
), | |
'update' => array( | |
@@ -277,24 +296,17 @@ class ServicesWebTestCase extends DrupalWebTestCase { | |
), | |
), | |
'actions' => array( | |
- 'login' => array( | |
- 'enabled' => 1, | |
- ), | |
- 'logout' => array( | |
- 'enabled' => 1, | |
- ), | |
- 'register' => array( | |
+ 'selectNodes' => array( | |
'enabled' => 1, | |
), | |
), | |
), | |
- 'comment' => array( | |
- 'alias' => '', | |
+ 'taxonomy_vocabulary' => array( | |
'operations' => array( | |
- 'create' => array( | |
+ 'retrieve' => array( | |
'enabled' => 1, | |
), | |
- 'retrieve' => array( | |
+ 'create' => array( | |
'enabled' => 1, | |
), | |
'update' => array( | |
@@ -303,41 +315,48 @@ class ServicesWebTestCase extends DrupalWebTestCase { | |
'delete' => array( | |
'enabled' => 1, | |
), | |
- ), | |
- 'actions' => array( | |
- 'countAll' => array( | |
+ 'index' => array( | |
'enabled' => 1, | |
), | |
- 'countNew' => array( | |
+ ), | |
+ 'actions' => array( | |
+ 'getTree' => array( | |
'enabled' => 1, | |
), | |
), | |
), | |
- 'file' => array( | |
- 'alias' => '', | |
+ 'user' => array( | |
'operations' => array( | |
+ 'retrieve' => array( | |
+ 'enabled' => 1, | |
+ ), | |
'create' => array( | |
'enabled' => 1, | |
), | |
- 'retrieve' => array( | |
+ 'update' => array( | |
'enabled' => 1, | |
), | |
'delete' => array( | |
'enabled' => 1, | |
), | |
- ), | |
- ), | |
- 'echo' => array( | |
- 'alias' => '', | |
- 'operations' => array( | |
'index' => array( | |
'enabled' => 1, | |
), | |
), | |
+ 'actions' => array( | |
+ 'login' => array( | |
+ 'enabled' => 1, | |
+ ), | |
+ 'logout' => array( | |
+ 'enabled' => 1, | |
+ ), | |
+ 'register' => array( | |
+ 'enabled' => 1, | |
+ ), | |
+ ), | |
), | |
); | |
$endpoint->debug = 1; | |
- $endpoint->status = 1; | |
$endpoint->export_type = FALSE; | |
services_endpoint_save($endpoint); | |
$endpoint = services_endpoint_load($endpoint->name); | |
diff --git a/tests/unit/TestServicesModule.test b/tests/unit/TestServicesModule.test | |
index 1da24e2..a0cb67b 100644 | |
--- a/tests/unit/TestServicesModule.test | |
+++ b/tests/unit/TestServicesModule.test | |
@@ -64,8 +64,8 @@ class ServicesModuleTests extends DrupalWebTestCase { | |
$message = t('services_perm should return an array') ; | |
$this->assertTrue(gettype($resultArray)=='array', $message) ; | |
- $message = t('There should be 6 permission types') ; | |
- $this->assertEqual(count($resultArray), 6, $message) ; | |
+ $message = t('There should be 7 permission types') ; | |
+ $this->assertEqual(count($resultArray), 7, $message) ; | |
$permission = 'administer services' ; | |
$this->helperPermExists($resultArray, $permission) ; | |
@@ -111,8 +111,7 @@ class ServicesModuleTests extends DrupalWebTestCase { | |
public function testEndpointMenu() { | |
// Create the endpoint. | |
$endpointSettings = array( | |
- 'name' => 'mchnname', | |
- 'title' => $this->randomName(20), | |
+ 'name' => $this->randomName(10), | |
'path' => $this->randomName(10), | |
'server' => 'rest_server', | |
'services_use_content_permissions' => TRUE, | |
@@ -190,7 +189,6 @@ class ServicesModuleTests extends DrupalWebTestCase { | |
$string = 'New Service object should have property '; | |
$this->assertTrue(property_exists($results, 'eid'), t($string . 'eid.')); | |
$this->assertTrue(property_exists($results, 'name'), t($string . 'name.')); | |
- $this->assertTrue(property_exists($results, 'title'), t($string . 'title.')); | |
$this->assertTrue(property_exists($results, 'server'), t($string . 'server.')); | |
$this->assertTrue(property_exists($results, 'path' ), t($string . 'path.')); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment