/** * Creates and returns a MobileFormatter * * @param MobileContext $context * @param string $html * * @return MobileFormatter */ public static function newFromContext(MobileContext $context, $html) { $mfSpecialCaseMainPage = $context->getMFConfig()->get('MFSpecialCaseMainPage'); $title = $context->getTitle(); $isMainPage = $title->isMainPage() && $mfSpecialCaseMainPage; $isFilePage = $title->inNamespace(NS_FILE); $isSpecialPage = $title->isSpecialPage(); $html = self::wrapHTML($html); $formatter = new MobileFormatter($html, $title); $formatter->enableExpandableSections(!$isMainPage && !$isSpecialPage); $formatter->setIsMainPage($isMainPage); if ($context->getContentTransformations() && !$isFilePage) { $formatter->setRemoveMedia($context->imagesDisabled()); } return $formatter; }
/** * Get data of requested article. * @param Title $title * @param boolean $noImages * @return array */ private function getData(Title $title, $noImages) { global $wgMemc, $wgUseTidy, $wgMFTidyMobileViewSections, $wgMFMinCachedPageSize, $wgMFSpecialCaseMainPage; $wp = $this->makeWikiPage($title); if ($this->followRedirects && $wp->isRedirect()) { $newTitle = $wp->getRedirectTarget(); if ($newTitle) { $title = $newTitle; $this->getResult()->addValue(null, $this->getModuleName(), array('redirected' => $title->getPrefixedText())); if ($title->getNamespace() < 0) { $this->getResult()->addValue(null, $this->getModuleName(), array('viewable' => 'no')); return array(); } $wp = $this->makeWikiPage($title); } } $latest = $wp->getLatest(); if ($this->file) { $key = wfMemcKey('mf', 'mobileview', self::CACHE_VERSION, $noImages, $latest, $this->noTransform, $this->file->getSha1(), $this->variant); $cacheExpiry = 3600; } else { if (!$latest) { // https://bugzilla.wikimedia.org/show_bug.cgi?id=53378 // Title::exists() above doesn't seem to always catch recently deleted pages $this->dieUsageMsg(array('notanarticle', $title->getPrefixedText())); } $parserOptions = $this->makeParserOptions($wp); $parserCacheKey = ParserCache::singleton()->getKey($wp, $parserOptions); $key = wfMemcKey('mf', 'mobileview', self::CACHE_VERSION, $noImages, $latest, $this->noTransform, $parserCacheKey); } $data = $wgMemc->get($key); if ($data) { wfIncrStats('mobile.view.cache-hit'); return $data; } wfIncrStats('mobile.view.cache-miss'); if ($this->file) { $html = $this->getFilePage($title); } else { $parserOutput = $this->getParserOutput($wp, $parserOptions); $html = $parserOutput->getText(); $cacheExpiry = $parserOutput->getCacheExpiry(); } if (!$this->noTransform) { $mf = new MobileFormatter(MobileFormatter::wrapHTML($html), $title); $mf->setRemoveMedia($noImages); $mf->filterContent(); $mf->setIsMainPage($this->mainPage && $wgMFSpecialCaseMainPage); $html = $mf->getText(); } if ($this->mainPage || $this->file) { $data = array('sections' => array(), 'text' => array($html), 'refsections' => array()); } else { $data = array(); $data['sections'] = $parserOutput->getSections(); $sectionCount = count($data['sections']); for ($i = 0; $i < $sectionCount; $i++) { $data['sections'][$i]['line'] = $title->getPageLanguage()->convert($data['sections'][$i]['line']); } $chunks = preg_split('/<h(?=[1-6]\\b)/i', $html); if (count($chunks) != count($data['sections']) + 1) { wfDebugLog('mobile', __METHOD__ . "(): mismatching number of " . "sections from parser and split on page {$title->getPrefixedText()}, oldid={$latest}"); // We can't be sure about anything here, return all page HTML as one big section $chunks = array($html); $data['sections'] = array(); } $data['text'] = array(); $data['refsections'] = array(); foreach ($chunks as $chunk) { if (count($data['text'])) { $chunk = "<h{$chunk}"; } if ($wgUseTidy && $wgMFTidyMobileViewSections && count($chunks) > 1) { $chunk = MWTidy::tidy($chunk); } if (preg_match('/<ol\\b[^>]*?class="references"/', $chunk)) { $data['refsections'][count($data['text'])] = true; } $data['text'][] = $chunk; } if ($this->usePageImages) { $image = $this->getPageImage($title); if ($image) { $data['image'] = $image->getTitle()->getText(); } } } $data['lastmodified'] = wfTimestamp(TS_ISO_8601, $wp->getTimestamp()); // Page id $data['id'] = $wp->getId(); $user = User::newFromId($wp->getUser()); if (!$user->isAnon()) { $data['lastmodifiedby'] = array('name' => $wp->getUserText(), 'gender' => $user->getOption('gender')); } else { $data['lastmodifiedby'] = null; } $data['revision'] = $title->getLatestRevID(); if (isset($parserOutput)) { $languages = $parserOutput->getLanguageLinks(); $data['languagecount'] = count($languages); $data['displaytitle'] = $parserOutput->getDisplayTitle(); // @fixme: Does no work for some extension properties that get added in LinksUpdate $data['pageprops'] = $parserOutput->getProperties(); } else { $data['languagecount'] = 0; $data['displaytitle'] = $title->getPrefixedText(); $data['pageprops'] = array(); } if ($title->getPageLanguage()->hasVariants()) { $data['hasvariants'] = true; } // Don't store small pages to decrease cache size requirements if (strlen($html) >= $wgMFMinCachedPageSize) { // store for the same time as original parser output $wgMemc->set($key, $data, $cacheExpiry); } return $data; }
/** * APIAfterExecute hook handler * @see: https://www.mediawiki.org/wiki/Manual:Hooks/ * @param ApiBase $module * @return bool */ public static function onAPIAfterExecute(ApiBase &$module) { global $wgMFSpecialCaseMainPage; if ($module->getModuleName() == 'parse') { if (defined('ApiResult::META_CONTENT')) { $data = $module->getResult()->getResultData(); } else { $data = $module->getResultData(); } $params = $module->extractRequestParams(); if (isset($data['parse']['text']) && $params['mobileformat']) { $result = $module->getResult(); $result->reset(); $title = Title::newFromText($data['parse']['title']); $text = $data['parse']['text']; if (is_array($text)) { if (defined('ApiResult::META_CONTENT') && isset($text[ApiResult::META_CONTENT])) { $contentKey = $text[ApiResult::META_CONTENT]; } else { $contentKey = '*'; } $html = MobileFormatter::wrapHTML($text[$contentKey]); } else { $html = MobileFormatter::wrapHTML($text); } $mf = new MobileFormatter($html, $title); $mf->setRemoveMedia($params['noimages']); $mf->setIsMainPage($params['mainpage'] && $wgMFSpecialCaseMainPage); $mf->enableExpandableSections(!$params['mainpage']); // HACK: need a nice way to request a TOC- and edit link-free HTML in the first place // FIXME: Should this be .mw-editsection? $mf->remove(array('.toc', 'mw-editsection', '.mw-headline-anchor')); $mf->filterContent(); if (is_array($text)) { $text[$contentKey] = $mf->getText(); } else { $text = $mf->getText(); } $data['parse']['text'] = $text; $result->addValue(null, $module->getModuleName(), $data['parse']); } } return true; }