/**
  * Getter for the $aNavigationSites array - either from hook, TopBarMenu title or cache
  * @global string $wgSitename
  * @return array
  */
 public static function getNavigationSites()
 {
     if (!is_null(self::$aNavigationSites)) {
         return self::$aNavigationSites;
     }
     $sKey = BsExtensionManager::getExtension('TopMenuBarCustomizer')->getCacheKey('NavigationSitesData');
     self::$aNavigationSites = BsCacheHelper::get($sKey);
     if (self::$aNavigationSites !== false) {
         return self::$aNavigationSites;
     }
     self::$aNavigationSites = array();
     $oTopBarMenuTitle = Title::makeTitle(NS_MEDIAWIKI, 'TopBarMenu');
     if (!is_null($oTopBarMenuTitle) && $oTopBarMenuTitle->exists()) {
         $sContent = BsPageContentProvider::getInstance()->getContentFromTitle($oTopBarMenuTitle);
         // Force unset of all menu items by creating an empty page
         if (!empty($sContent)) {
             self::$aNavigationSites = TopMenuBarCustomizerParser::getNavigationSites();
         }
         BsCacheHelper::set($sKey, self::$aNavigationSites, 60 * 1440);
         //max cache time 24h
         return self::$aNavigationSites;
     }
     global $wgSitename;
     $oCurrentTitle = RequestContext::getMain()->getTitle();
     $oMainPage = Title::newMainPage();
     self::$aNavigationSites[] = array('id' => 'wiki', 'href' => $oMainPage->getFullURL(), 'text' => $wgSitename, 'active' => $oCurrentTitle->equals($oMainPage), 'level' => 1, 'containsactive' => false, 'external' => false, 'children' => array());
     wfRunHooks('BSTopMenuBarCustomizerRegisterNavigationSites', array(&self::$aNavigationSites));
     BsCacheHelper::set($sKey, self::$aNavigationSites, 60 * 1440);
     //max cache time 24h
     return self::$aNavigationSites;
 }
 /**
  * Hook-Handler for 'OutputPageBeforeHTML' (MediaWiki). Replaces Emoticon syntax with images.
  * @param ParserOutput $oParserOutput The ParserOutput object that corresponds to the page.
  * @param string $sText The text that will be displayed in HTML.
  * @return bool Always true to keep hook running.
  */
 public function onOutputPageBeforeHTML(&$oParserOutput, &$sText)
 {
     global $wgScriptPath;
     $sCurrentAction = $this->getRequest()->getVal('action', 'view');
     $oCurrentTitle = $this->getTitle();
     if (in_array($sCurrentAction, array('edit', 'history', 'delete', 'watch'))) {
         return true;
     }
     if (in_array($oCurrentTitle->getNamespace(), array(NS_SPECIAL, NS_MEDIAWIKI))) {
         return true;
     }
     wfProfileIn('BS::' . __METHOD__);
     $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'Emoticons');
     $aMapping = BsCacheHelper::get($sKey);
     if ($aMapping == false) {
         $sPathToEmoticons = $wgScriptPath . '/extensions/BlueSpiceExtensions/Emoticons/emoticons';
         // Get the list of emoticons from the message system.
         $sMappingContent = "smile.png           :-)     :)\n\t\t\t\t\t\t\t\tsad.png             :-(     :(\n\t\t\t\t\t\t\t\tneutral.png         :-|     :|\n\t\t\t\t\t\t\t\tangry.png           :-@     :@\n\t\t\t\t\t\t\t\twink.png            ;-)     ;)\n\t\t\t\t\t\t\t\tsmile-big.png       :D     :-D\n\t\t\t\t\t\t\t\tthinking.png        :-/     :/\n\t\t\t\t\t\t\t\tshut-mouth.png      :-X     :X\n\t\t\t\t\t\t\t\tcrying.png          :'(\n\t\t\t\t\t\t\t\tshock.png           :-O\n\t\t\t\t\t\t\t\tconfused.png        :-S\n\t\t\t\t\t\t\t\tglasses-cool.png    8-)\n\t\t\t\t\t\t\t\tlaugh.png           :lol:\n\t\t\t\t\t\t\t\tyawn.png            (:|\n\t\t\t\t\t\t\t\tgood.png            :good:\n\t\t\t\t\t\t\t\tbad.png             :bad:\n\t\t\t\t\t\t\t\tembarrassed.png     :-[\n\t\t\t\t\t\t\t\tshame.png           [-X     [-x";
         if (empty($sMappingContent)) {
             return true;
         }
         // If the content successfully loaded, do the replacement
         $aMappingLines = explode("\n", $sMappingContent);
         $aEmoticons = array();
         $aImageReplacements = array();
         foreach ($aMappingLines as $sLine) {
             $sLine = trim($sLine);
             //Remove leading space
             if (empty($sLine)) {
                 continue;
             }
             //Empty line?
             if ($sLine[0] == '#') {
                 continue;
             }
             //Comment line?
             $aEmoticonHash = preg_split('/ +/', $sLine);
             // $aEmoticonHash = array('smile.png', ':-)', ':)');
             if (count($aEmoticonHash) > 1) {
                 $sImageName = array_shift($aEmoticonHash);
                 // first element is image name, here 'smile.png'
                 $oEmoticonImageView = new ViewBaseElement();
                 $oEmoticonImageView->setTemplate(' <img border="0" src="' . $sPathToEmoticons . '/{FILENAME}" alt="emoticon" />');
                 $oEmoticonImageView->addData(array('FILENAME' => $sImageName));
                 foreach ($aEmoticonHash as $sEmote) {
                     $aEmoticons[] = ' ' . $sEmote;
                     $aEmoticons[] = '&nbsp;' . $sEmote;
                     $aEmoticons[] = '&#160;' . $sEmote;
                     // (TL., 25.02.2011) das brauchen wir wirklich 3 mal, weil auch aEmoticons[] 3 mal gefüllt wird!
                     $aImageReplacements[] = $oEmoticonImageView->execute();
                     $aImageReplacements[] = $oEmoticonImageView->execute();
                     $aImageReplacements[] = $oEmoticonImageView->execute();
                 }
             }
         }
         $aMapping = array('emoticons' => $aEmoticons, 'replacements' => $aImageReplacements);
         BsCacheHelper::set($sKey, $aMapping);
     }
     $sText = str_replace($aMapping['emoticons'], $aMapping['replacements'], $sText);
     wfProfileOut('BS::' . __METHOD__);
     return true;
 }
 private function getAuthorsViewForAfterContent($oSkin, &$aDetails)
 {
     $oTitle = $oSkin->getTitle();
     //Read in config variables
     $iLimit = BsConfig::get('MW::Authors::Limit');
     $aBlacklist = BsConfig::get('MW::Authors::Blacklist');
     $sMoreImage = BsConfig::get('MW::Authors::MoreImage');
     $aParams = array();
     $aParams['width'] = BsConfig::get('MW::Authors::ImageWidth');
     $aParams['height'] = BsConfig::get('MW::Authors::ImageHeight');
     $sPrintable = $oSkin->getRequest()->getVal('printable', 'no');
     $iArticleId = $oTitle->getArticleID();
     $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'Authors', $iArticleId);
     $aData = BsCacheHelper::get($sKey);
     if ($aData !== false) {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetched AuthorsView and Details from cache');
         $oAuthorsView = $aData['view'];
         $aDetails = $aData['details'];
     } else {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching AuthorsView and Details from DB');
         //HINT: Maybe we want to use MW interface Article::getContributors() to have better caching
         //HINT2: Check if available in MW 1.17+
         // SW: There is still no caching in WikiPage::getContributors()! 17.07.2014
         $dbr = wfGetDB(DB_SLAVE);
         $res = $dbr->select(array('revision'), array('rev_user_text', 'MAX(rev_timestamp) AS ts'), array('rev_page' => $iArticleId), __METHOD__, array('GROUP BY' => 'rev_user_text', 'ORDER BY' => 'ts DESC'));
         if ($res->numRows() == 0) {
             return true;
         }
         $oAuthorsView = new ViewAuthors();
         if ($sPrintable == 'yes') {
             $oAuthorsView->setOption('print', true);
         }
         $aUserNames = array();
         foreach ($res as $row) {
             $aUserNames[] = $row->rev_user_text;
         }
         $iCount = count($aUserNames);
         $aDetails['count'] = $iCount;
         $sOriginatorUserName = $oTitle->getFirstRevision()->getUserText();
         $sOriginatorUserName = $this->checkOriginatorForBlacklist($sOriginatorUserName, $oTitle->getFirstRevision(), $aBlacklist);
         if ($iCount > 1) {
             array_unshift($aUserNames, $sOriginatorUserName);
             $iCount++;
         }
         $bAddMore = false;
         if ($iCount > $iLimit) {
             $bAddMore = true;
         }
         $i = 0;
         $iItems = 0;
         $aDetails['username'] = '';
         while ($i < $iCount) {
             if ($iItems > $iLimit) {
                 break;
             }
             $sUserName = $aUserNames[$i];
             if (User::isIP($sUserName)) {
                 unset($aUserNames[$i]);
                 $i++;
                 continue;
             }
             $oAuthorUser = User::newFromName($sUserName);
             if (!is_object($oAuthorUser) || in_array($oAuthorUser->getName(), $aBlacklist)) {
                 unset($aUserNames[$i]);
                 $i++;
                 continue;
             }
             $aDetails['username'] = $oAuthorUser->getName();
             $oUserMiniProfileView = BsCore::getInstance()->getUserMiniProfile($oAuthorUser, $aParams);
             if ($sPrintable == 'yes') {
                 $oUserMiniProfileView->setOption('print', true);
             }
             $iItems++;
             $i++;
             $oAuthorsView->addItem($oUserMiniProfileView);
         }
         if ($bAddMore === true) {
             $oMoreAuthorsView = BsCore::getInstance()->getUserMiniProfile(new User(), $aParams);
             $oMoreAuthorsView->setOption('userdisplayname', wfMessage('bs-authors-show-all-authors')->plain());
             $oMoreAuthorsView->setOption('userimagesrc', $this->getImagePath(true) . '/' . $sMoreImage);
             $oMoreAuthorsView->setOption('linktargethref', $oTitle->getLocalURL(array('action' => 'history')));
             $oMoreAuthorsView->setOption('classes', array('bs-authors-more-icon'));
             if ($sPrintable == 'yes') {
                 $oMoreAuthorsView->setOption('print', true);
             }
             $oAuthorsView->addItem($oMoreAuthorsView);
         }
         $dbr->freeResult($res);
         BsCacheHelper::set($sKey, array('view' => $oAuthorsView, 'details' => $aDetails));
     }
     return $oAuthorsView;
 }
 /**
  * Renders the blog. Called by parser function for bs:blog tag and also from Blog::onUnknownAction.
  * @param string $input Inner HTML of bs:blog tag. Not used.
  * @param array $args List of tag attributes.
  * @param Parser $parser MediaWiki parser object
  * @return string HTML output that is to be displayed.
  */
 public function onBlog($input, $args, $parser)
 {
     $oTitle = null;
     if ($parser instanceof Parser) {
         $oTitle = $parser->getTitle();
         $parser->disableCache();
     } else {
         $oTitle = $this->getTitle();
     }
     $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'Blog', $oTitle->getArticleID());
     $aData = BsCacheHelper::get($sKey);
     if ($aData !== false) {
         return $aData;
     }
     // initialize local variables
     $oErrorListView = new ViewTagErrorList($this);
     BsExtensionManager::setContext('MW::Blog::ShowBlog');
     // get all config options
     $iShowLimit = BsConfig::get('MW::Blog::ShowLimit');
     //$blogShowTrackback    = BsConfig::get('MW::Blog::ShowTrackback');  // see comment below
     $bShowPermalink = BsConfig::get('MW::Blog::ShowPermalink');
     $bShowInfo = BsConfig::get('MW::Blog::ShowInfo');
     $sSortBy = BsConfig::get('MW::Blog::SortBy');
     $bMoreInNewWindow = BsConfig::get('MW::Blog::MoreInNewWindow');
     $bShowAll = BsConfig::get('MW::Blog::ShowAll');
     $bMoreAtEndOfEntry = BsConfig::get('MW::Blog::MoreAtEndOfEntry');
     $bShowNewEntryField = BsConfig::get('MW::Blog::ShowNewEntryField');
     $bNewEntryFieldPosition = BsConfig::get('MW::Blog::NewEntryFieldPosition');
     $sImageRenderMode = BsConfig::get('MW::Blog::ImageRenderMode');
     $sImageFloatDirection = BsConfig::get('MW::Blog::ThumbFloatDirection');
     $iMaxEntryCharacters = BsConfig::get('MW::Blog::MaxEntryCharacters');
     // Trackbacks are not supported the way we intend it to be. From http://www.mediawiki.org/wiki/Manual:$wgUseTrackbacks
     // When MediaWiki receives a trackback ping, a box will show up at the bottom of the article containing a link to the originating page
     //if (!$wgUseTrackbacks)
     $bShowTrackback = false;
     // get tag attributes
     $argsIShowLimit = BsCore::sanitizeArrayEntry($args, 'count', $iShowLimit, BsPARAMTYPE::NUMERIC | BsPARAMOPTION::DEFAULT_ON_ERROR);
     $argsSCategory = BsCore::sanitizeArrayEntry($args, 'cat', false, BsPARAMTYPE::STRING);
     $argsINamespace = BsNamespaceHelper::getNamespaceIndex(BsCore::sanitizeArrayEntry($args, 'ns', NS_BLOG, BsPARAMTYPE::STRING));
     $argsBNewEntryField = BsCore::sanitizeArrayEntry($args, 'newentryfield', $bShowNewEntryField, BsPARAMTYPE::BOOL);
     $argsSNewEntryFieldPosition = BsCore::sanitizeArrayEntry($args, 'newentryfieldposition', $bNewEntryFieldPosition, BsPARAMTYPE::STRING);
     $argsSImageRenderMode = BsCore::sanitizeArrayEntry($args, 'imagerendermode', $sImageRenderMode, BsPARAMTYPE::STRING);
     $argsSImageFloatDirection = BsCore::sanitizeArrayEntry($args, 'imagefloatdirection', $sImageFloatDirection, BsPARAMTYPE::STRING);
     $argsIMaxEntryCharacters = BsCore::sanitizeArrayEntry($args, 'maxchars', $iMaxEntryCharacters, BsPARAMTYPE::INT);
     $argsSSortBy = BsCore::sanitizeArrayEntry($args, 'sort', $sSortBy, BsPARAMTYPE::STRING);
     $argsBShowInfo = BsCore::sanitizeArrayEntry($args, 'showinfo', $bShowInfo, BsPARAMTYPE::BOOL);
     $argsBMoreInNewWindow = BsCore::sanitizeArrayEntry($args, 'moreinnewwindow', $bMoreInNewWindow, BsPARAMTYPE::BOOL);
     $argsBShowPermalink = BsCore::sanitizeArrayEntry($args, 'showpermalink', $bShowPermalink, BsPARAMTYPE::BOOL);
     $argsModeNamespace = BsCore::sanitizeArrayEntry($args, 'mode', null, BsPARAMTYPE::STRING);
     if ($argsModeNamespace === 'ns' && is_object($oTitle)) {
         $argsINamespace = $oTitle->getNamespace();
     }
     // validate tag attributes
     $validateIShowLimit = BsValidator::isValid('ArgCount', $argsIShowLimit, array('fullResponse' => true));
     if ($validateIShowLimit->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($validateIShowLimit->getI18N()));
     }
     if ($argsSCategory) {
         $validateSCategory = BsValidator::isValid('Category', $argsSCategory, array('fullResponse' => true));
         if ($validateSCategory->getErrorCode()) {
             $oErrorListView->addItem(new ViewTagError($validateSCategory->getI18N()));
         }
     }
     $oValidationResult = BsValidator::isValid('SetItem', $argsSImageRenderMode, array('fullResponse' => true, 'setname' => 'imagerendermode', 'set' => array('full', 'thumb', 'none')));
     if ($oValidationResult->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($oValidationResult->getI18N()));
     }
     $oValidationResult = BsValidator::isValid('SetItem', $argsSImageFloatDirection, array('fullResponse' => true, 'setname' => 'imagefloatdirection', 'set' => array('left', 'right', 'none')));
     if ($oValidationResult->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($oValidationResult->getI18N()));
     }
     $oValidationResult = BsValidator::isValid('SetItem', $argsSSortBy, array('fullResponse' => true, 'setname' => 'sort', 'set' => array('title', 'creation')));
     if ($oValidationResult->getErrorCode()) {
         $oErrorListView->addItem(new ViewTagError($oValidationResult->getI18N()));
     }
     // if there are errors, abort with a message
     if ($oErrorListView->hasEntries()) {
         return $oErrorListView->execute();
     }
     if (BsConfig::get('MW::Blog::ShowTagFormWhenNotLoggedIn') != true) {
         $oPermissionTest = Title::newFromText('PermissionTest', $argsINamespace);
         if (!$oPermissionTest->userCan('edit')) {
             $argsBNewEntryField = false;
         }
     }
     // get array of article ids from Blog/subpages
     $oBlogTitle = Title::makeTitleSafe($oTitle->getNamespace(), 'Blog');
     $aSubpages = $oBlogTitle->getSubpages();
     $iLimit = 0;
     // for later use
     $aArticleIds = array();
     foreach ($aSubpages as $oSubpage) {
         $aArticleIds[] = $oSubpage->getArticleID();
         $iLimit++;
         // for later use
     }
     if (count($aArticleIds) < 1) {
         $aArticleIds = 0;
     }
     $aTables = array('page');
     $aFields = array('entry_page_id' => 'page_id');
     $aConditions = array();
     $aOptions = array();
     $aJoins = array();
     $dbr = wfGetDB(DB_SLAVE);
     // get blog entries
     if ($argsSSortBy == 'title') {
         $aOptions['ORDER BY'] = 'page_title ASC';
     } else {
         //Creation: Also fetch possible custom timestamps from page_props table
         $aOptions['ORDER BY'] = 'entry_timestamp DESC';
         $aOptions['GROUP BY'] = 'page_id';
         global $wgDBtype;
         switch ($wgDBtype) {
             case 'oracle':
                 $aFields['entry_timestamp'] = "NVL( pp_value, rev_timestamp )";
                 $aConditions[] = "NVL( pp_value, rev_timestamp ) < " . wfTimestampNow();
                 break;
             case 'mssql':
                 $aFields['entry_timestamp'] = "ISNULL( pp_value, rev_timestamp )";
                 $aConditions[] = "ISNULL( pp_value, rev_timestamp ) < " . wfTimestampNow();
                 break;
             case 'postgres':
                 $aFields['entry_timestamp'] = "NULLIF( pp_value, rev_timestamp )";
                 $aConditions[] = "NULLIF( pp_value, rev_timestamp ) < " . wfTimestampNow();
                 break;
             default:
                 //MySQL, SQLite
                 //use pp_value if exists
                 $aFields['entry_timestamp'] = "IFNULL( pp_value, rev_timestamp )";
                 //also do not list future entries
                 $aConditions[] = "IFNULL( pp_value, rev_timestamp ) < " . wfTimestampNow();
         }
         $aTables[] = 'revision';
         $aTables[] = 'page_props';
         $aConditions[] = 'rev_page = page_id';
         $aJoins['page_props'] = array('LEFT JOIN', "pp_page = rev_page AND pp_propname = 'blogtime'");
     }
     if ($argsSCategory) {
         $aTables[] = 'categorylinks';
         $aConditions['cl_to'] = $argsSCategory;
         $aConditions[] = 'cl_from = page_id';
     } else {
         if ($argsModeNamespace === 'ns') {
             $aConditions['page_id'] = $aArticleIds;
         }
         $aConditions['page_namespace'] = $argsINamespace;
     }
     $res = $dbr->select($aTables, $aFields, $aConditions, __METHOD__, $aOptions, $aJoins);
     $iNumberOfEntries = $dbr->numRows($res);
     $iLimit = $iNumberOfEntries;
     //All
     // Sole importance is the existence of param 'showall'
     $paramBShowAll = $this->getRequest()->getFuzzyBool('showall', false);
     if ($paramBShowAll == false) {
         $iLimit = $argsIShowLimit;
     }
     // abort if there are no entries
     if ($iNumberOfEntries < 1) {
         $oBlogView = new ViewBlog();
         $oBlogView->setOption('shownewentryfield', $argsBNewEntryField);
         $oBlogView->setOption('newentryfieldposition', $argsSNewEntryFieldPosition);
         $oBlogView->setOption('namespace', BsNamespaceHelper::getNamespaceName($argsINamespace));
         if ($argsSCategory) {
             $oBlogView->setOption('blogcat', $argsSCategory);
         }
         // actually create blog output
         $sOut = $oBlogView->execute();
         $sOut .= wfMessage('bs-blog-no-entries')->plain();
         return $sOut;
     }
     $oBlogView = new ViewBlog();
     // prepare views per blog item
     $iLoop = 0;
     foreach ($res as $row) {
         // prepare data for view class
         $oEntryTitle = Title::newFromID($row->entry_page_id);
         if (!$oEntryTitle->userCan('read')) {
             $iNumberOfEntries--;
             continue;
         }
         $bMore = false;
         $aContent = preg_split('#<(bs:blog:)?more */>#', BsPageContentProvider::getInstance()->getContentFromTitle($oEntryTitle));
         if (sizeof($aContent) > 1) {
             $bMore = true;
         }
         $aContent = trim($aContent[0]);
         // Prevent recursive rendering of blog tag
         $aContent = preg_replace('/<(bs:)blog[^>]*?>/', '', $aContent);
         // Thumbnail images
         $sNamespaceRegEx = implode('|', BsNamespaceHelper::getNamespaceNamesAndAliases(NS_IMAGE));
         switch ($argsSImageRenderMode) {
             case 'none':
                 $aContent = preg_replace('/(\\[\\[(' . $sNamespaceRegEx . '):[^\\|\\]]*)(\\|)?(.*?)(\\]\\])/', '', $aContent);
                 break;
             case 'full':
                 // do nothing
                 break;
             case 'thumb':
             default:
                 $aContent = preg_replace('/(\\[\\[(' . $sNamespaceRegEx . '):[^\\|\\]]*)(\\|)?(.*?)(\\]\\])/', "\$1|thumb|{$argsSImageFloatDirection}\$3\$4|150px\$5", $aContent);
                 break;
         }
         if (strlen($aContent) > $argsIMaxEntryCharacters) {
             $bMore = true;
         }
         $aContent = BsStringHelper::shorten($aContent, array('max-length' => $argsIMaxEntryCharacters, 'ignore-word-borders' => false, 'position' => 'end'));
         $resComment = $dbr->selectRow('revision', 'COUNT( rev_id ) AS cnt', array('rev_page' => $oEntryTitle->getTalkPage()->getArticleID()));
         $iCount = $resComment->cnt;
         // set data for view class
         $oBlogItemView = new ViewBlogItem();
         // use magic set
         $oBlogItemView->setOption('showInfo', $argsBShowInfo);
         $oBlogItemView->setOption('showLimit', $argsIShowLimit);
         $oBlogItemView->setOption('showTrackback', $bShowTrackback);
         $oBlogItemView->setOption('showPermalink', $argsBShowPermalink);
         $oBlogItemView->setOption('moreInNewWindow', $argsBMoreInNewWindow);
         $oBlogItemView->setOption('showAll', $bShowAll);
         $oBlogItemView->setOption('moreAtEndOfEntry', $bMoreAtEndOfEntry);
         $oBlogItemView->setOption('more', $bMore);
         //TODO: magic_call?
         if ($argsModeNamespace === 'ns') {
             $sTitle = substr($oEntryTitle->getText(), 5);
         } else {
             $sTitle = $oEntryTitle->getText();
         }
         $aTalkParams = array();
         if (!$oEntryTitle->getTalkPage()->exists()) {
             $aTalkParams = array('action' => 'edit');
         }
         $oRevision = Revision::newFromTitle($oEntryTitle);
         $oBlogItemView->setTitle($sTitle);
         $oBlogItemView->setRevId($oRevision->getId());
         $oBlogItemView->setURL($oEntryTitle->getLocalURL());
         $oBlogItemView->setTalkURL($oEntryTitle->getTalkPage()->getLocalURL($aTalkParams));
         $oBlogItemView->setTalkCount($iCount);
         $oBlogItemView->setTrackbackUrl($oEntryTitle->getLocalURL());
         if ($bShowInfo) {
             $oFirstRevision = $oEntryTitle->getFirstRevision();
             $sTimestamp = $oFirstRevision->getTimestamp();
             $sLocalDateTimeString = BsFormatConverter::timestampToAgeString(wfTimestamp(TS_UNIX, $sTimestamp));
             $oBlogItemView->setEntryDate($sLocalDateTimeString);
             $iUserId = $oFirstRevision->getUser();
             if ($iUserId != 0) {
                 $oAuthorUser = User::newFromId($iUserId);
                 $oBlogItemView->setAuthorPage($oAuthorUser->getUserPage()->getPrefixedText());
                 $oBlogItemView->setAuthorName($this->mCore->getUserDisplayName($oAuthorUser));
             } else {
                 $oBlogItemView->setAuthorName($oFirstRevision->getUserText());
             }
         }
         $oBlogItemView->setContent($aContent);
         $oBlogView->addItem($oBlogItemView);
         $iLoop++;
         if ($iLoop >= $iLimit) {
             break;
         }
     }
     $dbr->freeResult($res);
     // prepare complete blog output
     if ($bShowAll && !$paramBShowAll && $iNumberOfEntries > $argsIShowLimit) {
         $oBlogView->setOption('showall', true);
     }
     $oBlogView->setOption('shownewentryfield', $argsBNewEntryField);
     $oBlogView->setOption('newentryfieldposition', $argsSNewEntryFieldPosition);
     $oBlogView->setOption('namespace', BsNamespaceHelper::getNamespaceName($argsINamespace, false));
     $oBlogView->setOption('blogcat', $argsSCategory);
     if ($argsModeNamespace === 'ns') {
         $oBlogView->setOption('parentpage', 'Blog/');
     }
     // actually create blog output
     $sOut = $oBlogView->execute();
     //Use cache only in NS_BLOG - there is curently no functionality to
     //figure out in what type of blog tag a entry is showen and why
     //(coditions). Possible blog by categories or subpages...
     //Needs rework.
     if (in_array($oTitle->getNamespace(), array(NS_BLOG, NS_BLOG_TALK))) {
         $aKey = array($sKey);
         $sTagsKey = BsCacheHelper::getCacheKey('BlueSpice', 'Blog', 'Tags');
         $aTagsData = BsCacheHelper::get($sTagsKey);
         if ($aTagsData !== false) {
             if (!in_array($sKey, $aTagsData)) {
                 $aTagsData = array_merge($aTagsData, $aKey);
             }
         } else {
             $aTagsData = $aKey;
         }
         BsCacheHelper::set($sTagsKey, $aTagsData, 60 * 1440);
         // one day
         BsCacheHelper::set($sKey, $sOut, 60 * 1440);
         // one day
     }
     return $sOut;
 }
 /**
  * Helper function. Fetches database and returns array of responsible editors of an article
  * @param Integer $iArticleId The page_id of the article you want to retrieve the responsible editors for.
  * @return Array user_ids of responsible editors for given article
  */
 public function getResponsibleEditorsByArticleId($iArticleId, $bForceReload = false)
 {
     if (isset(self::$aResponsibleEditorsByArticleId[$iArticleId]) && $bForceReload === false) {
         return self::$aResponsibleEditorsByArticleId[$iArticleId];
     }
     $aResponsibleEditorIds = array();
     $aResponsibleEditors = array();
     $sKey = BsCacheHelper::getCacheKey('ResponsibleEditors', 'getResponsibleEditorsByArticleId', (int) $iArticleId);
     $aData = BsCacheHelper::get($sKey);
     if ($aData !== false) {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching ResponsibleEditors from cache');
         self::$aResponsibleEditorIdsByArticleId[$iArticleId] = $aData['EditorIdsByArticleId'];
         self::$aResponsibleEditorsByArticleId[$iArticleId] = $aData['EditorsByArticleId'];
     } else {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching ResponsibleEditors from DB');
         $dbr = wfGetDB(DB_SLAVE);
         $res = $dbr->select('bs_responsible_editors', '*', array('re_page_id' => $iArticleId), __METHOD__, array('ORDER BY' => 're_position'));
         foreach ($res as $row) {
             $row->re_user_id = (int) $row->re_user_id;
             $aResponsibleEditorIds[] = $row->re_user_id;
             $aResponsibleEditors[] = $row;
         }
         $aData = array();
         $aData['EditorIdsByArticleId'] = $aResponsibleEditorIds;
         $aData['EditorsByArticleId'] = $aResponsibleEditors;
         BsCacheHelper::set($sKey, $aData);
         self::$aResponsibleEditorIdsByArticleId[$iArticleId] = $aResponsibleEditorIds;
         self::$aResponsibleEditorsByArticleId[$iArticleId] = $aResponsibleEditors;
     }
     return $aResponsibleEditors;
 }
 /**
  * Fires event if user is not logged in or UserSidebar Article does not exist.
  * @param array $aViews of WidgetView objects
  * @param User $oUser The current MediaWiki User object
  * @param Title $oTitle The UserSidebar Title object, containing the UserSidebar list
  * @return array of WidgetView objects
  */
 private function getDefaultWidgets(&$aViews, $oUser, $oTitle)
 {
     if ($oUser->isLoggedIn()) {
         $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'UserSidebar', $oTitle->getPrefixedDBkey());
     } else {
         $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'UserSidebar', 'default');
     }
     $aData = BsCacheHelper::get($sKey);
     if ($aData !== false) {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching Widget views from cache');
         $aViews = $aData;
     } else {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching Widget views from DB');
         wfRunHooks('BSUserSidebarDefaultWidgets', array(&$aViews, $oUser, $oTitle));
         BsCacheHelper::set($sKey, $aViews, 60 * 15);
         // invalidate cache after 15 minutes
     }
     return true;
 }
 /**
  * Returns total number of shouts for the article id
  * @param int $iArticleId
  * @return int number of shouts
  */
 public static function getTotalShouts($iArticleId = 0)
 {
     $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'ShoutBox', 'totalCount' . $iArticleId);
     $iData = BsCacheHelper::get($sKey);
     if ($iData === false) {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching total count from DB');
         $dbr = wfGetDB(DB_SLAVE);
         $res = $dbr->select('bs_shoutbox', 'sb_id', array('sb_page_id' => $iArticleId, 'sb_archived' => '0', 'sb_parent_id' => '0', 'sb_title' => ''), __METHOD__);
         $iTotalShouts = $res !== false ? $dbr->numRows($res) : 0;
         BsCacheHelper::set($sKey, $iTotalShouts);
     } else {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching total count from cache');
         $iTotalShouts = $iData;
     }
     return $iTotalShouts;
 }
 /**
  *
  * @param Title $oTitle
  * @return array An Array of Title objects
  */
 public function getTitleListFromTitle($oTitle)
 {
     $sKey = BsCacheHelper::getCacheKey('BlueSpice', 'WantedArticle', $oTitle->getPrefixedText());
     $aData = BsCacheHelper::get($sKey);
     if ($aData !== false) {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching WantedArticle list from cache');
         $aTitleList = $aData;
     } else {
         wfDebugLog('BsMemcached', __CLASS__ . ': Fetching WantedArticle list from DB');
         $oArticleContent = BsPageContentProvider::getInstance()->getContentFromTitle($oTitle);
         $aTitleList = array();
         $aLines = explode("\n", $oArticleContent);
         foreach ($aLines as $sLine) {
             $sLine = trim($sLine);
             if (empty($sLine) || $sLine[0] != '*') {
                 continue;
             }
             $aMatches = array();
             #*[[Title]] --[[Spezial:Beiträge/0:0:0:0:0:0:0:1|0:0:0:0:0:0:0:1]] 12:31, 7. Jan. 2013 (AST)
             #*[[Title2]]--[[Benutzer:WikiSysop|WikiSysop]] ([[Benutzer Diskussion:WikiSysop|Diskussion]]) 17:47, 4. Jan. 2013 (AST)
             preg_match('#\\*.*?\\[\\[(.*?)\\]\\]( ?--\\[\\[.*?:(.*?/)?(.*?)\\|.*?\\]\\].*?\\)? (\\(.*?\\))? ?(.*?))?$#si', $sLine, $aMatches);
             if (empty($aMatches) || !isset($aMatches[1])) {
                 continue;
             }
             $sTitle = $aMatches[1];
             $sUsername = isset($aMatches[4]) ? $aMatches[4] : '';
             $sSignature = isset($aMatches[2]) ? $aMatches[2] : '';
             $oT = Title::newFromText($sTitle);
             if ($oT === null) {
                 continue;
             }
             $aTitleList[] = array('title' => $oT, 'username' => $sUsername, 'signature' => $sSignature);
         }
         BsCacheHelper::set($sKey, $aTitleList);
     }
     return $aTitleList;
 }