コード例 #1
0
 /**
  * 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;
 }
 /**
  * Shorten facet string.
  * @param string $sFacet Name of facet
  * @return string Shortened name of facet
  */
 private function reduceMaxFacetLength($sFacet)
 {
     $sFacet = str_replace('_', ' ', $sFacet);
     return BsStringHelper::shorten($sFacet, array('max-length' => $this->iMaxFacetLength, 'position' => 'middle'));
 }
 /**
  * Generates list of your edits
  * @return string list of edits
  */
 public function getYourEdits($iCount, $sOrigin = 'dashboard', $iDisplayLength = 18)
 {
     wfProfileIn('BS::' . __METHOD__);
     $iCount = BsCore::sanitize($iCount, 0, BsPARAMTYPE::INT);
     $oDbr = wfGetDB(DB_SLAVE);
     $res = $oDbr->select('revision', 'rev_page', array('rev_user' => $this->getUser()->getId()), __METHOD__, array('GROUP BY' => 'rev_page', 'ORDER BY' => 'MAX(rev_timestamp) DESC', 'LIMIT' => $iCount));
     $aEdits = array();
     if ($oDbr->numRows($res) > 0) {
         foreach ($res as $row) {
             $sHtml = '';
             $oTitle = Title::newFromID($row->rev_page);
             if (!$oTitle instanceof Title) {
                 continue;
             }
             if ($sOrigin === 'dashboard') {
                 $sHtml = $oTitle->getPrefixedText();
             } else {
                 $sHtml = BsStringHelper::shorten($oTitle->getPrefixedText(), array('max-length' => $iDisplayLength, 'position' => 'middle'));
             }
             $sLink = Linker::link($oTitle, $sHtml);
             $aEdits[] = Html::openElement('li') . $sLink . Html::closeElement('li');
         }
     } else {
         return '<ul><li>' . wfMessage('bs-smartlist-noedits')->plain() . '</ul></li>';
     }
     $sEdits = '<ul>' . implode('', $aEdits) . '</ul>';
     wfProfileOut('BS::' . __METHOD__);
     return $sEdits;
 }
 /**
  * Hook handler for UserSaveOptions
  * @param User $user User whose options are being modified.
  * @param Array &$options Options array
  * @return true always true to keep hook alive
  */
 public function onUserSaveOptions($user, &$options)
 {
     BsConfig::loadSettings();
     $oCurrentTitle = $this->getTitle();
     //May return null in CLI
     if ($oCurrentTitle instanceof Title && $oCurrentTitle->isSpecialPage()) {
         $bDeliverUserSettings = true;
     } else {
         $bDeliverUserSettings = false;
     }
     $bOrigDeliver = BsConfig::deliverUsersSettings($bDeliverUserSettings);
     $aRegisteredVariables = BsConfig::getRegisteredVars();
     $aSortedVariables = array();
     foreach ($aRegisteredVariables as $oVariable) {
         $iOptions = $oVariable->getOptions();
         if (!($iOptions & BsConfig::LEVEL_USER)) {
             continue;
         }
         if ($bDeliverUserSettings === false) {
             if ($iOptions & BsConfig::NO_DEFAULT) {
                 continue;
             }
         }
         $sAdapterName = strtoupper($oVariable->getAdapter());
         $sExtensionName = $oVariable->getExtension();
         if (empty($sExtensionName)) {
             $sExtensionName = 'BASE';
         }
         $aSortedVariables[$sAdapterName][$sExtensionName][] = $oVariable;
     }
     foreach ($aSortedVariables as $sAdapterName => $aExtensions) {
         if (!count($aExtensions)) {
             continue;
         }
         foreach ($aExtensions as $sExtensionName => $aSettings) {
             // if continue, then $oAdapterSetView is not added to output
             if (!count($aSettings)) {
                 continue;
             }
             foreach ($aSettings as $oVariable) {
                 //Avoid "undefined index" notices and weird NULL values in settings
                 $value = $oVariable->getValue();
                 if (isset($options[$oVariable->generateFieldId()])) {
                     //Set but no bool
                     $value = $options[$oVariable->generateFieldId()];
                 }
                 if (isset($options[$oVariable->getKey()])) {
                     //Set but no bool
                     $value = $options[$oVariable->getKey()];
                 }
                 $options[$oVariable->getKey()] = BsStringHelper::isSerialized($value) ? $value : serialize($value);
                 unset($options[$oVariable->generateFieldId()]);
             }
         }
     }
     BsConfig::deliverUsersSettings($bOrigDeliver);
     return true;
 }
 /**
  *
  * @param User $oCurrentUser
  * @param int $iCount
  * @param int $iMaxTitleLength
  * @param string $sOrder
  * @return ViewBaseElement
  */
 private function fetchWatchlist($oCurrentUser, $iCount = 10, $iMaxTitleLength = 50, $sOrder = 'pagename')
 {
     $aWatchlist = array();
     $aOptions = array();
     if ($sOrder == 'pagename') {
         $aOptions['ORDER BY'] = 'wl_title';
     }
     $aOptions['LIMIT'] = $iCount;
     $dbr = wfGetDB(DB_SLAVE);
     $res = $dbr->select('watchlist', array('wl_namespace', 'wl_title'), array('wl_user' => $oCurrentUser->getId(), 'NOT wl_notificationtimestamp' => NULL), __METHOD__, $aOptions);
     $oWatchedArticlesListView = new ViewBaseElement();
     $oWatchedArticlesListView->setTemplate('*{WIKILINK}' . "\n");
     foreach ($res as $row) {
         $oWatchedTitle = Title::newFromText($row->wl_title, $row->wl_namespace);
         if ($oWatchedTitle === null || $oWatchedTitle->exists() === false || $oWatchedTitle->userCan('read') === false) {
             continue;
         }
         $sDisplayTitle = BsStringHelper::shorten($oWatchedTitle->getPrefixedText(), array('max-length' => $iMaxTitleLength, 'position' => 'middle'));
         $oWatchedArticlesListView->addData(array('WIKILINK' => BsLinkProvider::makeEscapedWikiLinkForTitle($oWatchedTitle, $sDisplayTitle)));
     }
     return $oWatchedArticlesListView;
 }
 /**
  * Setter-Method for the internal $sText field.
  * @param string $sText The text next to the icon. It will automatically be shortend to 30 characters.
  * @return ViewStateBarTopElement Itself. For method chaining
  */
 public function setText($sText)
 {
     $this->sText = BsStringHelper::shorten($sText, array('max-length' => 30));
     return $this;
 }
 /**
  * Highlights title for a given search string
  * @param object $oTitle Title which should be highlighted
  * @param string $sSearchString search string
  * @return string highlighted title
  */
 private static function highlightTitle($oTitle, $sSearchString)
 {
     $sPartOfTitle = '';
     $sEscapedPattern = '';
     $aSearchStringParts = array();
     $sModifiedSearchString = str_replace('/', ' ', $sSearchString);
     $sLabelText = BsStringHelper::shorten($oTitle->getText(), array('max-length' => '54', 'position' => 'middle', 'ellipsis-characters' => '...'));
     $iPosition = mb_stripos($sLabelText, $sSearchString);
     if ($iPosition !== false) {
         $sPartOfTitle = mb_substr($sLabelText, $iPosition, mb_strlen($sSearchString));
         $sEscapedPattern = preg_quote($sPartOfTitle, '#');
         $sLabelText = preg_replace('#' . $sEscapedPattern . '#i', '<b>' . $sPartOfTitle . '</b>', $sLabelText, 1);
     } else {
         $aOccurrences = array();
         $aSearchStringParts = explode(' ', $sModifiedSearchString);
         foreach ($aSearchStringParts as $sPart) {
             if (empty($sPart)) {
                 continue;
             }
             $sModifiedPart = mb_strtolower($sPart);
             if (in_array($sModifiedPart, $aOccurrences)) {
                 continue;
             }
             $iPosition = mb_stripos($sLabelText, $sPart);
             if ($iPosition !== false) {
                 $sPartOfTitle = mb_substr($sLabelText, $iPosition, mb_strlen($sPart));
                 $sEscapedPattern = preg_quote($sPartOfTitle, '#');
                 $sLabelText = preg_replace('#' . $sEscapedPattern . '#i', '[' . $sPartOfTitle . ']', $sLabelText, 1);
                 $aOccurrences[] = $sModifiedPart;
             }
         }
         $sLabelText = str_replace(array('[', ']'), array('<b>', '</b>'), $sLabelText);
     }
     return $sLabelText;
 }
 /**
  * Gets the recently visited pages of the current user.
  * @param int $iCount The number of pages to display
  * @param string $sNamespaces Comma separated list of requested namespaces, i.e. "1,5,Category,101"
  * @param int $iCurrentNamespaceId To determin wether the current namespace is in the list of requested namespaces
  * @param string $sSortOrder Defines the sorting of the list. 'time|pagename', default is 'time'
  * @return ViewBaseElement Contains the list in its _data member. The predefined template is '*[[{LINK}|{TITLE}]]\n'
  */
 private function makePagesVisitedWikiList($iCount = 5, $sNamespaces = 'all', $iCurrentNamespaceId = 0, $iMaxTitleLength = 20, $sSortOrder = 'time')
 {
     $oCurrentUser = $this->getUser();
     if (is_null($oCurrentUser)) {
         return null;
     }
     // in CLI
     //$sCacheKey = md5( $oCurrentUser->getName().$iCount.$sNamespaces.$iCurrentNamespaceId.$iMaxTitleLength );
     //if( isset( self::$prResultListViewCache[$sCacheKey] ) ) return self::$prResultListViewCache[$sCacheKey];
     $oErrorListView = new ViewTagErrorList($this);
     $oErrorView = null;
     $aConditions = array();
     $aNamespaceIndexes = array(0);
     try {
         $aNamespaceIndexes = BsNamespaceHelper::getNamespaceIdsFromAmbiguousCSVString($sNamespaces);
         //Returns array of integer indexes
     } catch (BsInvalidNamespaceException $oException) {
         $aInvalidNamespaces = $oException->getListOfInvalidNamespaces();
         $oVisitedPagesListView = new ViewBaseElement();
         $oVisitedPagesListView->setTemplate('<ul><li><em>{TEXT}</em></li></ul>' . "\n");
         $iCount = count($aInvalidNamespaces);
         $sNs = implode(', ', $aInvalidNamespaces);
         $sErrorMsg = wfMessage('bs-pagesvisited-error-nsnotvalid', $iCount, $sNs)->text();
         $oVisitedPagesListView->addData(array('TEXT' => $sErrorMsg));
         //self::$prResultListViewCache[$sCacheKey] = $oVisitedPagesListView;
         return $oVisitedPagesListView;
     }
     $aConditions = array('wo_user_id' => $oCurrentUser->getId(), 'wo_action' => 'view');
     $aConditions[] = 'wo_page_namespace IN (' . implode(',', $aNamespaceIndexes) . ')';
     //Add IN clause to conditions-array
     $aConditions[] = 'wo_page_namespace != -1';
     // TODO RBV (24.02.11 13:54): Filter SpecialPages because there are difficulties to list them
     $aOptions = array('GROUP BY' => 'wo_page_id, wo_page_namespace, wo_page_title', 'ORDER BY' => 'MAX(wo_timestamp) DESC');
     if ($sSortOrder == 'pagename') {
         $aOptions['ORDER BY'] = 'wo_page_title ASC';
     }
     //If the page the extension is used on appears in the result set we have to fetch one row more than neccessary.
     if (in_array($iCurrentNamespaceId, $aNamespaceIndexes)) {
         $aOptions['OFFSET'] = 1;
     }
     $aFields = array('wo_page_id', 'wo_page_namespace', 'wo_page_title');
     $sTable = 'bs_whoisonline';
     $dbr = wfGetDB(DB_SLAVE);
     global $wgDBtype;
     if ($wgDBtype == 'oracle') {
         $sRowNumField = 'rnk';
         $sTable = mb_strtoupper($dbr->tablePrefix() . $sTable);
         $sFields = implode(',', $aFields);
         $sConditions = $dbr->makeList($aConditions, LIST_AND);
         $aOptions['ORDER BY'] = $sSortOrder == 'pagename' ? $aOptions['ORDER BY'] : 'wo_timestamp DESC';
         $res = $dbr->query("SELECT " . $sFields . " FROM (\n\t\t\t\t\t\t\t\t\t\t\tSELECT " . $sFields . ", row_number() over (order by " . $aOptions['ORDER BY'] . ") " . $sRowNumField . "\n\t\t\t\t\t\t\t\t\t\t\tFROM " . $sTable . "\n\t\t\t\t\t\t\t\t\t\t\tWHERE " . $sConditions . "\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\tWHERE " . $sRowNumField . " BETWEEN (0) AND (" . $iCount . ") GROUP BY " . $aOptions["GROUP BY"] . "");
     } else {
         $res = $dbr->select($sTable, $aFields, $aConditions, __METHOD__, $aOptions);
     }
     $oVisitedPagesListView = new ViewBaseElement();
     $oVisitedPagesListView->setTemplate('*{WIKILINK}' . "\n");
     $iItems = 1;
     foreach ($res as $row) {
         if ($iItems > $iCount) {
             break;
         }
         $oVisitedPageTitle = Title::newFromID($row->wo_page_id);
         /*
         // TODO RBV (24.02.11 13:52): Make SpecialPages work...
         $oVisitedPageTitle = ( $row->wo_page_namespace != NS_SPECIAL )
         					? Title::newFromID( $row->wo_page_id )
         					//: SpecialPage::getTitleFor( $row->wo_page_title );
         					: Title::makeTitle( NS_SPECIAL, $row->wo_page_title );
         */
         if ($oVisitedPageTitle == null || $oVisitedPageTitle->exists() === false || $oVisitedPageTitle->quickUserCan('read') === false) {
             continue;
         }
         $sDisplayTitle = BsStringHelper::shorten($oVisitedPageTitle->getPrefixedText(), array('max-length' => $iMaxTitleLength, 'position' => 'middle'));
         $oVisitedPagesListView->addData(array('WIKILINK' => BsLinkProvider::makeEscapedWikiLinkForTitle($oVisitedPageTitle, $sDisplayTitle)));
         $iItems++;
     }
     //$dbr->freeResult( $res );
     //self::$prResultListViewCache[$sCacheKey] = $oVisitedPagesListView;
     return $oVisitedPagesListView;
 }
 /**
  * Hook-Handler for BlueSpice 'BSExtendedSearchAutocomplete' hook. Creates suggest & create link in autocomplete.
  * @param array &$aResults contains results
  * @param string &$sSearchString search string
  * @param int &$iID number of last item
  * @return bool Always true to keep hooks running.
  */
 public function onBSExtendedSearchAutocomplete(&$aResults, $sSearchString, &$iID, $bTitleExists, $sEcpSearchString)
 {
     if (empty($sSearchString)) {
         return true;
     }
     if ($bTitleExists === true) {
         return true;
     }
     if (BsConfig::get('MW::ExtendedSearch::ShowCreSugInAc') == false) {
         return true;
     }
     $sShortAndEscapedString = BsStringHelper::shorten($sEcpSearchString, array('max-length' => '30', 'position' => 'middle', 'ellipsis-characters' => '...'));
     $oTitle = Title::newFromText($sEcpSearchString);
     if (is_object($oTitle)) {
         if ($oTitle->userCan('createpage') && $oTitle->userCan('edit')) {
             $oItemCreate = new stdClass();
             $oItemCreate->id = ++$iID;
             $oItemCreate->value = $sEcpSearchString;
             $oItemCreate->label = wfMessage('bs-wantedarticle-create-page', '<b>' . $sShortAndEscapedString . '</b>')->plain() . '';
             $oItemCreate->type = '';
             $oItemCreate->link = $oTitle->getFullURL();
             $oItemCreate->attr = 'bs-extendedsearch-ac-noresults';
             $aResults[] = $oItemCreate;
         }
         if ($oTitle->userCan('wantedarticle-suggest')) {
             $oItemSuggest = new stdClass();
             $oItemSuggest->id = ++$iID;
             $oItemSuggest->value = $sEcpSearchString;
             $oItemSuggest->label = wfMessage('bs-wantedarticle-suggest-page', '<b>' . $sShortAndEscapedString . '</b>')->plain() . '';
             $oItemSuggest->type = '';
             $oItemSuggest->link = '#' . $sEcpSearchString;
             $oItemSuggest->attr = 'bs-extendedsearch-suggest';
             $aResults[] = $oItemSuggest;
         }
     }
     return true;
 }