/**
  * Generates a list of the most visisted pages
  * @param string $sInput Inner HTML of BsTagMToplist tag. Not used.
  * @param array $aArgs List of tag attributes.
  * @param Parser $oParser MediaWiki parser object
  * @return string HTML output that is to be displayed.
  */
 public function getToplist($sInput, $aArgs, $oParser)
 {
     $sCat = BsCore::sanitizeArrayEntry($aArgs, 'cat', '', BsPARAMTYPE::STRING);
     $sNs = BsCore::sanitizeArrayEntry($aArgs, 'ns', '', BsPARAMTYPE::STRING);
     $iCount = BsCore::sanitizeArrayEntry($aArgs, 'count', 10, BsPARAMTYPE::INT);
     $sPeriod = BsCore::sanitizeArrayEntry($aArgs, 'period', 'alltime', BsPARAMTYPE::STRING);
     $iPortletPeriod = BsCore::sanitizeArrayEntry($aArgs, 'portletperiod', 0, BsPARAMTYPE::INT);
     $bAlltime = true;
     $oDbr = wfGetDB(DB_SLAVE);
     if (in_array($sPeriod, array('week', 'month')) || in_array($iPortletPeriod, array(7, 30))) {
         $aTables = array('bs_whoisonline');
         $aColumns = array('COUNT( wo_page_title ) AS page_counter', 'wo_page_title', 'wo_page_namespace');
         $aConditions = array('wo_action' => 'view');
         $aOptions = array('GROUP BY' => 'wo_page_title', 'ORDER BY' => 'page_counter DESC');
         $aJoinConditions = array();
         if ($sPeriod === 'week' || $iPortletPeriod === 7) {
             $iTimestamp = wfTimestamp(TS_UNIX) - 7 * 24 * 60 * 60;
             $aConditions[] = 'wo_timestamp >= ' . $iTimestamp;
         }
         $bAlltime = false;
     } else {
         $aTables = array('page');
         $aColumns = array('page_title', 'page_counter', 'page_namespace');
         $aConditions = array();
         $aOptions = array('ORDER BY' => 'page_counter DESC');
         $aJoinConditions = array();
     }
     if (!empty($sCat)) {
         $aCategories = explode(',', $sCat);
         $aCategories = array_map('trim', $aCategories);
         $aCategories = str_replace(' ', '_', $aCategories);
         if ($bAlltime === false) {
             $aColumns[] = 'wo_page_id';
             $aJoinConditions = array('categorylinks' => array('INNER JOIN ', 'wo_page_id = cl_from'));
             $aTables[] = 'categorylinks';
             $aConditions['cl_to'] = $aCategories;
         } else {
             $aTables[] = 'categorylinks';
             $aConditions[] = 'page_id = cl_from';
             $aConditions['cl_to'] = $aCategories;
         }
     }
     if (!empty($sNs) || $sNs === '0') {
         // string 0 is empty
         $aNamespaces = BsNamespaceHelper::getNamespaceIdsFromAmbiguousCSVString($sNs);
         if (!empty($aNamespaces)) {
             $sField = $bAlltime ? 'page_namespace' : 'wo_page_namespace';
             $aConditions[$sField] = $aNamespaces;
         }
     }
     $res = $oDbr->select($aTables, $aColumns, $aConditions, __METHOD__, $aOptions, $aJoinConditions);
     if ($oDbr->numRows($res) > 0) {
         $bCategories = false;
         if (!empty($aCategories)) {
             $bCategories = true;
             $aPrefixedCategories = array();
             foreach ($aCategories as $sCategory) {
                 $sCategory = str_replace(' ', '_', $sCategory);
                 $sCat = Title::makeTitle(NS_CATEGORY, $sCategory);
                 $aPrefixedCategories[] = $sCat->getPrefixedDBKey();
             }
         }
         $aList = array();
         $aInList = array();
         $iCurrCount = 0;
         if ($bAlltime === false) {
             foreach ($res as $row) {
                 if ($iCurrCount === $iCount) {
                     break;
                 }
                 if (empty($row->wo_page_title)) {
                     continue;
                 }
                 $oTitle = Title::makeTitle($row->wo_page_namespace, $row->wo_page_title);
                 if (!$oTitle->quickUserCan('read')) {
                     continue;
                 }
                 if ($bCategories === true) {
                     $aParents = array_keys($oTitle->getParentCategories());
                     $aResult = array_diff($aPrefixedCategories, $aParents);
                     if (!empty($aResult)) {
                         continue;
                     }
                 }
                 if (in_array($oTitle->getPrefixedText(), $aInList)) {
                     continue;
                 }
                 $aInList[] = $oTitle->getPrefixedText();
                 $sLink = BsLinkProvider::makeLink($oTitle);
                 $aList['<li>' . $sLink . ' (' . $row->page_counter . ')</li>'] = (int) $row->page_counter;
                 $iCurrCount++;
             }
             arsort($aList);
             $aList = array_keys($aList);
             array_unshift($aList, '<ol>');
         } else {
             $aList[] = '<ol>';
             foreach ($res as $row) {
                 if ($iCurrCount == $iCount) {
                     break;
                 }
                 if ($row->page_counter == '0') {
                     continue;
                 }
                 $oTitle = Title::makeTitle($row->page_namespace, $row->page_title);
                 if (!$oTitle->quickUserCan('read')) {
                     continue;
                 }
                 if ($bCategories === true) {
                     $aParents = array_keys($oTitle->getParentCategories());
                     $aResult = array_diff($aPrefixedCategories, $aParents);
                     if (!empty($aResult)) {
                         continue;
                     }
                 }
                 if (in_array($oTitle->getPrefixedText(), $aInList)) {
                     continue;
                 }
                 $aInList[] = $oTitle->getPrefixedText();
                 $sLink = BsLinkProvider::makeLink($oTitle);
                 $aList[] = '<li>' . $sLink . ' (' . $row->page_counter . ')</li>';
                 $iCurrCount++;
             }
         }
         $aList[] = '</ol>';
         $oDbr->freeResult($res);
         return "\n" . implode("\n", $aList);
     }
     $oDbr->freeResult($res);
     return wfMessage('bs-smartlist-no-entries')->plain();
 }
 /**
  * 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;
 }