Skip to content
Snippets Groups Projects
Commit a22471d1 authored by Andreas Gohr's avatar Andreas Gohr
Browse files

Merge pull request #1501 from splitbrain/reflection

Reflection based method export for remote plugins
parents 393c5550 14529785
No related branches found
No related tags found
No related merge requests found
......@@ -106,14 +106,32 @@ class remote_plugin_testplugin extends DokuWiki_Remote_Plugin {
function methodString() { return 'success'; }
function method2($str, $int, $bool = false) { return array($str, $int, $bool); }
function publicCall() {return true;}
}
class remote_plugin_testplugin2 extends DokuWiki_Remote_Plugin {
/**
* This is a dummy method
*
* @param string $str some more parameter description
* @param int $int
* @param bool $bool
* @param Object $unknown
* @return array
*/
public function commented($str, $int, $bool, $unknown) { return array($str, $int, $bool); }
private function privateMethod() {return true;}
protected function protectedMethod() {return true;}
public function _underscore() {return true;}
}
class remote_test extends DokuWikiTest {
var $userinfo;
/** @var RemoteAPI */
var $remote;
function setUp() {
......@@ -125,10 +143,18 @@ class remote_test extends DokuWikiTest {
parent::setUp();
// mock plugin controller to return our test plugins
$pluginManager = $this->getMock('Doku_Plugin_Controller');
$pluginManager->expects($this->any())->method('getList')->will($this->returnValue(array('testplugin')));
$pluginManager->expects($this->any())->method('load')->will($this->returnValue(new remote_plugin_testplugin()));
$pluginManager->method('getList')->willReturn(array('testplugin', 'testplugin2'));
$pluginManager->method('load')->willReturnCallback(
function($type, $plugin) {
if($plugin == 'testplugin2') {
return new remote_plugin_testplugin2();
} else {
return new remote_plugin_testplugin();
}
}
);
$plugin_controller = $pluginManager;
$conf['remote'] = 1;
......@@ -151,11 +177,28 @@ class remote_test extends DokuWikiTest {
$methods = $this->remote->getPluginMethods();
$actual = array_keys($methods);
sort($actual);
$expect = array('plugin.testplugin.method1', 'plugin.testplugin.method2', 'plugin.testplugin.methodString', 'plugin.testplugin.method2ext', 'plugin.testplugin.publicCall');
$expect = array(
'plugin.testplugin.method1',
'plugin.testplugin.method2',
'plugin.testplugin.methodString',
'plugin.testplugin.method2ext',
'plugin.testplugin.publicCall',
'plugin.testplugin2.commented'
);
sort($expect);
$this->assertEquals($expect,$actual);
}
function test_pluginDescriptors() {
$methods = $this->remote->getPluginMethods();
$this->assertEquals(array('string','int','bool','string'), $methods['plugin.testplugin2.commented']['args']);
$this->assertEquals('array', $methods['plugin.testplugin2.commented']['return']);
$this->assertEquals(0, $methods['plugin.testplugin2.commented']['public']);
$this->assertContains('This is a dummy method', $methods['plugin.testplugin2.commented']['doc']);
$this->assertContains('string $str some more parameter description', $methods['plugin.testplugin2.commented']['doc']);
}
function test_hasAccessSuccess() {
global $conf;
$conf['remoteuser'] = '';
......
......@@ -17,10 +17,82 @@ abstract class DokuWiki_Remote_Plugin extends DokuWiki_Plugin {
/**
* Get all available methods with remote access.
*
* @abstract
* By default it exports all public methods of a remote plugin. Methods beginning
* with an underscore are skipped.
*
* @return array Information about all provided methods. {@see RemoteAPI}.
*/
public abstract function _getMethods();
public function _getMethods() {
$result = array();
$reflection = new \ReflectionClass($this);
foreach($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
// skip parent methods, only methods further down are exported
$declaredin = $method->getDeclaringClass()->name;
if($declaredin == 'DokuWiki_Plugin' || $declaredin == 'DokuWiki_Remote_Plugin') continue;
$method_name = $method->name;
if(substr($method_name, 0, 1) == '_') continue;
// strip asterisks
$doc = $method->getDocComment();
$doc = preg_replace(
array('/^[ \t]*\/\*+[ \t]*/m', '/[ \t]*\*+[ \t]*/m', '/\*+\/\s*$/m','/\s*\/\s*$/m'),
array('', '', '', ''),
$doc
);
// prepare data
$data = array();
$data['name'] = $method_name;
$data['public'] = 0;
$data['doc'] = $doc;
$data['args'] = array();
// get parameter type from doc block type hint
foreach($method->getParameters() as $parameter) {
$name = $parameter->name;
$type = 'string'; // we default to string
if(preg_match('/^@param[ \t]+([\w|\[\]]+)[ \t]\$'.$name.'/m', $doc, $m)){
$type = $this->cleanTypeHint($m[1]);
}
$data['args'][] = $type;
}
// get return type from doc block type hint
if(preg_match('/^@return[ \t]+([\w|\[\]]+)/m', $doc, $m)){
$data['return'] = $this->cleanTypeHint($m[1]);
} else {
$data['return'] = 'string';
}
// add to result
$result[$method_name] = $data;
}
return $result;
}
/**
* Matches the given type hint against the valid options for the remote API
*
* @param string $hint
* @return string
*/
protected function cleanTypeHint($hint) {
$types = explode('|', $hint);
foreach($types as $t) {
if(substr($t, -2) == '[]') {
return 'array';
}
if($t == 'boolean') {
return 'bool';
}
if(in_array($t, array('array', 'string', 'int', 'double', 'bool', 'null', 'date', 'file'))) {
return $t;
}
}
return 'string';
}
/**
* @return RemoteAPI
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment