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 ); }
/** * 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); }
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"; }
/** * 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; }
/** * 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; }
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()