public function execute() { $stdin = $this->getStdin(); $urls = array(); while (!feof($stdin)) { $page = trim(fgets($stdin)); if (substr($page, 0, 7) == 'http://') { $urls[] = $page; } elseif ($page !== '') { $title = Title::newFromText($page); if ($title) { $url = $title->getFullUrl(); $this->output("{$url}\n"); $urls[] = $url; if (isset($options['purge'])) { $title->invalidateCache(); } } else { $this->output("(Invalid title '{$page}')\n"); } } } $this->output("Purging " . count($urls) . " urls...\n"); $u = new SquidUpdate($urls); $u->doUpdate(); $this->output("Done!\n"); }
public function execute() { global $wgUser, $wgArticleFeedbackRatingTypes, $wgArticleFeedbackSMaxage, $wgArticleFeedbackNamespaces; $params = $this->extractRequestParams(); // Anon token check if ($wgUser->isAnon()) { if (!isset($params['anontoken'])) { $this->dieUsageMsg(array('missingparam', 'anontoken')); } elseif (strlen($params['anontoken']) != 32) { $this->dieUsage('The anontoken is not 32 characters', 'invalidtoken'); } $token = $params['anontoken']; } else { $token = ''; } // Load check, is this page ArticleFeedback-enabled ? // Keep in sync with ext.articleFeedback.startup.js $title = Title::newFromID($params['pageid']); if (is_null($title) || !in_array($title->getNamespace(), $wgArticleFeedbackNamespaces) || $title->isRedirect()) { // ...then error out $this->dieUsage('ArticleFeedback is not enabled on this page', 'invalidpage'); } $dbw = wfGetDB(DB_MASTER); // Query the latest ratings by this user for this page, // possibly for an older revision // Select from the master to prevent replag-induced bugs $res = $dbw->select('article_feedback', array('aa_rating_id', 'aa_rating_value', 'aa_revision'), array('aa_user_text' => $wgUser->getName(), 'aa_page_id' => $params['pageid'], 'aa_rating_id' => array_keys($wgArticleFeedbackRatingTypes), 'aa_user_anon_token' => $token), __METHOD__, array('ORDER BY' => 'aa_revision DESC', 'LIMIT' => count($wgArticleFeedbackRatingTypes))); $lastRatings = array(); foreach ($res as $row) { $lastRatings[$row->aa_rating_id]['value'] = $row->aa_rating_value; $lastRatings[$row->aa_rating_id]['revision'] = $row->aa_revision; } $pageId = $params['pageid']; $revisionId = $params['revid']; foreach ($wgArticleFeedbackRatingTypes as $ratingID => $unused) { $lastPageRating = false; $lastRevRating = false; if (isset($lastRatings[$ratingID])) { $lastPageRating = intval($lastRatings[$ratingID]['value']); if (intval($lastRatings[$ratingID]['revision']) == $revisionId) { $lastRevRating = $lastPageRating; } } $thisRating = false; if (isset($params["r{$ratingID}"])) { $thisRating = intval($params["r{$ratingID}"]); } $this->insertRevisionRating($pageId, $revisionId, $ratingID, $thisRating - $lastRevRating, $thisRating, $lastRevRating); $this->insertPageRating($pageId, $ratingID, $thisRating - $lastPageRating, $thisRating, $lastPageRating); $this->insertUserRatings($pageId, $revisionId, $wgUser, $token, $ratingID, $thisRating, $params['bucket']); } $this->insertProperties($revisionId, $wgUser, $token, $params); $squidUpdate = new SquidUpdate(array(wfAppendQuery(wfScript('api'), array('action' => 'query', 'format' => 'json', 'list' => 'articlefeedback', 'afpageid' => $pageId, 'afanontoken' => '', 'afuserrating' => 0, 'maxage' => 0, 'smaxage' => $wgArticleFeedbackSMaxage)))); $squidUpdate->doUpdate(); wfRunHooks('ArticleFeedbackChangeRating', array($params)); $r = array('result' => 'Success'); $this->getResult()->addValue(null, $this->getModuleName(), $r); }
public function purgeVarnish() { global $wgHubRssFeeds, $wgServer; echo "| Purging varnishen..." . PHP_EOL; $urls = []; foreach ($wgHubRssFeeds as $feedEndpoint) { $urls[] = SpecialPage::getTitleFor(HubRssFeedSpecialController::SPECIAL_NAME)->getFullUrl() . '/' . $feedEndpoint; $urls[] = implode('/', [$wgServer, 'rss', $feedEndpoint]); } $u = new SquidUpdate($urls); $u->doUpdate(); }
function renderTimeline($timelinesrc) { global $wgUploadDirectory, $wgUploadPath, $IP, $wgTimelineSettings, $wgArticlePath, $wgTmpDirectory; $hash = md5($timelinesrc); $dest = $wgUploadDirectory . "/timeline/"; if (!is_dir($dest)) { mkdir($dest, 0777); } if (!is_dir($wgTmpDirectory)) { mkdir($wgTmpDirectory, 0777); } $fname = $dest . $hash; $previouslyFailed = file_exists($fname . ".err"); $previouslyRendered = file_exists($fname . ".png"); $expired = $previouslyRendered && filemtime($fname . ".png") < wfTimestamp(TS_UNIX, $wgTimelineSettings->epochTimestamp); if ($expired || !$previouslyRendered && !$previouslyFailed) { $handle = fopen($fname, "w"); fwrite($handle, $timelinesrc); fclose($handle); $cmdline = wfEscapeShellArg($wgTimelineSettings->perlCommand, $wgTimelineSettings->timelineFile) . " -i " . wfEscapeShellArg($fname) . " -m -P " . wfEscapeShellArg($wgTimelineSettings->ploticusCommand) . " -T " . wfEscapeShellArg($wgTmpDirectory) . " -A " . wfEscapeShellArg($wgArticlePath); $ret = `{$cmdline}`; unlink($fname); if ($ret == "") { // Message not localized, only relevant during install return "<div id=\"toc\"><tt>Timeline error: Executable not found. Command line was: {$cmdline}</tt></div>"; } } @($err = file_get_contents($fname . ".err")); if ($err != "") { $txt = "<div id=\"toc\"><tt>{$err}</tt></div>"; } else { @($map = file_get_contents($fname . ".map")); if (substr(php_uname(), 0, 7) == "Windows") { $ext = "gif"; } else { $ext = "png"; } $url = "{$wgUploadPath}/timeline/{$hash}.{$ext}"; $txt = "<map name=\"{$hash}\">{$map}</map>" . "<img usemap=\"#{$hash}\" src=\"{$url}\">"; if ($expired) { // Replacing an older file, we may need to purge the old one. global $wgUseSquid; if ($wgUseSquid) { $u = new SquidUpdate(array($url)); $u->doUpdate(); } } } return $txt; }
function render() { global $wgTmpDirectory, $wgInputEncoding; global $wgTexvc, $wgMathCheckFiles, $wgTexvcBackgroundColor; if ($this->mode == MW_MATH_SOURCE) { # No need to render or parse anything more! # New lines are replaced with spaces, which avoids confusing our parser (bugs 23190, 22818) return '<span class="tex">$ ' . str_replace("\n", " ", htmlspecialchars($this->tex)) . ' $</span>'; } if ($this->tex == '') { return; # bug 8372 } if (!$this->_recall()) { if ($wgMathCheckFiles) { # Ensure that the temp and output directories are available before continuing... if (!file_exists($wgTmpDirectory)) { if (!wfMkdirParents($wgTmpDirectory)) { return $this->_error('math_bad_tmpdir'); } } elseif (!is_dir($wgTmpDirectory) || !is_writable($wgTmpDirectory)) { return $this->_error('math_bad_tmpdir'); } } if (!is_executable($wgTexvc)) { return $this->_error('math_notexvc'); } $cmd = $wgTexvc . ' ' . escapeshellarg($wgTmpDirectory) . ' ' . escapeshellarg($wgTmpDirectory) . ' ' . escapeshellarg($this->tex) . ' ' . escapeshellarg($wgInputEncoding) . ' ' . escapeshellarg($wgTexvcBackgroundColor); if (wfIsWindows()) { # Invoke it within cygwin sh, because texvc expects sh features in its default shell $cmd = 'sh -c ' . wfEscapeShellArg($cmd); } wfDebug("TeX: {$cmd}\n"); $contents = wfShellExec($cmd); wfDebug("TeX output:\n {$contents}\n---\n"); if (strlen($contents) == 0) { return $this->_error('math_unknown_error'); } $retval = substr($contents, 0, 1); $errmsg = ''; if ($retval == 'C' || $retval == 'M' || $retval == 'L') { if ($retval == 'C') { $this->conservativeness = 2; } else { if ($retval == 'M') { $this->conservativeness = 1; } else { $this->conservativeness = 0; } } $outdata = substr($contents, 33); $i = strpos($outdata, ""); $this->html = substr($outdata, 0, $i); $this->mathml = substr($outdata, $i + 1); } else { if ($retval == 'c' || $retval == 'm' || $retval == 'l') { $this->html = substr($contents, 33); if ($retval == 'c') { $this->conservativeness = 2; } else { if ($retval == 'm') { $this->conservativeness = 1; } else { $this->conservativeness = 0; } } $this->mathml = null; } else { if ($retval == 'X') { $this->html = null; $this->mathml = substr($contents, 33); $this->conservativeness = 0; } else { if ($retval == '+') { $this->html = null; $this->mathml = null; $this->conservativeness = 0; } else { $errbit = htmlspecialchars(substr($contents, 1)); switch ($retval) { case 'E': $errmsg = $this->_error('math_lexing_error', $errbit); break; case 'S': $errmsg = $this->_error('math_syntax_error', $errbit); break; case 'F': $errmsg = $this->_error('math_unknown_function', $errbit); break; default: $errmsg = $this->_error('math_unknown_error', $errbit); } } } } } if (!$errmsg) { $this->hash = substr($contents, 1, 32); } wfRunHooks('MathAfterTexvc', array(&$this, &$errmsg)); if ($errmsg) { return $errmsg; } if (!preg_match("/^[a-f0-9]{32}\$/", $this->hash)) { return $this->_error('math_unknown_error'); } if (!file_exists("{$wgTmpDirectory}/{$this->hash}.png")) { return $this->_error('math_image_error'); } if (filesize("{$wgTmpDirectory}/{$this->hash}.png") == 0) { return $this->_error('math_image_error'); } $hashpath = $this->_getHashPath(); if (!file_exists($hashpath)) { wfSuppressWarnings(); $ret = wfMkdirParents($hashpath, 0755); wfRestoreWarnings(); if (!$ret) { return $this->_error('math_bad_output'); } } elseif (!is_dir($hashpath) || !is_writable($hashpath)) { return $this->_error('math_bad_output'); } if (!rename("{$wgTmpDirectory}/{$this->hash}.png", "{$hashpath}/{$this->hash}.png")) { return $this->_error('math_output_error'); } # Now save it back to the DB: if (!wfReadOnly()) { $outmd5_sql = pack('H32', $this->hash); $md5_sql = pack('H32', $this->md5); # Binary packed, not hex $dbw = wfGetDB(DB_MASTER); $dbw->replace('math', array('math_inputhash'), array('math_inputhash' => $dbw->encodeBlob($md5_sql), 'math_outputhash' => $dbw->encodeBlob($outmd5_sql), 'math_html_conservativeness' => $this->conservativeness, 'math_html' => $this->html, 'math_mathml' => $this->mathml), __METHOD__); } // If we're replacing an older version of the image, make sure it's current. global $wgUseSquid; if ($wgUseSquid) { $urls = array($this->_mathImageUrl()); $u = new SquidUpdate($urls); $u->doUpdate(); } } return $this->_doRender(); }
/** * Perform the actions of a page purging * @return bool */ public function doPurge() { if (!Hooks::run('ArticlePurge', array(&$this))) { return false; } $title = $this->mTitle; wfGetDB(DB_MASTER)->onTransactionIdle(function () use($title) { global $wgUseSquid; // Invalidate the cache in auto-commit mode $title->invalidateCache(); if ($wgUseSquid) { // Send purge now that page_touched update was committed above $update = new SquidUpdate($title->getSquidURLs()); $update->doUpdate(); } }); if ($this->mTitle->getNamespace() == NS_MEDIAWIKI) { // @todo move this logic to MessageCache if ($this->exists()) { // NOTE: use transclusion text for messages. // This is consistent with MessageCache::getMsgFromNamespace() $content = $this->getContent(); $text = $content === null ? null : $content->getWikitextForTransclusion(); if ($text === null) { $text = false; } } else { $text = false; } MessageCache::singleton()->replace($this->mTitle->getDBkey(), $text); } return true; }
/** * @static * @param $title Title * @param $commentTitle Title */ public static function doPurge($title, $commentTitle) { wfProfileIn(__METHOD__); global $wgMemc, $wgArticleCommentsLoadOnDemand; $wgMemc->set(wfMemcKey('articlecomment', 'comm', $title->getDBkey(), 'v1'), null); // make sure our comment list is refreshed from the master RT#141861 $commentList = ArticleCommentList::newFromTitle($title); $commentList->getCommentList(true); // Purge squid proxy URLs for ajax loaded content if we are lazy loading if (!empty($wgArticleCommentsLoadOnDemand)) { $app = F::app(); $urls = array(); $pages = $commentList->getCountPages(); $basePath = $app->wf->ExpandUrl($app->wg->Server . $app->wg->ScriptPath . '/wikia.php'); $params = array('controller' => 'ArticleCommentsController', 'method' => 'Content', 'format' => 'html', 'articleId' => $title->getArticleId()); for ($page = 1; $page <= $pages; $page++) { $params['page'] = $page; $urls[] = $app->wf->AppendQuery($basePath, $params); } $params['skin'] = true; $squidUpdate = new SquidUpdate($urls); $squidUpdate->doUpdate(); // Otherwise, purge the article } else { //BugID: 2483 purge the parent article when new comment is posted //BugID: 29462, purge the ACTUAL parent, not the root page... $#%^! $parentTitle = Title::newFromText($commentTitle->getBaseText()); if ($parentTitle) { $parentTitle->invalidateCache(); $parentTitle->purgeSquid(); } } /* $parentTitle = Title::newFromText( $commentTitle->getBaseText() ); if ($parentTitle) { if ( empty( $wgArticleCommentsLoadOnDemand ) ) { // need to invalidate parsed article if it includes comments in the body $parentTitle->invalidateCache(); } SquidUpdate::VarnishPurgeKey( self::getSurrogateKey( $parentTitle->getArticleID() ) ); } */ wfProfileOut(__METHOD__); }
function renderTimeline( $timelinesrc ){ global $wgUploadDirectory, $wgUploadPath, $IP, $wgTimelineSettings, $wgArticlePath, $wgTmpDirectory, $wgRenderHashAppend; $hash = md5( $timelinesrc ); if ($wgRenderHashAppend != "") $hash = md5( $hash . $wgRenderHashAppend ); $dest = $wgUploadDirectory."/timeline/"; if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); } if ( ! is_dir( $wgTmpDirectory ) ) { mkdir( $wgTmpDirectory, 0777 ); } $fname = $dest . $hash; $previouslyFailed = file_exists( $fname.".err" ); $previouslyRendered = file_exists( $fname.".png" ); $expired = $previouslyRendered && ( filemtime( $fname.".png" ) < wfTimestamp( TS_UNIX, $wgTimelineSettings->epochTimestamp ) ); if ( $expired || ( !$previouslyRendered && !$previouslyFailed ) ){ $handle = fopen($fname, "w"); fwrite($handle, $timelinesrc); fclose($handle); $cmdline = wfEscapeShellArg( $wgTimelineSettings->perlCommand, $wgTimelineSettings->timelineFile ) . " -i " . wfEscapeShellArg( $fname ) . " -m -P " . wfEscapeShellArg( $wgTimelineSettings->ploticusCommand ) . " -T " . wfEscapeShellArg( $wgTmpDirectory ) . " -A " . wfEscapeShellArg( $wgArticlePath ) . " -f " . wfEscapeShellArg( $wgTimelineSettings->fontFile ); wfDebug( "Timeline cmd: $cmdline\n" ); $ret = `{$cmdline}`; unlink($fname); if ( $ret == "" ) { // Message not localized, only relevant during install return "<div id=\"toc\" dir=\"ltr\"><tt>Timeline error. " . "Command line was: " . htmlspecialchars( $cmdline ) . "</tt></div>"; } } @$err = file_get_contents( $fname.".err" ); if ( $err != "" ) { // Convert the error from poorly-sanitized HTML to plain text $err = strtr( $err, array( '</p><p>' => "\n\n", '<p>' => '', '</p>' => '', '<b>' => '', '</b>' => '', '<br>' => "\n" ) ); $err = Sanitizer::decodeCharReferences( $err ); // Now convert back to HTML again $encErr = nl2br( htmlspecialchars( $err ) ); $txt = "<div id=\"toc\" dir=\"ltr\"><tt>$encErr</tt></div>"; } else { @$map = file_get_contents( $fname.".map" ); $map = str_replace( ' >', ' />', $map ); $map = "<map name=\"timeline_" . htmlspecialchars( $hash ) . "\">{$map}</map>"; $map = easyTimelineFixMap( $map ); if (wfIsWindows()) { $ext = "gif"; } else { $ext = "png"; } $url = "{$wgUploadPath}/timeline/{$hash}.{$ext}"; $txt = $map . "<img usemap=\"#timeline_" . htmlspecialchars( $hash ) . "\" " . "src=\"" . htmlspecialchars( $url ) . "\">"; if( $expired ) { // Replacing an older file, we may need to purge the old one. global $wgUseSquid; if( $wgUseSquid ) { $u = new SquidUpdate( array( $url ) ); $u->doUpdate(); } } } return $txt; }
/** * @static * @param $title Title * @param $commentTitle Title */ public static function doPurge($title, $commentTitle) { wfProfileIn(__METHOD__); global $wgArticleCommentsLoadOnDemand; // make sure our comment list is refreshed from the master RT#141861 $commentList = ArticleCommentList::newFromTitle($title); $commentList->purge(); $commentList->getCommentList(true); // Purge squid proxy URLs for ajax loaded content if we are lazy loading if (!empty($wgArticleCommentsLoadOnDemand)) { $urls = self::getSquidURLs($title); $squidUpdate = new SquidUpdate($urls); $squidUpdate->doUpdate(); // Otherwise, purge the article } else { // BugID: 2483 purge the parent article when new comment is posted // BugID: 29462, purge the ACTUAL parent, not the root page... $#%^! $parentTitle = Title::newFromText($commentTitle->getBaseText()); if ($parentTitle) { $parentTitle->invalidateCache(); $parentTitle->purgeSquid(); } } wfProfileOut(__METHOD__); }
/** * Move page to a title which is at present a redirect to the * source page * * @param $nt \type{Title} the page to move to, which should currently * be a redirect * @param $reason \type{\string} The reason for the move * @param $createRedirect \type{\bool} Whether to leave a redirect at the old title. * Ignored if the user doesn't have the suppressredirect right */ private function moveOverExistingRedirect(&$nt, $reason = '', $createRedirect = true) { global $wgUseSquid, $wgUser, $wgContLang; $comment = wfMsgForContent('1movedto2_redir', $this->getPrefixedText(), $nt->getPrefixedText()); if ($reason) { $comment .= wfMsgForContent('colon-separator') . $reason; } # Truncate for whole multibyte characters. +5 bytes for ellipsis $comment = $wgContLang->truncate($comment, 250); $now = wfTimestampNow(); $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); $latest = $this->getLatestRevID(); $dbw = wfGetDB(DB_MASTER); $rcts = $dbw->timestamp($nt->getEarliestRevTime()); $newns = $nt->getNamespace(); $newdbk = $nt->getDBkey(); # Delete the old redirect. We don't save it to history since # by definition if we've got here it's rather uninteresting. # We have to remove it so that the next step doesn't trigger # a conflict on the unique namespace+title index... $dbw->delete('page', array('page_id' => $newid), __METHOD__); if (!$dbw->cascadingDeletes()) { $dbw->delete('revision', array('rev_page' => $newid), __METHOD__); global $wgUseTrackbacks; if ($wgUseTrackbacks) { $dbw->delete('trackbacks', array('tb_page' => $newid), __METHOD__); } $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__); $dbw->delete('imagelinks', array('il_from' => $newid), __METHOD__); $dbw->delete('categorylinks', array('cl_from' => $newid), __METHOD__); $dbw->delete('templatelinks', array('tl_from' => $newid), __METHOD__); $dbw->delete('externallinks', array('el_from' => $newid), __METHOD__); $dbw->delete('langlinks', array('ll_from' => $newid), __METHOD__); $dbw->delete('redirect', array('rd_from' => $newid), __METHOD__); } // If the redirect was recently created, it may have an entry in recentchanges still $dbw->delete('recentchanges', array('rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1), __METHOD__); # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true); $nullRevId = $nullRevision->insertOn($dbw); $article = new Article($this); wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser)); # Change the name of the target page: $dbw->update('page', array('page_touched' => $dbw->timestamp($now), 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), __METHOD__); $nt->resetArticleID($oldid); # Recreate the redirect, this time in the other direction. if ($createRedirect || !$wgUser->isAllowed('suppressredirect')) { $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n"; $redirectArticle = new Article($this); $newid = $redirectArticle->insertOn($dbw); $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0); wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser)); # Now, we record the link from the redirect to the new title. # It should have no other outgoing links... $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__); $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), __METHOD__); $redirectSuppressed = false; } else { $this->resetArticleID(0); $redirectSuppressed = true; } # Log the move $log = new LogPage('move'); $log->addEntry('move_redir', $this, $reason, array(1 => $nt->getPrefixedText(), 2 => $redirectSuppressed)); # Purge squid if ($wgUseSquid) { $urls = array_merge($nt->getSquidURLs(), $this->getSquidURLs()); $u = new SquidUpdate($urls); $u->doUpdate(); } }
/** * Helper to purge an array of $urls * @param array $urls List of URLS to purge from squids */ private function sendPurgeRequest($urls) { if ($this->hasOption('delay')) { $delay = floatval($this->getOption('delay')); foreach ($urls as $url) { if ($this->hasOption('verbose')) { $this->output($url . "\n"); } $u = new SquidUpdate(array($url)); $u->doUpdate(); usleep($delay * 1000000.0); } } else { if ($this->hasOption('verbose')) { $this->output(implode("\n", $urls) . "\n"); } $u = new SquidUpdate($urls); $u->doUpdate(); } }
/** * Execute the API call: Save the form values */ public function execute() { global $wgUser, $wgArticleFeedbackv5SMaxage; $params = $this->extractRequestParams(); // Anon token check $token = $this->getAnonToken($params); // Is feedback enabled on this page check? if (!ApiArticleFeedbackv5Utils::isFeedbackEnabled($params)) { $this->dieUsage('ArticleFeedback is not enabled on this page', 'invalidpage'); } $dbr = wfGetDB(DB_SLAVE); $pageId = $params['pageid']; $bucket = $params['bucket']; $revisionId = $params['revid']; $error = null; $userAnswers = array(); $fields = ApiArticleFeedbackv5Utils::getFields(); $emailData = array('ratingData' => array(), 'pageID' => $pageId, 'bucketId' => $bucket); // Validate the response data foreach ($fields as $field) { $field_name = $field['afi_name']; if ($field['afi_bucket_id'] != $bucket) { continue; } if (isset($params[$field['afi_name']])) { $value = $params[$field_name]; $type = $field['afi_data_type']; if ($value === '') { continue; } if (!$this->validateParam($value, $type, $field['afi_id'], $pageId)) { $error = 'articlefeedbackv5-error-validation'; break; } if ('text' == $type && $this->findAbuse($value, $pageId)) { $error = 'articlefeedbackv5-error-abuse'; break; } $data = array('aa_field_id' => $field['afi_id']); foreach (array('rating', 'text', 'boolean', 'option_id') as $t) { $data["aa_response_{$t}"] = $t == $type ? $value : null; } $userAnswers[] = $data; $emailData['ratingData'][$field_name] = $value; } } if ($error) { $this->getResult()->addValue(null, 'error', $error); return; } // Save the response data $ratingIds = $this->saveUserRatings($userAnswers, $bucket, $params); $ctaId = $ratingIds['cta_id']; $feedbackId = $ratingIds['feedback_id']; $this->saveUserProperties($feedbackId); $this->updateRollupTables($pageId, $revisionId, $userAnswers); $this->updateFilterCounts($pageId, $userAnswers); // If we have an email address, capture it if ($params['email']) { $this->captureEmail($params['email'], FormatJson::encode($emailData)); } $squidUpdate = new SquidUpdate(array(wfAppendQuery(wfScript('api'), array('action' => 'query', 'format' => 'json', 'list' => 'articlefeedbackv5-view-ratings', 'afpageid' => $pageId, 'maxage' => 0, 'smaxage' => $wgArticleFeedbackv5SMaxage)))); $squidUpdate->doUpdate(); wfRunHooks('ArticleFeedbackChangeRating', array($params)); $this->getResult()->addValue(null, $this->getModuleName(), array('result' => 'Success', 'feedback_id' => $feedbackId, 'cta_id' => $ctaId)); }
<?php /** * Send purge requests for listed pages to squid */ require_once "commandLine.inc"; $stdin = fopen("php://stdin", "rt"); $urls = array(); while (!feof($stdin)) { $page = trim(fgets($stdin)); if (substr($page, 0, 7) == 'http://') { $urls[] = $page; } elseif ($page !== '') { $title = Title::newFromText($page); if ($title) { $url = $title->getFullUrl(); echo "{$url}\n"; $urls[] = $url; if (isset($options['purge'])) { $title->invalidateCache(); } } else { echo "(Invalid title '{$page}')\n"; } } } echo "Purging " . count($urls) . " urls...\n"; $u = new SquidUpdate($urls); $u->doUpdate(); echo "Done!\n";
/** * @param $timelinesrc string * @return string */ function wfRenderTimeline($timelinesrc) { global $wgUploadDirectory, $wgUploadPath, $wgArticlePath, $wgTmpDirectory, $wgRenderHashAppend; global $wgTimelineSettings; // Get the backend to store plot data and pngs if ($wgTimelineSettings->fileBackend != '') { $backend = FileBackendGroup::singleton()->get($wgTimelineSettings->fileBackend); } else { $backend = new FSFileBackend(array('name' => 'timeline-backend', 'lockManager' => 'nullLockManager', 'containerPaths' => array('timeline-render' => "{$wgUploadDirectory}/timeline"), 'fileMode' => 777)); } // Get a hash of the plot data $hash = md5($timelinesrc); if ($wgRenderHashAppend != '') { $hash = md5($hash . $wgRenderHashAppend); } // Storage destination path (excluding file extension) $fname = 'mwstore://' . $backend->getName() . "/timeline-render/{$hash}"; // Wikia change - begin wfRunHooks('BeforeRenderTimeline', [&$backend, &$fname, $hash]); // Wikia change - end $previouslyFailed = $backend->fileExists(array('src' => "{$fname}.err")); $previouslyRendered = $backend->fileExists(array('src' => "{$fname}.png")); if ($previouslyRendered) { $timestamp = $backend->getFileTimestamp(array('src' => "{$fname}.png")); $expired = $timestamp < $wgTimelineSettings->epochTimestamp; } else { $expired = false; } // Create a new .map, .png (or .gif), and .err file as needed... if ($expired || !$previouslyRendered && !$previouslyFailed) { if (!is_dir($wgTmpDirectory)) { mkdir($wgTmpDirectory, 0777); } $tmpFile = TempFSFile::factory('timeline_'); if ($tmpFile) { $tmpPath = $tmpFile->getPath(); file_put_contents($tmpPath, $timelinesrc); // store plot data to file // Get command for ploticus to read the user input and output an error, // map, and rendering (png or gif) file under the same dir as the temp file. $cmdline = wfEscapeShellArg($wgTimelineSettings->perlCommand, $wgTimelineSettings->timelineFile) . " -i " . wfEscapeShellArg($tmpPath) . " -m -P " . wfEscapeShellArg($wgTimelineSettings->ploticusCommand) . " -T " . wfEscapeShellArg($wgTmpDirectory) . " -A " . wfEscapeShellArg($wgArticlePath) . " -f " . wfEscapeShellArg($wgTimelineSettings->fontFile); // Actually run the command... wfDebug("Timeline cmd: {$cmdline}\n"); $retVal = null; $ret = wfShellExec($cmdline, $retVal); // Copy the output files into storage... // @TODO: store error files in another container or not at all? $opt = array('force' => 1, 'nonLocking' => 1, 'allowStale' => 1); // performance $backend->prepare(array('dir' => dirname($fname))); $backend->store(array('src' => "{$tmpPath}.map", 'dst' => "{$fname}.map"), $opt); $backend->store(array('src' => "{$tmpPath}.png", 'dst' => "{$fname}.png"), $opt); $backend->store(array('src' => "{$tmpPath}.err", 'dst' => "{$fname}.err"), $opt); } else { return "<div id=\"toc\" dir=\"ltr\"><tt>Timeline error. " . "Could not create temp file</tt></div>"; // ugh } if ($ret == "" || $retVal > 0) { // Message not localized, only relevant during install return "<div id=\"toc\" dir=\"ltr\"><tt>Timeline error. " . "Command line was: " . htmlspecialchars($cmdline) . "</tt></div>"; } } // Wikia change - begin if ($backend->fileExists(array('src' => "{$fname}.err", 'latest' => true))) { $err = $backend->getFileContents(array('src' => "{$fname}.err")); } else { $err = ''; } // Wikia change - end if ($err != "") { // Convert the error from poorly-sanitized HTML to plain text $err = strtr($err, array('</p><p>' => "\n\n", '<p>' => '', '</p>' => '', '<b>' => '', '</b>' => '', '<br>' => "\n")); $err = Sanitizer::decodeCharReferences($err); // Now convert back to HTML again $encErr = nl2br(htmlspecialchars($err)); $txt = "<div id=\"toc\" dir=\"ltr\"><tt>{$encErr}</tt></div>"; } else { // Wikia change - begin if ($backend->fileExists(array('src' => "{$fname}.map", 'latest' => true))) { $map = $backend->getFileContents(array('src' => "{$fname}.map")); } else { $map = ''; } // Wikia change - end $map = str_replace(' >', ' />', $map); $map = "<map name=\"timeline_" . htmlspecialchars($hash) . "\">{$map}</map>"; $map = easyTimelineFixMap($map); $url = "{$wgUploadPath}/timeline/{$hash}.png"; // Wikia change - begin $url = wfReplaceImageServer($url); // Wikia change - end $txt = $map . "<img usemap=\"#timeline_" . htmlspecialchars($hash) . "\" " . "src=\"" . htmlspecialchars($url) . "\">"; if ($expired) { // Replacing an older file, we may need to purge the old one. global $wgUseSquid; if ($wgUseSquid) { $u = new SquidUpdate(array($url)); $u->doUpdate(); } } } return $txt; }
/** * Helper to purge an array of $urls * @param $urls array List of URLS to purge from squids */ private function sendPurgeRequest($urls) { $this->output("Purging " . count($urls) . " urls\n"); $u = new SquidUpdate($urls); $u->doUpdate(); }
public static function VisualEditor($cv_name, $wiki_id, $value) { if ($cv_name == 'wgEnableNewVisualEditorExt') { Wikia::log(__METHOD__, $wiki_id, "{$cv_name} = {$value}"); // parsed wiki URL $wikiURL = parse_url(GlobalTitle::newFromText('Version', NS_SPECIAL, $wiki_id)->getFullURL()); $getStartupURL = function ($extraData = array()) use($wikiURL) { global $wgOut; // get resource loader url $link = $wgOut->makeResourceLoaderLink('startup', ResourceLoaderModule::TYPE_SCRIPTS, true, $extraData); if ($link != null) { // extract the url from the link src preg_match("/\"(.*)\"/", $link, $matches); if (isset($matches[1])) { $urls[] = $matches[1]; } } // parsed resource loader URL $resourceLoaderURL = parse_url($urls[0]); // URL to purge (constructed from $resourceLoaderURL and $wikiURL) return $wikiURL['scheme'] . '://' . $wikiURL['host'] . $resourceLoaderURL['path']; }; // purge $u = new SquidUpdate([$getStartupURL(), $getStartupURL(array('ve' => 1)), $getStartupURL(array('newve' => 1))]); $u->doUpdate(); } return true; }
/** * Move page to a title which is at present a redirect to the * source page * * @param &$nt \type{Title} the page to move to, which should currently * be a redirect * @param $reason \type{\string} The reason for the move * @param $createRedirect \type{\bool} Whether to leave a redirect at the old title. * Ignored if the user doesn't have the suppressredirect right */ private function moveOverExistingRedirect(&$nt, $reason = '', $createRedirect = true) { global $wgUseSquid, $wgUser; $fname = 'Title::moveOverExistingRedirect'; $comment = wfMsgForContent('1movedto2_redir', $this->getPrefixedText(), $nt->getPrefixedText()); if ($reason) { $comment .= ": {$reason}"; } $now = wfTimestampNow(); $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); $latest = $this->getLatestRevID(); $dbw = wfGetDB(DB_MASTER); # Delete the old redirect. We don't save it to history since # by definition if we've got here it's rather uninteresting. # We have to remove it so that the next step doesn't trigger # a conflict on the unique namespace+title index... $dbw->delete('page', array('page_id' => $newid), $fname); if (!$dbw->cascadingDeletes()) { $dbw->delete('revision', array('rev_page' => $newid), __METHOD__); global $wgUseTrackbacks; if ($wgUseTrackbacks) { $dbw->delete('trackbacks', array('tb_page' => $newid), __METHOD__); } $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__); $dbw->delete('imagelinks', array('il_from' => $newid), __METHOD__); $dbw->delete('categorylinks', array('cl_from' => $newid), __METHOD__); $dbw->delete('templatelinks', array('tl_from' => $newid), __METHOD__); $dbw->delete('externallinks', array('el_from' => $newid), __METHOD__); $dbw->delete('langlinks', array('ll_from' => $newid), __METHOD__); $dbw->delete('redirect', array('rd_from' => $newid), __METHOD__); } # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true); $nullRevId = $nullRevision->insertOn($dbw); $article = new Article($this); wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser)); # Change the name of the target page: $dbw->update('page', array('page_touched' => $dbw->timestamp($now), 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), $fname); $nt->resetArticleID($oldid); # Recreate the redirect, this time in the other direction. if ($createRedirect || !$wgUser->isAllowed('suppressredirect')) { $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n"; $redirectArticle = new Article($this); $newid = $redirectArticle->insertOn($dbw); $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0); wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser)); # Now, we record the link from the redirect to the new title. # It should have no other outgoing links... $dbw->delete('pagelinks', array('pl_from' => $newid), $fname); $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), $fname); $redirectSuppressed = false; } else { $this->resetArticleID(0); $redirectSuppressed = true; } # Move an image if this is a file if ($this->getNamespace() == NS_FILE) { $file = wfLocalFile($this); if ($file->exists()) { $status = $file->move($nt); if (!$status->isOk()) { $dbw->rollback(); return $status->getErrorsArray(); } } } # Log the move $log = new LogPage('move'); $log->addEntry('move_redir', $this, $reason, array(1 => $nt->getPrefixedText(), 2 => $redirectSuppressed)); # Purge squid if ($wgUseSquid) { $urls = array_merge($nt->getSquidURLs(), $this->getSquidURLs()); $u = new SquidUpdate($urls); $u->doUpdate(); } }
/** * Move page to a title which is at present a redirect to the * source page * * @param Title &$nt the page to move to, which should currently * be a redirect */ private function moveOverExistingRedirect(&$nt, $reason = '') { global $wgUseSquid; $fname = 'Title::moveOverExistingRedirect'; $comment = wfMsgForContent('1movedto2_redir', $this->getPrefixedText(), $nt->getPrefixedText()); if ($reason) { $comment .= ": {$reason}"; } $now = wfTimestampNow(); $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); $dbw = wfGetDB(DB_MASTER); $linkCache =& LinkCache::singleton(); # Delete the old redirect. We don't save it to history since # by definition if we've got here it's rather uninteresting. # We have to remove it so that the next step doesn't trigger # a conflict on the unique namespace+title index... $dbw->delete('page', array('page_id' => $newid), $fname); # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true); $nullRevId = $nullRevision->insertOn($dbw); # Change the name of the target page: $dbw->update('page', array('page_touched' => $dbw->timestamp($now), 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), $fname); $linkCache->clearLink($nt->getPrefixedDBkey()); # Recreate the redirect, this time in the other direction. $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n"; $redirectArticle = new Article($this); $newid = $redirectArticle->insertOn($dbw); $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0); $linkCache->clearLink($this->getPrefixedDBkey()); # Log the move $log = new LogPage('move'); $log->addEntry('move_redir', $this, $reason, array(1 => $nt->getPrefixedText())); # Now, we record the link from the redirect to the new title. # It should have no other outgoing links... $dbw->delete('pagelinks', array('pl_from' => $newid), $fname); $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDbKey()), $fname); # Purge squid if ($wgUseSquid) { $urls = array_merge($nt->getSquidURLs(), $this->getSquidURLs()); $u = new SquidUpdate($urls); $u->doUpdate(); } }
function purgePath($arr) { global $wgUseSquid, $wgServer; if ($wgUseSquid) { $urls = array(); foreach ($arr as $elem) { $urls[] = $wgServer . $elem; } $u = new SquidUpdate($urls); $u->doUpdate(); wfDebug("Avatar: Purging path of " . print_r($urls, true) . "\n"); } return true; }
/** * Purge all applicable Squid URLs */ public function purgeSquid() { global $wgUseSquid; if ($wgUseSquid) { $urls = $this->getSquidURLs(); $u = new SquidUpdate($urls); $u->doUpdate(); } }
public function execute() { global $wgHTCPRouting; if ($this->hasOption('htcp-dest')) { $parts = explode(':', $this->getOption('htcp-dest')); if (count($parts) < 2) { // Add default htcp port $parts[] = '4827'; } // Route all HTCP messages to provided host:port $wgHTCPRouting = array('' => array('host' => $parts[0], 'port' => $parts[1])); if ($this->hasOption('verbose')) { $this->output("HTCP broadcasts to {$parts[0]}:{$parts[1]}\n"); } } $dbr = $this->getDB(DB_SLAVE); $minTime = $dbr->timestamp($this->getOption('starttime')); $maxTime = $dbr->timestamp($this->getOption('endtime')); if ($maxTime < $minTime) { $this->error("\nERROR: starttime after endtime\n"); $this->maybeHelp(true); } $stuckCount = 0; // loop breaker while (true) { // Adjust bach size if we are stuck in a second that had many changes $bSize = $this->mBatchSize + $stuckCount * $this->mBatchSize; $res = $dbr->select(array('page', 'revision'), array('rev_timestamp', 'page_namespace', 'page_title'), array("rev_timestamp > " . $dbr->addQuotes($minTime), "rev_timestamp <= " . $dbr->addQuotes($maxTime), "page_latest = rev_id"), __METHOD__, array('ORDER BY' => 'rev_timestamp', 'LIMIT' => $bSize), array('page' => array('INNER JOIN', 'rev_page=page_id'))); if (!$res->numRows()) { // nothing more found so we are done break; } // Kludge to not get stuck in loops for batches with the same timestamp list($rows, $lastTime) = $this->pageableSortedRows($res, 'rev_timestamp', $bSize); if (!count($rows)) { ++$stuckCount; continue; } // Reset suck counter $stuckCount = 0; $this->output("Processing changes from {$minTime} to {$lastTime}.\n"); // Advance past the last row next time $minTime = $lastTime; // Create list of URLs from page_namespace + page_title $urls = array(); foreach ($rows as $row) { $title = Title::makeTitle($row->page_namespace, $row->page_title); $urls[] = $title->getInternalURL(); } if ($this->hasOption('dry-run') || $this->hasOption('verbose')) { $this->output(implode("\n", $urls) . "\n"); if ($this->hasOption('dry-run')) { continue; } } // Send batch of purge requests out to squids $squid = new SquidUpdate($urls, count($urls)); $squid->doUpdate(); if ($this->hasOption('sleep-per-batch')) { // sleep-per-batch is milliseconds, usleep wants micro seconds. usleep(1000 * (int) $this->getOption('sleep-per-batch')); } } $this->output("Done!\n"); }