diff options
72 files changed, 1432 insertions, 1277 deletions
diff --git a/_test/core/DokuWikiTest.php b/_test/core/DokuWikiTest.php index c9a598af4..2f0df6705 100644 --- a/_test/core/DokuWikiTest.php +++ b/_test/core/DokuWikiTest.php @@ -1,4 +1,7 @@ <?php + +use dokuwiki\Extension\EventHandler; + if(!class_exists('PHPUnit_Framework_TestCase')) { /** * phpunit 5/6 compatibility @@ -133,7 +136,7 @@ abstract class DokuWikiTest extends PHPUnit_Framework_TestCase { // reset event handler global $EVENT_HANDLER; - $EVENT_HANDLER = new Doku_Event_Handler(); + $EVENT_HANDLER = new EventHandler(); // reload language $local = $conf['lang']; diff --git a/_test/mock/AuthPlugin.php b/_test/mock/AuthPlugin.php new file mode 100644 index 000000000..53edb2fe1 --- /dev/null +++ b/_test/mock/AuthPlugin.php @@ -0,0 +1,10 @@ +<?php + +namespace dokuwiki\test\mock; + +/** + * Class dokuwiki\Plugin\DokuWiki_Auth_Plugin + */ +class AuthPlugin extends \dokuwiki\Extension\AuthPlugin { + +} diff --git a/_test/mock/DokuWiki_Auth_Plugin.php b/_test/mock/DokuWiki_Auth_Plugin.php deleted file mode 100644 index 9014b020f..000000000 --- a/_test/mock/DokuWiki_Auth_Plugin.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php - -namespace dokuwiki\test\mock; - -/** - * Class DokuWiki_Auth_Plugin - */ -class DokuWiki_Auth_Plugin extends \DokuWiki_Auth_Plugin { - -} diff --git a/_test/tests/inc/PageUtilsIsHiddenPage.test.php b/_test/tests/inc/PageUtilsIsHiddenPage.test.php index a7077862e..09ab78e1b 100644 --- a/_test/tests/inc/PageUtilsIsHiddenPage.test.php +++ b/_test/tests/inc/PageUtilsIsHiddenPage.test.php @@ -41,7 +41,7 @@ class PageUtilsIsHiddenPageTest extends DokuWikiTest { $this->assertTrue(isHiddenPage('another')); } - function alwaysHide(Doku_Event &$event, $params) { + function alwaysHide(Doku_Event $event, $params) { $event->data['hidden'] = true; } @@ -53,7 +53,7 @@ class PageUtilsIsHiddenPageTest extends DokuWikiTest { $this->assertFalse(isHiddenPage('test')); } - function showBefore(Doku_Event &$event, $params) { + function showBefore(Doku_Event $event, $params) { $event->data['hidden'] = false; $event->preventDefault(); $event->stopPropagation(); @@ -75,7 +75,7 @@ class PageUtilsIsHiddenPageTest extends DokuWikiTest { $this->assertTrue(isHiddenPage('another')); } - function hideBeforeWithoutPrevent(Doku_Event &$event, $params) { + function hideBeforeWithoutPrevent(Doku_Event $event, $params) { $event->data['hidden'] = true; } @@ -87,7 +87,7 @@ class PageUtilsIsHiddenPageTest extends DokuWikiTest { $this->assertFalse(isHiddenPage('test')); } - function showAfter(Doku_Event &$event, $params) { + function showAfter(Doku_Event $event, $params) { $event->data['hidden'] = false; } diff --git a/_test/tests/inc/auth_aclcheck.test.php b/_test/tests/inc/auth_aclcheck.test.php index 4f1103ff2..2b5342e43 100644 --- a/_test/tests/inc/auth_aclcheck.test.php +++ b/_test/tests/inc/auth_aclcheck.test.php @@ -1,6 +1,6 @@ <?php -use dokuwiki\test\mock\DokuWiki_Auth_Plugin; +use dokuwiki\test\mock\AuthPlugin; class auth_acl_test extends DokuWikiTest { @@ -11,7 +11,7 @@ class auth_acl_test extends DokuWikiTest { global $AUTH_ACL; global $auth; $this->oldAuthAcl = $AUTH_ACL; - $auth = new DokuWiki_Auth_Plugin(); + $auth = new AuthPlugin(); } function tearDown() { diff --git a/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php b/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php index 21b2cfdb0..644675de4 100644 --- a/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php +++ b/_test/tests/inc/auth_aclcheck_caseinsensitive.test.php @@ -1,6 +1,8 @@ <?php -class auth_acl_caseinsensitive_auth extends DokuWiki_Auth_Plugin { +use dokuwiki\Extension\AuthPlugin; + +class auth_acl_caseinsensitive_auth extends AuthPlugin { function isCaseSensitive() { return false; } diff --git a/_test/tests/inc/auth_admincheck.test.php b/_test/tests/inc/auth_admincheck.test.php index c4aa78ce5..82ddafcff 100644 --- a/_test/tests/inc/auth_admincheck.test.php +++ b/_test/tests/inc/auth_admincheck.test.php @@ -1,8 +1,8 @@ <?php -use dokuwiki\test\mock\DokuWiki_Auth_Plugin; +use dokuwiki\test\mock\AuthPlugin; -class auth_admin_test_AuthInSensitive extends DokuWiki_Auth_Plugin { +class auth_admin_test_AuthInSensitive extends AuthPlugin { function isCaseSensitive(){ return false; } @@ -20,7 +20,7 @@ class auth_admin_test extends DokuWikiTest { function setSensitive() { global $auth; - $auth = new DokuWiki_Auth_Plugin(); + $auth = new AuthPlugin(); } function setInSensitive() { diff --git a/_test/tests/inc/auth_deleteprofile.test.php b/_test/tests/inc/auth_deleteprofile.test.php index e9f679d5c..2195ee97d 100644 --- a/_test/tests/inc/auth_deleteprofile.test.php +++ b/_test/tests/inc/auth_deleteprofile.test.php @@ -1,13 +1,14 @@ <?php use dokuwiki\Input\Input; +use dokuwiki\Extension\AuthPlugin; -class Mock_Auth_Plugin extends DokuWiki_Auth_Plugin { +class Mock_Auth_Plugin extends AuthPlugin { - public $loggedOff = false; + public $loggedOff = false; public function __construct($canDeleteUser = true) { - $this->cando['delUser'] = $canDeleteUser; + $this->cando['delUser'] = $canDeleteUser; } public function checkPass($user, $pass) { @@ -15,11 +16,11 @@ class Mock_Auth_Plugin extends DokuWiki_Auth_Plugin { } public function deleteUsers($users) { - return in_array($_SERVER['REMOTE_USER'], $users); + return in_array($_SERVER['REMOTE_USER'], $users); } public function logoff() { - $this->loggedOff = true; + $this->loggedOff = true; } } @@ -29,7 +30,7 @@ class auth_deleteprofile_test extends DokuWikiTest { /* * Tests: * - * 1. It works and the user is logged off + * 1. It works and the user is logged off * 2. Password matches when config requires it * 3,4. Auth plugin can prevent & wiki config can prevent * 5. Any of invalid security token, missing/not set 'delete' flag, missing/unchecked 'confirm_delete' diff --git a/_test/tests/inc/common_saveWikiText.test.php b/_test/tests/inc/common_saveWikiText.test.php index d363fbf0e..7ae12ca27 100644 --- a/_test/tests/inc/common_saveWikiText.test.php +++ b/_test/tests/inc/common_saveWikiText.test.php @@ -168,7 +168,7 @@ class common_saveWikiText_test extends DokuWikiTest { function test_savesequencedeleteexternalrevision() { // add an additional delay when saving files to make sure // nobody relies on the saving happening in the same second - /** @var $EVENT_HANDLER Doku_Event_Handler */ + /** @var $EVENT_HANDLER \dokuwiki\Extension\EventHandler */ global $EVENT_HANDLER; $EVENT_HANDLER->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle_write'); diff --git a/_test/tests/inc/pageutils_findnearest.test.php b/_test/tests/inc/pageutils_findnearest.test.php index 545e0980b..55db44afa 100644 --- a/_test/tests/inc/pageutils_findnearest.test.php +++ b/_test/tests/inc/pageutils_findnearest.test.php @@ -1,6 +1,6 @@ <?php -use dokuwiki\test\mock\DokuWiki_Auth_Plugin; +use dokuwiki\test\mock\AuthPlugin; class pageutils_findnearest_test extends DokuWikiTest { @@ -15,7 +15,7 @@ class pageutils_findnearest_test extends DokuWikiTest { $conf['useacl'] = 1; $this->oldAuthAcl = $AUTH_ACL; - $auth = new DokuWiki_Auth_Plugin(); + $auth = new AuthPlugin(); $AUTH_ACL = array( '* @ALL 1', diff --git a/_test/tests/inc/remote.test.php b/_test/tests/inc/remote.test.php index acc9e7cc8..a74a4d029 100644 --- a/_test/tests/inc/remote.test.php +++ b/_test/tests/inc/remote.test.php @@ -1,8 +1,10 @@ <?php +use dokuwiki\Extension\AuthPlugin; +use dokuwiki\Extension\RemotePlugin; use dokuwiki\Remote\Api; -class MockAuth extends DokuWiki_Auth_Plugin { +class MockAuth extends AuthPlugin { function isCaseSensitive() { return true; } } @@ -77,7 +79,7 @@ class RemoteAPICoreTest { } -class remote_plugin_testplugin extends DokuWiki_Remote_Plugin { +class remote_plugin_testplugin extends RemotePlugin { function _getMethods() { return array( 'method1' => array( @@ -110,7 +112,7 @@ class remote_plugin_testplugin extends DokuWiki_Remote_Plugin { function publicCall() {return true;} } -class remote_plugin_testplugin2 extends DokuWiki_Remote_Plugin { +class remote_plugin_testplugin2 extends RemotePlugin { /** * This is a dummy method * diff --git a/_test/tests/inc/remoteapicore.test.php b/_test/tests/inc/remoteapicore.test.php index 712f3924b..70b7710e8 100644 --- a/_test/tests/inc/remoteapicore.test.php +++ b/_test/tests/inc/remoteapicore.test.php @@ -2,7 +2,7 @@ use dokuwiki\Remote\Api; use dokuwiki\Remote\ApiCore; -use dokuwiki\test\mock\DokuWiki_Auth_Plugin; +use dokuwiki\test\mock\AuthPlugin; /** * Class remoteapicore_test @@ -25,7 +25,7 @@ class remoteapicore_test extends DokuWikiTest { global $auth; $this->oldAuthAcl = $AUTH_ACL; $this->userinfo = $USERINFO; - $auth = new DokuWiki_Auth_Plugin(); + $auth = new AuthPlugin(); $conf['remote'] = 1; $conf['remoteuser'] = '@user'; @@ -393,7 +393,7 @@ You can use up to five different levels of', } public function test_getPageVersions() { - /** @var $EVENT_HANDLER Doku_Event_Handler */ + /** @var $EVENT_HANDLER \dokuwiki\Extension\EventHandler */ global $EVENT_HANDLER; $EVENT_HANDLER->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle_write'); global $conf; diff --git a/bin/plugin.php b/bin/plugin.php index a31b4c13d..184317108 100755 --- a/bin/plugin.php +++ b/bin/plugin.php @@ -1,6 +1,7 @@ #!/usr/bin/php <?php +use dokuwiki\Extension\CLIPlugin; use splitbrain\phpcli\CLI; use splitbrain\phpcli\Colors; use splitbrain\phpcli\Options; @@ -85,7 +86,7 @@ class PluginCLI extends CLI { * Instantiate a CLI plugin * * @param string $name - * @return DokuWiki_CLI_Plugin|null + * @return \dokuwiki\Extension\CLIPlugin|null */ protected function loadPlugin($name) { // execute the plugin CLI @@ -12,6 +12,8 @@ use dokuwiki\Cache\Cache; use dokuwiki\ChangeLog\MediaChangeLog; use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\Extension\AuthPlugin; +use dokuwiki\Extension\Event; if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/'); require_once(DOKU_INC.'inc/init.php'); @@ -80,7 +82,7 @@ if(isset($modes[$opt['feed_mode']])) { 'opt' => &$opt, 'data' => &$data, ); - $event = new Doku_Event('FEED_MODE_UNKNOWN', $eventData); + $event = new Event('FEED_MODE_UNKNOWN', $eventData); if($event->advise_before(true)) { echo sprintf('<error>Unknown feed mode %s</error>', hsc($opt['feed_mode'])); exit; @@ -193,7 +195,7 @@ function rss_parseOptions() { function rss_buildItems(&$rss, &$data, $opt) { global $conf; global $lang; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; $eventData = array( @@ -201,7 +203,7 @@ function rss_buildItems(&$rss, &$data, $opt) { 'data' => &$data, 'opt' => &$opt, ); - $event = new Doku_Event('FEED_DATA_PROCESS', $eventData); + $event = new Event('FEED_DATA_PROCESS', $eventData); if($event->advise_before(false)) { foreach($data as $ditem) { if(!is_array($ditem)) { @@ -447,7 +449,7 @@ function rss_buildItems(&$rss, &$data, $opt) { 'ditem' => &$ditem, 'rss' => &$rss ); - $evt = new Doku_Event('FEED_ITEM_ADD', $evdata); + $evt = new Event('FEED_ITEM_ADD', $evdata); if($evt->advise_before()) { $rss->addItem($item); } diff --git a/inc/Action/Admin.php b/inc/Action/Admin.php index cc6dfd74f..1c9afd6b9 100644 --- a/inc/Action/Admin.php +++ b/inc/Action/Admin.php @@ -28,7 +28,7 @@ class Admin extends AbstractUserAction { // retrieve admin plugin name from $_REQUEST['page'] if(($page = $INPUT->str('page', '', true)) != '') { - /** @var $plugin \DokuWiki_Admin_Plugin */ + /** @var $plugin \dokuwiki\Extension\AdminPlugin */ if($plugin = plugin_getRequestAdminPlugin()) { // FIXME this method does also permission checking if(!$plugin->isAccessibleByCurrentUser()) { throw new ActionException('denied'); diff --git a/inc/Action/Logout.php b/inc/Action/Logout.php index 8b464e85d..28e8fee58 100644 --- a/inc/Action/Logout.php +++ b/inc/Action/Logout.php @@ -23,7 +23,7 @@ class Logout extends AbstractUserAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; if(!$auth->canDo('logout')) throw new ActionDisabledException(); } diff --git a/inc/Action/Plugin.php b/inc/Action/Plugin.php index c3e16bf87..43964cf39 100644 --- a/inc/Action/Plugin.php +++ b/inc/Action/Plugin.php @@ -23,7 +23,7 @@ class Plugin extends AbstractAction { * @triggers TPL_ACT_UNKNOWN */ public function tplContent() { - $evt = new \Doku_Event('TPL_ACT_UNKNOWN', $this->actionname); + $evt = new \dokuwiki\Extension\Event('TPL_ACT_UNKNOWN', $this->actionname); if($evt->advise_before()) { msg('Failed to handle action: ' . hsc($this->actionname), -1); } diff --git a/inc/Action/Profile.php b/inc/Action/Profile.php index 53d8d2ff3..654a23818 100644 --- a/inc/Action/Profile.php +++ b/inc/Action/Profile.php @@ -23,7 +23,7 @@ class Profile extends AbstractUserAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; if(!$auth->canDo('Profile')) throw new ActionDisabledException(); } diff --git a/inc/Action/ProfileDelete.php b/inc/Action/ProfileDelete.php index 995f81394..89c58edb5 100644 --- a/inc/Action/ProfileDelete.php +++ b/inc/Action/ProfileDelete.php @@ -23,7 +23,7 @@ class ProfileDelete extends AbstractUserAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; if(!$auth->canDo('delUser')) throw new ActionDisabledException(); } diff --git a/inc/Action/Register.php b/inc/Action/Register.php index 0d5415868..7d21bff4a 100644 --- a/inc/Action/Register.php +++ b/inc/Action/Register.php @@ -23,7 +23,7 @@ class Register extends AbstractAclAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; global $conf; if(isset($conf['openregister']) && !$conf['openregister']) throw new ActionDisabledException(); diff --git a/inc/Action/Resendpwd.php b/inc/Action/Resendpwd.php index 5b5e38194..f3f8d3bad 100644 --- a/inc/Action/Resendpwd.php +++ b/inc/Action/Resendpwd.php @@ -23,7 +23,7 @@ class Resendpwd extends AbstractAclAction { public function checkPreconditions() { parent::checkPreconditions(); - /** @var \DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; global $conf; if(isset($conf['resendpasswd']) && !$conf['resendpasswd']) throw new ActionDisabledException(); //legacy option @@ -59,7 +59,7 @@ class Resendpwd extends AbstractAclAction { protected function resendpwd() { global $lang; global $conf; - /* @var \DokuWiki_Auth_Plugin $auth */ + /* @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; global $INPUT; diff --git a/inc/ActionRouter.php b/inc/ActionRouter.php index edc45cfc4..dfcce3aff 100644 --- a/inc/ActionRouter.php +++ b/inc/ActionRouter.php @@ -76,7 +76,7 @@ class ActionRouter { try { // give plugins an opportunity to process the actionname - $evt = new \Doku_Event('ACTION_ACT_PREPROCESS', $actionname); + $evt = new Extension\Event('ACTION_ACT_PREPROCESS', $actionname); if ($evt->advise_before()) { $this->action = $this->loadAction($actionname); $this->checkAction($this->action); diff --git a/inc/Ajax.php b/inc/Ajax.php index f8524ea43..e8cbc84d5 100644 --- a/inc/Ajax.php +++ b/inc/Ajax.php @@ -20,7 +20,7 @@ class Ajax { if(method_exists($this, $callfn)) { $this->$callfn(); } else { - $evt = new \Doku_Event('AJAX_CALL_UNKNOWN', $call); + $evt = new Extension\Event('AJAX_CALL_UNKNOWN', $call); if($evt->advise_before()) { print "AJAX call '" . hsc($call) . "' unknown!\n"; } else { diff --git a/inc/Debug/DebugHelper.php b/inc/Debug/DebugHelper.php index f943cc038..a8126be33 100644 --- a/inc/Debug/DebugHelper.php +++ b/inc/Debug/DebugHelper.php @@ -4,6 +4,7 @@ namespace dokuwiki\Debug; use Doku_Event; +use dokuwiki\Extension\EventHandler; class DebugHelper { @@ -20,6 +21,7 @@ class DebugHelper public static function dbgDeprecatedFunction($alternative = '', $callerOffset = 1) { global $conf; + /** @var EventHandler $EVENT_HANDLER */ global $EVENT_HANDLER; if (!$conf['allowdebug'] && !$EVENT_HANDLER->hasHandlerForEvent(self::INFO_DEPRECATION_LOG_EVENT)) { // avoid any work if no one cares diff --git a/inc/Draft.php b/inc/Draft.php index 7c3109bab..f80016c8d 100644 --- a/inc/Draft.php +++ b/inc/Draft.php @@ -86,7 +86,7 @@ class Draft 'cname' => $this->cname, 'errors' => [], ]; - $event = new \Doku_Event('DRAFT_SAVE', $draft); + $event = new Extension\Event('DRAFT_SAVE', $draft); if ($event->advise_before()) { $draft['hasBeenSaved'] = io_saveFile($draft['cname'], serialize($draft)); if ($draft['hasBeenSaved']) { diff --git a/inc/Extension/ActionPlugin.php b/inc/Extension/ActionPlugin.php new file mode 100644 index 000000000..ed6d82038 --- /dev/null +++ b/inc/Extension/ActionPlugin.php @@ -0,0 +1,22 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * Action Plugin Prototype + * + * Handles action hooks within a plugin + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Christopher Smith <chris@jalakai.co.uk> + */ +abstract class ActionPlugin extends Plugin +{ + + /** + * Registers a callback function for a given event + * + * @param \Doku_Event_Handler $controller + */ + abstract public function register(\Doku_Event_Handler $controller); +} diff --git a/inc/Extension/AdminPlugin.php b/inc/Extension/AdminPlugin.php new file mode 100644 index 000000000..7900a1ec4 --- /dev/null +++ b/inc/Extension/AdminPlugin.php @@ -0,0 +1,123 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * Admin Plugin Prototype + * + * Implements an admin interface in a plugin + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Christopher Smith <chris@jalakai.co.uk> + */ +abstract class AdminPlugin extends Plugin +{ + + /** + * Return the text that is displayed at the main admin menu + * (Default localized language string 'menu' is returned, override this function for setting another name) + * + * @param string $language language code + * @return string menu string + */ + public function getMenuText($language) + { + $menutext = $this->getLang('menu'); + if (!$menutext) { + $info = $this->getInfo(); + $menutext = $info['name'] . ' ...'; + } + return $menutext; + } + + /** + * Return the path to the icon being displayed in the main admin menu. + * By default it tries to find an 'admin.svg' file in the plugin directory. + * (Override this function for setting another image) + * + * Important: you have to return a single path, monochrome SVG icon! It has to be + * under 2 Kilobytes! + * + * We recommend icons from https://materialdesignicons.com/ or to use a matching + * style. + * + * @return string full path to the icon file + */ + public function getMenuIcon() + { + $plugin = $this->getPluginName(); + return DOKU_PLUGIN . $plugin . '/admin.svg'; + } + + /** + * Determine position in list in admin window + * Lower values are sorted up + * + * @return int + */ + public function getMenuSort() + { + return 1000; + } + + /** + * Carry out required processing + */ + public function handle() + { + // some plugins might not need this + } + + /** + * Output html of the admin page + */ + abstract public function html(); + + /** + * Checks if access should be granted to this admin plugin + * + * @return bool true if the current user may access this admin plugin + */ + public function isAccessibleByCurrentUser() { + $data = []; + $data['instance'] = $this; + $data['hasAccess'] = false; + + $event = new Event('ADMINPLUGIN_ACCESS_CHECK', $data); + if($event->advise_before()) { + if ($this->forAdminOnly()) { + $data['hasAccess'] = auth_isadmin(); + } else { + $data['hasAccess'] = auth_ismanager(); + } + } + $event->advise_after(); + + return $data['hasAccess']; + } + + /** + * Return true for access only by admins (config:superuser) or false if managers are allowed as well + * + * @return bool + */ + public function forAdminOnly() + { + return true; + } + + /** + * Return array with ToC items. Items can be created with the html_mktocitem() + * + * @see html_mktocitem() + * @see tpl_toc() + * + * @return array + */ + public function getTOC() + { + return array(); + } + +} + diff --git a/inc/Extension/AuthPlugin.php b/inc/Extension/AuthPlugin.php new file mode 100644 index 000000000..2123e1320 --- /dev/null +++ b/inc/Extension/AuthPlugin.php @@ -0,0 +1,458 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * Auth Plugin Prototype + * + * allows to authenticate users in a plugin + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Chris Smith <chris@jalakai.co.uk> + * @author Jan Schumann <js@jschumann-it.com> + */ +abstract class AuthPlugin extends Plugin +{ + public $success = true; + + /** + * Possible things an auth backend module may be able to + * do. The things a backend can do need to be set to true + * in the constructor. + */ + protected $cando = array( + 'addUser' => false, // can Users be created? + 'delUser' => false, // can Users be deleted? + 'modLogin' => false, // can login names be changed? + 'modPass' => false, // can passwords be changed? + 'modName' => false, // can real names be changed? + 'modMail' => false, // can emails be changed? + 'modGroups' => false, // can groups be changed? + 'getUsers' => false, // can a (filtered) list of users be retrieved? + 'getUserCount' => false, // can the number of users be retrieved? + 'getGroups' => false, // can a list of available groups be retrieved? + 'external' => false, // does the module do external auth checking? + 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth) + ); + + /** + * Constructor. + * + * Carry out sanity checks to ensure the object is + * able to operate. Set capabilities in $this->cando + * array here + * + * For future compatibility, sub classes should always include a call + * to parent::__constructor() in their constructors! + * + * Set $this->success to false if checks fail + * + * @author Christopher Smith <chris@jalakai.co.uk> + */ + public function __construct() + { + // the base class constructor does nothing, derived class + // constructors do the real work + } + + /** + * Available Capabilities. [ DO NOT OVERRIDE ] + * + * For introspection/debugging + * + * @author Christopher Smith <chris@jalakai.co.uk> + * @return array + */ + public function getCapabilities() + { + return array_keys($this->cando); + } + + /** + * Capability check. [ DO NOT OVERRIDE ] + * + * Checks the capabilities set in the $this->cando array and + * some pseudo capabilities (shortcutting access to multiple + * ones) + * + * ususal capabilities start with lowercase letter + * shortcut capabilities start with uppercase letter + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $cap the capability to check + * @return bool + */ + public function canDo($cap) + { + switch ($cap) { + case 'Profile': + // can at least one of the user's properties be changed? + return ($this->cando['modPass'] || + $this->cando['modName'] || + $this->cando['modMail']); + break; + case 'UserMod': + // can at least anything be changed? + return ($this->cando['modPass'] || + $this->cando['modName'] || + $this->cando['modMail'] || + $this->cando['modLogin'] || + $this->cando['modGroups'] || + $this->cando['modMail']); + break; + default: + // print a helping message for developers + if (!isset($this->cando[$cap])) { + msg("Check for unknown capability '$cap' - Do you use an outdated Plugin?", -1); + } + return $this->cando[$cap]; + } + } + + /** + * Trigger the AUTH_USERDATA_CHANGE event and call the modification function. [ DO NOT OVERRIDE ] + * + * You should use this function instead of calling createUser, modifyUser or + * deleteUsers directly. The event handlers can prevent the modification, for + * example for enforcing a user name schema. + * + * @author Gabriel Birke <birke@d-scribe.de> + * @param string $type Modification type ('create', 'modify', 'delete') + * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. + * The content of this array depends on the modification type + * @return bool|null|int Result from the modification function or false if an event handler has canceled the action + */ + public function triggerUserMod($type, $params) + { + $validTypes = array( + 'create' => 'createUser', + 'modify' => 'modifyUser', + 'delete' => 'deleteUsers', + ); + if (empty($validTypes[$type])) { + return false; + } + + $result = false; + $eventdata = array('type' => $type, 'params' => $params, 'modification_result' => null); + $evt = new Event('AUTH_USER_CHANGE', $eventdata); + if ($evt->advise_before(true)) { + $result = call_user_func_array(array($this, $validTypes[$type]), $evt->data['params']); + $evt->data['modification_result'] = $result; + } + $evt->advise_after(); + unset($evt); + return $result; + } + + /** + * Log off the current user [ OPTIONAL ] + * + * Is run in addition to the ususal logoff method. Should + * only be needed when trustExternal is implemented. + * + * @see auth_logoff() + * @author Andreas Gohr <andi@splitbrain.org> + */ + public function logOff() + { + } + + /** + * Do all authentication [ OPTIONAL ] + * + * Set $this->cando['external'] = true when implemented + * + * If this function is implemented it will be used to + * authenticate a user - all other DokuWiki internals + * will not be used for authenticating, thus + * implementing the checkPass() function is not needed + * anymore. + * + * The function can be used to authenticate against third + * party cookies or Apache auth mechanisms and replaces + * the auth_login() function + * + * The function will be called with or without a set + * username. If the Username is given it was called + * from the login form and the given credentials might + * need to be checked. If no username was given it + * the function needs to check if the user is logged in + * by other means (cookie, environment). + * + * The function needs to set some globals needed by + * DokuWiki like auth_login() does. + * + * @see auth_login() + * @author Andreas Gohr <andi@splitbrain.org> + * + * @param string $user Username + * @param string $pass Cleartext Password + * @param bool $sticky Cookie should not expire + * @return bool true on successful auth + */ + public function trustExternal($user, $pass, $sticky = false) + { + /* some example: + + global $USERINFO; + global $conf; + $sticky ? $sticky = true : $sticky = false; //sanity check + + // do the checking here + + // set the globals if authed + $USERINFO['name'] = 'FIXME'; + $USERINFO['mail'] = 'FIXME'; + $USERINFO['grps'] = array('FIXME'); + $_SERVER['REMOTE_USER'] = $user; + $_SESSION[DOKU_COOKIE]['auth']['user'] = $user; + $_SESSION[DOKU_COOKIE]['auth']['pass'] = $pass; + $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; + return true; + + */ + } + + /** + * Check user+password [ MUST BE OVERRIDDEN ] + * + * Checks if the given user exists and the given + * plaintext password is correct + * + * May be ommited if trustExternal is used. + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $user the user name + * @param string $pass the clear text password + * @return bool + */ + public function checkPass($user, $pass) + { + msg("no valid authorisation system in use", -1); + return false; + } + + /** + * Return user info [ MUST BE OVERRIDDEN ] + * + * Returns info about the given user needs to contain + * at least these fields: + * + * name string full name of the user + * mail string email address of the user + * grps array list of groups the user is in + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $user the user name + * @param bool $requireGroups whether or not the returned data must include groups + * @return false|array containing user data or false + */ + public function getUserData($user, $requireGroups = true) + { + if (!$this->cando['external']) msg("no valid authorisation system in use", -1); + return false; + } + + /** + * Create a new User [implement only where required/possible] + * + * Returns false if the user already exists, null when an error + * occurred and true if everything went well. + * + * The new user HAS TO be added to the default group by this + * function! + * + * Set addUser capability when implemented + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $user + * @param string $pass + * @param string $name + * @param string $mail + * @param null|array $grps + * @return bool|null + */ + public function createUser($user, $pass, $name, $mail, $grps = null) + { + msg("authorisation method does not allow creation of new users", -1); + return null; + } + + /** + * Modify user data [implement only where required/possible] + * + * Set the mod* capabilities according to the implemented features + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param string $user nick of the user to be changed + * @param array $changes array of field/value pairs to be changed (password will be clear text) + * @return bool + */ + public function modifyUser($user, $changes) + { + msg("authorisation method does not allow modifying of user data", -1); + return false; + } + + /** + * Delete one or more users [implement only where required/possible] + * + * Set delUser capability when implemented + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param array $users + * @return int number of users deleted + */ + public function deleteUsers($users) + { + msg("authorisation method does not allow deleting of users", -1); + return 0; + } + + /** + * Return a count of the number of user which meet $filter criteria + * [should be implemented whenever retrieveUsers is implemented] + * + * Set getUserCount capability when implemented + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param array $filter array of field/pattern pairs, empty array for no filter + * @return int + */ + public function getUserCount($filter = array()) + { + msg("authorisation method does not provide user counts", -1); + return 0; + } + + /** + * Bulk retrieval of user data [implement only where required/possible] + * + * Set getUsers capability when implemented + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param int $start index of first user to be returned + * @param int $limit max number of users to be returned, 0 for unlimited + * @param array $filter array of field/pattern pairs, null for no filter + * @return array list of userinfo (refer getUserData for internal userinfo details) + */ + public function retrieveUsers($start = 0, $limit = 0, $filter = null) + { + msg("authorisation method does not support mass retrieval of user data", -1); + return array(); + } + + /** + * Define a group [implement only where required/possible] + * + * Set addGroup capability when implemented + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param string $group + * @return bool + */ + public function addGroup($group) + { + msg("authorisation method does not support independent group creation", -1); + return false; + } + + /** + * Retrieve groups [implement only where required/possible] + * + * Set getGroups capability when implemented + * + * @author Chris Smith <chris@jalakai.co.uk> + * @param int $start + * @param int $limit + * @return array + */ + public function retrieveGroups($start = 0, $limit = 0) + { + msg("authorisation method does not support group list retrieval", -1); + return array(); + } + + /** + * Return case sensitivity of the backend [OPTIONAL] + * + * When your backend is caseinsensitive (eg. you can login with USER and + * user) then you need to overwrite this method and return false + * + * @return bool + */ + public function isCaseSensitive() + { + return true; + } + + /** + * Sanitize a given username [OPTIONAL] + * + * This function is applied to any user name that is given to + * the backend and should also be applied to any user name within + * the backend before returning it somewhere. + * + * This should be used to enforce username restrictions. + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $user username + * @return string the cleaned username + */ + public function cleanUser($user) + { + return $user; + } + + /** + * Sanitize a given groupname [OPTIONAL] + * + * This function is applied to any groupname that is given to + * the backend and should also be applied to any groupname within + * the backend before returning it somewhere. + * + * This should be used to enforce groupname restrictions. + * + * Groupnames are to be passed without a leading '@' here. + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $group groupname + * @return string the cleaned groupname + */ + public function cleanGroup($group) + { + return $group; + } + + /** + * Check Session Cache validity [implement only where required/possible] + * + * DokuWiki caches user info in the user's session for the timespan defined + * in $conf['auth_security_timeout']. + * + * This makes sure slow authentication backends do not slow down DokuWiki. + * This also means that changes to the user database will not be reflected + * on currently logged in users. + * + * To accommodate for this, the user manager plugin will touch a reference + * file whenever a change is submitted. This function compares the filetime + * of this reference file with the time stored in the session. + * + * This reference file mechanism does not reflect changes done directly in + * the backend's database through other means than the user manager plugin. + * + * Fast backends might want to return always false, to force rechecks on + * each page load. Others might want to use their own checking here. If + * unsure, do not override. + * + * @param string $user - The username + * @author Andreas Gohr <andi@splitbrain.org> + * @return bool + */ + public function useSessionCache($user) + { + global $conf; + return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'] . '/sessionpurge')); + } +} diff --git a/inc/Extension/CLIPlugin.php b/inc/Extension/CLIPlugin.php new file mode 100644 index 000000000..8637ccf8c --- /dev/null +++ b/inc/Extension/CLIPlugin.php @@ -0,0 +1,13 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * CLI plugin prototype + * + * Provides DokuWiki plugin functionality on top of php-cli + */ +abstract class CLIPlugin extends \splitbrain\phpcli\CLI implements PluginInterface +{ + use PluginTrait; +} diff --git a/inc/Extension/Event.php b/inc/Extension/Event.php new file mode 100644 index 000000000..66a0976b5 --- /dev/null +++ b/inc/Extension/Event.php @@ -0,0 +1,164 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * The Action plugin event + */ +class Event +{ + + // public properties + public $name = ''; // READONLY event name, objects must register against this name to see the event + public $data = null; // READWRITE data relevant to the event, no standardised format (YET!) + public $result = null; // READWRITE the results of the event action, only relevant in "_AFTER" advise + // event handlers may modify this if they are preventing the default action + // to provide the after event handlers with event results + public $canPreventDefault = true; // READONLY if true, event handlers can prevent the events default action + + // private properties, event handlers can effect these through the provided methods + protected $_default = true; // whether or not to carry out the default action associated with the event + protected $_continue = true; // whether or not to continue propagating the event to other handlers + + /** + * event constructor + * + * @param string $name + * @param mixed $data + */ + public function __construct($name, &$data) + { + + $this->name = $name; + $this->data =& $data; + + } + + /** + * @return string + */ + public function __toString() + { + return $this->name; + } + + /** + * advise functions + * + * advise all registered handlers of this event + * + * if these methods are used by functions outside of this object, they must + * properly handle correct processing of any default action and issue an + * advise_after() signal. e.g. + * $evt = new dokuwiki\Plugin\Doku_Event(name, data); + * if ($evt->advise_before(canPreventDefault) { + * // default action code block + * } + * $evt->advise_after(); + * unset($evt); + * + * @param bool $enablePreventDefault + * @return bool results of processing the event, usually $this->_default + */ + public function advise_before($enablePreventDefault = true) + { + global $EVENT_HANDLER; + + $this->canPreventDefault = $enablePreventDefault; + $EVENT_HANDLER->process_event($this, 'BEFORE'); + + return (!$enablePreventDefault || $this->_default); + } + + public function advise_after() + { + global $EVENT_HANDLER; + + $this->_continue = true; + $EVENT_HANDLER->process_event($this, 'AFTER'); + } + + /** + * trigger + * + * - advise all registered (<event>_BEFORE) handlers that this event is about to take place + * - carry out the default action using $this->data based on $enablePrevent and + * $this->_default, all of which may have been modified by the event handlers. + * - advise all registered (<event>_AFTER) handlers that the event has taken place + * + * @param null|callable $action + * @param bool $enablePrevent + * @return mixed $event->results + * the value set by any <event>_before or <event> handlers if the default action is prevented + * or the results of the default action (as modified by <event>_after handlers) + * or NULL no action took place and no handler modified the value + */ + public function trigger($action = null, $enablePrevent = true) + { + + if (!is_callable($action)) { + $enablePrevent = false; + if (!is_null($action)) { + trigger_error( + 'The default action of ' . $this . + ' is not null but also not callable. Maybe the method is not public?', + E_USER_WARNING + ); + } + } + + if ($this->advise_before($enablePrevent) && is_callable($action)) { + if (is_array($action)) { + list($obj, $method) = $action; + $this->result = $obj->$method($this->data); + } else { + $this->result = $action($this->data); + } + } + + $this->advise_after(); + + return $this->result; + } + + /** + * stopPropagation + * + * stop any further processing of the event by event handlers + * this function does not prevent the default action taking place + */ + public function stopPropagation() + { + $this->_continue = false; + } + + /** + * may the event propagate to the next handler? + * + * @return bool + */ + public function mayPropagate() + { + return $this->_continue; + } + + /** + * preventDefault + * + * prevent the default action taking place + */ + public function preventDefault() + { + $this->_default = false; + } + + /** + * should the default action be executed? + * + * @return bool + */ + public function mayRunDefault() + { + return $this->_default; + } +} diff --git a/inc/Extension/EventHandler.php b/inc/Extension/EventHandler.php new file mode 100644 index 000000000..f6dd26be2 --- /dev/null +++ b/inc/Extension/EventHandler.php @@ -0,0 +1,107 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * Controls the registration and execution of all events, + */ +class EventHandler +{ + + // public properties: none + + // private properties + protected $_hooks = array(); // array of events and their registered handlers + + /** + * event_handler + * + * constructor, loads all action plugins and calls their register() method giving them + * an opportunity to register any hooks they require + */ + public function __construct() + { + + // load action plugins + /** @var ActionPlugin $plugin */ + $plugin = null; + $pluginlist = plugin_list('action'); + + foreach ($pluginlist as $plugin_name) { + $plugin = plugin_load('action', $plugin_name); + + if ($plugin !== null) $plugin->register($this); + } + } + + /** + * register_hook + * + * register a hook for an event + * + * @param string $event string name used by the event, (incl '_before' or '_after' for triggers) + * @param string $advise + * @param object $obj object in whose scope method is to be executed, + * if NULL, method is assumed to be a globally available function + * @param string $method event handler function + * @param mixed $param data passed to the event handler + * @param int $seq sequence number for ordering hook execution (ascending) + */ + public function register_hook($event, $advise, $obj, $method, $param = null, $seq = 0) + { + $seq = (int)$seq; + $doSort = !isset($this->_hooks[$event . '_' . $advise][$seq]); + $this->_hooks[$event . '_' . $advise][$seq][] = array($obj, $method, $param); + + if ($doSort) { + ksort($this->_hooks[$event . '_' . $advise]); + } + } + + /** + * process the before/after event + * + * @param Event $event + * @param string $advise BEFORE or AFTER + */ + public function process_event($event, $advise = '') + { + + $evt_name = $event->name . ($advise ? '_' . $advise : '_BEFORE'); + + if (!empty($this->_hooks[$evt_name])) { + foreach ($this->_hooks[$evt_name] as $sequenced_hooks) { + foreach ($sequenced_hooks as $hook) { + list($obj, $method, $param) = $hook; + + if (is_null($obj)) { + $method($event, $param); + } else { + $obj->$method($event, $param); + } + + if (!$event->mayPropagate()) return; + } + } + } + } + + /** + * Check if an event has any registered handlers + * + * When $advise is empty, both BEFORE and AFTER events will be considered, + * otherwise only the given advisory is checked + * + * @param string $name Name of the event + * @param string $advise BEFORE, AFTER or empty + * @return bool + */ + public function hasHandlerForEvent($name, $advise = '') + { + if ($advise) { + return isset($this->_hooks[$name . '_' . $advise]); + } else { + return isset($this->_hooks[$name . '_BEFORE']) || isset($this->_hooks[$name . '_AFTER']); + } + } +} diff --git a/inc/Extension/Plugin.php b/inc/Extension/Plugin.php new file mode 100644 index 000000000..03637fe4d --- /dev/null +++ b/inc/Extension/Plugin.php @@ -0,0 +1,13 @@ +<?php + +namespace dokuwiki\Extension; + +/** + * DokuWiki Base Plugin + * + * Most plugin types inherit from this class + */ +abstract class Plugin implements PluginInterface +{ + use PluginTrait; +} diff --git a/inc/PluginInterface.php b/inc/Extension/PluginInterface.php index 608989096..f2dbe8626 100644 --- a/inc/PluginInterface.php +++ b/inc/Extension/PluginInterface.php @@ -1,14 +1,18 @@ <?php + +namespace dokuwiki\Extension; + /** * DokuWiki Plugin Interface * * Defines the public contract all DokuWiki plugins will adhere to. The actual code - * to do so is defined in DokuWiki_PluginTrait + * to do so is defined in dokuwiki\Extension\PluginTrait * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Christopher Smith <chris@jalakai.co.uk> */ -interface DokuWiki_PluginInterface { +interface PluginInterface +{ /** * General Info * @@ -107,7 +111,7 @@ interface DokuWiki_PluginInterface { * * @param string $name name of plugin to load * @param bool $msg if a message should be displayed in case the plugin is not available - * @return DokuWiki_PluginInterface|null helper plugin object + * @return PluginInterface|null helper plugin object */ public function loadHelper($name, $msg = true); diff --git a/inc/PluginTrait.php b/inc/Extension/PluginTrait.php index 57b735e85..f1db0f598 100644 --- a/inc/PluginTrait.php +++ b/inc/Extension/PluginTrait.php @@ -1,10 +1,12 @@ <?php +namespace dokuwiki\Extension; + /** - * Do not inherit directly from this class, instead inherit from the specialized - * ones in lib/plugin + * Provides standard DokuWiki plugin behaviour */ -trait DokuWiki_PluginTrait { +trait PluginTrait +{ protected $localised = false; // set to true by setupLocale() after loading language dependent strings protected $lang = array(); // array to hold language dependent strings, best accessed via ->getLang() @@ -12,12 +14,13 @@ trait DokuWiki_PluginTrait { protected $conf = array(); // array to hold plugin settings, best accessed via ->getConf() /** - * @see DokuWiki_PluginInterface::getInfo() + * @see PluginInterface::getInfo() */ - public function getInfo() { + public function getInfo() + { $parts = explode('_', get_class($this)); $info = DOKU_PLUGIN . '/' . $parts[2] . '/plugin.info.txt'; - if(file_exists($info)) return confToHash($info); + if (file_exists($info)) return confToHash($info); msg( 'getInfo() not implemented in ' . get_class($this) . ' and ' . $info . ' not found.<br />' . @@ -31,43 +34,48 @@ trait DokuWiki_PluginTrait { } /** - * @see DokuWiki_PluginInterface::isSingleton() + * @see PluginInterface::isSingleton() */ - public function isSingleton() { + public function isSingleton() + { return true; } /** - * @see DokuWiki_PluginInterface::loadHelper() + * @see PluginInterface::loadHelper() */ - public function loadHelper($name, $msg = true) { + public function loadHelper($name, $msg = true) + { $obj = plugin_load('helper', $name); - if(is_null($obj) && $msg) msg("Helper plugin $name is not available or invalid.", -1); + if (is_null($obj) && $msg) msg("Helper plugin $name is not available or invalid.", -1); return $obj; } // region introspection methods /** - * @see DokuWiki_PluginInterface::getPluginType() + * @see PluginInterface::getPluginType() */ - public function getPluginType() { + public function getPluginType() + { list($t) = explode('_', get_class($this), 2); return $t; } /** - * @see DokuWiki_PluginInterface::getPluginName() + * @see PluginInterface::getPluginName() */ - public function getPluginName() { + public function getPluginName() + { list(/* $t */, /* $p */, $n) = explode('_', get_class($this), 4); return $n; } /** - * @see DokuWiki_PluginInterface::getPluginComponent() + * @see PluginInterface::getPluginComponent() */ - public function getPluginComponent() { + public function getPluginComponent() + { list(/* $t */, /* $p */, /* $n */, $c) = explode('_', get_class($this), 4); return (isset($c) ? $c : ''); } @@ -76,31 +84,34 @@ trait DokuWiki_PluginTrait { // region localization methods /** - * @see DokuWiki_PluginInterface::getLang() + * @see PluginInterface::getLang() */ - public function getLang($id) { - if(!$this->localised) $this->setupLocale(); + public function getLang($id) + { + if (!$this->localised) $this->setupLocale(); return (isset($this->lang[$id]) ? $this->lang[$id] : ''); } /** - * @see DokuWiki_PluginInterface::locale_xhtml() + * @see PluginInterface::locale_xhtml() */ - public function locale_xhtml($id) { + public function locale_xhtml($id) + { return p_cached_output($this->localFN($id)); } /** - * @see DokuWiki_PluginInterface::localFN() + * @see PluginInterface::localFN() */ - public function localFN($id, $ext = 'txt') { + public function localFN($id, $ext = 'txt') + { global $conf; $plugin = $this->getPluginName(); $file = DOKU_CONF . 'plugin_lang/' . $plugin . '/' . $conf['lang'] . '/' . $id . '.' . $ext; - if(!file_exists($file)) { + if (!file_exists($file)) { $file = DOKU_PLUGIN . $plugin . '/lang/' . $conf['lang'] . '/' . $id . '.' . $ext; - if(!file_exists($file)) { + if (!file_exists($file)) { //fall back to english $file = DOKU_PLUGIN . $plugin . '/lang/en/' . $id . '.' . $ext; } @@ -109,10 +120,11 @@ trait DokuWiki_PluginTrait { } /** - * @see DokuWiki_PluginInterface::setupLocale() + * @see PluginInterface::setupLocale() */ - public function setupLocale() { - if($this->localised) return; + public function setupLocale() + { + if ($this->localised) return; global $conf, $config_cascade; // definitely don't invoke "global $lang" $path = DOKU_PLUGIN . $this->getPluginName() . '/lang/'; @@ -121,16 +133,16 @@ trait DokuWiki_PluginTrait { // don't include once, in case several plugin components require the same language file @include($path . 'en/lang.php'); - foreach($config_cascade['lang']['plugin'] as $config_file) { - if(file_exists($config_file . $this->getPluginName() . '/en/lang.php')) { + foreach ($config_cascade['lang']['plugin'] as $config_file) { + if (file_exists($config_file . $this->getPluginName() . '/en/lang.php')) { include($config_file . $this->getPluginName() . '/en/lang.php'); } } - if($conf['lang'] != 'en') { + if ($conf['lang'] != 'en') { @include($path . $conf['lang'] . '/lang.php'); - foreach($config_cascade['lang']['plugin'] as $config_file) { - if(file_exists($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php')) { + foreach ($config_cascade['lang']['plugin'] as $config_file) { + if (file_exists($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php')) { include($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php'); } } @@ -144,15 +156,16 @@ trait DokuWiki_PluginTrait { // region configuration methods /** - * @see DokuWiki_PluginInterface::getConf() + * @see PluginInterface::getConf() */ - public function getConf($setting, $notset = false) { + public function getConf($setting, $notset = false) + { - if(!$this->configloaded) { + if (!$this->configloaded) { $this->loadConfig(); } - if(isset($this->conf[$setting])) { + if (isset($this->conf[$setting])) { return $this->conf[$setting]; } else { return $notset; @@ -160,16 +173,17 @@ trait DokuWiki_PluginTrait { } /** - * @see DokuWiki_PluginInterface::loadConfig() + * @see PluginInterface::loadConfig() */ - public function loadConfig() { + public function loadConfig() + { global $conf; $defaults = $this->readDefaultSettings(); $plugin = $this->getPluginName(); - foreach($defaults as $key => $value) { - if(isset($conf['plugin'][$plugin][$key])) continue; + foreach ($defaults as $key => $value) { + if (isset($conf['plugin'][$plugin][$key])) continue; $conf['plugin'][$plugin][$key] = $value; } @@ -183,12 +197,13 @@ trait DokuWiki_PluginTrait { * * @return array setting => value */ - protected function readDefaultSettings() { + protected function readDefaultSettings() + { $path = DOKU_PLUGIN . $this->getPluginName() . '/conf/'; $conf = array(); - if(file_exists($path . 'default.php')) { + if (file_exists($path . 'default.php')) { include($path . 'default.php'); } @@ -199,38 +214,41 @@ trait DokuWiki_PluginTrait { // region output methods /** - * @see DokuWiki_PluginInterface::email() + * @see PluginInterface::email() */ - public function email($email, $name = '', $class = '', $more = '') { - if(!$email) return $name; + public function email($email, $name = '', $class = '', $more = '') + { + if (!$email) return $name; $email = obfuscate($email); - if(!$name) $name = $email; + if (!$name) $name = $email; $class = "class='" . ($class ? $class : 'mail') . "'"; return "<a href='mailto:$email' $class title='$email' $more>$name</a>"; } /** - * @see DokuWiki_PluginInterface::external_link() + * @see PluginInterface::external_link() */ - public function external_link($link, $title = '', $class = '', $target = '', $more = '') { + public function external_link($link, $title = '', $class = '', $target = '', $more = '') + { global $conf; $link = htmlentities($link); - if(!$title) $title = $link; - if(!$target) $target = $conf['target']['extern']; - if($conf['relnofollow']) $more .= ' rel="nofollow"'; + if (!$title) $title = $link; + if (!$target) $target = $conf['target']['extern']; + if ($conf['relnofollow']) $more .= ' rel="nofollow"'; - if($class) $class = " class='$class'"; - if($target) $target = " target='$target'"; - if($more) $more = " " . trim($more); + if ($class) $class = " class='$class'"; + if ($target) $target = " target='$target'"; + if ($more) $more = " " . trim($more); return "<a href='$link'$class$target$more>$title</a>"; } /** - * @see DokuWiki_PluginInterface::render_text() + * @see PluginInterface::render_text() */ - public function render_text($text, $format = 'xhtml') { + public function render_text($text, $format = 'xhtml') + { return p_render($format, p_get_instructions($text), $info); } diff --git a/inc/Extension/RemotePlugin.php b/inc/Extension/RemotePlugin.php new file mode 100644 index 000000000..612db3349 --- /dev/null +++ b/inc/Extension/RemotePlugin.php @@ -0,0 +1,118 @@ +<?php + +namespace dokuwiki\Extension; + +use dokuwiki\Remote\Api; +use ReflectionException; +use ReflectionMethod; + +/** + * Remote Plugin prototype + * + * Add functionality to the remote API in a plugin + */ +abstract class RemotePlugin extends Plugin +{ + + private $api; + + /** + * Constructor + */ + public function __construct() + { + $this->api = new Api(); + } + + /** + * Get all available methods with remote access. + * + * 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 dokuwiki\Remote\RemoteAPI}. + * @throws ReflectionException + */ + 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\Extension\Plugin' || $declaredin == 'dokuwiki\Extension\RemotePlugin') 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 Api + */ + protected function getApi() + { + return $this->api; + } + +} diff --git a/inc/Extension/SyntaxPlugin.php b/inc/Extension/SyntaxPlugin.php new file mode 100644 index 000000000..e5dda9bdc --- /dev/null +++ b/inc/Extension/SyntaxPlugin.php @@ -0,0 +1,132 @@ +<?php + +namespace dokuwiki\Extension; + +use \Doku_Handler; +use \Doku_Renderer; + +/** + * Syntax Plugin Prototype + * + * All DokuWiki plugins to extend the parser/rendering mechanism + * need to inherit from this class + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ +abstract class SyntaxPlugin extends \dokuwiki\Parsing\ParserMode\Plugin +{ + use PluginTrait; + + protected $allowedModesSetup = false; + + /** + * Syntax Type + * + * Needs to return one of the mode types defined in $PARSER_MODES in Parser.php + * + * @return string + */ + abstract public function getType(); + + /** + * Allowed Mode Types + * + * Defines the mode types for other dokuwiki markup that maybe nested within the + * plugin's own markup. Needs to return an array of one or more of the mode types + * defined in $PARSER_MODES in Parser.php + * + * @return array + */ + public function getAllowedTypes() + { + return array(); + } + + /** + * Paragraph Type + * + * Defines how this syntax is handled regarding paragraphs. This is important + * for correct XHTML nesting. Should return one of the following: + * + * 'normal' - The plugin can be used inside paragraphs + * 'block' - Open paragraphs need to be closed before plugin output + * 'stack' - Special case. Plugin wraps other paragraphs. + * + * @see Doku_Handler_Block + * + * @return string + */ + public function getPType() + { + return 'normal'; + } + + /** + * Handler to prepare matched data for the rendering process + * + * This function can only pass data to render() via its return value - render() + * may be not be run during the object's current life. + * + * Usually you should only need the $match param. + * + * @param string $match The text matched by the patterns + * @param int $state The lexer state for the match + * @param int $pos The character position of the matched text + * @param Doku_Handler $handler The Doku_Handler object + * @return bool|array Return an array with all data you want to use in render, false don't add an instruction + */ + abstract public function handle($match, $state, $pos, Doku_Handler $handler); + + /** + * Handles the actual output creation. + * + * The function must not assume any other of the classes methods have been run + * during the object's current life. The only reliable data it receives are its + * parameters. + * + * The function should always check for the given output format and return false + * when a format isn't supported. + * + * $renderer contains a reference to the renderer object which is + * currently handling the rendering. You need to use it for writing + * the output. How this is done depends on the renderer used (specified + * by $format + * + * The contents of the $data array depends on what the handler() function above + * created + * + * @param string $format output format being rendered + * @param Doku_Renderer $renderer the current renderer object + * @param array $data data created by handler() + * @return boolean rendered correctly? (however, returned value is not used at the moment) + */ + abstract public function render($format, Doku_Renderer $renderer, $data); + + /** + * There should be no need to override this function + * + * @param string $mode + * @return bool + */ + public function accepts($mode) + { + + if (!$this->allowedModesSetup) { + global $PARSER_MODES; + + $allowedModeTypes = $this->getAllowedTypes(); + foreach ($allowedModeTypes as $mt) { + $this->allowedModes = array_merge($this->allowedModes, $PARSER_MODES[$mt]); + } + + $idx = array_search(substr(get_class($this), 7), (array)$this->allowedModes); + if ($idx !== false) { + unset($this->allowedModes[$idx]); + } + $this->allowedModesSetup = true; + } + + return parent::accepts($mode); + } +} diff --git a/inc/HTTP/HTTPClient.php b/inc/HTTP/HTTPClient.php index c916d77f0..90c22b7f1 100644 --- a/inc/HTTP/HTTPClient.php +++ b/inc/HTTP/HTTPClient.php @@ -165,7 +165,6 @@ class HTTPClient { $this->start = $this->time(); $this->error = ''; $this->status = 0; - $this->status = 0; $this->resp_body = ''; $this->resp_headers = array(); diff --git a/inc/Mailer.class.php b/inc/Mailer.class.php index 36a37c558..048890106 100644 --- a/inc/Mailer.class.php +++ b/inc/Mailer.class.php @@ -9,6 +9,8 @@ * @author Andreas Gohr <andi@splitbrain.org> */ +use dokuwiki\Extension\Event; + // end of line for mail lines - RFC822 says CRLF but postfix (and other MTAs?) // think different if(!defined('MAILHEADER_EOL')) define('MAILHEADER_EOL', "\n"); @@ -682,7 +684,7 @@ class Mailer { ); // do our thing if BEFORE hook approves - $evt = new Doku_Event('MAIL_MESSAGE_SEND', $data); + $evt = new Event('MAIL_MESSAGE_SEND', $data); if($evt->advise_before(true)) { // clean up before using the headers $this->cleanHeaders(); diff --git a/inc/Plugin.php b/inc/Plugin.php deleted file mode 100644 index 9cd0ae805..000000000 --- a/inc/Plugin.php +++ /dev/null @@ -1,11 +0,0 @@ -<?php - -/** - * DokuWiki Plugin - * - * Most of DokuWiki's plugin types simply inherit from this. All it does is - * add the DokuWiki_PluginTrait to the class. - */ -class DokuWiki_Plugin implements DokuWiki_PluginInterface { - use DokuWiki_PluginTrait; -} diff --git a/inc/Remote/Api.php b/inc/Remote/Api.php index bcb5f028c..6127c07d7 100644 --- a/inc/Remote/Api.php +++ b/inc/Remote/Api.php @@ -2,8 +2,7 @@ namespace dokuwiki\Remote; -use DokuWiki_Remote_Plugin; -use dokuwiki\Input\Input; +use dokuwiki\Extension\RemotePlugin; /** * This class provides information about remote access to the wiki. @@ -290,10 +289,10 @@ class Api $plugins = plugin_list('remote'); foreach ($plugins as $pluginName) { - /** @var DokuWiki_Remote_Plugin $plugin */ + /** @var RemotePlugin $plugin */ $plugin = plugin_load('remote', $pluginName); - if (!is_subclass_of($plugin, 'DokuWiki_Remote_Plugin')) { - throw new RemoteException("Plugin $pluginName does not implement DokuWiki_Remote_Plugin"); + if (!is_subclass_of($plugin, 'dokuwiki\Extension\RemotePlugin')) { + throw new RemoteException("Plugin $pluginName does not implement dokuwiki\Plugin\DokuWiki_Remote_Plugin"); } try { diff --git a/inc/Remote/ApiCore.php b/inc/Remote/ApiCore.php index cea0a9dc7..238691ea8 100644 --- a/inc/Remote/ApiCore.php +++ b/inc/Remote/ApiCore.php @@ -5,7 +5,7 @@ namespace dokuwiki\Remote; use Doku_Renderer_xhtml; use dokuwiki\ChangeLog\MediaChangeLog; use dokuwiki\ChangeLog\PageChangeLog; -use DokuWiki_Auth_Plugin; +use dokuwiki\Extension\AuthPlugin; define('DOKU_API_VERSION', 10); @@ -594,7 +594,7 @@ class ApiCore if (!auth_isadmin()) { throw new AccessDeniedException('Only admins are allowed to delete users', 114); } - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Plugin\\dokuwiki\Extension\AuthPlugin $auth */ global $auth; return (bool)$auth->triggerUserMod('delete', array($usernames)); } @@ -671,7 +671,7 @@ class ApiCore */ public function aclCheck($id, $user = null, $groups = null) { - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Plugin\\dokuwiki\Extension\AuthPlugin $auth */ global $auth; $id = $this->resolvePageId($id); @@ -965,7 +965,7 @@ class ApiCore public function login($user, $pass) { global $conf; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Plugin\\dokuwiki\Extension\AuthPlugin $auth */ global $auth; if (!$conf['useacl']) return 0; diff --git a/inc/Sitemap/Mapper.php b/inc/Sitemap/Mapper.php index 7aef61a87..2f0567f05 100644 --- a/inc/Sitemap/Mapper.php +++ b/inc/Sitemap/Mapper.php @@ -64,7 +64,7 @@ class Mapper { } $eventData = array('items' => &$items, 'sitemap' => &$sitemap); - $event = new \Doku_Event('SITEMAP_GENERATE', $eventData); + $event = new \dokuwiki\Extension\Event('SITEMAP_GENERATE', $eventData); if ($event->advise_before(true)) { //save the new sitemap $event->result = io_saveFile($sitemap, Mapper::getXML($items)); @@ -147,7 +147,7 @@ class Mapper { $data = array('ping_urls' => $ping_urls, 'encoded_sitemap_url' => $encoded_sitemap_url ); - $event = new \Doku_Event('SITEMAP_PING', $data); + $event = new \dokuwiki\Extension\Event('SITEMAP_PING', $data); if ($event->advise_before(true)) { foreach ($data['ping_urls'] as $name => $url) { dbglog("Sitemapper::PingSearchEngines(): pinging $name"); diff --git a/inc/TaskRunner.php b/inc/TaskRunner.php index 0645dd345..997e825b7 100644 --- a/inc/TaskRunner.php +++ b/inc/TaskRunner.php @@ -2,7 +2,7 @@ namespace dokuwiki; -use Doku_Event; +use dokuwiki\Extension\Event; use dokuwiki\Sitemap\Mapper; use Subscription; @@ -44,7 +44,7 @@ class TaskRunner // run one of the jobs $tmp = []; // No event data - $evt = new Doku_Event('INDEXER_TASKS_RUN', $tmp); + $evt = new Event('INDEXER_TASKS_RUN', $tmp); if ($evt->advise_before()) { $this->runIndexer() or $this->runSitemapper() or diff --git a/inc/Ui/Admin.php b/inc/Ui/Admin.php index e0443f1fb..fe319d414 100644 --- a/inc/Ui/Admin.php +++ b/inc/Ui/Admin.php @@ -119,8 +119,8 @@ class Admin extends Ui { $menu = ['admin' => [], 'manager' => [], 'other' => []]; foreach($pluginlist as $p) { - /** @var \DokuWiki_Admin_Plugin $obj */ - if (($obj = plugin_load('admin', $p)) === null) continue; + /** @var \dokuwiki\Extension\AdminPlugin $obj */ + if(($obj = plugin_load('admin', $p)) === null) continue; // check permissions if (!$obj->isAccessibleByCurrentUser()) continue; diff --git a/inc/auth.php b/inc/auth.php index 84805ce2e..0cd03469d 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -11,6 +11,8 @@ // some ACL level defines use dokuwiki\PassHash; +use dokuwiki\Extension\AuthPlugin; +use dokuwiki\Extension\Event; define('AUTH_NONE', 0); define('AUTH_READ', 1); @@ -34,7 +36,7 @@ define('AUTH_ADMIN', 255); */ function auth_setup() { global $conf; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -211,7 +213,7 @@ function auth_login($user, $pass, $sticky = false, $silent = false) { global $USERINFO; global $conf; global $lang; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -407,7 +409,7 @@ function auth_decrypt($ciphertext, $secret) { function auth_logoff($keepbc = false) { global $conf; global $USERINFO; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -451,7 +453,7 @@ function auth_logoff($keepbc = false) { function auth_ismanager($user = null, $groups = null, $adminonly = false) { global $conf; global $USERINFO; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -508,7 +510,7 @@ function auth_isadmin($user = null, $groups = null) { * @return bool true for membership acknowledged */ function auth_isMember($memberlist, $user, array $groups) { - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; if(!$auth) return false; @@ -601,7 +603,7 @@ function auth_aclcheck_cb($data) { global $conf; global $AUTH_ACL; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; // if no ACL is used always return upload rights @@ -778,7 +780,7 @@ function auth_pwgen($foruser = '') { 'foruser' => $foruser ); - $evt = new Doku_Event('AUTH_PASSWORD_GENERATE', $data); + $evt = new Event('AUTH_PASSWORD_GENERATE', $data); if($evt->advise_before(true)) { $c = 'bcdfghjklmnprstvwz'; //consonants except hard to speak ones $v = 'aeiou'; //vowels @@ -810,7 +812,7 @@ function auth_pwgen($foruser = '') { */ function auth_sendPassword($user, $password) { global $lang; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; if(!$auth) return false; @@ -845,7 +847,7 @@ function auth_sendPassword($user, $password) { function register() { global $lang; global $conf; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; global $INPUT; @@ -914,7 +916,7 @@ function register() { function updateprofile() { global $conf; global $lang; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -1003,7 +1005,7 @@ function updateprofile() { function auth_deleteprofile(){ global $conf; global $lang; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -1057,7 +1059,7 @@ function auth_deleteprofile(){ function act_resendpwd() { global $lang; global $conf; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; /* @var Input $INPUT */ global $INPUT; @@ -1225,7 +1227,7 @@ function auth_verifyPassword($clear, $crypt) { */ function auth_setCookie($user, $pass, $sticky) { global $conf; - /* @var DokuWiki_Auth_Plugin $auth */ + /* @var AuthPlugin $auth */ global $auth; global $USERINFO; diff --git a/inc/common.php b/inc/common.php index 42e82b1a5..a2ef313f9 100644 --- a/inc/common.php +++ b/inc/common.php @@ -9,6 +9,8 @@ use dokuwiki\Cache\CacheInstructions; use dokuwiki\Cache\CacheRenderer; use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\Extension\AuthPlugin; +use dokuwiki\Extension\Event; /** * These constants are used with the recents function @@ -1082,7 +1084,7 @@ function pageTemplate($id) { 'doreplace' => true // should wildcard replacements be done on the text? ); - $evt = new Doku_Event('COMMON_PAGETPL_LOAD', $data); + $evt = new Event('COMMON_PAGETPL_LOAD', $data); if($evt->advise_before(true)) { // the before event might have loaded the content already if(empty($data['tpl'])) { @@ -1359,7 +1361,7 @@ function saveWikiText($id, $text, $summary, $minor = false) { $svdta['changeType'] = DOKU_CHANGE_TYPE_MINOR_EDIT; } - $event = new Doku_Event('COMMON_WIKIPAGE_SAVE', $svdta); + $event = new Event('COMMON_WIKIPAGE_SAVE', $svdta); if(!$event->advise_before()) return; // if the content has not been changed, no save happens (plugins may override this) @@ -1776,7 +1778,7 @@ function editorinfo($username, $textonly = false) { */ function userlink($username = null, $textonly = false) { global $conf, $INFO; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var AuthPlugin $auth */ global $auth; /** @var Input $INPUT */ global $INPUT; @@ -1808,7 +1810,7 @@ function userlink($username = null, $textonly = false) { } } - $evt = new Doku_Event('COMMON_USER_LINK', $data); + $evt = new Event('COMMON_USER_LINK', $data); if($evt->advise_before(true)) { if(empty($data['name'])) { if($auth) $info = $auth->getUserData($username); diff --git a/inc/confutils.php b/inc/confutils.php index 60c78c928..de4d418b4 100644 --- a/inc/confutils.php +++ b/inc/confutils.php @@ -11,6 +11,9 @@ * (scheme.conf & stopwords.conf), e.g. * !gopher */ + +use dokuwiki\Extension\AuthPlugin; +use dokuwiki\Extension\Event; const DOKU_CONF_NEGATION = '!'; /** @@ -145,7 +148,7 @@ function getCdnUrls() { 'versions' => $versions, 'src' => &$src ); - $event = new Doku_Event('CONFUTIL_CDN_SELECT', $data); + $event = new Event('CONFUTIL_CDN_SELECT', $data); if($event->advise_before()) { if(!$conf['jquerycdn']) { $jqmod = md5(join('-', $versions)); @@ -350,7 +353,7 @@ function actionOK($action){ static $disabled = null; if(is_null($disabled) || defined('SIMPLE_TEST')){ global $conf; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var AuthPlugin $auth */ global $auth; // prepare disabled actions array and handle legacy options diff --git a/inc/events.php b/inc/events.php index 1b660f541..56d0dfad3 100644 --- a/inc/events.php +++ b/inc/events.php @@ -1,260 +1,4 @@ <?php -/** - * DokuWiki Events - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Christopher Smith <chris@jalakai.co.uk> - */ - -/** - * The event - */ -class Doku_Event { - - // public properties - public $name = ''; // READONLY event name, objects must register against this name to see the event - public $data = null; // READWRITE data relevant to the event, no standardised format (YET!) - public $result = null; // READWRITE the results of the event action, only relevant in "_AFTER" advise - // event handlers may modify this if they are preventing the default action - // to provide the after event handlers with event results - public $canPreventDefault = true; // READONLY if true, event handlers can prevent the events default action - - // private properties, event handlers can effect these through the provided methods - protected $_default = true; // whether or not to carry out the default action associated with the event - protected $_continue = true; // whether or not to continue propagating the event to other handlers - - /** - * event constructor - * - * @param string $name - * @param mixed $data - */ - public function __construct($name, &$data) { - - $this->name = $name; - $this->data =& $data; - - } - - /** - * @return string - */ - public function __toString() { - return $this->name; - } - - /** - * advise functions - * - * advise all registered handlers of this event - * - * if these methods are used by functions outside of this object, they must - * properly handle correct processing of any default action and issue an - * advise_after() signal. e.g. - * $evt = new Doku_Event(name, data); - * if ($evt->advise_before(canPreventDefault) { - * // default action code block - * } - * $evt->advise_after(); - * unset($evt); - * - * @param bool $enablePreventDefault - * @return bool results of processing the event, usually $this->_default - */ - public function advise_before($enablePreventDefault=true) { - global $EVENT_HANDLER; - - $this->canPreventDefault = $enablePreventDefault; - $EVENT_HANDLER->process_event($this,'BEFORE'); - - return (!$enablePreventDefault || $this->_default); - } - - public function advise_after() { - global $EVENT_HANDLER; - - $this->_continue = true; - $EVENT_HANDLER->process_event($this,'AFTER'); - } - - /** - * trigger - * - * - advise all registered (<event>_BEFORE) handlers that this event is about to take place - * - carry out the default action using $this->data based on $enablePrevent and - * $this->_default, all of which may have been modified by the event handlers. - * - advise all registered (<event>_AFTER) handlers that the event has taken place - * - * @param null|callable $action - * @param bool $enablePrevent - * @return mixed $event->results - * the value set by any <event>_before or <event> handlers if the default action is prevented - * or the results of the default action (as modified by <event>_after handlers) - * or NULL no action took place and no handler modified the value - */ - public function trigger($action=null, $enablePrevent=true) { - - if (!is_callable($action)) { - $enablePrevent = false; - if (!is_null($action)) { - trigger_error( - 'The default action of ' . $this . - ' is not null but also not callable. Maybe the method is not public?', - E_USER_WARNING - ); - } - } - - if ($this->advise_before($enablePrevent) && is_callable($action)) { - if (is_array($action)) { - list($obj,$method) = $action; - $this->result = $obj->$method($this->data); - } else { - $this->result = $action($this->data); - } - } - - $this->advise_after(); - - return $this->result; - } - - /** - * stopPropagation - * - * stop any further processing of the event by event handlers - * this function does not prevent the default action taking place - */ - public function stopPropagation() { - $this->_continue = false; - } - - /** - * may the event propagate to the next handler? - * - * @return bool - */ - public function mayPropagate() { - return $this->_continue; - } - - /** - * preventDefault - * - * prevent the default action taking place - */ - public function preventDefault() { - $this->_default = false; - } - - /** - * should the default action be executed? - * - * @return bool - */ - public function mayRunDefault() { - return $this->_default; - } -} - -/** - * Controls the registration and execution of all events, - */ -class Doku_Event_Handler { - - // public properties: none - - // private properties - protected $_hooks = array(); // array of events and their registered handlers - - /** - * event_handler - * - * constructor, loads all action plugins and calls their register() method giving them - * an opportunity to register any hooks they require - */ - public function __construct() { - - // load action plugins - /** @var DokuWiki_Action_Plugin $plugin */ - $plugin = null; - $pluginlist = plugin_list('action'); - - foreach ($pluginlist as $plugin_name) { - $plugin = plugin_load('action',$plugin_name); - - if ($plugin !== null) $plugin->register($this); - } - } - - /** - * register_hook - * - * register a hook for an event - * - * @param string $event string name used by the event, (incl '_before' or '_after' for triggers) - * @param string $advise - * @param object $obj object in whose scope method is to be executed, - * if NULL, method is assumed to be a globally available function - * @param string $method event handler function - * @param mixed $param data passed to the event handler - * @param int $seq sequence number for ordering hook execution (ascending) - */ - public function register_hook($event, $advise, $obj, $method, $param=null, $seq=0) { - $seq = (int)$seq; - $doSort = !isset($this->_hooks[$event.'_'.$advise][$seq]); - $this->_hooks[$event.'_'.$advise][$seq][] = array($obj, $method, $param); - - if ($doSort) { - ksort($this->_hooks[$event.'_'.$advise]); - } - } - - /** - * process the before/after event - * - * @param Doku_Event $event - * @param string $advise BEFORE or AFTER - */ - public function process_event($event,$advise='') { - - $evt_name = $event->name . ($advise ? '_'.$advise : '_BEFORE'); - - if (!empty($this->_hooks[$evt_name])) { - foreach ($this->_hooks[$evt_name] as $sequenced_hooks) { - foreach ($sequenced_hooks as $hook) { - list($obj, $method, $param) = $hook; - - if (is_null($obj)) { - $method($event, $param); - } else { - $obj->$method($event, $param); - } - - if (!$event->mayPropagate()) return; - } - } - } - } - - /** - * Check if an event has any registered handlers - * - * When $advise is empty, both BEFORE and AFTER events will be considered, - * otherwise only the given advisory is checked - * - * @param string $name Name of the event - * @param string $advise BEFORE, AFTER or empty - * @return bool - */ - public function hasHandlerForEvent($name, $advise = '') { - if($advise) { - return isset($this->_hooks[$name . '_' . $advise]); - } else { - return isset($this->_hooks[$name . '_BEFORE']) || isset($this->_hooks[$name . '_AFTER']); - } - } -} /** * trigger_event @@ -272,6 +16,6 @@ class Doku_Event_Handler { */ function trigger_event($name, &$data, $action=null, $canPreventDefault=true) { - $evt = new Doku_Event($name, $data); + $evt = new \dokuwiki\Extension\Event($name, $data); return $evt->trigger($action, $canPreventDefault); } diff --git a/inc/fulltext.php b/inc/fulltext.php index 54e7b8cd9..194b46fae 100644 --- a/inc/fulltext.php +++ b/inc/fulltext.php @@ -4,7 +4,7 @@ * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Andreas Gohr <andi@splitbrain.org> - */ + */use dokuwiki\Extension\Event; /** * create snippets for the first few results only @@ -93,7 +93,7 @@ function _ft_pageSearch(&$data) { 'phrase' => $phrase, 'text' => rawWiki($id) ); - $evt = new Doku_Event('FULLTEXT_PHRASE_MATCH',$evdata); + $evt = new Event('FULLTEXT_PHRASE_MATCH',$evdata); if ($evt->advise_before() && $evt->result !== true) { $text = utf8_strtolower($evdata['text']); if (strpos($text, $phrase) !== false) { @@ -405,7 +405,7 @@ function ft_snippet($id,$highlight){ 'snippet' => '', ); - $evt = new Doku_Event('FULLTEXT_SNIPPET_CREATE',$evdata); + $evt = new Event('FULLTEXT_SNIPPET_CREATE',$evdata); if ($evt->advise_before()) { $match = array(); $snippets = array(); diff --git a/inc/html.php b/inc/html.php index 525698b2f..ef4ea164a 100644 --- a/inc/html.php +++ b/inc/html.php @@ -8,6 +8,7 @@ use dokuwiki\ChangeLog\MediaChangeLog; use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\Extension\AuthPlugin; if (!defined('SEC_EDIT_PATTERN')) { define('SEC_EDIT_PATTERN', '#<!-- EDIT({.*?}) -->#'); @@ -1723,7 +1724,7 @@ function html_updateprofile(){ global $conf; global $INPUT; global $INFO; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var AuthPlugin $auth */ global $auth; print p_locale_xhtml('updateprofile'); @@ -2016,7 +2017,7 @@ function html_minoredit(){ function html_debug(){ global $conf; global $lang; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var AuthPlugin $auth */ global $auth; global $INFO; diff --git a/inc/indexer.php b/inc/indexer.php index 02eb96798..7149ea944 100644 --- a/inc/indexer.php +++ b/inc/indexer.php @@ -8,7 +8,7 @@ */ // Version tag used to force rebuild on upgrade -define('INDEXER_VERSION', 8); +use dokuwiki\Extension\Event;define('INDEXER_VERSION', 8); // set the minimum token length to use in the index (note, this doesn't apply to numeric tokens) if (!defined('IDX_MINWORDLENGTH')) define('IDX_MINWORDLENGTH',2); @@ -585,7 +585,7 @@ class Doku_Indexer { $stopwords =& idx_get_stopwords(); // prepare the text to be tokenized - $evt = new Doku_Event('INDEXER_TEXT_PREPARE', $text); + $evt = new Event('INDEXER_TEXT_PREPARE', $text); if ($evt->advise_before(true)) { if (preg_match('/[^0-9A-Za-z ]/u', $text)) { // handle asian chars as single words (may fail on older PHP version) @@ -1423,7 +1423,7 @@ function idx_addPage($page, $verbose=false, $force=false) { $metadata['relation_media'] = array(); $data = compact('page', 'body', 'metadata', 'pid'); - $evt = new Doku_Event('INDEXER_PAGE_ADD', $data); + $evt = new Event('INDEXER_PAGE_ADD', $data); if ($evt->advise_before()) $data['body'] = $data['body'] . " " . rawWiki($page); $evt->advise_after(); unset($evt); diff --git a/inc/infoutils.php b/inc/infoutils.php index ff2945a20..ba137c1ac 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -453,7 +453,6 @@ function dbglog($msg,$header=''){ * Log accesses to deprecated fucntions to the debug log * * @param string $alternative The function or method that should be used instead - * @param string|null $deprecatedThing What is deprecated if not the current method * @triggers INFO_DEPRECATION_LOG */ function dbg_deprecated($alternative = '') { diff --git a/inc/init.php b/inc/init.php index 1db625de0..16f350dc3 100644 --- a/inc/init.php +++ b/inc/init.php @@ -3,6 +3,8 @@ * Initialize some defaults needed for DokuWiki */ +use dokuwiki\Extension\EventHandler; + /** * timing Dokuwiki execution * @@ -189,9 +191,9 @@ init_paths(); init_files(); // setup plugin controller class (can be overwritten in preload.php) -$plugin_types = array('auth', 'admin','syntax','action','renderer', 'helper','remote'); +$plugin_types = array('auth', 'admin','syntax','action','renderer', 'helper','remote','cli'); global $plugin_controller_class, $plugin_controller; -if (empty($plugin_controller_class)) $plugin_controller_class = 'Doku_Plugin_Controller'; +if (empty($plugin_controller_class)) $plugin_controller_class = Doku_Plugin_Controller::class; // load libraries require_once(DOKU_INC.'vendor/autoload.php'); @@ -216,7 +218,7 @@ $plugin_controller = new $plugin_controller_class(); // initialize the event handler global $EVENT_HANDLER; -$EVENT_HANDLER = new Doku_Event_Handler(); +$EVENT_HANDLER = new EventHandler(); $local = $conf['lang']; trigger_event('INIT_LANG_LOAD', $local, 'init_lang', true); diff --git a/inc/legacy.php b/inc/legacy.php new file mode 100644 index 000000000..fa72649b7 --- /dev/null +++ b/inc/legacy.php @@ -0,0 +1,18 @@ +<?php +/** + * We map legacy class names to the new namespaced versions here + * + * These are names that we will probably never change because they have been part of DokuWiki's + * public interface for years and renaming would break just too many plugins + */ + +class_alias('\dokuwiki\Extension\EventHandler', 'Doku_Event_Handler'); +class_alias('\dokuwiki\Extension\Event', 'Doku_Event'); + +class_alias('\dokuwiki\Extension\ActionPlugin', 'DokuWiki_Action_Plugin'); +class_alias('\dokuwiki\Extension\AdminPlugin', 'DokuWiki_Admin_Plugin'); +class_alias('\dokuwiki\Extension\AuthPlugin', 'DokuWiki_Auth_Plugin'); +class_alias('\dokuwiki\Extension\CLIPlugin', 'DokuWiki_CLI_Plugin'); +class_alias('\dokuwiki\Extension\Plugin', 'DokuWiki_Plugin'); +class_alias('\dokuwiki\Extension\RemotePlugin', 'DokuWiki_Remote_Plugin'); +class_alias('\dokuwiki\Extension\SyntaxPlugin', 'DokuWiki_Syntax_Plugin'); diff --git a/inc/load.php b/inc/load.php index f4e9004f0..1bf767051 100644 --- a/inc/load.php +++ b/inc/load.php @@ -35,6 +35,7 @@ require_once(DOKU_INC.'inc/utf8.php'); require_once(DOKU_INC.'inc/auth.php'); require_once(DOKU_INC.'inc/compatibility.php'); require_once(DOKU_INC.'inc/deprecated.php'); +require_once(DOKU_INC.'inc/legacy.php'); /** * spl_autoload_register callback @@ -51,7 +52,7 @@ require_once(DOKU_INC.'inc/deprecated.php'); */ function load_autoload($name){ static $classes = null; - if(is_null($classes)) $classes = array( + if($classes === null) $classes = array( 'Diff' => DOKU_INC.'inc/DifferenceEngine.php', 'UnifiedDiffFormatter' => DOKU_INC.'inc/DifferenceEngine.php', 'TableDiffFormatter' => DOKU_INC.'inc/DifferenceEngine.php', @@ -59,8 +60,7 @@ function load_autoload($name){ 'cache_parser' => DOKU_INC.'inc/cache.php', 'cache_instructions' => DOKU_INC.'inc/cache.php', 'cache_renderer' => DOKU_INC.'inc/cache.php', - 'Doku_Event' => DOKU_INC.'inc/events.php', - 'Doku_Event_Handler' => DOKU_INC.'inc/events.php', + 'Input' => DOKU_INC.'inc/Input.class.php', 'JpegMeta' => DOKU_INC.'inc/JpegMeta.php', 'SimplePie' => DOKU_INC.'inc/SimplePie.php', 'FeedParser' => DOKU_INC.'inc/FeedParser.php', @@ -74,18 +74,6 @@ function load_autoload($name){ 'Mailer' => DOKU_INC.'inc/Mailer.class.php', 'Subscription' => DOKU_INC.'inc/subscription.php', - 'DokuWiki_PluginInterface' => DOKU_INC.'inc/PluginInterface.php', - 'DokuWiki_PluginTrait' => DOKU_INC.'inc/PluginTrait.php', - 'DokuWiki_Plugin' => DOKU_INC.'inc/Plugin.php', - - - 'DokuWiki_Action_Plugin' => DOKU_PLUGIN.'action.php', - 'DokuWiki_Admin_Plugin' => DOKU_PLUGIN.'admin.php', - 'DokuWiki_Syntax_Plugin' => DOKU_PLUGIN.'syntax.php', - 'DokuWiki_Remote_Plugin' => DOKU_PLUGIN.'remote.php', - 'DokuWiki_Auth_Plugin' => DOKU_PLUGIN.'auth.php', - 'DokuWiki_CLI_Plugin' => DOKU_PLUGIN.'cli.php', - 'Doku_Handler' => DOKU_INC.'inc/parser/handler.php', 'Doku_Renderer' => DOKU_INC.'inc/parser/renderer.php', 'Doku_Renderer_xhtml' => DOKU_INC.'inc/parser/xhtml.php', diff --git a/inc/media.php b/inc/media.php index 31292452d..a68770478 100644 --- a/inc/media.php +++ b/inc/media.php @@ -8,6 +8,7 @@ use dokuwiki\ChangeLog\MediaChangeLog; use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Extension\Event; /** * Lists pages which currently use a media file selected for deletion @@ -265,7 +266,7 @@ function media_delete($id,$auth){ $data['unl'] = false; $data['del'] = false; - $evt = new Doku_Event('MEDIA_DELETE_FILE',$data); + $evt = new Event('MEDIA_DELETE_FILE',$data); if ($evt->advise_before()) { $old = @filemtime($file); if(!file_exists(mediaFN($id, $old)) && file_exists($file)) { @@ -1512,7 +1513,7 @@ function media_searchlist($query,$ns,$auth=null,$fullscreen=false,$sort='natural 'query' => $query ); if (!blank($query)) { - $evt = new Doku_Event('MEDIA_SEARCH', $evdata); + $evt = new Event('MEDIA_SEARCH', $evdata); if ($evt->advise_before()) { $dir = utf8_encodeFN(str_replace(':','/',$evdata['ns'])); $quoted = preg_quote($evdata['query'],'/'); diff --git a/inc/parser/handler.php b/inc/parser/handler.php index 6d4c6b97e..1d13db3f0 100644 --- a/inc/parser/handler.php +++ b/inc/parser/handler.php @@ -1,5 +1,6 @@ <?php +use dokuwiki\Extension\SyntaxPlugin; use dokuwiki\Parsing\Handler\Block; use dokuwiki\Parsing\Handler\CallWriter; use dokuwiki\Parsing\Handler\CallWriterInterface; @@ -226,7 +227,7 @@ class Doku_Handler { */ public function plugin($match, $state, $pos, $pluginname){ $data = array($match); - /** @var DokuWiki_Syntax_Plugin $plugin */ + /** @var SyntaxPlugin $plugin */ $plugin = plugin_load('syntax',$pluginname); if($plugin != null){ $data = $plugin->handle($match, $state, $pos, $this); diff --git a/inc/parser/renderer.php b/inc/parser/renderer.php index eb4d658be..d00e7388c 100644 --- a/inc/parser/renderer.php +++ b/inc/parser/renderer.php @@ -6,6 +6,9 @@ * @author Andreas Gohr <andi@splitbrain.org> */ +use dokuwiki\Extension\Plugin; +use dokuwiki\Extension\SyntaxPlugin; + /** * Allowed chars in $language for code highlighting * @see GeSHi::set_language() @@ -15,7 +18,7 @@ define('PREG_PATTERN_VALID_LANGUAGE', '#[^a-zA-Z0-9\-_]#'); /** * An empty renderer, produces no output * - * Inherits from DokuWiki_Plugin for giving additional functions to render plugins + * Inherits from dokuwiki\Plugin\DokuWiki_Plugin for giving additional functions to render plugins * * The renderer transforms the syntax instructions created by the parser and handler into the * desired output format. For each instruction a corresponding method defined in this class will @@ -23,7 +26,7 @@ define('PREG_PATTERN_VALID_LANGUAGE', '#[^a-zA-Z0-9\-_]#'); * $doc field. When all instructions are processed, the $doc field contents will be cached by * DokuWiki and sent to the user. */ -abstract class Doku_Renderer extends DokuWiki_Plugin { +abstract class Doku_Renderer extends Plugin { /** @var array Settings, control the behavior of the renderer */ public $info = array( 'cache' => true, // may the rendered result cached? @@ -105,7 +108,7 @@ abstract class Doku_Renderer extends DokuWiki_Plugin { * @param string $match raw matched syntax */ public function plugin($name, $data, $state = '', $match = '') { - /** @var DokuWiki_Syntax_Plugin $plugin */ + /** @var SyntaxPlugin $plugin */ $plugin = plugin_load('syntax', $name); if($plugin != null) { $plugin->render($this->getFormat(), $this, $data); diff --git a/inc/parserutils.php b/inc/parserutils.php index 89d607fc2..fe25b220f 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -9,6 +9,8 @@ use dokuwiki\Cache\CacheInstructions; use dokuwiki\Cache\CacheRenderer; +use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\Extension\Event; use dokuwiki\Parsing\Parser; /** @@ -86,7 +88,7 @@ function p_wiki_xhtml($id, $rev='', $excuse=true,$date_at=''){ $ret = p_cached_output($file,'xhtml',$id); }elseif($excuse){ //check if the page once existed - $changelog = new PageChangelog($id); + $changelog = new PageChangeLog($id); if($changelog->hasRevisions()) { $ret = p_locale_xhtml('onceexisted'); } else { @@ -307,10 +309,10 @@ function p_get_metadata($id, $key='', $render=METADATA_RENDER_USING_CACHE){ * * @see http://www.dokuwiki.org/devel:metadata#functions_to_get_and_set_metadata * - * @param String $id is the ID of a wiki page - * @param Array $data is an array with key ⇒ value pairs to be set in the metadata - * @param Boolean $render whether or not the page metadata should be generated with the renderer - * @param Boolean $persistent indicates whether or not the particular metadata value will persist through + * @param string $id is the ID of a wiki page + * @param array $data is an array with key ⇒ value pairs to be set in the metadata + * @param boolean $render whether or not the page metadata should be generated with the renderer + * @param boolean $persistent indicates whether or not the particular metadata value will persist through * the next metadata rendering. * @return boolean true on success * @@ -491,7 +493,7 @@ function p_render_metadata($id, $orig){ // add an extra key for the event - to tell event handlers the page whose metadata this is $orig['page'] = $id; - $evt = new Doku_Event('PARSER_METADATA_RENDER', $orig); + $evt = new Event('PARSER_METADATA_RENDER', $orig); if ($evt->advise_before()) { // get instructions @@ -552,7 +554,7 @@ function p_get_parsermodes(){ global $PARSER_MODES; $obj = null; foreach($pluginlist as $p){ - /** @var DokuWiki_Syntax_Plugin $obj */ + /** @var \dokuwiki\Extension\SyntaxPlugin $obj */ if(!$obj = plugin_load('syntax',$p)) continue; //attempt to load plugin into $obj $PARSER_MODES[$obj->getType()][] = "plugin_$p"; //register mode type //add to modes diff --git a/inc/plugincontroller.class.php b/inc/plugincontroller.class.php index 1899b13fa..419eff556 100644 --- a/inc/plugincontroller.class.php +++ b/inc/plugincontroller.class.php @@ -7,6 +7,8 @@ */ // plugin related constants +use dokuwiki\Extension\PluginInterface; + if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); class Doku_Plugin_Controller { @@ -68,7 +70,7 @@ class Doku_Plugin_Controller { * @param $name string name of the plugin to load * @param $new bool true to return a new instance of the plugin, false to use an already loaded instance * @param $disabled bool true to load even disabled plugins - * @return DokuWiki_PluginInterface|null the plugin object or null on failure + * @return PluginInterface|null the plugin object or null on failure */ public function load($type,$name,$new=false,$disabled=false){ diff --git a/inc/pluginutils.php b/inc/pluginutils.php index aa39f29b8..47f8d1cad 100644 --- a/inc/pluginutils.php +++ b/inc/pluginutils.php @@ -7,6 +7,9 @@ */ // plugin related constants +use dokuwiki\Extension\AdminPlugin; +use dokuwiki\Extension\PluginInterface; + if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); // note that only [a-z0-9]+ is officially supported, // this is only to support plugins that don't follow these conventions, too @@ -38,7 +41,7 @@ function plugin_list($type='',$all=false) { * @param $name string name of the plugin to load * @param $new bool true to return a new instance of the plugin, false to use an already loaded instance * @param $disabled bool true to load even disabled plugins - * @return DokuWiki_PluginInterface|null the plugin object or null on failure + * @return PluginInterface|null the plugin object or null on failure */ function plugin_load($type,$name,$new=false,$disabled=false) { /** @var $plugin_controller Doku_Plugin_Controller */ @@ -121,7 +124,7 @@ function plugin_getRequestAdminPlugin(){ $pluginlist = plugin_list('admin'); if (in_array($page, $pluginlist)) { // attempt to load the plugin - /** @var $admin_plugin DokuWiki_Admin_Plugin */ + /** @var $admin_plugin AdminPlugin */ $admin_plugin = plugin_load('admin', $page); // verify if ($admin_plugin && !$admin_plugin->isAccessibleByCurrentUser()) { diff --git a/inc/subscription.php b/inc/subscription.php index 80b301ed5..d68801704 100644 --- a/inc/subscription.php +++ b/inc/subscription.php @@ -1,6 +1,7 @@ <?php use dokuwiki\ChangeLog\PageChangeLog; +use dokuwiki\Extension\AuthPlugin; /** * Class for handling (email) subscriptions @@ -293,7 +294,7 @@ class Subscription { public function send_bulk($page) { if(!$this->isenabled()) return 0; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; global $conf; global $USERINFO; @@ -663,7 +664,7 @@ class Subscription { public function notifyaddresses(&$data) { if(!$this->isenabled()) return; - /** @var DokuWiki_Auth_Plugin $auth */ + /** @var \dokuwiki\Extension\AuthPlugin $auth */ global $auth; global $conf; /** @var Input $INPUT */ diff --git a/inc/template.php b/inc/template.php index ece077f88..fc3eff6a7 100644 --- a/inc/template.php +++ b/inc/template.php @@ -6,6 +6,9 @@ * @author Andreas Gohr <andi@splitbrain.org> */ +use dokuwiki\Extension\AdminPlugin; +use dokuwiki\Extension\Event; + /** * Access a template file * @@ -140,7 +143,7 @@ function tpl_toc($return = false) { } } elseif($ACT == 'admin') { // try to load admin plugin TOC - /** @var $plugin DokuWiki_Admin_Plugin */ + /** @var $plugin AdminPlugin */ if ($plugin = plugin_getRequestAdminPlugin()) { $toc = $plugin->getTOC(); $TOC = $toc; // avoid later rebuild @@ -173,7 +176,7 @@ function tpl_admin() { if(in_array($class, $pluginlist)) { // attempt to load the plugin - /** @var $plugin DokuWiki_Admin_Plugin */ + /** @var $plugin AdminPlugin */ $plugin = plugin_load('admin', $class); } } @@ -601,7 +604,7 @@ function tpl_get_action($type) { $unknown = true; } - $evt = new Doku_Event('TPL_ACTION_GET', $data); + $evt = new Event('TPL_ACTION_GET', $data); if($evt->advise_before()) { //handle unknown types if($unknown) { @@ -931,7 +934,7 @@ function tpl_pagetitle($id = null, $ret = false) { case 'admin' : $page_title = $lang['btn_admin']; // try to get the plugin name - /** @var $plugin DokuWiki_Admin_Plugin */ + /** @var $plugin AdminPlugin */ if ($plugin = plugin_getRequestAdminPlugin()){ $plugin_title = $plugin->getMenuText($conf['lang']); $page_title = $plugin_title ? $plugin_title : $plugin->getPluginName(); @@ -1341,7 +1344,7 @@ function tpl_mediaContent($fromajax = false, $sort='natural') { // output the content pane, wrapped in an event. if(!$fromajax) ptln('<div id="media__content">'); $data = array('do' => $do); - $evt = new Doku_Event('MEDIAMANAGER_CONTENT_OUTPUT', $data); + $evt = new Event('MEDIAMANAGER_CONTENT_OUTPUT', $data); if($evt->advise_before()) { $do = $data['do']; if($do == 'filesinuse') { @@ -1865,7 +1868,7 @@ function tpl_toolsevent($toolsname, $items, $view = 'main') { ); $hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY'; - $evt = new Doku_Event($hook, $data); + $evt = new Event($hook, $data); if($evt->advise_before()) { foreach($evt->data['items'] as $k => $html) echo $html; } diff --git a/inc/toolbar.php b/inc/toolbar.php index 07b9e98ee..056221aa4 100644 --- a/inc/toolbar.php +++ b/inc/toolbar.php @@ -4,7 +4,7 @@ * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Andreas Gohr <andi@splitbrain.org> - */ + */use dokuwiki\Extension\Event; /** * Prepares and prints an JavaScript array with all toolbar buttons @@ -18,7 +18,7 @@ function toolbar_JSdefines($varname){ $menu = array(); - $evt = new Doku_Event('TOOLBAR_DEFINE', $menu); + $evt = new Event('TOOLBAR_DEFINE', $menu); if ($evt->advise_before()){ // build button array diff --git a/lib/exe/css.php b/lib/exe/css.php index 107e2a9c2..88ca42bbd 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -7,8 +7,9 @@ */ use dokuwiki\Cache\Cache; +use dokuwiki\Extension\Event; -if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +if(!defined('DOKU_INC')) define('DOKU_INC', __DIR__ .'/../../'); if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching) if(!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT',1); // we gzip ourself here if(!defined('NL')) define('NL',"\n"); @@ -87,7 +88,7 @@ function css_out(){ // Let plugins decide to either put more styles here or to remove some $media_files[$mediatype] = css_filewrapper($mediatype, $files); - $CSSEvt = new Doku_Event('CSS_STYLES_INCLUDED', $media_files[$mediatype]); + $CSSEvt = new Event('CSS_STYLES_INCLUDED', $media_files[$mediatype]); // Make it preventable. if ( $CSSEvt->advise_before() ) { diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php index a9070abfc..5c5ae899b 100644 --- a/lib/exe/fetch.php +++ b/lib/exe/fetch.php @@ -6,6 +6,8 @@ * @author Andreas Gohr <andi@splitbrain.org> */ +use dokuwiki\Extension\Event; + if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/../../'); if (!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT', 1); require_once(DOKU_INC.'inc/init.php'); @@ -56,7 +58,7 @@ if (defined('SIMPLE_TEST')) { ); // handle the file status - $evt = new Doku_Event('FETCH_MEDIA_STATUS', $data); + $evt = new Event('FETCH_MEDIA_STATUS', $data); if($evt->advise_before()) { // redirects if($data['status'] > 300 && $data['status'] <= 304) { @@ -87,7 +89,7 @@ if (defined('SIMPLE_TEST')) { } // finally send the file to the client - $evt = new Doku_Event('MEDIA_SENDFILE', $data); + $evt = new Event('MEDIA_SENDFILE', $data); if($evt->advise_before()) { sendFile($data['file'], $data['mime'], $data['download'], $data['cache'], $data['ispublic'], $data['orig']); } diff --git a/lib/plugins/action.php b/lib/plugins/action.php index 496c56926..a3cbec722 100644 --- a/lib/plugins/action.php +++ b/lib/plugins/action.php @@ -1,19 +1,2 @@ <?php -/** - * Action Plugin Prototype - * - * All DokuWiki plugins to interfere with the event system - * need to inherit from this class - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Christopher Smith <chris@jalakai.co.uk> - */ -abstract class DokuWiki_Action_Plugin extends DokuWiki_Plugin { - - /** - * Registers a callback function for a given event - * - * @param Doku_Event_Handler $controller - */ - abstract public function register(Doku_Event_Handler $controller); -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/admin.php b/lib/plugins/admin.php index ca0ac3d7d..a3cbec722 100644 --- a/lib/plugins/admin.php +++ b/lib/plugins/admin.php @@ -1,113 +1,2 @@ <?php -/** - * Admin Plugin Prototype - * - * All DokuWiki plugins to extend the admin function - * need to inherit from this class - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Christopher Smith <chris@jalakai.co.uk> - */ -abstract class DokuWiki_Admin_Plugin extends DokuWiki_Plugin { - - /** - * Return the text that is displayed at the main admin menu - * (Default localized language string 'menu' is returned, override this function for setting another name) - * - * @param string $language language code - * @return string menu string - */ - public function getMenuText($language) { - $menutext = $this->getLang('menu'); - if (!$menutext) { - $info = $this->getInfo(); - $menutext = $info['name'].' ...'; - } - return $menutext; - } - - /** - * Return the path to the icon being displayed in the main admin menu. - * By default it tries to find an 'admin.svg' file in the plugin directory. - * (Override this function for setting another image) - * - * Important: you have to return a single path, monochrome SVG icon! It has to be - * under 2 Kilobytes! - * - * We recommend icons from https://materialdesignicons.com/ or to use a matching - * style. - * - * @return string full path to the icon file - */ - public function getMenuIcon() { - $plugin = $this->getPluginName(); - return DOKU_PLUGIN . $plugin . '/admin.svg'; - } - - /** - * Determine position in list in admin window - * Lower values are sorted up - * - * @return int - */ - public function getMenuSort() { - return 1000; - } - - /** - * Carry out required processing - */ - public function handle() { - // some plugins might not need this - } - - /** - * Output html of the admin page - */ - abstract public function html(); - - /** - * Checks if access should be granted to this admin plugin - * - * @return bool true if the current user may access this admin plugin - */ - public function isAccessibleByCurrentUser() { - $data = []; - $data['instance'] = $this; - $data['hasAccess'] = false; - - $event = new Doku_Event('ADMINPLUGIN_ACCESS_CHECK', $data); - if($event->advise_before()) { - if ($this->forAdminOnly()) { - $data['hasAccess'] = auth_isadmin(); - } else { - $data['hasAccess'] = auth_ismanager(); - } - } - $event->advise_after(); - - return $data['hasAccess']; - } - - /** - * Return true for access only by admins (config:superuser) or false if managers are allowed as well - * - * @return bool - */ - public function forAdminOnly() { - return true; - } - - /** - * Return array with ToC items. Items can be created with the html_mktocitem() - * - * @see html_mktocitem() - * @see tpl_toc() - * - * @return array - */ - public function getTOC(){ - return array(); - } -} -//Setup VIM: ex: et ts=4 : +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/auth.php b/lib/plugins/auth.php index 442580b23..a3cbec722 100644 --- a/lib/plugins/auth.php +++ b/lib/plugins/auth.php @@ -1,436 +1,2 @@ <?php -/** - * Auth Plugin Prototype - * - * foundation authorisation class - * all auth classes should inherit from this class - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Chris Smith <chris@jalakai.co.uk> - * @author Jan Schumann <js@jschumann-it.com> - */ -abstract class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { - public $success = true; - - /** - * Possible things an auth backend module may be able to - * do. The things a backend can do need to be set to true - * in the constructor. - */ - protected $cando = array( - 'addUser' => false, // can Users be created? - 'delUser' => false, // can Users be deleted? - 'modLogin' => false, // can login names be changed? - 'modPass' => false, // can passwords be changed? - 'modName' => false, // can real names be changed? - 'modMail' => false, // can emails be changed? - 'modGroups' => false, // can groups be changed? - 'getUsers' => false, // can a (filtered) list of users be retrieved? - 'getUserCount' => false, // can the number of users be retrieved? - 'getGroups' => false, // can a list of available groups be retrieved? - 'external' => false, // does the module do external auth checking? - 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth) - ); - - /** - * Constructor. - * - * Carry out sanity checks to ensure the object is - * able to operate. Set capabilities in $this->cando - * array here - * - * For future compatibility, sub classes should always include a call - * to parent::__constructor() in their constructors! - * - * Set $this->success to false if checks fail - * - * @author Christopher Smith <chris@jalakai.co.uk> - */ - public function __construct() { - // the base class constructor does nothing, derived class - // constructors do the real work - } - - /** - * Available Capabilities. [ DO NOT OVERRIDE ] - * - * For introspection/debugging - * - * @author Christopher Smith <chris@jalakai.co.uk> - * @return array - */ - public function getCapabilities(){ - return array_keys($this->cando); - } - - /** - * Capability check. [ DO NOT OVERRIDE ] - * - * Checks the capabilities set in the $this->cando array and - * some pseudo capabilities (shortcutting access to multiple - * ones) - * - * ususal capabilities start with lowercase letter - * shortcut capabilities start with uppercase letter - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $cap the capability to check - * @return bool - */ - public function canDo($cap) { - switch($cap) { - case 'Profile': - // can at least one of the user's properties be changed? - return ($this->cando['modPass'] || - $this->cando['modName'] || - $this->cando['modMail']); - break; - case 'UserMod': - // can at least anything be changed? - return ($this->cando['modPass'] || - $this->cando['modName'] || - $this->cando['modMail'] || - $this->cando['modLogin'] || - $this->cando['modGroups'] || - $this->cando['modMail']); - break; - default: - // print a helping message for developers - if(!isset($this->cando[$cap])) { - msg("Check for unknown capability '$cap' - Do you use an outdated Plugin?", -1); - } - return $this->cando[$cap]; - } - } - - /** - * Trigger the AUTH_USERDATA_CHANGE event and call the modification function. [ DO NOT OVERRIDE ] - * - * You should use this function instead of calling createUser, modifyUser or - * deleteUsers directly. The event handlers can prevent the modification, for - * example for enforcing a user name schema. - * - * @author Gabriel Birke <birke@d-scribe.de> - * @param string $type Modification type ('create', 'modify', 'delete') - * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. - * The content of this array depends on the modification type - * @return bool|null|int Result from the modification function or false if an event handler has canceled the action - */ - public function triggerUserMod($type, $params) { - $validTypes = array( - 'create' => 'createUser', - 'modify' => 'modifyUser', - 'delete' => 'deleteUsers' - ); - if(empty($validTypes[$type])) { - return false; - } - - $result = false; - $eventdata = array('type' => $type, 'params' => $params, 'modification_result' => null); - $evt = new Doku_Event('AUTH_USER_CHANGE', $eventdata); - if($evt->advise_before(true)) { - $result = call_user_func_array(array($this, $validTypes[$type]), $evt->data['params']); - $evt->data['modification_result'] = $result; - } - $evt->advise_after(); - unset($evt); - return $result; - } - - /** - * Log off the current user [ OPTIONAL ] - * - * Is run in addition to the ususal logoff method. Should - * only be needed when trustExternal is implemented. - * - * @see auth_logoff() - * @author Andreas Gohr <andi@splitbrain.org> - */ - public function logOff() { - } - - /** - * Do all authentication [ OPTIONAL ] - * - * Set $this->cando['external'] = true when implemented - * - * If this function is implemented it will be used to - * authenticate a user - all other DokuWiki internals - * will not be used for authenticating, thus - * implementing the checkPass() function is not needed - * anymore. - * - * The function can be used to authenticate against third - * party cookies or Apache auth mechanisms and replaces - * the auth_login() function - * - * The function will be called with or without a set - * username. If the Username is given it was called - * from the login form and the given credentials might - * need to be checked. If no username was given it - * the function needs to check if the user is logged in - * by other means (cookie, environment). - * - * The function needs to set some globals needed by - * DokuWiki like auth_login() does. - * - * @see auth_login() - * @author Andreas Gohr <andi@splitbrain.org> - * - * @param string $user Username - * @param string $pass Cleartext Password - * @param bool $sticky Cookie should not expire - * @return bool true on successful auth - */ - public function trustExternal($user, $pass, $sticky = false) { - /* some example: - - global $USERINFO; - global $conf; - $sticky ? $sticky = true : $sticky = false; //sanity check - - // do the checking here - - // set the globals if authed - $USERINFO['name'] = 'FIXME'; - $USERINFO['mail'] = 'FIXME'; - $USERINFO['grps'] = array('FIXME'); - $_SERVER['REMOTE_USER'] = $user; - $_SESSION[DOKU_COOKIE]['auth']['user'] = $user; - $_SESSION[DOKU_COOKIE]['auth']['pass'] = $pass; - $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; - return true; - - */ - } - - /** - * Check user+password [ MUST BE OVERRIDDEN ] - * - * Checks if the given user exists and the given - * plaintext password is correct - * - * May be ommited if trustExternal is used. - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user the user name - * @param string $pass the clear text password - * @return bool - */ - public function checkPass($user, $pass) { - msg("no valid authorisation system in use", -1); - return false; - } - - /** - * Return user info [ MUST BE OVERRIDDEN ] - * - * Returns info about the given user needs to contain - * at least these fields: - * - * name string full name of the user - * mail string email address of the user - * grps array list of groups the user is in - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user the user name - * @param bool $requireGroups whether or not the returned data must include groups - * @return false|array containing user data or false - */ - public function getUserData($user, $requireGroups=true) { - if(!$this->cando['external']) msg("no valid authorisation system in use", -1); - return false; - } - - /** - * Create a new User [implement only where required/possible] - * - * Returns false if the user already exists, null when an error - * occurred and true if everything went well. - * - * The new user HAS TO be added to the default group by this - * function! - * - * Set addUser capability when implemented - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user - * @param string $pass - * @param string $name - * @param string $mail - * @param null|array $grps - * @return bool|null - */ - public function createUser($user, $pass, $name, $mail, $grps = null) { - msg("authorisation method does not allow creation of new users", -1); - return null; - } - - /** - * Modify user data [implement only where required/possible] - * - * Set the mod* capabilities according to the implemented features - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param string $user nick of the user to be changed - * @param array $changes array of field/value pairs to be changed (password will be clear text) - * @return bool - */ - public function modifyUser($user, $changes) { - msg("authorisation method does not allow modifying of user data", -1); - return false; - } - - /** - * Delete one or more users [implement only where required/possible] - * - * Set delUser capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param array $users - * @return int number of users deleted - */ - public function deleteUsers($users) { - msg("authorisation method does not allow deleting of users", -1); - return 0; - } - - /** - * Return a count of the number of user which meet $filter criteria - * [should be implemented whenever retrieveUsers is implemented] - * - * Set getUserCount capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param array $filter array of field/pattern pairs, empty array for no filter - * @return int - */ - public function getUserCount($filter = array()) { - msg("authorisation method does not provide user counts", -1); - return 0; - } - - /** - * Bulk retrieval of user data [implement only where required/possible] - * - * Set getUsers capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param int $start index of first user to be returned - * @param int $limit max number of users to be returned, 0 for unlimited - * @param array $filter array of field/pattern pairs, null for no filter - * @return array list of userinfo (refer getUserData for internal userinfo details) - */ - public function retrieveUsers($start = 0, $limit = 0, $filter = null) { - msg("authorisation method does not support mass retrieval of user data", -1); - return array(); - } - - /** - * Define a group [implement only where required/possible] - * - * Set addGroup capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param string $group - * @return bool - */ - public function addGroup($group) { - msg("authorisation method does not support independent group creation", -1); - return false; - } - - /** - * Retrieve groups [implement only where required/possible] - * - * Set getGroups capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param int $start - * @param int $limit - * @return array - */ - public function retrieveGroups($start = 0, $limit = 0) { - msg("authorisation method does not support group list retrieval", -1); - return array(); - } - - /** - * Return case sensitivity of the backend [OPTIONAL] - * - * When your backend is caseinsensitive (eg. you can login with USER and - * user) then you need to overwrite this method and return false - * - * @return bool - */ - public function isCaseSensitive() { - return true; - } - - /** - * Sanitize a given username [OPTIONAL] - * - * This function is applied to any user name that is given to - * the backend and should also be applied to any user name within - * the backend before returning it somewhere. - * - * This should be used to enforce username restrictions. - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user username - * @return string the cleaned username - */ - public function cleanUser($user) { - return $user; - } - - /** - * Sanitize a given groupname [OPTIONAL] - * - * This function is applied to any groupname that is given to - * the backend and should also be applied to any groupname within - * the backend before returning it somewhere. - * - * This should be used to enforce groupname restrictions. - * - * Groupnames are to be passed without a leading '@' here. - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $group groupname - * @return string the cleaned groupname - */ - public function cleanGroup($group) { - return $group; - } - - /** - * Check Session Cache validity [implement only where required/possible] - * - * DokuWiki caches user info in the user's session for the timespan defined - * in $conf['auth_security_timeout']. - * - * This makes sure slow authentication backends do not slow down DokuWiki. - * This also means that changes to the user database will not be reflected - * on currently logged in users. - * - * To accommodate for this, the user manager plugin will touch a reference - * file whenever a change is submitted. This function compares the filetime - * of this reference file with the time stored in the session. - * - * This reference file mechanism does not reflect changes done directly in - * the backend's database through other means than the user manager plugin. - * - * Fast backends might want to return always false, to force rechecks on - * each page load. Others might want to use their own checking here. If - * unsure, do not override. - * - * @param string $user - The username - * @author Andreas Gohr <andi@splitbrain.org> - * @return bool - */ - public function useSessionCache($user) { - global $conf; - return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'].'/sessionpurge')); - } -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/cli.php b/lib/plugins/cli.php index 721f54779..a3cbec722 100644 --- a/lib/plugins/cli.php +++ b/lib/plugins/cli.php @@ -1,11 +1,2 @@ <?php - -/** - * Base class for CLI plugins - * - * Provides DokuWiki plugin functionality on top of phpcli - */ -abstract class DokuWiki_CLI_Plugin extends \splitbrain\phpcli\CLI implements DokuWiki_PluginInterface { - use DokuWiki_PluginTrait; - -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/remote.php b/lib/plugins/remote.php index d63f82aee..a3cbec722 100644 --- a/lib/plugins/remote.php +++ b/lib/plugins/remote.php @@ -1,107 +1,2 @@ <?php - -use dokuwiki\Remote\Api; - -/** - * Class DokuWiki_Remote_Plugin - */ -abstract class DokuWiki_Remote_Plugin extends DokuWiki_Plugin { - - private $api; - - /** - * Constructor - */ - public function __construct() { - $this->api = new Api(); - } - - /** - * Get all available methods with remote access. - * - * 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 dokuwiki\Remote\RemoteAPI}. - * @throws ReflectionException - */ - 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 Api - */ - protected function getApi() { - return $this->api; - } - -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/syntax.php b/lib/plugins/syntax.php index b74bb5bf0..a3cbec722 100644 --- a/lib/plugins/syntax.php +++ b/lib/plugins/syntax.php @@ -1,123 +1,2 @@ <?php -/** - * Syntax Plugin Prototype - * - * All DokuWiki plugins to extend the parser/rendering mechanism - * need to inherit from this class - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Andreas Gohr <andi@splitbrain.org> - */ -abstract class DokuWiki_Syntax_Plugin extends \dokuwiki\Parsing\ParserMode\Plugin { - use DokuWiki_PluginTrait; - - protected $allowedModesSetup = false; - - /** - * Syntax Type - * - * Needs to return one of the mode types defined in $PARSER_MODES in Parser.php - * - * @return string - */ - abstract public function getType(); - - /** - * Allowed Mode Types - * - * Defines the mode types for other dokuwiki markup that maybe nested within the - * plugin's own markup. Needs to return an array of one or more of the mode types - * defined in $PARSER_MODES in Parser.php - * - * @return array - */ - public function getAllowedTypes() { - return array(); - } - - /** - * Paragraph Type - * - * Defines how this syntax is handled regarding paragraphs. This is important - * for correct XHTML nesting. Should return one of the following: - * - * 'normal' - The plugin can be used inside paragraphs - * 'block' - Open paragraphs need to be closed before plugin output - * 'stack' - Special case. Plugin wraps other paragraphs. - * - * @see Doku_Handler_Block - * - * @return string - */ - public function getPType(){ - return 'normal'; - } - - /** - * Handler to prepare matched data for the rendering process - * - * This function can only pass data to render() via its return value - render() - * may be not be run during the object's current life. - * - * Usually you should only need the $match param. - * - * @param string $match The text matched by the patterns - * @param int $state The lexer state for the match - * @param int $pos The character position of the matched text - * @param Doku_Handler $handler The Doku_Handler object - * @return bool|array Return an array with all data you want to use in render, false don't add an instruction - */ - abstract public function handle($match, $state, $pos, Doku_Handler $handler); - - /** - * Handles the actual output creation. - * - * The function must not assume any other of the classes methods have been run - * during the object's current life. The only reliable data it receives are its - * parameters. - * - * The function should always check for the given output format and return false - * when a format isn't supported. - * - * $renderer contains a reference to the renderer object which is - * currently handling the rendering. You need to use it for writing - * the output. How this is done depends on the renderer used (specified - * by $format - * - * The contents of the $data array depends on what the handler() function above - * created - * - * @param string $format output format being rendered - * @param Doku_Renderer $renderer the current renderer object - * @param array $data data created by handler() - * @return boolean rendered correctly? (however, returned value is not used at the moment) - */ - abstract public function render($format, Doku_Renderer $renderer, $data); - - /** - * There should be no need to override this function - * - * @param string $mode - * @return bool - */ - public function accepts($mode) { - - if (!$this->allowedModesSetup) { - global $PARSER_MODES; - - $allowedModeTypes = $this->getAllowedTypes(); - foreach($allowedModeTypes as $mt) { - $this->allowedModes = array_merge($this->allowedModes, $PARSER_MODES[$mt]); - } - - $idx = array_search(substr(get_class($this), 7), (array) $this->allowedModes); - if ($idx !== false) { - unset($this->allowedModes[$idx]); - } - $this->allowedModesSetup = true; - } - - return parent::accepts($mode); - } -} -//Setup VIM: ex: et ts=4 : +dbg_deprecated('Autoloading. Do not require() files yourself.'); |