protected function getDetails() { $article = \Article::newFromTitle($this->commentTitle, \RequestContext::getMain()); $service = new \ArticleService($article); $snippet = $service->getTextSnippet(); return $snippet; }
public static function purgeMainPage($args) { if ($args['name'] === 'wgEnableNjordExt') { Article::newFromTitle(Title::newFromText(self::MAINPAGE_PAGE), RequestContext::getMain())->doPurge(); } return true; }
function wfTalkHereAjaxEditor( $page, $section, $returnto ) { global $wgRequest, $wgTitle, $wgOut; $title = Title::newFromText( $page ); if ( !$title ) { return false; } //fake editor environment $args = array( 'wpTalkHere' => '1', 'wpReturnTo' => $returnto, 'action' => 'edit', 'section' => $section ); $wgRequest = new FauxRequest( $args ); $wgTitle = $title; $article = Article::newFromTitle( $title, RequestContext::getMain() ); $editor = new TalkHereEditPage( $article ); //generate form $editor->importFormData( $wgRequest ); $editor->showEditForm(); $response = new AjaxResponse(); $response->addText( $wgOut->getHTML() ); $response->setCacheDuration( false ); //don't cache, because of tokens etc return $response; }
protected function runOnPageSet(ApiPageSet $pageSet) { $articles = array_map(function (Title $item) { return Article::newFromTitle($item, RequestContext::getMain()); }, $pageSet->getGoodTitles()); /** * @var Article $article */ foreach ($articles as $id => $article) { $d = $article->getParserOutput()->getProperty(PortableInfoboxDataService::INFOBOXES_PROPERTY_NAME); if (is_array($d)) { $inf = []; foreach (array_keys($d) as $k => $v) { $inf[$k] = []; } $pageSet->getResult()->setIndexedTagName($inf, 'infobox'); $pageSet->getResult()->addValue(['query', 'pages', $id], 'infoboxes', $inf); foreach ($d as $count => $infobox) { $s = isset($infobox['sources']) ? $infobox['sources'] : []; $pageSet->getResult()->addValue(['query', 'pages', $id, 'infoboxes', $count], 'id', $count); $pageSet->getResult()->setIndexedTagName($s, "source"); $pageSet->getResult()->addValue(['query', 'pages', $id, 'infoboxes', $count], 'sources', $s); } } } }
protected function getDetails() { $article = \Article::newFromTitle($this->postTitle, \RequestContext::getMain()); $service = new \ArticleService($article); // Include +3 characters here for the ellipsis added when we have to truncate $snippet = $service->getTextSnippet($length = 303, $breakLimit = 500); return $snippet; }
/** * Returns infobox data * * @return array in format [ 'data' => [], 'sources' => [] ] or [] will be returned */ public function getData() { if ($this->title && $this->title->exists()) { $parserOutput = Article::newFromTitle($this->title, RequestContext::getMain())->getParserOutput(); $data = $parserOutput ? $parserOutput->getProperty(self::INFOBOXES_PROPERTY_NAME) : false; //return empty [] to prevent false on non existing infobox data return $data ? $data : []; } return []; }
/** * Purges the cache of a page */ public function execute() { global $wgUser; $params = $this->extractRequestParams(); if (!$wgUser->isAllowed('purge') && !$this->getMain()->isInternalMode() && !$this->getMain()->getRequest()->wasPosted()) { $this->dieUsageMsg(array('mustbeposted', $this->getModuleName())); } $forceLinkUpdate = $params['forcelinkupdate']; $result = array(); foreach ($params['titles'] as $t) { $r = array(); $title = Title::newFromText($t); if (!$title instanceof Title) { $r['title'] = $t; $r['invalid'] = ''; $result[] = $r; continue; } ApiQueryBase::addTitleInfo($r, $title); if (!$title->exists()) { $r['missing'] = ''; $result[] = $r; continue; } $context = $this->createContext(); $context->setTitle($title); $article = Article::newFromTitle($title, $context); $article->doPurge(); // Directly purge and skip the UI part of purge(). $r['purged'] = ''; if ($forceLinkUpdate) { if (!$wgUser->pingLimiter()) { global $wgParser, $wgEnableParserCache; $popts = new ParserOptions(); $p_result = $wgParser->parse($article->getContent(), $title, $popts); # Update the links tables $u = new LinksUpdate($title, $p_result); $u->doUpdate(); $r['linkupdate'] = ''; if ($wgEnableParserCache) { $pcache = ParserCache::singleton(); $pcache->save($p_result, $article, $popts); } } else { $this->setWarning($this->parseMsg(array('actionthrottledtext'))); $forceLinkUpdate = false; } } $result[] = $r; } $apiResult = $this->getResult(); $apiResult->setIndexedTagName($result, 'page'); $apiResult->addValue(null, $this->getModuleName(), $result); }
/** * @param $out OutputPage * @param $sk Skin * @return bool */ function fnLastModified(&$out, &$sk) { global $wgLastModifiedRange; $context = $out->getContext(); $title = $context->getTitle(); $article = Article::newFromTitle($title, $context); if ($article && ($title instanceof Title && $title->getNamespace() == 0)) { $timestamp = wfTimestamp(TS_UNIX, $article->getTimestamp()); $out->addMeta('http:last-modified', date('r', $timestamp)); $out->addMeta('last-modified-timestamp', $timestamp); $out->addMeta('last-modified-range', $wgLastModifiedRange); $out->addModules('last.modified'); } return true; }
public function prepareDocumentation() { global $wgOut, $wgParser, $wgScriptPath, $wgTitle, $wgUser; /** * We need a lot of stuff from our PonyDocs extension! */ $ponydocs = PonyDocsWiki::getInstance($this->data['selectedProduct']); $this->data['manuals'] = $ponydocs->getManualsForProduct($this->data['selectedProduct']); /** * Adjust content actions as needed, such as add 'view all' link. */ $this->contentActions(); $this->navURLS(); /** * Possible topic syntax we must handle: * * Documentation:<topic> *Which may include a version tag at the end, we don't care about this. * Documentation:<productShortName>:<manualShortName>:<topic>:<version> * Documentation:<productShortName>:<manualShortName> */ /** * Based on the name; i.e. 'Documentation:Product:Manual:Topic' we need to parse it out and store the manual name and * the topic name as parameters. We store manual in 'manualname' and topic in 'topicname'. Special handling * needs to be done for versions and TOC? * * 0=NS (Documentation) * 1=Product (Short name) * 2=Manual (Short name) * 3=Topic * 4=Version */ $pManual = null; $pieces = explode(':', $wgTitle->__toString()); $helpClass = ''; /** * This isn't a specific topic+version -- handle appropriately. */ if (sizeof($pieces) < 4) { if (!strcmp(PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':' . $this->data['selectedProduct'] . PONYDOCS_PRODUCTVERSION_SUFFIX, $wgTitle->__toString())) { $this->data['titletext'] = 'Versions Management - ' . $this->data['selectedProduct']; $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>* Use {{#version:name|status}} to define a new version,' . ' where status is released, unreleased, or preview.' . ' Valid chars in version name are A-Z, 0-9, period, comma, and dash.</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>* Use {{#versiongroup:name|message}} to set a banner' . ' message that will appear on every topic in every version following the versiongroup.</i></span>'); } elseif (!strcmp(PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':' . $this->data['selectedProduct'] . PONYDOCS_PRODUCTMANUAL_SUFFIX, $wgTitle->__toString())) { $this->data['titletext'] = 'Manuals Management - ' . $this->data['selectedProduct']; $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Use {{#manual:manualShortName|displayName|categories}} to define a new manual.'); $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Prepend manual short name with ' . PONYDOCS_PRODUCT_STATIC_PREFIX . ' to define a static manual.' . '</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '">' . '<i>* If you omit display name, the short name will be used in links.</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '">' . '<i>* Categories is a comma-separated list of categories</i></span>'); } elseif (!strcmp(PONYDOCS_DOCUMENTATION_PRODUCTS_TITLE, $wgTitle->__toString())) { $this->data['titletext'] = 'Products Management'; $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Use {{#product:productShortName|displayName|description|parent|categories}} to define a new product.' . '</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Prepend product short name with ' . PONYDOCS_PRODUCT_STATIC_PREFIX . ' to define a static product.' . '</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* displayName, description, parent, and categories can be left empty.</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '">' . '<i>* If you leave displayName empty, productShortName will be used in links.</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '">' . '<i>* Categories is a comma-separated list of categories.</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '">' . '<i>* Each product here <b>MUST</b> also be listed in $ponyDocsProductsList,' . ' usually configured in LocalSettings.php.</i></span>'); } elseif (preg_match('/(.*)TOC(.*)/', $pieces[2], $matches)) { $this->data['titletext'] = $matches[1] . ' Table of Contents Page'; $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Optionally start this page with {{#manualDescription:Manual Description.}}' . ' followed by two line-breaks to set a manual description for the Manual this TOC belongs to.' . '</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Topics are grouped into sections by section headers.' . ' Any line without markup is considered a section header.' . ' A section header is required before the the first topic tag.</i></span>'); $wgOut->addHTML('<br><span class="' . $helpClass . '"><i>' . '* Topic tags must be part of an unordered list.' . ' Use {{#topic:Display Name}} after a * (list item markup) to create topics.</i></span>'); } elseif (sizeof($pieces) >= 2 && PonyDocsProductManual::IsManual($pieces[1], $pieces[2])) { $pManual = PonyDocsProductManual::GetManualByShortName($pieces[1], $pieces[2]); if ($pManual) { $this->data['manualname'] = $pManual->getLongName(); } else { $this->data['manualname'] = $pieces[2]; } $this->data['topicname'] = $pieces[3]; $this->data['titletext'] = $pieces[2]; } else { $this->data['topicname'] = $pieces[2]; } } else { $pManual = PonyDocsProductManual::GetManualByShortName($pieces[1], $pieces[2]); if ($pManual) { $this->data['manualname'] = $pManual->getLongName(); } else { $this->data['manualname'] = $pieces[2]; } $this->data['topicname'] = $pieces[3]; $h1 = PonyDocsTopic::FindH1ForTitle($wgTitle->__toString()); if ($h1 !== FALSE) { $this->data['titletext'] = $h1; } } /** * Get current topic, passing it our global Article object. * From this, generate our TOC based on the current topic selected. * This generates our left sidebar TOC plus our prev/next/start navigation links. * This should ONLY be done if we actually are WITHIN a manual, so special pages like TOC, etc. should not do this! */ if ($pManual) { $p = PonyDocsProduct::GetProductByShortName($this->data['selectedProduct']); $v = PonyDocsProductVersion::GetVersionByName($this->data['selectedProduct'], $this->data['selectedVersion']); $toc = new PonyDocsTOC($pManual, $v, $p); list($this->data['manualtoc'], $this->data['tocprev'], $this->data['tocnext'], $this->data['tocstart']) = $toc->loadContent(); $this->data['toctitle'] = $toc->getTOCPageTitle(); } /** * Create a PonyDocsTopic from our article. From this we populate: * * topicversions: List of version names topic is tagged with. * inlinetoc: Inline TOC shown above article body. * catcode: Special category code. * cattext: Category description. * basetopicname: Base topic name (w/o :<version> at end). * basetopiclink: Link to special TopicList page to view all same topics. */ $context = $this->skin->getContext(); $article = Article::newFromTitle($context->getTitle(), $context); $topic = new PonyDocsTopic($article); if (preg_match('/^' . PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':(.*):(.*):(.*):(.*)/', $wgTitle->__toString()) || preg_match('/^' . PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':.*:.*TOC.*/', $wgTitle->__toString())) { $this->data['topicversions'] = PonyDocsWiki::getVersionsForTopic($topic); $this->data['inlinetoc'] = $topic->getSubContents(); $this->data['versionclasses'] = $topic->getVersionClasses(); $this->data['versionGroupMessage'] = $this->data['pVersion']->getVersionGroupMessage(); /** * Sort of a hack -- we only use this right now when loading a TOC page which is new/does not exist. * When this happens a hook (AlternateEdit) adds an inline script to define this JS function, * which populates the edit box with the proper Category tag based on the currently selected version. */ $this->data['body_onload'] = 'ponyDocsOnLoad();'; switch ($this->data['catcode']) { case 0: $this->data['cattext'] = 'Applies to latest version which is currently unreleased.'; break; case 1: $this->data['cattext'] = 'Applies to latest version.'; break; case 2: $this->data['cattext'] = 'Applies to released version(s) but not the latest.'; break; case 3: $this->data['cattext'] = 'Applies to latest preview version.'; break; case 4: $this->data['cattext'] = 'Applies to one or more preview version(s) only.'; break; case 5: $this->data['cattext'] = 'Applies to one or more unreleased version(s) only.'; break; case -2: /** Means its not a a title name which should be checked. */ break; default: $this->data['cattext'] = 'Does not apply to any version of PonyDocs.'; break; } } $this->data['basetopicname'] = $topic->getBaseTopicName(); if (strlen($this->data['basetopicname'])) { $this->data['basetopiclink'] = '<a href="' . $wgScriptPath . '/index.php?title=Special:TopicList&topic=' . $this->data['basetopicname'] . '">View All</a>'; } $temp = PonyDocsTopic::FindH1ForTitle(PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':' . $topic->getTitle()->getText()); if ($temp !== false) { // We got an H1! $this->data['pagetitle'] = $temp; } }
/** * Perform reverse parsing on given HTML (when needed) */ private static function resolveWikitext($content, $mode, $page, $method, $section) { global $wgRequest, $wgTitle, $wgOut, $wgEnableSlowPagesBlacklistExt; wfProfileIn(__METHOD__); if (!empty($wgEnableSlowPagesBlacklistExt)) { global $wgSlowPagesBlacklist; if (in_array($wgTitle->getFullURL(), $wgSlowPagesBlacklist)) { wfProfileOut(__METHOD__); return ['html' => wfMessage('slowpagesblacklist-preview-unavailable')->plain(), 'catbox' => '', 'interlanglinks' => '']; } } if ($wgTitle && class_exists($page)) { $pageObj = new $page(); if (is_a($pageObj, 'SpecialCustomEditPage')) { $wikitext = $pageObj->getWikitextFromRequestForPreview($wgRequest->getVal('title', 'empty')); $service = new EditPageService($wgTitle); $html = $pageObj->getOwnPreviewDiff($wikitext, $method); /** * @val String $type - partial or full - whether to return full skin along with css and js or just a content */ $type = $wgRequest->getVal('type', 'partial'); $res = []; if ($html === false) { $html = ''; if ($method == 'preview') { list($html, $catbox, $interlanglinks) = $service->getPreview($wikitext); // allow extensions to modify preview (BugId:8354) - this hook should only be run on article's content wfRunHooks('OutputPageBeforeHTML', array(&$wgOut, &$html)); if (F::app()->checkSkin('wikiamobile')) { if ($type === 'full') { $res['html'] = F::app()->renderView('WikiaMobileService', 'preview', ['content' => $html, 'section' => $section]); } else { $res['html'] = $html; } } elseif (F::app()->checkSkin('venus')) { if ($type === 'full') { $res['html'] = F::app()->renderView('VenusController', 'preview', ['content' => $html, 'section' => $section]); } else { $res['html'] = $html; } } else { // add page title when not in section edit mode if ($section === '') { $html = '<h1 class="pagetitle">' . $wgTitle->getPrefixedText() . '</h1>' . $html; } // allow extensions to modify preview (BugId:6721) wfRunHooks('EditPageLayoutModifyPreview', array($wgTitle, &$html, $wikitext)); /** * bugid: 11407 * Provide an appropriate preview for a redirect, based on wikitext, not revision. */ if (preg_match('/^#REDIRECT /m', $wikitext)) { $article = Article::newFromTitle($wgTitle, RequestContext::getMain()); $matches = array(); if (preg_match_all('/^#REDIRECT \\[\\[([^\\]]+)\\]\\]/Um', $wikitext, $matches)) { $redirectTitle = Title::newFromText($matches[1][0]); if ($redirectTitle) { $html = $article->viewRedirect(array($redirectTitle)); } else { \Wikia\Logger\WikiaLogger::instance()->info('No redirect title', ['titleText' => $matches[1][0]]); $html = ''; } } } $html = '<div class="WikiaArticle">' . $html . '</div>'; $res = ['html' => $html, 'catbox' => $catbox, 'interlanglinks' => $interlanglinks]; } } elseif ($method == 'diff') { $res['html'] = $service->getDiff($wikitext, intval($section)); } } wfProfileOut(__METHOD__); return $res; } } wfProfileOut(__METHOD__); return ['html' => '']; }
/** * skinTemplateOutputPageBeforeExec hook * * Cooks the skin template Seizam-Style! * * @param SkinSkinzam $skin * @param SkinzamTemplate $tpl */ public static function skinTemplateOutputPageBeforeExec(&$skin, &$tpl) { $background['url'] = false; $navigation['content'] = false; $title = $skin->getRelevantTitle(); $ns = $title->getNamespace(); if (WpPage::isInWikiplaceNamespaces($ns)) { $explosion = WpWikiplace::explodeWikipageKey($title->getText(), $ns); $wikiplaceKey = $explosion[0]; // Wikiplace Background?g|png|gif)$/i'; $background['url'] = self::getBackgroundUrlForWikiPlace($wikiplaceKey); // Wikiplace Navigation Menu $navigationKey = $wikiplaceKey . '/' . WPNAVIGATIONKEY; /** @todo i18n */ $navigationTitle = Title::newFromText($navigationKey, NS_WIKIPLACE); $navigationPage = WikiPage::factory($navigationTitle); $navigationText = $navigationPage->getText(); if ($navigationText) { $navigationArticle = Article::newFromTitle($navigationTitle, $skin->getContext()); $navigation['content'] = $navigationArticle->getOutputFromWikitext($navigationText)->getText(); } } else { $background['url'] = self::getBackgroundUrlForOther($title); } $tpl->set('wp_background', $background); $tpl->set('wp_navigation', $navigation); return true; }
public function execute() { global $wgRequestTime; if (!$this->enabled) { $this->error("Nothing to do -- \$wgUseFileCache is disabled.", true); } $start = $this->getOption('start', "0"); if (!ctype_digit($start)) { $this->error("Invalid value for start parameter.", true); } $start = intval($start); $end = $this->getOption('end', "0"); if (!ctype_digit($end)) { $this->error("Invalid value for end parameter.", true); } $end = intval($end); $this->output("Building content page file cache from page {$start}!\n"); $dbr = $this->getDB(DB_REPLICA); $overwrite = $this->getOption('overwrite', false); $start = $start > 0 ? $start : $dbr->selectField('page', 'MIN(page_id)', false, __METHOD__); $end = $end > 0 ? $end : $dbr->selectField('page', 'MAX(page_id)', false, __METHOD__); if (!$start) { $this->error("Nothing to do.", true); } $_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client # Do remaining chunk $end += $this->mBatchSize - 1; $blockStart = $start; $blockEnd = $start + $this->mBatchSize - 1; $dbw = $this->getDB(DB_MASTER); // Go through each page and save the output while ($blockEnd <= $end) { // Get the pages $res = $dbr->select('page', ['page_namespace', 'page_title', 'page_id'], ['page_namespace' => MWNamespace::getContentNamespaces(), "page_id BETWEEN {$blockStart} AND {$blockEnd}"], __METHOD__, ['ORDER BY' => 'page_id ASC', 'USE INDEX' => 'PRIMARY']); $this->beginTransaction($dbw, __METHOD__); // for any changes foreach ($res as $row) { $rebuilt = false; $title = Title::makeTitleSafe($row->page_namespace, $row->page_title); if (null == $title) { $this->output("Page {$row->page_id} has bad title\n"); continue; // broken title? } $context = new RequestContext(); $context->setTitle($title); $article = Article::newFromTitle($title, $context); $context->setWikiPage($article->getPage()); // If the article is cacheable, then load it if ($article->isFileCacheable(HTMLFileCache::MODE_REBUILD)) { $viewCache = new HTMLFileCache($title, 'view'); $historyCache = new HTMLFileCache($title, 'history'); if ($viewCache->isCacheGood() && $historyCache->isCacheGood()) { if ($overwrite) { $rebuilt = true; } else { $this->output("Page '{$title}' (id {$row->page_id}) already cached\n"); continue; // done already! } } MediaWiki\suppressWarnings(); // header notices // Cache ?action=view $wgRequestTime = microtime(true); # bug 22852 ob_start(); $article->view(); $context->getOutput()->output(); $context->getOutput()->clearHTML(); $viewHtml = ob_get_clean(); $viewCache->saveToFileCache($viewHtml); // Cache ?action=history $wgRequestTime = microtime(true); # bug 22852 ob_start(); Action::factory('history', $article, $context)->show(); $context->getOutput()->output(); $context->getOutput()->clearHTML(); $historyHtml = ob_get_clean(); $historyCache->saveToFileCache($historyHtml); MediaWiki\restoreWarnings(); if ($rebuilt) { $this->output("Re-cached page '{$title}' (id {$row->page_id})..."); } else { $this->output("Cached page '{$title}' (id {$row->page_id})..."); } $this->output("[view: " . strlen($viewHtml) . " bytes; " . "history: " . strlen($historyHtml) . " bytes]\n"); } else { $this->output("Page '{$title}' (id {$row->page_id}) not cacheable\n"); } } $this->commitTransaction($dbw, __METHOD__); // commit any changes (just for sanity) $blockStart += $this->mBatchSize; $blockEnd += $this->mBatchSize; } $this->output("Done!\n"); }
public function getAsJson() { $articleId = $this->getRequest()->getInt(self::SIMPLE_JSON_ARTICLE_ID_PARAMETER_NAME, NULL); $articleTitle = $this->getRequest()->getVal(self::SIMPLE_JSON_ARTICLE_TITLE_PARAMETER_NAME, NULL); $redirect = $this->request->getVal('redirect'); if (!empty($articleId) && !empty($articleTitle)) { throw new BadRequestApiException('Can\'t use id and title in the same request'); } if (empty($articleId) && empty($articleTitle)) { throw new BadRequestApiException('You need to pass title or id of an article'); } if (!empty($articleId)) { $article = Article::newFromID($articleId); } else { $title = Title::newFromText($articleTitle, NS_MAIN); if ($title instanceof Title && $title->exists()) { $article = Article::newFromTitle($title, RequestContext::getMain()); } } if (empty($article)) { throw new NotFoundApiException("Unable to find any article"); } if ($redirect !== 'no' && $article->getPage()->isRedirect()) { // false, Title object of local target or string with URL $followRedirect = $article->getPage()->followRedirect(); if ($followRedirect && !is_string($followRedirect)) { $article = Article::newFromTitle($followRedirect, RequestContext::getMain()); } } //Response is based on wikiamobile skin as this already removes inline style //and make response smaller RequestContext::getMain()->setSkin(Skin::newFromKey('wikiamobile')); global $wgArticleAsJson; $wgArticleAsJson = true; $parsedArticle = $article->getParserOutput(); if ($parsedArticle instanceof ParserOutput) { $articleContent = json_decode($parsedArticle->getText()); } else { throw new ArticleAsJsonParserException('Parser is currently not available'); } $wgArticleAsJson = false; $categories = []; foreach (array_keys($parsedArticle->getCategories()) as $category) { $categoryTitle = Title::newFromText($category, NS_CATEGORY); if ($categoryTitle) { $categories[] = ['title' => $categoryTitle->getText(), 'url' => $categoryTitle->getLocalURL()]; } } $result = ['content' => $articleContent->content, 'media' => $articleContent->media, 'users' => $articleContent->users, 'categories' => $categories]; $this->setResponseData($result, '', self::SIMPLE_JSON_VARNISH_CACHE_EXPIRATION); }
public function execute() { $user = $this->getUser(); $params = $this->extractRequestParams(); if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) { $this->dieUsageMsg('missingtext'); } $titleObj = Title::newFromText($params['title']); if (!$titleObj || $titleObj->isExternal()) { $this->dieUsageMsg(array('invalidtitle', $params['title'])); } $apiResult = $this->getResult(); if ($params['redirect']) { if ($titleObj->isRedirect()) { $oldTitle = $titleObj; $titles = Title::newFromRedirectArray(Revision::newFromTitle($oldTitle)->getText(Revision::FOR_THIS_USER)); // array_shift( $titles ); $redirValues = array(); foreach ($titles as $id => $newTitle) { if (!isset($titles[$id - 1])) { $titles[$id - 1] = $oldTitle; } $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText()); $titleObj = $newTitle; } $apiResult->setIndexedTagName($redirValues, 'r'); $apiResult->addValue(null, 'redirects', $redirValues); } } if ($params['createonly'] && $titleObj->exists()) { $this->dieUsageMsg('createonly-exists'); } if ($params['nocreate'] && !$titleObj->exists()) { $this->dieUsageMsg('nocreate-missing'); } // Now let's check whether we're even allowed to do this $errors = $titleObj->getUserPermissionsErrors('edit', $user); if (!$titleObj->exists()) { $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $user)); } if (count($errors)) { $this->dieUsageMsg($errors[0]); } $articleObj = Article::newFromTitle($titleObj, $this->getContext()); $toMD5 = $params['text']; if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) { // For non-existent pages, Article::getContent() // returns an interface message rather than '' // We do want getContent()'s behavior for non-existent // MediaWiki: pages, though if ($articleObj->getID() == 0 && $titleObj->getNamespace() != NS_MEDIAWIKI) { $content = ''; } else { $content = $articleObj->getContent(); } if (!is_null($params['section'])) { // Process the content for section edits global $wgParser; $section = intval($params['section']); $content = $wgParser->getSection($content, $section, false); if ($content === false) { $this->dieUsage("There is no section {$section}.", 'nosuchsection'); } } $params['text'] = $params['prependtext'] . $content . $params['appendtext']; $toMD5 = $params['prependtext'] . $params['appendtext']; } if ($params['undo'] > 0) { if ($params['undoafter'] > 0) { if ($params['undo'] < $params['undoafter']) { list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']); } $undoafterRev = Revision::newFromID($params['undoafter']); } $undoRev = Revision::newFromID($params['undo']); if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) { $this->dieUsageMsg(array('nosuchrevid', $params['undo'])); } if ($params['undoafter'] == 0) { $undoafterRev = $undoRev->getPrevious(); } if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) { $this->dieUsageMsg(array('nosuchrevid', $params['undoafter'])); } if ($undoRev->getPage() != $articleObj->getID()) { $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText())); } if ($undoafterRev->getPage() != $articleObj->getID()) { $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText())); } $newtext = $articleObj->getUndoText($undoRev, $undoafterRev); if ($newtext === false) { $this->dieUsageMsg('undo-failure'); } $params['text'] = $newtext; // If no summary was given and we only undid one rev, // use an autosummary if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) { $params['summary'] = wfMsgForContent('undo-summary', $params['undo'], $undoRev->getUserText()); } } // See if the MD5 hash checks out if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) { $this->dieUsageMsg('hashcheckfailed'); } // EditPage wants to parse its stuff from a WebRequest // That interface kind of sucks, but it's workable $requestArray = array('wpTextbox1' => $params['text'], 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => ''); if (!is_null($params['summary'])) { $requestArray['wpSummary'] = $params['summary']; } if (!is_null($params['sectiontitle'])) { $requestArray['wpSectionTitle'] = $params['sectiontitle']; } // Watch out for basetimestamp == '' // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') { $requestArray['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']); } else { $requestArray['wpEdittime'] = $articleObj->getTimestamp(); } if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') { $requestArray['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']); } else { $requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime } if ($params['minor'] || !$params['notminor'] && $user->getGlobalPreference('minordefault')) { $requestArray['wpMinoredit'] = ''; } if ($params['recreate']) { $requestArray['wpRecreate'] = ''; } if (!is_null($params['section'])) { $section = intval($params['section']); if ($section == 0 && $params['section'] != '0' && $params['section'] != 'new') { $this->dieUsage("The section parameter must be set to an integer or 'new'", "invalidsection"); } $requestArray['wpSection'] = $params['section']; } else { $requestArray['wpSection'] = ''; } $watch = $this->getWatchlistValue($params['watchlist'], $titleObj); // Deprecated parameters if ($params['watch']) { $watch = true; } elseif ($params['unwatch']) { $watch = false; } if ($watch) { $requestArray['wpWatchthis'] = ''; } global $wgTitle, $wgRequest; $req = new DerivativeRequest($this->getRequest(), $requestArray, true); // Some functions depend on $wgTitle == $ep->mTitle // TODO: Make them not or check if they still do $wgTitle = $titleObj; $ep = new EditPage($articleObj); $ep->setContextTitle($titleObj); $ep->importFormData($req); // Run hooks // Handle APIEditBeforeSave parameters $r = array(); if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) { if (count($r)) { $r['result'] = 'Failure'; $apiResult->addValue(null, $this->getModuleName(), $r); return; } else { $this->dieUsageMsg('hookaborted'); } } // Do the actual save $oldRevId = $articleObj->getRevIdFetched(); $result = null; // Fake $wgRequest for some hooks inside EditPage // @todo FIXME: This interface SUCKS $oldRequest = $wgRequest; $wgRequest = $req; $status = $ep->internalAttemptSave($result, $user->isAllowed('bot') && $params['bot']); $wgRequest = $oldRequest; global $wgMaxArticleSize; switch ($status->value) { case EditPage::AS_HOOK_ERROR: case EditPage::AS_HOOK_ERROR_EXPECTED: $this->dieUsageMsg('hookaborted'); case EditPage::AS_IMAGE_REDIRECT_ANON: $this->dieUsageMsg('noimageredirect-anon'); case EditPage::AS_IMAGE_REDIRECT_LOGGED: $this->dieUsageMsg('noimageredirect-logged'); case EditPage::AS_SPAM_ERROR: $this->dieUsageMsg(array('spamdetected', $result['spam'])); case EditPage::AS_FILTERING: $this->dieUsageMsg('filtered'); case EditPage::AS_BLOCKED_PAGE_FOR_USER: $this->dieUsageMsg('blockedtext'); case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED: case EditPage::AS_CONTENT_TOO_BIG: $this->dieUsageMsg(array('contenttoobig', $wgMaxArticleSize)); case EditPage::AS_READ_ONLY_PAGE_ANON: $this->dieUsageMsg('noedit-anon'); case EditPage::AS_READ_ONLY_PAGE_LOGGED: $this->dieUsageMsg('noedit'); case EditPage::AS_READ_ONLY_PAGE: $this->dieReadOnly(); case EditPage::AS_RATE_LIMITED: $this->dieUsageMsg('actionthrottledtext'); case EditPage::AS_ARTICLE_WAS_DELETED: $this->dieUsageMsg('wasdeleted'); case EditPage::AS_NO_CREATE_PERMISSION: $this->dieUsageMsg('nocreate-loggedin'); case EditPage::AS_BLANK_ARTICLE: $this->dieUsageMsg('blankpage'); case EditPage::AS_CONFLICT_DETECTED: $this->dieUsageMsg('editconflict'); // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary case EditPage::AS_TEXTBOX_EMPTY: $this->dieUsageMsg('emptynewsection'); case EditPage::AS_SUCCESS_NEW_ARTICLE: $r['new'] = ''; case EditPage::AS_SUCCESS_UPDATE: $r['result'] = 'Success'; $r['pageid'] = intval($titleObj->getArticleID()); $r['title'] = $titleObj->getPrefixedText(); $newRevId = $articleObj->getLatest(); if ($newRevId == $oldRevId) { $r['nochange'] = ''; } else { $r['oldrevid'] = intval($oldRevId); $r['newrevid'] = intval($newRevId); $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $articleObj->getTimestamp()); wfRunHooks('ApiEditPage::SuccessfulApiEdit', [$newRevId]); wfSetupSession(); } break; case EditPage::AS_SUMMARY_NEEDED: $this->dieUsageMsg('summaryrequired'); case EditPage::AS_END: // $status came from WikiPage::doEdit() $errors = $status->getErrorsArray(); $this->dieUsageMsg($errors[0]); // TODO: Add new errors to message map break; default: if (is_string($status->value) && strlen($status->value)) { $this->dieUsage("An unknown return value was returned by Editpage. The code returned was \"{$status->value}\"", $status->value); } else { $this->dieUsageMsg(array('unknownerror', $status->value)); } } $apiResult->addValue(null, $this->getModuleName(), $r); }
function execute($par) { global $wgRequest, $wgSitename, $wgLanguageCode, $IP; global $wgDeferredUpdateList, $wgOut, $wgUser, $wgServer; $this->setHeaders(); if ($wgUser->isBlocked()) { $wgOut->blockedPage(); return; } $target = isset($par) ? $par : $wgRequest->getVal('target'); if (!$target) { $wgOut->addHTML(wfMsg('notarget')); return; } $titleObj = Title::newFromUrl(urldecode($target)); if (!$titleObj || !$titleObj->exists()) { $wgOut->addHTML('Error: bad target'); return; } $whow = WikihowArticleEditor::newFromTitle($titleObj); $rev = Revision::newFromTitle($titleObj); $article = Article::newFromTitle($titleObj, $this->getContext()); $text = $rev->getText(); if ($wgRequest->wasPosted()) { // protect from users who can't edit if (!$titleObj->userCan('edit')) { $wgOut->readOnlyPage($article->getContent(), true); return; } // construct the related wikihow section $rel_array = split("\\|", $wgRequest->getVal('related_list')); $result = ""; foreach ($rel_array as $rel) { $rel = urldecode(trim($rel)); if (!$rel) { continue; } $result .= "* [[" . $rel . "|" . wfMsg('howto', $rel) . "]]\n"; } if (strpos($text, "\n== " . wfMsg('relatedwikihows') . " ==\n") !== false) { // no newline neeeded to start with $result = "== " . wfMsg('relatedwikihows') . " ==\n" . $result; } else { $result = "\n== " . wfMsg('relatedwikihows') . " ==\n" . $result; } $text = ""; $index = 0; $content = $article->getContent(); $last_heading = ""; $inserted = false; $section = -1; $ext_links_section = -1; if ($article->getSection($content, $index) == null) { $index++; // weird where there's no summary } while (($sectiontext = $article->getSection($content, $index)) != null) { $i = strpos($sectiontext, "\n"); if ($i > 0) { $heading = substr($sectiontext, 0, $i); $heading = trim(str_replace("==", "", $heading)); if ($heading == wfMsg('relatedwikihows')) { $section = $index; break; } if ($heading == wfMsg('sources')) { $ext_links_section = $index; } } $index++; } $text = $result; $tail = ''; $text = $article->getContent(); // figure out which section to replace if related wikihows // don't exist $just_append = false; if ($section <= 0) { if ($ext_links_section > 0) { // related wikihows have to go before external links $section = $ext_links_section; // glue external links and related wikihows together // and replace external links $result = $result . "\n" . $article->getSection($content, $section); } else { $section = $index; $result = "\n" . $result; // make it a bit prettier $just_append = true; } } else { $s = $article->getSection($content, $section); $lines = split("\n", $s); for ($i = 1; $i < sizeof($lines); $i++) { $line = $lines[$i]; if (strpos($line, "*") !== 0) { // not a list item $tail .= "\n" . $line; } } } $result .= $tail; $summary = ''; if (!$just_append) { $text = $article->replaceSection($section, $result, $summary); } else { $text = $text . $result; } $watch = false; $minor = false; $forceBot = false; if ($wgUser->getID() > 0) { $watch = $wgUser->isWatched($titleObj); } $summary = wfMsg('relatedwikihows'); // summary for the edit $article->updateArticle($text, $summary, $minor, $watch, $forceBot); $this->getContext()->getOutput()->redirect($article->getTitle()->getFullURL()); } // MW should handle editing extensions better, duplication of code sucks if ($titleObj->isProtected('edit')) { if ($titleObj->isSemiProtected()) { $notice = wfMsg('semiprotectedpagewarning'); } else { $notice = wfMsg('protectedpagewarning'); } $wgOut->addWikiText($notice); } $relatedHTML = ""; $text = $article->getContent(); $relwh = $whow->getSection("related wikihows"); if ($relwh != "") { $related_vis = "show"; $relatedHTML = $relwh; $relatedHTML = str_replace("*", "", $relatedHTML); $relatedHTML = str_replace("[[", "", $relatedHTML); $relatedHTML = str_replace("]]", "", $relatedHTML); $lines = split("\n", $relatedHTML); $relatedHTML = ""; foreach ($lines as $line) { $xx = strpos($line, "|"); if ($xx !== false) { $line = substr($line, 0, $xx); } $line = trim($line); if ($line == "") { continue; } $relatedHTML .= "<option value=\"" . str_replace("\"", ""e", $line) . "\">{$line}</option>\n"; } } $me = Title::makeTitle(NS_SPECIAL, "ManageRelated"); $cssFile = wfGetPad('/extensions/min/f/extensions/wikihow/ManageRelated/managerelated.css?rev=') . WH_SITEREV; $jsFile = wfGetPad('/extensions/min/?f=extensions/wikihow/ManageRelated/managerelated.js,extensions/wikihow/common/jquery.scrollTo/jquery.scrollTo.js&rev=') . WH_SITEREV; $targetEnc = htmlspecialchars($target, ENT_QUOTES); $wgOut->addHTML(<<<EOHTML \t<style type='text/css' media='all'>/*<![CDATA[*/ @import '{$cssFile}'; /*]]>*/</style> \t<script type='text/javascript'> \t\tvar wgServer = "{$wgServer}"; \t</script> \t<script type='text/javascript' src='{$jsFile}'></script> \t<form method='POST' action='{$me->getFullURL()}' name='temp' onsubmit='return WH.ManageRelated.check();'> \tYou are currently editing related wikiHows for the article \t<a href='{$titleObj->getFullURL()}' target='new'>How to {$titleObj->getFullText()}</a>.<br/> \t<table style='padding: 10px 5px 25px 5px;'> \t<tr><td valign='top'> \t<ol><li>Enter some search terms to find related wikiHows and press 'Search'.</li></ol> \t<input type='hidden' name='target' value='{$targetEnc}'/> \t<input type='hidden' name='related_list'/> \t<input type='text' name='q'/> \t<input type='button' class='btn' onclick='WH.ManageRelated.check();' value='Search' style="margin-top: 5px;" /> \t</td> \t<td valign='top' style='padding-left: 10px; border-left: 1px solid #ddd;'> \t<div style='width: 175px; float: left;'> \t<u>Related wikiHows</u> \t</div> \t<div style='width: 175px; float: right; text-align: right; margin-bottom:5px;'> \tMove <input type=button value='Up ↑' class='btn' onclick='WH.ManageRelated.moveRelated("up");'/> <input type=button value='Down ↓' class='btn' onclick='WH.ManageRelated.moveRelated("down");'/> \t</div> \t<select size='5' id='related' ondblclick='WH.ManageRelated.viewRelated();'> \t\t{$relatedHTML} \t</select> \t<br/><br/> \t<div style='width: 205px; float: left; text-align: left; font-size: xx-small; font-style: italic;'> \t(double click item to open wikiHow in new window) \t</div> \t<div style='width: 175px; float: right; text-align: right;'> \t<input type=button onclick='WH.ManageRelated.removeRelated();' value='Remove' class='btn'/> \t<input type=button value='Save' onclick='WH.ManageRelated.submitForm();' class='btn'/> \t</div> \t</td></tr> \t<tr> \t\t<td id='lucene_results' colspan='2' valign='top' class='lucene_results' style="padding-top: 10px;"></td> \t</tr><tr> \t\t<td id='previewold' colspan='2' valign='top'></td> \t</tr></table> \t</form> \t<div id='preview'></div> EOHTML ); }
/** * @brief Adds the properties, hooks into SMWStore::updateDataBefore. * * @param SMWStore $store, SMWSemanticData $newData * * @return true * */ public function sespUpdateDataBefore($store, $data) { global $sespSpecialProperties, $wgDisableCounters; // just some compat mode global $smwgPageSpecialProperties2; if (isset($smwgPageSpecialProperties2) && !isset($sespSpecialProperties)) { $sespSpecialProperties = $smwgPageSpecialProperties2; } /* Get array of properties to set */ if (!isset($sespSpecialProperties)) { wfDebug(__METHOD__ . ": SESP array is not specified, please add the following\n"); wfDebug("variables to your LocalSettings.php:\n"); wfDebug("\$sespSpecialProperties\n"); return true; } /* Get current title and article */ $title = $data->getSubject()->getTitle(); $article = Article::newFromTitle($title, RequestContext::getMain()); // return if $title or $article is null if (is_null($title) || is_null($article)) { return true; } /**************************/ /* CUSER (First author) */ /**************************/ if (in_array('_CUSER', $sespSpecialProperties)) { $firstRevision = $title->getFirstRevision(); if ($firstRevision !== null) { $firstAuthor = User::newFromId($firstRevision->getRawUser()); if ($firstAuthor) { $property = new SMWDIProperty('___CUSER'); $dataItem = SMWDIWikiPage::newFromTitle($firstAuthor->getUserPage()); $data->addPropertyObjectValue($property, $dataItem); } } } // end if _CUSER /**************************/ /* REVID (Revision ID) */ /**************************/ if (in_array('_REVID', $sespSpecialProperties)) { $property = new SMWDIProperty('___REVID'); $dataItem = new SMWDINumber($article->getRevIdFetched()); $data->addPropertyObjectValue($property, $dataItem); } /********************************/ /* VIEWS (Number of page views) */ /********************************/ if (in_array('_VIEWS', $sespSpecialProperties) && !$wgDisableCounters) { $property = new SMWDIProperty('___VIEWS'); $dataItem = new SMWDINumber($article->getCount()); $data->addPropertyObjectValue($property, $dataItem); } /*****************************/ /* EUSER (Page contributors) */ /*****************************/ if (in_array('_EUSER', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___EUSER'); /* Get options */ global $wgSESPExcludeBots; if (!isset($wgSESPExcludeBots)) { $wgSESPExcludeBots = false; } /* Get author from current revision */ $u = User::newFromId($article->getUser()); /* Get authors from earlier revisions */ $authors = $article->getContributors(); while ($u) { if (!$u->isHidden() && !(in_array('bot', $u->getRights()) && $wgSESPExcludeBots) && !$u->isAnon()) { //no anonymous users /* Add values*/ $dataItem = SMWDIWikiPage::newFromTitle($u->getUserPage()); $data->addPropertyObjectValue($property, $dataItem); } $u = $authors->current(); $authors->next(); } } /******************************/ /* NREV (Number of revisions) */ /******************************/ if (in_array('_NREV', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___NREV'); /* Get number of revisions */ $dbr =& wfGetDB(DB_SLAVE); $num = $dbr->estimateRowCount("revision", "*", array("rev_page" => $title->getArticleID())); /* Add values */ $dataItem = new SMWDINumber($num); $data->addPropertyObjectValue($property, $dataItem); } /*****************************************/ /* NTREV (Number of talk page revisions) */ /*****************************************/ if (in_array('_NTREV', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___NTREV'); /* Get number of revisions */ if (!isset($dbr)) { $dbr =& wfGetDB(DB_SLAVE); } $talkPage = $title->getTalkPage(); $num = $dbr->estimateRowCount("revision", "*", array("rev_page" => $talkPage->getArticleID())); /* Add values */ $dataItem = new SMWDINumber($num); $data->addPropertyObjectValue($property, $dataItem); } /************************/ /* SUBP (Get sub pages) */ /************************/ if (in_array('_SUBP', $sespSpecialProperties)) { /* Create property */ $property = new SMWDIProperty('___SUBP'); $subpages = $title->getSubpages(-1); //-1 = no limit. Returns TitleArray object /* Add values*/ foreach ($subpages as $t) { $dataItem = SMWDIWikiPage::newFromTitle($t); $data->addPropertyObjectValue($property, $dataItem); } // end foreach } // end _SUBP /************************/ /* MIMETYPE */ /************************/ if ($title->inNamespace(NS_FILE) && in_array('_MIMETYPE', $sespSpecialProperties)) { // Build image page instance $imagePage = new ImagePage($title); $file = $imagePage->getFile(); $mimetype = $file->getMimeType(); $mediaType = MimeMagic::singleton()->findMediaType($mimetype); list($mimetypemajor, $mimetypeminor) = $file->splitMime($mimetype); // MIMETYPE $property = new SMWDIProperty('___MIMETYPE'); $dataItem = new SMWDIString($mimetypeminor); $data->addPropertyObjectValue($property, $dataItem); // MEDIATYPE $property = new SMWDIProperty('___MEDIATYPE'); $dataItem = new SMWDIString($mediaType); $data->addPropertyObjectValue($property, $dataItem); } // end if MIMETYPE /************************/ /* IMAGEMETA */ /************************/ function convertexifdate($exifString) { $exifPieces = explode(":", $exifString); if ($exifPieces[0] && $exifPieces[1] && $exifPieces[2]) { $res = new DateTime($exifPieces[0] . "-" . $exifPieces[1] . "-" . $exifPieces[2] . ":" . $exifPieces[3] . ":" . $exifPieces[4]); return $res; } else { return false; } } if ($title->inNamespace(NS_FILE) && in_array('_METADATA', $sespSpecialProperties)) { $imagePage = new ImagePage($title); $file = $imagePage->getFile(); $metadata = $file->getMetadata(); if ($metadata === ExifBitmapHandler::OLD_BROKEN_FILE || $metadata === ExifBitmapHandler::BROKEN_FILE) { // So we don't try and display metadata from PagedTiffHandler // for example when using InstantCommons. return true; } $exif = unserialize($metadata); if ($exif) { if (count($exif)) { // EXIFDATETIME if (array_key_exists('DateTimeOriginal', $exif) || array_key_exists('DateTime', $exif)) { $property = new SMWDIProperty('___EXIFDATETIME'); if (array_key_exists('DateTimeOriginal', $exif)) { $exifstr = $exif['DateTimeOriginal']; } else { $exifstr = $exif['DateTime']; } $datetime = convertexifdate($exifstr); if ($datetime) { $dataItem = new SMWDITime(SMWDITime::CM_GREGORIAN, $datetime->format('Y'), $datetime->format('n'), $datetime->format('j'), $datetime->format('G'), $datetime->format('i')); $data->addPropertyObjectValue($property, $dataItem); } } // EXIFSOFTWARE if (array_key_exists('Software', $exif) || array_key_exists('metadata', $exif) && array_key_exists('Software', $exif['metadata'])) { $str = array_key_exists('Software', $exif) ? $exif['Software'] : $exif['metadata']['Software']; if (is_array($str)) { $str = array_key_exists('x-default', $str) ? $str['x-default'] : $str[0]; } if (!$str) { return true; } $property = new SMWDIProperty('___EXIFSOFTWARE'); $dataItem = new SMWDIString($str); $data->addPropertyObjectValue($property, $dataItem); } // EXIFLATLON /* //TODO if ( array_key_exists( 'GPSLatitudeRef', $exif ) || array_key_exists( 'GPSLongitudeRef', $exif ) ) { } */ //EXIFLATLON } } } //IMAGEMETA /************************/ /* SHORTURL */ /************************/ //FIXME handle internal and external links if (in_array('_SHORTURL', $sespSpecialProperties) && class_exists('ShortUrlUtils')) { global $wgShortUrlPrefix; if (!is_string($wgShortUrlPrefix)) { $urlPrefix = SpecialPage::getTitleFor('ShortUrl')->getFullUrl() . '/'; } else { $urlPrefix = $wgShortUrlPrefix; } if (ShortUrlUtils::needsShortUrl($title)) { $shortId = ShortUrlUtils::encodeTitle($title); $shortURL = $urlPrefix . $shortId; $property = new SMWDIProperty('___SHORTURL'); $dataItem = new SMWDIUri('http', $shortURL, '', ''); $data->addPropertyObjectValue($property, $dataItem); } else { } } // end if SHORTURL return true; }
protected function getArticleByUrl($url) { global $wgArticlePath; $url = $this->getUrlWithoutPath($url->value, $wgArticlePath); if (empty($url)) { return null; } $title = Title::newFromURL($url); if ($title) { $article = Article::newFromTitle($title, RequestContext::getMain()); return $article; } else { \Wikia\Logger\WikiaLogger::instance()->info("TabView with not existing url found.", ["url" => $url]); return null; } }
/** * Initialize the main Article object for "standard" actions (view, etc) * Create an Article object for the page, following redirects if needed. * * @return mixed an Article, or a string to redirect to another URL */ private function initializeArticle() { global $wgDisableHardRedirects, $wgTitle; wfProfileIn(__METHOD__); $title = $this->context->getTitle(); $article = Article::newFromTitle($title, $this->context); $this->context->setWikiPage($article->getPage()); // NS_MEDIAWIKI has no redirects. // It is also used for CSS/JS, so performance matters here... if ($title->getNamespace() == NS_MEDIAWIKI) { wfProfileOut(__METHOD__); return $article; } $request = $this->context->getRequest(); // Namespace might change when using redirects // Check for redirects ... $action = $request->getVal('action', 'view'); // commented by wikia; $file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null; // ... and check that we still have ImagePage instance here (might be replaced by 'ArticleFromTitle' hook above) - bugId:9286 (ADi) $file = $title->getNamespace() == NS_FILE && $article instanceof ImagePage ? $article->getFile() : null; if (($action == 'view' || $action == 'render') && !$request->getVal('oldid') && !$request->getVal('diff') && $request->getVal('redirect') != 'no' && true) { // Give extensions a change to ignore/handle redirects as needed $ignoreRedirect = $target = false; wfRunHooks('InitializeArticleMaybeRedirect', array(&$title, &$request, &$ignoreRedirect, &$target, &$article)); // Follow redirects only for... redirects. // If $target is set, then a hook wanted to redirect. if (!$ignoreRedirect && ($target || $article->isRedirect())) { // Is the target already set by an extension? $target = $target ? $target : $article->followRedirect(); if (is_string($target)) { if (!$wgDisableHardRedirects) { // we'll need to redirect wfProfileOut(__METHOD__); return $target; } } if (is_object($target)) { // Rewrite environment to redirected article $rarticle = Article::newFromTitle($target, $this->context); $rarticle->loadPageData(); if ($rarticle->exists() || is_object($file) && !$file->isLocal()) { $rarticle->setRedirectedFrom($title); $article = $rarticle; $this->context->setTitle($target); $this->context->setWikiPage($article->getPage()); // in MW 1.16 $wgTitle = $target, so we added it here too $wgTitle = $target; } } } else { $this->context->setTitle($article->getTitle()); $this->context->setWikiPage($article->getPage()); } } wfProfileOut(__METHOD__); return $article; }
/** * Create a new wikipage and return a $local_url */ public function createNewWikiPage($new_url, $content = '') { $content = empty($content) ? '<!--' . $this->msg('manuscriptdesk-newpage') . '-->' : $content; $title = $this->createTitleObjectNewPage($new_url); $local_url = $title->getLocalURL(); $context = $this->getContext(); $article = Article::newFromTitle($title, $context); $editor_object = new EditPage($article); $content_new = new wikitextcontent($content); $doEditStatus = $editor_object->mArticle->doEditContent($content_new, $editor_object->summary, 97, false, null, $editor_object->contentFormat); if (!$doEditStatus->isOK()) { $errors = $doEditStatus->getErrorsArray(); throw new \Exception('error-newpage'); } return $local_url; }
public function execute() { // The data is hot but user-dependent, like page views, so we set vary cookies $this->getMain()->setCacheMode('anon-public-user-private'); // Get parameters $params = $this->extractRequestParams(); $text = $params['text']; $title = $params['title']; if ($title === null) { $titleProvided = false; // A title is needed for parsing, so arbitrarily choose one $title = 'API'; } else { $titleProvided = true; } $page = $params['page']; $pageid = $params['pageid']; $oldid = $params['oldid']; $model = $params['contentmodel']; $format = $params['contentformat']; if (!is_null($page) && (!is_null($text) || $titleProvided)) { $this->dieUsage('The page parameter cannot be used together with the text and title parameters', 'params'); } $prop = array_flip($params['prop']); if (isset($params['section'])) { $this->section = $params['section']; if (!preg_match('/^((T-)?\\d+|new)$/', $this->section)) { $this->dieUsage("The section parameter must be a valid section id or 'new'", "invalidsection"); } } else { $this->section = false; } // The parser needs $wgTitle to be set, apparently the // $title parameter in Parser::parse isn't enough *sigh* // TODO: Does this still need $wgTitle? global $wgParser, $wgTitle; $redirValues = null; // Return result $result = $this->getResult(); if (!is_null($oldid) || !is_null($pageid) || !is_null($page)) { if ($this->section === 'new') { $this->dieUsage('section=new cannot be combined with oldid, pageid or page parameters. ' . 'Please use text', 'params'); } if (!is_null($oldid)) { // Don't use the parser cache $rev = Revision::newFromId($oldid); if (!$rev) { $this->dieUsage("There is no revision ID {$oldid}", 'missingrev'); } if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) { $this->dieUsage("You don't have permission to view deleted revisions", 'permissiondenied'); } $titleObj = $rev->getTitle(); $wgTitle = $titleObj; $pageObj = WikiPage::factory($titleObj); $popts = $this->makeParserOptions($pageObj, $params); // If for some reason the "oldid" is actually the current revision, it may be cached // Deliberately comparing $pageObj->getLatest() with $rev->getId(), rather than // checking $rev->isCurrent(), because $pageObj is what actually ends up being used, // and if its ->getLatest() is outdated, $rev->isCurrent() won't tell us that. if ($rev->getId() == $pageObj->getLatest()) { // May get from/save to parser cache $p_result = $this->getParsedContent($pageObj, $popts, $pageid, isset($prop['wikitext'])); } else { // This is an old revision, so get the text differently $this->content = $rev->getContent(Revision::FOR_THIS_USER, $this->getUser()); if ($this->section !== false) { $this->content = $this->getSectionContent($this->content, 'r' . $rev->getId()); } // Should we save old revision parses to the parser cache? $p_result = $this->content->getParserOutput($titleObj, $rev->getId(), $popts); } } else { // Not $oldid, but $pageid or $page if ($params['redirects']) { $reqParams = array('redirects' => ''); if (!is_null($pageid)) { $reqParams['pageids'] = $pageid; } else { // $page $reqParams['titles'] = $page; } $req = new FauxRequest($reqParams); $main = new ApiMain($req); $pageSet = new ApiPageSet($main); $pageSet->execute(); $redirValues = $pageSet->getRedirectTitlesAsResult($this->getResult()); $to = $page; foreach ($pageSet->getRedirectTitles() as $title) { $to = $title->getFullText(); } $pageParams = array('title' => $to); } elseif (!is_null($pageid)) { $pageParams = array('pageid' => $pageid); } else { // $page $pageParams = array('title' => $page); } $pageObj = $this->getTitleOrPageId($pageParams, 'fromdb'); $titleObj = $pageObj->getTitle(); if (!$titleObj || !$titleObj->exists()) { $this->dieUsage("The page you specified doesn't exist", 'missingtitle'); } $wgTitle = $titleObj; if (isset($prop['revid'])) { $oldid = $pageObj->getLatest(); } $popts = $this->makeParserOptions($pageObj, $params); // Don't pollute the parser cache when setting options that aren't // in ParserOptions::optionsHash() /// @todo: This should be handled closer to the actual cache instead of here, see T110269 $suppressCache = $params['disablepp'] || $params['disablelimitreport'] || $params['preview'] || $params['sectionpreview'] || $params['disabletidy']; if ($suppressCache) { $this->content = $this->getContent($pageObj, $pageid); $p_result = $this->content->getParserOutput($titleObj, null, $popts); } else { // Potentially cached $p_result = $this->getParsedContent($pageObj, $popts, $pageid, isset($prop['wikitext'])); } } } else { // Not $oldid, $pageid, $page. Hence based on $text $titleObj = Title::newFromText($title); if (!$titleObj || $titleObj->isExternal()) { $this->dieUsageMsg(array('invalidtitle', $title)); } $wgTitle = $titleObj; if ($titleObj->canExist()) { $pageObj = WikiPage::factory($titleObj); } else { // Do like MediaWiki::initializeArticle() $article = Article::newFromTitle($titleObj, $this->getContext()); $pageObj = $article->getPage(); } $popts = $this->makeParserOptions($pageObj, $params); $textProvided = !is_null($text); if (!$textProvided) { if ($titleProvided && ($prop || $params['generatexml'])) { $this->setWarning("'title' used without 'text', and parsed page properties were requested " . "(did you mean to use 'page' instead of 'title'?)"); } // Prevent warning from ContentHandler::makeContent() $text = ''; } // If we are parsing text, do not use the content model of the default // API title, but default to wikitext to keep BC. if ($textProvided && !$titleProvided && is_null($model)) { $model = CONTENT_MODEL_WIKITEXT; $this->setWarning("No 'title' or 'contentmodel' was given, assuming {$model}."); } try { $this->content = ContentHandler::makeContent($text, $titleObj, $model, $format); } catch (MWContentSerializationException $ex) { $this->dieUsage($ex->getMessage(), 'parseerror'); } if ($this->section !== false) { if ($this->section === 'new') { // Insert the section title above the content. if (!is_null($params['sectiontitle']) && $params['sectiontitle'] !== '') { $this->content = $this->content->addSectionHeader($params['sectiontitle']); } } else { $this->content = $this->getSectionContent($this->content, $titleObj->getPrefixedText()); } } if ($params['pst'] || $params['onlypst']) { $this->pstContent = $this->content->preSaveTransform($titleObj, $this->getUser(), $popts); } if ($params['onlypst']) { // Build a result and bail out $result_array = array(); $result_array['text'] = $this->pstContent->serialize($format); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text'; if (isset($prop['wikitext'])) { $result_array['wikitext'] = $this->content->serialize($format); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'wikitext'; } if (!is_null($params['summary']) || !is_null($params['sectiontitle']) && $this->section === 'new') { $result_array['parsedsummary'] = $this->formatSummary($titleObj, $params); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsedsummary'; } $result->addValue(null, $this->getModuleName(), $result_array); return; } // Not cached (save or load) if ($params['pst']) { $p_result = $this->pstContent->getParserOutput($titleObj, null, $popts); } else { $p_result = $this->content->getParserOutput($titleObj, null, $popts); } } $result_array = array(); $result_array['title'] = $titleObj->getPrefixedText(); $result_array['pageid'] = $pageid ? $pageid : $pageObj->getId(); if (!is_null($oldid)) { $result_array['revid'] = intval($oldid); } if ($params['redirects'] && !is_null($redirValues)) { $result_array['redirects'] = $redirValues; } if ($params['disabletoc']) { $p_result->setTOCEnabled(false); } if (isset($prop['text'])) { $result_array['text'] = $p_result->getText(); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text'; } if (!is_null($params['summary']) || !is_null($params['sectiontitle']) && $this->section === 'new') { $result_array['parsedsummary'] = $this->formatSummary($titleObj, $params); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsedsummary'; } if (isset($prop['langlinks'])) { $langlinks = $p_result->getLanguageLinks(); if ($params['effectivelanglinks']) { // Link flags are ignored for now, but may in the future be // included in the result. $linkFlags = array(); Hooks::run('LanguageLinks', array($titleObj, &$langlinks, &$linkFlags)); } } else { $langlinks = false; } if (isset($prop['langlinks'])) { $result_array['langlinks'] = $this->formatLangLinks($langlinks); } if (isset($prop['categories'])) { $result_array['categories'] = $this->formatCategoryLinks($p_result->getCategories()); } if (isset($prop['categorieshtml'])) { $result_array['categorieshtml'] = $this->categoriesHtml($p_result->getCategories()); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'categorieshtml'; } if (isset($prop['links'])) { $result_array['links'] = $this->formatLinks($p_result->getLinks()); } if (isset($prop['templates'])) { $result_array['templates'] = $this->formatLinks($p_result->getTemplates()); } if (isset($prop['images'])) { $result_array['images'] = array_keys($p_result->getImages()); } if (isset($prop['externallinks'])) { $result_array['externallinks'] = array_keys($p_result->getExternalLinks()); } if (isset($prop['sections'])) { $result_array['sections'] = $p_result->getSections(); } if (isset($prop['displaytitle'])) { $result_array['displaytitle'] = $p_result->getDisplayTitle() ? $p_result->getDisplayTitle() : $titleObj->getPrefixedText(); } if (isset($prop['headitems']) || isset($prop['headhtml'])) { $context = $this->getContext(); $context->setTitle($titleObj); $context->getOutput()->addParserOutputMetadata($p_result); if (isset($prop['headitems'])) { $headItems = $this->formatHeadItems($p_result->getHeadItems()); $css = $this->formatCss($context->getOutput()->buildCssLinksArray()); $scripts = array($context->getOutput()->getHeadScripts()); $result_array['headitems'] = array_merge($headItems, $css, $scripts); } if (isset($prop['headhtml'])) { $result_array['headhtml'] = $context->getOutput()->headElement($context->getSkin()); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'headhtml'; } } if (isset($prop['modules'])) { $result_array['modules'] = array_values(array_unique($p_result->getModules())); $result_array['modulescripts'] = array_values(array_unique($p_result->getModuleScripts())); $result_array['modulestyles'] = array_values(array_unique($p_result->getModuleStyles())); // To be removed in 1.27 $result_array['modulemessages'] = array(); $this->setWarning('modulemessages is deprecated since MediaWiki 1.26'); } if (isset($prop['jsconfigvars'])) { $result_array['jsconfigvars'] = ApiResult::addMetadataToResultVars($p_result->getJsConfigVars()); } if (isset($prop['encodedjsconfigvars'])) { $result_array['encodedjsconfigvars'] = FormatJson::encode($p_result->getJsConfigVars(), false, FormatJson::ALL_OK); $result_array[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars'; } if (isset($prop['modules']) && !isset($prop['jsconfigvars']) && !isset($prop['encodedjsconfigvars'])) { $this->setWarning("Property 'modules' was set but not 'jsconfigvars' " . "or 'encodedjsconfigvars'. Configuration variables are necessary " . "for proper module usage."); } if (isset($prop['indicators'])) { $result_array['indicators'] = (array) $p_result->getIndicators(); ApiResult::setArrayType($result_array['indicators'], 'BCkvp', 'name'); } if (isset($prop['iwlinks'])) { $result_array['iwlinks'] = $this->formatIWLinks($p_result->getInterwikiLinks()); } if (isset($prop['wikitext'])) { $result_array['wikitext'] = $this->content->serialize($format); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'wikitext'; if (!is_null($this->pstContent)) { $result_array['psttext'] = $this->pstContent->serialize($format); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'psttext'; } } if (isset($prop['properties'])) { $result_array['properties'] = (array) $p_result->getProperties(); ApiResult::setArrayType($result_array['properties'], 'BCkvp', 'name'); } if (isset($prop['limitreportdata'])) { $result_array['limitreportdata'] = $this->formatLimitReportData($p_result->getLimitReportData()); } if (isset($prop['limitreporthtml'])) { $result_array['limitreporthtml'] = EditPage::getPreviewLimitReport($p_result); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'limitreporthtml'; } if (isset($prop['parsetree']) || $params['generatexml']) { if ($this->content->getModel() != CONTENT_MODEL_WIKITEXT) { $this->dieUsage("parsetree is only supported for wikitext content", "notwikitext"); } $wgParser->startExternalParse($titleObj, $popts, Parser::OT_PREPROCESS); $dom = $wgParser->preprocessToDom($this->content->getNativeData()); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $result_array['parsetree'] = $xml; $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'parsetree'; } $result_mapping = array('redirects' => 'r', 'langlinks' => 'll', 'categories' => 'cl', 'links' => 'pl', 'templates' => 'tl', 'images' => 'img', 'externallinks' => 'el', 'iwlinks' => 'iw', 'sections' => 's', 'headitems' => 'hi', 'modules' => 'm', 'indicators' => 'ind', 'modulescripts' => 'm', 'modulestyles' => 'm', 'modulemessages' => 'm', 'properties' => 'pp', 'limitreportdata' => 'lr'); $this->setIndexedTagNames($result_array, $result_mapping); $result->addValue(null, $this->getModuleName(), $result_array); }
public function execute() { global $wgUseFileCache, $wgReadOnly, $wgContentNamespaces, $wgRequestTime; global $wgOut; if (!$wgUseFileCache) { $this->error("Nothing to do -- \$wgUseFileCache is disabled.", true); } $wgReadOnly = 'Building cache'; // avoid DB writes (like enotif/counters) $start = $this->getOption('start', "0"); if (!ctype_digit($start)) { $this->error("Invalid value for start parameter.", true); } $start = intval($start); $end = $this->getOption('end', "0"); if (!ctype_digit($end)) { $this->error("Invalid value for end parameter.", true); } $end = intval($end); $this->output("Building content page file cache from page {$start}!\n"); $dbr = $this->getDB(DB_SLAVE); $overwrite = $this->getOption('overwrite', false); $start = $start > 0 ? $start : $dbr->selectField('page', 'MIN(page_id)', false, __FUNCTION__); $end = $end > 0 ? $end : $dbr->selectField('page', 'MAX(page_id)', false, __FUNCTION__); if (!$start) { $this->error("Nothing to do.", true); } $_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip'; // hack, no real client # Do remaining chunk $end += $this->mBatchSize - 1; $blockStart = $start; $blockEnd = $start + $this->mBatchSize - 1; $dbw = $this->getDB(DB_MASTER); // Go through each page and save the output while ($blockEnd <= $end) { // Get the pages $res = $dbr->select('page', array('page_namespace', 'page_title', 'page_id'), array('page_namespace' => $wgContentNamespaces, "page_id BETWEEN {$blockStart} AND {$blockEnd}"), array('ORDER BY' => 'page_id ASC', 'USE INDEX' => 'PRIMARY')); $this->beginTransaction($dbw, __METHOD__); // for any changes foreach ($res as $row) { $rebuilt = false; $wgRequestTime = microtime(true); # bug 22852 $title = Title::makeTitleSafe($row->page_namespace, $row->page_title); if (null == $title) { $this->output("Page {$row->page_id} has bad title\n"); continue; // broken title? } $context = new RequestContext(); $context->setTitle($title); $article = Article::newFromTitle($title, $context); $context->setWikiPage($article->getPage()); $wgOut = $context->getOutput(); // set display title // If the article is cacheable, then load it if ($article->isFileCacheable()) { $cache = HTMLFileCache::newFromTitle($title, 'view'); if ($cache->isCacheGood()) { if ($overwrite) { $rebuilt = true; } else { $this->output("Page {$row->page_id} already cached\n"); continue; // done already! } } ob_start(array(&$cache, 'saveToFileCache')); // save on ob_end_clean() $wgUseFileCache = false; // hack, we don't want $article fiddling with filecache $article->view(); MediaWiki\suppressWarnings(); // header notices $wgOut->output(); MediaWiki\restoreWarnings(); $wgUseFileCache = true; ob_end_clean(); // clear buffer if ($rebuilt) { $this->output("Re-cached page {$row->page_id}\n"); } else { $this->output("Cached page {$row->page_id}\n"); } } else { $this->output("Page {$row->page_id} not cacheable\n"); } } $this->commitTransaction($dbw, __METHOD__); // commit any changes (just for sanity) $blockStart += $this->mBatchSize; $blockEnd += $this->mBatchSize; } $this->output("Done!\n"); }
/** * Initialize the main Article object for "standard" actions (view, etc) * Create an Article object for the page, following redirects if needed. * * @return mixed an Article, or a string to redirect to another URL */ private function initializeArticle() { global $wgDisableHardRedirects; wfProfileIn(__METHOD__); $title = $this->context->getTitle(); if ($this->context->canUseWikiPage()) { // Try to use request context wiki page, as there // is already data from db saved in per process // cache there from this->getAction() call. $page = $this->context->getWikiPage(); $article = Article::newFromWikiPage($page, $this->context); } else { // This case should not happen, but just in case. $article = Article::newFromTitle($title, $this->context); $this->context->setWikiPage($article->getPage()); } // NS_MEDIAWIKI has no redirects. // It is also used for CSS/JS, so performance matters here... if ($title->getNamespace() == NS_MEDIAWIKI) { wfProfileOut(__METHOD__); return $article; } $request = $this->context->getRequest(); // Namespace might change when using redirects // Check for redirects ... $action = $request->getVal('action', 'view'); $file = $title->getNamespace() == NS_FILE ? $article->getFile() : null; if (($action == 'view' || $action == 'render') && !$request->getVal('oldid') && !$request->getVal('diff') && $request->getVal('redirect') != 'no' && !(is_object($file) && $file->exists() && !$file->getRedirected())) { // Give extensions a change to ignore/handle redirects as needed $ignoreRedirect = $target = false; wfRunHooks('InitializeArticleMaybeRedirect', array(&$title, &$request, &$ignoreRedirect, &$target, &$article)); // Follow redirects only for... redirects. // If $target is set, then a hook wanted to redirect. if (!$ignoreRedirect && ($target || $article->isRedirect())) { // Is the target already set by an extension? $target = $target ? $target : $article->followRedirect(); if (is_string($target)) { if (!$wgDisableHardRedirects) { // we'll need to redirect wfProfileOut(__METHOD__); return $target; } } if (is_object($target)) { // Rewrite environment to redirected article $rarticle = Article::newFromTitle($target, $this->context); $rarticle->loadPageData(); if ($rarticle->exists() || is_object($file) && !$file->isLocal()) { $rarticle->setRedirectedFrom($title); $article = $rarticle; $this->context->setTitle($target); $this->context->setWikiPage($article->getPage()); } } } else { $this->context->setTitle($article->getTitle()); $this->context->setWikiPage($article->getPage()); } } wfProfileOut(__METHOD__); return $article; }
/** * Initialize the main Article object for "standard" actions (view, etc) * Create an Article object for the page, following redirects if needed. * * @return mixed An Article, or a string to redirect to another URL */ private function initializeArticle() { $title = $this->context->getTitle(); if ($this->context->canUseWikiPage()) { // Try to use request context wiki page, as there // is already data from db saved in per process // cache there from this->getAction() call. $page = $this->context->getWikiPage(); $article = Article::newFromWikiPage($page, $this->context); } else { // This case should not happen, but just in case. $article = Article::newFromTitle($title, $this->context); $this->context->setWikiPage($article->getPage()); } // Skip some unnecessary code if the content model doesn't support redirects if (!ContentHandler::getForTitle($title)->supportsRedirects()) { return $article; } $request = $this->context->getRequest(); // Namespace might change when using redirects // Check for redirects ... $action = $request->getVal('action', 'view'); $file = $title->getNamespace() == NS_FILE ? $article->getFile() : null; if (($action == 'view' || $action == 'render') && !$request->getVal('oldid') && !$request->getVal('diff') && $request->getVal('redirect') != 'no' && !(is_object($file) && $file->exists() && !$file->getRedirected())) { // Give extensions a change to ignore/handle redirects as needed $ignoreRedirect = $target = false; Hooks::run('InitializeArticleMaybeRedirect', array(&$title, &$request, &$ignoreRedirect, &$target, &$article)); // Follow redirects only for... redirects. // If $target is set, then a hook wanted to redirect. if (!$ignoreRedirect && ($target || $article->isRedirect())) { // Is the target already set by an extension? $target = $target ? $target : $article->followRedirect(); if (is_string($target)) { if (!$this->config->get('DisableHardRedirects')) { // we'll need to redirect return $target; } } if (is_object($target)) { // Rewrite environment to redirected article $rarticle = Article::newFromTitle($target, $this->context); $rarticle->loadPageData(); if ($rarticle->exists() || is_object($file) && !$file->isLocal()) { $rarticle->setRedirectedFrom($title); $article = $rarticle; $this->context->setTitle($target); $this->context->setWikiPage($article->getPage()); } } } else { $this->context->setTitle($article->getTitle()); $this->context->setWikiPage($article->getPage()); } } return $article; }
public static function onArticleViewFooter( $article ) { global $wgOut, $wgRequest, $wgUser, $wgJsMimeType, $wgUseAjax, $wgTalkHereNamespaces; $action = $wgRequest->getVal( 'action', 'view' ); if ( $action != 'view' && $action != 'purge' ) { return true; } if ( $wgRequest->getVal( 'oldid' ) || $wgRequest->getVal( 'diff' ) ) { return true; } $title = $article->getTitle(); $ns = $title->getNamespace(); if ( MWNamespace::isTalk($ns) || !MWNamespace::canTalk($ns) || !$title->exists() || ( $wgTalkHereNamespaces && !in_array( $ns, $wgTalkHereNamespaces ) ) ) { return true; } $talk = $title->getTalkPage(); if ( !$talk || !$talk->userCanRead() ) { return true; } $hastalk = $talk->exists(); $cantalk = $talk->userCan('edit'); if ( !$hastalk && !$cantalk ) { return true; } $skin = $wgUser->getSkin(); $talkArticle = Article::newFromTitle( $talk, RequestContext::getMain() ); $wgOut->addHTML('<div class="talkhere" id="talkhere">'); if ($hastalk) { //Bah, would have to call a skin-snippet here :( $wgOut->addHTML('<div class="talkhere-head">'); $wgOut->addHTML('<h1>'); if ($talk->userCan('edit')) { $wgOut->addHTML('<span class="editsection">'); $wgOut->addHTML( '[' . $skin->makeKnownLinkObj( $talk, wfMsg('talkhere-talkpage' ) ) . ']' ); $wgOut->addHTML('</span>'); } $wgOut->addWikiText( wfMsg('talkhere-title', $talk->getPrefixedText() ), false ); $wgOut->addHTML('</h1>'); $headtext = wfMsg('talkhere-headtext', $title->getPrefixedText(), $talk->getPrefixedText() ); if ( $headtext ) { $wgOut->addWikiText( $headtext ); $wgOut->addHTML('<hr/>'); } $wgOut->addHTML('</div>'); //talkhere-head $wgOut->addHTML('<div class="talkhere-comments">'); $talkArticle->view(); $wgOut->addHTML('</div>'); // talkhere-comments } $wgOut->addHTML('<div class="talkhere-foot">'); if ( $cantalk ) { if ($hastalk) { $wgOut->addHTML('<hr/>'); } else { $wgOut->addHTML('<div class="talkhere-comments talkhere-notalk">'); $wgOut->addWikiText( wfMsg('talkhere-notalk') ); $wgOut->addHTML('</div>'); // talkhere-comments } if ( $wgUseAjax ) $wgOut->addScript( " <script type=\"{$wgJsMimeType}\"> var talkHereLoadingMsg = \"" . Xml::escapeJsString(wfMsg('talkhere-loading')) . "\"; var talkHereCollapseMsg = \"" . Xml::escapeJsString(wfMsg('talkhere-collapse')) . "\"; var talkHereExpandMsg = \"" . Xml::escapeJsString(wfMsg('talkhere-addcomment')) . "\"; </script>\n" ); $returnto = $title->getPrefixedDBKey(); $talktitle = $talk->getPrefixedDBKey(); $q = 'action=edit§ion=new&wpTalkHere=1&wpReturnTo=' . urlencode($returnto); $js = $wgUseAjax ? 'this.href="javascript:void(0);"; talkHereLoadEditor("talkhere_talklink", "talkhere_talkform", "'.Xml::escapeJsString($talktitle).'", "new", "'.Xml::escapeJsString($returnto).'"); ' : ''; $a = 'onclick="'.htmlspecialchars($js).'" id="talkhere_talklink"'; $wgOut->addHTML('<div class="talkhere-talklink">'); $wgOut->addHTML( $skin->makeKnownLinkObj( $talk, wfMsg('talkhere-addcomment' ), $q, '', '', $a ) ); $wgOut->addHTML('</div>'); $wgOut->addHTML('<div id="talkhere_talkform" style="display:none;"> </div>'); //self::showCommentForm( $title, $talk, 'new' ); } if ($hastalk) { $foottext = wfMsg('talkhere-foottext', $title->getPrefixedText(), $talk->getPrefixedText() ); if ( $foottext ) { $wgOut->addHTML('<hr/>'); $wgOut->addWikiText( $foottext ); } } $wgOut->addHTML('</div>'); // talkhere-foot $wgOut->addHTML('</div>'); // talkhere return true; }
public function execute() { // The data is hot but user-dependent, like page views, so we set vary cookies $this->getMain()->setCacheMode('anon-public-user-private'); // Get parameters $params = $this->extractRequestParams(); $text = $params['text']; $title = $params['title']; if ($title === null) { $titleProvided = false; // A title is needed for parsing, so arbitrarily choose one $title = 'API'; } else { $titleProvided = true; } $page = $params['page']; $pageid = $params['pageid']; $oldid = $params['oldid']; $model = $params['contentmodel']; $format = $params['contentformat']; if (!is_null($page) && (!is_null($text) || $titleProvided)) { $this->dieUsage('The page parameter cannot be used together with the text and title parameters', 'params'); } $prop = array_flip($params['prop']); if (isset($params['section'])) { $this->section = $params['section']; } else { $this->section = false; } // The parser needs $wgTitle to be set, apparently the // $title parameter in Parser::parse isn't enough *sigh* // TODO: Does this still need $wgTitle? global $wgParser, $wgTitle; // Currently unnecessary, code to act as a safeguard against any change // in current behavior of uselang $oldLang = null; if (isset($params['uselang']) && $params['uselang'] != $this->getContext()->getLanguage()->getCode()) { $oldLang = $this->getContext()->getLanguage(); // Backup language $this->getContext()->setLanguage(Language::factory($params['uselang'])); } $redirValues = null; // Return result $result = $this->getResult(); if (!is_null($oldid) || !is_null($pageid) || !is_null($page)) { if (!is_null($oldid)) { // Don't use the parser cache $rev = Revision::newFromID($oldid); if (!$rev) { $this->dieUsage("There is no revision ID {$oldid}", 'missingrev'); } $this->checkReadPermissions($rev->getTitle()); if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) { $this->dieUsage("You don't have permission to view deleted revisions", 'permissiondenied'); } $titleObj = $rev->getTitle(); $wgTitle = $titleObj; $pageObj = WikiPage::factory($titleObj); $popts = $this->makeParserOptions($pageObj, $params); // If for some reason the "oldid" is actually the current revision, it may be cached if ($rev->isCurrent()) { // May get from/save to parser cache $p_result = $this->getParsedContent($pageObj, $popts, $pageid, isset($prop['wikitext'])); } else { // This is an old revision, so get the text differently $this->content = $rev->getContent(Revision::FOR_THIS_USER, $this->getUser()); if ($this->section !== false) { $this->content = $this->getSectionContent($this->content, 'r' . $rev->getId()); } // Should we save old revision parses to the parser cache? $p_result = $this->content->getParserOutput($titleObj, $rev->getId(), $popts); } } else { // Not $oldid, but $pageid or $page if ($params['redirects']) { $reqParams = array('action' => 'query', 'redirects' => ''); if (!is_null($pageid)) { $reqParams['pageids'] = $pageid; } else { // $page $reqParams['titles'] = $page; } $req = new FauxRequest($reqParams); $main = new ApiMain($req); $main->execute(); $data = $main->getResultData(); $redirValues = isset($data['query']['redirects']) ? $data['query']['redirects'] : array(); $to = $page; foreach ((array) $redirValues as $r) { $to = $r['to']; } $pageParams = array('title' => $to); } elseif (!is_null($pageid)) { $pageParams = array('pageid' => $pageid); } else { // $page $pageParams = array('title' => $page); } $pageObj = $this->getTitleOrPageId($pageParams, 'fromdb'); $titleObj = $pageObj->getTitle(); if (!$titleObj || !$titleObj->exists()) { $this->dieUsage("The page you specified doesn't exist", 'missingtitle'); } $this->checkReadPermissions($titleObj); $wgTitle = $titleObj; if (isset($prop['revid'])) { $oldid = $pageObj->getLatest(); } $popts = $this->makeParserOptions($pageObj, $params); // Potentially cached $p_result = $this->getParsedContent($pageObj, $popts, $pageid, isset($prop['wikitext'])); } } else { // Not $oldid, $pageid, $page. Hence based on $text $titleObj = Title::newFromText($title); if (!$titleObj || $titleObj->isExternal()) { $this->dieUsageMsg(array('invalidtitle', $title)); } $wgTitle = $titleObj; if ($titleObj->canExist()) { $pageObj = WikiPage::factory($titleObj); } else { // Do like MediaWiki::initializeArticle() $article = Article::newFromTitle($titleObj, $this->getContext()); $pageObj = $article->getPage(); } $popts = $this->makeParserOptions($pageObj, $params); $textProvided = !is_null($text); if (!$textProvided) { if ($titleProvided && ($prop || $params['generatexml'])) { $this->setWarning("'title' used without 'text', and parsed page properties were requested " . "(did you mean to use 'page' instead of 'title'?)"); } // Prevent warning from ContentHandler::makeContent() $text = ''; } // If we are parsing text, do not use the content model of the default // API title, but default to wikitext to keep BC. if ($textProvided && !$titleProvided && is_null($model)) { $model = CONTENT_MODEL_WIKITEXT; $this->setWarning("No 'title' or 'contentmodel' was given, assuming {$model}."); } try { $this->content = ContentHandler::makeContent($text, $titleObj, $model, $format); } catch (MWContentSerializationException $ex) { $this->dieUsage($ex->getMessage(), 'parseerror'); } if ($this->section !== false) { $this->content = $this->getSectionContent($this->content, $titleObj->getText()); } if ($params['pst'] || $params['onlypst']) { $this->pstContent = $this->content->preSaveTransform($titleObj, $this->getUser(), $popts); } if ($params['onlypst']) { // Build a result and bail out $result_array = array(); $result_array['text'] = array(); ApiResult::setContent($result_array['text'], $this->pstContent->serialize($format)); if (isset($prop['wikitext'])) { $result_array['wikitext'] = array(); ApiResult::setContent($result_array['wikitext'], $this->content->serialize($format)); } $result->addValue(null, $this->getModuleName(), $result_array); return; } // Not cached (save or load) if ($params['pst']) { $p_result = $this->pstContent->getParserOutput($titleObj, null, $popts); } else { $p_result = $this->content->getParserOutput($titleObj, null, $popts); } } $result_array = array(); $result_array['title'] = $titleObj->getPrefixedText(); if (!is_null($oldid)) { $result_array['revid'] = intval($oldid); } if ($params['redirects'] && !is_null($redirValues)) { $result_array['redirects'] = $redirValues; } if ($params['disabletoc']) { $p_result->setTOCEnabled(false); } if (isset($prop['text'])) { $result_array['text'] = array(); ApiResult::setContent($result_array['text'], $p_result->getText()); } if (!is_null($params['summary'])) { $result_array['parsedsummary'] = array(); ApiResult::setContent($result_array['parsedsummary'], Linker::formatComment($params['summary'], $titleObj)); } if (isset($prop['langlinks']) || isset($prop['languageshtml'])) { $langlinks = $p_result->getLanguageLinks(); if ($params['effectivelanglinks']) { // Link flags are ignored for now, but may in the future be // included in the result. $linkFlags = array(); wfRunHooks('LanguageLinks', array($titleObj, &$langlinks, &$linkFlags)); } } else { $langlinks = false; } if (isset($prop['langlinks'])) { $result_array['langlinks'] = $this->formatLangLinks($langlinks); } if (isset($prop['languageshtml'])) { $languagesHtml = $this->languagesHtml($langlinks); $result_array['languageshtml'] = array(); ApiResult::setContent($result_array['languageshtml'], $languagesHtml); } if (isset($prop['categories'])) { $result_array['categories'] = $this->formatCategoryLinks($p_result->getCategories()); } if (isset($prop['categorieshtml'])) { $categoriesHtml = $this->categoriesHtml($p_result->getCategories()); $result_array['categorieshtml'] = array(); ApiResult::setContent($result_array['categorieshtml'], $categoriesHtml); } if (isset($prop['links'])) { $result_array['links'] = $this->formatLinks($p_result->getLinks()); } if (isset($prop['templates'])) { $result_array['templates'] = $this->formatLinks($p_result->getTemplates()); } if (isset($prop['images'])) { $result_array['images'] = array_keys($p_result->getImages()); } if (isset($prop['externallinks'])) { $result_array['externallinks'] = array_keys($p_result->getExternalLinks()); } if (isset($prop['sections'])) { $result_array['sections'] = $p_result->getSections(); } if (isset($prop['displaytitle'])) { $result_array['displaytitle'] = $p_result->getDisplayTitle() ? $p_result->getDisplayTitle() : $titleObj->getPrefixedText(); } if (isset($prop['headitems']) || isset($prop['headhtml'])) { $context = new DerivativeContext($this->getContext()); $context->setTitle($titleObj); $context->setWikiPage($pageObj); // We need an OutputPage tied to $context, not to the // RequestContext at the root of the stack. $output = new OutputPage($context); $output->addParserOutputNoText($p_result); if (isset($prop['headitems'])) { $headItems = $this->formatHeadItems($p_result->getHeadItems()); $css = $this->formatCss($output->buildCssLinksArray()); $scripts = array($output->getHeadScripts()); $result_array['headitems'] = array_merge($headItems, $css, $scripts); } if (isset($prop['headhtml'])) { $result_array['headhtml'] = array(); ApiResult::setContent($result_array['headhtml'], $output->headElement($context->getSkin())); } } if (isset($prop['iwlinks'])) { $result_array['iwlinks'] = $this->formatIWLinks($p_result->getInterwikiLinks()); } if (isset($prop['wikitext'])) { $result_array['wikitext'] = array(); ApiResult::setContent($result_array['wikitext'], $this->content->serialize($format)); if (!is_null($this->pstContent)) { $result_array['psttext'] = array(); ApiResult::setContent($result_array['psttext'], $this->pstContent->serialize($format)); } } if (isset($prop['properties'])) { $result_array['properties'] = $this->formatProperties($p_result->getProperties()); } if (isset($prop['limitreportdata'])) { $result_array['limitreportdata'] = $this->formatLimitReportData($p_result->getLimitReportData()); } if (isset($prop['limitreporthtml'])) { $limitreportHtml = EditPage::getPreviewLimitReport($p_result); $result_array['limitreporthtml'] = array(); ApiResult::setContent($result_array['limitreporthtml'], $limitreportHtml); } if ($params['generatexml']) { if ($this->content->getModel() != CONTENT_MODEL_WIKITEXT) { $this->dieUsage("generatexml is only supported for wikitext content", "notwikitext"); } $wgParser->startExternalParse($titleObj, $popts, OT_PREPROCESS); $dom = $wgParser->preprocessToDom($this->content->getNativeData()); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $result_array['parsetree'] = array(); ApiResult::setContent($result_array['parsetree'], $xml); } $result_mapping = array('redirects' => 'r', 'langlinks' => 'll', 'categories' => 'cl', 'links' => 'pl', 'templates' => 'tl', 'images' => 'img', 'externallinks' => 'el', 'iwlinks' => 'iw', 'sections' => 's', 'headitems' => 'hi', 'properties' => 'pp', 'limitreportdata' => 'lr'); $this->setIndexedTagNames($result_array, $result_mapping); $result->addValue(null, $this->getModuleName(), $result_array); if (!is_null($oldLang)) { $this->getContext()->setLanguage($oldLang); // Reset language to $oldLang } }
/** * @desc Get wiki article from article title * * @param $titleText Wiki page title text * @return Article|null */ function articleFromTitle($titleText) { $title = Title::newFromText($titleText, NS_MAIN); if (!is_null($title) && $title->exists()) { return Article::newFromTitle($title, $this->context); } return null; }
/** * Show the new revision of the page. */ function renderNewRevision() { wfProfileIn(__METHOD__); $out = $this->getOutput(); $revHeader = $this->getRevisionHeader($this->mNewRev); # Add "current version as of X" title $out->addHTML("<hr class='diff-hr' />\n\t\t<h2 class='diff-currentversion-title'>{$revHeader}</h2>\n"); # Page content may be handled by a hooked call instead... if (wfRunHooks('ArticleContentOnDiff', array($this, $out))) { $this->loadNewText(); $out->setRevisionId($this->mNewid); $out->setRevisionTimestamp($this->mNewRev->getTimestamp()); $out->setArticleFlag(true); // NOTE: only needed for B/C: custom rendering of JS/CSS via hook if ($this->mNewPage->isCssJsSubpage() || $this->mNewPage->isCssOrJsPage()) { // Stolen from Article::view --AG 2007-10-11 // Give hooks a chance to customise the output // @TODO: standardize this crap into one function if (ContentHandler::runLegacyHooks('ShowRawCssJs', array($this->mNewContent, $this->mNewPage, $out))) { // NOTE: deprecated hook, B/C only // use the content object's own rendering $po = $this->mNewRev->getContent()->getParserOutput($this->mNewRev->getTitle(), $this->mNewRev->getId()); $out->addHTML($po->getText()); } } elseif (!wfRunHooks('ArticleContentViewCustom', array($this->mNewContent, $this->mNewPage, $out))) { // Handled by extension } elseif (!ContentHandler::runLegacyHooks('ArticleViewCustom', array($this->mNewContent, $this->mNewPage, $out))) { // NOTE: deprecated hook, B/C only // Handled by extension } else { // Normal page if ($this->getTitle()->equals($this->mNewPage)) { // If the Title stored in the context is the same as the one // of the new revision, we can use its associated WikiPage // object. $wikiPage = $this->getWikiPage(); } else { // Otherwise we need to create our own WikiPage object $wikiPage = WikiPage::factory($this->mNewPage); } $parserOutput = $this->getParserOutput($wikiPage, $this->mNewRev); # Also try to load it as a redirect $rt = $this->mNewContent->getRedirectTarget(); if ($rt) { $article = Article::newFromTitle($this->mNewPage, $this->getContext()); $out->addHTML($article->viewRedirect($rt)); # WikiPage::getParserOutput() should not return false, but just in case if ($parserOutput) { # Show categories etc. $out->addParserOutputNoText($parserOutput); } } else { if ($parserOutput) { $out->addParserOutput($parserOutput); } } } } # Add redundant patrol link on bottom... $out->addHTML($this->markPatrolledLink()); wfProfileOut(__METHOD__); }
/** * Hook entry for Category Service to invalidate the cache * Removes entries from memcached */ public static function onCategoryServiceInvalidateTopArticles($title, $ns) { if ($ns == NS_MAIN) { $categoryPage = Article::newFromTitle($title, RequestContext::getMain()); $gallery = new CategoryGallery($categoryPage); $gallery->invalidate(); } return true; }
function put( $serverOptions ) { global $wgUser; if ( !$wgUser->isAllowed( 'edit' ) ) { $this->setResponseStatus( '401 Unauthorized' ); return; } if ( wfReadOnly() ) { $this->setResponseStatus( '403 Forbidden' ); return; } if ( empty( $this->pathComponents ) ) { return; } $pathComponent = array_shift( $this->pathComponents ); if ( $pathComponent != 'webdav.php' ) { return; } $title = Title::newFromURL( implode( '/', $this->pathComponents ) ); if (!isset( $title )) { $title = Title::newMainPage(); } if ( !$title->exists() && !$title->userCan( 'create' ) ) { $this->setResponseStatus( '401 Unauthorized' ); return; } $article = Article::newFromTitle( $title, RequestContext::getMain() ); if ( ( $handle = $this->openRequestBody() ) === false ) { return; } $text = null; while ( !feof( $handle ) ) { if ( ( $buffer = fread( $handle, 4096 ) ) === false ) { return; } $text .= $buffer; } $article->doEdit( $text, null ); return true; }
/** * Really find the title match. */ private static function getNearMatchInternal($searchterm) { global $wgContLang; $allSearchTerms = array($searchterm); if ($wgContLang->hasVariants()) { $allSearchTerms = array_merge($allSearchTerms, $wgContLang->autoConvertToAllVariants($searchterm)); } $titleResult = null; if (!wfRunHooks('SearchGetNearMatchBefore', array($allSearchTerms, &$titleResult))) { return $titleResult; } $context = new RequestContext(); foreach ($allSearchTerms as $term) { # Exact match? No need to look further. $title = Title::newFromText($term); if (is_null($title)) { return null; } if ($title->getNamespace() == NS_SPECIAL || $title->isExternal() || $title->exists()) { return $title; } # See if it still otherwise has content is some sane sense $context->setTitle($title); $article = Article::newFromTitle($title, $context); if ($article->hasViewableContent()) { return $title; } # Now try all lower case (i.e. first letter capitalized) # $title = Title::newFromText($wgContLang->lc($term)); if ($title && $title->exists()) { return $title; } # Now try capitalized string # $title = Title::newFromText($wgContLang->ucwords($term)); if ($title && $title->exists()) { return $title; } # Now try all upper case # $title = Title::newFromText($wgContLang->uc($term)); if ($title && $title->exists()) { return $title; } # Now try Word-Caps-Breaking-At-Word-Breaks, for hyphenated names etc $title = Title::newFromText($wgContLang->ucwordbreaks($term)); if ($title && $title->exists()) { return $title; } // Give hooks a chance at better match variants $title = null; if (!wfRunHooks('SearchGetNearMatch', array($term, &$title))) { return $title; } } $title = Title::newFromText($searchterm); # Entering an IP address goes to the contributions page if ($title->getNamespace() == NS_USER && User::isIP($title->getText()) || User::isIP(trim($searchterm))) { return SpecialPage::getTitleFor('Contributions', $title->getDBkey()); } # Entering a user goes to the user page whether it's there or not if ($title->getNamespace() == NS_USER) { return $title; } # Go to images that exist even if there's no local page. # There may have been a funny upload, or it may be on a shared # file repository such as Wikimedia Commons. if ($title->getNamespace() == NS_FILE) { $image = wfFindFile($title); if ($image) { return $title; } } # MediaWiki namespace? Page may be "implied" if not customized. # Just return it, with caps forced as the message system likes it. if ($title->getNamespace() == NS_MEDIAWIKI) { return Title::makeTitle(NS_MEDIAWIKI, $wgContLang->ucfirst($title->getText())); } # Quoted term? Try without the quotes... $matches = array(); if (preg_match('/^"([^"]+)"$/', $searchterm, $matches)) { return SearchEngine::getNearMatch($matches[1]); } return null; }