Jgoettlich has uploaded a new change for review. https://gerrit.wikimedia.org/r/192322
Change subject: Added new global for better permission config ...................................................................... Added new global for better permission config *$bsgPermissionConfig is for adding some configs to every permission *in registerPermission I set check if a permission has the "type" set, if not I set a default one. Change-Id: I44787c6f5e4ec1161ff08735f86f499f96b346bc --- M includes/Core.class.php M includes/DefaultSettings.php 2 files changed, 878 insertions(+), 770 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/BlueSpiceFoundation refs/changes/22/192322/1 diff --git a/includes/Core.class.php b/includes/Core.class.php index a587010..02bbb99 100644 --- a/includes/Core.class.php +++ b/includes/Core.class.php @@ -1,771 +1,776 @@ -<?php - -/** - * This file contains the BsCore class. - * - * The BsCore class is the main class of the BlueSpice framework. - * It controlls the whole life sequence of the framework. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * This file is part of BlueSpice for MediaWiki - * For further information visit http://www.blue-spice.org - * - * @author Sebastian Ulbricht <sebastian.ulbri...@dragon-design.hk> - * @author Robert Vogel <vo...@hallowelt.biz> - * @author Stephan Muggli <mug...@hallowelt.biz> - * @package Bluespice_Core - * @copyright Copyright (C) 2014 Hallo Welt! - Medienwerkstatt GmbH, All rights reserved. - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License v2 or later - * @filesource - */ - -/** - * The BsCore - * @package BlueSpice_Core - * @subpackage Core - */ -class BsCore { - - public $aBehaviorSwitches = array(); - - /** - * - * @var array - * @deprecated since version 2.22 - */ - protected $aEditButtons = array(); - - /** - * - * @var array - * @deprecated since version 2.22 - */ - protected $aEditButtonRanking = array(); - - /** - * Array of illegal chars in article title - * @var array - */ - protected static $prForbiddenCharsInArticleTitle = array( '#', '<', '>', '[', ']', '|', '{', '}' ); - /** - * an array of adapter instances - * @var array - */ - protected static $oInstance = null; - /** - * a state flag if ExtJs is already loaded - * @var bool - * @deprecated since version 2.22 - */ - protected static $bExtJsLoaded = false; - /** - * holds the requested URI after the first time, the method getRequestURI was running - * @var string - */ - protected static $prRequestUri = null; - /** - * a state flag if the requested URL is encodet - * @var bool - */ - protected static $prUrlIsEncoded = false; - /** - * Local Parser - * @var object - */ - protected static $oLocalParser = false; - /** - * Local Parser - * @var object - */ - protected static $oLocalParserOptions = false; - /** - * Current User Object - * @var object - */ - protected static $prCurrentUser = null; - /** - * Simple caching mechanism for UserMiniProfiles - * @var array - */ - protected static $aUserMiniProfiles = array(); - - protected static $aClientScriptBlocks = array(); - - protected static $bHtmlFormClassLoaded = false; - - /** - * The constructor is protected because of the singleton pattern. - */ - protected function __construct() { - wfProfileIn('Performance: ' . __METHOD__); - global $wgScriptPath; - $sPath = $wgScriptPath . "/extensions/BlueSpiceFoundation/resources/bluespice/images/"; - - $aFiles = array( 'doc', 'docx', 'pdf', 'xls', 'xlsx' ); - $aImages = array( 'png', 'gif', 'jpg', 'jpeg' ); - BsConfig::registerVar( 'MW::FileExtensions', $aFiles, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_ARRAY_STRING, 'bs-pref-fileextensions', 'multiselectplusadd' ); - BsConfig::registerVar( 'MW::ImageExtensions', $aImages, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_ARRAY_STRING, 'bs-pref-imageextensions', 'multiselectplusadd' ); - BsConfig::registerVar( 'MW::LogoPath', $sPath . 'bs-logo.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-logopath' ); - BsConfig::registerVar( 'MW::FaviconPath', $sPath . 'favicon.ico', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-faviconpath' ); - BsConfig::registerVar( 'MW::DefaultUserImage', $sPath . 'bs-user-default-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-defaultuserimage' ); - BsConfig::registerVar( 'MW::MiniProfileEnforceHeight', true, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_BOOL, 'bs-pref-miniprofileenforceheight', 'toggle' ); - BsConfig::registerVar( 'MW::AnonUserImage', $sPath . 'bs-user-anon-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-anonuserimage' ); - BsConfig::registerVar( 'MW::DeletedUserImage', $sPath . 'bs-user-deleted-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-deleteduserimage' ); - BsConfig::registerVar( 'MW::UserImage', '', BsConfig::LEVEL_USER | BsConfig::TYPE_STRING | BsConfig::NO_DEFAULT, 'bs-authors-profileimage' ); - BsConfig::registerVar( 'MW::PingInterval', 10, BsConfig::LEVEL_PUBLIC | BsConfig::RENDER_AS_JAVASCRIPT | BsConfig::TYPE_INT, 'bs-pref-bspinginterval' ); - BsConfig::registerVar( 'MW::SortAlph', false, BsConfig::LEVEL_PUBLIC | BsConfig::LEVEL_USER | BsConfig::TYPE_BOOL, 'bs-pref-sortalph', 'toggle' ); - BsConfig::registerVar( 'MW::TestMode', false, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_BOOL, 'bs-pref-testmode', 'toggle' ); - - BsConfig::set( 'MW::ApplicationContext', 'Wiki' ); - wfProfileOut('Performance: ' . __METHOD__); - } - - public static function getForbiddenCharsInArticleTitle() { - return self::$prForbiddenCharsInArticleTitle; - } - - /** - * Used to access the singleton BlueSpice object. - * @return BsCore Singleton instance of BlueSpice object. - */ - public static function getInstance() { - wfProfileIn('Performance: ' . __METHOD__); - if ( self::$oInstance === null ) { - self::$oInstance = new BsCore(); - } - wfProfileOut('Performance: ' . __METHOD__); - return self::$oInstance; - } - - /** - * When retrieving data from sources different from the BsCore::getParam() - * method, use this interface to sanitize the value. For security reasons it - * is strongly recommended to use this method! - * @param mixed $handover The value that has to be sanitized. - * @param mixed $default A default value that gets returned, if the - * submitted value is not valid or does not match the requested BsPARAMTYPE. - * @param BsPARAMTYPE $options Sets the type of the expected return value. - * This information is used for proper sanitizing. - * @return mixed Depending on the BsPARAMTYPE sumbitted in $options the - * sanitized $handover or in case of invalidity of $handover, the $default - * value. - */ - public static function sanitize($handover, $default = false, $options = BsPARAMTYPE::STRING) { - // TODO MRG20100725: Ist die Reihenfolge hier überlegt? Was ist, wenn ich BsPARAMTYPE::INT & BsPARAMTYPE::STRING angebe? - // TODO MRG20100725: Kann man das nicht mit getParam zusammenschalten, so dass diese Funktion sanitize verwendet? - // TODO MRG20100725: Sollte $default nicht auch durch den sanitizer? - /* Lilu: - * Die Reihenfolge ist meiner Meinung nach unerheblich, da immer nur der erste BsPARAMTYPE, der einen Treffer landet, - * zurückgegeben wird. - * Eine Trennung zwischen getParam und sanitize besteht, da man bei getParam angeben kann, ob man im Fehlerfall - * Default-Werte verwenden möchte oder versucht werden soll, die Daten mit sanitize zu bereinigen. - * Ich denke, das jeder Programmierer seinen Extensions passende Default-Werte liefern sollte. - * Beim Sanitizen der Default-Werte entsteht sonst ggf. das Problem, das wir keinen gültigen Wert zurückgeben können. (null?) - * Das würde einen großen Vorteil des Sanitizers (die nicht mehr benötigte Gültigkeitsprüfung) wieder aushebeln. - */ - if ( $options & BsPARAMTYPE::RAW ) { - return $handover; - } - if ( $options & BsPARAMTYPE::ARRAY_MIXED ) { - if ( is_array( $handover ) ) { - return $handover; - } - return array( $handover ); - } - if ( $options & BsPARAMTYPE::NUMERIC ) { - if ( is_numeric( $handover ) ) { - return $handover; - } - return floatval( $handover ); - } - if ( $options & BsPARAMTYPE::INT ) { - if ( is_int( $handover ) ) { - return $handover; - } - return intval( $handover ); - } - if ( $options & BsPARAMTYPE::FLOAT ) { - if ( is_float( $handover ) ) { - return $handover; - } - return floatval( $handover ); - } - if ( $options & BsPARAMTYPE::BOOL ) { - if ( $handover == 'false' || $handover == '0' || $handover == '' ) { - $handover = false; - } - if ( $handover == 'true' || $handover == '1' ) { - $handover = true; - } - if ( is_bool( $handover ) ) { - return $handover; - } - return (bool)$handover; - } - if ( $options & BsPARAMTYPE::STRING ) { - if ( is_string( $handover ) ) { - if ( $options & BsPARAMOPTION::CLEANUP_STRING ) { - return addslashes( strip_tags( $handover ) ); - } - return $handover; - } - } - if ( $options & BsPARAMTYPE::SQL_STRING ) { - if ( is_string( $handover ) ) { - $oDb = wfGetDB( DB_SLAVE ); - // Use database specific escape methods - $handover = $oDb->strencode( $handover ); - - return $handover; - } - } - if ( $options & BsPARAMTYPE::ARRAY_NUMERIC && is_array( $handover ) ) { - foreach ( $handover as $k => $v ) { - if ( !is_numeric( $v ) ) { - $handover[$k] = null; - } - } - return $handover; - } - if ( $options & BsPARAMTYPE::ARRAY_INT && is_array( $handover ) ) { - foreach ( $handover as $key => $v ) { - if ( !is_int( $v ) ) { - $handover[$key] = null; - } - } - return $handover; - } - if ( $options & BsPARAMTYPE::ARRAY_FLOAT && is_array( $handover ) ) { - foreach ( $handover as $key => $v ) { - if ( !is_float( $v ) ) { - $handover[$key] = null; - } - } - return $handover; - } - if ( $options & BsPARAMTYPE::ARRAY_BOOL && is_array( $handover ) ) { - foreach ($handover as $key => $v) { - if (!is_bool($v)) { - $handover[$key] = null; - } - } - return $handover; - } - if ( $options & BsPARAMTYPE::ARRAY_STRING && is_array( $handover ) ) { - foreach ( $handover as $key => $v ) { - if ( !is_string( $v ) ) { - $handover[$key] = null; - } - } - return $handover; - } - // TODO MRG20100725: Ich halte eine Option TRIM / TRIMRIGHT / TRIMLEFT für sinnvoll. - // TODO MRG20100725: Ebenso HTMLENTITIES etc, wie unten beschrieben. - return $default; - /* - * Development Notes: - * further functions to think about: - * - htmlentieties() um die HTML Eingaben abzufangen - * => html_entity_decode() um die Umwandlung rückgängig zu machen - * - htmlspecialchars() - Wandelt Sonderzeichen in HTML-Codes um - * ==> neither htmlentities() nor htmlspecialchars() are used in directory bluespice-mw or beyond (exc. GeSHi) - * - escapeshellcmd() - * - escapeshellarg() - * ==> Only used in Rss/extlib/Snoopy.class.inc and GeSHi - * - * Alternate options - * HTML Purifier : http://htmlpurifier.org/ - * Popoon: http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php - */ - } - - /** - * When retrieving data from sources different from the BsCore::getParam() - * method, use this interface to sanitize an array. For security reasons it - * is strongly recommended to use this method! - * @param array $array The array that has to be sanitized. - * @param array $default A default array that gets returned, if the - * submitted array is not valid or does not match the requested BsPARAMTYPE. - * @param BsPARAMTYPE $options Sets the type of the expected return value. - * This information is used for proper sanitizing. - * @return array Depending on the BsPARAMTYPE sumbitted in $options the - * sanitized $array or in case of invalidity of $array, the $default - * array. - */ - public static function sanitizeArrayEntry($array, $key, $default = null, $options = null) { - // TODO MRG20100725: Sollte $default nicht auch durch den sanitizer? - if (!is_array($array)) { - return $default; - } - if (!isset($array[$key])) { - return $default; - } - return self::sanitize($array[$key], $default, $options); - } - - public static function doInitialise() { - wfProfileIn('Performance: ' . __METHOD__ . ' - Initialize Core'); - self::$oInstance = new BsCore(); - wfProfileOut('Performance: ' . __METHOD__ . ' - Initialize Core'); - - wfProfileIn('Performance: ' . __METHOD__ . ' - Load Settings'); - if ( !defined( 'DO_MAINTENANCE' ) ) { - BsConfig::loadSettings(); - } - wfProfileOut('Performance: ' . __METHOD__ . ' - Load Settings'); - - wfProfileIn('Performance: ' . __METHOD__ . ' - Load and initialize all Extensions'); - BsExtensionManager::includeExtensionFiles( self::$oInstance ); - wfProfileOut('Performance: ' . __METHOD__ . ' - Load and initialize all Extensions'); - - global $wgHooks; - $wgHooks['ArticleAfterFetchContent'][] = array( self::$oInstance, 'behaviorSwitches' ); - $wgHooks['ParserBeforeStrip'][] = array( self::$oInstance, 'hideBehaviorSwitches' ); - $wgHooks['ParserBeforeTidy'][] = array( self::$oInstance, 'recoverBehaviorSwitches' ); - - array_unshift( - $wgHooks['EditPage::showEditForm:initial'], - array( self::$oInstance, 'lastChanceBehaviorSwitches' ) - ); - - //TODO: This does not seem to be the right place for stuff like this. - global $wgFileExtensions; - $aFileExtensions = BsConfig::get( 'MW::FileExtensions' ); - $aImageExtensions = BsConfig::get( 'MW::ImageExtensions' ); - $wgFileExtensions = array_merge( $aFileExtensions, $aImageExtensions ); - $wgFileExtensions = array_values( array_unique( $wgFileExtensions ) ); - } - - /* Returns the filesystem path of the core installation - * @return String Filesystempath to the core installation - */ - - public static function getFileSystemPath() { - return BSROOTDIR; - } - - // todo msc 2011-04-27 wiederholter Aufruf führt schnell zu einem Speicherüberlauf (>128MB bei Indexierung) - // scheinbar wird ausserhalb der Methode gecacht! Aufruf mit adapter->parseWikiText($text, true) schafft KEINE Abhilfe. - public function parseWikiText( $sText, $oTitle, $nocache = false, $numberheadings = null ) { - wfProfileIn('BS::' . __METHOD__); - - if ( !self::$oLocalParser ) self::$oLocalParser = new Parser(); - if ( !self::$oLocalParserOptions ) self::$oLocalParserOptions = new ParserOptions(); - - if ( $numberheadings === false ) { - self::$oLocalParserOptions->setNumberHeadings( false ); - } elseif ( $numberheadings === true ) { - self::$oLocalParserOptions->setNumberHeadings( true ); - } - - // TODO MRG20110707: Check it this cannot be unified - - if ( $nocache ) self::$oLocalParser->disableCache(); - - if ( !( $oTitle instanceof Title ) ) return ''; - - $output = self::$oLocalParser->parse( $sText, $oTitle, self::$oLocalParserOptions, true )->getText(); - - wfProfileOut('BS::' . __METHOD__); - return $output; - } - - public static function getUserDisplayName( $oUser = null ) { - wfProfileIn( 'BS::'.__METHOD__ ); - global $wgUser; - if ( $oUser === null ) { - $oUser = $wgUser; - } - if ( !( $oUser instanceof User ) ) { - wfProfileOut( 'BS::'.__METHOD__ ); - return false; - } - $sRealname = $oUser->getRealName(); - if ( $sRealname ) { - wfProfileOut( 'BS::'.__METHOD__ ); - return $sRealname; - } else { - wfProfileOut( 'BS::'.__METHOD__ ); - return $oUser->getName(); - } - } - - /** - * Determines the request URI for Apache and IIS - * - * @param bool $getUrlEncoded set to true to get URI url encoded - * @return string the requested URI - */ - public static function getRequestURI($getUrlEncoded = false) { - wfProfileIn( 'BS::'.__METHOD__ ); - if (self::$prRequestUri === null) { - $requestUri = ''; - if ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) { // check this first so IIS will catch - $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; - } elseif ( isset( $_SERVER['REQUEST_URI'] ) ) { - $requestUri = $_SERVER['REQUEST_URI']; - } elseif ( isset( $_SERVER['ORIG_PATH_INFO'] ) ) { // IIS 5.0, PHP as CGI - $requestUri = $_SERVER['ORIG_PATH_INFO']; - if ( !empty( $_SERVER['QUERY_STRING'] ) ) { - $requestUri .= '?' . $_SERVER['QUERY_STRING']; - } - } - self::$prRequestUri = $requestUri; - self::$prUrlIsEncoded = ( urldecode( self::$prRequestUri ) != self::$prRequestUri ); - } - if ( $getUrlEncoded ) { - return ( self::$prUrlIsEncoded ? self::$prRequestUri : urlencode( self::$prRequestUri ) ); - } - wfProfileOut( 'BS::'.__METHOD__ ); - return ( self::$prUrlIsEncoded ? urldecode( self::$prRequestUri ) : self::$prRequestUri ); - } - - // TODO MRG (09.12.10 11:21): Habe silent im Standard auf true gesetzt. Echo ist ohnehin nicht gut. - /** - * - * @param string $sPermission - * @param string $sI18NInstanceKey - * @param string $sI18NMessageKey - * @param bool $bSilent - * @return bool - */ - public static function checkAccessAdmission( $sPermission = 'read', $sI18NInstanceKey = 'BlueSpice', $sI18NMessageKey = 'not_allowed', $bSilent = true ) { - wfProfileIn('BS::' . __METHOD__); - // TODO MRG28072010: isAllowed prüft nicht gegen die Artikel. D.H. die Rechte sind nicht per Namespace überprüfbar - $oUser = self::loadCurrentUser(); - if ( $oUser->isAllowed( $sPermission ) ) { - wfProfileOut('BS::' . __METHOD__); - return true; - } - if ( !$bSilent ) echo wfMessage( 'bs-' . $sI18NMessageKey )->plain(); - - wfProfileOut('BS::' . __METHOD__); - return false; - } - - public static function loadCurrentUser() { - wfProfileIn('BS::' . __METHOD__); - /* Load current user */ - global $wgUser; - - if ( !$wgUser || is_null( $wgUser->mId ) ) { - - if ( !is_null( self::$prCurrentUser ) ) { - wfProfileOut('BS::' . __METHOD__); - return self::$prCurrentUser; - } - - self::$prCurrentUser = User::newFromSession(); - self::$prCurrentUser->load(); - wfProfileOut('BS::' . __METHOD__); - return self::$prCurrentUser; - } - - wfProfileOut('BS::' . __METHOD__); - return $wgUser; - // Used to bie like the following code. however, this did not take into account the __session-Cookie, and logged out users were still recognized. - /* if( isset( $_SESSION['wsUserID'] ) ) { - self::$prCurrentUser = User::newFromId( $_SESSION['wsUserID'] ); // object created but not loaded from DB - self::$prCurrentUser->loadFromId(); // get from DB or MemCache - return self::$prCurrentUser; - } - return new User(); //anonymous - */ - } - - /** - * Creates a miniprofile for a user. It consists if the useres profile image - * and links to his userpage. In future versions it should also have a - * little menu with his mail adress, and other profile information. - * @param User $oUser The requested MediaWiki User object - * @param array $aParams The settings array for the mini profile view object - * @return ViewUserMiniProfile A view with the users mini profile - */ - public function getUserMiniProfile( $oUser, $aParams = array() ) { - wfProfileIn('BS::' . __METHOD__); - $sParamsHash = md5( serialize( $aParams ) ); - $sViewHash = $oUser->getName() . $sParamsHash; - - if ( isset( self::$aUserMiniProfiles[$sViewHash] ) ) { - wfProfileOut('BS::' . __METHOD__); - return self::$aUserMiniProfiles[$sViewHash]; - } - - $oUserMiniProfileView = new ViewUserMiniProfile(); - $oUserMiniProfileView->setOptions( $aParams ); - $oUserMiniProfileView->setOption( 'user', $oUser ); - - wfRunHooks( 'BSCoreGetUserMiniProfileBeforeInit', array( &$oUserMiniProfileView, &$oUser, &$aParams ) ); - - $oUserMiniProfileView->init(); - - self::$aUserMiniProfiles[$sViewHash] = $oUserMiniProfileView; - - wfProfileOut('BS::' . __METHOD__); - return $oUserMiniProfileView; - } - - /** - * Registers a permission with the MediaWiki Framework. - * object for proper internationalisation of your permission. Every - * permission is granted automatically to the user group 'sysop'. You can - * specify additional groups through the third parameter. - * @param String $sPermissionName I.e. 'myextension-dosomething' - * @param Array $aUserGroups User groups that get preinitialized with the new - * pemission. I.e. array( 'user', 'bureaucrats' ) - * @return void - */ - public function registerPermission( $sPermissionName, $aUserGroups = array() ) { - // TODO MRG (05.02.11 19:24): @Sebastian Ist der dritte Parameter im PermissionsManager berücksichtigt? - wfProfileIn('BS::' . __METHOD__); - - global $wgGroupPermissions, $wgAvailableRights; - $wgGroupPermissions['sysop'][$sPermissionName] = true; - - foreach ( $aUserGroups as $sGroup ) { - if ( !isset( $wgGroupPermissions[$sGroup][$sPermissionName] ) ) { - $wgGroupPermissions[$sGroup][$sPermissionName] = true; - } - } - - $wgAvailableRights[] = $sPermissionName; - - wfProfileOut('BS::' . __METHOD__); - } - - /** - * Register a callback for a MagicWord - * @param string $sMagicWord The MagicWord in upper case and without - * surrounding double underscores. OR: if $callback == null this may be a - * lower case identifier that gets written to the page_props table by the - * parser. - * @param callable $aCallback or null to use MediaWiki page_props mechanism - */ - public function registerBehaviorSwitch( $sMagicWord, $aCallback = null ) { - if ( is_callable( $aCallback ) ) { - $this->aBehaviorSwitches[$sMagicWord] = $aCallback; - } elseif ( !isset( MagicWord::$mDoubleUnderscoreIDs[$sMagicWord] ) ) { - MagicWord::$mDoubleUnderscoreIDs[] = $sMagicWord; - } - } - - /** - * Hook-handler for "ArticleAfterFetchContent" - * @param WikiPage $article - * @param string $content - * @return boolean Always true to keep hook running - */ - public function behaviorSwitches( &$article, &$content ) { - if ( !isset( $this->aBehaviorSwitches ) ) { - return true; - } - - $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $content ); - foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { - if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { - call_user_func( $sCallback ); - } - } - return true; - } - - /** - * Hook-handler for "ParserBeforeStrip" - * @param Parser $parser - * @param string $text - * @return boolean Always true to keep hook running - * @deprecated since version 2.22 - */ - public function hideBehaviorSwitches( &$parser, &$text ) { - if ( !isset( $this->aBehaviorSwitches ) ) { - return true; - } - - $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $text ); - foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { - if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { - call_user_func( $sCallback ); - } - - $text = preg_replace( "/(<nowiki>.*?)__{$sSwitch}__(.*?<\/nowiki>)/i", "$1@@{$sSwitch}@@$2", $text ); - } - return true; - } - - /** - * Hook-handler for "ParserBeforeTidy" - * @param Parser $parser - * @param string $text - * @return boolean Always true to keep hook running - * @deprecated since version 2.22 - */ - public function recoverBehaviorSwitches( &$parser, &$text ) { - if ( !isset( $this->aBehaviorSwitches ) ) { - return true; - } - - foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { - $text = str_replace( '__' . $sSwitch . '__', "", $text ); - $text = preg_replace( "/@@" . $sSwitch . "@@/", '__' . $sSwitch . '__', $text ); - } - return true; - } - - /** - * Hook-handler for "EditPage::showEditForm:initial" - * Needed for edit and sumbit (preview) mode - * @param EditPage $editPage - * @return boolean Always true to keep hook running - */ - public function lastChanceBehaviorSwitches( $editPage ) { - // TODO SW(05.01.12 15:39): Profiling - $sContent = BsPageContentProvider::getInstance()->getContentFromTitle( RequestContext::getMain()->getTitle() ); - if ( !isset( $this->aBehaviorSwitches ) ) return true; - - $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $sContent ); - foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { - if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { - call_user_func( $sCallback ); - } - } - // TODO: This note should be displayed when the editor is deactivated - //$editPage->editFormTextTop = "Der Editor wurde deaktiviert <br/>"; - if ( isset( $editPage->textbox1 ) ) { - foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { - $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $editPage->textbox1 ); - if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { - call_user_func( $sCallback ); - } - } - } - return true; - } - - /** - * Handles requests to the BS-AJAX-PING-BUS (BSAPB) - * TODO: Move to seperate class - * @return String JSON encoded data - */ - public static function ajaxBSPing() { - $aResult = array( - "success" => false, - "errors" => array(), - "message" => '', - ); - - $oRequest = RequestContext::getMain()->getRequest(); - $iArticleId = $oRequest->getInt( 'iArticleID', 0 ); - $iNamespace = $oRequest->getInt( 'iNamespace', 0 ); - $sTitle = $oRequest->getVal( 'sTitle', '' ); - $iRevision = $oRequest->getInt( 'iRevision', 0 ); - $aBSPingData = $oRequest->getArray( 'BsPingData', array() ); - - $aResult['success'] = true; - foreach ( $aBSPingData as $aSinglePing ) { - if ( empty( $aSinglePing['sRef'] ) ) continue; - if ( !$aResult['success'] ) break; - - if ( !isset( $aSinglePing['aData'] ) ) - $aSinglePing['aData'] = array(); - - $aSingleResult = array( - "success" => false, - "errors" => array(), - "message" => '', - ); - //if hook returns false - overall success is false - $aResult['success'] = wfRunHooks( 'BsAdapterAjaxPingResult', - array( $aSinglePing['sRef'], $aSinglePing['aData'], - $iArticleId, $sTitle, $iNamespace, $iRevision, - &$aSingleResult ) - ); - $aResult[$aSinglePing['sRef']] = $aSingleResult; - } - - return FormatJson::encode( $aResult ); - } - - /** - * Make the page being parsed have a dependency on $page via the templatelinks table. - * http://www.mediawiki.org/wiki/Manual:Tag_extensions#Regenerating_the_page_when_another_page_is_edited - * @param Parser $oParser - * @param String $sTitle - */ - public static function addTemplateLinkDependencyByText($oParser, $sTitle) { - $oTitle = Title::newFromText( $sTitle ); - static::addTemplateLinkDependency($oParser, $oTitle); - } - - /** - * Make the page being parsed have a dependency on $page via the templatelinks table. - * http://www.mediawiki.org/wiki/Manual:Tag_extensions#Regenerating_the_page_when_another_page_is_edited - * @param Parser $oParser - * @param Title $oTitle - */ - public static function addTemplateLinkDependency( $oParser, $oTitle ) { - $oRevision = Revision::newFromTitle( $oTitle ); - $iPageId = $oRevision ? $oRevision->getPage() : 0; - $iRevId = $oRevision ? $oRevision->getId() : 0; - - $oParser->getOutput()->addTemplate( - $oTitle, - $iPageId, - $iRevId - ); // Register dependency in templatelinks - } - - /** - * Returns the MediaWiki include path variable - * @global String $IP MediaWiki include path variable - * @return String MediaWiki include path variable - */ - public static function getMediaWikiIncludePath() { - wfProfileIn('BS::' . __METHOD__); - global $IP; - wfProfileOut('BS::' . __METHOD__); - return str_replace('\\', '/', $IP); - } - - /** - * Returns the filesystempath to the webroot directory in which MediaWiki is installed. - * @global String $wgScriptPath The relative path from the webroot for hyperlinks. - * @return String Webroot directory in which MediaWiki is installed - */ - public static function getMediaWikiWebrootPath() { - global $wgScriptPath; - return str_replace($wgScriptPath, '', self::getMediaWikiIncludePath()); - } - - public static function getClientScriptBlocks() { - return self::$aClientScriptBlocks; - } - - /** - * Use this to place javascript logic _below_ the including script files. Therefore you can benefit from the available frameworks like BlueSpiceFramework, ExtJS and jQuery. - * @param String $sExtensionKey The name of the extension. This is just for creating a nice comment within the script-Tags - * @param String $sCode The JavaScript code, that should be executed after all scriptfiles have been included - * @param String $sUniqueKey (Optional) If provided the script block gets saved in with a unique key and therefore will not be registered multiple times. - * @deprecated Use MediaWikis Outpage interface instead - */ - public static function registerClientScriptBlock( $sExtensionKey, $sCode, $sUniqueKey = '' ) { - wfDeprecated(__METHOD__); - if( !empty( $sUniqueKey ) ) { - self::$aClientScriptBlocks[$sUniqueKey] = array( $sExtensionKey, $sCode ); - } else { - self::$aClientScriptBlocks[] = array( $sExtensionKey, $sCode ); - } - } +<?php + +/** + * This file contains the BsCore class. + * + * The BsCore class is the main class of the BlueSpice framework. + * It controlls the whole life sequence of the framework. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This file is part of BlueSpice for MediaWiki + * For further information visit http://www.blue-spice.org + * + * @author Sebastian Ulbricht <sebastian.ulbri...@dragon-design.hk> + * @author Robert Vogel <vo...@hallowelt.biz> + * @author Stephan Muggli <mug...@hallowelt.biz> + * @package Bluespice_Core + * @copyright Copyright (C) 2014 Hallo Welt! - Medienwerkstatt GmbH, All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License v2 or later + * @filesource + */ + +/** + * The BsCore + * @package BlueSpice_Core + * @subpackage Core + */ +class BsCore { + + public $aBehaviorSwitches = array(); + + /** + * + * @var array + * @deprecated since version 2.22 + */ + protected $aEditButtons = array(); + + /** + * + * @var array + * @deprecated since version 2.22 + */ + protected $aEditButtonRanking = array(); + + /** + * Array of illegal chars in article title + * @var array + */ + protected static $prForbiddenCharsInArticleTitle = array( '#', '<', '>', '[', ']', '|', '{', '}' ); + /** + * an array of adapter instances + * @var array + */ + protected static $oInstance = null; + /** + * a state flag if ExtJs is already loaded + * @var bool + * @deprecated since version 2.22 + */ + protected static $bExtJsLoaded = false; + /** + * holds the requested URI after the first time, the method getRequestURI was running + * @var string + */ + protected static $prRequestUri = null; + /** + * a state flag if the requested URL is encodet + * @var bool + */ + protected static $prUrlIsEncoded = false; + /** + * Local Parser + * @var object + */ + protected static $oLocalParser = false; + /** + * Local Parser + * @var object + */ + protected static $oLocalParserOptions = false; + /** + * Current User Object + * @var object + */ + protected static $prCurrentUser = null; + /** + * Simple caching mechanism for UserMiniProfiles + * @var array + */ + protected static $aUserMiniProfiles = array(); + + protected static $aClientScriptBlocks = array(); + + protected static $bHtmlFormClassLoaded = false; + + /** + * The constructor is protected because of the singleton pattern. + */ + protected function __construct() { + wfProfileIn('Performance: ' . __METHOD__); + global $wgScriptPath; + $sPath = $wgScriptPath . "/extensions/BlueSpiceFoundation/resources/bluespice/images/"; + + $aFiles = array( 'doc', 'docx', 'pdf', 'xls', 'xlsx' ); + $aImages = array( 'png', 'gif', 'jpg', 'jpeg' ); + BsConfig::registerVar( 'MW::FileExtensions', $aFiles, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_ARRAY_STRING, 'bs-pref-fileextensions', 'multiselectplusadd' ); + BsConfig::registerVar( 'MW::ImageExtensions', $aImages, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_ARRAY_STRING, 'bs-pref-imageextensions', 'multiselectplusadd' ); + BsConfig::registerVar( 'MW::LogoPath', $sPath . 'bs-logo.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-logopath' ); + BsConfig::registerVar( 'MW::FaviconPath', $sPath . 'favicon.ico', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-faviconpath' ); + BsConfig::registerVar( 'MW::DefaultUserImage', $sPath . 'bs-user-default-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-defaultuserimage' ); + BsConfig::registerVar( 'MW::MiniProfileEnforceHeight', true, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_BOOL, 'bs-pref-miniprofileenforceheight', 'toggle' ); + BsConfig::registerVar( 'MW::AnonUserImage', $sPath . 'bs-user-anon-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-anonuserimage' ); + BsConfig::registerVar( 'MW::DeletedUserImage', $sPath . 'bs-user-deleted-image.png', BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_STRING, 'bs-pref-deleteduserimage' ); + BsConfig::registerVar( 'MW::UserImage', '', BsConfig::LEVEL_USER | BsConfig::TYPE_STRING | BsConfig::NO_DEFAULT, 'bs-authors-profileimage' ); + BsConfig::registerVar( 'MW::PingInterval', 10, BsConfig::LEVEL_PUBLIC | BsConfig::RENDER_AS_JAVASCRIPT | BsConfig::TYPE_INT, 'bs-pref-bspinginterval' ); + BsConfig::registerVar( 'MW::SortAlph', false, BsConfig::LEVEL_PUBLIC | BsConfig::LEVEL_USER | BsConfig::TYPE_BOOL, 'bs-pref-sortalph', 'toggle' ); + BsConfig::registerVar( 'MW::TestMode', false, BsConfig::LEVEL_PUBLIC | BsConfig::TYPE_BOOL, 'bs-pref-testmode', 'toggle' ); + + BsConfig::set( 'MW::ApplicationContext', 'Wiki' ); + wfProfileOut('Performance: ' . __METHOD__); + } + + public static function getForbiddenCharsInArticleTitle() { + return self::$prForbiddenCharsInArticleTitle; + } + + /** + * Used to access the singleton BlueSpice object. + * @return BsCore Singleton instance of BlueSpice object. + */ + public static function getInstance() { + wfProfileIn('Performance: ' . __METHOD__); + if ( self::$oInstance === null ) { + self::$oInstance = new BsCore(); + } + wfProfileOut('Performance: ' . __METHOD__); + return self::$oInstance; + } + + /** + * When retrieving data from sources different from the BsCore::getParam() + * method, use this interface to sanitize the value. For security reasons it + * is strongly recommended to use this method! + * @param mixed $handover The value that has to be sanitized. + * @param mixed $default A default value that gets returned, if the + * submitted value is not valid or does not match the requested BsPARAMTYPE. + * @param BsPARAMTYPE $options Sets the type of the expected return value. + * This information is used for proper sanitizing. + * @return mixed Depending on the BsPARAMTYPE sumbitted in $options the + * sanitized $handover or in case of invalidity of $handover, the $default + * value. + */ + public static function sanitize($handover, $default = false, $options = BsPARAMTYPE::STRING) { + // TODO MRG20100725: Ist die Reihenfolge hier überlegt? Was ist, wenn ich BsPARAMTYPE::INT & BsPARAMTYPE::STRING angebe? + // TODO MRG20100725: Kann man das nicht mit getParam zusammenschalten, so dass diese Funktion sanitize verwendet? + // TODO MRG20100725: Sollte $default nicht auch durch den sanitizer? + /* Lilu: + * Die Reihenfolge ist meiner Meinung nach unerheblich, da immer nur der erste BsPARAMTYPE, der einen Treffer landet, + * zurückgegeben wird. + * Eine Trennung zwischen getParam und sanitize besteht, da man bei getParam angeben kann, ob man im Fehlerfall + * Default-Werte verwenden möchte oder versucht werden soll, die Daten mit sanitize zu bereinigen. + * Ich denke, das jeder Programmierer seinen Extensions passende Default-Werte liefern sollte. + * Beim Sanitizen der Default-Werte entsteht sonst ggf. das Problem, das wir keinen gültigen Wert zurückgeben können. (null?) + * Das würde einen großen Vorteil des Sanitizers (die nicht mehr benötigte Gültigkeitsprüfung) wieder aushebeln. + */ + if ( $options & BsPARAMTYPE::RAW ) { + return $handover; + } + if ( $options & BsPARAMTYPE::ARRAY_MIXED ) { + if ( is_array( $handover ) ) { + return $handover; + } + return array( $handover ); + } + if ( $options & BsPARAMTYPE::NUMERIC ) { + if ( is_numeric( $handover ) ) { + return $handover; + } + return floatval( $handover ); + } + if ( $options & BsPARAMTYPE::INT ) { + if ( is_int( $handover ) ) { + return $handover; + } + return intval( $handover ); + } + if ( $options & BsPARAMTYPE::FLOAT ) { + if ( is_float( $handover ) ) { + return $handover; + } + return floatval( $handover ); + } + if ( $options & BsPARAMTYPE::BOOL ) { + if ( $handover == 'false' || $handover == '0' || $handover == '' ) { + $handover = false; + } + if ( $handover == 'true' || $handover == '1' ) { + $handover = true; + } + if ( is_bool( $handover ) ) { + return $handover; + } + return (bool)$handover; + } + if ( $options & BsPARAMTYPE::STRING ) { + if ( is_string( $handover ) ) { + if ( $options & BsPARAMOPTION::CLEANUP_STRING ) { + return addslashes( strip_tags( $handover ) ); + } + return $handover; + } + } + if ( $options & BsPARAMTYPE::SQL_STRING ) { + if ( is_string( $handover ) ) { + $oDb = wfGetDB( DB_SLAVE ); + // Use database specific escape methods + $handover = $oDb->strencode( $handover ); + + return $handover; + } + } + if ( $options & BsPARAMTYPE::ARRAY_NUMERIC && is_array( $handover ) ) { + foreach ( $handover as $k => $v ) { + if ( !is_numeric( $v ) ) { + $handover[$k] = null; + } + } + return $handover; + } + if ( $options & BsPARAMTYPE::ARRAY_INT && is_array( $handover ) ) { + foreach ( $handover as $key => $v ) { + if ( !is_int( $v ) ) { + $handover[$key] = null; + } + } + return $handover; + } + if ( $options & BsPARAMTYPE::ARRAY_FLOAT && is_array( $handover ) ) { + foreach ( $handover as $key => $v ) { + if ( !is_float( $v ) ) { + $handover[$key] = null; + } + } + return $handover; + } + if ( $options & BsPARAMTYPE::ARRAY_BOOL && is_array( $handover ) ) { + foreach ($handover as $key => $v) { + if (!is_bool($v)) { + $handover[$key] = null; + } + } + return $handover; + } + if ( $options & BsPARAMTYPE::ARRAY_STRING && is_array( $handover ) ) { + foreach ( $handover as $key => $v ) { + if ( !is_string( $v ) ) { + $handover[$key] = null; + } + } + return $handover; + } + // TODO MRG20100725: Ich halte eine Option TRIM / TRIMRIGHT / TRIMLEFT für sinnvoll. + // TODO MRG20100725: Ebenso HTMLENTITIES etc, wie unten beschrieben. + return $default; + /* + * Development Notes: + * further functions to think about: + * - htmlentieties() um die HTML Eingaben abzufangen + * => html_entity_decode() um die Umwandlung rückgängig zu machen + * - htmlspecialchars() - Wandelt Sonderzeichen in HTML-Codes um + * ==> neither htmlentities() nor htmlspecialchars() are used in directory bluespice-mw or beyond (exc. GeSHi) + * - escapeshellcmd() + * - escapeshellarg() + * ==> Only used in Rss/extlib/Snoopy.class.inc and GeSHi + * + * Alternate options + * HTML Purifier : http://htmlpurifier.org/ + * Popoon: http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php + */ + } + + /** + * When retrieving data from sources different from the BsCore::getParam() + * method, use this interface to sanitize an array. For security reasons it + * is strongly recommended to use this method! + * @param array $array The array that has to be sanitized. + * @param array $default A default array that gets returned, if the + * submitted array is not valid or does not match the requested BsPARAMTYPE. + * @param BsPARAMTYPE $options Sets the type of the expected return value. + * This information is used for proper sanitizing. + * @return array Depending on the BsPARAMTYPE sumbitted in $options the + * sanitized $array or in case of invalidity of $array, the $default + * array. + */ + public static function sanitizeArrayEntry($array, $key, $default = null, $options = null) { + // TODO MRG20100725: Sollte $default nicht auch durch den sanitizer? + if (!is_array($array)) { + return $default; + } + if (!isset($array[$key])) { + return $default; + } + return self::sanitize($array[$key], $default, $options); + } + + public static function doInitialise() { + wfProfileIn('Performance: ' . __METHOD__ . ' - Initialize Core'); + self::$oInstance = new BsCore(); + wfProfileOut('Performance: ' . __METHOD__ . ' - Initialize Core'); + + wfProfileIn('Performance: ' . __METHOD__ . ' - Load Settings'); + if ( !defined( 'DO_MAINTENANCE' ) ) { + BsConfig::loadSettings(); + } + wfProfileOut('Performance: ' . __METHOD__ . ' - Load Settings'); + + wfProfileIn('Performance: ' . __METHOD__ . ' - Load and initialize all Extensions'); + BsExtensionManager::includeExtensionFiles( self::$oInstance ); + wfProfileOut('Performance: ' . __METHOD__ . ' - Load and initialize all Extensions'); + + global $wgHooks; + $wgHooks['ArticleAfterFetchContent'][] = array( self::$oInstance, 'behaviorSwitches' ); + $wgHooks['ParserBeforeStrip'][] = array( self::$oInstance, 'hideBehaviorSwitches' ); + $wgHooks['ParserBeforeTidy'][] = array( self::$oInstance, 'recoverBehaviorSwitches' ); + + array_unshift( + $wgHooks['EditPage::showEditForm:initial'], + array( self::$oInstance, 'lastChanceBehaviorSwitches' ) + ); + + //TODO: This does not seem to be the right place for stuff like this. + global $wgFileExtensions; + $aFileExtensions = BsConfig::get( 'MW::FileExtensions' ); + $aImageExtensions = BsConfig::get( 'MW::ImageExtensions' ); + $wgFileExtensions = array_merge( $aFileExtensions, $aImageExtensions ); + $wgFileExtensions = array_values( array_unique( $wgFileExtensions ) ); + } + + /* Returns the filesystem path of the core installation + * @return String Filesystempath to the core installation + */ + + public static function getFileSystemPath() { + return BSROOTDIR; + } + + // todo msc 2011-04-27 wiederholter Aufruf führt schnell zu einem Speicherüberlauf (>128MB bei Indexierung) + // scheinbar wird ausserhalb der Methode gecacht! Aufruf mit adapter->parseWikiText($text, true) schafft KEINE Abhilfe. + public function parseWikiText( $sText, $oTitle, $nocache = false, $numberheadings = null ) { + wfProfileIn('BS::' . __METHOD__); + + if ( !self::$oLocalParser ) self::$oLocalParser = new Parser(); + if ( !self::$oLocalParserOptions ) self::$oLocalParserOptions = new ParserOptions(); + + if ( $numberheadings === false ) { + self::$oLocalParserOptions->setNumberHeadings( false ); + } elseif ( $numberheadings === true ) { + self::$oLocalParserOptions->setNumberHeadings( true ); + } + + // TODO MRG20110707: Check it this cannot be unified + + if ( $nocache ) self::$oLocalParser->disableCache(); + + if ( !( $oTitle instanceof Title ) ) return ''; + + $output = self::$oLocalParser->parse( $sText, $oTitle, self::$oLocalParserOptions, true )->getText(); + + wfProfileOut('BS::' . __METHOD__); + return $output; + } + + public static function getUserDisplayName( $oUser = null ) { + wfProfileIn( 'BS::'.__METHOD__ ); + global $wgUser; + if ( $oUser === null ) { + $oUser = $wgUser; + } + if ( !( $oUser instanceof User ) ) { + wfProfileOut( 'BS::'.__METHOD__ ); + return false; + } + $sRealname = $oUser->getRealName(); + if ( $sRealname ) { + wfProfileOut( 'BS::'.__METHOD__ ); + return $sRealname; + } else { + wfProfileOut( 'BS::'.__METHOD__ ); + return $oUser->getName(); + } + } + + /** + * Determines the request URI for Apache and IIS + * + * @param bool $getUrlEncoded set to true to get URI url encoded + * @return string the requested URI + */ + public static function getRequestURI($getUrlEncoded = false) { + wfProfileIn( 'BS::'.__METHOD__ ); + if (self::$prRequestUri === null) { + $requestUri = ''; + if ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) { // check this first so IIS will catch + $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; + } elseif ( isset( $_SERVER['REQUEST_URI'] ) ) { + $requestUri = $_SERVER['REQUEST_URI']; + } elseif ( isset( $_SERVER['ORIG_PATH_INFO'] ) ) { // IIS 5.0, PHP as CGI + $requestUri = $_SERVER['ORIG_PATH_INFO']; + if ( !empty( $_SERVER['QUERY_STRING'] ) ) { + $requestUri .= '?' . $_SERVER['QUERY_STRING']; + } + } + self::$prRequestUri = $requestUri; + self::$prUrlIsEncoded = ( urldecode( self::$prRequestUri ) != self::$prRequestUri ); + } + if ( $getUrlEncoded ) { + return ( self::$prUrlIsEncoded ? self::$prRequestUri : urlencode( self::$prRequestUri ) ); + } + wfProfileOut( 'BS::'.__METHOD__ ); + return ( self::$prUrlIsEncoded ? urldecode( self::$prRequestUri ) : self::$prRequestUri ); + } + + // TODO MRG (09.12.10 11:21): Habe silent im Standard auf true gesetzt. Echo ist ohnehin nicht gut. + /** + * + * @param string $sPermission + * @param string $sI18NInstanceKey + * @param string $sI18NMessageKey + * @param bool $bSilent + * @return bool + */ + public static function checkAccessAdmission( $sPermission = 'read', $sI18NInstanceKey = 'BlueSpice', $sI18NMessageKey = 'not_allowed', $bSilent = true ) { + wfProfileIn('BS::' . __METHOD__); + // TODO MRG28072010: isAllowed prüft nicht gegen die Artikel. D.H. die Rechte sind nicht per Namespace überprüfbar + $oUser = self::loadCurrentUser(); + if ( $oUser->isAllowed( $sPermission ) ) { + wfProfileOut('BS::' . __METHOD__); + return true; + } + if ( !$bSilent ) echo wfMessage( 'bs-' . $sI18NMessageKey )->plain(); + + wfProfileOut('BS::' . __METHOD__); + return false; + } + + public static function loadCurrentUser() { + wfProfileIn('BS::' . __METHOD__); + /* Load current user */ + global $wgUser; + + if ( !$wgUser || is_null( $wgUser->mId ) ) { + + if ( !is_null( self::$prCurrentUser ) ) { + wfProfileOut('BS::' . __METHOD__); + return self::$prCurrentUser; + } + + self::$prCurrentUser = User::newFromSession(); + self::$prCurrentUser->load(); + wfProfileOut('BS::' . __METHOD__); + return self::$prCurrentUser; + } + + wfProfileOut('BS::' . __METHOD__); + return $wgUser; + // Used to bie like the following code. however, this did not take into account the __session-Cookie, and logged out users were still recognized. + /* if( isset( $_SESSION['wsUserID'] ) ) { + self::$prCurrentUser = User::newFromId( $_SESSION['wsUserID'] ); // object created but not loaded from DB + self::$prCurrentUser->loadFromId(); // get from DB or MemCache + return self::$prCurrentUser; + } + return new User(); //anonymous + */ + } + + /** + * Creates a miniprofile for a user. It consists if the useres profile image + * and links to his userpage. In future versions it should also have a + * little menu with his mail adress, and other profile information. + * @param User $oUser The requested MediaWiki User object + * @param array $aParams The settings array for the mini profile view object + * @return ViewUserMiniProfile A view with the users mini profile + */ + public function getUserMiniProfile( $oUser, $aParams = array() ) { + wfProfileIn('BS::' . __METHOD__); + $sParamsHash = md5( serialize( $aParams ) ); + $sViewHash = $oUser->getName() . $sParamsHash; + + if ( isset( self::$aUserMiniProfiles[$sViewHash] ) ) { + wfProfileOut('BS::' . __METHOD__); + return self::$aUserMiniProfiles[$sViewHash]; + } + + $oUserMiniProfileView = new ViewUserMiniProfile(); + $oUserMiniProfileView->setOptions( $aParams ); + $oUserMiniProfileView->setOption( 'user', $oUser ); + + wfRunHooks( 'BSCoreGetUserMiniProfileBeforeInit', array( &$oUserMiniProfileView, &$oUser, &$aParams ) ); + + $oUserMiniProfileView->init(); + + self::$aUserMiniProfiles[$sViewHash] = $oUserMiniProfileView; + + wfProfileOut('BS::' . __METHOD__); + return $oUserMiniProfileView; + } + + /** + * Registers a permission with the MediaWiki Framework. + * object for proper internationalisation of your permission. Every + * permission is granted automatically to the user group 'sysop'. You can + * specify additional groups through the third parameter. + * @param String $sPermissionName I.e. 'myextension-dosomething' + * @param Array $aUserGroups User groups that get preinitialized with the new + * pemission. I.e. array( 'user', 'bureaucrats' ) + * @param Array $aConfig set configs for permissions i.e. array('type'=>'global'. + * Default here is 'type' = 'global') + * @return void + */ + public function registerPermission( $sPermissionName, $aUserGroups = array(), $aConfig = array() ) { + // TODO MRG (05.02.11 19:24): @Sebastian Ist der dritte Parameter im PermissionsManager berücksichtigt? + wfProfileIn('BS::' . __METHOD__); + global $wgGroupPermissions, $wgAvailableRights, $bsgPermissionConfig; + $wgGroupPermissions['sysop'][$sPermissionName] = true; + if(!isset($bsgPermissionConfig[$sPermissionName])){ + if ( isset( $aConfig ) ) { + $bsgPermissionConfig[$sPermissionName] = $sConfig; + } else { + $bsgPermissionConfig[$sPermissionName] = array( 'type' => 'namespace' ); + } + } + foreach ( $aUserGroups as $sGroup ) { + if ( !isset( $wgGroupPermissions[$sGroup][$sPermissionName] ) ) { + $wgGroupPermissions[$sGroup][$sPermissionName] = true; + } + } + $wgAvailableRights[] = $sPermissionName; + wfProfileOut('BS::' . __METHOD__); + } + + /** + * Register a callback for a MagicWord + * @param string $sMagicWord The MagicWord in upper case and without + * surrounding double underscores. OR: if $callback == null this may be a + * lower case identifier that gets written to the page_props table by the + * parser. + * @param callable $aCallback or null to use MediaWiki page_props mechanism + */ + public function registerBehaviorSwitch( $sMagicWord, $aCallback = null ) { + if ( is_callable( $aCallback ) ) { + $this->aBehaviorSwitches[$sMagicWord] = $aCallback; + } elseif ( !isset( MagicWord::$mDoubleUnderscoreIDs[$sMagicWord] ) ) { + MagicWord::$mDoubleUnderscoreIDs[] = $sMagicWord; + } + } + + /** + * Hook-handler for "ArticleAfterFetchContent" + * @param WikiPage $article + * @param string $content + * @return boolean Always true to keep hook running + */ + public function behaviorSwitches( &$article, &$content ) { + if ( !isset( $this->aBehaviorSwitches ) ) { + return true; + } + + $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $content ); + foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { + if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { + call_user_func( $sCallback ); + } + } + return true; + } + + /** + * Hook-handler for "ParserBeforeStrip" + * @param Parser $parser + * @param string $text + * @return boolean Always true to keep hook running + * @deprecated since version 2.22 + */ + public function hideBehaviorSwitches( &$parser, &$text ) { + if ( !isset( $this->aBehaviorSwitches ) ) { + return true; + } + + $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $text ); + foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { + if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { + call_user_func( $sCallback ); + } + + $text = preg_replace( "/(<nowiki>.*?)__{$sSwitch}__(.*?<\/nowiki>)/i", "$1@@{$sSwitch}@@$2", $text ); + } + return true; + } + + /** + * Hook-handler for "ParserBeforeTidy" + * @param Parser $parser + * @param string $text + * @return boolean Always true to keep hook running + * @deprecated since version 2.22 + */ + public function recoverBehaviorSwitches( &$parser, &$text ) { + if ( !isset( $this->aBehaviorSwitches ) ) { + return true; + } + + foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { + $text = str_replace( '__' . $sSwitch . '__', "", $text ); + $text = preg_replace( "/@@" . $sSwitch . "@@/", '__' . $sSwitch . '__', $text ); + } + return true; + } + + /** + * Hook-handler for "EditPage::showEditForm:initial" + * Needed for edit and sumbit (preview) mode + * @param EditPage $editPage + * @return boolean Always true to keep hook running + */ + public function lastChanceBehaviorSwitches( $editPage ) { + // TODO SW(05.01.12 15:39): Profiling + $sContent = BsPageContentProvider::getInstance()->getContentFromTitle( RequestContext::getMain()->getTitle() ); + if ( !isset( $this->aBehaviorSwitches ) ) return true; + + $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $sContent ); + foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { + if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { + call_user_func( $sCallback ); + } + } + // TODO: This note should be displayed when the editor is deactivated + //$editPage->editFormTextTop = "Der Editor wurde deaktiviert <br/>"; + if ( isset( $editPage->textbox1 ) ) { + foreach ( $this->aBehaviorSwitches as $sSwitch => $sCallback ) { + $sNowikistripped = preg_replace( "#<nowiki>.*?<\/nowiki>#si", "", $editPage->textbox1 ); + if ( strstr( $sNowikistripped, '__' . $sSwitch . '__' ) ) { + call_user_func( $sCallback ); + } + } + } + return true; + } + + /** + * Handles requests to the BS-AJAX-PING-BUS (BSAPB) + * TODO: Move to seperate class + * @return String JSON encoded data + */ + public static function ajaxBSPing() { + $aResult = array( + "success" => false, + "errors" => array(), + "message" => '', + ); + + $oRequest = RequestContext::getMain()->getRequest(); + $iArticleId = $oRequest->getInt( 'iArticleID', 0 ); + $iNamespace = $oRequest->getInt( 'iNamespace', 0 ); + $sTitle = $oRequest->getVal( 'sTitle', '' ); + $iRevision = $oRequest->getInt( 'iRevision', 0 ); + $aBSPingData = $oRequest->getArray( 'BsPingData', array() ); + + $aResult['success'] = true; + foreach ( $aBSPingData as $aSinglePing ) { + if ( empty( $aSinglePing['sRef'] ) ) continue; + if ( !$aResult['success'] ) break; + + if ( !isset( $aSinglePing['aData'] ) ) + $aSinglePing['aData'] = array(); + + $aSingleResult = array( + "success" => false, + "errors" => array(), + "message" => '', + ); + //if hook returns false - overall success is false + $aResult['success'] = wfRunHooks( 'BsAdapterAjaxPingResult', + array( $aSinglePing['sRef'], $aSinglePing['aData'], + $iArticleId, $sTitle, $iNamespace, $iRevision, + &$aSingleResult ) + ); + $aResult[$aSinglePing['sRef']] = $aSingleResult; + } + + return FormatJson::encode( $aResult ); + } + + /** + * Make the page being parsed have a dependency on $page via the templatelinks table. + * http://www.mediawiki.org/wiki/Manual:Tag_extensions#Regenerating_the_page_when_another_page_is_edited + * @param Parser $oParser + * @param String $sTitle + */ + public static function addTemplateLinkDependencyByText($oParser, $sTitle) { + $oTitle = Title::newFromText( $sTitle ); + static::addTemplateLinkDependency($oParser, $oTitle); + } + + /** + * Make the page being parsed have a dependency on $page via the templatelinks table. + * http://www.mediawiki.org/wiki/Manual:Tag_extensions#Regenerating_the_page_when_another_page_is_edited + * @param Parser $oParser + * @param Title $oTitle + */ + public static function addTemplateLinkDependency( $oParser, $oTitle ) { + $oRevision = Revision::newFromTitle( $oTitle ); + $iPageId = $oRevision ? $oRevision->getPage() : 0; + $iRevId = $oRevision ? $oRevision->getId() : 0; + + $oParser->getOutput()->addTemplate( + $oTitle, + $iPageId, + $iRevId + ); // Register dependency in templatelinks + } + + /** + * Returns the MediaWiki include path variable + * @global String $IP MediaWiki include path variable + * @return String MediaWiki include path variable + */ + public static function getMediaWikiIncludePath() { + wfProfileIn('BS::' . __METHOD__); + global $IP; + wfProfileOut('BS::' . __METHOD__); + return str_replace('\\', '/', $IP); + } + + /** + * Returns the filesystempath to the webroot directory in which MediaWiki is installed. + * @global String $wgScriptPath The relative path from the webroot for hyperlinks. + * @return String Webroot directory in which MediaWiki is installed + */ + public static function getMediaWikiWebrootPath() { + global $wgScriptPath; + return str_replace($wgScriptPath, '', self::getMediaWikiIncludePath()); + } + + public static function getClientScriptBlocks() { + return self::$aClientScriptBlocks; + } + + /** + * Use this to place javascript logic _below_ the including script files. Therefore you can benefit from the available frameworks like BlueSpiceFramework, ExtJS and jQuery. + * @param String $sExtensionKey The name of the extension. This is just for creating a nice comment within the script-Tags + * @param String $sCode The JavaScript code, that should be executed after all scriptfiles have been included + * @param String $sUniqueKey (Optional) If provided the script block gets saved in with a unique key and therefore will not be registered multiple times. + * @deprecated Use MediaWikis Outpage interface instead + */ + public static function registerClientScriptBlock( $sExtensionKey, $sCode, $sUniqueKey = '' ) { + wfDeprecated(__METHOD__); + if( !empty( $sUniqueKey ) ) { + self::$aClientScriptBlocks[$sUniqueKey] = array( $sExtensionKey, $sCode ); + } else { + self::$aClientScriptBlocks[] = array( $sExtensionKey, $sCode ); + } + } } \ No newline at end of file diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 2dac392..50bff08 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -101,6 +101,109 @@ ) ); +$bsgPermissionConfig = array( + 'read' => array( + 'type' => 'namespace', + 'preventLockout' => true + ), + 'siteadmin' => array( + 'type' => 'global', + 'preventLockout' => true + ), + 'wikiadmin' => array( + 'type' => 'global', + 'preventLockout' => true + ), + "apihighlimits" => array( + 'type' => 'global' + ), + "autoconfirmed" => array( + 'type' => 'global' + ), + "autopatrol" => array( + 'type' => 'global' + ), + "bigdelete" => array( + 'type' => 'global' + ), + "block" => array( + 'type' => 'global' + ), + "blockemail" => array( + 'type' => 'global' + ), + "bot" => array( + 'type' => 'global' + ), + "browsearchive" => array( + 'type' => 'global' + ), + "createaccount" => array( + 'type' => 'global' + ), + "editinterface" => array( + 'type' => 'global' + ), + "editusercssjs" => array( + 'type' => 'global' + ), + "editusercss" => array( + 'type' => 'global' + ), + "edituserjs" => array( + 'type' => 'global' + ), + "hideuser" => array( + 'type' => 'global' + ), + "import" => array( + 'type' => 'global' + ), + "importupload" => array( + 'type' => 'global' + ), + "ipblock-exempt" => array( + 'type' => 'global' + ), + "move-rootuserpages" => array( + 'type' => 'global' + ), + "override-export-depth" => array( + 'type' => 'global' + ), + "passwordreset" => array( + 'type' => 'global' + ), + "proxyunbannable" => array( + 'type' => 'global' + ), + "sendemail" => array( + 'type' => 'global' + ), + "unblockself" => array( + 'type' => 'global' + ), + "userrights" => array( + 'type' => 'global' + ), + "userrights-interwiki" => array( + 'type' => 'global' + ), + "writeapi" => array( + 'type' => 'global' + ), + "skipcaptcha" => array( + 'type' => 'global' + ), + "renameuser" => array( + 'type' => 'global' + ), + "viewfiles" => array( + 'type' => 'global' + ), + "searchfiles", +); + $bsgExtJSTheme = 'bluespice'; unset($sResourcesPath); -- To view, visit https://gerrit.wikimedia.org/r/192322 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I44787c6f5e4ec1161ff08735f86f499f96b346bc Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation Gerrit-Branch: master Gerrit-Owner: Jgoettlich <goettl...@hallowelt.biz> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits