public function execute()
 {
     global $wgDBname;
     if ($this->hasOption('days')) {
         $inactivitydays = $this->getOption('days');
     } else {
         $inactivitydays = 30;
     }
     if ($this->hasOption('timezone')) {
         $timezone = $this->getOption('timezone');
     } else {
         $timezone = 'UTC';
     }
     # Generates a timestamp in yearmonthdayhourminutesecond format of the current time
     date_default_timezone_set($timezone);
     $date = date("YmdHis", strtotime("-{$inactivitydays} days"));
     $dbw = wfGetDB(DB_MASTER);
     $res = $dbw->select('recentchanges', 'rc_timestamp', 'rc_timestamp >= ' . $dbw->addQuotes($date), __METHOD__, array('ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => 1));
     if ($res->numRows() > 0) {
         if ($this->hasOption('display-active')) {
             foreach ($res as $row) {
                 $this->output("The wiki \"{$wgDBname}\" does NOT meet the inactivity requirements, date of last RecentChanges log entry: " . wfTimestamp(TS_DB, $row->rc_timestamp) . "\n");
             }
         }
     } else {
         $res = $dbw->select('recentchanges', 'rc_timestamp', 'rc_timestamp < ' . $dbw->addQuotes($date), __METHOD__, array('ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => 1));
         foreach ($res as $row) {
             $this->output("The wiki \"{$wgDBname}\" DOES meet the inactivity requirements, date of last RecentChanges log entry: " . wfTimeStamp(TS_DB, $row->rc_timestamp) . "\n");
         }
     }
 }
	private function makeCSV( $articles, $name ) {
		$outstream = fopen( "php://output", "w" );
		$headers = array(
			'article',
			'revision',
			'added'
		);
		fputcsv( $outstream, $headers );
		foreach( $articles as $article ) {
			$row = array(
				$article['title']->getFullText(),
				$article['s_revision'],
				wfTimeStamp( TS_ISO_8601, $article['s_timestamp'] )
			);
			fputcsv( $outstream, $row );
		}
		fclose( $outstream );
	}
Exemplo n.º 3
0
 /**
  * This method updates cache entries that are used in properties
  * that are outdated for a single webservice
  *
  */
 private function updateWSResults($ws)
 {
     $log = SGAGardeningIssuesAccess::getGardeningIssuesAccess();
     echo "updating " . $ws->getName() . "\n";
     $parameterSets = WSStorage::getDatabase()->getWSUsages($ws->getArticleID());
     $updatedEntries = 0;
     $affectedArticles = array();
     foreach ($parameterSets as $parameterSet) {
         echo "\t updating paramater set " . $parameterSet["paramSetId"] . "\n";
         $cacheResult = WSStorage::getDatabase()->getResultFromCache($ws->getArticleID(), $parameterSet["paramSetId"]);
         $refresh = false;
         if (count($cacheResult) < 1) {
             $refresh = true;
         }
         if (!$refresh) {
             if ($ws->getQueryPolicy() > 0) {
                 if (wfTime() - wfTimestamp(TS_UNIX, $cacheResult["lastUpdate"]) > $ws->getQueryPolicy() * 60) {
                     $refresh = true;
                 }
             }
         }
         if ($refresh) {
             echo "\t\t update necessary\n";
             if ($updatedEntries > 0) {
                 sleep($ws->getUpdateDelay());
                 echo "\t\t sleeping " . $ws->getUpdateDelay() . "\n";
             }
             $parameters = WSStorage::getDatabase()->getParameters($parameterSet["paramSetId"]);
             $parameters = $ws->initializeCallParameters($parameters);
             $response = $ws->getWSClient()->call($ws->getMethod(), $parameters);
             $goon = true;
             if (is_string($response)) {
                 $log->addGardeningIssueAboutValue($this->id, SMW_GARDISSUE_ERROR_WSCACHE_ENTRIES, Title::newFromText($ws->getName()), 0);
                 $goon = false;
             }
             if ($goon) {
                 WSStorage::getDatabase()->storeCacheEntry($ws->getArticleID(), $parameterSet["paramSetId"], serialize($response), wfTimeStamp(TS_MW, wfTime()), wfTimeStamp(TS_MW, wfTime()));
                 echo "\t\t update was successfully\n";
                 //get articles which have to be refreshed
             }
         }
         $tempAffectedArticles = WSStorage::getDatabase()->getUsedWSParameterSetPairs($ws->getArticleID(), $parameterSet["paramSetId"]);
         if ($ws->getQueryPolicy() > 0) {
             if ($refresh || count($tempAffectedArticles) > 1) {
                 $affectedArticles = array_merge($affectedArticles, $tempAffectedArticles);
             }
             $updatedEntries += 1;
         }
     }
     return $affectedArticles;
 }
 /**
  * Add a new campaign to the database
  * @param $noticeName string: Name of the campaign
  * @param $enabled int: Boolean setting, 0 or 1
  * @param $start array: Start date and time
  * @param $projects array: Targeted project types (wikipedia, wikibooks, etc.)
  * @param $project_languages array: Targeted project languages (en, de, etc.)
  * @param $geotargeted int: Boolean setting, 0 or 1
  * @param $geo_countries array: Targeted countries
  * @return true or null
  */
 function addCampaign($noticeName, $enabled, $start, $projects, $project_languages, $geotargeted, $geo_countries)
 {
     $noticeName = trim($noticeName);
     if (CentralNoticeDB::campaignExists($noticeName)) {
         $this->showError('centralnotice-notice-exists');
         return null;
     } elseif (empty($projects)) {
         $this->showError('centralnotice-no-project');
         return null;
     } elseif (empty($project_languages)) {
         $this->showError('centralnotice-no-language');
         return null;
     } else {
         if (!$geo_countries) {
             $geo_countries = array();
         }
         $dbw = wfGetDB(DB_MASTER);
         $dbw->begin();
         $start['hour'] = substr($start['hour'], 0, 2);
         $start['min'] = substr($start['min'], 0, 2);
         if ($start['month'] == 12) {
             $end['month'] = '01';
             $end['year'] = $start['year'] + 1;
         } elseif ($start['month'] == '09') {
             $end['month'] = '10';
             $end['year'] = $start['year'];
         } else {
             $end['month'] = substr($start['month'], 0, 1) == 0 ? 0 . (intval($start['month']) + 1) : $start['month'] + 1;
             $end['year'] = $start['year'];
         }
         $startTs = wfTimeStamp(TS_MW, "{$start['year']}:{$start['month']}:{$start['day']} " . "{$start['hour']}:{$start['min']}:00");
         $endTs = wfTimeStamp(TS_MW, "{$end['year']}:{$end['month']}:{$start['day']} " . "{$start['hour']}:{$start['min']}:00");
         $res = $dbw->insert('cn_notices', array('not_name' => $noticeName, 'not_enabled' => $enabled, 'not_start' => $dbw->timestamp($startTs), 'not_end' => $dbw->timestamp($endTs), 'not_geo' => $geotargeted));
         $not_id = $dbw->insertId();
         if ($not_id) {
             // Do multi-row insert for campaign projects
             $insertArray = array();
             foreach ($projects as $project) {
                 $insertArray[] = array('np_notice_id' => $not_id, 'np_project' => $project);
             }
             $res = $dbw->insert('cn_notice_projects', $insertArray, __METHOD__, array('IGNORE'));
             // Do multi-row insert for campaign languages
             $insertArray = array();
             foreach ($project_languages as $code) {
                 $insertArray[] = array('nl_notice_id' => $not_id, 'nl_language' => $code);
             }
             $res = $dbw->insert('cn_notice_languages', $insertArray, __METHOD__, array('IGNORE'));
             if ($geotargeted) {
                 // Do multi-row insert for campaign countries
                 $insertArray = array();
                 foreach ($geo_countries as $code) {
                     $insertArray[] = array('nc_notice_id' => $not_id, 'nc_country' => $code);
                 }
                 $res = $dbw->insert('cn_notice_countries', $insertArray, __METHOD__, array('IGNORE'));
             }
             $dbw->commit();
             // Log the creation of the campaign
             $beginSettings = array();
             $endSettings = array('projects' => implode(", ", $projects), 'languages' => implode(", ", $project_languages), 'countries' => implode(", ", $geo_countries), 'start' => $dbw->timestamp($startTs), 'end' => $dbw->timestamp($endTs), 'enabled' => $enabled, 'preferred' => 0, 'locked' => 0, 'geo' => $geotargeted);
             $this->logCampaignChange('created', $not_id, $beginSettings, $endSettings);
             return true;
         } else {
             return null;
         }
     }
 }
 protected function makeUserList($users, $stats)
 {
     $day = 60 * 60 * 24;
     // Scale of the activity colors, anything
     // longer than this is just inactive
     $period = $this->period;
     $links = array();
     $statsTable = new StatsTable();
     foreach ($users as $username => $count) {
         $title = Title::makeTitleSafe(NS_USER, $username);
         $enc = htmlspecialchars($username);
         $attribs = array();
         $styles = array();
         if (isset($stats[$username][0])) {
             if ($count === -1) {
                 $count = $stats[$username][0];
             }
             $styles['font-size'] = round(log($count, 10) * 30) + 70 . '%';
             $last = wfTimestamp(TS_UNIX) - wfTimeStamp(TS_UNIX, $stats[$username][1]);
             $last = round($last / $day);
             $attribs['title'] = $this->msg('supportedlanguages-activity', $username)->numParams($count, $last)->text();
             $last = max(1, min($period, $last));
             $styles['border-bottom'] = '3px solid #' . $statsTable->getBackgroundColor($period - $last, $period);
         } else {
             $enc = "<del>{$enc}</del>";
         }
         $stylestr = $this->formatStyle($styles);
         if ($stylestr) {
             $attribs['style'] = $stylestr;
         }
         $links[] = Linker::link($title, $enc, $attribs);
     }
     // for GENDER support
     $username = '';
     if (count($users) === 1) {
         $keys = array_keys($users);
         $username = $keys[0];
     }
     $linkList = $this->getLanguage()->listToText($links);
     $html = "<p class='mw-translate-spsl-translators'>";
     $html .= $this->msg('supportedlanguages-translators')->rawParams($linkList)->numParams(count($links))->params($username)->escaped();
     $html .= "</p>\n";
     $this->getOutput()->addHTML($html);
 }
Exemplo n.º 6
0
 public static function dynamicPageList($input, $params, $parser, &$bReset, $calledInMode)
 {
     // Output
     $output = '';
     error_reporting(E_ALL);
     global $wgUser, $wgLang, $wgContLang, $wgRequest;
     global $wgNonincludableNamespaces;
     //logger (display of debug messages)
     $logger = new DPLLogger();
     //check that we are not in an infinite transclusion loop
     if (isset($parser->mTemplatePath[$parser->mTitle->getPrefixedText()])) {
         return $logger->escapeMsg(ExtDynamicPageList::WARN_TRANSCLUSIONLOOP, $parser->mTitle->getPrefixedText());
     }
     /**
      * Initialization
      */
     $dplStartTime = microtime(true);
     // Local parser created. See http://www.mediawiki.org/wiki/Extensions_FAQ#How_do_I_render_wikitext_in_my_extension.3F
     $localParser = new Parser();
     $pOptions = $parser->mOptions;
     // check if DPL shall only be executed from protected pages
     if (array_key_exists('RunFromProtectedPagesOnly', ExtDynamicPageList::$options) && ExtDynamicPageList::$options['RunFromProtectedPagesOnly'] == true && !$parser->mTitle->isProtected('edit')) {
         // Ideally we would like to allow using a DPL query if the query istelf is coded on a template page
         // which is protected. Then there would be no need for the article to be protected.
         // BUT: How can one find out from which wiki source an extension has been invoked???
         return ExtDynamicPageList::$options['RunFromProtectedPagesOnly'];
     }
     // get database access
     $dbr =& wfGetDB(DB_SLAVE);
     $sPageTable = $dbr->tableName('page');
     $sCategorylinksTable = $dbr->tableName('categorylinks');
     // Extension variables
     // Allowed namespaces for DPL: all namespaces except the first 2: Media (-2) and Special (-1), because we cannot use the DB for these to generate dynamic page lists.
     if (!is_array(ExtDynamicPageList::$allowedNamespaces)) {
         // Initialization
         $aNs = $wgContLang->getNamespaces();
         ExtDynamicPageList::$allowedNamespaces = array_slice($aNs, 2, count($aNs), true);
         if (!is_array(ExtDynamicPageList::$options['namespace'])) {
             ExtDynamicPageList::$options['namespace'] = ExtDynamicPageList::$allowedNamespaces;
         } else {
             // Make sure user namespace options are allowed.
             ExtDynamicPageList::$options['namespace'] = array_intersect(ExtDynamicPageList::$options['namespace'], ExtDynamicPageList::$allowedNamespaces);
         }
         if (!isset(ExtDynamicPageList::$options['namespace']['default'])) {
             ExtDynamicPageList::$options['namespace']['default'] = null;
         }
         if (!is_array(ExtDynamicPageList::$options['notnamespace'])) {
             ExtDynamicPageList::$options['notnamespace'] = ExtDynamicPageList::$allowedNamespaces;
         } else {
             ExtDynamicPageList::$options['notnamespace'] = array_intersect(ExtDynamicPageList::$options['notnamespace'], ExtDynamicPageList::$allowedNamespaces);
         }
         if (!isset(ExtDynamicPageList::$options['notnamespace']['default'])) {
             ExtDynamicPageList::$options['notnamespace']['default'] = null;
         }
     }
     // check parameters which can be set via the URL
     self::getUrlArgs();
     if (strpos($input, '{%DPL_') >= 0) {
         for ($i = 1; $i <= 5; $i++) {
             $input = self::resolveUrlArg($input, 'DPL_arg' . $i);
         }
     }
     $_sOffset = $wgRequest->getVal('DPL_offset', ExtDynamicPageList::$options['offset']['default']);
     $iOffset = $_sOffset == '' ? 0 : intval($_sOffset);
     // commandline parameters like %DPL_offset% are replaced
     $input = self::resolveUrlArg($input, 'DPL_offset');
     $input = self::resolveUrlArg($input, 'DPL_count');
     $input = self::resolveUrlArg($input, 'DPL_fromTitle');
     $input = self::resolveUrlArg($input, 'DPL_findTitle');
     $input = self::resolveUrlArg($input, 'DPL_toTitle');
     // variables needed for scrolling
     $sCount = '';
     $sCountScroll = '';
     $sTitleGE = '';
     $sTitleLE = '';
     $scrollDir = '';
     $originalInput = $input;
     $bDPLRefresh = $wgRequest->getVal('DPL_refresh', '') == 'yes';
     // Options
     $DPLCache = '';
     $DPLCachePath = '';
     $DPLCacheStorage = ExtDynamicPageList::$options['dplcachestorage']['default'];
     $iDPLCachePeriod = intval(ExtDynamicPageList::$options['dplcacheperiod']['default']);
     $sGoal = ExtDynamicPageList::$options['goal']['default'];
     $bSelectionCriteriaFound = false;
     $bConflictsWithOpenReferences = false;
     // array for LINK / TEMPLATE / CATGEORY / IMAGE  by RESET / ELIMINATE
     if (ExtDynamicPageList::$options['eliminate'] == 'all') {
         $bReset = array(false, false, false, false, true, true, true, true);
     } else {
         $bReset = array(false, false, false, false, false, false, false, false);
     }
     // we allow " like " or "="
     $sCategoryComparisonMode = '=';
     $sNotCategoryComparisonMode = '=';
     $sTitleMatchMode = ' LIKE ';
     $sNotTitleMatchMode = ' LIKE ';
     // execAndExit
     $sExecAndExit = ExtDynamicPageList::$options['execandexit']['default'];
     // ordermethod, order, mode, userdateformat, allowcachedresults:
     // if we have to behave like Extension:Intersection we use different default values for some commands
     if (ExtDynamicPageList::$behavingLikeIntersection) {
         ExtDynamicPageList::$options['ordermethod'] = array('default' => 'categoryadd', 'categoryadd', 'lastedit', 'none');
         ExtDynamicPageList::$options['order'] = array('default' => 'descending', 'ascending', 'descending');
         ExtDynamicPageList::$options['mode'] = array('default' => 'unordered', 'none', 'ordered', 'unordered');
         ExtDynamicPageList::$options['userdateformat'] = array('default' => 'Y-m-d: ');
         ExtDynamicPageList::$options['allowcachedresults']['default'] = 'true';
     } else {
         ExtDynamicPageList::$options['ordermethod'] = array('default' => 'titlewithoutnamespace', 'counter', 'size', 'category', 'sortkey', 'category,firstedit', 'category,lastedit', 'category,pagetouched', 'category,sortkey', 'categoryadd', 'firstedit', 'lastedit', 'pagetouched', 'pagesel', 'title', 'titlewithoutnamespace', 'user', 'user,firstedit', 'user,lastedit', 'none');
         ExtDynamicPageList::$options['order'] = array('default' => 'ascending', 'ascending', 'descending');
         ExtDynamicPageList::$options['mode'] = array('default' => 'unordered', 'category', 'inline', 'none', 'ordered', 'unordered', 'userformat');
         ExtDynamicPageList::$options['userdateformat'] = array('default' => 'Y-m-d H:i:s');
         ExtDynamicPageList::$options['allowcachedresults']['default'] = ExtDynamicPageList::$respectParserCache;
     }
     $aOrderMethods = array(ExtDynamicPageList::$options['ordermethod']['default']);
     $sOrder = ExtDynamicPageList::$options['order']['default'];
     $sOrderCollation = ExtDynamicPageList::$options['ordercollation']['default'];
     $sPageListMode = ExtDynamicPageList::$options['mode']['default'];
     $sUserDateFormat = ExtDynamicPageList::$options['userdateformat']['default'];
     $sHListMode = ExtDynamicPageList::$options['headingmode']['default'];
     $bHeadingCount = self::argBoolean(ExtDynamicPageList::$options['headingcount']['default']);
     $bEscapeLinks = ExtDynamicPageList::$options['escapelinks']['default'];
     $bSkipThisPage = ExtDynamicPageList::$options['skipthispage']['default'];
     $sHiddenCategories = ExtDynamicPageList::$options['hiddencategories']['default'];
     $sMinorEdits = null;
     $acceptOpenReferences = self::argBoolean(ExtDynamicPageList::$options['openreferences']['default']);
     $sLastRevisionBefore = ExtDynamicPageList::$options['lastrevisionbefore']['default'];
     $sAllRevisionsBefore = ExtDynamicPageList::$options['allrevisionsbefore']['default'];
     $sFirstRevisionSince = ExtDynamicPageList::$options['firstrevisionsince']['default'];
     $sAllRevisionsSince = ExtDynamicPageList::$options['allrevisionssince']['default'];
     $_sMinRevisions = ExtDynamicPageList::$options['minrevisions']['default'];
     $iMinRevisions = $_sMinRevisions == '' ? null : intval($_sMinRevisions);
     $_sMaxRevisions = ExtDynamicPageList::$options['maxrevisions']['default'];
     $iMaxRevisions = $_sMaxRevisions == '' ? null : intval($_sMaxRevisions);
     $sRedirects = ExtDynamicPageList::$options['redirects']['default'];
     $sQuality = ExtDynamicPageList::$options['qualitypages']['default'];
     $sStable = ExtDynamicPageList::$options['stablepages']['default'];
     $bSuppressErrors = self::argBoolean(ExtDynamicPageList::$options['suppresserrors']['default']);
     $sResultsHeader = ExtDynamicPageList::$options['resultsheader']['default'];
     $sResultsFooter = ExtDynamicPageList::$options['resultsfooter']['default'];
     $sNoResultsHeader = ExtDynamicPageList::$options['noresultsheader']['default'];
     $sNoResultsFooter = ExtDynamicPageList::$options['noresultsfooter']['default'];
     $sOneResultHeader = ExtDynamicPageList::$options['oneresultheader']['default'];
     $sOneResultFooter = ExtDynamicPageList::$options['oneresultfooter']['default'];
     $aListSeparators = array();
     $sTable = ExtDynamicPageList::$options['table']['default'];
     $aTableRow = array();
     $iTableSortCol = ExtDynamicPageList::$options['tablesortcol']['default'];
     $sInlTxt = ExtDynamicPageList::$options['inlinetext']['default'];
     $bShowNamespace = self::argBoolean(ExtDynamicPageList::$options['shownamespace']['default']);
     $bShowCurID = self::argBoolean(ExtDynamicPageList::$options['showcurid']['default']);
     $bAddFirstCategoryDate = self::argBoolean(ExtDynamicPageList::$options['addfirstcategorydate']['default']);
     $bAddPageCounter = self::argBoolean(ExtDynamicPageList::$options['addpagecounter']['default']);
     $bAddPageSize = self::argBoolean(ExtDynamicPageList::$options['addpagesize']['default']);
     $bAddPageTouchedDate = self::argBoolean(ExtDynamicPageList::$options['addpagetoucheddate']['default']);
     $bAddEditDate = self::argBoolean(ExtDynamicPageList::$options['addeditdate']['default']);
     $bAddUser = self::argBoolean(ExtDynamicPageList::$options['adduser']['default']);
     $bAddAuthor = self::argBoolean(ExtDynamicPageList::$options['addauthor']['default']);
     $bAddContribution = self::argBoolean(ExtDynamicPageList::$options['addcontribution']['default']);
     $bAddLastEditor = self::argBoolean(ExtDynamicPageList::$options['addlasteditor']['default']);
     $bAddExternalLink = self::argBoolean(ExtDynamicPageList::$options['addexternallink']['default']);
     $bAllowCachedResults = self::argBoolean(ExtDynamicPageList::$options['allowcachedresults']['default']);
     $bWarnCachedResults = false;
     $bAddCategories = self::argBoolean(ExtDynamicPageList::$options['addcategories']['default']);
     $bIncludeSubpages = self::argBoolean(ExtDynamicPageList::$options['includesubpages']['default']);
     $bIncludeTrim = self::argBoolean(ExtDynamicPageList::$options['includetrim']['default']);
     $bIgnoreCase = self::argBoolean(ExtDynamicPageList::$options['ignorecase']['default']);
     $_incpage = ExtDynamicPageList::$options['includepage']['default'];
     $bIncPage = is_string($_incpage) && $_incpage !== '';
     $aSecLabels = array();
     if ($bIncPage) {
         $aSecLabels = explode(',', $_incpage);
     }
     $aSecLabelsMatch = array();
     $aSecLabelsNotMatch = array();
     $bIncParsed = false;
     // default is to match raw parameters
     $aSecSeparators = explode(',', ExtDynamicPageList::$options['secseparators']['default']);
     $aMultiSecSeparators = explode(',', ExtDynamicPageList::$options['multisecseparators']['default']);
     $iDominantSection = ExtDynamicPageList::$options['dominantsection']['default'];
     $_sColumns = ExtDynamicPageList::$options['columns']['default'];
     $iColumns = $_sColumns == '' ? 1 : intval($_sColumns);
     $_sRows = ExtDynamicPageList::$options['rows']['default'];
     $iRows = $_sRows == '' ? 1 : intval($_sRows);
     $_sRowSize = ExtDynamicPageList::$options['rowsize']['default'];
     $iRowSize = $_sRowSize == '' ? 0 : intval($_sRowSize);
     $sRowColFormat = ExtDynamicPageList::$options['rowcolformat']['default'];
     $_sRandomSeed = ExtDynamicPageList::$options['randomseed']['default'];
     $iRandomSeed = $_sRandomSeed == '' ? null : intval($_sRandomSeed);
     $_sRandomCount = ExtDynamicPageList::$options['randomcount']['default'];
     $iRandomCount = $_sRandomCount == '' ? null : intval($_sRandomCount);
     $sDistinctResultSet = 'true';
     $sListHtmlAttr = ExtDynamicPageList::$options['listattr']['default'];
     $sItemHtmlAttr = ExtDynamicPageList::$options['itemattr']['default'];
     $sHListHtmlAttr = ExtDynamicPageList::$options['hlistattr']['default'];
     $sHItemHtmlAttr = ExtDynamicPageList::$options['hitemattr']['default'];
     $_sTitleMaxLen = ExtDynamicPageList::$options['titlemaxlength']['default'];
     $iTitleMaxLen = $_sTitleMaxLen == '' ? null : intval($_sTitleMaxLen);
     $aReplaceInTitle[0] = '';
     $aReplaceInTitle[1] = '';
     $_sCatMinMax = ExtDynamicPageList::$options['categoriesminmax']['default'];
     $aCatMinMax = $_sCatMinMax == '' ? null : explode(',', $_sCatMinMax);
     $_sIncludeMaxLen = ExtDynamicPageList::$options['includemaxlength']['default'];
     $iIncludeMaxLen = $_sIncludeMaxLen == '' ? null : intval($_sIncludeMaxLen);
     $bScroll = self::argBoolean(ExtDynamicPageList::$options['scroll']['default']);
     $aLinksTo = array();
     $aNotLinksTo = array();
     $aLinksFrom = array();
     $aNotLinksFrom = array();
     $aLinksToExternal = array();
     $aImageUsed = array();
     $aImageContainer = array();
     $aUses = array();
     $aNotUses = array();
     $aUsedBy = array();
     $sCreatedBy = '';
     $sNotCreatedBy = '';
     $sModifiedBy = '';
     $sNotModifiedBy = '';
     $sLastModifiedBy = '';
     $sNotLastModifiedBy = '';
     $aTitleMatch = array();
     $aNotTitleMatch = array();
     $sTitleIs = '';
     $aIncludeCategories = array();
     // $aIncludeCategories is a 2-dimensional array: Memberarrays are linked using 'AND'
     $aExcludeCategories = array();
     $aCatHeadings = array();
     $aCatNotHeadings = array();
     $aNamespaces = array();
     $aExcludeNamespaces = array();
     $sArticleCategory = null;
     $sUpdateRules = ExtDynamicPageList::$options['updaterules']['default'];
     $sDeleteRules = ExtDynamicPageList::$options['deleterules']['default'];
     $bOrderSuitSymbols = false;
     // ###### PARSE PARAMETERS ######
     // we replace double angle brackets by < > ; thus we avoid premature tag expansion in the input
     $input = str_replace('»', '>', $input);
     $input = str_replace('«', '<', $input);
     // use the ¦ as a general alias for |
     $input = str_replace('¦', '|', $input);
     // the symbol is utf8-escaped
     // the combination '²{' and '}²'will be translated to double curly braces; this allows postponed template execution
     // which is crucial for DPL queries which call other DPL queries
     $input = str_replace('²{', '{{', $input);
     $input = str_replace('}²', '}}', $input);
     $aParams = explode("\n", $input);
     $bIncludeUncat = false;
     // to check if pseudo-category of Uncategorized pages is included
     // version 0.9:
     // we do not parse parameters recursively when reading them in.
     // we rather leave them unchanged, produce the complete output and then finally
     // parse the result recursively. This allows to build complex structures in the output
     // which are only understood by the parser if seen as a whole
     foreach ($aParams as $iParam => $sParam) {
         $aParam = explode('=', $sParam, 2);
         if (count($aParam) < 2) {
             if (trim($aParam[0]) != '') {
                 $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, $aParam[0] . " [missing '=']", self::validParametersList());
             }
             continue;
         }
         $sType = trim($aParam[0]);
         $sArg = trim($aParam[1]);
         if ($sType == '') {
             $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, '[empty string]', self::validParametersList());
             continue;
         }
         // ignore comment lines
         if ($sType[0] == '#') {
             continue;
         }
         // ignore parameter settings without argument (except namespace and category)
         if ($sArg == '') {
             if ($sType != 'namespace' && $sType != 'notnamespace' && $sType != 'category' && array_key_exists($sType, ExtDynamicPageList::$options)) {
                 continue;
             }
         }
         // for each level of functionalRichness we have a separate block of options
         // the first block is always active ($functionalRichness>=0)
         //------------------------------------------------------------------------------------------- level 0
         $validOptionFound = true;
         switch ($sType) {
             /**
              * FILTER PARAMETERS
              */
             case 'category':
                 // Init array of categories to include
                 $aCategories = array();
                 $bHeading = false;
                 $bNotHeading = false;
                 if ($sArg != '' && $sArg[0] == '+') {
                     // categories are headings
                     $bHeading = true;
                     $sArg[0] = '';
                 }
                 if ($sArg != '' && $sArg[0] == '-') {
                     // categories are NOT headings
                     $bNotHeading = true;
                     $sArg[0] = '';
                 }
                 $op = 'OR';
                 // we expand html entities because they contain an '& 'which would be interpreted as an AND condition
                 $sArg = html_entity_decode($sArg, ENT_QUOTES);
                 if (strpos($sArg, '&') !== false) {
                     $aParams = explode('&', $sArg);
                     $op = 'AND';
                 } else {
                     $aParams = explode('|', $sArg);
                 }
                 foreach ($aParams as $sParam) {
                     $sParam = trim($sParam);
                     if ($sParam == '') {
                         // ignore empty line
                     } else {
                         if ($sParam == '_none_') {
                             // include uncategorized pages (special value: empty string)
                             $aParams[$sParam] = '';
                             $bIncludeUncat = true;
                             $aCategories[] = '';
                         } else {
                             if ($sParam[0] == '*' && strlen($sParam) >= 2) {
                                 if ($sParam[1] == '*') {
                                     $sParamList = explode('|', self::getSubcategories(substr($sParam, 2), $sPageTable, 2));
                                 } else {
                                     $sParamList = explode('|', self::getSubcategories(substr($sParam, 1), $sPageTable, 1));
                                 }
                                 foreach ($sParamList as $sPar) {
                                     $title = Title::newFromText($sPar);
                                     if (!is_null($title)) {
                                         $aCategories[] = $title->getDbKey();
                                     }
                                 }
                             } else {
                                 $title = Title::newFromText($sParam);
                                 if (!is_null($title)) {
                                     $aCategories[] = $title->getDbKey();
                                 }
                             }
                         }
                     }
                 }
                 if (!empty($aCategories)) {
                     if ($op == 'OR') {
                         $aIncludeCategories[] = $aCategories;
                     } else {
                         foreach ($aCategories as $aParams) {
                             $sParam = array();
                             $sParam[] = $aParams;
                             $aIncludeCategories[] = $sParam;
                         }
                     }
                     if ($bHeading) {
                         $aCatHeadings = array_unique($aCatHeadings + $aCategories);
                     }
                     if ($bNotHeading) {
                         $aCatNotHeadings = array_unique($aCatNotHeadings + $aCategories);
                     }
                     $bConflictsWithOpenReferences = true;
                 }
                 break;
             case 'hiddencategories':
                 if (in_array($sArg, ExtDynamicPageList::$options['hiddencategories'])) {
                     $sHiddenCategories = $sArg;
                 } else {
                     $output .= $logger->msgWrongParam('hiddencategories', $sArg);
                 }
                 break;
             case 'notcategory':
                 $title = Title::newFromText($sArg);
                 if (!is_null($title)) {
                     $aExcludeCategories[] = $title->getDbKey();
                     $bConflictsWithOpenReferences = true;
                 }
                 break;
             case 'namespace':
                 $aParams = explode('|', $sArg);
                 foreach ($aParams as $sParam) {
                     $sParam = trim($sParam);
                     $sNs = $sParam;
                     if (in_array($sNs, ExtDynamicPageList::$options['namespace'])) {
                         $aNamespaces[] = $wgContLang->getNsIndex($sNs);
                         $bSelectionCriteriaFound = true;
                     } else {
                         if (array_key_exists($sNs, array_keys(ExtDynamicPageList::$options['namespace']))) {
                             $aNamespaces[] = $sNs;
                             $bSelectionCriteriaFound = true;
                         } else {
                             return $logger->msgWrongParam('namespace', $sParam);
                         }
                     }
                 }
                 break;
             case 'redirects':
                 if (in_array($sArg, ExtDynamicPageList::$options['redirects'])) {
                     $sRedirects = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('redirects', $sArg);
                 }
                 break;
             case 'stablepages':
                 if (in_array($sArg, ExtDynamicPageList::$options['stablepages'])) {
                     $sStable = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('stablepages', $sArg);
                 }
                 break;
             case 'qualitypages':
                 if (in_array($sArg, ExtDynamicPageList::$options['qualitypages'])) {
                     $sQuality = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('qualitypages', $sArg);
                 }
                 break;
             case 'count':
                 // setting by URL overwrites other settings, hence we ignore the command
                 if ($sCount == '') {
                     $sCount = trim($sArg);
                 }
                 break;
                 /**
                  * CONTENT PARAMETERS
                  */
             /**
              * CONTENT PARAMETERS
              */
             case 'addfirstcategorydate':
                 if (in_array($sArg, ExtDynamicPageList::$options['addfirstcategorydate'])) {
                     $bAddFirstCategoryDate = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addfirstcategorydate', $sArg);
                 }
                 break;
                 /**
                  * ORDER PARAMETERS
                  */
             /**
              * ORDER PARAMETERS
              */
             case 'ordermethod':
                 $methods = explode(',', $sArg);
                 $breakaway = false;
                 foreach ($methods as $method) {
                     if (!in_array($method, ExtDynamicPageList::$options['ordermethod'])) {
                         $output .= $logger->msgWrongParam('ordermethod', $method);
                         $breakaway = true;
                     }
                 }
                 if (!$breakaway) {
                     $aOrderMethods = $methods;
                     if ($methods[0] != 'none') {
                         $bConflictsWithOpenReferences = true;
                     }
                 }
                 break;
             case 'order':
                 if (in_array($sArg, ExtDynamicPageList::$options['order'])) {
                     $sOrder = $sArg;
                 } else {
                     $output .= $logger->msgWrongParam('order', $sArg);
                 }
                 break;
                 /**
                  * FORMAT/HTML PARAMETERS
                  * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
                  */
             /**
              * FORMAT/HTML PARAMETERS
              * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
              */
             case 'mode':
                 if (in_array($sArg, ExtDynamicPageList::$options['mode'])) {
                     //'none' mode is implemented as a specific submode of 'inline' with <br/> as inline text
                     if ($sArg == 'none') {
                         $sPageListMode = 'inline';
                         $sInlTxt = '<br/>';
                     } else {
                         if ($sArg == 'userformat') {
                             // userformat resets inline text to empty string
                             $sInlTxt = '';
                             $sPageListMode = $sArg;
                         } else {
                             $sPageListMode = $sArg;
                         }
                     }
                 } else {
                     $output .= $logger->msgWrongParam('mode', $sArg);
                 }
                 break;
             case 'showcurid':
                 if (in_array($sArg, ExtDynamicPageList::$options['showcurid'])) {
                     $bShowCurID = self::argBoolean($sArg);
                     if ($bShowCurID == true) {
                         $bConflictsWithOpenReferences = true;
                     }
                 } else {
                     $output .= $logger->msgWrongParam('showcurid', $sArg);
                 }
                 break;
             case 'shownamespace':
                 if (in_array($sArg, ExtDynamicPageList::$options['shownamespace'])) {
                     $bShowNamespace = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('shownamespace', $sArg);
                 }
                 break;
             case 'suppresserrors':
                 if (in_array($sArg, ExtDynamicPageList::$options['suppresserrors'])) {
                     $bSuppressErrors = self::argBoolean($sArg);
                     if ($bSuppressErrors) {
                         $sNoResultsHeader = ' ';
                     }
                 } else {
                     $output .= $logger->msgWrongParam('suppresserrors', $sArg);
                 }
                 break;
                 /**
                  * OTHER PARAMETER
                  */
             /**
              * OTHER PARAMETER
              */
             case 'execandexit':
                 // we offer a possibility to execute a DPL command without querying the database
                 // this is useful if you want to catch the command line parameters DPL_arg1,... etc
                 // in this case we prevent the parser cache from being disabled by later statements
                 $sExecAndExit = $sArg;
                 break;
                 /**
                  * UNKNOWN PARAMETER
                  */
             /**
              * UNKNOWN PARAMETER
              */
             default:
                 $validOptionFound = false;
         }
         if ($validOptionFound) {
             continue;
         }
         // the next blocks are only available if $functionalRichness > 0
         if (ExtDynamicPageList::$functionalRichness <= 0) {
             $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, $sType, self::validParametersList());
             continue;
         }
         //------------------------------------------------------------------------------------------- level 1
         $validOptionFound = true;
         switch ($sType) {
             /**
              * FILTER PARAMETERS
              */
             case 'notnamespace':
                 $sArg = trim($sArg);
                 $sNs = $sArg;
                 if (!in_array($sNs, ExtDynamicPageList::$options['notnamespace'])) {
                     return $logger->msgWrongParam('notnamespace', $sArg);
                 }
                 $aExcludeNamespaces[] = $wgContLang->getNsIndex($sNs);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'offset':
                 //ensure that $iOffset is a number
                 if (preg_match(ExtDynamicPageList::$options['offset']['pattern'], $sArg)) {
                     $iOffset = $sArg == '' ? 0 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('offset', $sArg);
                 }
                 break;
             case 'randomseed':
                 //ensure that $iRandomSeed is a number;
                 if (preg_match(ExtDynamicPageList::$options['randomseed']['pattern'], $sArg)) {
                     $iRandomSeed = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('randomseed', $sArg);
                 }
                 break;
             case 'randomcount':
                 //ensure that $iRandomCount is a number;
                 if (preg_match(ExtDynamicPageList::$options['randomcount']['pattern'], $sArg)) {
                     $iRandomCount = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('randomcount', $sArg);
                 }
                 break;
             case 'distinct':
                 if (in_array($sArg, ExtDynamicPageList::$options['distinct'])) {
                     if ($sArg == 'strict') {
                         $sDistinctResultSet = 'strict';
                     } else {
                         if (self::argBoolean($sArg)) {
                             $sDistinctResultSet = 'true';
                         } else {
                             $sDistinctResultSet = 'false';
                         }
                     }
                 } else {
                     $output .= $logger->msgWrongParam('distinct', $sArg);
                 }
                 break;
                 /*
                  * ORDER PARAMETERS
                  */
             /*
              * ORDER PARAMETERS
              */
             case 'ordercollation':
                 if ($sArg == 'bridge') {
                     $bOrderSuitSymbols = true;
                 } else {
                     if ($sArg != '') {
                         $sOrderCollation = "COLLATE {$sArg}";
                     }
                 }
                 break;
                 /**
                  * FORMAT/HTML PARAMETERS
                  * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
                  */
             /**
              * FORMAT/HTML PARAMETERS
              * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
              */
             case 'columns':
                 //ensure that $iColumns is a number
                 if (preg_match(ExtDynamicPageList::$options['columns']['pattern'], $sArg)) {
                     $iColumns = $sArg == '' ? 1 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('columns', $sArg);
                 }
                 break;
             case 'rows':
                 //ensure that $iRows is a number
                 if (preg_match(ExtDynamicPageList::$options['rows']['pattern'], $sArg)) {
                     $iRows = $sArg == '' ? 1 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('rows', $sArg);
                 }
                 break;
             case 'rowsize':
                 //ensure that $iRowSize is a number
                 if (preg_match(ExtDynamicPageList::$options['rowsize']['pattern'], $sArg)) {
                     $iRowSize = $sArg == '' ? 0 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('rowsize', $sArg);
                 }
                 break;
             case 'rowcolformat':
                 $sRowColFormat = self::killHtmlTags($sArg);
                 break;
             case 'userdateformat':
                 $sUserDateFormat = self::killHtmlTags($sArg);
                 break;
             case 'escapelinks':
                 if (in_array($sArg, ExtDynamicPageList::$options['escapelinks'])) {
                     $bEscapeLinks = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('escapelinks', $sArg);
                 }
                 break;
             case 'inlinetext':
                 $sInlTxt = self::killHtmlTags($sArg);
                 break;
             case 'format':
             case 'listseparators':
                 // parsing of wikitext will happen at the end of the output phase
                 // we replace '\n' in the input by linefeed because wiki syntax depends on linefeeds
                 $sArg = self::killHtmlTags($sArg);
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 $aListSeparators = explode(',', $sArg, 4);
                 // mode=userformat will be automatically assumed
                 $sPageListMode = 'userformat';
                 $sInlTxt = '';
                 break;
             case 'title':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $title = Title::newFromText($sArg);
                 if ($title) {
                     $sNamespace = $title->getNamespace();
                     $sTitleIs = str_replace(' ', '_', $title->getText());
                     $aNamespaces[0] = $sNamespace;
                     $sPageListMode = 'userformat';
                     $aOrderMethods = explode(',', '');
                     $bSelectionCriteriaFound = true;
                     $bConflictsWithOpenReferences = true;
                     $bAllowCachedResults = true;
                 }
                 break;
             case 'title>':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $sTitleGE = str_replace(' ', '_', $sArg);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'title<':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $sTitleLE = str_replace(' ', '_', $sArg);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'scroll':
                 if (in_array($sArg, ExtDynamicPageList::$options['scroll'])) {
                     $bScroll = self::argBoolean($sArg);
                     // if scrolling is active we adjust the values for certain other parameters
                     // based on URL arguments
                     if ($bScroll) {
                         $sTitleGE = $wgRequest->getVal('DPL_fromTitle', '');
                         if (strlen($sTitleGE) > 0) {
                             $sTitleGE[0] = strtoupper($sTitleGE[0]);
                         }
                         // findTitle has priority over fromTitle
                         $findTitle = $wgRequest->getVal('DPL_findTitle', '');
                         if (strlen($findTitle) > 0) {
                             $findTitle[0] = strtoupper($findTitle[0]);
                         }
                         if ($findTitle != '') {
                             $sTitleGE = '=_' . $findTitle;
                         }
                         $sTitleLE = $wgRequest->getVal('DPL_toTitle', '');
                         if (strlen($sTitleLE) > 0) {
                             $sTitleLE[0] = strtoupper($sTitleLE[0]);
                         }
                         $sTitleGE = str_replace(' ', '_', $sTitleGE);
                         $sTitleLE = str_replace(' ', '_', $sTitleLE);
                         $scrollDir = $wgRequest->getVal('DPL_scrollDir', '');
                         // also set count limit from URL if not otherwise set
                         $sCountScroll = $wgRequest->getVal('DPL_count', '');
                     }
                 } else {
                     $output .= $logger->msgWrongParam('scroll', $sArg);
                 }
                 break;
             case 'titlemaxlength':
                 //processed like 'count' param
                 if (preg_match(ExtDynamicPageList::$options['titlemaxlength']['pattern'], $sArg)) {
                     $iTitleMaxLen = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('titlemaxlength', $sArg);
                 }
                 break;
             case 'replaceintitle':
                 // we offer a possibility to replace some part of the title
                 $aReplaceInTitle = explode(',', $sArg, 2);
                 if (isset($aReplaceInTitle[1])) {
                     $aReplaceInTitle[1] = self::killHtmlTags($aReplaceInTitle[1]);
                 }
                 break;
             case 'resultsheader':
                 $sResultsHeader = self::killHtmlTags($sArg);
                 break;
             case 'resultsfooter':
                 $sResultsFooter = self::killHtmlTags($sArg);
                 break;
             case 'noresultsheader':
                 $sNoResultsHeader = self::killHtmlTags($sArg);
                 break;
             case 'noresultsfooter':
                 $sNoResultsFooter = self::killHtmlTags($sArg);
                 break;
             case 'oneresultheader':
                 $sOneResultHeader = self::killHtmlTags($sArg);
                 break;
             case 'oneresultfooter':
                 $sOneResultFooter = self::killHtmlTags($sArg);
                 break;
                 /**
                  * DEBUG, RESET and CACHE PARAMETER
                  */
             /**
              * DEBUG, RESET and CACHE PARAMETER
              */
             case 'debug':
                 if (in_array($sArg, ExtDynamicPageList::$options['debug'])) {
                     if ($iParam > 1) {
                         $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_DEBUGPARAMNOTFIRST, $sArg);
                     }
                     $logger->iDebugLevel = intval($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('debug', $sArg);
                 }
                 break;
                 /**
                  * UNKNOWN PARAMETER
                  */
             /**
              * UNKNOWN PARAMETER
              */
             default:
                 $validOptionFound = false;
         }
         if ($validOptionFound) {
             continue;
         }
         if (ExtDynamicPageList::$functionalRichness <= 1) {
             $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, $sType, self::validParametersList());
             continue;
         }
         //------------------------------------------------------------------------------------------- level 2
         $validOptionFound = true;
         switch ($sType) {
             /**
              * FILTER PARAMETERS
              */
             case 'linksto':
                 $problems = self::getPageNameList('linksto', $sArg, $aLinksTo, $bSelectionCriteriaFound, $logger, true);
                 if ($problems != '') {
                     return $problems;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notlinksto':
                 $problems = self::getPageNameList('notlinksto', $sArg, $aNotLinksTo, $bSelectionCriteriaFound, $logger, true);
                 if ($problems != '') {
                     return $problems;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'linksfrom':
                 $problems = self::getPageNameList('linksfrom', $sArg, $aLinksFrom, $bSelectionCriteriaFound, $logger, true);
                 if ($problems != '') {
                     return $problems;
                 }
                 // $bConflictsWithOpenReferences=true;
                 break;
             case 'notlinksfrom':
                 $problems = self::getPageNameList('notlinksfrom', $sArg, $aNotLinksFrom, $bSelectionCriteriaFound, $logger, true);
                 if ($problems != '') {
                     return $problems;
                 }
                 break;
             case 'linkstoexternal':
                 $problems = self::getPageNameList('linkstoexternal', $sArg, $aLinksToExternal, $bSelectionCriteriaFound, $logger, false);
                 if ($problems != '') {
                     return $problems;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'imageused':
                 $pages = explode('|', trim($sArg));
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('imageused', $sArg);
                     }
                     $aImageUsed[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('imageused', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'imagecontainer':
                 $pages = explode('|', trim($sArg));
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('imagecontainer', $sArg);
                     }
                     $aImageContainer[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('imagecontainer', $sArg);
                 }
                 break;
             case 'uses':
                 $pages = explode('|', $sArg);
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('uses', $sArg);
                     }
                     $aUses[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('uses', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notuses':
                 $pages = explode('|', $sArg);
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('notuses', $sArg);
                     }
                     $aNotUses[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('notuses', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'usedby':
                 $pages = explode('|', $sArg);
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('usedby', $sArg);
                     }
                     $aUsedBy[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('usedby', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'createdby':
                 $sCreatedBy = $sArg;
                 if ($sCreatedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notcreatedby':
                 $sNotCreatedBy = $sArg;
                 if ($sNotCreatedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'modifiedby':
                 $sModifiedBy = $sArg;
                 if ($sModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notmodifiedby':
                 $sNotModifiedBy = $sArg;
                 if ($sNotModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'lastmodifiedby':
                 $sLastModifiedBy = $sArg;
                 if ($sLastModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notlastmodifiedby':
                 $sNotLastModifiedBy = $sArg;
                 if ($sNotLastModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'titlematch':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $aTitleMatch = explode('|', str_replace(' ', '\\_', $sArg));
                 $bSelectionCriteriaFound = true;
                 break;
             case 'minoredits':
                 if (in_array($sArg, ExtDynamicPageList::$options['minoredits'])) {
                     $sMinorEdits = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     //wrong param val, using default
                     $sMinorEdits = ExtDynamicPageList::$options['minoredits']['default'];
                     $output .= $logger->msgWrongParam('minoredits', $sArg);
                 }
                 break;
             case 'includesubpages':
                 if (in_array($sArg, ExtDynamicPageList::$options['includesubpages'])) {
                     $bIncludeSubpages = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('includesubpages', $sArg);
                 }
                 break;
             case 'ignorecase':
                 if (in_array($sArg, ExtDynamicPageList::$options['ignorecase'])) {
                     $bIgnoreCase = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('ignorecase', $sArg);
                 }
                 break;
             case 'categoriesminmax':
                 if (preg_match(ExtDynamicPageList::$options['categoriesminmax']['pattern'], $sArg)) {
                     $aCatMinMax = $sArg == '' ? null : explode(',', $sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('categoriesminmax', $sArg);
                 }
                 break;
             case 'skipthispage':
                 if (in_array($sArg, ExtDynamicPageList::$options['skipthispage'])) {
                     $bSkipThisPage = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('skipthispage', $sArg);
                 }
                 break;
                 /**
                  * CONTENT PARAMETERS
                  */
             /**
              * CONTENT PARAMETERS
              */
             case 'addcategories':
                 if (in_array($sArg, ExtDynamicPageList::$options['addcategories'])) {
                     $bAddCategories = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addcategories', $sArg);
                 }
                 break;
             case 'addeditdate':
                 if (in_array($sArg, ExtDynamicPageList::$options['addeditdate'])) {
                     $bAddEditDate = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addeditdate', $sArg);
                 }
                 break;
             case 'addexternallink':
                 if (in_array($sArg, ExtDynamicPageList::$options['addexternallink'])) {
                     $bAddExternalLink = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addexternallink', $sArg);
                 }
                 break;
             case 'addpagecounter':
                 if (in_array($sArg, ExtDynamicPageList::$options['addpagecounter'])) {
                     $bAddPageCounter = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addpagecounter', $sArg);
                 }
                 break;
             case 'addpagesize':
                 if (in_array($sArg, ExtDynamicPageList::$options['addpagesize'])) {
                     $bAddPageSize = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addpagesize', $sArg);
                 }
                 break;
             case 'addpagetoucheddate':
                 if (in_array($sArg, ExtDynamicPageList::$options['addpagetoucheddate'])) {
                     $bAddPageTouchedDate = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addpagetoucheddate', $sArg);
                 }
                 break;
             case 'include':
             case 'includepage':
                 $bIncPage = $sArg !== '';
                 if ($bIncPage) {
                     $aSecLabels = explode(',', $sArg);
                 }
                 break;
             case 'includematchparsed':
                 $bIncParsed = true;
             case 'includematch':
                 $aSecLabelsMatch = explode(',', $sArg);
                 break;
             case 'includenotmatchparsed':
                 $bIncParsed = true;
             case 'includenotmatch':
                 $aSecLabelsNotMatch = explode(',', $sArg);
                 break;
             case 'includetrim':
                 if (in_array($sArg, ExtDynamicPageList::$options['includetrim'])) {
                     $bIncludeTrim = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('includetrim', $sArg);
                 }
                 break;
             case 'adduser':
                 if (in_array($sArg, ExtDynamicPageList::$options['adduser'])) {
                     $bAddUser = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('adduser', $sArg);
                 }
                 break;
             case 'addauthor':
                 if (in_array($sArg, ExtDynamicPageList::$options['addauthor'])) {
                     $bAddAuthor = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addauthor', $sArg);
                 }
                 break;
             case 'addcontribution':
                 if (in_array($sArg, ExtDynamicPageList::$options['addcontribution'])) {
                     $bAddContribution = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addcontribution', $sArg);
                 }
                 break;
             case 'addlasteditor':
                 if (in_array($sArg, ExtDynamicPageList::$options['addlasteditor'])) {
                     $bAddLastEditor = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addlasteditor', $sArg);
                 }
                 break;
                 /**
                  * FORMAT/HTML PARAMETERS
                  * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
                  */
             /**
              * FORMAT/HTML PARAMETERS
              * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
              */
             case 'headingmode':
                 if (in_array($sArg, ExtDynamicPageList::$options['headingmode'])) {
                     $sHListMode = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('headingmode', $sArg);
                 }
                 break;
             case 'headingcount':
                 if (in_array($sArg, ExtDynamicPageList::$options['headingcount'])) {
                     $bHeadingCount = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('headingcount', $sArg);
                 }
                 break;
             case 'secseparators':
                 // we replace '\n' by newline to support wiki syntax within the section separators
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 $aSecSeparators = explode(',', $sArg);
                 break;
             case 'multisecseparators':
                 // we replace '\n' by newline to support wiki syntax within the section separators
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 $aMultiSecSeparators = explode(',', $sArg);
                 break;
             case 'table':
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sTable = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 break;
             case 'tablerow':
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 if (trim($sArg) == '') {
                     $aTableRow = array();
                 } else {
                     $aTableRow = explode(',', $sArg);
                 }
                 break;
             case 'tablesortcol':
                 if (preg_match(ExtDynamicPageList::$options['tablesortcol']['pattern'], $sArg)) {
                     $iTableSortCol = $sArg == '' ? 0 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('tablesortcol', $sArg);
                 }
                 break;
             case 'dominantsection':
                 if (preg_match(ExtDynamicPageList::$options['dominantsection']['pattern'], $sArg)) {
                     $iDominantSection = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('dominantsection', $sArg);
                 }
                 break;
             case 'includemaxlength':
                 //processed like 'count' param
                 if (preg_match(ExtDynamicPageList::$options['includemaxlength']['pattern'], $sArg)) {
                     $iIncludeMaxLen = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('includemaxlength', $sArg);
                 }
                 break;
             case 'listattr':
                 $sListHtmlAttr = $sArg;
                 break;
             case 'itemattr':
                 $sItemHtmlAttr = $sArg;
                 break;
             case 'hlistattr':
                 $sHListHtmlAttr = $sArg;
                 break;
             case 'hitemattr':
                 $sHItemHtmlAttr = $sArg;
                 break;
                 /**
                  * DEBUG, RESET and CACHE PARAMETER
                  */
             /**
              * DEBUG, RESET and CACHE PARAMETER
              */
             case 'allowcachedresults':
                 // if execAndExit was previously set (i.e. if it is not empty) we will ignore all cache settings
                 // which are placed AFTER the execandexit statement
                 // thus we make sure that the cache will only become invalid if the query is really executed
                 /** Wikia change begin - disable allowcachedresults parameter (CE-1066) **/
                 // if ($sExecAndExit=='') {
                 // 	if( in_array($sArg, ExtDynamicPageList::$options['allowcachedresults'])) {
                 // 		$bAllowCachedResults = self::argBoolean($sArg);
                 // 		if ($sArg=='yes+warn') {
                 // 			$bAllowCachedResults = true;
                 // 			$bWarnCachedResults = true;
                 // 		}
                 // 	}
                 // 	else
                 // 		$output .= $logger->msgWrongParam('allowcachedresults', $sArg);
                 // }
                 /** Wikia change end **/
                 break;
             case 'dplcache':
                 if ($sArg != '') {
                     $DPLCache = $parser->mTitle->getArticleID() . '_' . str_replace("/", "_", $sArg) . '.dplc';
                     $DPLCachePath = $parser->mTitle->getArticleID() % 10;
                 } else {
                     $output .= $logger->msgWrongParam('dplcache', $sArg);
                 }
                 break;
             case 'dplcacheperiod':
                 if (preg_match(ExtDynamicPageList::$options['dplcacheperiod']['pattern'], $sArg)) {
                     $iDPLCachePeriod = $sArg == '' ? ExtDynamicPageList::$options['dplcacheperiod']['default'] : intval($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('dplcacheperiod', $sArg);
                 }
                 break;
             case 'fixcategory':
                 ExtDynamicPageList::fixCategory($sArg);
                 break;
             case 'reset':
                 foreach (preg_split('/[;,]/', $sArg) as $arg) {
                     $arg = trim($arg);
                     if ($arg == '') {
                         continue;
                     }
                     if (!in_array($arg, ExtDynamicPageList::$options['reset'])) {
                         $output .= $logger->msgWrongParam('reset', $arg);
                     } else {
                         if ($arg == 'links') {
                             $bReset[0] = true;
                         } else {
                             if ($arg == 'templates') {
                                 $bReset[1] = true;
                             } else {
                                 if ($arg == 'categories') {
                                     $bReset[2] = true;
                                 } else {
                                     if ($arg == 'images') {
                                         $bReset[3] = true;
                                     } else {
                                         if ($arg == 'all') {
                                             $bReset[0] = true;
                                             $bReset[1] = true;
                                             $bReset[2] = true;
                                             $bReset[3] = true;
                                         } else {
                                             if ($arg == 'none') {
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     // do nothing
                 }
                 break;
             case 'eliminate':
                 foreach (preg_split('/[;,]/', $sArg) as $arg) {
                     $arg = trim($arg);
                     if ($arg == '') {
                         continue;
                     }
                     if (!in_array($arg, ExtDynamicPageList::$options['eliminate'])) {
                         $output .= $logger->msgWrongParam('eliminate', $arg);
                     } else {
                         if ($arg == 'links') {
                             $bReset[4] = true;
                         } else {
                             if ($arg == 'templates') {
                                 $bReset[5] = true;
                             } else {
                                 if ($arg == 'categories') {
                                     $bReset[6] = true;
                                 } else {
                                     if ($arg == 'images') {
                                         $bReset[7] = true;
                                     } else {
                                         if ($arg == 'all') {
                                             $bReset[4] = true;
                                             $bReset[5] = true;
                                             $bReset[6] = true;
                                             $bReset[7] = true;
                                         } else {
                                             if ($arg == 'none') {
                                                 $bReset[4] = false;
                                                 $bReset[5] = false;
                                                 $bReset[6] = false;
                                                 $bReset[7] = false;
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
                 break;
                 /**
                  * UNKNOWN PARAMETER
                  */
             /**
              * UNKNOWN PARAMETER
              */
             default:
                 $validOptionFound = false;
         }
         if ($validOptionFound) {
             continue;
         }
         if (ExtDynamicPageList::$functionalRichness <= 2) {
             $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, $sType, self::validParametersList());
             continue;
         }
         //------------------------------------------------------------------------------------------- level 3
         $validOptionFound = true;
         switch ($sType) {
             /**
              * FILTER PARAMETERS
              */
             case 'categoryregexp':
                 $sCategoryComparisonMode = ' REGEXP ';
                 $aIncludeCategories[] = array($sArg);
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'categorymatch':
                 $sCategoryComparisonMode = ' LIKE ';
                 $aIncludeCategories[] = explode('|', $sArg);
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notcategoryregexp':
                 $sNotCategoryComparisonMode = ' REGEXP ';
                 $aExcludeCategories[] = $sArg;
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notcategorymatch':
                 $sNotCategoryComparisonMode = ' LIKE ';
                 $aExcludeCategories[] = $sArg;
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'titleregexp':
                 $sTitleMatchMode = ' REGEXP ';
                 $aTitleMatch = array($sArg);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'nottitleregexp':
                 $sNotTitleMatchMode = ' REGEXP ';
                 $aNotTitleMatch = array($sArg);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'nottitlematch':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $aNotTitleMatch = explode('|', str_replace(' ', '_', $sArg));
                 $bSelectionCriteriaFound = true;
                 break;
             case 'lastrevisionbefore':
             case 'allrevisionsbefore':
             case 'firstrevisionsince':
             case 'allrevisionssince':
                 if (preg_match(ExtDynamicPageList::$options[$sType]['pattern'], $sArg)) {
                     $date = str_pad(preg_replace('/[^0-9]/', '', $sArg), 14, '0');
                     $date = $wgLang->userAdjust($date);
                     if ($sType == 'lastrevisionbefore') {
                         $sLastRevisionBefore = $date;
                     }
                     if ($sType == 'allrevisionsbefore') {
                         $sAllRevisionsBefore = $date;
                     }
                     if ($sType == 'firstrevisionsince') {
                         $sFirstRevisionSince = $date;
                     }
                     if ($sType == 'allrevisionssince') {
                         $sAllRevisionsSince = $date;
                     }
                     $bConflictsWithOpenReferences = true;
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam($sType, $sArg);
                 }
                 break;
             case 'minrevisions':
                 //ensure that $iMinRevisions is a number
                 if (preg_match(ExtDynamicPageList::$options['minrevisions']['pattern'], $sArg)) {
                     $iMinRevisions = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('minrevisions', $sArg);
                 }
                 break;
             case 'maxrevisions':
                 //ensure that $iMaxRevisions is a number
                 if (preg_match(ExtDynamicPageList::$options['maxrevisions']['pattern'], $sArg)) {
                     $iMaxRevisions = $sArg == '' ? null : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('maxrevisions', $sArg);
                 }
                 break;
             case 'openreferences':
                 if (in_array($sArg, ExtDynamicPageList::$options['openreferences'])) {
                     $acceptOpenReferences = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('openreferences', $sArg);
                 }
                 break;
             case 'articlecategory':
                 $sArticleCategory = str_replace(' ', '_', $sArg);
                 break;
                 /**
                  * UNKNOWN PARAMETER
                  */
             /**
              * UNKNOWN PARAMETER
              */
             default:
                 $validOptionFound = false;
         }
         if ($validOptionFound) {
             continue;
         }
         if (ExtDynamicPageList::$functionalRichness <= 3) {
             $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, $sType, self::validParametersList());
             continue;
         }
         //------------------------------------------------------------------------------------------- level 4
         $validOptionFound = true;
         switch ($sType) {
             /**
              * GOAL
              */
             case 'goal':
                 if (in_array($sArg, ExtDynamicPageList::$options['goal'])) {
                     $sGoal = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('goal', $sArg);
                 }
                 break;
                 /**
                  * UPDATERULES
                  */
             /**
              * UPDATERULES
              */
             case 'updaterules':
                 $sUpdateRules = $sArg;
                 break;
                 /**
                  * DELETERULES
                  */
             /**
              * DELETERULES
              */
             case 'deleterules':
                 $sDeleteRules = $sArg;
                 break;
                 /**
                  * UNKNOWN PARAMETER
                  */
             /**
              * UNKNOWN PARAMETER
              */
             default:
                 $validOptionFound = false;
         }
         if ($validOptionFound) {
             continue;
         }
         $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_UNKNOWNPARAM, $sType, self::validParametersList());
     }
     // set COUNT
     if ($sCount == '') {
         $sCount = $sCountScroll;
     }
     if ($sCount == '') {
         $iCount = -1;
     } else {
         if (preg_match(ExtDynamicPageList::$options['count']['pattern'], $sCount)) {
             $iCount = intval($sCount);
         } else {
             // wrong value
             $output .= $logger->msgWrongParam('count', "{$sCount} : not a number!");
             $iCount = 1;
         }
     }
     if (!ExtDynamicPageList::$allowUnlimitedResults && ($iCount < 0 || $iCount > ExtDynamicPageList::$maxResultCount)) {
         // justify limits;
         $iCount = ExtDynamicPageList::$maxResultCount;
     }
     // disable parser cache	if caching is not allowed (which is default for DPL but not for <DynamicPageList>)
     /** Wikia change begin - never disable parser cache (CE-1066) **/
     // if ( !$bAllowCachedResults) {
     // 	$parser->disableCache();
     // }
     /** Wikia change end **/
     // place cache warning in resultsheader
     if ($bWarnCachedResults) {
         $sResultsHeader = '{{DPL Cache Warning}}' . $sResultsHeader;
     }
     if ($sExecAndExit != '') {
         // the keyword "geturlargs" is used to return the Url arguments and do nothing else.
         if ($sExecAndExit == 'geturlargs') {
             return '';
         }
         // in all other cases we return the value of the argument (which may contain parser function calls)
         return $sExecAndExit;
     }
     // if Caching is desired AND if the cache is up to date: get result from Cache and exit
     global $wgUploadDirectory, $wgRequest, $wgMemc;
     if ($DPLCache != '') {
         $DPLCache .= "-" . md5($originalInput);
         $cacheFile = "{$wgUploadDirectory}/dplcache/{$DPLCachePath}/{$DPLCache}";
         // when the page containing the DPL statement is changed we must recreate the cache as the DPL statement may have changed
         // otherwise we accept the cache if it is not too old
         if (!$bDPLRefresh) {
             $cacheFound = false;
             $cacheTimeStamp = null;
             $cacheAge = null;
             $cacheInput = null;
             $cacheOutput = null;
             // load cached data from chosen storage
             switch ($DPLCacheStorage) {
                 case 'files':
                     // check if cache file exists
                     if (file_exists($cacheFile)) {
                         // find out if cache is acceptable or too old
                         $cacheTimeStamp = filemtime($cacheFile);
                         $cacheAge = time() - $cacheTimeStamp;
                         if ($cacheAge <= $iDPLCachePeriod) {
                             $cacheOutput = file_get_contents($cacheFile);
                             $cacheOutputPos = strpos($cacheOutput, "+++\n");
                             $cacheInput = substr($cacheOutput, 0, $cacheOutputPos);
                             $cacheOutput = substr($cacheOutput, $cacheOutputPos + 4);
                             $cacheFound = true;
                         }
                     }
                     break;
                 case 'memcache':
                     // create the unique cache key (replace spaces with underscores)
                     $cacheKey = self::getMemcacheKey($DPLCache);
                     $cacheData = $wgMemc->get($cacheKey);
                     // if data was found in memcache
                     if ($cacheData && is_array($cacheData)) {
                         $cacheTimeStamp = $cacheData['timestamp'];
                         $cacheAge = time() - $cacheTimeStamp;
                         // if cached data isn't too old
                         if ($cacheAge <= $iDPLCachePeriod) {
                             $cacheInput = $cacheData['input'];
                             $cacheOutput = $cacheData['output'];
                             $cacheFound = true;
                         }
                     }
                     break;
             }
             // when submitting a page we check if the DPL statement has changed
             if ($cacheFound && ($wgRequest->getVal('action', 'view') != 'submit' || $originalInput == $cacheInput)) {
                 $cacheTimeStamp = self::prettyTimeStamp(date('YmdHis', $cacheTimeStamp));
                 $cachePeriod = self::durationTime($iDPLCachePeriod);
                 $diffTime = self::durationTime($cacheAge);
                 $output .= $cacheOutput;
                 if ($logger->iDebugLevel >= 2) {
                     $output .= "{{Extension DPL cache|mode=get|page={{FULLPAGENAME}}|cache={$DPLCache}|date={$cacheTimeStamp}|now=" . date('H:i:s') . "|age={$diffTime}|period={$cachePeriod}|offset={$iOffset}}}";
                 }
                 // ignore further parameters, stop processing, return cache content
                 return $output;
             }
         }
     }
     // debug level 5 puts nowiki tags around the output
     if ($logger->iDebugLevel == 5) {
         $logger->iDebugLevel = 2;
         $sResultsHeader = '<pre><nowiki>' . $sResultsHeader;
         $sResultsFooter .= '</nowiki></pre>';
     }
     // construct internal keys for TableRow according to the structure of "include"
     // this will be needed in the output phase
     self::updateTableRowKeys($aTableRow, $aSecLabels);
     // foreach ($aTableRow as $key => $val) $output .= "TableRow($key)=$val;<br/>";
     $iIncludeCatCount = count($aIncludeCategories);
     $iTotalIncludeCatCount = count($aIncludeCategories, COUNT_RECURSIVE) - $iIncludeCatCount;
     $iExcludeCatCount = count($aExcludeCategories);
     $iTotalCatCount = $iTotalIncludeCatCount + $iExcludeCatCount;
     if ($calledInMode == 'tag') {
         // in tag mode 'eliminate' is the same as 'reset' for tpl,cat,img
         if ($bReset[5]) {
             $bReset[1] = true;
             $bReset[5] = false;
         }
         if ($bReset[6]) {
             $bReset[2] = true;
             $bReset[6] = false;
         }
         if ($bReset[7]) {
             $bReset[3] = true;
             $bReset[7] = false;
         }
     } else {
         if ($bReset[1]) {
             ExtDynamicPageList::$createdLinks['resetTemplates'] = true;
         }
         if ($bReset[2]) {
             ExtDynamicPageList::$createdLinks['resetCategories'] = true;
         }
         if ($bReset[3]) {
             ExtDynamicPageList::$createdLinks['resetImages'] = true;
         }
     }
     if ($calledInMode == 'tag' && $bReset[0] || $calledInMode == 'func') {
         if ($bReset[0]) {
             ExtDynamicPageList::$createdLinks['resetLinks'] = true;
         }
         // register a hook to reset links which were produced during parsing DPL output
         global $wgHooks;
         if (!isset($wgHooks['ParserAfterTidy']) || !(in_array('ExtDynamicPageList::endReset', $wgHooks['ParserAfterTidy']) || in_array(array('ExtDynamicPageList', 'endReset'), $wgHooks['ParserAfterTidy'], true))) {
             $wgHooks['ParserAfterTidy'][] = 'ExtDynamicPageList' . '__endReset';
         }
     }
     // ###### CHECKS ON PARAMETERS ######
     // too many categories!
     if ($iTotalCatCount > ExtDynamicPageList::$maxCategoryCount && !ExtDynamicPageList::$allowUnlimitedCategories) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_TOOMANYCATS, ExtDynamicPageList::$maxCategoryCount);
     }
     // too few categories!
     if ($iTotalCatCount < ExtDynamicPageList::$minCategoryCount) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_TOOFEWCATS, ExtDynamicPageList::$minCategoryCount);
     }
     // no selection criteria! Warn only if no debug level is set
     if ($iTotalCatCount == 0 && $bSelectionCriteriaFound == false) {
         if ($logger->iDebugLevel <= 1) {
             return $output;
         }
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_NOSELECTION);
     }
     // ordermethod=sortkey requires ordermethod=category
     // delayed to the construction of the SQL query, see near line 2211, gs
     //if (in_array('sortkey',$aOrderMethods) && ! in_array('category',$aOrderMethods)) $aOrderMethods[] = 'category';
     // no included categories but ordermethod=categoryadd or addfirstcategorydate=true!
     if ($iTotalIncludeCatCount == 0 && ($aOrderMethods[0] == 'categoryadd' || $bAddFirstCategoryDate == true)) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_CATDATEBUTNOINCLUDEDCATS);
     }
     // more than one included category but ordermethod=categoryadd or addfirstcategorydate=true!
     // we ALLOW this parameter combination, risking ambiguous results
     //if ($iTotalIncludeCatCount > 1 && ($aOrderMethods[0] == 'categoryadd' || $bAddFirstCategoryDate == true) )
     //	return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_CATDATEBUTMORETHAN1CAT);
     // no more than one type of date at a time!
     if ($bAddPageTouchedDate + $bAddFirstCategoryDate + $bAddEditDate > 1) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_MORETHAN1TYPEOFDATE);
     }
     // the dominant section must be one of the sections mentioned in includepage
     if ($iDominantSection > 0 && count($aSecLabels) < $iDominantSection) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_DOMINANTSECTIONRANGE, count($aSecLabels));
     }
     // category-style output requested with not compatible order method
     if ($sPageListMode == 'category' && !array_intersect($aOrderMethods, array('sortkey', 'title', 'titlewithoutnamespace'))) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_WRONGORDERMETHOD, 'mode=category', 'sortkey | title | titlewithoutnamespace');
     }
     // addpagetoucheddate=true with unappropriate order methods
     if ($bAddPageTouchedDate && !array_intersect($aOrderMethods, array('pagetouched', 'title'))) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_WRONGORDERMETHOD, 'addpagetoucheddate=true', 'pagetouched | title');
     }
     // addeditdate=true but not (ordermethod=...,firstedit or ordermethod=...,lastedit)
     //firstedit (resp. lastedit) -> add date of first (resp. last) revision
     if ($bAddEditDate && !array_intersect($aOrderMethods, array('firstedit', 'lastedit')) & $sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince == '') {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_WRONGORDERMETHOD, 'addeditdate=true', 'firstedit | lastedit');
     }
     // adduser=true but not (ordermethod=...,firstedit or ordermethod=...,lastedit)
     /**
      * @todo allow to add user for other order methods.
      * The fact is a page may be edited by multiple users. Which user(s) should we show? all? the first or the last one?
      * Ideally, we could use values such as 'all', 'first' or 'last' for the adduser parameter.
      */
     if ($bAddUser && !array_intersect($aOrderMethods, array('firstedit', 'lastedit')) & $sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince == '') {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_WRONGORDERMETHOD, 'adduser=true', 'firstedit | lastedit');
     }
     if (isset($sMinorEdits) && !array_intersect($aOrderMethods, array('firstedit', 'lastedit'))) {
         return $output . $logger->escapeMsg(ExtDynamicPageList::FATAL_WRONGORDERMETHOD, 'minoredits', 'firstedit | lastedit');
     }
     /**
      * If we include the Uncategorized, we need the 'dpl_clview': VIEW of the categorylinks table where we have cl_to='' (empty string) for all uncategorized pages. This VIEW must have been created by the administrator of the mediawiki DB at installation. See the documentation.
      */
     $sDplClView = '';
     if ($bIncludeUncat) {
         $sDplClView = $dbr->tableName('dpl_clview');
         // If the view is not there, we can't perform logical operations on the Uncategorized.
         if (!$dbr->tableExists('dpl_clview')) {
             $sSqlCreate_dpl_clview = 'CREATE VIEW ' . $sDplClView . " AS SELECT IFNULL(cl_from, page_id) AS cl_from, IFNULL(cl_to, '') AS cl_to, cl_sortkey FROM " . $sPageTable . ' LEFT OUTER JOIN ' . $sCategorylinksTable . ' ON ' . $sPageTable . '.page_id=cl_from';
             $output .= $logger->escapeMsg(ExtDynamicPageList::FATAL_NOCLVIEW, $sDplClView, $sSqlCreate_dpl_clview);
             return $output;
         }
     }
     //add*** parameters have no effect with 'mode=category' (only namespace/title can be viewed in this mode)
     if ($sPageListMode == 'category' && ($bAddCategories || $bAddEditDate || $bAddFirstCategoryDate || $bAddPageTouchedDate || $bIncPage || $bAddUser || $bAddAuthor || $bAddContribution || $bAddLastEditor)) {
         $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_CATOUTPUTBUTWRONGPARAMS);
     }
     //headingmode has effects with ordermethod on multiple components only
     if ($sHListMode != 'none' && count($aOrderMethods) < 2) {
         $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_HEADINGBUTSIMPLEORDERMETHOD, $sHListMode, 'none');
         $sHListMode = 'none';
     }
     // openreferences is incompatible with many other options
     if ($acceptOpenReferences && $bConflictsWithOpenReferences) {
         $output .= $logger->escapeMsg(ExtDynamicPageList::FATAL_OPENREFERENCES);
         $acceptOpenReferences = false;
     }
     // if 'table' parameter is set: derive values for listseparators, secseparators and multisecseparators
     $defaultTemplateSuffix = '.default';
     if ($sTable != '') {
         $defaultTemplateSuffix = '';
         $sPageListMode = 'userformat';
         $sInlTxt = '';
         $withHLink = "[[%PAGE%|%TITLE%]]\n|";
         foreach (explode(',', $sTable) as $tabnr => $tab) {
             if ($tabnr == 0) {
                 if ($tab == '') {
                     $tab = 'class=wikitable';
                 }
                 $aListSeparators[0] = '{|' . $tab;
             } else {
                 if ($tabnr == 1 && $tab == '-') {
                     $withHLink = '';
                     continue;
                 }
                 if ($tabnr == 1 && $tab == '') {
                     $tab = 'Article';
                 }
                 $aListSeparators[0] .= "\n!{$tab}";
             }
         }
         $aListSeparators[1] = '';
         // the user may have specified the third parameter of 'format' to add meta attributes of articles to the table
         if (!array_key_exists(2, $aListSeparators)) {
             $aListSeparators[2] = '';
         }
         $aListSeparators[3] = "\n|}";
         for ($i = 0; $i < count($aSecLabels); $i++) {
             if ($i == 0) {
                 $aSecSeparators[0] = "\n|-\n|" . $withHLink;
                 //."\n";
                 $aSecSeparators[1] = '';
                 $aMultiSecSeparators[0] = "\n|-\n|" . $withHLink;
                 // ."\n";
             } else {
                 $aSecSeparators[2 * $i] = "\n|";
                 // ."\n";
                 $aSecSeparators[2 * $i + 1] = '';
                 if (is_array($aSecLabels[$i]) && $aSecLabels[$i][0] == '#') {
                     $aMultiSecSeparators[$i] = "\n----\n";
                 }
                 if ($aSecLabels[$i][0] == '#') {
                     $aMultiSecSeparators[$i] = "\n----\n";
                 } else {
                     $aMultiSecSeparators[$i] = "<br/>\n";
                 }
             }
         }
     }
     // backward scrolling: if the user specified titleLE and wants ascending order we reverse the SQL sort order
     if ($sTitleLE != '' && $sTitleGE == '') {
         if ($sOrder == 'ascending') {
             $sOrder = 'descending';
         }
     }
     $output .= '{{Extension DPL}}';
     // ###### BUILD SQL QUERY ######
     $sSqlPage_counter = '';
     $sSqlPage_size = '';
     $sSqlPage_touched = '';
     $sSqlCalcFoundRows = '';
     if (!ExtDynamicPageList::$allowUnlimitedResults && $sGoal != 'categories' && strpos($sResultsHeader . $sResultsFooter . $sNoResultsHeader, '%TOTALPAGES%') !== false) {
         $sSqlCalcFoundRows = 'SQL_CALC_FOUND_ROWS';
     }
     if ($sDistinctResultSet == 'false') {
         $sSqlDistinct = '';
     } else {
         $sSqlDistinct = 'DISTINCT';
     }
     $sSqlGroupBy = '';
     if ($sDistinctResultSet == 'strict' && count($aLinksTo) + count($aNotLinksTo) + count($aLinksFrom) + count($aNotLinksFrom) + count($aLinksToExternal) + count($aImageUsed) > 0) {
         $sSqlGroupBy = 'page_title';
     }
     $sSqlSortkey = '';
     $sSqlCl_to = '';
     $sSqlCats = '';
     $sSqlCl_timestamp = '';
     $sSqlClHeadTable = '';
     $sSqlCond_page_cl_head = '';
     $sSqlClTableForGC = '';
     $sSqlCond_page_cl_gc = '';
     $sSqlRCTable = '';
     // recent changes
     $sRCTable = $dbr->tableName('recentchanges');
     $sRevisionTable = $dbr->tableName('revision');
     $sSqlRevisionTable = '';
     $sSqlRev_timestamp = '';
     $sSqlRev_id = '';
     $sSqlRev_user = '';
     $sSqlCond_page_rev = '';
     $sPageLinksTable = $dbr->tableName('pagelinks');
     $sExternalLinksTable = $dbr->tableName('externallinks');
     $sImageLinksTable = $dbr->tableName('imagelinks');
     $sTemplateLinksTable = $dbr->tableName('templatelinks');
     $sSqlPageLinksTable = '';
     $sSqlExternalLinksTable = '';
     $sSqlCreationRevisionTable = '';
     $sSqlNoCreationRevisionTable = '';
     $sSqlChangeRevisionTable = '';
     $sSqlCond_page_pl = '';
     $sSqlCond_page_el = '';
     $sSqlCond_page_tpl = '';
     $sSqlCond_MaxCat = '';
     $sSqlWhere = ' WHERE 1=1 ';
     $sSqlSelPage = '';
     // initial page for selection
     // normally we create a result of normal pages, but when goal=categories is set, we create a list of categories
     // as this conflicts with some options we need to avoid producing incoorect SQl code
     $bGoalIsPages = true;
     if ($sGoal == 'categories') {
         $aOrderMethods = explode(',', '');
         $bGoalIsPages = false;
     }
     foreach ($aOrderMethods as $sOrderMethod) {
         switch ($sOrderMethod) {
             case 'category':
                 $sSqlCl_to = "cl_head.cl_to, ";
                 // Gives category headings in the result
                 $sSqlClHeadTable = (in_array('', $aCatHeadings) || in_array('', $aCatNotHeadings) ? $sDplClView : $sCategorylinksTable) . ' AS cl_head';
                 // use dpl_clview if Uncategorized in headings
                 $sSqlCond_page_cl_head = 'page_id=cl_head.cl_from';
                 if (!empty($aCatHeadings)) {
                     $sSqlWhere .= " AND cl_head.cl_to IN (" . $dbr->makeList($aCatHeadings) . ")";
                 }
                 if (!empty($aCatNotHeadings)) {
                     $sSqlWhere .= " AND NOT (cl_head.cl_to IN (" . $dbr->makeList($aCatNotHeadings) . "))";
                 }
                 break;
             case 'firstedit':
                 $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
                 $sSqlRev_timestamp = ', rev_timestamp';
                 // deleted because of conflict with revsion-parameters
                 $sSqlCond_page_rev = ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MIN(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page )';
                 break;
             case 'pagetouched':
                 $sSqlPage_touched = ", {$sPageTable}.page_touched as page_touched";
                 break;
             case 'lastedit':
                 if (ExtDynamicPageList::$behavingLikeIntersection) {
                     $sSqlPage_touched = ", {$sPageTable}.page_touched as page_touched";
                 } else {
                     $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
                     $sSqlRev_timestamp = ', rev_timestamp';
                     // deleted because of conflict with revision-parameters
                     $sSqlCond_page_rev = ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MAX(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page )';
                 }
                 break;
             case 'sortkey':
                 // We need the namespaces with strictly positive indices (DPL allowed namespaces, except the first one: Main).
                 $aStrictNs = array_slice(ExtDynamicPageList::$allowedNamespaces, 1, count(ExtDynamicPageList::$allowedNamespaces), true);
                 // map ns index to name
                 $sSqlNsIdToText = 'CASE ' . $sPageTable . '.page_namespace';
                 foreach ($aStrictNs as $iNs => $sNs) {
                     $sSqlNsIdToText .= ' WHEN ' . intval($iNs) . " THEN " . $dbr->addQuotes($sNs);
                 }
                 $sSqlNsIdToText .= ' END';
                 // If cl_sortkey is null (uncategorized page), generate a sortkey in the usual way (full page name, underscores replaced with spaces).
                 // UTF-8 created problems with non-utf-8 MySQL databases
                 //see line 2011 (order method sortkey requires category
                 if (count($aIncludeCategories) + count($aExcludeCategories) > 0) {
                     if (in_array('category', $aOrderMethods) && count($aIncludeCategories) + count($aExcludeCategories) > 0) {
                         $sSqlSortkey = ", IFNULL(cl_head.cl_sortkey, REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' ')) " . $sOrderCollation . " as sortkey";
                     } else {
                         $sSqlSortkey = ", IFNULL(cl0.cl_sortkey, REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' ')) " . $sOrderCollation . " as sortkey";
                     }
                 } else {
                     $sSqlSortkey = ", REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' ') " . $sOrderCollation . " as sortkey";
                 }
                 break;
             case 'pagesel':
                 $sSqlSortkey = ', CONCAT(pl.pl_namespace,pl.pl_title) ' . $sOrderCollation . ' as sortkey';
                 break;
             case 'titlewithoutnamespace':
                 $sSqlSortkey = ", {$sPageTable}.page_title " . $sOrderCollation . " as sortkey";
                 break;
             case 'title':
                 $aStrictNs = array_slice(ExtDynamicPageList::$allowedNamespaces, 1, count(ExtDynamicPageList::$allowedNamespaces), true);
                 // map namespace index to name
                 if ($acceptOpenReferences) {
                     $sSqlNsIdToText = 'CASE pl_namespace';
                     foreach ($aStrictNs as $iNs => $sNs) {
                         $sSqlNsIdToText .= ' WHEN ' . intval($iNs) . " THEN " . $dbr->addQuotes($sNs);
                     }
                     $sSqlNsIdToText .= ' END';
                     $sSqlSortkey = ", REPLACE(CONCAT( IF(pl_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), pl_title), '_', ' ') " . $sOrderCollation . " as sortkey";
                 } else {
                     $sSqlNsIdToText = 'CASE ' . $sPageTable . '.page_namespace';
                     foreach ($aStrictNs as $iNs => $sNs) {
                         $sSqlNsIdToText .= ' WHEN ' . intval($iNs) . " THEN " . $dbr->addQuotes($sNs);
                     }
                     $sSqlNsIdToText .= ' END';
                     // Generate sortkey like for category links. UTF-8 created problems with non-utf-8 MySQL databases
                     $sSqlSortkey = ", REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' ') " . $sOrderCollation . " as sortkey";
                 }
                 break;
             case 'user':
                 $sSqlRevisionTable = $sRevisionTable . ', ';
                 $sSqlRev_user = '******';
                 break;
             case 'none':
                 break;
         }
     }
     // linksto
     if (count($aLinksTo) > 0) {
         $sSqlPageLinksTable .= $sPageLinksTable . ' AS pl, ';
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id=pl.pl_from AND ';
         $sSqlSelPage = ', pl.pl_title AS sel_title, pl.pl_namespace AS sel_ns';
         $n = 0;
         foreach ($aLinksTo as $linkGroup) {
             if (++$n > 1) {
                 break;
             }
             $sSqlCond_page_pl .= '( ';
             $m = 0;
             foreach ($linkGroup as $link) {
                 if (++$m > 1) {
                     $sSqlCond_page_pl .= ' OR ';
                 }
                 $sSqlCond_page_pl .= '(pl.pl_namespace=' . intval($link->getNamespace());
                 if (strpos($link->getDbKey(), '%') >= 0) {
                     $operator = ' LIKE ';
                 } else {
                     $operator = '=';
                 }
                 if ($bIgnoreCase) {
                     $sSqlCond_page_pl .= ' AND LOWER(CAST(pl.pl_title AS char))' . $operator . 'LOWER(' . $dbr->addQuotes($link->getDbKey()) . '))';
                 } else {
                     $sSqlCond_page_pl .= ' AND pl.pl_title' . $operator . $dbr->addQuotes($link->getDbKey()) . ')';
                 }
             }
             $sSqlCond_page_pl .= ')';
         }
     }
     if (count($aLinksTo) > 1) {
         $n = 0;
         foreach ($aLinksTo as $linkGroup) {
             if (++$n == 1) {
                 continue;
             }
             $m = 0;
             $sSqlCond_page_pl .= ' AND EXISTS(select pl_from FROM ' . $sPageLinksTable . ' WHERE (' . $sPageLinksTable . '.pl_from=page_id AND (';
             foreach ($linkGroup as $link) {
                 if (++$m > 1) {
                     $sSqlCond_page_pl .= ' OR ';
                 }
                 $sSqlCond_page_pl .= '(' . $sPageLinksTable . '.pl_namespace=' . intval($link->getNamespace());
                 if (strpos($link->getDbKey(), '%') >= 0) {
                     $operator = ' LIKE ';
                 } else {
                     $operator = '=';
                 }
                 if ($bIgnoreCase) {
                     $sSqlCond_page_pl .= ' AND LOWER(CAST(' . $sPageLinksTable . '.pl_title AS char))' . $operator . 'LOWER(' . $dbr->addQuotes($link->getDbKey()) . ')';
                 } else {
                     $sSqlCond_page_pl .= ' AND ' . $sPageLinksTable . '.pl_title' . $operator . $dbr->addQuotes($link->getDbKey());
                 }
                 $sSqlCond_page_pl .= ')';
             }
             $sSqlCond_page_pl .= ')))';
         }
     }
     // notlinksto
     if (count($aNotLinksTo) > 0) {
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id NOT IN (SELECT ' . $sPageLinksTable . '.pl_from FROM ' . $sPageLinksTable . ' WHERE (';
         $n = 0;
         foreach ($aNotLinksTo as $links) {
             foreach ($links as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_pl .= ' OR ';
                 }
                 $sSqlCond_page_pl .= '(' . $sPageLinksTable . '.pl_namespace=' . intval($link->getNamespace());
                 if (strpos($link->getDbKey(), '%') >= 0) {
                     $operator = ' LIKE ';
                 } else {
                     $operator = '=';
                 }
                 if ($bIgnoreCase) {
                     $sSqlCond_page_pl .= ' AND LOWER(CAST(' . $sPageLinksTable . '.pl_title AS char))' . $operator . 'LOWER(' . $dbr->addQuotes($link->getDbKey()) . '))';
                 } else {
                     $sSqlCond_page_pl .= ' AND       ' . $sPageLinksTable . '.pl_title' . $operator . $dbr->addQuotes($link->getDbKey()) . ')';
                 }
                 $n++;
             }
         }
         $sSqlCond_page_pl .= ') )';
     }
     // linksfrom
     if (count($aLinksFrom) > 0) {
         if ($acceptOpenReferences) {
             $sSqlCond_page_pl .= ' AND (';
             $n = 0;
             foreach ($aLinksFrom as $links) {
                 foreach ($links as $link) {
                     if ($n > 0) {
                         $sSqlCond_page_pl .= ' OR ';
                     }
                     $sSqlCond_page_pl .= '(pl_from=' . $link->getArticleID() . ')';
                     $n++;
                 }
             }
             $sSqlCond_page_pl .= ')';
         } else {
             $sSqlPageLinksTable .= $sPageLinksTable . ' AS plf, ' . $sPageTable . 'AS pagesrc, ';
             $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_namespace = plf.pl_namespace AND ' . $sPageTable . '.page_title = plf.pl_title  AND pagesrc.page_id=plf.pl_from AND (';
             $sSqlSelPage = ', pagesrc.page_title AS sel_title, pagesrc.page_namespace AS sel_ns';
             $n = 0;
             foreach ($aLinksFrom as $links) {
                 foreach ($links as $link) {
                     if ($n > 0) {
                         $sSqlCond_page_pl .= ' OR ';
                     }
                     $sSqlCond_page_pl .= '(plf.pl_from=' . $link->getArticleID() . ')';
                     $n++;
                 }
             }
             $sSqlCond_page_pl .= ')';
         }
     }
     // notlinksfrom
     if (count($aNotLinksFrom) > 0) {
         if ($acceptOpenReferences) {
             $sSqlCond_page_pl .= ' AND (';
             $n = 0;
             foreach ($aNotLinksFrom as $links) {
                 foreach ($links as $link) {
                     if ($n > 0) {
                         $sSqlCond_page_pl .= ' AND ';
                     }
                     $sSqlCond_page_pl .= 'pl_from <> ' . $link->getArticleID() . ' ';
                     $n++;
                 }
             }
             $sSqlCond_page_pl .= ')';
         } else {
             $sSqlCond_page_pl .= ' AND CONCAT(page_namespace,page_title) NOT IN (SELECT CONCAT(' . $sPageLinksTable . '.pl_namespace,' . $sPageLinksTable . '.pl_title) from ' . $sPageLinksTable . ' WHERE (';
             $n = 0;
             foreach ($aNotLinksFrom as $links) {
                 foreach ($links as $link) {
                     if ($n > 0) {
                         $sSqlCond_page_pl .= ' OR ';
                     }
                     $sSqlCond_page_pl .= $sPageLinksTable . '.pl_from=' . $link->getArticleID() . ' ';
                     $n++;
                 }
             }
             $sSqlCond_page_pl .= '))';
         }
     }
     // linkstoexternal
     if (count($aLinksToExternal) > 0) {
         $sSqlExternalLinksTable .= $sExternalLinksTable . ' AS el, ';
         $sSqlCond_page_el .= ' AND ' . $sPageTable . '.page_id=el.el_from AND (';
         $sSqlSelPage = ', el.el_to as el_to';
         $n = 0;
         foreach ($aLinksToExternal as $linkGroup) {
             if (++$n > 1) {
                 break;
             }
             $m = 0;
             foreach ($linkGroup as $link) {
                 if (++$m > 1) {
                     $sSqlCond_page_el .= ' OR ';
                 }
                 $sSqlCond_page_el .= '(el.el_to LIKE ' . $dbr->addQuotes($link) . ')';
             }
         }
         $sSqlCond_page_el .= ')';
     }
     if (count($aLinksToExternal) > 1) {
         $n = 0;
         foreach ($aLinksToExternal as $linkGroup) {
             if (++$n == 1) {
                 continue;
             }
             $m = 0;
             $sSqlCond_page_el .= ' AND EXISTS(SELECT el_from FROM ' . $sExternalLinksTable . ' WHERE (' . $sExternalLinksTable . '.el_from=page_id AND (';
             foreach ($linkGroup as $link) {
                 if (++$m > 1) {
                     $sSqlCond_page_el .= ' OR ';
                 }
                 $sSqlCond_page_el .= '(' . $sExternalLinksTable . '.el_to LIKE ' . $dbr->addQuotes($link) . ')';
             }
             $sSqlCond_page_el .= ')))';
         }
     }
     // imageused
     if (count($aImageUsed) > 0) {
         $sSqlPageLinksTable .= $sImageLinksTable . ' AS il, ';
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id=il.il_from AND (';
         $sSqlSelPage = ', il.il_to AS image_sel_title';
         $n = 0;
         foreach ($aImageUsed as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= "LOWER(CAST(il.il_to AS char))=LOWER(" . $dbr->addQuotes($link->getDbKey()) . ')';
             } else {
                 $sSqlCond_page_pl .= "il.il_to=" . $dbr->addQuotes($link->getDbKey());
             }
             $n++;
         }
         $sSqlCond_page_pl .= ')';
     }
     // imagecontainer
     if (count($aImageContainer) > 0) {
         $sSqlPageLinksTable .= $sImageLinksTable . ' AS ic, ';
         if ($acceptOpenReferences) {
             $sSqlCond_page_pl .= ' AND (';
         } else {
             $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_namespace=\'6\' AND ' . $sPageTable . '.page_title=ic.il_to AND (';
         }
         $n = 0;
         foreach ($aImageContainer as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= "LOWER(CAST(ic.il_from AS char)=LOWER(" . $dbr->addQuotes($link->getArticleID()) . ')';
             } else {
                 $sSqlCond_page_pl .= "ic.il_from=" . $dbr->addQuotes($link->getArticleID());
             }
             $n++;
         }
         $sSqlCond_page_pl .= ')';
     }
     // uses
     if (count($aUses) > 0) {
         $sSqlPageLinksTable .= ' ' . $sTemplateLinksTable . ' as tl, ';
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id=tl.tl_from  AND (';
         $n = 0;
         foreach ($aUses as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             $sSqlCond_page_pl .= '(tl.tl_namespace=' . intval($link->getNamespace());
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= " AND LOWER(CAST(tl.tl_title AS char))=LOWER(" . $dbr->addQuotes($link->getDbKey()) . '))';
             } else {
                 $sSqlCond_page_pl .= " AND       tl.tl_title=" . $dbr->addQuotes($link->getDbKey()) . ')';
             }
             $n++;
         }
         $sSqlCond_page_pl .= ')';
     }
     // notuses
     if (count($aNotUses) > 0) {
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id NOT IN (SELECT ' . $sTemplateLinksTable . '.tl_from FROM ' . $sTemplateLinksTable . ' WHERE (';
         $n = 0;
         foreach ($aNotUses as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             $sSqlCond_page_pl .= '(' . $sTemplateLinksTable . '.tl_namespace=' . intval($link->getNamespace());
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= ' AND LOWER(CAST(' . $sTemplateLinksTable . '.tl_title AS char))=LOWER(' . $dbr->addQuotes($link->getDbKey()) . '))';
             } else {
                 $sSqlCond_page_pl .= ' AND ' . $sTemplateLinksTable . '.tl_title=' . $dbr->addQuotes($link->getDbKey()) . ')';
             }
             $n++;
         }
         $sSqlCond_page_pl .= ') )';
     }
     // usedby
     if (count($aUsedBy) > 0) {
         if ($acceptOpenReferences) {
             $sSqlCond_page_tpl .= ' AND (';
             $n = 0;
             foreach ($aUsedBy as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_tpl .= ' OR ';
                 }
                 $sSqlCond_page_tpl .= '(tpl_from=' . $link->getArticleID() . ')';
                 $n++;
             }
             $sSqlCond_page_tpl .= ')';
         } else {
             $sSqlPageLinksTable .= $sTemplateLinksTable . ' AS tpl, ' . $sPageTable . 'AS tplsrc, ';
             $sSqlCond_page_tpl .= ' AND ' . $sPageTable . '.page_title = tpl.tl_title  AND tplsrc.page_id=tpl.tl_from AND (';
             $sSqlSelPage = ', tplsrc.page_title AS tpl_sel_title, tplsrc.page_namespace AS tpl_sel_ns';
             $n = 0;
             foreach ($aUsedBy as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_tpl .= ' OR ';
                 }
                 $sSqlCond_page_tpl .= '(tpl.tl_from=' . $link->getArticleID() . ')';
                 $n++;
             }
             $sSqlCond_page_tpl .= ')';
         }
     }
     // recent changes  =============================
     if ($bAddContribution) {
         $sSqlRCTable = $sRCTable . ' AS rc, ';
         $sSqlSelPage .= ', SUM( ABS( rc.rc_new_len - rc.rc_old_len ) ) AS contribution, rc.rc_user_text AS contributor';
         $sSqlWhere .= ' AND page.page_id=rc.rc_cur_id';
         if ($sSqlGroupBy != '') {
             $sSqlGroupBy .= ', ';
         }
         $sSqlGroupBy .= 'rc.rc_cur_id';
     }
     // Revisions ==================================
     if ($sCreatedBy != "") {
         $sSqlCreationRevisionTable = $sRevisionTable . ' AS creation_rev, ';
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sCreatedBy) . ' = creation_rev.rev_user_text' . ' AND creation_rev.rev_page = page_id' . ' AND creation_rev.rev_parent_id = 0';
     }
     if ($sNotCreatedBy != "") {
         $sSqlNoCreationRevisionTable = $sRevisionTable . ' AS no_creation_rev, ';
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sNotCreatedBy) . ' != no_creation_rev.rev_user_text' . ' AND no_creation_rev.rev_page = page_id' . ' AND no_creation_rev.rev_parent_id = 0';
     }
     if ($sModifiedBy != "") {
         $sSqlChangeRevisionTable = $sRevisionTable . ' AS change_rev, ';
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sModifiedBy) . ' = change_rev.rev_user_text' . ' AND change_rev.rev_page = page_id';
     }
     if ($sNotModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND NOT EXISTS (SELECT 1 FROM ' . $sRevisionTable . ' WHERE ' . $sRevisionTable . '.rev_page=page_id AND ' . $sRevisionTable . '.rev_user_text = ' . $dbr->addQuotes($sNotModifiedBy) . ' LIMIT 1)';
     }
     if ($sLastModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sLastModifiedBy) . ' = (SELECT rev_user_text FROM ' . $sRevisionTable . ' WHERE ' . $sRevisionTable . '.rev_page=page_id ORDER BY ' . $sRevisionTable . '.rev_timestamp DESC LIMIT 1)';
     }
     if ($sNotLastModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sNotLastModifiedBy) . ' != (SELECT rev_user_text FROM ' . $sRevisionTable . ' WHERE ' . $sRevisionTable . '.rev_page=page_id ORDER BY ' . $sRevisionTable . '.rev_timestamp DESC LIMIT 1)';
     }
     if ($bAddAuthor && $sSqlRevisionTable == '') {
         $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
         $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MIN(rev_aux_min.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux_min WHERE rev_aux_min.rev_page=rev.rev_page )';
     }
     if ($bAddLastEditor && $sSqlRevisionTable == '') {
         $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
         $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MAX(rev_aux_max.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux_max WHERE rev_aux_max.rev_page=rev.rev_page )';
     }
     if ($sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince != '') {
         $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
         $sSqlRev_timestamp = ', rev_timestamp';
         $sSqlRev_id = ', rev_id';
         if ($sLastRevisionBefore != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MAX(rev_aux_bef.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux_bef WHERE rev_aux_bef.rev_page=rev.rev_page AND rev_aux_bef.rev_timestamp < ' . $sLastRevisionBefore . ')';
         }
         if ($sAllRevisionsBefore != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp < ' . $sAllRevisionsBefore;
         }
         if ($sFirstRevisionSince != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MIN(rev_aux_snc.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux_snc WHERE rev_aux_snc.rev_page=rev.rev_page AND rev_aux_snc.rev_timestamp >= ' . $sFirstRevisionSince . ')';
         }
         if ($sAllRevisionsSince != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp >= ' . $sAllRevisionsSince;
         }
     }
     if (isset($aCatMinMax[0]) && $aCatMinMax[0] != '') {
         $sSqlCond_MaxCat .= ' AND ' . $aCatMinMax[0] . ' <= (SELECT count(*) FROM ' . $sCategorylinksTable . ' WHERE ' . $sCategorylinksTable . '.cl_from=page_id)';
     }
     if (isset($aCatMinMax[1]) && $aCatMinMax[1] != '') {
         $sSqlCond_MaxCat .= ' AND ' . $aCatMinMax[1] . ' >= (SELECT count(*) FROM ' . $sCategorylinksTable . ' WHERE ' . $sCategorylinksTable . '.cl_from=page_id)';
     }
     if ($bAddFirstCategoryDate) {
         //format cl_timestamp field (type timestamp) to string in same format AS rev_timestamp field
         //to make it compatible with $wgLang->date() function used in function DPLOutputListStyle() to show "firstcategorydate"
         $sSqlCl_timestamp = ", DATE_FORMAT(cl0.cl_timestamp, '%Y%m%d%H%i%s') AS cl_timestamp";
     }
     if ($bAddPageCounter) {
         $sSqlPage_counter = ", {$sPageTable}.page_counter AS page_counter";
     }
     if ($bAddPageSize) {
         $sSqlPage_size = ", {$sPageTable}.page_len AS page_len";
     }
     if ($bAddPageTouchedDate && $sSqlPage_touched == '') {
         $sSqlPage_touched = ", {$sPageTable}.page_touched AS page_touched";
     }
     if ($bAddUser || $bAddAuthor || $bAddLastEditor || $sSqlRevisionTable != '') {
         $sSqlRev_user = '******';
     }
     if ($bAddCategories) {
         $sSqlCats = ", GROUP_CONCAT(DISTINCT cl_gc.cl_to ORDER BY cl_gc.cl_to ASC SEPARATOR ' | ') AS cats";
         // Gives list of all categories linked from each article, if any.
         $sSqlClTableForGC = $sCategorylinksTable . ' AS cl_gc';
         // Categorylinks table used by the Group Concat (GC) function above
         $sSqlCond_page_cl_gc = 'page_id=cl_gc.cl_from';
         if ($sSqlGroupBy != '') {
             $sSqlGroupBy .= ', ';
         }
         $sSqlGroupBy .= $sSqlCl_to . $sPageTable . '.page_id';
     }
     // SELECT ... FROM
     if ($acceptOpenReferences) {
         // SELECT ... FROM
         if (count($aImageContainer) > 0) {
             $sSqlSelectFrom = "SELECT {$sSqlCalcFoundRows} {$sSqlDistinct} " . $sSqlCl_to . 'ic.il_to, ' . $sSqlSelPage . "ic.il_to AS sortkey" . ' FROM ' . $sImageLinksTable . ' AS ic';
         } else {
             $sSqlSelectFrom = "SELECT {$sSqlCalcFoundRows} {$sSqlDistinct} " . $sSqlCl_to . 'pl_namespace, pl_title' . $sSqlSelPage . $sSqlSortkey . ' FROM ' . $sPageLinksTable;
         }
     } else {
         $sSqlSelectFrom = "SELECT {$sSqlCalcFoundRows} {$sSqlDistinct} " . $sSqlCl_to . $sPageTable . '.page_namespace AS page_namespace,' . $sPageTable . '.page_title AS page_title,' . $sPageTable . '.page_id AS page_id' . $sSqlSelPage . $sSqlSortkey . $sSqlPage_counter . $sSqlPage_size . $sSqlPage_touched . $sSqlRev_user . $sSqlRev_timestamp . $sSqlRev_id . $sSqlCats . $sSqlCl_timestamp . ' FROM ' . $sSqlRevisionTable . $sSqlCreationRevisionTable . $sSqlNoCreationRevisionTable . $sSqlChangeRevisionTable . $sSqlRCTable . $sSqlPageLinksTable . $sSqlExternalLinksTable . $sPageTable;
     }
     // JOIN ...
     if ($sSqlClHeadTable != '' || $sSqlClTableForGC != '') {
         $b2tables = $sSqlClHeadTable != '' && $sSqlClTableForGC != '';
         $sSqlSelectFrom .= ' LEFT OUTER JOIN ' . $sSqlClHeadTable . ($b2tables ? ', ' : '') . $sSqlClTableForGC . ' ON (' . $sSqlCond_page_cl_head . ($b2tables ? ' AND ' : '') . $sSqlCond_page_cl_gc . ')';
     }
     // Include categories...
     $iClTable = 0;
     for ($i = 0; $i < $iIncludeCatCount; $i++) {
         // If we want the Uncategorized
         $sSqlSelectFrom .= ' INNER JOIN ' . (in_array('', $aIncludeCategories[$i]) ? $sDplClView : $sCategorylinksTable) . ' AS cl' . $iClTable . ' ON ' . $sPageTable . '.page_id=cl' . $iClTable . '.cl_from AND (cl' . $iClTable . '.cl_to' . $sCategoryComparisonMode . $dbr->addQuotes(str_replace(' ', '_', $aIncludeCategories[$i][0]));
         for ($j = 1; $j < count($aIncludeCategories[$i]); $j++) {
             $sSqlSelectFrom .= ' OR cl' . $iClTable . '.cl_to' . $sCategoryComparisonMode . $dbr->addQuotes(str_replace(' ', '_', $aIncludeCategories[$i][$j]));
         }
         $sSqlSelectFrom .= ') ';
         $iClTable++;
     }
     // Exclude categories...
     for ($i = 0; $i < $iExcludeCatCount; $i++) {
         $sSqlSelectFrom .= ' LEFT OUTER JOIN ' . $sCategorylinksTable . ' AS cl' . $iClTable . ' ON ' . $sPageTable . '.page_id=cl' . $iClTable . '.cl_from' . ' AND cl' . $iClTable . '.cl_to' . $sNotCategoryComparisonMode . $dbr->addQuotes(str_replace(' ', '_', $aExcludeCategories[$i]));
         $sSqlWhere .= ' AND cl' . $iClTable . '.cl_to IS NULL';
         $iClTable++;
     }
     // WHERE... (actually finish the WHERE clause we may have started if we excluded categories - see above)
     // Namespace IS ...
     if (!empty($aNamespaces)) {
         if ($acceptOpenReferences) {
             $sSqlWhere .= ' AND ' . $sPageLinksTable . '.pl_namespace IN (' . $dbr->makeList($aNamespaces) . ')';
         } else {
             $sSqlWhere .= ' AND ' . $sPageTable . '.page_namespace IN (' . $dbr->makeList($aNamespaces) . ')';
         }
     }
     // Namespace IS NOT ...
     if (!empty($aExcludeNamespaces)) {
         if ($acceptOpenReferences) {
             $sSqlWhere .= ' AND ' . $sPageLinksTable . '.pl_namespace NOT IN (' . $dbr->makeList($aExcludeNamespaces) . ')';
         } else {
             $sSqlWhere .= ' AND ' . $sPageTable . '.page_namespace NOT IN (' . $dbr->makeList($aExcludeNamespaces) . ')';
         }
     }
     // TitleIs
     if ($sTitleIs != '') {
         if ($bIgnoreCase) {
             $sSqlWhere .= ' AND LOWER(CAST(' . $sPageTable . '.page_title AS char)) = LOWER(' . $dbr->addQuotes($sTitleIs) . ')';
         } else {
             $sSqlWhere .= ' AND ' . $sPageTable . '.page_title = ' . $dbr->addQuotes($sTitleIs);
         }
     }
     // TitleGE ...
     if ($sTitleGE != '') {
         $sSqlWhere .= ' AND (';
         if (substr($sTitleGE, 0, 2) == '=_') {
             if ($acceptOpenReferences) {
                 $sSqlWhere .= 'pl_title >=' . $dbr->addQuotes(substr($sTitleGE, 2));
             } else {
                 $sSqlWhere .= $sPageTable . '.page_title >=' . $dbr->addQuotes(substr($sTitleGE, 2));
             }
         } else {
             if ($acceptOpenReferences) {
                 $sSqlWhere .= 'pl_title >' . $dbr->addQuotes($sTitleGE);
             } else {
                 $sSqlWhere .= $sPageTable . '.page_title >' . $dbr->addQuotes($sTitleGE);
             }
         }
         $sSqlWhere .= ')';
     }
     // TitleLE ...
     if ($sTitleLE != '') {
         $sSqlWhere .= ' AND (';
         if (substr($sTitleLE, 0, 2) == '=_') {
             if ($acceptOpenReferences) {
                 $sSqlWhere .= 'pl_title <=' . $dbr->addQuotes(substr($sTitleLE, 2));
             } else {
                 $sSqlWhere .= $sPageTable . '.page_title <=' . $dbr->addQuotes(substr($sTitleLE, 2));
             }
         } else {
             if ($acceptOpenReferences) {
                 $sSqlWhere .= 'pl_title <' . $dbr->addQuotes($sTitleLE);
             } else {
                 $sSqlWhere .= $sPageTable . '.page_title <' . $dbr->addQuotes($sTitleLE);
             }
         }
         $sSqlWhere .= ')';
     }
     // TitleMatch ...
     if (count($aTitleMatch) > 0) {
         $sSqlWhere .= ' AND (';
         $n = 0;
         foreach ($aTitleMatch as $link) {
             if ($n > 0) {
                 $sSqlWhere .= ' OR ';
             }
             if ($acceptOpenReferences) {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'LOWER(CAST(pl_title AS char))' . $sTitleMatchMode . strtolower($dbr->addQuotes($link));
                 } else {
                     $sSqlWhere .= 'pl_title' . $sTitleMatchMode . $dbr->addQuotes($link);
                 }
             } else {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'LOWER(CAST(' . $sPageTable . '.page_title AS char))' . $sTitleMatchMode . strtolower($dbr->addQuotes($link));
                 } else {
                     $sSqlWhere .= $sPageTable . '.page_title' . $sTitleMatchMode . $dbr->addQuotes($link);
                 }
             }
             $n++;
         }
         $sSqlWhere .= ')';
     }
     // NotTitleMatch ...
     if (count($aNotTitleMatch) > 0) {
         $sSqlWhere .= ' AND NOT (';
         $n = 0;
         foreach ($aNotTitleMatch as $link) {
             if ($n > 0) {
                 $sSqlWhere .= ' OR ';
             }
             if ($acceptOpenReferences) {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'LOWER(CAST(pl_title AS char))' . $sNotTitleMatchMode . 'LOWER(' . $dbr->addQuotes($link) . ')';
                 } else {
                     $sSqlWhere .= 'pl_title' . $sNotTitleMatchMode . $dbr->addQuotes($link);
                 }
             } else {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'LOWER(CAST(' . $sPageTable . '.page_title AS char))' . $sNotTitleMatchMode . 'LOWER(' . $dbr->addQuotes($link) . ')';
                 } else {
                     $sSqlWhere .= $sPageTable . '.page_title' . $sNotTitleMatchMode . $dbr->addQuotes($link);
                 }
             }
             $n++;
         }
         $sSqlWhere .= ')';
     }
     // rev_minor_edit IS
     if (isset($sMinorEdits) && $sMinorEdits == 'exclude') {
         $sSqlWhere .= ' AND rev_minor_edit=0';
     }
     // page_is_redirect IS ...
     if (!$acceptOpenReferences) {
         switch ($sRedirects) {
             case 'only':
                 $sSqlWhere .= ' AND ' . $sPageTable . '.page_is_redirect=1';
                 break;
             case 'exclude':
                 $sSqlWhere .= ' AND ' . $sPageTable . '.page_is_redirect=0';
                 break;
         }
     }
     // page_id=rev_page (if revision table required)
     $sSqlWhere .= $sSqlCond_page_rev;
     if ($iMinRevisions != null) {
         $sSqlWhere .= " and ((SELECT count(rev_aux2.rev_page) FROM revision AS rev_aux2 WHERE rev_aux2.rev_page=page.page_id) >= {$iMinRevisions})";
     }
     if ($iMaxRevisions != null) {
         $sSqlWhere .= " and ((SELECT count(rev_aux3.rev_page) FROM revision AS rev_aux3 WHERE rev_aux3.rev_page=page.page_id) <= {$iMaxRevisions})";
     }
     // count(all categories) <= max no of categories
     $sSqlWhere .= $sSqlCond_MaxCat;
     // check against forbidden namespaces
     if (is_array($wgNonincludableNamespaces) && array_count_values($wgNonincludableNamespaces) > 0 && implode(',', $wgNonincludableNamespaces) != '') {
         $sSqlWhere .= ' AND ' . $sPageTable . '.page_namespace NOT IN (' . implode(',', $wgNonincludableNamespaces) . ')';
     }
     // page_id=pl.pl_from (if pagelinks table required)
     $sSqlWhere .= $sSqlCond_page_pl;
     // page_id=el.el_from (if external links table required)
     $sSqlWhere .= $sSqlCond_page_el;
     // page_id=tpl.tl_from (if templatelinks table required)
     $sSqlWhere .= $sSqlCond_page_tpl;
     if (isset($sArticleCategory) && $sArticleCategory !== null) {
         $sSqlWhere .= " AND {$sPageTable}.page_title IN (\n                SELECT p2.page_title\n                FROM {$sPageTable} p2\n                INNER JOIN {$sCategorylinksTable} clstc ON (clstc.cl_from = p2.page_id AND clstc.cl_to = " . $dbr->addQuotes($sArticleCategory) . " )\n                WHERE p2.page_namespace = 0\n                ) ";
     }
     if (function_exists('efLoadFlaggedRevs')) {
         $filterSet = array('only', 'exclude');
         # Either involves the same JOIN here...
         if (in_array($sStable, $filterSet) || in_array($sQuality, $filterSet)) {
             $flaggedpages = $dbr->tableName('flaggedpages');
             $sSqlSelectFrom .= " LEFT JOIN {$flaggedpages} ON page_id = fp_page_id";
         }
         switch ($sStable) {
             case 'only':
                 $sSqlWhere .= ' AND fp_stable IS NOT NULL ';
                 break;
             case 'exclude':
                 $sSqlWhere .= ' AND fp_stable IS NULL ';
                 break;
         }
         switch ($sQuality) {
             case 'only':
                 $sSqlWhere .= ' AND fp_quality >= 1';
                 break;
             case 'exclude':
                 $sSqlWhere .= ' AND fp_quality = 0';
                 break;
         }
     }
     // GROUP BY ...
     if ($sSqlGroupBy != '') {
         $sSqlWhere .= ' GROUP BY ' . $sSqlGroupBy . ' ';
     }
     // ORDER BY ...
     if ($aOrderMethods[0] != '' && $aOrderMethods[0] != 'none') {
         $sSqlWhere .= ' ORDER BY ';
         foreach ($aOrderMethods as $i => $sOrderMethod) {
             if ($i > 0) {
                 $sSqlWhere .= ', ';
             }
             switch ($sOrderMethod) {
                 case 'category':
                     $sSqlWhere .= 'cl_head.cl_to';
                     break;
                 case 'categoryadd':
                     $sSqlWhere .= 'cl0.cl_timestamp';
                     break;
                 case 'counter':
                     $sSqlWhere .= 'page_counter';
                     break;
                 case 'size':
                     $sSqlWhere .= 'page_len';
                     break;
                 case 'firstedit':
                     $sSqlWhere .= 'rev_timestamp';
                     break;
                 case 'lastedit':
                     // extension:intersection used to sort by page_touched although the field is called 'lastedit'
                     if (ExtDynamicPageList::$behavingLikeIntersection) {
                         $sSqlWhere .= 'page_touched';
                     } else {
                         $sSqlWhere .= 'rev_timestamp';
                     }
                     break;
                 case 'pagetouched':
                     $sSqlWhere .= 'page_touched';
                     break;
                 case 'sortkey':
                 case 'title':
                 case 'pagesel':
                     $sSqlWhere .= 'sortkey';
                     break;
                 case 'titlewithoutnamespace':
                     if ($acceptOpenReferences) {
                         $sSqlWhere .= "pl_title";
                     } else {
                         $sSqlWhere .= "page_title";
                     }
                     break;
                 case 'user':
                     // rev_user_text can discriminate anonymous users (e.g. based on IP), rev_user cannot (=' 0' for all)
                     $sSqlWhere .= 'rev_user_text';
                     break;
                 default:
             }
         }
         if ($sOrder == 'descending') {
             $sSqlWhere .= ' DESC';
         } else {
             $sSqlWhere .= ' ASC';
         }
     }
     if ($sAllRevisionsSince != '' || $sAllRevisionsBefore != '') {
         if ($aOrderMethods[0] == '' || $aOrderMethods[0] == 'none') {
             $sSqlWhere .= ' ORDER BY ';
         } else {
             $sSqlWhere .= ', ';
         }
         $sSqlWhere .= 'rev_id DESC';
     }
     // LIMIT ....
     // we must switch off LIMITS when going for categories as output goal (due to mysql limitations)
     if ((!ExtDynamicPageList::$allowUnlimitedResults || $iCount >= 0) && $sGoal != 'categories') {
         if ($iCount < 0) {
             $iCount = intval(ExtDynamicPageList::$options['count']['default']);
         }
         $sSqlWhere .= " LIMIT {$iCount} OFFSET {$iOffset} ";
     }
     // when we go for a list of categories as result we transform the output of the normal query into a subquery
     // of a selection on the categorylinks
     if ($sGoal == 'categories') {
         $sSqlSelectFrom = 'SELECT DISTINCT cl3.cl_to FROM ' . $sCategorylinksTable . ' AS cl3 WHERE cl3.cl_from IN ( ' . preg_replace('/SELECT +DISTINCT +.* FROM /', 'SELECT DISTINCT ' . $sPageTable . '.page_id FROM ', $sSqlSelectFrom);
         if ($sOrder == 'descending') {
             $sSqlWhere .= ' ) ORDER BY cl3.cl_to DESC';
         } else {
             $sSqlWhere .= ' ) ORDER BY cl3.cl_to ASC';
         }
     }
     // ###### DUMP SQL QUERY ######
     if ($logger->iDebugLevel >= 3) {
         //DEBUG: output SQL query
         $output .= "DPL debug -- Query=<br />\n<tt>" . $sSqlSelectFrom . $sSqlWhere . "</tt>\n\n";
     }
     // Do NOT proces the SQL command if debug==6; this is useful if the SQL statement contains bad code
     if ($logger->iDebugLevel == 6) {
         return $output;
     }
     // ###### PROCESS SQL QUERY ######
     try {
         $res = $dbr->query($sSqlSelectFrom . $sSqlWhere);
     } catch (Exception $e) {
         $result = "The DPL extension (version " . ExtDynamicPageList::$DPLVersion . ") produced a SQL statement which lead to a Database error.<br>\n" . "The reason may be an internal error of DPL or an error which you made,<br />\n" . "especially when using DPL options like titleregexp.<br />\n" . "Query text is:<br />\n<tt>" . $sSqlSelectFrom . $sSqlWhere . "</tt>\n\n" . "Error message is:<br />\n<tt>" . $dbr->lastError() . "</tt>\n\n";
         return $result;
     }
     // Wikia change - mark transactions that trigger DPL queries (PLATFORM-1074)
     Transaction::setAttribute(Transaction::PARAM_DPL, true);
     if ($dbr->numRows($res) <= 0) {
         $header = str_replace('%TOTALPAGES%', '0', str_replace('%PAGES%', '0', $sNoResultsHeader));
         if ($sNoResultsHeader != '') {
             $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $header));
         }
         $footer = str_replace('%TOTALPAGES%', '0', str_replace('%PAGES%', '0', $sNoResultsFooter));
         if ($sNoResultsFooter != '') {
             $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $footer));
         }
         if ($sNoResultsHeader == '' && $sNoResultsFooter == '') {
             $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_NORESULTS);
         }
         $dbr->freeResult($res);
         return $output;
     }
     // generate title for Special:Contributions (used if adduser=true)
     $sSpecContribs = '[[:Special:Contributions|Contributions]]';
     $aHeadings = array();
     // maps heading to count (# of pages under each heading)
     $aArticles = array();
     // pick some elements by random
     $pick[0] = true;
     if (isset($iRandomCount)) {
         $nResults = $dbr->numRows($res);
         if (isset($iRandomSeed)) {
             mt_srand($iRandomSeed);
         } else {
             mt_srand((double) microtime() * 10000000);
         }
         if ($iRandomCount > $nResults) {
             $iRandomCount = $nResults;
         }
         $r = 0;
         while (true) {
             $rnum = mt_rand(1, $nResults);
             if (!isset($pick[$rnum])) {
                 $pick[$rnum] = true;
                 $r++;
                 if ($r >= $iRandomCount) {
                     break;
                 }
             }
         }
     }
     $thisTitle = $parser->getTitle();
     $iArticle = 0;
     $firstNamespaceFound = '';
     $firstTitleFound = '';
     $lastNamespaceFound = '';
     $lastTitleFound = '';
     foreach ($res as $row) {
         $iArticle++;
         // in random mode skip articles which were not chosen
         if (isset($iRandomCount) && !isset($pick[$iArticle])) {
             continue;
         }
         if ($sGoal == 'categories') {
             $pageNamespace = 14;
             // CATEGORY
             $pageTitle = $row->cl_to;
         } else {
             if ($acceptOpenReferences) {
                 if (count($aImageContainer) > 0) {
                     $pageNamespace = 6;
                     $pageTitle = $row->il_to;
                 } else {
                     // maybe non-existing title
                     $pageNamespace = $row->pl_namespace;
                     $pageTitle = $row->pl_title;
                 }
             } else {
                 // existing PAGE TITLE
                 $pageNamespace = $row->page_namespace;
                 $pageTitle = $row->page_title;
             }
         }
         // if subpages are to be excluded: skip them
         if (!$bIncludeSubpages && !(strpos($pageTitle, '/') === false)) {
             continue;
         }
         $title = Title::makeTitle($pageNamespace, $pageTitle);
         // block recursion: avoid to show the page which contains the DPL statement as part of the result
         if ($bSkipThisPage && $thisTitle->equals($title)) {
             // $output.= 'BLOCKED '.$thisTitle->getText().' DUE TO RECURSION'."\n";
             continue;
         }
         $dplArticle = new DPLArticle($title, $pageNamespace);
         //PAGE LINK
         $sTitleText = $title->getText();
         if ($bShowNamespace) {
             $sTitleText = $title->getPrefixedText();
         }
         if ($aReplaceInTitle[0] != '') {
             $sTitleText = preg_replace($aReplaceInTitle[0], $aReplaceInTitle[1], $sTitleText);
         }
         //chop off title if "too long"
         if (isset($iTitleMaxLen) && strlen($sTitleText) > $iTitleMaxLen) {
             $sTitleText = substr($sTitleText, 0, $iTitleMaxLen) . '...';
         }
         if ($bShowCurID && isset($row->page_id)) {
             //$articleLink = '<html>'.Linker::makeKnownLinkObj($title, htmlspecialchars($sTitleText),'curid='.$row->page_id).'</html>';
             $articleLink = '[{{fullurl:' . $title->getText() . '|curid=' . $row->page_id . '}} ' . htmlspecialchars($sTitleText) . ']';
         } else {
             if (!$bEscapeLinks || $pageNamespace != 14 && $pageNamespace != 6) {
                 // links to categories or images need an additional ":"
                 $articleLink = '[[' . $title->getPrefixedText() . '|' . $wgContLang->convert($sTitleText) . ']]';
             } else {
                 // $articleLink = '<html>'.Linker::makeKnownLinkObj($title, htmlspecialchars($sTitleText)).'</html>';
                 $articleLink = '[{{fullurl:' . $title->getText() . '}} ' . htmlspecialchars($sTitleText) . ']';
             }
         }
         $dplArticle->mLink = $articleLink;
         //get first char used for category-style output
         if (isset($row->sortkey)) {
             $dplArticle->mStartChar = $wgContLang->convert($wgContLang->firstChar($row->sortkey));
         }
         if (isset($row->sortkey)) {
             $dplArticle->mStartChar = $wgContLang->convert($wgContLang->firstChar($row->sortkey));
         } else {
             $dplArticle->mStartChar = $wgContLang->convert($wgContLang->firstChar($pageTitle));
         }
         // page_id
         if (isset($row->page_id)) {
             $dplArticle->mID = $row->page_id;
         } else {
             $dplArticle->mID = 0;
         }
         // external link
         if (isset($row->el_to)) {
             $dplArticle->mExternalLink = $row->el_to;
         }
         //SHOW PAGE_COUNTER
         if (isset($row->page_counter)) {
             $dplArticle->mCounter = $row->page_counter;
         }
         //SHOW PAGE_SIZE
         if (isset($row->page_len)) {
             $dplArticle->mSize = $row->page_len;
         }
         //STORE initially selected PAGE
         if (count($aLinksTo) > 0 || count($aLinksFrom) > 0) {
             if (!isset($row->sel_title)) {
                 $dplArticle->mSelTitle = 'unknown page';
                 $dplArticle->mSelNamespace = 0;
             } else {
                 $dplArticle->mSelTitle = $row->sel_title;
                 $dplArticle->mSelNamespace = $row->sel_ns;
             }
         }
         //STORE selected image
         if (count($aImageUsed) > 0) {
             if (!isset($row->image_sel_title)) {
                 $dplArticle->mImageSelTitle = 'unknown image';
             } else {
                 $dplArticle->mImageSelTitle = $row->image_sel_title;
             }
         }
         if ($bGoalIsPages) {
             //REVISION SPECIFIED
             if ($sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince != '') {
                 $dplArticle->mRevision = $row->rev_id;
                 $dplArticle->mUser = $row->rev_user_text;
                 $dplArticle->mDate = $row->rev_timestamp;
             }
             //SHOW "PAGE_TOUCHED" DATE, "FIRSTCATEGORYDATE" OR (FIRST/LAST) EDIT DATE
             if ($bAddPageTouchedDate) {
                 $dplArticle->mDate = $row->page_touched;
             } elseif ($bAddFirstCategoryDate) {
                 $dplArticle->mDate = $row->cl_timestamp;
             } elseif ($bAddEditDate && isset($row->rev_timestamp)) {
                 $dplArticle->mDate = $row->rev_timestamp;
             } elseif ($bAddEditDate && isset($row->page_touched)) {
                 $dplArticle->mDate = $row->page_touched;
             }
             // time zone adjustment
             if ($dplArticle->mDate != '') {
                 $dplArticle->mDate = $wgLang->userAdjust($dplArticle->mDate);
             }
             if ($dplArticle->mDate != '' && $sUserDateFormat != '') {
                 // we apply the userdateformat
                 $dplArticle->myDate = gmdate($sUserDateFormat, wfTimeStamp(TS_UNIX, $dplArticle->mDate));
             }
             // CONTRIBUTION, CONTRIBUTOR
             if ($bAddContribution) {
                 $dplArticle->mContribution = $row->contribution;
                 $dplArticle->mContributor = $row->contributor;
                 $dplArticle->mContrib = substr('*****************', 0, round(log($row->contribution)));
             }
             //USER/AUTHOR(S)
             // because we are going to do a recursive parse at the end of the output phase
             // we have to generate wiki syntax for linking to a user´s homepage
             if ($bAddUser || $bAddAuthor || $bAddLastEditor || $sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince != '') {
                 $dplArticle->mUserLink = '[[User:'******'|' . $row->rev_user_text . ']]';
                 $dplArticle->mUser = $row->rev_user_text;
                 $dplArticle->mComment = $row->rev_comment;
             }
             //CATEGORY LINKS FROM CURRENT PAGE
             if ($bAddCategories && $bGoalIsPages && $row->cats != '') {
                 $artCatNames = explode(' | ', $row->cats);
                 foreach ($artCatNames as $artCatName) {
                     $dplArticle->mCategoryLinks[] = '[[:Category:' . $artCatName . '|' . str_replace('_', ' ', $artCatName) . ']]';
                     $dplArticle->mCategoryTexts[] = str_replace('_', ' ', $artCatName);
                 }
             }
             // PARENT HEADING (category of the page, editor (user) of the page, etc. Depends on ordermethod param)
             if ($sHListMode != 'none') {
                 switch ($aOrderMethods[0]) {
                     case 'category':
                         //count one more page in this heading
                         $aHeadings[$row->cl_to] = isset($aHeadings[$row->cl_to]) ? $aHeadings[$row->cl_to] + 1 : 1;
                         if ($row->cl_to == '') {
                             //uncategorized page (used if ordermethod=category,...)
                             $dplArticle->mParentHLink = '[[:Special:Uncategorizedpages|' . wfMsg('uncategorizedpages') . ']]';
                         } else {
                             $dplArticle->mParentHLink = '[[:Category:' . $row->cl_to . '|' . str_replace('_', ' ', $row->cl_to) . ']]';
                         }
                         break;
                     case 'user':
                         $aHeadings[$row->rev_user_text] = isset($aHeadings[$row->rev_user_text]) ? $aHeadings[$row->rev_user_text] + 1 : 1;
                         if ($row->rev_user == 0) {
                             //anonymous user
                             $dplArticle->mParentHLink = '[[User:'******'|' . $row->rev_user_text . ']]';
                         } else {
                             $dplArticle->mParentHLink = '[[User:'******'|' . $row->rev_user_text . ']]';
                         }
                         break;
                 }
             }
         }
         $aArticles[] = $dplArticle;
     }
     $dbr->freeResult($res);
     $rowcount = -1;
     if ($sSqlCalcFoundRows != '') {
         $res = $dbr->query('SELECT FOUND_ROWS() AS rowcount');
         $row = $dbr->fetchObject($res);
         $rowcount = $row->rowcount;
         $dbr->freeResult($res);
     }
     // backward scrolling: if the user specified titleLE we reverse the output order
     if ($sTitleLE != '' && $sTitleGE == '' && $sOrder == 'descending') {
         $aArticles = array_reverse($aArticles);
     }
     // special sort for card suits (Bridge)
     if ($bOrderSuitSymbols) {
         self::cardSuitSort($aArticles);
     }
     // ###### SHOW OUTPUT ######
     $listMode = new DPLListMode($sPageListMode, $aSecSeparators, $aMultiSecSeparators, $sInlTxt, $sListHtmlAttr, $sItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection);
     $hListMode = new DPLListMode($sHListMode, $aSecSeparators, $aMultiSecSeparators, '', $sHListHtmlAttr, $sHItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection);
     $dpl = new DPL($aHeadings, $bHeadingCount, $iColumns, $iRows, $iRowSize, $sRowColFormat, $aArticles, $aOrderMethods[0], $hListMode, $listMode, $bEscapeLinks, $bAddExternalLink, $bIncPage, $iIncludeMaxLen, $aSecLabels, $aSecLabelsMatch, $aSecLabelsNotMatch, $bIncParsed, $parser, $logger, $aReplaceInTitle, $iTitleMaxLen, $defaultTemplateSuffix, $aTableRow, $bIncludeTrim, $iTableSortCol, $sUpdateRules, $sDeleteRules);
     if ($rowcount == -1) {
         $rowcount = $dpl->getRowCount();
     }
     $dplResult = $dpl->getText();
     $header = '';
     if ($sOneResultHeader != '' && $rowcount == 1) {
         $header = str_replace('%TOTALPAGES%', $rowcount, str_replace('%PAGES%', 1, $sOneResultHeader));
     } else {
         if ($rowcount == 0) {
             $header = str_replace('%TOTALPAGES%', $rowcount, str_replace('%PAGES%', $dpl->getRowCount(), $sNoResultsHeader));
             if ($sNoResultsHeader != '') {
                 $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $header));
             }
             $footer = str_replace('%TOTALPAGES%', $rowcount, str_replace('%PAGES%', $dpl->getRowCount(), $sNoResultsFooter));
             if ($sNoResultsFooter != '') {
                 $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $footer));
             }
             if ($sNoResultsHeader == '' && $sNoResultsFooter == '') {
                 $output .= $logger->escapeMsg(ExtDynamicPageList::WARN_NORESULTS);
             }
         } else {
             if ($sResultsHeader != '') {
                 $header = str_replace('%TOTALPAGES%', $rowcount, str_replace('%PAGES%', $dpl->getRowCount(), $sResultsHeader));
             }
         }
     }
     $header = str_replace('\\n', "\n", str_replace("¶", "\n", $header));
     $header = str_replace('%VERSION%', ExtDynamicPageList::$DPLVersion, $header);
     $footer = '';
     if ($sOneResultFooter != '' && $rowcount == 1) {
         $footer = str_replace('%PAGES%', 1, $sOneResultFooter);
     } else {
         if ($sResultsFooter != '') {
             $footer = str_replace('%TOTALPAGES%', $rowcount, str_replace('%PAGES%', $dpl->getRowCount(), $sResultsFooter));
         }
     }
     $footer = str_replace('\\n', "\n", str_replace("¶", "\n", $footer));
     $footer = str_replace('%VERSION%', ExtDynamicPageList::$DPLVersion, $footer);
     // replace %DPLTIME% by execution time and timestamp in header and footer
     $nowTimeStamp = self::prettyTimeStamp(date('YmdHis'));
     $dplElapsedTime = sprintf('%.3f sec.', microtime(true) - $dplStartTime);
     $header = str_replace('%DPLTIME%', "{$dplElapsedTime} ({$nowTimeStamp})", $header);
     $footer = str_replace('%DPLTIME%', "{$dplElapsedTime} ({$nowTimeStamp})", $footer);
     // replace %LASTTITLE% / %LASTNAMESPACE% by the last title found in header and footer
     if (($n = count($aArticles)) > 0) {
         $firstNamespaceFound = str_replace(' ', '_', $aArticles[0]->mTitle->getNamespace());
         $firstTitleFound = str_replace(' ', '_', $aArticles[0]->mTitle->getText());
         $lastNamespaceFound = str_replace(' ', '_', $aArticles[$n - 1]->mTitle->getNamespace());
         $lastTitleFound = str_replace(' ', '_', $aArticles[$n - 1]->mTitle->getText());
     }
     $header = str_replace('%FIRSTNAMESPACE%', $firstNamespaceFound, $header);
     $footer = str_replace('%FIRSTNAMESPACE%', $firstNamespaceFound, $footer);
     $header = str_replace('%FIRSTTITLE%', $firstTitleFound, $header);
     $footer = str_replace('%FIRSTTITLE%', $firstTitleFound, $footer);
     $header = str_replace('%LASTNAMESPACE%', $lastNamespaceFound, $header);
     $footer = str_replace('%LASTNAMESPACE%', $lastNamespaceFound, $footer);
     $header = str_replace('%LASTTITLE%', $lastTitleFound, $header);
     $footer = str_replace('%LASTTITLE%', $lastTitleFound, $footer);
     $header = str_replace('%SCROLLDIR%', $scrollDir, $header);
     $footer = str_replace('%SCROLLDIR%', $scrollDir, $footer);
     $output .= $header . $dplResult . $footer;
     self::defineScrollVariables($firstNamespaceFound, $firstTitleFound, $lastNamespaceFound, $lastTitleFound, $scrollDir, $iCount, "{$dplElapsedTime} ({$nowTimeStamp})", $rowcount, $dpl->getRowCount());
     // save generated wiki text to dplcache page if desired
     if ($DPLCache != '') {
         // save data in chosen storage
         switch ($DPLCacheStorage) {
             case 'files':
                 if (!is_writeable($cacheFile)) {
                     wfMkdirParents(dirname($cacheFile));
                 } elseif (($bDPLRefresh || $wgRequest->getVal('action', 'view') == 'submit') && strpos($DPLCache, '/') > 0 && strpos($DPLCache, '..') === false) {
                     // if the cache file contains a path and the user requested a refresh (or saved the file) we delete all brothers
                     wfRecursiveRemoveDir(dirname($cacheFile));
                     wfMkdirParents(dirname($cacheFile));
                 }
                 $cFile = fopen($cacheFile, 'w');
                 fwrite($cFile, $originalInput);
                 fwrite($cFile, "+++\n");
                 fwrite($cFile, $output);
                 fclose($cFile);
                 break;
             case 'memcache':
                 // create the unique cache key (replace spaces with underscores)
                 $cacheKey = self::getMemcacheKey($DPLCache);
                 $cacheData = array('timestamp' => time(), 'input' => $originalInput, 'output' => $output);
                 $wgMemc->set($cacheKey, $cacheData, $iDPLCachePeriod);
                 break;
         }
         $cacheTimeStamp = self::prettyTimeStamp(date('YmdHis'));
         $dplElapsedTime = time() - $dplStartTime;
         if ($logger->iDebugLevel >= 2) {
             $output .= "{{Extension DPL cache|mode=update|page={{FULLPAGENAME}}|cache={$DPLCache}|date={$cacheTimeStamp}|age=0|now=" . date('H:i:s') . "|dpltime={$dplElapsedTime}|offset={$iOffset}}}";
         }
         /** Wikia change begin - never disable parser cache (CE-1066) **/
         // $parser->disableCache();
         /** Wikia change end **/
     }
     // update dependencies to CacheAPI if DPL is to respect the MW ParserCache and the page containing the DPL query is changed
     if (ExtDynamicPageList::$useCacheAPI && $bAllowCachedResults && $wgRequest->getVal('action', 'view') == 'submit') {
         /*
         			CacheAPI::remDependencies( $parser->mTitle->getArticleID());
         
         			// add category dependencies
         
         			$conditionTypes = array ( CACHETYPE_CATEGORY );
         			$conditions = array();
         			$conditions[0] = array();
         			$categorylist = array();
         			foreach ($aIncludeCategories as $categorygroup) {
         				$c=0;
         				foreach ($categorygroup as $category) {
         					if ($c==0) $conditions[0][]= $category;
         					$c++;
         				}
         			}
         
         			// add template dependencies
         
         			// add link dependencies
         
         			// add general dependencies
         
         			// CacheAPI::addDependencies ( $parser->mTitle->getArticleID(), $conditionTypes, $conditions);
         */
     }
     // The following requires an extra parser step which may consume some time
     // we parse the DPL output and save all references found in that output in a global list
     // in a final user exit after the whole document processing we eliminate all these links
     // we use a local parser to avoid interference with the main parser
     if ($bReset[4] || $bReset[5] || $bReset[6] || $bReset[7]) {
         // register a hook to reset links which were produced during parsing DPL output
         global $wgHooks;
         if (!isset($wgHooks['ParserAfterTidy']) || !(in_array('ExtDynamicPageList::endEliminate', $wgHooks['ParserAfterTidy']) || in_array(array('ExtDynamicPageList', 'endEliminate'), $wgHooks['ParserAfterTidy'], true))) {
             $wgHooks['ParserAfterTidy'][] = 'ExtDynamicPageList' . '__endEliminate';
         }
         $parserOutput = $localParser->parse($output, $parser->mTitle, $parser->mOptions);
     }
     if ($bReset[4]) {
         // LINKS
         // we trigger the mediawiki parser to find links, images, categories etc. which are contained in the DPL output
         // this allows us to remove these links from the link list later
         // If the article containing the DPL statement itself uses one of these links they will be thrown away!
         ExtDynamicPageList::$createdLinks[0] = array();
         foreach ($parserOutput->getLinks() as $nsp => $link) {
             ExtDynamicPageList::$createdLinks[0][$nsp] = $link;
         }
     }
     if ($bReset[5]) {
         // TEMPLATES
         ExtDynamicPageList::$createdLinks[1] = array();
         foreach ($parserOutput->getTemplates() as $nsp => $tpl) {
             ExtDynamicPageList::$createdLinks[1][$nsp] = $tpl;
         }
     }
     if ($bReset[6]) {
         // CATEGORIES
         ExtDynamicPageList::$createdLinks[2] = $parserOutput->mCategories;
     }
     if ($bReset[7]) {
         // IMAGES
         ExtDynamicPageList::$createdLinks[3] = $parserOutput->mImages;
     }
     return $output;
 }
 private function buildRevisionLine($rev, $title, $isFirst = false, $isLast = false)
 {
     // Builds a line for revision $rev
     // Helper to buildRevisionList() and buildOneRevForm()
     // $rev: Revision object
     // $title: Title object
     // $isFirst: Set to true if $rev is the first revision
     // $isLast: Set to true if $rev is the last revision
     // Returns: HTML
     // Build curlink
     if ($isFirst) {
         $curLink = wfMsgExt('cur', array('escape'));
     } else {
         $curLink = $this->skin->makeKnownLinkObj($title, wfMsgExt('cur', array('escape')), "oldid={$rev->getId()}&diff=cur");
     }
     if ($isLast) {
         $lastLink = wfMsgExt('last', array('escape'));
     } else {
         $lastLink = $this->skin->makeKnownLinkObj($title, wfMsgExt('last', array('escape')), "oldid=prev&diff={$rev->getId()}");
     }
     // Build oldid link
     global $wgLang;
     $date = $wgLang->timeanddate(wfTimeStamp(TS_MW, $rev->getTimestamp()), true);
     if ($rev->userCan(Revision::DELETED_TEXT)) {
         $link = $this->skin->makeKnownLinkObj($title, $date, "oldid={$rev->getId()}");
     } else {
         $link = $date;
     }
     // Build user textbox
     global $wgRequest;
     $userBox = Xml::input("user-new-{$rev->getId()}", 50, $wgRequest->getVal("user-{$rev->getId()}", $rev->getUserText()));
     $userText = Xml::hidden("user-old-{$rev->getId()}", $rev->getUserText()) . $rev->getUserText();
     if (!is_null($size = $rev->getSize())) {
         if ($size == 0) {
             $stxt = wfMsgHtml('historyempty');
         } else {
             $stxt = wfMsgHtml('historysize', $wgLang->formatNum($size));
         }
     } else {
         $stxt = '';
     }
     // Stop PHP from whining about unset variables
     $comment = $this->skin->commentBlock($rev->getComment(), $title);
     // Now put it all together
     return "<li>({$curLink}) ({$lastLink}) {$link} . . {$userBox} ({$userText}) {$stxt} {$comment}</li>\n";
 }
Exemplo n.º 8
0
 /**
  * calls the webservice and returns the
  * webservice result. if an appropriate result
  * allready exists in the cache, then the
  * result is taken from the cache
  *
  * @param string $parameterSetId
  * @param string $resultParts
  * @return an array that contains the result
  */
 public function call($parameterSetId, $resultParts)
 {
     $resultParts = array_keys($resultParts);
     //always get parameters although a cached web service result might be used
     //because some features of the result extraction might want to know about
     //special parameters like the Linked Data subject and so on.
     $specParameters = WSStorage::getDatabase()->getParameters($parameterSetId);
     $this->initializeCallParameters($specParameters);
     $cacheResult = WSStorage::getDatabase()->getResultFromCache($this->mArticleID, $parameterSetId);
     $response = null;
     //check if an appropriate result allready exists in the cache
     if ($cacheResult != null) {
         if ($this->mDisplayPolicy == 0 || wfTime() - wfTimestamp(TS_UNIX, $cacheResult["lastUpdate"]) < $this->getDisplayPolicy() * 60) {
             $response = @unserialize($cacheResult["result"]);
             WSStorage::getDatabase()->updateCacheLastAccess($this->mArticleID, $parameterSetId);
         }
     }
     // get the result from a call to a webservice if there
     // was no appropriate result in the cache
     if (!$response) {
         if ($this->getConfirmationStatus() == "once") {
             return wfMsg('smw_wws_need_confirmation');
         } else {
             $this->createWSClient();
             if ($this->mWSClient) {
                 $response = $this->mWSClient->call($this->mMethod, $this->mCallParameters);
             } else {
                 return "Could not connect to Web Service. Please check your Wiki Web Service Definition.";
             }
             if (is_string($response)) {
                 return $response;
             } else {
                 //the content type which is required for RDF processing is stored together
                 //with the cached WS result -> implement better solution
                 if ($this->isLinkedDataResource()) {
                     $response['http-content-type'] = $this->getWSClient()->getContentType();
                 }
                 WSStorage::getDatabase()->storeCacheEntry($this->mArticleID, $parameterSetId, serialize($response), wfTimeStamp(TS_MW, wfTime()), wfTimeStamp(TS_MW, wfTime()));
             }
         }
     }
     //the content-type of the ws result, which is important for RDF parsing,
     //is stored in the cached response. Todo: Implement s.th. more elegant
     if (array_key_exists('http-content-type', $response)) {
         $this->responseContentType = $response['http-content-type'];
         unset($response['http-content-type']);
     }
     $result = $this->getCallResultParts($response[0], $resultParts);
     $ws = $this->mArticleID;
     if ($this->getConfirmationStatus() == "false") {
         $this->mConfirmationStatus = "once";
         WSStorage::getDatabase()->setWWSDConfirmationStatus($this->mArticleID, "once");
     }
     return $result;
 }
 /**
  * Subroutine for optionally prepending article match to result array. 
  * @return WikiaSearchResultSet provides fluent interface
  */
 public function prependArticleMatchIfExists()
 {
     wfProfileIn(__METHOD__);
     if (!($this->searchConfig->hasArticleMatch() && $this->resultsStart == 0)) {
         return $this;
     }
     $articleMatch = $this->searchConfig->getArticleMatch();
     $article = $articleMatch->getCanonicalArticle();
     $title = $article->getTitle();
     $articleId = $article->getID();
     if (!in_array($title->getNamespace(), $this->searchConfig->getNamespaces())) {
         // we had an article match by name, but not in our desired namespaces
         return $this;
     }
     $articleMatchId = sprintf('%s_%s', $this->wg->CityId, $articleId);
     $articleService = F::build('ArticleService', array($articleId));
     $firstRev = $title->getFirstRevision();
     $created = $firstRev ? wfTimestamp(TS_ISO_8601, $firstRev->getTimestamp()) : '';
     $lastRev = Revision::newFromId($title->getLatestRevID());
     $touched = $lastRev ? wfTimeStamp(TS_ISO_8601, $lastRev->getTimestamp()) : '';
     $fieldsArray = array('wid' => $this->wg->CityId, 'title' => $article->mTitle, 'url' => urldecode($title->getFullUrl()), 'score' => 'PTT', 'isArticleMatch' => true, 'ns' => $title->getNamespace(), 'pageId' => $article->getID(), 'created' => $created, 'touched' => $touched);
     //@TODO: we could put categories ^^ here but we aren't really using them yet
     $result = F::build('WikiaSearchResult', array($fieldsArray));
     $snippet = $articleService->getTextSnippet(250);
     $result->setText($snippet);
     if ($articleMatch->hasRedirect()) {
         $result->setVar('redirectTitle', $articleMatch->getArticle()->getTitle());
     }
     $result->setVar('id', $articleMatchId);
     $this->addResult($result);
     $this->resultsFound++;
     wfProfileOut(__METHOD__);
     return $this;
 }
Exemplo n.º 10
0
 /**
  * Initialize a new instance from a database row.
  *
  * @access	public
  * @param	array	Database Row
  * @param	object	\DPL\Parameters Object
  * @param	object	Mediawiki Title Object
  * @param	integer	Page Namespace ID
  * @param	string	Page Title as Selected from Query
  * @return	object	\DPL\Article Object
  */
 public static function newFromRow($row, Parameters $parameters, \Title $title, $pageNamespace, $pageTitle)
 {
     global $wgLang, $wgContLang;
     $article = new Article($title, $pageNamespace);
     $titleText = $title->getText();
     if ($parameters->getParameter('shownamespace') === true) {
         $titleText = $title->getPrefixedText();
     }
     if ($parameters->getParameter('replaceintitle') !== null) {
         $titleText = preg_replace($parameters->getParameter('replaceintitle')[0], $parameters->getParameter('replaceintitle')[1], $titleText);
     }
     //Chop off title if longer than the 'titlemaxlen' parameter.
     if ($parameters->getParameter('titlemaxlen') !== null && strlen($titleText) > $parameters->getParameter('titlemaxlen')) {
         $titleText = substr($titleText, 0, $parameters->getParameter('titlemaxlen')) . '...';
     }
     if ($parameters->getParameter('showcurid') === true && isset($row['page_id'])) {
         $articleLink = '[' . $title->getLinkURL(['curid' => $row['page_id']]) . ' ' . htmlspecialchars($titleText) . ']';
     } else {
         $articleLink = '[[' . ($parameters->getParameter('escapelinks') && ($pageNamespace == NS_CATEGORY || $pageNamespace == NS_FILE) ? ':' : '') . $title->getFullText() . '|' . htmlspecialchars($titleText) . ']]';
     }
     $article->mLink = $articleLink;
     //get first char used for category-style output
     if (isset($row['sortkey'])) {
         $article->mStartChar = $wgContLang->convert($wgContLang->firstChar($row['sortkey']));
     } else {
         $article->mStartChar = $wgContLang->convert($wgContLang->firstChar($pageTitle));
     }
     $article->mID = intval($row['page_id']);
     //External link
     if (isset($row['el_to'])) {
         $article->mExternalLink = $row['el_to'];
     }
     //SHOW PAGE_COUNTER
     if (isset($row['page_counter'])) {
         $article->mCounter = $row['page_counter'];
     }
     //SHOW PAGE_SIZE
     if (isset($row['page_len'])) {
         $article->mSize = $row['page_len'];
     }
     //STORE initially selected PAGE
     if (count($parameters->getParameter('linksto')) || count($parameters->getParameter('linksfrom'))) {
         if (!isset($row['sel_title'])) {
             $article->mSelTitle = 'unknown page';
             $article->mSelNamespace = 0;
         } else {
             $article->mSelTitle = $row['sel_title'];
             $article->mSelNamespace = $row['sel_ns'];
         }
     }
     //STORE selected image
     if (count($parameters->getParameter('imageused')) > 0) {
         if (!isset($row['image_sel_title'])) {
             $article->mImageSelTitle = 'unknown image';
         } else {
             $article->mImageSelTitle = $row['image_sel_title'];
         }
     }
     if ($parameters->getParameter('goal') != 'categories') {
         //REVISION SPECIFIED
         if ($parameters->getParameter('lastrevisionbefore') || $parameters->getParameter('allrevisionsbefore') || $parameters->getParameter('firstrevisionsince') || $parameters->getParameter('allrevisionssince')) {
             $article->mRevision = $row['rev_id'];
             $article->mUser = $row['rev_user_text'];
             $article->mDate = $row['rev_timestamp'];
             $article->mComment = $row['rev_comment'];
         }
         //SHOW "PAGE_TOUCHED" DATE, "FIRSTCATEGORYDATE" OR (FIRST/LAST) EDIT DATE
         if ($parameters->getParameter('addpagetoucheddate')) {
             $article->mDate = $row['page_touched'];
         } elseif ($parameters->getParameter('addfirstcategorydate')) {
             $article->mDate = $row['cl_timestamp'];
         } elseif ($parameters->getParameter('addeditdate') && isset($row['rev_timestamp'])) {
             $article->mDate = $row['rev_timestamp'];
         } elseif ($parameters->getParameter('addeditdate') && isset($row['page_touched'])) {
             $article->mDate = $row['page_touched'];
         }
         //Time zone adjustment
         if ($article->mDate) {
             $article->mDate = $wgLang->userAdjust($article->mDate);
         }
         if ($article->mDate && $parameters->getParameter('userdateformat')) {
             //Apply the userdateformat
             $article->myDate = gmdate($parameters->getParameter('userdateformat'), wfTimeStamp(TS_UNIX, $article->mDate));
         }
         // CONTRIBUTION, CONTRIBUTOR
         if ($parameters->getParameter('addcontribution')) {
             $article->mContribution = $row['contribution'];
             $article->mContributor = $row['contributor'];
             $article->mContrib = substr('*****************', 0, round(log($row['contribution'])));
         }
         //USER/AUTHOR(S)
         // because we are going to do a recursive parse at the end of the output phase
         // we have to generate wiki syntax for linking to a user´s homepage
         if ($parameters->getParameter('adduser') || $parameters->getParameter('addauthor') || $parameters->getParameter('addlasteditor')) {
             $article->mUserLink = '[[User:'******'rev_user_text'] . '|' . $row['rev_user_text'] . ']]';
             $article->mUser = $row['rev_user_text'];
         }
         //CATEGORY LINKS FROM CURRENT PAGE
         if ($parameters->getParameter('addcategories') && $row['cats']) {
             $artCatNames = explode(' | ', $row['cats']);
             foreach ($artCatNames as $artCatName) {
                 $article->mCategoryLinks[] = '[[:Category:' . $artCatName . '|' . str_replace('_', ' ', $artCatName) . ']]';
                 $article->mCategoryTexts[] = str_replace('_', ' ', $artCatName);
             }
         }
         // PARENT HEADING (category of the page, editor (user) of the page, etc. Depends on ordermethod param)
         if ($parameters->getParameter('headingmode') != 'none') {
             switch ($parameters->getParameter('ordermethod')[0]) {
                 case 'category':
                     //Count one more page in this heading
                     self::$headings[$row['cl_to']] = isset(self::$headings[$row['cl_to']]) ? self::$headings[$row['cl_to']] + 1 : 1;
                     if ($row['cl_to'] == '') {
                         //uncategorized page (used if ordermethod=category,...)
                         $article->mParentHLink = '[[:Special:Uncategorizedpages|' . wfMsg('uncategorizedpages') . ']]';
                     } else {
                         $article->mParentHLink = '[[:Category:' . $row['cl_to'] . '|' . str_replace('_', ' ', $row['cl_to']) . ']]';
                     }
                     break;
                 case 'user':
                     self::$headings[$row['rev_user_text']] = isset(self::$headings[$row['rev_user_text']]) ? self::$headings[$row['rev_user_text']] + 1 : 1;
                     if ($row['rev_user'] == 0) {
                         //anonymous user
                         $article->mParentHLink = '[[User:'******'rev_user_text'] . '|' . $row['rev_user_text'] . ']]';
                     } else {
                         $article->mParentHLink = '[[User:'******'rev_user_text'] . '|' . $row['rev_user_text'] . ']]';
                     }
                     break;
             }
         }
     }
     return $article;
 }
Exemplo n.º 11
0
 private static function dynamicPageList($input, $params, &$parser, &$bReset, $calledInMode)
 {
     error_reporting(E_ALL & ~E_STRICT);
     global $wgUser, $wgContLang;
     global $wgTitle, $wgNonincludableNamespaces;
     //logger (display of debug messages)
     $logger = new DPL2Logger();
     //check that we are not in an infinite transclusion loop
     if (isset($parser->mTemplatePath[$parser->mTitle->getPrefixedText()])) {
         return $logger->escapeMsg(DPL2_i18n::WARN_TRANSCLUSIONLOOP, $parser->mTitle->getPrefixedText());
     }
     /**
      * Initialization
      */
     // Local parser created. See http://meta.wikimedia.org/wiki/MediaWiki_extensions_FAQ#How_do_I_render_wikitext_in_my_extension.3F
     $localParser = ParserPool::create();
     $pOptions = $parser->mOptions;
     $pTitle = $parser->mTitle;
     // get database access
     $dbr = wfGetDB(DB_SLAVE, 'dpl');
     $sPageTable = $dbr->tableName('page');
     $sCategorylinksTable = $dbr->tableName('categorylinks');
     // Extension variables
     // Allowed namespaces for DPL2: all namespaces except the first 2: Media (-2) and Special (-1), because we cannot use the DB for these to generate dynamic page lists.
     if (!is_array(self::$allowedNamespaces)) {
         // Initialization
         $aNs = $wgContLang->getNamespaces();
         // namespaces which are nonicludable will maybe somewhen ignored
         // if (isset($wgNonincludableNamespaces)) {
         //	foreach ($wgNonincludableNamespaces as $nonInc) unset ($aNs[$nonInc]);
         // }
         self::$allowedNamespaces = array_slice($aNs, 2, count($aNs), true);
         if (!is_array(self::$options['namespace'])) {
             self::$options['namespace'] = self::$allowedNamespaces;
         } else {
             // Make sure user namespace options are allowed.
             self::$options['namespace'] = array_intersect(self::$options['namespace'], self::$allowedNamespaces);
         }
         if (!isset(self::$options['namespace']['default'])) {
             self::$options['namespace']['default'] = NULL;
         }
         if (!is_array(self::$options['notnamespace'])) {
             self::$options['notnamespace'] = self::$allowedNamespaces;
         } else {
             self::$options['notnamespace'] = array_intersect(self::$options['notnamespace'], self::$allowedNamespaces);
         }
         if (!isset(self::$options['notnamespace']['default'])) {
             self::$options['notnamespace']['default'] = NULL;
         }
     }
     // Options
     $sGoal = self::$options['goal']['default'];
     $bSelectionCriteriaFound = false;
     $bConflictsWithOpenReferences = false;
     // array for LINK / TEMPLATE / CATGEORY / IMAGE  by RESET / ELIMINATE
     $bReset = array(false, false, false, false, false, false, false, false);
     // we allow " like " or "="
     $sCategoryComparisonMode = '=';
     $sNotCategoryComparisonMode = '=';
     $sTitleMatchMode = ' LIKE ';
     $sNotTitleMatchMode = ' LIKE ';
     $aOrderMethods = explode(',', self::$options['ordermethod']['default']);
     $sOrder = self::$options['order']['default'];
     $sOrderCollation = self::$options['ordercollation']['default'];
     $sPageListMode = self::$options['mode']['default'];
     $sHListMode = self::$options['headingmode']['default'];
     $bHeadingCount = self::argBoolean(self::$options['headingcount']['default']);
     $bEscapeLinks = self::$options['escapelinks']['default'];
     $bSkipThisPage = self::$options['skipthispage']['default'];
     $sMinorEdits = NULL;
     $acceptOpenReferences = self::argBoolean(self::$options['openreferences']['default']);
     $sLastRevisionBefore = self::$options['lastrevisionbefore']['default'];
     $sAllRevisionsBefore = self::$options['allrevisionsbefore']['default'];
     $sFirstRevisionSince = self::$options['firstrevisionsince']['default'];
     $sAllRevisionsSince = self::$options['allrevisionssince']['default'];
     $sRedirects = self::$options['redirects']['default'];
     $sResultsHeader = self::$options['resultsheader']['default'];
     $sResultsFooter = self::$options['resultsfooter']['default'];
     $sNoResultsHeader = self::$options['noresultsheader']['default'];
     $sNoResultsFooter = self::$options['noresultsfooter']['default'];
     $sOneResultHeader = self::$options['oneresultheader']['default'];
     $sOneResultFooter = self::$options['oneresultfooter']['default'];
     $aListSeparators = array();
     $sTable = self::$options['table']['default'];
     $aTableRow = array();
     $sInlTxt = self::$options['inlinetext']['default'];
     $bShowNamespace = self::argBoolean(self::$options['shownamespace']['default']);
     $bAddFirstCategoryDate = self::argBoolean(self::$options['addfirstcategorydate']['default']);
     $bAddPageCounter = self::argBoolean(self::$options['addpagecounter']['default']);
     $bAddPageSize = self::argBoolean(self::$options['addpagesize']['default']);
     $bAddPageTouchedDate = self::argBoolean(self::$options['addpagetoucheddate']['default']);
     $bAddEditDate = self::argBoolean(self::$options['addeditdate']['default']);
     $bAddUser = self::argBoolean(self::$options['adduser']['default']);
     $bAddAuthor = self::argBoolean(self::$options['addauthor']['default']);
     $bAddContribution = self::argBoolean(self::$options['addcontribution']['default']);
     $bAddLastEditor = self::argBoolean(self::$options['addlasteditor']['default']);
     $bAllowCachedResults = self::argBoolean(self::$options['allowcachedresults']['default']);
     $sUserDateFormat = self::$options['userdateformat']['default'];
     $bAddCategories = self::argBoolean(self::$options['addcategories']['default']);
     $bIncludeSubpages = self::argBoolean(self::$options['includesubpages']['default']);
     $bIgnoreCase = self::argBoolean(self::$options['ignorecase']['default']);
     $_incpage = self::$options['includepage']['default'];
     $bIncPage = is_string($_incpage) && $_incpage !== '';
     $aSecLabels = array();
     if ($bIncPage && $_incpage != '*') {
         $aSecLabels = explode(',', $_incpage);
     }
     $aSecLabelsMatch = array();
     $aSecLabelsNotMatch = array();
     $aSecSeparators = array();
     $aSecSeparators = explode(',', self::$options['secseparators']['default']);
     $aMultiSecSeparators = explode(',', self::$options['multisecseparators']['default']);
     $iDominantSection = self::$options['dominantsection']['default'];
     $_sOffset = self::$options['offset']['default'];
     $iOffset = $_sOffset == '' ? 0 : intval($_sOffset);
     $_sCount = self::$options['count']['default'];
     $iCount = $_sCount == '' ? NULL : intval($_sCount);
     $_sColumns = self::$options['columns']['default'];
     $iColumns = $_sColumns == '' ? 1 : intval($_sColumns);
     $_sRows = self::$options['rows']['default'];
     $iRows = $_sRows == '' ? 1 : intval($_sRows);
     $_sRowSize = self::$options['rowsize']['default'];
     $iRowSize = $_sRowSize == '' ? 0 : intval($_sRowSize);
     $sRowColFormat = self::$options['rowcolformat']['default'];
     $_sRandomSeed = self::$options['randomseed']['default'];
     $iRandomSeed = $_sRandomSeed == '' ? NULL : intval($_sRandomSeed);
     $_sRandomCount = self::$options['randomcount']['default'];
     $iRandomCount = $_sRandomCount == '' ? NULL : intval($_sRandomCount);
     $sDistinctResultSet = 'true';
     $sListHtmlAttr = self::$options['listattr']['default'];
     $sItemHtmlAttr = self::$options['itemattr']['default'];
     $sHListHtmlAttr = self::$options['hlistattr']['default'];
     $sHItemHtmlAttr = self::$options['hitemattr']['default'];
     $_sTitleMaxLen = self::$options['titlemaxlength']['default'];
     $iTitleMaxLen = $_sTitleMaxLen == '' ? NULL : intval($_sTitleMaxLen);
     $aReplaceInTitle[0] = '';
     $aReplaceInTitle[1] = '';
     $_sCatMinMax = self::$options['categoriesminmax']['default'];
     $aCatMinMax = $_sCatMinMax == '' ? NULL : explode(',', $_sCatMinMax);
     $_sIncludeMaxLen = self::$options['includemaxlength']['default'];
     $iIncludeMaxLen = $_sIncludeMaxLen == '' ? NULL : intval($_sIncludeMaxLen);
     $aLinksTo = array();
     $aNotLinksTo = array();
     $aLinksFrom = array();
     $aNotLinksFrom = array();
     $aUses = array();
     $aNotUses = array();
     $sCreatedBy = '';
     $sNotCreatedBy = '';
     $sModifiedBy = '';
     $sNotModifiedBy = '';
     $sLastModifiedBy = '';
     $sNotLastModifiedBy = '';
     $aTitleMatch = array();
     $aNotTitleMatch = array();
     $sTitleIs = '';
     $aIncludeCategories = array();
     // $aIncludeCategories is a 2-dimensional array: Memberarrays are linked using 'AND'
     $aExcludeCategories = array();
     $aCatHeadings = array();
     $aCatNotHeadings = array();
     $aNamespaces = array();
     $aExcludeNamespaces = array();
     $sArticleCategory = null;
     // Output
     $output = '';
     // ###### PARSE PARAMETERS ######
     // we replace double angle brackets by < > ; thus we avoid premature tag expansion in the input
     $input = str_replace('»', '>', $input);
     $input = str_replace('«', '<', $input);
     // use the � as a general alias for |
     $input = str_replace('¦', '|', $input);
     // the symbol is utf8-escaped
     // the combination '�{' and '}�'will be translated to double curly braces; this allows postponed template execution
     // which is crucial for DPL queries which call other DPL queries
     $input = str_replace('²{', '{{', $input);
     $input = str_replace('}²', '}}', $input);
     $aParams = explode("\n", $input);
     $bIncludeUncat = false;
     // to check if pseudo-category of Uncategorized pages is included
     // version 0.9:
     // we do not parse parameters recursively when reading them in.
     // we rather leave them unchanged, produce the complete output and then finally
     // parse the result recursively. This allows to build complex structures in the output
     // which are only understood by the parser if seen as a whole
     foreach ($aParams as $iParam => $sParam) {
         $aParam = explode('=', $sParam, 2);
         if (count($aParam) < 2) {
             if (trim($aParam[0]) != '') {
                 $output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, $aParam[0] . " [missing '=']", implode(', ', array_keys(self::$options)));
             }
             continue;
         }
         $sType = trim($aParam[0]);
         $sArg = trim($aParam[1]);
         if ($sType == '') {
             $output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, '[empty string]', implode(', ', array_keys(self::$options)));
             continue;
         }
         // ignore comment lines
         if ($sType[0] == '#') {
             continue;
         }
         // ignore parameter settings without argument (except namespace and category)
         if ($sArg == '') {
             if ($sType != 'namespace' && $sType != 'notnamespace' && $sType != 'category' && array_key_exists($sType, self::$options)) {
                 continue;
             }
         }
         // check if parameter is known
         if (!array_key_exists($sType, self::$options)) {
             $output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, $sType, implode(', ', array_keys(self::$options)));
             continue;
         }
         switch ($sType) {
             /**
              * GOAL
              */
             case 'goal':
                 if (in_array($sArg, self::$options['goal'])) {
                     $sGoal = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('goal', $sArg);
                 }
                 break;
                 /**
                  * FILTER PARAMETERS
                  */
             /**
              * FILTER PARAMETERS
              */
             case 'categoryregexp':
                 $sCategoryComparisonMode = ' REGEXP ';
                 $aIncludeCategories[] = array($sArg);
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'categorymatch':
                 $sCategoryComparisonMode = ' LIKE ';
                 $aIncludeCategories[] = explode('|', $sArg);
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'category':
                 // Init array of categories to include
                 $aCategories = array();
                 $bHeading = false;
                 $bNotHeading = false;
                 if ($sArg != '' && $sArg[0] == '+') {
                     // categories are headings
                     $bHeading = true;
                     $sArg[0] = '';
                 }
                 if ($sArg != '' && $sArg[0] == '-') {
                     // categories are NOT headings
                     $bNotHeading = true;
                     $sArg[0] = '';
                 }
                 $aParams = explode('|', $sArg);
                 foreach ($aParams as $sParam) {
                     $sParam = trim($sParam);
                     if ($sParam == '') {
                         // include uncategorized pages (special value: empty string)
                         $bIncludeUncat = true;
                         $aCategories[] = '';
                     } else {
                         if ($sParam[0] == '*') {
                             $sParamList = explode('|', self::getSubcategories(substr($sParam, 1), $sPageTable));
                             foreach ($sParamList as $sPar) {
                                 $title = Title::newFromText($localParser->transformMsg($sPar, $pOptions));
                                 if (!is_null($title)) {
                                     $aCategories[] = $title->getDbKey();
                                 }
                             }
                         } else {
                             $title = Title::newFromText($localParser->transformMsg($sParam, $pOptions));
                             if (!is_null($title)) {
                                 $aCategories[] = $title->getDbKey();
                             }
                         }
                     }
                 }
                 if (!empty($aCategories)) {
                     $aIncludeCategories[] = $aCategories;
                     if ($bHeading) {
                         $aCatHeadings = array_unique($aCatHeadings + $aCategories);
                     }
                     if ($bNotHeading) {
                         $aCatNotHeadings = array_unique($aCatNotHeadings + $aCategories);
                     }
                     $bConflictsWithOpenReferences = true;
                 }
                 break;
             case 'notcategoryregexp':
                 $sNotCategoryComparisonMode = ' REGEXP ';
                 $aExcludeCategories[] = $sArg;
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notcategorymatch':
                 $sNotCategoryComparisonMode = ' LIKE ';
                 $aExcludeCategories[] = $sArg;
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notcategory':
                 $title = Title::newFromText($localParser->transformMsg($sArg, $pOptions));
                 if (!is_null($title)) {
                     $aExcludeCategories[] = $title->getDbKey();
                     $bConflictsWithOpenReferences = true;
                 }
                 break;
             case 'namespace':
                 $aParams = explode('|', $sArg);
                 foreach ($aParams as $sParam) {
                     $sParam = trim($sParam);
                     $sNs = $localParser->transformMsg($sParam, $pOptions);
                     if (!in_array($sNs, self::$options['namespace'])) {
                         return $logger->msgWrongParam('namespace', $sParam);
                     }
                     $aNamespaces[] = $wgContLang->getNsIndex($sNs);
                     $bSelectionCriteriaFound = true;
                 }
                 break;
             case 'notnamespace':
                 $sArg = trim($sArg);
                 $sNs = $localParser->transformMsg($sArg, $pOptions);
                 if (!in_array($sNs, self::$options['notnamespace'])) {
                     return $logger->msgWrongParam('notnamespace', $sArg);
                 }
                 $aExcludeNamespaces[] = $wgContLang->getNsIndex($sNs);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'linksto':
                 $pages = explode('|', trim($sArg));
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('linksto', $sArg);
                     }
                     $aLinksTo[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('linksto', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notlinksto':
                 $pages = explode('|', trim($sArg));
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('notlinksto', $sArg);
                     }
                     $aNotLinksTo[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('notlinksto', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'linksfrom':
                 $pages = explode('|', trim($sArg));
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('linksfrom', $sArg);
                     }
                     $aLinksFrom[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('linksfrom', $sArg);
                 }
                 break;
             case 'notlinksfrom':
                 $pages = explode('|', trim($sArg));
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('notlinksfrom', $sArg);
                     }
                     $aNotLinksFrom[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('notlinksfrom', $sArg);
                 }
                 break;
             case 'uses':
                 $pages = explode('|', $sArg);
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('uses', $sArg);
                     }
                     $aUses[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('uses', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notuses':
                 $pages = explode('|', $sArg);
                 $n = 0;
                 foreach ($pages as $page) {
                     if (trim($page) == '') {
                         continue;
                     }
                     if (!($theTitle = Title::newFromText(trim($page)))) {
                         return $logger->msgWrongParam('notuses', $sArg);
                     }
                     $aNotUses[$n++] = $theTitle;
                     $bSelectionCriteriaFound = true;
                 }
                 if (!$bSelectionCriteriaFound) {
                     return $logger->msgWrongParam('notuses', $sArg);
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'createdby':
                 $sCreatedBy = $sArg;
                 if ($sCreatedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notcreatedby':
                 $sNotCreatedBy = $sArg;
                 if ($sNotCreatedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'modifiedby':
                 $sModifiedBy = $sArg;
                 if ($sModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notmodifiedby':
                 $sNotModifiedBy = $sArg;
                 if ($sNotModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'lastmodifiedby':
                 $sLastModifiedBy = $sArg;
                 if ($sLastModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'notlastmodifiedby':
                 $sNotLastModifiedBy = $sArg;
                 if ($sNotLastModifiedBy != '') {
                     $bSelectionCriteriaFound = true;
                 }
                 $bConflictsWithOpenReferences = true;
                 break;
             case 'title':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $title = Title::newFromText($sArg);
                 if ($title) {
                     $sNamespace = $title->getNamespace();
                     $sTitleIs = str_replace(' ', '_', $title->getText());
                     $aNamespaces[0] = $sNamespace;
                     $sPageListMode = 'userformat';
                     $aOrderMethods = explode(',', '');
                     $bSelectionCriteriaFound = true;
                     $bConflictsWithOpenReferences = true;
                     $bAllowCachedResults = true;
                 }
                 break;
             case 'titleregexp':
                 $sTitleMatchMode = ' REGEXP ';
                 $aTitleMatch = array($sArg);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'titlematch':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $aTitleMatch = explode('|', str_replace(' ', '_', $localParser->transformMsg($sArg, $pOptions)));
                 $bSelectionCriteriaFound = true;
                 break;
             case 'nottitleregexp':
                 $sNotTitleMatchMode = ' REGEXP ';
                 $aNotTitleMatch = array($sArg);
                 $bSelectionCriteriaFound = true;
                 break;
             case 'nottitlematch':
                 // we replace blanks by underscores to meet the internal representation
                 // of page names in the database
                 $aNotTitleMatch = explode('|', str_replace(' ', '_', $localParser->transformMsg($sArg, $pOptions)));
                 $bSelectionCriteriaFound = true;
                 break;
             case 'minoredits':
                 if (in_array($sArg, self::$options['minoredits'])) {
                     $sMinorEdits = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     //wrong param val, using default
                     $sMinorEdits = self::$options['minoredits']['default'];
                     $output .= $logger->msgWrongParam('minoredits', $sArg);
                 }
                 break;
             case 'includesubpages':
                 if (in_array($sArg, self::$options['includesubpages'])) {
                     $bIncludeSubpages = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('includesubpages', $sArg);
                 }
                 break;
             case 'ignorecase':
                 if (in_array($sArg, self::$options['ignorecase'])) {
                     $bIgnoreCase = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('ignorecase', $sArg);
                 }
                 break;
             case 'lastrevisionbefore':
             case 'allrevisionsbefore':
             case 'firstrevisionsince':
             case 'allrevisionssince':
                 if (preg_match(self::$options[$sType]['pattern'], $sArg)) {
                     if ($sType == 'lastrevisionbefore') {
                         $sLastRevisionBefore = str_pad(preg_replace('/[^0-9]/', '', $sArg), 14, '0');
                     }
                     if ($sType == 'allrevisionsbefore') {
                         $sAllRevisionsBefore = str_pad(preg_replace('/[^0-9]/', '', $sArg), 14, '0');
                     }
                     if ($sType == 'firstrevisionsince') {
                         $sFirstRevisionSince = str_pad(preg_replace('/[^0-9]/', '', $sArg), 14, '0');
                     }
                     if ($sType == 'allrevisionssince') {
                         $sAllRevisionsSince = str_pad(preg_replace('/[^0-9]/', '', $sArg), 14, '0');
                     }
                     $bConflictsWithOpenReferences = true;
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam($sType, $sArg);
                 }
                 break;
             case 'openreferences':
                 if (in_array($sArg, self::$options['openreferences'])) {
                     $acceptOpenReferences = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('openreferences', $sArg);
                 }
                 break;
             case 'redirects':
                 if (in_array($sArg, self::$options['redirects'])) {
                     $sRedirects = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('redirects', $sArg);
                 }
                 break;
             case 'offset':
                 //ensure that $iOffset is a number
                 if (preg_match(self::$options['offset']['pattern'], $sArg)) {
                     $iOffset = $sArg == '' ? 0 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('offset', $sArg);
                 }
                 break;
             case 'count':
                 //ensure that $iCount is a number or no count limit;
                 if (preg_match(self::$options['count']['pattern'], $sArg)) {
                     $iCount = $sArg == '' ? NULL : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('count', $sArg);
                 }
                 break;
             case 'randomseed':
                 //ensure that $iRandomSeed is a number;
                 if (preg_match(self::$options['randomseed']['pattern'], $sArg)) {
                     $iRandomSeed = $sArg == '' ? NULL : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('randomseed', $sArg);
                 }
                 break;
             case 'randomcount':
                 //ensure that $iRandomCount is a number;
                 if (preg_match(self::$options['randomcount']['pattern'], $sArg)) {
                     $iRandomCount = $sArg == '' ? NULL : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('randomcount', $sArg);
                 }
                 break;
             case 'distinct':
                 if (in_array($sArg, self::$options['distinct'])) {
                     if ($sArg == 'strict') {
                         $sDistinctResultSet = 'strict';
                     } else {
                         if (self::argBoolean($sArg)) {
                             $sDistinctResultSet = 'true';
                         } else {
                             $sDistinctResultSet = 'false';
                         }
                     }
                 } else {
                     $output .= $logger->msgWrongParam('distinct', $sArg);
                 }
                 break;
             case 'categoriesminmax':
                 if (preg_match(self::$options['categoriesminmax']['pattern'], $sArg)) {
                     $aCatMinMax = $sArg == '' ? NULL : explode(',', $sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('categoriesminmax', $sArg);
                 }
                 break;
             case 'skipthispage':
                 if (in_array($sArg, self::$options['skipthispage'])) {
                     $bSkipThisPage = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('skipthispage', $sArg);
                 }
                 break;
             case 'articlecategory':
                 $sArticleCategory = $sArg;
                 break;
                 /**
                  * CONTENT PARAMETERS
                  */
             /**
              * CONTENT PARAMETERS
              */
             case 'addcategories':
                 if (in_array($sArg, self::$options['addcategories'])) {
                     $bAddCategories = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addcategories', $sArg);
                 }
                 break;
             case 'addeditdate':
                 if (in_array($sArg, self::$options['addeditdate'])) {
                     $bAddEditDate = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addeditdate', $sArg);
                 }
                 break;
             case 'addfirstcategorydate':
                 if (in_array($sArg, self::$options['addfirstcategorydate'])) {
                     $bAddFirstCategoryDate = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addfirstcategorydate', $sArg);
                 }
                 break;
             case 'addpagecounter':
                 if (in_array($sArg, self::$options['addpagecounter'])) {
                     $bAddPageCounter = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addpagecounter', $sArg);
                 }
                 break;
             case 'addpagesize':
                 if (in_array($sArg, self::$options['addpagesize'])) {
                     $bAddPageSize = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addpagesize', $sArg);
                 }
                 break;
             case 'addpagetoucheddate':
                 if (in_array($sArg, self::$options['addpagetoucheddate'])) {
                     $bAddPageTouchedDate = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addpagetoucheddate', $sArg);
                 }
                 break;
             case 'include':
             case 'includepage':
                 $bIncPage = $sArg !== '';
                 if ($bIncPage && $sArg != '*') {
                     $aSecLabels = explode(',', $sArg);
                 }
                 break;
             case 'includematch':
                 $aSecLabelsMatch = explode(',', $sArg);
                 break;
             case 'includenotmatch':
                 $aSecLabelsNotMatch = explode(',', $sArg);
                 break;
             case 'adduser':
                 if (in_array($sArg, self::$options['adduser'])) {
                     $bAddUser = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('adduser', $sArg);
                 }
                 break;
             case 'addauthor':
                 if (in_array($sArg, self::$options['addauthor'])) {
                     $bAddAuthor = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addauthor', $sArg);
                 }
                 break;
             case 'addcontribution':
                 if (in_array($sArg, self::$options['addcontribution'])) {
                     $bAddContribution = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addcontribution', $sArg);
                 }
                 break;
             case 'addlasteditor':
                 if (in_array($sArg, self::$options['addlasteditor'])) {
                     $bAddLastEditor = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('addlasteditor', $sArg);
                 }
                 break;
                 /**
                  * ORDER PARAMETERS
                  */
             /**
              * ORDER PARAMETERS
              */
             case 'ordermethod':
                 $methods = explode(',', $sArg);
                 $breakaway = false;
                 foreach ($methods as $method) {
                     if (!in_array($method, self::$options['ordermethod'])) {
                         $output .= $logger->msgWrongParam('ordermethod', $method);
                         $breakaway = true;
                     }
                 }
                 if (!$breakaway) {
                     $aOrderMethods = $methods;
                     $bConflictsWithOpenReferences = true;
                 }
                 break;
             case 'order':
                 if (in_array($sArg, self::$options['order'])) {
                     $sOrder = $sArg;
                 } else {
                     $output .= $logger->msgWrongParam('order', $sArg);
                 }
                 break;
             case 'ordercollation':
                 if ($sArg != '') {
                     $sOrderCollation = "COLLATE {$sArg}";
                 }
                 break;
                 /**
                  * FORMAT/HTML PARAMETERS
                  * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
                  */
             /**
              * FORMAT/HTML PARAMETERS
              * @todo allow addpagetoucheddate, addeditdate, adduser, addcategories to have effect with 'mode=category'
              */
             case 'columns':
                 //ensure that $iColumns is a number
                 if (preg_match(self::$options['columns']['pattern'], $sArg)) {
                     $iColumns = $sArg == '' ? 1 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('columns', $sArg);
                 }
                 break;
             case 'rows':
                 //ensure that $iRows is a number
                 if (preg_match(self::$options['rows']['pattern'], $sArg)) {
                     $iRows = $sArg == '' ? 1 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('rows', $sArg);
                 }
                 break;
             case 'rowsize':
                 //ensure that $iRowSize is a number
                 if (preg_match(self::$options['rowsize']['pattern'], $sArg)) {
                     $iRowSize = $sArg == '' ? 0 : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('rowsize', $sArg);
                 }
                 break;
             case 'rowcolformat':
                 $sRowColFormat = $sArg;
                 break;
             case 'userdateformat':
                 $sUserDateFormat = $sArg;
                 break;
             case 'headingmode':
                 if (in_array($sArg, self::$options['headingmode'])) {
                     $sHListMode = $sArg;
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('headingmode', $sArg);
                 }
                 break;
             case 'headingcount':
                 if (in_array($sArg, self::$options['headingcount'])) {
                     $bHeadingCount = self::argBoolean($sArg);
                     $bConflictsWithOpenReferences = true;
                 } else {
                     $output .= $logger->msgWrongParam('headingcount', $sArg);
                 }
                 break;
             case 'mode':
                 if (in_array($sArg, self::$options['mode'])) {
                     //'none' mode is implemented as a specific submode of 'inline' with <BR/> as inline text
                     if ($sArg == 'none') {
                         $sPageListMode = 'inline';
                         $sInlTxt = '<BR/>';
                     } else {
                         if ($sArg == 'userformat') {
                             // userformat resets inline text to empty string
                             $sInlTxt = '';
                             $sPageListMode = $sArg;
                         } else {
                             $sPageListMode = $sArg;
                         }
                     }
                 } else {
                     $output .= $logger->msgWrongParam('mode', $sArg);
                 }
                 break;
             case 'escapelinks':
                 if (in_array($sArg, self::$options['escapelinks'])) {
                     $bEscapeLinks = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('escapelinks', $sArg);
                 }
                 break;
             case 'inlinetext':
                 $sInlTxt = $sArg;
                 break;
             case 'format':
             case 'listseparators':
                 // parsing of wikitext will happen at the end of the output phase
                 // we replace '\n' in the input by linefeed because wiki syntax depends on linefeeds
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 $aListSeparators = explode(',', $sArg, 4);
                 // mode=userformat will be automatically assumed
                 $sPageListMode = 'userformat';
                 $sInlTxt = '';
                 break;
             case 'secseparators':
                 // we replace '\n' by newline to support wiki syntax within the section separators
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 $aSecSeparators = explode(',', $sArg);
                 break;
             case 'multisecseparators':
                 // we replace '\n' by newline to support wiki syntax within the section separators
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 $aMultiSecSeparators = explode(',', $sArg);
                 break;
             case 'table':
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sTable = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 break;
             case 'tablerow':
                 $sArg = str_replace('\\n', "\n", $sArg);
                 $sArg = str_replace("¶", "\n", $sArg);
                 // the paragraph delimiter is utf8-escaped
                 if (trim($sArg) == '') {
                     $aTableRow = array();
                 } else {
                     $aTableRow = explode(',', $sArg);
                 }
                 break;
             case 'dominantsection':
                 if (preg_match(self::$options['dominantsection']['pattern'], $sArg)) {
                     $iDominantSection = $sArg == '' ? NULL : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('dominantsection', $sArg);
                 }
                 break;
             case 'shownamespace':
                 if (in_array($sArg, self::$options['shownamespace'])) {
                     $bShowNamespace = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('shownamespace', $sArg);
                 }
                 break;
             case 'titlemaxlength':
                 //processed like 'count' param
                 if (preg_match(self::$options['titlemaxlength']['pattern'], $sArg)) {
                     $iTitleMaxLen = $sArg == '' ? NULL : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('titlemaxlength', $sArg);
                 }
                 break;
             case 'replaceintitle':
                 // we offer a possibility to replace some part of the title
                 $aReplaceInTitle = explode(',', $sArg, 2);
                 break;
             case 'includemaxlength':
                 //processed like 'count' param
                 if (preg_match(self::$options['includemaxlength']['pattern'], $sArg)) {
                     $iIncludeMaxLen = $sArg == '' ? NULL : intval($sArg);
                 } else {
                     // wrong value
                     $output .= $logger->msgWrongParam('includemaxlength', $sArg);
                 }
                 break;
             case 'listattr':
                 $sListHtmlAttr = $sArg;
                 break;
             case 'itemattr':
                 $sItemHtmlAttr = $sArg;
                 break;
             case 'hlistattr':
                 $sHListHtmlAttr = $sArg;
                 break;
             case 'hitemattr':
                 $sHItemHtmlAttr = $sArg;
                 break;
             case 'resultsheader':
                 $sResultsHeader = $sArg;
                 break;
             case 'resultsfooter':
                 $sResultsFooter = $sArg;
                 break;
             case 'noresultsheader':
                 $sNoResultsHeader = $sArg;
                 break;
             case 'noresultsfooter':
                 $sNoResultsFooter = $sArg;
                 break;
             case 'oneresultheader':
                 $sOneResultHeader = $sArg;
                 break;
             case 'oneresultfooter':
                 $sOneResultFooter = $sArg;
                 break;
                 /**
                  * DEBUG, RESET and CACHE PARAMETER
                  */
             /**
              * DEBUG, RESET and CACHE PARAMETER
              */
             case 'allowcachedresults':
                 if (in_array($sArg, self::$options['allowcachedresults'])) {
                     $bAllowCachedResults = self::argBoolean($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('allowcachedresults', $sArg);
                 }
                 break;
             case 'reset':
                 foreach (preg_split('/[;,]/', $sArg) as $arg) {
                     $arg = trim($arg);
                     if ($arg == '') {
                         continue;
                     }
                     if (!in_array($arg, self::$options['reset'])) {
                         $output .= $logger->msgWrongParam('reset', $arg);
                     } else {
                         if ($arg == 'links') {
                             $bReset[0] = true;
                         } else {
                             if ($arg == 'templates') {
                                 $bReset[1] = true;
                             } else {
                                 if ($arg == 'categories') {
                                     $bReset[2] = true;
                                 } else {
                                     if ($arg == 'images') {
                                         $bReset[3] = true;
                                     } else {
                                         if ($arg == 'all') {
                                             $bReset[0] = true;
                                             $bReset[1] = true;
                                             $bReset[2] = true;
                                             $bReset[3] = true;
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
                 break;
             case 'eliminate':
                 foreach (preg_split('/[;,]/', $sArg) as $arg) {
                     $arg = trim($arg);
                     if ($arg == '') {
                         continue;
                     }
                     if (!in_array($arg, self::$options['eliminate'])) {
                         $output .= $logger->msgWrongParam('eliminate', $arg);
                     } else {
                         if ($arg == 'links') {
                             $bReset[4] = true;
                         } else {
                             if ($arg == 'templates') {
                                 $bReset[5] = true;
                             } else {
                                 if ($arg == 'categories') {
                                     $bReset[6] = true;
                                 } else {
                                     if ($arg == 'images') {
                                         $bReset[7] = true;
                                     } else {
                                         if ($arg == 'all') {
                                             $bReset[4] = true;
                                             $bReset[5] = true;
                                             $bReset[6] = true;
                                             $bReset[7] = true;
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
                 break;
             case 'debug':
                 if (in_array($sArg, self::$options['debug'])) {
                     if ($iParam > 1) {
                         $output .= $logger->escapeMsg(DPL2_i18n::WARN_DEBUGPARAMNOTFIRST, $sArg);
                     }
                     $logger->iDebugLevel = intval($sArg);
                 } else {
                     $output .= $logger->msgWrongParam('debug', $sArg);
                 }
                 break;
             case 'suppresserrors':
                 if (in_array($sArg, self::$options['suppresserrors'])) {
                     $logger->setSuppressErrors('true');
                 } else {
                     $logger->setSuppressErrors('false');
                 }
                 break;
                 /**
                  * UNKNOWN PARAMETER
                  */
             /**
              * UNKNOWN PARAMETER
              */
             default:
                 $output .= $logger->escapeMsg(DPL2_i18n::WARN_UNKNOWNPARAM, $sType, implode(', ', array_keys(self::$options)));
         }
     }
     // debug level 5 puts nowiki tags around the output
     if ($logger->iDebugLevel == 5) {
         $logger->iDebugLevel = 2;
         $sResultsHeader = '<pre><nowiki>' . $sResultsHeader;
         $sResultsFooter .= '</nowiki></pre>';
     }
     // construct internal keys for TableRow according to the structure of "include"
     // this will be needed in the output phase
     self::updateTableRowKeys($aTableRow, $aSecLabels);
     // foreach ($aTableRow as $key => $val) $output .= "TableRow($key)=$val;<br>";
     $iIncludeCatCount = count($aIncludeCategories);
     $iTotalIncludeCatCount = count($aIncludeCategories, COUNT_RECURSIVE) - $iIncludeCatCount;
     $iExcludeCatCount = count($aExcludeCategories);
     $iTotalCatCount = $iTotalIncludeCatCount + $iExcludeCatCount;
     // disable parser cache
     if (!$bAllowCachedResults) {
         $parser->disableCache();
     }
     if ($calledInMode == 'tag') {
         // in tag mode 'eliminate' is the same as 'reset' for tpl,cat,img
         if ($bReset[5]) {
             $bReset[1] = true;
             $bReset[5] = false;
         }
         if ($bReset[6]) {
             $bReset[2] = true;
             $bReset[6] = false;
         }
         if ($bReset[7]) {
             $bReset[3] = true;
             $bReset[7] = false;
         }
     } else {
         if ($bReset[1]) {
             self::$createdLinks['resetTemplates'] = true;
         }
         if ($bReset[2]) {
             self::$createdLinks['resetCategories'] = true;
         }
         if ($bReset[3]) {
             self::$createdLinks['resetImages'] = true;
         }
     }
     if ($calledInMode == 'tag' && $bReset[0] || $calledInMode == 'func') {
         if ($bReset[0]) {
             self::$createdLinks['resetLinks'] = true;
         }
         // register a hook to reset links which were produced during parsing DPL output
         global $wgHooks;
         if (!isset($wgHooks['ParserAfterTidy']) || !(in_array(__CLASS__ . '::endReset', $wgHooks['ParserAfterTidy']) || in_array(array(__CLASS__, 'endReset'), $wgHooks['ParserAfterTidy']))) {
             // changed back to globals, gs
             //$wgHooks['ParserAfterTidy'][]   = __CLASS__ . '::endReset';
             $wgHooks['ParserAfterTidy'][] = __CLASS__ . '__endReset';
         }
     }
     // ###### CHECKS ON PARAMETERS ######
     // too many categories!!
     if ($iTotalCatCount > self::$maxCategoryCount && !self::$allowUnlimitedCategories) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_TOOMANYCATS, self::$maxCategoryCount);
     }
     // too few categories!!
     if ($iTotalCatCount < self::$minCategoryCount) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_TOOFEWCATS, self::$minCategoryCount);
     }
     // no selection criteria!! Warn only if no debug level is set
     if ($iTotalCatCount == 0 && $bSelectionCriteriaFound == false) {
         if ($logger->iDebugLevel >= 1) {
             return $output;
         } else {
             return $output . $logger->escapeMsg(DPL2_i18n::FATAL_NOSELECTION);
         }
     }
     // ordermethod=sortkey requires ordermethod=category
     // delayed to the construction of the SQL query, see near line 2211, gs
     //if (in_array('sortkey',$aOrderMethods) && ! in_array('category',$aOrderMethods)) $aOrderMethods[] = 'category';
     // no included categories but ordermethod=categoryadd or addfirstcategorydate=true!!
     if ($iTotalIncludeCatCount == 0 && ($aOrderMethods[0] == 'categoryadd' || $bAddFirstCategoryDate == true)) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_CATDATEBUTNOINCLUDEDCATS);
     }
     // more than one included category but ordermethod=categoryadd or addfirstcategorydate=true!!
     // we ALLOW this parameter combination, risking ambiguous results
     //if ($iTotalIncludeCatCount > 1 && ($aOrderMethods[0] == 'categoryadd' || $bAddFirstCategoryDate == true) )
     //	return $output . $logger->escapeMsg(DPL2_i18n::FATAL_CATDATEBUTMORETHAN1CAT);
     // no more than one type of date at a time!!
     if ($bAddPageTouchedDate + $bAddFirstCategoryDate + $bAddEditDate > 1) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_MORETHAN1TYPEOFDATE);
     }
     // the dominant section must be one of the sections mentioned in includepage
     if ($iDominantSection > 0 && count($aSecLabels) < $iDominantSection) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_DOMINANTSECTIONRANGE, count($aSecLabels));
     }
     // category-style output requested with not compatible order method
     if ($sPageListMode == 'category' && !array_intersect($aOrderMethods, array('sortkey', 'title', 'titlewithoutnamespace'))) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_WRONGORDERMETHOD, 'mode=category', 'sortkey | title | titlewithoutnamespace');
     }
     // addpagetoucheddate=true with unappropriate order methods
     if ($bAddPageTouchedDate && !array_intersect($aOrderMethods, array('pagetouched', 'title'))) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_WRONGORDERMETHOD, 'addpagetoucheddate=true', 'pagetouched | title');
     }
     // addeditdate=true but not (ordermethod=...,firstedit or ordermethod=...,lastedit)
     //firstedit (resp. lastedit) -> add date of first (resp. last) revision
     if ($bAddEditDate && !array_intersect($aOrderMethods, array('firstedit', 'lastedit'))) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_WRONGORDERMETHOD, 'addeditdate=true', 'firstedit | lastedit');
     }
     // adduser=true but not (ordermethod=...,firstedit or ordermethod=...,lastedit)
     /**
      * @todo allow to add user for other order methods.
      * The fact is a page may be edited by multiple users. Which user(s) should we show? all? the first or the last one?
      * Ideally, we could use values such as 'all', 'first' or 'last' for the adduser parameter.
      */
     if ($bAddUser && !array_intersect($aOrderMethods, array('firstedit', 'lastedit'))) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_WRONGORDERMETHOD, 'adduser=true', 'firstedit | lastedit');
     }
     if (isset($sMinorEdits) && !array_intersect($aOrderMethods, array('firstedit', 'lastedit'))) {
         return $output . $logger->escapeMsg(DPL2_i18n::FATAL_WRONGORDERMETHOD, 'minoredits', 'firstedit | lastedit');
     }
     /**
      * If we include the Uncategorized, we need the 'dpl_clview': VIEW of the categorylinks table where we have cl_to='' (empty string) for all uncategorized pages. This VIEW must have been created by the administrator of the mediawiki DB at installation. See the documentation.
      */
     $sDplClView = '';
     if ($bIncludeUncat) {
         $sDplClView = $dbr->tableName('dpl_clview');
         // If the view is not there, we can't perform logical operations on the Uncategorized.
         if (!$dbr->tableExists('dpl_clview')) {
             $sSqlCreate_dpl_clview = 'CREATE VIEW ' . $sDplClView . " AS SELECT IFNULL(cl_from, page_id) AS cl_from, IFNULL(cl_to, '') AS cl_to, cl_sortkey FROM " . $sPageTable . ' LEFT OUTER JOIN ' . $sCategorylinksTable . ' ON ' . $sPageTable . '.page_id=cl_from';
             $output .= $logger->escapeMsg(DPL2_i18n::FATAL_NOCLVIEW, $sDplClView, $sSqlCreate_dpl_clview);
             return $output;
         }
     }
     //add*** parameters have no effect with 'mode=category' (only namespace/title can be viewed in this mode)
     if ($sPageListMode == 'category' && ($bAddCategories || $bAddEditDate || $bAddFirstCategoryDate || $bAddPageTouchedDate || $bIncPage || $bAddUser || $bAddAuthor || $bAddContribution || $bAddLastEditor)) {
         $output .= $logger->escapeMsg(DPL2_i18n::WARN_CATOUTPUTBUTWRONGPARAMS);
     }
     //headingmode has effects with ordermethod on multiple components only
     if ($sHListMode != 'none' && count($aOrderMethods) < 2) {
         $output .= $logger->escapeMsg(DPL2_i18n::WARN_HEADINGBUTSIMPLEORDERMETHOD, $sHListMode, 'none');
         $sHListMode = 'none';
     }
     // openreferences is incompatible with many other options
     if ($acceptOpenReferences && $bConflictsWithOpenReferences) {
         $output .= $logger->escapeMsg(DPL2_i18n::FATAL_OPENREFERENCES);
         $acceptOpenReferences = false;
     }
     // justify limits;
     if (isset($iCount)) {
         if ($iCount > self::$maxResultCount) {
             $iCount = self::$maxResultCount;
         }
     } else {
         if (self::$allowUnlimitedResults) {
             $iCount = 99999999;
         } else {
             $iCount = self::$maxResultCount;
         }
     }
     // if 'table' parameter is set: derive values for listseparators, secseparators and multisecseparators
     $defaultTemplateSuffix = '.default';
     if ($sTable != '') {
         $defaultTemplateSuffix = '';
         $sPageListMode = 'userformat';
         $sInlTxt = '';
         $withHLink = "[[%PAGE%|%TITLE%]]\n|";
         foreach (explode(',', $sTable) as $tabnr => $tab) {
             if ($tabnr == 0) {
                 if ($tab == '') {
                     $tab = 'class=wikitable';
                 }
                 $aListSeparators[0] = '{|' . $tab;
             } else {
                 if ($tabnr == 1 && $tab == '-') {
                     $withHLink = '';
                     continue;
                 }
                 if ($tabnr == 1 && $tab == '') {
                     $tab = 'Article';
                 }
                 $aListSeparators[0] .= "\n!{$tab}";
             }
         }
         $aListSeparators[1] = '';
         // the user may have specified the third parameter of 'format' to add meta attributes of articles to the table
         if (!array_key_exists(2, $aListSeparators)) {
             $aListSeparators[2] = '';
         }
         $aListSeparators[3] = "\n|}";
         for ($i = 0; $i < count($aSecLabels); $i++) {
             if ($i == 0) {
                 $aSecSeparators[0] = "\n|-\n|" . $withHLink;
                 //."\n";
                 $aSecSeparators[1] = '';
                 $aMultiSecSeparators[0] = "\n|-\n|" . $withHLink;
                 // ."\n";
             } else {
                 $aSecSeparators[2 * $i] = "\n|";
                 // ."\n";
                 $aSecSeparators[2 * $i + 1] = '';
                 if ($aSecLabels[$i][0] == '#') {
                     $aMultiSecSeparators[$i] = "\n----\n";
                 } else {
                     $aMultiSecSeparators[$i] = "<br/>\n";
                 }
             }
         }
     }
     // ###### BUILD SQL QUERY ######
     $sSqlPage_counter = '';
     $sSqlPage_size = '';
     $sSqlPage_touched = '';
     if ($sDistinctResultSet == 'false') {
         $sSqlDistinct = '';
     } else {
         $sSqlDistinct = 'DISTINCT';
     }
     $sSqlGroupBy = '';
     if ($sDistinctResultSet == 'strict' && count($aLinksTo) + count($aNotLinksTo) + count($aLinksFrom) + count($aNotLinksFrom) > 0) {
         $sSqlGroupBy = 'page_title';
     }
     $sSqlSortkey = '';
     $sSqlCl_to = '';
     $sSqlCats = '';
     $sSqlCl_timestamp = '';
     $sSqlClHeadTable = '';
     $sSqlCond_page_cl_head = '';
     $sSqlClTableForGC = '';
     $sSqlCond_page_cl_gc = '';
     $sSqlRCTable = '';
     // recent changes
     $sRCTable = $dbr->tableName('recentchanges');
     $sRevisionTable = $dbr->tableName('revision');
     $sSqlRevisionTable = '';
     $sSqlRev_timestamp = '';
     $sSqlRev_id = '';
     $sSqlRev_user = '';
     $sSqlCond_page_rev = '';
     $sPageLinksTable = $dbr->tableName('pagelinks');
     $sTemplateLinksTable = $dbr->tableName('templatelinks');
     $sSqlPageLinksTable = '';
     $sSqlCond_page_pl = '';
     $sSqlCond_MaxCat = '';
     $sSqlWhere = ' WHERE 1=1 ';
     $sSqlSelPage = '';
     // initial page for selection
     // normally we create a result of normal pages, but when goal=categories is set, we create a list of categories
     // as this conflicts with some options we need to avoid producing incoorect SQl code
     $bGoalIsPages = true;
     if ($sGoal == 'categories') {
         $aOrderMethods = explode(',', '');
         $bGoalIsPages = false;
     }
     foreach ($aOrderMethods as $sOrderMethod) {
         switch ($sOrderMethod) {
             case 'category':
                 $sSqlCl_to = "cl_head.cl_to, ";
                 // Gives category headings in the result
                 $sSqlClHeadTable = (in_array('', $aCatHeadings) || in_array('', $aCatNotHeadings) ? $sDplClView : $sCategorylinksTable) . ' AS cl_head';
                 // use dpl_clview if Uncategorized in headings
                 $sSqlCond_page_cl_head = 'page_id=cl_head.cl_from';
                 if (!empty($aCatHeadings)) {
                     $sSqlWhere .= " AND cl_head.cl_to IN (" . $dbr->makeList($aCatHeadings) . ")";
                 }
                 if (!empty($aCatNotHeadings)) {
                     $sSqlWhere .= " AND NOT (cl_head.cl_to IN (" . $dbr->makeList($aCatNotHeadings) . "))";
                 }
                 break;
             case 'firstedit':
                 $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
                 $sSqlRev_timestamp = ', rev_timestamp';
                 $sSqlCond_page_rev = ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MIN(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page )';
                 break;
             case 'lastedit':
                 $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
                 $sSqlRev_timestamp = ', rev_timestamp';
                 $sSqlCond_page_rev = ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MAX(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page )';
                 break;
             case 'sortkey':
                 // We need the namespaces with strictly positive indices (DPL2 allowed namespaces, except the first one: Main).
                 $aStrictNs = array_slice(self::$allowedNamespaces, 1, count(self::$allowedNamespaces), true);
                 // map ns index to name
                 $sSqlNsIdToText = 'CASE ' . $sPageTable . '.page_namespace';
                 foreach ($aStrictNs as $iNs => $sNs) {
                     $sSqlNsIdToText .= ' WHEN ' . intval($iNs) . " THEN " . $dbr->addQuotes($sNs);
                 }
                 $sSqlNsIdToText .= ' END';
                 // If cl_sortkey is null (uncategorized page), generate a sortkey in the usual way (full page name, underscores replaced with spaces).
                 // UTF-8 created problems with non-utf-8 MySQL databases
                 //see line 2011 (order method sortkey requires category
                 if (in_array('category', $aOrderMethods)) {
                     $sSqlSortkey = ", IFNULL(cl_head.cl_sortkey, REPLACE(REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' '),'♣','⣣')) " . $sOrderCollation . " as sortkey";
                 } else {
                     $sSqlSortkey = ", IFNULL(cl0.cl_sortkey, REPLACE(REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' '),'♣','⣣')) " . $sOrderCollation . " as sortkey";
                 }
                 break;
             case 'titlewithoutnamespace':
                 $sSqlSortkey = ", REPLACE(page_title,'♣','⣣') " . $sOrderCollation . " as sortkey";
                 break;
             case 'pagesel':
                 $sSqlSortkey = ", CONCAT(pl.pl_namespace,pl.pl_title) " . $sOrderCollation . " as sortkey";
                 break;
             case 'title':
                 $aStrictNs = array_slice(self::$allowedNamespaces, 1, count(self::$allowedNamespaces), true);
                 // map ns index to name
                 if ($acceptOpenReferences) {
                     $sSqlNsIdToText = 'CASE pl_namespace';
                     foreach ($aStrictNs as $iNs => $sNs) {
                         $sSqlNsIdToText .= ' WHEN ' . intval($iNs) . " THEN " . $dbr->addQuotes($sNs);
                     }
                     $sSqlNsIdToText .= ' END';
                     $sSqlSortkey = ", REPLACE(REPLACE(CONCAT( IF(pl_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), pl_title), '_', ' '),'♣','⣣') " . $sOrderCollation . " as sortkey";
                 } else {
                     $sSqlNsIdToText = 'CASE ' . $sPageTable . '.page_namespace';
                     foreach ($aStrictNs as $iNs => $sNs) {
                         $sSqlNsIdToText .= ' WHEN ' . intval($iNs) . " THEN " . $dbr->addQuotes($sNs);
                     }
                     $sSqlNsIdToText .= ' END';
                     // Generate sortkey like for category links. UTF-8 created problems with non-utf-8 MySQL databases
                     $sSqlSortkey = ", REPLACE(REPLACE(CONCAT( IF(" . $sPageTable . ".page_namespace=0, '', CONCAT(" . $sSqlNsIdToText . ", ':')), " . $sPageTable . ".page_title), '_', ' '),'♣','⣣') " . $sOrderCollation . " as sortkey";
                 }
                 break;
             case 'user':
                 $sSqlRevisionTable = $sRevisionTable . ', ';
                 $sSqlRev_user = '******';
                 break;
         }
     }
     // linksto
     if (count($aLinksTo) > 0) {
         $sSqlPageLinksTable .= $sPageLinksTable . ' as pl, ';
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id=pl.pl_from AND (';
         $sSqlSelPage = ', pl.pl_title as sel_title, pl.pl_namespace as sel_ns';
         $n = 0;
         foreach ($aLinksTo as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             $sSqlCond_page_pl .= '(pl.pl_namespace=' . intval($link->getNamespace());
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= " AND UPPER(pl.pl_title)=UPPER(" . $dbr->addQuotes($link->getDbKey()) . '))';
             } else {
                 $sSqlCond_page_pl .= " AND pl.pl_title=" . $dbr->addQuotes($link->getDbKey()) . ')';
             }
             $n++;
         }
         $sSqlCond_page_pl .= ')';
     }
     // notlinksto
     if (count($aNotLinksTo) > 0) {
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id not in (select ' . $sPageLinksTable . '.pl_from from ' . $sPageLinksTable . ' where (';
         $n = 0;
         foreach ($aNotLinksTo as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             $sSqlCond_page_pl .= '(' . $sPageLinksTable . '.pl_namespace=' . intval($link->getNamespace());
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= ' AND UPPER(' . $sPageLinksTable . '.pl_title)=UPPER(' . $dbr->addQuotes($link->getDbKey()) . '))';
             } else {
                 $sSqlCond_page_pl .= ' AND       ' . $sPageLinksTable . '.pl_title=' . $dbr->addQuotes($link->getDbKey()) . ')';
             }
             $n++;
         }
         $sSqlCond_page_pl .= ') )';
     }
     // linksfrom
     if (count($aLinksFrom) > 0) {
         if ($acceptOpenReferences) {
             $sSqlCond_page_pl .= ' AND (';
             $n = 0;
             foreach ($aLinksFrom as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_pl .= ' OR ';
                 }
                 $sSqlCond_page_pl .= '(pl_from=' . $link->getArticleID() . ')';
                 $n++;
             }
             $sSqlCond_page_pl .= ')';
         } else {
             $sSqlPageLinksTable .= $sPageLinksTable . ' as plf, ' . $sPageTable . 'as pagesrc, ';
             $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_namespace = plf.pl_namespace AND ' . $sPageTable . '.page_title = plf.pl_title  AND pagesrc.page_id=plf.pl_from AND (';
             $sSqlSelPage = ', pagesrc.page_title as sel_title, pagesrc.page_namespace as sel_ns';
             $n = 0;
             foreach ($aLinksFrom as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_pl .= ' OR ';
                 }
                 $sSqlCond_page_pl .= '(plf.pl_from=' . $link->getArticleID() . ')';
                 $n++;
             }
             $sSqlCond_page_pl .= ')';
         }
     }
     // notlinksfrom
     if (count($aNotLinksFrom) > 0) {
         if ($acceptOpenReferences) {
             $sSqlCond_page_pl .= ' AND (';
             $n = 0;
             foreach ($aNotLinksFrom as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_pl .= ' AND ';
                 }
                 $sSqlCond_page_pl .= 'pl_from <> ' . $link->getArticleID() . ' ';
                 $n++;
             }
             $sSqlCond_page_pl .= ')';
         } else {
             $sSqlCond_page_pl .= ' AND CONCAT(page_namespace,page_title) not in (select CONCAT(' . $sPageLinksTable . '.pl_namespace,' . $sPageLinksTable . '.pl_title) from ' . $sPageLinksTable . ' where (';
             $n = 0;
             foreach ($aNotLinksFrom as $link) {
                 if ($n > 0) {
                     $sSqlCond_page_pl .= ' OR ';
                 }
                 $sSqlCond_page_pl .= $sPageLinksTable . '.pl_from=' . $link->getArticleID() . ' ';
                 $n++;
             }
             $sSqlCond_page_pl .= '))';
         }
     }
     // uses
     if (count($aUses) > 0) {
         $sSqlPageLinksTable .= ' ' . $sTemplateLinksTable . ' as tl, ';
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id=tl.tl_from  AND (';
         $n = 0;
         foreach ($aUses as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             $sSqlCond_page_pl .= '(tl.tl_namespace=' . intval($link->getNamespace());
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= " AND UPPER(tl.tl_title)=UPPER(" . $dbr->addQuotes($link->getDbKey()) . '))';
             } else {
                 $sSqlCond_page_pl .= " AND       tl.tl_title=" . $dbr->addQuotes($link->getDbKey()) . ')';
             }
             $n++;
         }
         $sSqlCond_page_pl .= ')';
     }
     // notuses
     if (count($aNotUses) > 0) {
         $sSqlCond_page_pl .= ' AND ' . $sPageTable . '.page_id not in (select ' . $sTemplateLinksTable . '.tl_from from ' . $sTemplateLinksTable . ' where (';
         $n = 0;
         foreach ($aNotUses as $link) {
             if ($n > 0) {
                 $sSqlCond_page_pl .= ' OR ';
             }
             $sSqlCond_page_pl .= '(' . $sTemplateLinksTable . '.tl_namespace=' . intval($link->getNamespace());
             if ($bIgnoreCase) {
                 $sSqlCond_page_pl .= ' AND UPPER(' . $sTemplateLinksTable . '.tl_title)=UPPER(' . $dbr->addQuotes($link->getDbKey()) . '))';
             } else {
                 $sSqlCond_page_pl .= ' AND ' . $sTemplateLinksTable . '.tl_title=' . $dbr->addQuotes($link->getDbKey()) . ')';
             }
             $n++;
         }
         $sSqlCond_page_pl .= ') )';
     }
     // recent changes  =============================
     if ($bAddContribution) {
         $sSqlRCTable = $sRCTable . ' AS rc, ';
         $sSqlSelPage .= ', SUM( ABS( rc.rc_new_len - rc.rc_old_len ) ) AS contribution, rc.rc_user_text as contributor';
         $sSqlWhere .= ' AND page.page_id=rc.rc_cur_id';
         if ($sSqlGroupBy != '') {
             $sSqlGroupBy .= ', ';
         }
         $sSqlGroupBy .= 'rc.rc_cur_id';
     }
     // Revisions ==================================
     if ($sCreatedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sCreatedBy) . ' = (select rev_user_text from ' . $sRevisionTable . ' where ' . $sRevisionTable . '.rev_page=page_id order by ' . $sRevisionTable . '.rev_timestamp ASC limit 1)';
     }
     if ($sNotCreatedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sNotCreatedBy) . ' != (select rev_user_text from ' . $sRevisionTable . ' where ' . $sRevisionTable . '.rev_page=page_id order by ' . $sRevisionTable . '.rev_timestamp ASC limit 1)';
     }
     if ($sModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sModifiedBy) . ' in (select rev_user_text from ' . $sRevisionTable . ' where ' . $sRevisionTable . '.rev_page=page_id)';
     }
     if ($sNotModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sNotModifiedBy) . ' not in (select rev_user_text from ' . $sRevisionTable . ' where ' . $sRevisionTable . '.rev_page=page_id)';
     }
     if ($sLastModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sLastModifiedBy) . ' = (select rev_user_text from ' . $sRevisionTable . ' where ' . $sRevisionTable . '.rev_page=page_id order by ' . $sRevisionTable . '.rev_timestamp DESC limit 1)';
     }
     if ($sNotLastModifiedBy != "") {
         $sSqlCond_page_rev .= ' AND ' . $dbr->addQuotes($sNotLastModifiedBy) . ' != (select rev_user_text from ' . $sRevisionTable . ' where ' . $sRevisionTable . '.rev_page=page_id order by ' . $sRevisionTable . '.rev_timestamp DESC limit 1)';
     }
     if ($bAddAuthor && $sSqlRevisionTable == '') {
         $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
         $sSqlCond_page_rev = ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MIN(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page )';
     }
     if ($bAddLastEditor && $sSqlRevisionTable == '') {
         $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
         $sSqlCond_page_rev = ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MAX(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page )';
     }
     if ($sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince != '') {
         // later during output we are going to create html links to the revisions, so we must enable RawHtml
         // wiki syntax does not support links to revisions as far as I know -- gs
         global $wgRawHtml;
         $wgRawHtml = true;
         $sSqlRevisionTable = $sRevisionTable . ' AS rev, ';
         $sSqlRev_timestamp = ', rev_timestamp';
         $sSqlRev_id = ', rev_id';
         if ($sLastRevisionBefore != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MAX(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page AND rev_aux.rev_timestamp < ' . $sLastRevisionBefore . ')';
         }
         if ($sAllRevisionsBefore != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp < ' . $sAllRevisionsBefore;
         }
         if ($sFirstRevisionSince != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp=( SELECT MIN(rev_aux.rev_timestamp) FROM ' . $sRevisionTable . ' AS rev_aux WHERE rev_aux.rev_page=rev.rev_page AND rev_aux.rev_timestamp >= ' . $sFirstRevisionSince . ')';
         }
         if ($sAllRevisionsSince != '') {
             $sSqlCond_page_rev .= ' AND ' . $sPageTable . '.page_id=rev.rev_page AND rev.rev_timestamp >= ' . $sAllRevisionsSince;
         }
     }
     if (isset($aCatMinMax[0]) && $aCatMinMax[0] != '') {
         $sSqlCond_MaxCat .= ' AND ' . $aCatMinMax[0] . ' <= (select count(*) from ' . $sCategorylinksTable . ' where ' . $sCategorylinksTable . '.cl_from=page_id)';
     }
     if (isset($aCatMinMax[1]) && $aCatMinMax[1] != '') {
         $sSqlCond_MaxCat .= ' AND ' . $aCatMinMax[1] . ' >= (select count(*) from ' . $sCategorylinksTable . ' where ' . $sCategorylinksTable . '.cl_from=page_id)';
     }
     if ($bAddFirstCategoryDate) {
         //format cl_timestamp field (type timestamp) to string in same format as rev_timestamp field
         //to make it compatible with $wgLang->date() function used in function DPL2OutputListStyle() to show "firstcategorydate"
         $sSqlCl_timestamp = ", DATE_FORMAT(cl0.cl_timestamp, '%Y%m%d%H%i%s') AS cl_timestamp";
     }
     if ($bAddPageCounter) {
         $sSqlPage_counter = ", {$sPageTable}.page_counter as page_counter";
     }
     if ($bAddPageSize) {
         $sSqlPage_size = ", {$sPageTable}.page_len as page_len";
     }
     if ($bAddPageTouchedDate) {
         $sSqlPage_touched = ", {$sPageTable}.page_touched as page_touched";
     }
     if ($bAddUser || $bAddAuthor || $bAddLastEditor || $sSqlRevisionTable != '') {
         $sSqlRev_user = '******';
     }
     if ($bAddCategories) {
         $sSqlCats = ", GROUP_CONCAT(DISTINCT cl_gc.cl_to ORDER BY cl_gc.cl_to ASC SEPARATOR ' | ') AS cats";
         // Gives list of all categories linked from each article, if any.
         $sSqlClTableForGC = $sCategorylinksTable . ' AS cl_gc';
         // Categorylinks table used by the Group Concat (GC) function above
         $sSqlCond_page_cl_gc = 'page_id=cl_gc.cl_from';
         if ($sSqlGroupBy != '') {
             $sSqlGroupBy .= ', ';
         }
         $sSqlGroupBy .= $sSqlCl_to . $sPageTable . '.page_id';
     }
     // SELECT ... FROM
     if ($acceptOpenReferences) {
         $sSqlSelectFrom = "SELECT {$sSqlDistinct} " . $sSqlCl_to . 'pl_namespace, pl_title' . $sSqlSelPage . $sSqlSortkey . ' FROM ' . $sPageLinksTable;
     } else {
         $sSqlSelectFrom = "SELECT {$sSqlDistinct} " . $sSqlCl_to . $sPageTable . '.page_namespace as page_namespace,' . $sPageTable . '.page_title as page_title' . $sSqlSelPage . $sSqlSortkey . $sSqlPage_counter . $sSqlPage_size . $sSqlPage_touched . $sSqlRev_user . $sSqlRev_timestamp . $sSqlRev_id . $sSqlCats . $sSqlCl_timestamp . ' FROM ' . $sSqlRevisionTable . $sSqlRCTable . $sSqlPageLinksTable . $sPageTable;
     }
     // JOIN ...
     if ($sSqlClHeadTable != '' || $sSqlClTableForGC != '') {
         $b2tables = $sSqlClHeadTable != '' && $sSqlClTableForGC != '';
         $sSqlSelectFrom .= ' LEFT OUTER JOIN (' . $sSqlClHeadTable . ($b2tables ? ', ' : '') . $sSqlClTableForGC . ') ON (' . $sSqlCond_page_cl_head . ($b2tables ? ' AND ' : '') . $sSqlCond_page_cl_gc . ')';
     }
     // Include categories...
     $iClTable = 0;
     for ($i = 0; $i < $iIncludeCatCount; $i++) {
         // If we want the Uncategorized
         $sSqlSelectFrom .= ' INNER JOIN ' . (in_array('', $aIncludeCategories[$i]) ? $sDplClView : $sCategorylinksTable) . ' AS cl' . $iClTable . ' ON ' . $sPageTable . '.page_id=cl' . $iClTable . '.cl_from AND (cl' . $iClTable . '.cl_to' . $sCategoryComparisonMode . $dbr->addQuotes($aIncludeCategories[$i][0]);
         for ($j = 1; $j < count($aIncludeCategories[$i]); $j++) {
             $sSqlSelectFrom .= ' OR cl' . $iClTable . '.cl_to' . $sCategoryComparisonMode . $dbr->addQuotes($aIncludeCategories[$i][$j]);
         }
         $sSqlSelectFrom .= ') ';
         $iClTable++;
     }
     // Exclude categories...
     for ($i = 0; $i < $iExcludeCatCount; $i++) {
         $sSqlSelectFrom .= ' LEFT OUTER JOIN ' . $sCategorylinksTable . ' AS cl' . $iClTable . ' ON ' . $sPageTable . '.page_id=cl' . $iClTable . '.cl_from' . ' AND cl' . $iClTable . '.cl_to' . $sNotCategoryComparisonMode . $dbr->addQuotes($aExcludeCategories[$i]);
         $sSqlWhere .= ' AND cl' . $iClTable . '.cl_to IS NULL';
         $iClTable++;
     }
     // WHERE... (actually finish the WHERE clause we may have started if we excluded categories - see above)
     // Namespace IS ...
     if (!empty($aNamespaces)) {
         if ($acceptOpenReferences) {
             $sSqlWhere .= ' AND ' . $sPageTable . '.pl_namespace IN (' . $dbr->makeList($aNamespaces) . ')';
         } else {
             $sSqlWhere .= ' AND ' . $sPageTable . '.page_namespace IN (' . $dbr->makeList($aNamespaces) . ')';
         }
     }
     // Namespace IS NOT ...
     if (!empty($aExcludeNamespaces)) {
         if ($acceptOpenReferences) {
             $sSqlWhere .= ' AND ' . $sPageTable . '.pl_namespace NOT IN (' . $dbr->makeList($aExcludeNamespaces) . ')';
         } else {
             $sSqlWhere .= ' AND ' . $sPageTable . '.page_namespace NOT IN (' . $dbr->makeList($aExcludeNamespaces) . ')';
         }
     }
     // TitleIs
     if ($sTitleIs != '') {
         if ($bIgnoreCase) {
             $sSqlWhere .= ' AND UPPER(' . $sPageTable . '.page_title) = UPPER(' . $dbr->addQuotes($sTitleIs) . ')';
         } else {
             $sSqlWhere .= ' AND ' . $sPageTable . '.page_title = ' . $dbr->addQuotes($sTitleIs);
         }
     }
     // TitleMatch ...
     if (count($aTitleMatch) > 0) {
         $sSqlWhere .= ' AND (';
         $n = 0;
         foreach ($aTitleMatch as $link) {
             if ($n > 0) {
                 $sSqlWhere .= ' OR ';
             }
             if ($acceptOpenReferences) {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'UPPER(pl_title)' . $sTitleMatchMode . 'UPPER(' . $dbr->addQuotes($link) . ')';
                 } else {
                     $sSqlWhere .= 'pl_title' . $sTitleMatchMode . $dbr->addQuotes($link);
                 }
             } else {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'UPPER(' . $sPageTable . '.page_title)' . $sTitleMatchMode . 'UPPER(' . $dbr->addQuotes($link) . ')';
                 } else {
                     $sSqlWhere .= $sPageTable . '.page_title' . $sTitleMatchMode . $dbr->addQuotes($link);
                 }
             }
             $n++;
         }
         $sSqlWhere .= ')';
     }
     // NotTitleMatch ...
     if (count($aNotTitleMatch) > 0) {
         $sSqlWhere .= ' AND NOT (';
         $n = 0;
         foreach ($aNotTitleMatch as $link) {
             if ($n > 0) {
                 $sSqlWhere .= ' OR ';
             }
             if ($acceptOpenReferences) {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'UPPER(pl_title)' . $sNotTitleMatchMode . 'UPPER(' . $dbr->addQuotes($link) . ')';
                 } else {
                     $sSqlWhere .= 'pl_title' . $sNotTitleMatchMode . $dbr->addQuotes($link);
                 }
             } else {
                 if ($bIgnoreCase) {
                     $sSqlWhere .= 'UPPER(' . $sPageTable . '.page_title)' . $sNotTitleMatchMode . 'UPPER(' . $dbr->addQuotes($link) . ')';
                 } else {
                     $sSqlWhere .= $sPageTable . '.page_title' . $sNotTitleMatchMode . $dbr->addQuotes($link);
                 }
             }
             $n++;
         }
         $sSqlWhere .= ')';
     }
     // rev_minor_edit IS
     if (isset($sMinorEdits) && $sMinorEdits == 'exclude') {
         $sSqlWhere .= ' AND rev_minor_edit=0';
     }
     // page_is_redirect IS ...
     if (!$acceptOpenReferences) {
         switch ($sRedirects) {
             case 'only':
                 $sSqlWhere .= ' AND ' . $sPageTable . '.page_is_redirect=1';
                 break;
             case 'exclude':
                 $sSqlWhere .= ' AND ' . $sPageTable . '.page_is_redirect=0';
                 break;
         }
     }
     // page_id=rev_page (if revision table required)
     $sSqlWhere .= $sSqlCond_page_rev;
     // count(all categories) <= max no of categories
     $sSqlWhere .= $sSqlCond_MaxCat;
     // page_id=pl.pl_from (if pagelinks table required)
     $sSqlWhere .= $sSqlCond_page_pl;
     if (isset($sArticleCategory) && $sArticleCategory !== null) {
         $sSqlWhere .= " AND {$sPageTable}.page_title IN (\n                select p2.page_title\n                from {$sPageTable} p2\n                inner join {$sCategorylinksTable} clstc ON (clstc.cl_from = p2.page_id AND clstc.cl_to = " . $dbr->addQuotes($sArticleCategory) . " )\n                where p2.page_namespace = 0\n                ) ";
     }
     // GROUP BY ...
     if ($sSqlGroupBy != '') {
         $sSqlWhere .= ' GROUP BY ' . $sSqlGroupBy . ' ';
     }
     // ORDER BY ...
     if ($aOrderMethods[0] != '') {
         $sSqlWhere .= ' ORDER BY ';
         foreach ($aOrderMethods as $i => $sOrderMethod) {
             if ($i > 0) {
                 $sSqlWhere .= ', ';
             }
             switch ($sOrderMethod) {
                 case 'category':
                     $sSqlWhere .= 'cl_head.cl_to';
                     break;
                 case 'categoryadd':
                     $sSqlWhere .= 'cl0.cl_timestamp';
                     break;
                 case 'counter':
                     $sSqlWhere .= 'page_counter';
                     break;
                 case 'size':
                     $sSqlWhere .= 'page_len';
                     break;
                 case 'firstedit':
                 case 'lastedit':
                     $sSqlWhere .= 'rev_timestamp';
                     break;
                 case 'pagetouched':
                     $sSqlWhere .= 'page_touched';
                     break;
                 case 'sortkey':
                 case 'title':
                 case 'pagesel':
                 case 'titlewithoutnamespace':
                     $sSqlWhere .= 'sortkey';
                     break;
                 case 'user':
                     // rev_user_text can discriminate anonymous users (e.g. based on IP), rev_user cannot (=' 0' for all)
                     $sSqlWhere .= 'rev_user_text';
                     break;
             }
         }
         if ($sOrder == 'descending') {
             $sSqlWhere .= ' DESC';
         } else {
             $sSqlWhere .= ' ASC';
         }
     }
     if ($sAllRevisionsSince != '' || $sAllRevisionsBefore != '') {
         $sSqlWhere .= ', rev_id DESC';
     }
     // LIMIT ....
     // we must switch off LIMITS when going for categories as output goal (due to mysql limitations)
     if (isset($iCount) && $sGoal != 'categories') {
         $sSqlWhere .= " LIMIT {$iOffset}, " . intval($iCount);
     }
     // when we go for a list of categories as result we transform the output of the normal query into a subquery
     // of a selection on the categorylinks
     if ($sGoal == 'categories') {
         $sSqlSelectFrom = 'select distinct cl3.cl_to from ' . $sCategorylinksTable . ' as cl3 where cl3.cl_from in ( ' . preg_replace('/SELECT DISTINCT .* FROM /', 'SELECT DISTINCT ' . $sPageTable . '.page_id FROM ', $sSqlSelectFrom);
         if ($sOrder == 'descending') {
             $sSqlWhere .= ' ) order by cl3.cl_to DESC';
         } else {
             $sSqlWhere .= ' ) order by cl3.cl_to ASC';
         }
     }
     // ###### PROCESS SQL QUERY ######
     if ($logger->iDebugLevel >= 3) {
         //DEBUG: output SQL query
         $output .= "DPL debug -- Query=<br>\n<tt>" . $sSqlSelectFrom . $sSqlWhere . "</tt>\n\n";
     }
     global $wgMemc;
     $__cacheKey = sha1($sSqlSelectFrom . $sSqlWhere);
     MessageCache::singleton()->lock($__cacheKey);
     $mem_key = wfMemcKey('dpl', 'query', $__cacheKey);
     $mem_key_counter = wfMemcKey('dpl', 'counter');
     $data = $wgMemc->get($mem_key);
     if (empty($data)) {
         try {
             $res = $dbr->query($sSqlSelectFrom . $sSqlWhere, "DPL");
         } catch (Exception $e) {
             $result = '';
             if (!$logger->getSuppressErrors()) {
                 $result = "The DPL extension (version " . self::VERSION . ") produced a SQL statement which lead to a Database error.<br>\n" . "The reason may be an internal error of DPL or an error which you made,<br>\n" . "especially when using DPL options like titleregexp.<br>\n" . "Query text is:<br>\n<tt>" . $sSqlSelectFrom . $sSqlWhere . "</tt>\n\n" . "Error message is:<br>\n<tt>" . $dbr->lastError() . "</tt>\n\n";
             }
             MessageCache::singleton()->unlock($__cacheKey);
             return $result;
         }
         if ($dbr->numRows($res) <= 0) {
             if ($sNoResultsHeader != '') {
                 $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $sNoResultsHeader));
             }
             if ($sNoResultsFooter != '') {
                 $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $sNoResultsFooter));
             }
             if ($sNoResultsHeader == '' && $sNoResultsFooter == '') {
                 $output .= $logger->escapeMsg(DPL2_i18n::WARN_NORESULTS);
             }
             $dbr->freeResult($res);
             MessageCache::singleton()->unlock($__cacheKey);
             return $output;
         }
         $sk =& RequestContext::getMain()->getSkin();
         // generate title for Special:Contributions (used if adduser=true)
         $sSpecContribs = '[[:Special:Contributions|Contributions]]';
         $aHeadings = array();
         // maps heading to count (# of pages under each heading)
         $aArticles = array();
         // pick some elements by random
         $pick[0] = true;
         if (isset($iRandomCount)) {
             $nResults = $dbr->numRows($res);
             if (isset($iRandomSeed)) {
                 mt_srand($iRandomSeed);
             } else {
                 mt_srand((double) microtime() * 10000000);
             }
             if ($iRandomCount > $nResults) {
                 $iRandomCount = $nResults;
             }
             $r = 0;
             while (true) {
                 $rnum = mt_rand(1, $nResults);
                 if (!isset($pick[$rnum])) {
                     $pick[$rnum] = true;
                     $r++;
                     if ($r >= $iRandomCount) {
                         break;
                     }
                 }
             }
         }
         $iArticle = 0;
         while ($row = $dbr->fetchObject($res)) {
             $iArticle++;
             // in random mode skip articles which were not chosen
             if (isset($iRandomCount) && !isset($pick[$iArticle])) {
                 continue;
             }
             if ($sGoal == 'categories') {
                 $pageNamespace = 14;
                 // CATEGORY
                 $pageTitle = $row->cl_to;
             } else {
                 if ($acceptOpenReferences) {
                     // existing PAGE TITLE
                     $pageNamespace = $row->pl_namespace;
                     $pageTitle = $row->pl_title;
                 } else {
                     // maybe non-existing title
                     $pageNamespace = $row->page_namespace;
                     $pageTitle = $row->page_title;
                 }
             }
             // if subpages are to be excluded: skip them
             if (!$bIncludeSubpages && !(strpos($pageTitle, '/') === false)) {
                 continue;
             }
             // maybe we will somewhen support namespace protections
             // do not allow access to protected Namespaces
             // if (count($wgNonincludableNamespaces)>0 && in_array($pageNamespace,$wgNonincludableNamespaces) ) continue;
             // we should produce an error message if debug >= 3
             $title = Title::makeTitle($pageNamespace, $pageTitle);
             if (!$title instanceof Title || !$wgTitle instanceof Title) {
                 continue;
             }
             // block recursion: avoid to show the page which contains the DPL statement as part of the result
             if ($bSkipThisPage && ($title->getNamespace() == $wgTitle->getNamespace() && $title->getText() == $wgTitle->getText())) {
                 // $output.= 'BLOCKED '.$wgTitle->getText().' DUE TO RECURSION'."\n";
                 continue;
             }
             $dplArticle = new DPL2Article($title, $pageNamespace);
             //PAGE LINK
             $sTitleText = $title->getText();
             if (is_array($aReplaceInTitle) && $aReplaceInTitle[0] != '') {
                 $sTitleText = preg_replace($aReplaceInTitle[0], !empty($aReplaceInTitle[1]) ? $aReplaceInTitle[1] : "", $sTitleText);
             }
             //chop off title if "too long"
             if (isset($iTitleMaxLen) && strlen($sTitleText) > $iTitleMaxLen) {
                 $sTitleText = substr($sTitleText, 0, $iTitleMaxLen) . '...';
             }
             if ($bShowNamespace) {
                 //Adapted from Title::getPrefixedText()
                 $sTitleText = $title->getPrefixedText($sTitleText);
             }
             if ($bEscapeLinks && ($pageNamespace == 14 || $pageNamespace == 6)) {
                 // links to categories or images need an additional ":"
                 $articleLink = '[[:' . $title->getPrefixedText() . '|' . $wgContLang->convert($sTitleText) . ']]';
             } else {
                 $articleLink = '[[' . $title->getPrefixedText() . '|' . $wgContLang->convert($sTitleText) . ']]';
             }
             $dplArticle->mLink = $articleLink;
             //get first char used for category-style output
             if (isset($row->sortkey)) {
                 $dplArticle->mStartChar = $wgContLang->convert($wgContLang->firstChar($row->sortkey));
             }
             //SHOW PAGE_COUNTER
             if (isset($row->page_counter)) {
                 $dplArticle->mCounter = $row->page_counter;
             }
             //SHOW PAGE_SIZE
             if (isset($row->page_len)) {
                 $dplArticle->mSize = $row->page_len;
             }
             //STORE initially selected PAGE
             if (count($aLinksTo) > 0 || count($aLinksFrom) > 0) {
                 if (!isset($row->sel_title)) {
                     $dplArticle->mSelTitle = 'unknown page';
                     $dplArticle->mSelNamespace = 0;
                 } else {
                     $dplArticle->mSelTitle = $row->sel_title;
                     $dplArticle->mSelNamespace = $row->sel_ns;
                 }
             }
             if ($bGoalIsPages) {
                 //REVISION SPECIFIED
                 if ($sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince != '') {
                     $dplArticle->mRevision = $row->rev_id;
                     $dplArticle->mUser = $row->rev_user_text;
                     $dplArticle->mDate = $row->rev_timestamp;
                 }
                 //SHOW "PAGE_TOUCHED" DATE, "FIRSTCATEGORYDATE" OR (FIRST/LAST) EDIT DATE
                 if ($bAddPageTouchedDate) {
                     $dplArticle->mDate = $row->page_touched;
                 } elseif ($bAddFirstCategoryDate) {
                     $dplArticle->mDate = $row->cl_timestamp;
                 } elseif ($bAddEditDate) {
                     $dplArticle->mDate = $row->rev_timestamp;
                 }
                 if ($dplArticle->mDate != '' && $sUserDateFormat != '') {
                     // we add one space for nicer formatting
                     $dplArticle->myDate = gmdate($sUserDateFormat, wfTimeStamp(TS_UNIX, $dplArticle->mDate)) . ' ';
                 }
                 // CONTRIBUTION, CONTRIBUTOR
                 if ($bAddContribution) {
                     $dplArticle->mContribution = $row->contribution;
                     $dplArticle->mContributor = $row->contributor;
                     $dplArticle->mContrib = substr('*****************', 0, round(log($row->contribution)));
                 }
                 //USER/AUTHOR(S)
                 // because we are going to do a recursive parse at the end of the output phase
                 // we have to generate wiki syntax for linking to a user�s homepage
                 if ($bAddUser || $bAddAuthor || $bAddLastEditor || $sLastRevisionBefore . $sAllRevisionsBefore . $sFirstRevisionSince . $sAllRevisionsSince != '') {
                     $dplArticle->mUserLink = '[[User:'******'|' . $row->rev_user_text . ']]';
                     $dplArticle->mUser = $row->rev_user_text;
                 }
                 //CATEGORY LINKS FROM CURRENT PAGE
                 if ($bAddCategories && $bGoalIsPages && $row->cats != '') {
                     $artCatNames = explode(' | ', $row->cats);
                     foreach ($artCatNames as $iArtCat => $artCatName) {
                         $dplArticle->mCategoryLinks[] = '[[:Category:' . $artCatName . '|' . str_replace('_', ' ', $artCatName) . ']]';
                         $dplArticle->mCategoryTexts[] = str_replace('_', ' ', $artCatName);
                     }
                 }
                 // PARENT HEADING (category of the page, editor (user) of the page, etc. Depends on ordermethod param)
                 if ($sHListMode != 'none') {
                     switch ($aOrderMethods[0]) {
                         case 'category':
                             //count one more page in this heading
                             $aHeadings[$row->cl_to] = isset($aHeadings[$row->cl_to]) ? $aHeadings[$row->cl_to] + 1 : 1;
                             if ($row->cl_to == '') {
                                 //uncategorized page (used if ordermethod=category,...)
                                 $dplArticle->mParentHLink = '[[:Special:Uncategorizedpages|' . wfMsg('uncategorizedpages') . ']]';
                             } else {
                                 $dplArticle->mParentHLink = '[[:Category:' . $row->cl_to . '|' . str_replace('_', ' ', $row->cl_to) . ']]';
                             }
                             break;
                         case 'user':
                             $aHeadings[$row->rev_user_text] = isset($aHeadings[$row->rev_user_text]) ? $aHeadings[$row->rev_user_text] + 1 : 1;
                             if ($row->rev_user == 0) {
                                 //anonymous user
                                 $dplArticle->mParentHLink = '[[User:'******'|' . $row->rev_user_text . ']]';
                             } else {
                                 $dplArticle->mParentHLink = '[[User:'******'|' . $row->rev_user_text . ']]';
                             }
                             break;
                     }
                 }
             }
             $aArticles[] = $dplArticle;
         }
         $dbr->freeResult($res);
         // ###### SHOW OUTPUT ######
         $listMode = new DPL2ListMode($sPageListMode, $aSecSeparators, $aMultiSecSeparators, $sInlTxt, $sListHtmlAttr, $sItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection);
         $hListMode = new DPL2ListMode($sHListMode, $aSecSeparators, $aMultiSecSeparators, '', $sHListHtmlAttr, $sHItemHtmlAttr, $aListSeparators, $iOffset, $iDominantSection);
         $dpl = new DPL2($aHeadings, $bHeadingCount, $iColumns, $iRows, $iRowSize, $sRowColFormat, $aArticles, $aOrderMethods[0], $hListMode, $listMode, $bEscapeLinks, $bIncPage, $iIncludeMaxLen, $aSecLabels, $aSecLabelsMatch, $aSecLabelsNotMatch, $parser, $logger, $aReplaceInTitle, $iTitleMaxLen, $defaultTemplateSuffix, $aTableRow);
         $dpl2result = $dpl->getText();
         $header = '';
         if ($sOneResultHeader != '' && $dpl->getRowCount() == 1) {
             $header = str_replace('%PAGES%', 1, $sOneResultHeader);
         } else {
             if ($dpl->getRowCount() == 0) {
                 if ($sNoResultsHeader != '') {
                     $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $sNoResultsHeader));
                 }
                 if ($sNoResultsFooter != '') {
                     $output .= str_replace('\\n', "\n", str_replace("¶", "\n", $sNoResultsFooter));
                 }
                 if ($sNoResultsHeader == '' && $sNoResultsFooter == '') {
                     $output .= $logger->escapeMsg(DPL2_i18n::WARN_NORESULTS);
                 }
             } else {
                 if ($sResultsHeader != '') {
                     $header = str_replace('%PAGES%', $dpl->getRowCount(), $sResultsHeader);
                 }
             }
         }
         $header = str_replace('\\n', "\n", str_replace("¶", "\n", $header));
         $footer = '';
         if ($sOneResultFooter != '' && $dpl->getRowCount() == 1) {
             $footer = str_replace('%PAGES%', 1, $sOneResultFooter);
         } else {
             if ($sResultsFooter != '') {
                 $footer = str_replace('%PAGES%', $dpl->getRowCount(), $sResultsFooter);
             }
         }
         $footer = str_replace('\\n', "\n", str_replace("¶", "\n", $footer));
         $output .= $header . $dpl2result . $footer;
         // The following requires an extra parser step which may consume some time
         // we parse the DPL output and save all referenced found in that output in a global list
         // in a final user exit after the whole document processing we eliminate all these links
         // we use a local parser to avoid interference with the main parser
         if ($bReset[4] || $bReset[5] || $bReset[6] || $bReset[7]) {
             // register a hook to reset links which were produced during parsing DPL output
             global $wgHooks;
             if (!isset($wgHooks['ParserAfterTidy']) || !(in_array(__CLASS__ . '::endEliminate', $wgHooks['ParserAfterTidy']) || in_array(array(__CLASS__, 'endEliminate'), $wgHooks['ParserAfterTidy']))) {
                 // changed back to globals, gs
                 // $wgHooks['ParserAfterTidy'][]   = __CLASS__ . '::endEliminate';
                 $wgHooks['ParserAfterTidy'][] = __CLASS__ . '__endEliminate';
             }
             $parserOutput = $localParser->parse($output, $parser->mTitle, $parser->mOptions);
         }
         if ($bReset[4]) {
             // LINKS
             // we trigger the mediawiki parser to find links, images, categories etc. which are contained in the DPL output
             // this allows us to remove these links from the link list later
             // If the article containing the DPL statement itself uses one of these links they will be thrown away!!
             foreach ($parserOutput->getLinks() as $link) {
                 foreach ($link as $key => $val) {
                     self::$createdLinks[0][$key] = $val;
                     // $output.= "storing link $val($key).";
                 }
             }
         }
         if ($bReset[5]) {
             // TEMPLATES
             foreach ($parserOutput->getTemplates() as $tpl) {
                 foreach ($tpl as $key => $val) {
                     self::$createdLinks[1][$key] = $val;
                     // $output.= "storing use of template $val($key).";
                 }
             }
         }
         if ($bReset[6]) {
             // CATEGORIES
             foreach ($parserOutput->mCategories as $catname => $catkey) {
                 self::$createdLinks[2][$catname] = $catname;
             }
         }
         if ($bReset[7]) {
             // IMAGES
             foreach ($parserOutput->mImages as $imgid => $dummy) {
                 self::$createdLinks[3][$imgid] = $imgid;
             }
         }
     } else {
         $wgMemc->incr($mem_key_counter, 1);
         $output = $mem_key;
     }
     MessageCache::singleton()->unlock($__cacheKey);
     return $output;
 }
	protected function languageCloud() {
		global $wgTranslateMessageNamespaces;

		$cache = wfGetCache( CACHE_ANYTHING );
		$cachekey = wfMemcKey( 'translate-supportedlanguages-language-cloud' );
		$data = $cache->get( $cachekey );
		if ( !$this->purge && is_array( $data ) ) {
			return $data;
		}

		$dbr = wfGetDB( DB_SLAVE );
		$tables = array( 'recentchanges' );
		$fields = array( 'substring_index(rc_title, \'/\', -1) as lang', 'count(*) as count' );
		$conds = array(
			'rc_title' . $dbr->buildLike( $dbr->anyString(), '/', $dbr->anyString() ),
			'rc_namespace' => $wgTranslateMessageNamespaces,
			'rc_timestamp > ' . $dbr->timestamp( TS_DB, wfTimeStamp( TS_UNIX ) - 60 * 60 * 24 * $this->period ),
		);
		$options = array( 'GROUP BY' => 'lang', 'HAVING' => 'count > 20' );

		$res = $dbr->select( $tables, $fields, $conds, __METHOD__, $options );

		$data = array();
		foreach ( $res as $row ) {
			$data[$row->lang] = $row->count;
		}

		$cache->set( $cachekey, $data, 3600 );
		return $data;
	}
	public function execute() {
		$articles = $this->data['articles'];
		$name = $this->data['name'];
		$csv_link = $this->data['csv_link'];
?>

<div id="">
<?php if( count($articles) > 0 ) { ?>
<h3>Articles in Selection <?php echo htmlentities( $name ); ?></h3> <small><a href="<?php echo htmlentities( $csv_link ); ?>">Export CSV</a></small>
	<table>
	<tr>
		<th style="width:150px">Article</th>
		<th style="width:150px">Added on</th>
		<th style="width:75px">Revision</th>
		<th style="width:300px">Actions</th>
	</tr>	
	<?php foreach( $articles as $article ) { ?>
	<tr class="article-row" data-namespace="<?php echo htmlentities( $article['s_namespace'] ); ?>" data-article="<?php echo htmlentities( $article['s_article'] ); ?>">
	<td><a href="<?php echo $article['title']->getLinkURL(); ?>"><?php echo htmlentities( $article['s_article'] ); ?></a></td>
	<td><?php echo wfTimeStamp( TS_ISO_8601, $article['s_timestamp'] );	?></td>
	<td><?php if($article['s_revision'] != null) { ?>
		<a href="<?php echo htmlentities( $article['title']->getLinkUrl( array( 'oldid' => $article['s_revision'] ) ) ); ?>" class="revision-link"><?php echo htmlentities( $article['s_revision'] ); ?></a>
		<?php } ?>
	</td>
	<td>
		<div class="item-actions">
		<div class="revision-input" style="display:none">
			<input type="text" class="revision-id" placeholder="Enter revision id" value="<?php echo htmlentities( $article['s_revision'] ); ?>" />
			(<a href="#" class="revision-save">Save</a> | <a href="#" class="revision-cancel">Cancel</a>)
		</div>
		<a href="#" class="change-revision">Set Revision</a> |
		<a href="#" class="delete-article">Delete</a>
		</div>
	</td>
	</tr>
	<?php } ?>
	</table>
<?php } else { ?> 
<p>No such selection found</p>
<?php } ?>
</div>

		<script type="text/javascript">
		// Should this be a RL module?
		$(document).ready(function() {
			$(".change-revision").click(function() {
				var parent = $(this).parents(".article-row");
				var input_box = $(".revision-input", parent);
				input_box.fadeToggle();
				return false;
			});
			$(".revision-save").click(function() {
				var parent = $(this).parents(".article-row");
				var ns = parent.attr("data-namespace"),
					article = parent.attr("data-article");
				var input = $("input.revision-id", parent);
				var input_box = $(".revision-input", parent);
				var revlink = $(".revision-link", parent);

				var revid = input.val();

				$.post('', {
					action: 'setrevision',
					namespace: ns,
					article: article,
					revision: revid
				}, function(raw_data) {
					var data = $.parseJSON(raw_data)
					console.log(data);					
					input_box.fadeOut();
					revlink.hide();
					revlink.attr("href", data.revision_url).html(data.revision).fadeIn();
				});

				return false;
			});
			$(".delete-article").click(function() {
				var parent = $(this).parents(".article-row");
				var ns = parent.attr("data-namespace"),
					article = parent.attr("data-article");

				$.post('', {
					action: 'deletearticle',
					namespace: ns,
					article: article
				}, function() {
					parent.fadeOut();
				});

				return false;
			});

			$(".revision-cancel").click(function() {
				var parent = $(this).parents("div.item-actions");
				var input_box = parent.children(".revision-input");
				input_box.fadeOut();
			});
		});
		</script>

<?php
	} // execute()