/** * */ public function getSimpleFormatForArticle(\Article $article) { $measurement = \Wikia\Measurements\Time::start([__CLASS__, __METHOD__]); $cacheKey = wfMemcKey("SimpleJson", $article->getPage()->getId(), self::SIMPLE_JSON_SCHEMA_VERSION); $jsonSimple = $this->app->wg->memc->get($cacheKey); if ($jsonSimple === false) { /** * Prevention from circular references, when parsing articles with tabs. * * E.g. when page contains tab, which is actually link to itself, * or if any tab contains tab, which referenced to given page. * * @see DivContainingHeadersVisitor::parseTabview */ \Wikia\JsonFormat\HtmlParser::markAsVisited($article->getTitle()->getText()); $jsonFormatRootNode = $this->getJsonFormatForArticle($article); // We have finished parsing of article, so we can clean array of visited articles \Wikia\JsonFormat\HtmlParser::clearVisited(); $simplifier = new Wikia\JsonFormat\JsonFormatSimplifier(); $jsonSimple = $simplifier->simplify($jsonFormatRootNode, $article->getTitle()->getText()); $this->app->wg->memc->set($cacheKey, $jsonSimple, self::SIMPLE_JSON_CACHE_EXPIRATION); } $measurement->stop(); return $jsonSimple; }
/** * Get the description, name and upload time of the passed wiki file */ public static function getUploadedFileInfo($title) { $article = new Article($title); $desc = $article->getPage()->getContent()->getNativeData(); $dbr = wfGetDB(DB_SLAVE); $row = $dbr->selectRow('revision', array('rev_user', 'rev_timestamp'), array('rev_page' => $title->getArticleID()), __METHOD__, array('ORDER BY' => 'rev_timestamp', 'LIMIT' => 1)); return array($row->rev_user, $row->rev_timestamp, $desc); }
/** * Save the metadata to DB ( page_wikia_props ) * to prop name defined in self::article_prop_name */ public function save($propagateToSolr = false) { $this->setWikiaProp(self::ARTICLE_PROP_NAME, $this->articleId, $this->getMetadata()); if ($propagateToSolr) { $article = new Article($this->articleTitle); // push directly to article_metadata core $this->pushToSolr(F::app()->wg->CityId, $this->articleId, $this->getMetadata()); // push to main core via scribe ScribeEventProducerController::notifyPageHasChanged($article->getPage()); } }
public function MainPageModuleSave() { $articleTitle = $this->getRequest()->getVal('pageTitle'); $wikiMarkup = $this->getRequest()->getVal('wikiMarkup'); $pageTitleObj = Title::newFromText($articleTitle); $pageArticleObj = new Article($pageTitleObj); $pageArticleObj->doEdit($wikiMarkup, ''); $pageArticleObj->doPurge(); $newHtml = $pageArticleObj->getPage()->getParserOutput(new ParserOptions(null, null))->getText(); $this->getResponse()->setFormat('json'); $this->getResponse()->setVal('html', $newHtml); }
protected function doDBUpdates() { // get "User:" namespace prefix in wiki language global $wgContLang; $namespaces = $wgContLang->getFormattedNamespaces(); $title = Title::newFromText(wfMessage('flow-ve-mention-template-title')->inContentLanguage()->plain(), NS_TEMPLATE); $article = new Article($title); $page = $article->getPage(); if ($page->getRevision() !== null) { // template already exists, don't overwrite it return true; } $status = $page->doEditContent(new WikitextContent('@[[' . $namespaces[NS_USER] . ':{{{1|Example}}}|{{{2|{{{1|Example}}}}}}]]'), '/* Automatically created by Flow */', EDIT_FORCE_BOT | EDIT_SUPPRESS_RC, false, FlowHooks::getOccupationController()->getTalkpageManager()); return $status->isOK(); }
/** * Accesses a snippet from MediaWiki. * @return string */ public function getUncachedSnippetFromArticle() { // get standard parser cache for anons, // 99% of the times it will be available but // generate it in case is not $content = ''; $page = $this->article->getPage(); $opts = $page->makeParserOptions(new User()); $parserOutput = $page->getParserOutput($opts); try { $content = $this->getContentFromParser($parserOutput); } catch (Exception $e) { \Wikia\Logger\WikiaLogger::instance()->error('ArticleService, not parser output object found', ['parserOutput' => $parserOutput, 'parserOptions' => $opts, 'page' => $page, 'exception' => $e]); } // Run hook to allow wikis to modify the content (ie: customize their snippets) before the stripping and length limitations are done. wfRunHooks('ArticleService::getTextSnippet::beforeStripping', array(&$this->article, &$content, ArticleService::MAX_LENGTH)); return $this->cleanArticleSnippet($content); }
public static function onBeforePageDisplay($out, $skin) { // Add sidebar content $title = Title::newFromText('Od-sidebar', NS_MEDIAWIKI); $article = new Article($title); $html = $out->parse($article->getPage()->getContent()->getNativeData()); $out->addHTML("<div id=\"wikitext-sidebar\" style=\"display:none\">{$html}</div>"); // Add footer content $title = Title::newFromText('Footer', NS_MEDIAWIKI); $article = new Article($title); $html = $out->parse($article->getPage()->getContent()->getNativeData()); $out->addHTML("<div id=\"wikitext-footer\" style=\"display:none\"><div id=\"od-footer\">{$html}</div></div>"); // Add the other items self::donations($out); self::languages($out); self::avatar($out); return true; }
/** * Use the plain-text of the summary for the item description */ private function desc($title) { global $wgParser; $article = new Article($title); $content = $article->getPage()->getContent()->getNativeData(); $text = preg_match("/^.+?1=(.+?)\\|2=/s", $content, $m) ? $m[1] : $title->getText(); $html = $wgParser->parse(trim($text), $title, new ParserOptions(), true, true)->getText(); $html = preg_replace('|<a[^<]+<img .+?</a>|', '', $html); $desc = strip_tags($html, '<p><a><i><b><u><s>'); $desc = preg_replace("/[\r\n]+/", "", $desc); $desc = preg_replace("|<p></p>|", "", $desc); $desc = trim(preg_replace("|<p>|", "\n<p>", $desc)); return $desc; }
public static function onShowMissingArticle(Article $article) { if ($article->getPage()->getContentModel() !== CONTENT_MODEL_FLOW_BOARD) { return true; } if ($article->getTitle()->getNamespace() === NS_TOPIC) { // @todo pretty message about invalid workflow throw new FlowException('Non-existent topic'); } $emptyContent = ContentHandler::getForModelID(CONTENT_MODEL_FLOW_BOARD)->makeEmptyContent(); $parserOutput = $emptyContent->getParserOutput($article->getTitle()); $article->getContext()->getOutput()->addParserOutput($parserOutput); return false; }
public function execute() { global $wgTitle; $res = $this->queryPages(); if (!$res || count($res) === 0) { $this->log('No results'); } else { $this->log(count($res) . ' results found'); } if ($this->hasOption('from_title')) { $from_title = trim($this->getOption('from_title')); $skip = true; } if ($this->hasOption('unmodified_since')) { $before_date = strtotime($this->getOption('unmodified_since')); } //echo $from; exit; //$this->log(print_r($res,true)); foreach ($res as $row) { if (isset($from_title)) { if (trim($row->page_title) == $from_title) { $skip = false; } if ($skip) { $this->log('Skipping ' . $row->page_title); continue; } } $title = Title::newFromText($row->page_title); $article = new Article($title, 0); if (!$article) { $this->log('Page title not found: ' . $row->page_title); continue; } $page = $article->getPage(); //it would probably be better to do this via a join on the most recent revision's timestamp field, but whatever... if (isset($before_date)) { $time = strtotime($page->getTimestamp()); if ($time > $before_date) { $this->log('Skipping ' . $row->page_title . ' - has been modified since specified date: ' . date('Y-M-d', $before_date) . ' ' . $this->getOption('unmodified_since')); continue; } } $content = $article->fetchContent(); if (preg_match('%{{Plant%ui', $content, $m)) { $has_tpl = preg_match('%{{Plant%ui', $content, $matched); if ($has_tpl) { $this->log($title->getText()); $this->log('Migrating article to CC-BY-SA'); /*$content = preg_replace('%|cultivation=%i', "|cultivation notes=|PFAF cultivation notes=" ,$content, 1); $content = preg_replace('%|propagation=%i', "|propagation notes=|PFAF propagation notes=", $content, 1); $content = preg_replace('%|toxicity notes=%i', "|toxicity notes=|PFAF toxicity notes=", $content, 1); $content = preg_replace('%|edible use notes=%i', "|edible use notes=|PFAF edible use notes=", $content, 1); $content = preg_replace('%|material use notes=%i', "|material use notes=|PFAF material use notes=", $content, 1); $content = preg_replace('%|medicinal use notes=%i', "|medicinal use notes=|PFAF medicinal use notes=", $content, 1);*/ //since we're replacing with content which contains the replace match, we need to use an intermediate step /*$content = preg_replace('%|(toxicity|edible use|material use|medicinal use) notes=%', '|$1 replace=', $content); $patterns = array( '%|(cultivation)=%', '%|(propagation)=%', '%|((toxicity|edible use|material use|medicinal use) replace)=%', ); $replacements = array( "|cultivation notes=|PFAF cultivation notes=", "|propagation notes=|PFAF propagation notes=", "|$1=|PFAF $1=", ); $content = preg_replace($patterns, $replacements, $content); */ $renames = array('|cultivation=' => "|cultivation notes=\n|PFAF cultivation notes=", '|propagation=' => "|propagation notes=\n|PFAF propagation notes=", '|toxicity notes=' => "|toxicity notes=\n|PFAF toxicity notes=", '|edible use notes=' => "|edible use notes=\n|PFAF edible use notes=", '|material use notes=' => "|material use notes=\n|PFAF material use notes=", '|medicinal use notes=' => "|medicinal use notes=\n|PFAF medicinal use notes="); foreach ($renames as $old => $new) { $check = stripos($content, $new); if ($check) { $this->log('Article appears to have already been migrated. Skipping.'); break; } $pos = stripos($content, $old); if ($pos) { /*$this->log('Replacing text found at '.$pos.' - '. ($pos+strlen($old)) ); $this->log(substr($content, $pos, strlen($old) ) ); $this->log('with'); $this->log( $new );*/ $content = substr_replace($content, $new, $pos, strlen($old)); } } $edit_summary = 'Migrating article to Creative Commons BY-SA, isolating PFAF NC content for manual migration. See the page: Migrating PFAF Licensing'; $user = User::newFromName('Bot'); $article->doEdit($content, $edit_summary, EDIT_FORCE_BOT + EDIT_SUPPRESS_RC, $user); } else { $this->log($row->page_title . ' does not have the Plant template. Skipping.'); } } } }
/** * @param Article $article */ public function __construct(Article $article) { $this->mArticle = $article; $this->page = $article->getPage(); // model object $this->mTitle = $article->getTitle(); $this->contentModel = $this->mTitle->getContentModel(); $handler = ContentHandler::getForModelID($this->contentModel); $this->contentFormat = $handler->getDefaultFormat(); }
/** * @param Content|null $def_content The default value to return * * @return Content|null Content on success, $def_content for invalid sections * * @since 1.21 */ protected function getContentObject($def_content = null) { global $wgOut, $wgRequest, $wgUser, $wgContLang; wfProfileIn(__METHOD__); $content = false; // For message page not locally set, use the i18n message. // For other non-existent articles, use preload text if any. if (!$this->mTitle->exists() || $this->section == 'new') { if ($this->mTitle->getNamespace() == NS_MEDIAWIKI && $this->section != 'new') { # If this is a system message, get the default text. $msg = $this->mTitle->getDefaultMessageText(); $content = $this->toEditContent($msg); } if ($content === false) { # If requested, preload some text. $preload = $wgRequest->getVal('preload', $this->section === 'new' ? 'MediaWiki:addsection-preload' : ''); $params = $wgRequest->getArray('preloadparams', array()); $content = $this->getPreloadedContent($preload, $params); } // For existing pages, get text based on "undo" or section parameters. } else { if ($this->section != '') { // Get section edit text (returns $def_text for invalid sections) $orig = $this->getOriginalContent($wgUser); $content = $orig ? $orig->getSection($this->section) : null; if (!$content) { $content = $def_content; } } else { $undoafter = $wgRequest->getInt('undoafter'); $undo = $wgRequest->getInt('undo'); if ($undo > 0 && $undoafter > 0) { $undorev = Revision::newFromId($undo); $oldrev = Revision::newFromId($undoafter); # Sanity check, make sure it's the right page, # the revisions exist and they were not deleted. # Otherwise, $content will be left as-is. if (!is_null($undorev) && !is_null($oldrev) && !$undorev->isDeleted(Revision::DELETED_TEXT) && !$oldrev->isDeleted(Revision::DELETED_TEXT)) { $content = $this->mArticle->getUndoContent($undorev, $oldrev); if ($content === false) { # Warn the user that something went wrong $undoMsg = 'failure'; } else { $oldContent = $this->mArticle->getPage()->getContent(Revision::RAW); $popts = ParserOptions::newFromUserAndLang($wgUser, $wgContLang); $newContent = $content->preSaveTransform($this->mTitle, $wgUser, $popts); if ($newContent->equals($oldContent)) { # Tell the user that the undo results in no change, # i.e. the revisions were already undone. $undoMsg = 'nochange'; $content = false; } else { # Inform the user of our success and set an automatic edit summary $undoMsg = 'success'; # If we just undid one rev, use an autosummary $firstrev = $oldrev->getNext(); if ($firstrev && $firstrev->getId() == $undo) { $userText = $undorev->getUserText(); if ($userText === '') { $undoSummary = wfMessage('undo-summary-username-hidden', $undo)->inContentLanguage()->text(); } else { $undoSummary = wfMessage('undo-summary', $undo, $userText)->inContentLanguage()->text(); } if ($this->summary === '') { $this->summary = $undoSummary; } else { $this->summary = $undoSummary . wfMessage('colon-separator')->inContentLanguage()->text() . $this->summary; } $this->undidRev = $undo; } $this->formtype = 'diff'; } } } else { // Failed basic sanity checks. // Older revisions may have been removed since the link // was created, or we may simply have got bogus input. $undoMsg = 'norev'; } // Messages: undo-success, undo-failure, undo-norev, undo-nochange $class = ($undoMsg == 'success' ? '' : 'error ') . "mw-undo-{$undoMsg}"; $this->editFormPageTop .= $wgOut->parse("<div class=\"{$class}\">" . wfMessage('undo-' . $undoMsg)->plain() . '</div>', true, true); } if ($content === false) { $content = $this->getOriginalContent($wgUser); } } } wfProfileOut(__METHOD__); return $content; }
/** * Log stuff to EventLogging's Schema:Edit - see https://meta.wikimedia.org/wiki/Schema:Edit * If you don't have EventLogging installed, does nothing. * * @param string $action * @param Article $article Which article (with full context, page, title, etc.) * @param array $data Data to log for this action * @return bool Whether the event was logged or not. */ public static function doEventLogging($action, $article, $data = array()) { global $wgVersion; if (!class_exists('EventLogging')) { return false; } // Sample 6.25% (via hex digit) if ($data['editingSessionId'][0] > '0') { return false; } $user = $article->getContext()->getUser(); $page = $article->getPage(); $title = $article->getTitle(); $data = array('action' => $action, 'version' => 1, 'editor' => 'wikitext', 'platform' => 'desktop', 'integration' => 'page', 'page.id' => $page->getId(), 'page.title' => $title->getPrefixedText(), 'page.ns' => $title->getNamespace(), 'page.revid' => $page->getRevision() ? $page->getRevision()->getId() : 0, 'user.id' => $user->getId(), 'user.editCount' => $user->getEditCount() ?: 0, 'mediawiki.version' => $wgVersion) + $data; if ($user->isAnon()) { $data['user.class'] = 'IP'; } return EventLogging::logEvent('Edit', 13457736, $data); }
/** * Expand the #file parser-function */ function expandFile($parser, $filename, $anchor = false) { global $wgJQUploadFileLinkPopup; $class = ''; $href = false; $info = ''; if ($anchor === false) { $anchor = $filename; } // Check if the file is a locally uploaded one $img = wfLocalFile($filename); if ($img->exists()) { global $wgLang; $href = $img->getUrl(); $class = ' local-file'; if ($wgJQUploadFileLinkPopup) { $title = $img->getTitle(); $article = new Article($title); $wikitext = $article->getPage()->getContent()->getNativeData(); $info = $parser->parse($wikitext, $parser->getTitle(), new ParserOptions(), false, false)->getText(); if (!empty($info)) { $info = '<span class="file-desc">' . $info . '</span>'; } $date = wfMsg('jqueryupload-uploadinfo', $img->user_text, $wgLang->date($img->timestamp, true)); $info = '<span class="file-info">' . $date . '</span><br />' . $info; } } // Not local, check if it's a jQuery one if ($href === false) { global $wgUploadDirectory, $wgScriptPath; if ($glob = glob("{$wgUploadDirectory}/jquery_upload_files/*/{$filename}")) { if (preg_match("|jquery_upload_files/(\\d+)/|", $glob[0], $m)) { $path = $m[1]; $class = ' jquery-file'; $href = "{$wgScriptPath}/api.php?action=jqu&rsargs[]={$path}&rsargs[]=" . urlencode($filename); if ($wgJQUploadFileLinkPopup) { $meta = "{$wgUploadDirectory}/jquery_upload_files/{$path}/meta/{$filename}"; if (file_exists($meta)) { $data = unserialize(file_get_contents($meta)); $info = '<span class="file-info">' . MWUploadHandler::renderData($data) . '</span>'; if ($data[2]) { $info .= '<br /><span class="file-desc">' . $data[2] . '</span>'; } } } } } } if ($href === false) { $class = ' redlink'; } //$title = empty( $info ) ? " title=\"$filename\"" : ''; if (!empty($info)) { $info = "<span style=\"display:none\">{$info}</span>"; } return "<span class=\"jqu-span\"><span class=\"plainlinks{$class}\" title=\"{$href}\">{$anchor}{$info}</span></span>"; }
/** * Perform the export operation */ public static function onUnknownAction($action, $article) { global $wgOut, $wgUser, $wgParser, $wgRequest, $wgAjaxComments, $wgPdfBookDownload; global $wgServer, $wgArticlePath, $wgScriptPath, $wgUploadPath, $wgUploadDirectory, $wgScript; if ($action == 'pdfbook' && $wgUser->isLoggedIn()) { $title = $article->getTitle(); $opt = ParserOptions::newFromUser($wgUser); // Log the export $msg = wfMsg('pdfbook-log', $wgUser->getUserPage()->getPrefixedText()); $log = new LogPage('pdf', false); $log->addEntry('book', $article->getTitle(), $msg); // Initialise PDF variables $format = $wgRequest->getText('format'); $notitle = $wgRequest->getText('notitle'); $comments = $wgAjaxComments ? $wgRequest->getText('comments') : ''; $layout = $format == 'single' ? '--webpage' : '--firstpage toc'; $charset = self::setProperty('Charset', 'iso-8859-1'); $left = self::setProperty('LeftMargin', '1cm'); $right = self::setProperty('RightMargin', '1cm'); $top = self::setProperty('TopMargin', '1cm'); $bottom = self::setProperty('BottomMargin', '1cm'); $font = self::setProperty('Font', 'Arial'); $size = self::setProperty('FontSize', '8'); $ls = self::setProperty('LineSpacing', 1); $linkcol = self::setProperty('LinkColour', '217A28'); $levels = self::setProperty('TocLevels', '2'); $exclude = self::setProperty('Exclude', array()); $width = self::setProperty('Width', ''); $options = self::setProperty('Options', ''); $width = $width ? "--browserwidth {$width}" : ''; if (!is_array($exclude)) { $exclude = split('\\s*,\\s*', $exclude); } // Select articles from members if a category or links in content if not if ($format == 'single') { $articles = array($title); } else { $articles = array(); if ($title->getNamespace() == NS_CATEGORY) { $db = wfGetDB(DB_SLAVE); $cat = $db->addQuotes($title->getDBkey()); $result = $db->select('categorylinks', 'cl_from', "cl_to = {$cat}", 'PdfBook', array('ORDER BY' => 'cl_sortkey')); if ($result instanceof ResultWrapper) { $result = $result->result; } while ($row = $db->fetchRow($result)) { $articles[] = Title::newFromID($row[0]); } } else { $text = $article->getPage()->getContent()->getNativeData(); $text = $wgParser->preprocess($text, $title, $opt); if (preg_match_all("/^\\*\\s*\\[{2}\\s*([^\\|\\]]+)\\s*.*?\\]{2}/m", $text, $links)) { foreach ($links[1] as $link) { $articles[] = Title::newFromText($link); } } } } // Format the article(s) as a single HTML document with absolute URL's $book = $title->getText(); $html = ''; $wgArticlePath = $wgServer . $wgArticlePath; $wgPdfBookTab = false; $wgScriptPath = $wgServer . $wgScriptPath; $wgUploadPath = $wgServer . $wgUploadPath; $wgScript = $wgServer . $wgScript; foreach ($articles as $title) { $ttext = $title->getPrefixedText(); if (!in_array($ttext, $exclude)) { $article = new Article($title); $text = $article->getPage()->getContent()->getNativeData(); $text = preg_replace("/<!--([^@]+?)-->/s", "@@" . "@@\$1@@" . "@@", $text); # preserve HTML comments if ($format != 'single') { $text .= "__NOTOC__"; } $opt->setEditSection(false); # remove section-edit links $out = $wgParser->parse($text, $title, $opt, true, true); $text = $out->getText(); $text = preg_replace("|(<img[^>]+?src=\")(/.+?>)|", "\$1{$wgServer}\$2", $text); # make image urls absolute $text = preg_replace("|<div\\s*class=['\"]?noprint[\"']?>.+?</div>|s", "", $text); # non-printable areas $text = preg_replace("|@{4}([^@]+?)@{4}|s", "<!--\$1-->", $text); # HTML comments hack $ttext = basename($ttext); $h1 = $notitle ? "" : "<center><h1>{$ttext}</h1></center>"; // Add comments if selected and AjaxComments is installed if ($comments) { $comments = $wgAjaxComments->onUnknownAction('ajaxcommentsinternal', $article); } $html .= utf8_decode("{$h1}{$text}\n{$comments}"); } } // $wgPdfBookTab = false; If format=html in query-string, return html content directly if ($format == 'html') { $wgOut->disable(); header("Content-Type: text/html"); header("Content-Disposition: attachment; filename=\"{$book}.html\""); print $html; } else { // Write the HTML to a tmp file if (!is_dir($wgUploadDirectory)) { mkdir($wgUploadDirectory); } $file = "{$wgUploadDirectory}/" . uniqid('pdf-book'); file_put_contents($file, $html); $footer = $format == 'single' ? "..." : ".1."; $toc = $format == 'single' ? "" : " --toclevels {$levels}"; // Send the file to the client via htmldoc converter $wgOut->disable(); header("Content-Type: application/pdf"); if ($wgPdfBookDownload) { header("Content-Disposition: attachment; filename=\"{$book}.pdf\""); } else { header("Content-Disposition: inline; filename=\"{$book}.pdf\""); } $cmd = "--left {$left} --right {$right} --top {$top} --bottom {$bottom}"; $cmd .= " --header ... --footer {$footer} --headfootsize 8 --quiet --jpeg --color"; $cmd .= " --bodyfont {$font} --fontsize {$size} --fontspacing {$ls} --linkstyle plain --linkcolor {$linkcol}"; $cmd .= "{$toc} --no-title --format pdf14 --numbered {$layout} {$width}"; $cmd = "htmldoc -t pdf --charset {$charset} {$options} {$cmd} {$file}"; putenv("HTMLDOC_NOCGI=1"); passthru($cmd); @unlink($file); } return false; } return true; }
public function execute() { $dbw = wfGetDB(DB_MASTER); // Scan all talk pages for AjaxComments data structures $this->output("\nScanning talk pages for comments needing migration...\n"); $res = $dbw->select('page', array('page_id'), array('page_namespace & 1')); $data = array(); $pages = 0; $cpages = 0; foreach ($res as $row) { $id = $row->page_id; $title = Title::newFromId($id); if ($title->exists()) { $pages++; $article = new Article($title); $content = $article->getPage()->getContent()->getNativeData(); // This page ID of the associated content page $page = Title::newFromText($title->getText(), $title->getNamespace() - 1); if ($page) { $page = $page->getArticleID(); $this->output(" Processing talk page with ID {$id} (associated content page has ID {$page})\n"); // If this page has AjaxComments data in it's current revision, extract the data, if ($ac = $this->textToData($content)) { $cpages++; foreach ($ac as $k => $v) { $data[$k] = $v; $data[$k]['talk'] = $id; $data[$k]['page'] = $page; $data[$k]['id'] = count($data); } // and revert it to it's state prior to AjaxComments, or delete it $rev = Revision::newFromId($title->getLatestRevID()); do { $rev = $rev->getPrevious(); } while ($rev && strpos($comment = $rev->getRawComment(), 'AjaxComments') !== false); if ($rev) { $this->output(" Reverting (talkpage {$id}) to comment " . $rev->getId() . " (Edit comment: '{$comment}').\n"); $article->doEdit($rev->getText(), 'Reverted talkpage to state prior to AJAXCOMMENTS additions', EDIT_UPDATE); } else { $this->output(" Deleting (talkpage {$id}) as it has only AjaxComments revisions.\n"); $article->doDelete('Deleting talkpage, comments data has been moved into the "ajaxcomments" database table.'); } } } } } $this->output(" Done (" . count($data) . " comments migrated from {$cpages} talkpages out of {$pages} in total)\n"); // Update the data to the new format $this->output("\nUpgrading comment data...\n"); foreach ($data as $k => $v) { $id = $data[$k]['id']; $name = $data[$k][AJAXCOMMENTS_USER]; $uid = User::newFromName($name)->getId(); if ($uid < 1) { $uid = 0; $this->output(' WARNING: Invalid user in comment $k in page ' . $data[$k]['page'] . " ID set to zero\n"); } $data[$k][AJAXCOMMENTS_USER] = $uid; $this->output(" New id for {$k} is {$id}, user '{$name}' has ID {$uid}\n"); if ($parent = $data[$k][AJAXCOMMENTS_PARENT]) { $data[$k][AJAXCOMMENTS_PARENT] = $data[$parent]['id']; $this->output(" 'parent' field changed from {$parent} to " . $data[$parent]['id'] . "\n"); } if ($n = count($data[$k][AJAXCOMMENTS_LIKE])) { $likes = array(); foreach ($data[$k][AJAXCOMMENTS_LIKE] as $name => $val) { $uid = User::newFromName($name)->getId(); if ($uid) { $likes[$uid] = $val; } else { $this->output(" WARNING: Invalid user in 'like' field, item dropped\n"); } } $data[$k][AJAXCOMMENTS_LIKE] = $likes; $this->output(" {$n} usernames changed to IDs in the 'like' field\n"); } } $this->output(" Done\n"); // Add the new table $tbl = $dbw->tableName(AJAXCOMMENTS_TABLE); $this->output("\nAdding table {$tbl} if it doesn't already exist, clearing data if it does exist...\n"); $dbw->query("DROP TABLE IF EXISTS {$tbl}"); $dbw->query("CREATE TABLE IF NOT EXISTS {$tbl} (\n\t\t\tac_id INT UNSIGNED NOT NULL AUTO_INCREMENT,\n\t\t\tac_type INT UNSIGNED NOT NULL,\n\t\t\tac_parent INT UNSIGNED,\n\t\t\tac_user INT UNSIGNED,\n\t\t\tac_page INT UNSIGNED,\n\t\t\tac_time INT UNSIGNED,\n\t\t\tac_data TEXT,\n\t\t\tPRIMARY KEY (ac_id)\n\t\t)"); $this->output(" Done\n"); // Insert the upgraded data into the table $this->output("\nInserting the upgraded data into the table...\n"); foreach ($data as $k => $v) { $id = $data[$k]['id']; $page = $data[$k]['page']; $this->output(" Inserting comment {$id} (was {$k})\n"); $dbw->insert(AJAXCOMMENTS_TABLE, array('ac_type' => AJAXCOMMENTS_DATATYPE_COMMENT, 'ac_parent' => $data[$k][AJAXCOMMENTS_PARENT], 'ac_user' => $data[$k][AJAXCOMMENTS_USER], 'ac_page' => $page, 'ac_time' => $data[$k][AJAXCOMMENTS_DATE], 'ac_data' => $data[$k][AJAXCOMMENTS_TEXT])); // Insert a row for each 'like' in this comment if ($n = count($data[$k][AJAXCOMMENTS_LIKE])) { foreach ($data[$k][AJAXCOMMENTS_LIKE] as $uid => $val) { $dbw->insert(AJAXCOMMENTS_TABLE, array('ac_type' => AJAXCOMMENTS_DATATYPE_LIKE, 'ac_parent' => $id, 'ac_user' => $uid, 'ac_page' => $page, 'ac_data' => $val)); } $this->output(" {$n} 'like' rows added for this comment\n"); } } }
public function triggerReindexing() { // FIXME: currently reindexing of only SpecialPromote data is impossible, some page must be indexed with it // so MainPage took the bullet, if in future search reindexing would be more selective, attempt to reindex only SpecialPromote data $article = new Article(Title::newMainPage()); ScribeEventProducerController::notifyPageHasChanged($article->getPage()); }
/** * @covers Title::exists */ public function testExists() { $title = Title::makeTitle(NS_PROJECT, 'New page'); $linkCache = LinkCache::singleton(); $article = new Article($title); $page = $article->getPage(); $page->doEditContent(new WikitextContent('Some [[link]]'), 'summary'); // Tell Title it doesn't know whether it exists $title->mArticleID = -1; // Tell the link cache it doesn't exists when it really does $linkCache->clearLink($title); $linkCache->addBadLinkObj($title); $this->assertEquals(false, $title->exists(), 'exists() should rely on link cache unless GAID_FOR_UPDATE is used'); $this->assertEquals(true, $title->exists(Title::GAID_FOR_UPDATE), 'exists() should re-query database when GAID_FOR_UPDATE is used'); }
/** * Replace fields in message (enclosed in single braces) * - fields can have a default value, eg {name|default} */ function replaceFields($text, $email) { // Scan all records of this type for the first containing matching email address $dbr = $this->db; $tbl = $dbr->tableName('templatelinks'); $type = $dbr->addQuotes($this->record); $res = $dbr->select($tbl, 'tl_from', "tl_namespace = 10 AND tl_title = {$type}", __METHOD__); while ($row = $dbr->fetchRow($res)) { $a = new Article(Title::newFromID($row[0])); $c = $a->getPage()->getContent()->getNativeData(); // Check if this records email address matches if (preg_match("|\\s*\\|\\s*\\w+\\s*=\\s*{$email}\\s*(?=[\\|\\}])|s", $c)) { // Extract all the fields from the content (should use examineBraces here) $this->args = array(); preg_match_all("|\\|\\s*(.+?)\\s*=\\s*(.*?)\\s*(?=[\\|\\}])|s", $c, $m); foreach ($m[1] as $i => $k) { $this->args[strtolower($k)] = $m[2][$i]; } // Replace any fields in the message text with our extracted args (should use wiki parser for this) $text = preg_replace_callback("|\\{(\\w+)(\\|(.+?))?\\}|s", array($this, 'replaceField'), $text); break; } } $dbr->freeResult($res); return $text; }