Commit 579310a4 authored by Dries's avatar Dries

- Patch #656266 by fgm, sun: hook_xmlrpc_alter() cannot alter built-in methods.

parent 96672dee
......@@ -45,7 +45,9 @@ function xmlrpc_server($callbacks) {
// We build an array of all method names by combining the built-ins
// with those defined by modules implementing the _xmlrpc hook.
// Built-in methods are overridable.
foreach (array_merge($defaults, (array) $callbacks) as $key => $callback) {
$callbacks = array_merge($defaults, (array) $callbacks);
drupal_alter('xmlrpc', $callbacks);
foreach ($callbacks as $key => $callback) {
// we could check for is_array($callback)
if (is_int($key)) {
$method = $callback[0];
......
......@@ -188,8 +188,8 @@ class XMLRPCValidator1IncTestCase extends DrupalWebTestCase {
class XMLRPCMessagesTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'XML-RPC message',
'description' => 'Test large messages.',
'name' => 'XML-RPC message and alteration',
'description' => 'Test large messages and method alterations.',
'group' => 'XML-RPC',
);
}
......@@ -211,4 +211,25 @@ class XMLRPCMessagesTestCase extends DrupalWebTestCase {
$this->assertEqual($xml_message_l, $xml_message_r, t('XML-RPC messages.messageSizedInKB of %s Kb size received', array('%s' => $size)));
}
}
/**
* Ensure that hook_xmlrpc_alter() can hide even builtin methods.
*/
protected function testAlterListMethods() {
// Ensure xmlrpc_test_xmlrpc_alter() is disabled and retrieve regular list of methods.
variable_set('xmlrpc_test_xmlrpc_alter', FALSE);
$url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php';
$methods1 = xmlrpc($url, array('system.listMethods' => array()));
// Enable the alter hook and retrieve the list of methods again.
variable_set('xmlrpc_test_xmlrpc_alter', TRUE);
$methods2 = xmlrpc($url, array('system.listMethods' => array()));
$diff = array_diff($methods1, $methods2);
$this->assertTrue(is_array($diff) && !empty($diff), t('Method list is altered by hook_xmlrpc_alter'));
$removed = reset($diff);
$this->assertEqual($removed, 'system.methodSignature', t('Hiding builting system.methodSignature with hook_xmlrpc_alter works'));
}
}
......@@ -63,6 +63,29 @@ function xmlrpc_test_xmlrpc() {
);
}
/**
* Implements hook_xmlrpc_alter().
*
* Hide (or not) the system.methodSignature() service depending on a variable.
*/
function xmlrpc_test_xmlrpc_alter(&$services) {
if (variable_get('xmlrpc_test_xmlrpc_alter', FALSE)) {
$remove = NULL;
foreach ($services as $key => $value) {
if (!is_array($value)) {
continue;
}
if ($value[0] == 'system.methodSignature') {
$remove = $key;
break;
}
}
if (isset($remove)) {
unset($services[$remove]);
}
}
}
/**
* Created a message of the desired size in KB.
*
......
......@@ -1954,37 +1954,33 @@ function hook_xmlrpc() {
}
/**
* Alter the definition of XML-RPC methods before they are called.
* Alters the definition of XML-RPC methods before they are called.
*
* This hook lets at module modify the callback definition for already
* declared XML-RPC methods, when they are being invoked by a client.
* This hook allows modules to modify the callback definition of declared
* XML-RPC methods, right before they are invoked by a client. Methods may be
* added, or existing methods may be altered.
*
* This hook is invoked by xmlrpc.php. The method definitions are
* passed in by reference. Each element of the $methods array is one
* callback definition returned by a module from hook_xmlrpc. Additional
* methods may be added, or existing items altered.
*
* Modules implementing this hook must take care of the fact that
* hook_xmlrpc allows two distinct and incompatible formats for callback
* definition, so module must be prepared to handle either format for
* each callback being altered.
* Note that hook_xmlrpc() supports two distinct and incompatible formats to
* define a callback, so care must be taken when altering other methods.
*
* @param $methods
* Associative array of method callback definitions returned from
* hook_xmlrpc.
* An asssociative array of method callback definitions, as returned from
* hook_xmlrpc() implementations.
*
* @see hook_xmlrpc()
* @see xmlrpc_server()
*/
function hook_xmlrpc_alter(&$methods) {
// Direct update for methods defined the simple way
// Directly change a simple method.
$methods['drupal.login'] = 'mymodule_login';
// Lookup update for methods defined the complex way
// Alter complex definitions.
foreach ($methods as $key => &$method) {
// Skip simple method definitions.
if (!is_int($key)) {
continue;
}
// Perform the wanted manipulation.
if ($method[0] == 'drupal.site.ping') {
$method[1] = 'mymodule_directory_ping';
}
......
......@@ -16,6 +16,4 @@
include_once DRUPAL_ROOT . '/includes/xmlrpc.inc';
include_once DRUPAL_ROOT . '/includes/xmlrpcs.inc';
$services = module_invoke_all('xmlrpc');
drupal_alter('xmlrpc', $services);
xmlrpc_server($services);
xmlrpc_server(module_invoke_all('xmlrpc'));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment