/** * Creates and returns a MobileFormatter * * @param MobileContext $context * @param string $html * * @return MobileFormatter */ public static function newFromContext($context, $html) { global $wgMFSpecialCaseMainPage; $title = $context->getTitle(); $isMainPage = $title->isMainPage() && $wgMFSpecialCaseMainPage; $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; }
/** * Updates the aa_lastlogin value for the specified user * * @param User $user the user that just logged in * * @return bool return True to continue processing hooks */ static function updateLastLogin(User $user) { if (wfReadOnly()) { return true; } $now = time(); $db = wfGetDB(DB_MASTER); $method = __METHOD__; $requestMethod = self::ACCESS_METHOD_DEFAULT; if (class_exists("MobileContext") && MobileContext::singleton()->shouldDisplayMobileView()) { $requestMethod = self::ACCESS_METHOD_MOBILE; } $db->onTransactionIdle(function () use($user, $requestMethod, $now, $db, $method) { if ($db->getType() === 'mysql') { // MySQL-specific implementation $db->query("INSERT INTO " . $db->tableName('accountaudit_login') . "( aa_user, aa_method, aa_lastlogin ) VALUES (" . $db->addQuotes($user->getId()) . ", " . $db->addQuotes($requestMethod) . ", " . $db->addQuotes($db->timestamp($now)) . ") ON DUPLICATE KEY UPDATE aa_lastlogin = " . $db->addQuotes($db->timestamp($now)), $method); } else { $db->update('accountaudit_login', array('aa_lastlogin' => $db->timestamp($now)), array('aa_user' => $user->getId(), 'aa_method' => $requestMethod), $method); if ($db->affectedRows() == 0) { // no row existed for that user, method $db->insert('accountaudit_login', array('aa_user' => $user->getId(), 'aa_method' => $requestMethod, 'aa_lastlogin' => $db->timestamp($now)), $method, array('IGNORE')); } } }); // always return true, this should be a non-blocking hook on failure return true; }
/** * Generates HTML for the uploads page for the passed user. * * @param User $user * @return string */ public function getUserUploadsPageHtml(User $user) { $uploadCount = $this->getUserUploadCount($user->getName()); $mobileContext = MobileContext::singleton(); $html = ''; $attrs = array(); if ($uploadCount !== false) { $threshold = $this->getUploadCountThreshold(); // FIXME: Use Html class? $html .= '<div class="content">'; if ($mobileContext->userCanUpload()) { $html .= '<div class="ctaUploadPhoto"></div>'; } if ($uploadCount > $threshold) { $msg = $this->msg('mobile-frontend-photo-upload-user-count-over-limit')->text(); } else { $msg = $this->msg('mobile-frontend-photo-upload-user-count')->numParams($uploadCount)->parse(); if ($uploadCount === 0) { $attrs = array('style' => 'display:none'); } } $html .= Html::openElement('h2', $attrs) . $msg . Html::closeElement('h2'); $html .= '</div>'; } return $html; }
/** * Render the special page and redirect the user to the editor (if page exists) * @param string $subpage The name of the page to edit */ public function executeWhenAvailable($subpage) { if (!is_string($subpage)) { $this->showPageNotFound(); return; } else { $title = Title::newFromText($subpage); if (is_null($title)) { $this->showPageNotFound(); return; } } $data = $this->getRequest()->getValues(); unset($data['title']); // Remove the title of the special page $section = (int) $this->getRequest()->getVal('section', 0); $output = $this->getOutput(); $output->addModules('mobile.special.mobileeditor.scripts'); $output->setPageTitle($this->msg('mobile-frontend-editor-redirect-title')->text()); $context = MobileContext::singleton(); $articleUrl = $context->getMobileUrl($title->getFullURL($data)); $targetUrl = $articleUrl . '#/editor/' . $section; $html = Html::openElement('div', array('id' => 'mw-mf-editor', 'data-targeturl' => $targetUrl)) . Html::openElement('noscript') . MobileUI::errorBox($this->msg('mobile-frontend-editor-unavailable')->text()) . Html::openElement('p') . Html::element('a', array('href' => $title->getLocalUrl()), $this->msg('returnto', $title->getText())->text()) . Html::closeElement('noscript') . Html::closeElement('div'); // #mw-mf-editorunavailable $output->addHTML($html); }
/** * Render the navigation menu * @param string $par never used */ public function executeWhenAvailable($par = '') { $this->setHeaders(); $out = $this->getOutput(); $out->setPageTitle(wfMessage('mobile-frontend-main-menu-page-title')->text()); if (!MobileContext::singleton()->isAlphaGroupMember()) { $out->setProperty('bodyClassName', 'navigation-enabled navigation-full-screen'); } }
/** * @dataProvider redirectFromDesktopDiffProvider */ public function testRedirectFromDesktopDiff(array $query, $expected) { foreach ($query as $k => $v) { MobileContext::singleton()->getRequest()->setVal($k, $v); $this->unsetReqVals[] = $k; } if ($expected) { $expected = Title::newFromText($expected)->getLocalURL(); } $redirectUrl = MockSpecialMobileDiff::getMobileUrlFromDesktop(); $this->assertEquals($expected, $redirectUrl); }
/** * Generate user page content for non-existent user pages * * @param OutputPage $output * @param User $pageUser owner of the user page * @return string */ public static function getUserPageContent($output, $pageUser) { $context = MobileContext::singleton(); $pageUsername = $pageUser->getName(); // Is the current user viewing their own page? $isCurrentUser = $output->getUser()->getName() === $pageUsername; $data['ctaHeading'] = $isCurrentUser ? $context->msg('mobile-frontend-user-page-no-owner-page-yet')->text() : $context->msg('mobile-frontend-user-page-no-page-yet', $pageUsername)->parse(); $data['ctaDescription'] = $isCurrentUser ? $context->msg('mobile-frontend-user-page-describe-yourself', $context->msg('mobile-frontend-user-page-describe-yourself-editors')->text())->text() : $context->msg('mobile-frontend-user-page-desired-action', $pageUsername)->parse(); $data['createPageLinkLabel'] = $isCurrentUser ? $context->msg('mobile-frontend-user-page-create-owner-page-link-label')->text() : $context->msg('mobile-frontend-user-page-create-user-page-link-label', $pageUser->getUserPage()->getBaseTitle())->parse(); $data['createPageLinkAdditionalClasses'] = $isCurrentUser ? 'mw-ui-button' : ''; $templateParser = new TemplateParser(__DIR__); return $templateParser->processTemplate('user_page_cta', $data); }
/** * Get CSS classes for icons * @param string $iconName * @param string $iconType element or before * @param string $additionalClassNames additional class names you want to associate * with the iconed element * @return string class name for use with HTML element */ public static function iconClass($iconName, $iconType = 'element', $additionalClassNames = '') { $ctx = MobileContext::singleton(); if ($ctx->isBetaGroupMember()) { $base = 'mw-ui-icon'; $modifiers = 'mw-ui-icon-' . $iconType; $modifiers .= ' mw-ui-icon-' . $iconName; } else { $base = 'icon'; $modifiers = $iconType === 'before' ? 'icon-text' : ''; $modifiers .= ' icon-' . $iconName; } return $base . ' ' . $modifiers . ' ' . $additionalClassNames; }
/** * Transforms content to be mobile friendly version. * Filters out various elements and runs the MobileFormatter. * @param OutputPage $out * * @return string */ public static function DOMParse(OutputPage $out) { $html = $out->getHTML(); $context = MobileContext::singleton(); $formatter = MobileFormatter::newFromContext($context, $html); Hooks::run('MobileFrontendBeforeDOM', array($context, $formatter)); $title = $out->getTitle(); $isSpecialPage = $title->isSpecialPage(); $formatter->enableExpandableSections($out->canUseWikiPage() && $out->getWikiPage()->getContentModel() == CONTENT_MODEL_WIKITEXT && array_search($title->getNamespace(), $context->getMFConfig()->get('MFNamespacesWithoutCollapsibleSections')) === false && $context->getRequest()->getText('action', 'view') == 'view'); if ($context->getContentTransformations()) { // Remove images if they're disabled from special pages, but don't transform otherwise $formatter->filterContent(!$isSpecialPage); } $contentHtml = $formatter->getText(); return $contentHtml; }
/** * Checks the availability of the special page in actual mode and display the page, if available * @param string $subPage parameter submitted as "subpage" */ public function execute($subPage) { $ctx = MobileContext::singleton(); $this->config = $ctx->getMFConfig(); $this->getOutput()->setProperty('desktopUrl', $this->getDesktopUrl($subPage)); if (!$ctx->shouldDisplayMobileView() && !$this->hasDesktopVersion) { $this->renderUnavailableBanner($this->msg('mobile-frontend-requires-mobile')); } elseif ($this->mode !== 'stable') { if ($this->mode === 'beta' && !$ctx->isBetaGroupMember()) { $this->renderUnavailableBanner($this->msg('mobile-frontend-requires-optin')->parse()); } else { $this->executeWhenAvailable($subPage); } } else { $this->executeWhenAvailable($subPage); } }
/** * Returns a count of the most recent uploads to $wgMFPhotoUploadWiki since * a given timestamp, not exceeding LIMIT. * * @param int $fromDate Time to measure from * @return int the amount of edits */ public function countRecentUploads($fromDate) { $mfPhotoUploadWiki = MobileContext::singleton()->getMFConfig()->get('MFPhotoUploadWiki'); global $wgConf; if (!$mfPhotoUploadWiki) { $dbr = wfGetDB(DB_SLAVE); } elseif ($mfPhotoUploadWiki && !in_array($mfPhotoUploadWiki, $wgConf->getLocalDatabases())) { // early return if the database is invalid return false; } else { $dbr = wfGetDB(DB_SLAVE, array(), $mfPhotoUploadWiki); } $where = array('img_user_text' => $this->user->getName()); $where[] = 'img_timestamp > ' . $dbr->addQuotes($dbr->timestamp($fromDate)); $constraints = array('LIMIT' => self::LIMIT + 1); $result = $dbr->selectRowCount('image', 'img_timestamp', $where, __METHOD__, $constraints); return $result; }
/** * Prepare the content for the 'last edited' message, e.g. 'Last edited on 30 August * 2013, at 23:31'. This message is different for the main page since main page * content is typically transcuded rather than edited directly. * @param Title $title The Title object of the page being viewed * @return array */ protected function getHistoryLink(Title $title) { $user = $this->getUser(); $isMainPage = $title->isMainPage(); $mp = new MobilePage($this->getTitle(), false); $timestamp = $mp->getLatestTimestamp(); // Main pages tend to include transclusions (see bug 51924) if ($isMainPage) { $lastModified = $this->msg('mobile-frontend-history')->plain(); } else { $lastModified = $this->msg('mobile-frontend-last-modified-date', $this->getLanguage()->userDate($timestamp, $user), $this->getLanguage()->userTime($timestamp, $user))->parse(); } $historyUrl = $this->mobileContext->getMobileUrl($title->getFullURL('action=history')); $edit = $mp->getLatestEdit(); $link = array('data-timestamp' => $isMainPage ? '' : $edit['timestamp'], 'href' => $historyUrl, 'text' => $lastModified, 'data-user-name' => $edit['name'], 'data-user-gender' => $edit['gender']); $link['href'] = SpecialPage::getTitleFor('History', $title)->getLocalURL(); return $link; }
/** * APIAfterExecute hook handler * @see: https://www.mediawiki.org/wiki/Manual:Hooks/ * @param ApiBase $module * @return bool */ public static function onAPIAfterExecute(ApiBase &$module) { $mfSpecialCaseMainPage = MobileContext::singleton()->getMFConfig()->get('MFSpecialCaseMainPage'); 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'] && $mfSpecialCaseMainPage); $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; }
/** * @dataProvider providerShowRedLinks */ public function testRedLinks($showRedLinks, $showRedLinksAnon, $username, $expected) { // set config variables, which we test here $values = array('wgMFShowRedLinks' => $showRedLinks, 'wgMFShowRedLinksAnon' => $showRedLinksAnon, 'wgMFEnableBeta' => true); $this->setMwGlobals($values); // create our specific user object $user = User::newFromName($username); $user->load(); // create a new RequestContext for this test case and set User and title $context = new RequestContext(); $context->setUser($user); $context->setTitle(Title::newFromText('Main_page')); // create SkinMinerva to test $skin = $this->getSkin(); $skin->setContext($context); // set the fake mobile mode MobileContext::singleton()->setMobileMode($this->getMode()); // test now $vars = $skin->getSkinConfigVariables(); $this->assertEquals($expected, $vars['wgMFShowRedLinks']); }
/** * Check, if context modules aren't arrays. They will be added as an array with modules to * to load, which doesn't allow arrays as values. */ public function testGetContextSpecificModules() { // try to cover all possible modules (maybe extent, if other modules added) $values = array('wgMFEnableBeta' => true); $this->setMwGlobals($values); // UTSysop will be a logged in user $user = User::newFromName('UTSysop'); $user->load(); // create a new RequestContext for this test case and set User and title $context = new RequestContext(); $context->setUser($user); // UTPage is an existing page in the main namespace $context->setTitle(Title::newFromText('UTPage')); MobileContext::singleton()->setMobileMode('alpha'); $skin = $this->getSkin(); $skin->setContext($context); $modules = $skin->getContextSpecificModules(); foreach ($modules as $module) { $this->assertFalse(is_array($module), 'Context specific modules can\'t be arrays.'); } }
/** * @param $user object: The User object that was created. * @param $byEmail boolean The form has a [By e-mail] button. * @return bool True */ public static function onAddNewAccount($user, $byEmail) { global $wgRequest, $wgUser; $userId = $user->getId(); $creatorUserId = $wgUser->getId(); // MediaWiki allows existing users to create accounts on behalf // of others. In such cases the ID of the newly-created user and // the ID of the user making this web request are different. $isSelfMade = $userId && $userId === $creatorUserId; $displayMobile = class_exists('MobileContext') && MobileContext::singleton()->shouldDisplayMobileView(); $event = array('token' => $wgRequest->getCookie('mediaWiki.user.id', '', ''), 'userId' => $userId, 'userName' => $user->getName(), 'isSelfMade' => $isSelfMade, 'userBuckets' => $wgRequest->getCookie('userbuckets', '', ''), 'displayMobile' => $displayMobile); $returnTo = $wgRequest->getVal('returnto'); if ($returnTo !== null) { $event['returnTo'] = $returnTo; } $returnToQuery = $wgRequest->getVal('returntoquery'); if ($returnToQuery !== null) { $event['returnToQuery'] = $returnToQuery; } efLogServerSideEvent('ServerSideAccountCreation', 5233795, $event); return true; }
/** * Returns an array of languages that the page is available in * @return array */ private function getLanguages() { $api = new ApiMain(new DerivativeRequest($this->getRequest(), array('action' => 'query', 'prop' => 'langlinks', 'llprop' => 'url', 'lllimit' => 'max', 'titles' => $this->title->getPrefixedText()))); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $data = (array) $api->getResult()->getResultData(array('query', 'pages'), array('Strip' => 'all')); } else { $data = $api->getResult()->getData(); // Paranoia if (!isset($data['query']['pages'])) { return array(); } $data = $data['query']['pages']; } // Silly strict php $pages = array_values($data); $page = array_shift($pages); if (isset($page['langlinks'])) { // Set the name of each lanugage based on the system list of language names $languageMap = Language::fetchLanguageNames(); $languages = $page['langlinks']; foreach ($page['langlinks'] as $code => $langObject) { if (!isset($languageMap[$langObject['lang']])) { // Bug T93500: DB might still have preantiquated rows with bogus languages unset($languages[$code]); continue; } $langObject['langname'] = $languageMap[$langObject['lang']]; $langObject['url'] = MobileContext::singleton()->getMobileUrl($langObject['url']); $languages[$code] = $langObject; } return $languages; } else { // No langlinks available return array(); } }
/** * Handler for MakeGlobalVariablesScript hook. * @see http://www.mediawiki.org/wiki/Manual:Hooks/MakeGlobalVariablesScript * @param &$vars array Variables to be added into the output * @param $outputPage OutputPage instance calling the hook * @return bool true in all cases */ public static function onMakeGlobalVariablesScript(array &$vars, OutputPage $out) { // If the device is a mobile, Remove the category entry. if (MobileContext::singleton()->shouldDisplayMobileView()) { unset($vars['wgCategories']); } return true; }
/** * Returns HTML of license link or empty string * For example: * "<a title="Wikipedia:Copyright" href="/index.php/Wikipedia:Copyright">CC BY</a>" * * @param string $context The context in which the license link appears, e.g. footer, * editor, talk, or upload. * @param array $attribs An associative array of extra HTML attributes to add to the link * @return string */ public static function getLicense($context, $attribs = array()) { $config = MobileContext::singleton()->getConfig(); $rightsPage = $config->get('RightsPage'); $rightsUrl = $config->get('RightsUrl'); $rightsText = $config->get('RightsText'); // Construct the link to the licensing terms if ($rightsText) { // Use shorter text for some common licensing strings. See Installer.i18n.php // for the currently offered strings. Unfortunately, there is no good way to // comprehensively support localized licensing strings since the license (as // stored in LocalSetttings.php) is just freeform text, not an i18n key. $commonLicenses = array('Creative Commons Attribution-Share Alike 3.0' => 'CC BY-SA 3.0', 'Creative Commons Attribution Share Alike' => 'CC BY-SA', 'Creative Commons Attribution 3.0' => 'CC BY 3.0', 'Creative Commons Attribution 2.5' => 'CC BY 2.5', 'Creative Commons Attribution' => 'CC BY', 'Creative Commons Attribution Non-Commercial Share Alike' => 'CC BY-NC-SA', 'Creative Commons Zero (Public Domain)' => 'CC0 (Public Domain)', 'GNU Free Documentation License 1.3 or later' => 'GFDL 1.3 or later'); if (isset($commonLicenses[$rightsText])) { $rightsText = $commonLicenses[$rightsText]; } if ($rightsPage) { $title = Title::newFromText($rightsPage); $link = Linker::linkKnown($title, $rightsText, $attribs); } elseif ($rightsUrl) { $link = Linker::makeExternalLink($rightsUrl, $rightsText, true, '', $attribs); } else { $link = $rightsText; } } else { $link = ''; } // Allow other extensions (for example, WikimediaMessages) to override Hooks::run('MobileLicenseLink', array(&$link, $context, $attribs)); // for plural support we need the info, if there is one or more licenses used in the license text // this check if very simple and works on the base, that more than one license will // use "and" as a connective // 1 - no plural // 2 - plural $delimiterMsg = wfMessage('and'); // check, if "and" isn't disabled and exists in site language $isPlural = !$delimiterMsg->isDisabled() && strpos($rightsText, $delimiterMsg->text()) === false ? 1 : 2; return array('link' => $link, 'plural' => $isPlural); }
/** * Get the URL of this special page * @param string|null $option Subpage string, or false to not use a subpage * @param Title $returnTo Destination to returnto after successfully action on the page returned * @param boolean $fullUrl Whether to get the local url, or the full url * * @return string */ public static function getURL($option, Title $returnTo = null, $fullUrl = false) { $t = SpecialPage::getTitleFor('MobileOptions', $option); $params = array(); if ($returnTo) { $params['returnto'] = $returnTo->getPrefixedText(); } if ($fullUrl) { return MobileContext::singleton()->getMobileUrl($t->getFullURL($params)); } else { return $t->getLocalURL($params); } }
/** * Get the HTML needed to show if a user doesn't watch any page, show information * how to watch pages where no pages have been watched. * @param boolean $feed Render as feed (true) or list (false) view? * @param Language $lang The language of the current mode * @return string */ public static function getEmptyListHtml($feed, $lang) { $dir = $lang->isRTL() ? 'rtl' : 'ltr'; $imgUrl = MobileContext::singleton()->getConfig()->get('ExtensionAssetsPath') . "/MobileFrontend/images/emptywatchlist-page-actions-{$dir}.png"; if ($feed) { $msg = Html::element('p', null, wfMessage('mobile-frontend-watchlist-feed-empty')->plain()); } else { $msg = Html::element('p', null, wfMessage('mobile-frontend-watchlist-a-z-empty-howto')->plain()); $msg .= Html::element('img', array('src' => $imgUrl, 'alt' => wfMessage('mobile-frontend-watchlist-a-z-empty-howto-alt')->plain())); } return Html::openElement('div', array('class' => 'info empty-page')) . $msg . Html::element('a', array('class' => 'button', 'href' => Title::newMainPage()->getLocalUrl()), wfMessage('mobile-frontend-watchlist-back-home')->plain()) . Html::closeElement('div'); }
/** * Returns HTML of license link or empty string * For example: * "<a title="Wikipedia:Copyright" href="/index.php/Wikipedia:Copyright">CC BY</a>" * * @param string $context The context in which the license link appears, e.g. footer, * editor, talk, or upload. * @param array $attribs An associative array of extra HTML attributes to add to the link * @return string */ public static function getLicenseLink($context, $attribs = array()) { $config = MobileContext::singleton()->getConfig(); $rightsPage = $config->get('RightsPage'); $rightsUrl = $config->get('RightsUrl'); $rightsText = $config->get('RightsText'); // Construct the link to the licensing terms if ($rightsText) { // Use shorter text for some common licensing strings. See Installer.i18n.php // for the currently offered strings. Unfortunately, there is no good way to // comprehensively support localized licensing strings since the license (as // stored in LocalSetttings.php) is just freeform text, not an i18n key. $commonLicenses = array('Creative Commons Attribution-Share Alike 3.0' => 'CC BY-SA 3.0', 'Creative Commons Attribution Share Alike' => 'CC BY-SA', 'Creative Commons Attribution 3.0' => 'CC BY 3.0', 'Creative Commons Attribution 2.5' => 'CC BY 2.5', 'Creative Commons Attribution' => 'CC BY', 'Creative Commons Attribution Non-Commercial Share Alike' => 'CC BY-NC-SA', 'Creative Commons Zero (Public Domain)' => 'CC0 (Public Domain)', 'GNU Free Documentation License 1.3 or later' => 'GFDL 1.3 or later'); if (isset($commonLicenses[$rightsText])) { $rightsText = $commonLicenses[$rightsText]; } if ($rightsPage) { $title = Title::newFromText($rightsPage); $link = Linker::linkKnown($title, $rightsText, $attribs); } elseif ($rightsUrl) { $link = Linker::makeExternalLink($rightsUrl, $rightsText, true, '', $attribs); } else { $link = $rightsText; } } else { $link = ''; } // Allow other extensions (for example, WikimediaMessages) to override Hooks::run('MobileLicenseLink', array(&$link, $context, $attribs)); return $link; }
/** * Returns an instance of detection class, overridable by extensions * @return IDeviceDetector */ public static function factory() { $deviceDetectionClass = MobileContext::singleton()->getMFConfig()->get('DeviceDetectionClass'); static $instance = null; if (!$instance) { $instance = new $deviceDetectionClass(); } return $instance; }
/** * Returns the site name for the footer, either as a text or <img> tag * @param boolean $withPossibleTrademark If true and a trademark symbol is specified * by $wgMFTrademarkSitename, append that trademark symbol to the sitename/logo. * This param exists so that the trademark symbol can be appended in some * contexts, for example, the footer, but not in others. See bug T95007. * @return string */ public static function getSitename($withPossibleTrademark = false) { $config = MobileContext::singleton()->getMFConfig(); $customLogos = $config->get('MFCustomLogos'); $trademarkSymbol = $config->get('MFTrademarkSitename'); $suffix = ''; $footerSitename = wfMessage('mobile-frontend-footer-sitename')->text(); // Add a trademark symbol if needed if ($withPossibleTrademark) { // Registered trademark if ($trademarkSymbol === 'registered') { $suffix = Html::element('sup', array(), '®'); // Unregistered (or unspecified) trademark } elseif ($trademarkSymbol) { $suffix = Html::element('sup', array(), '™'); } } // If there's a custom site logo, use that instead of text if (isset($customLogos['copyright'])) { $attributes = array('src' => $customLogos['copyright'], 'alt' => $footerSitename . $suffix); if (isset($customLogos['copyright-height'])) { $attributes['height'] = $customLogos['copyright-height']; } if (isset($customLogos['copyright-width'])) { $attributes['width'] = $customLogos['copyright-width']; } $sitename = Html::element('img', $attributes); } else { $sitename = $footerSitename; } return $sitename . $suffix; }
/** * HTMLFileCache::useFileCache hook handler * Disables file caching for mobile pageviews * @see https://www.mediawiki.org/wiki/Manual:Hooks/HTMLFileCache::useFileCache * * @return bool */ public static function onHTMLFileCache_useFileCache() { return !MobileContext::singleton()->shouldDisplayMobileView(); }
/** * Display Mobile Frontend specific logo over login form. */ protected function getLogoHtml() { $mfLogo = MobileContext::singleton()->getMFConfig()->get('MobileFrontendLogo'); if (!$mfLogo) { return ''; } return '<div class="watermark">' . Html::element('img', array('src' => $mfLogo, 'alt' => '')) . '</div>'; }
/** * Removes content inappropriate for mobile devices * @param bool $removeDefaults Whether default settings at $wgMFRemovableClasses should be used * @return array */ public function filterContent($removeDefaults = true) { $mfRemovableClasses = MobileContext::singleton()->getMFConfig()->get('MFRemovableClasses'); if ($removeDefaults) { $this->remove($mfRemovableClasses['base']); $this->remove($mfRemovableClasses['HTML']); // @todo: Migrate this variable } if ($this->removeMedia) { $this->doRemoveImages(); } return parent::filterContent(); }
/** * Renders the view/edit (normal) mode of the watchlist. */ protected function executeViewEditWatchlist() { $ns = NS_MAIN; $html = ''; $total = 0; $images = array(); $watchlist = $this->getWatchlistInfo(); if (isset($watchlist[$ns])) { $allPages = $watchlist[$ns]; $from = $this->getNextPage($allPages); $allPages = $this->getPagesToDisplay($allPages); } else { $allPages = array(); $from = false; } // Begin rendering of watchlist. $watchlist = array($ns => $allPages); if (!MobileContext::singleton()->imagesDisabled()) { Hooks::run('SpecialMobileEditWatchlist::images', array($this->getContext(), &$watchlist, &$images)); } // create list of pages $mobilePages = new MobileCollection(); $pageKeys = array_keys($watchlist[$ns]); foreach ($pageKeys as $dbkey) { if (isset($images[$ns][$dbkey])) { $page = new MobilePage(Title::makeTitleSafe($ns, $dbkey), wfFindFile($images[$ns][$dbkey])); } else { $page = new MobilePage(Title::makeTitleSafe($ns, $dbkey)); } $mobilePages->add($page); } if (count($mobilePages) === 0) { $html = SpecialMobileWatchlist::getEmptyListHtml(false, $this->getLanguage()); } else { $html = $this->getViewHtml($mobilePages); } if ($from) { // show more link if there are more items to show $qs = array('from' => $from); $html .= Html::element('a', array('class' => MobileUI::anchorClass('progressive', 'more'), 'href' => SpecialPage::getTitleFor('EditWatchlist')->getLocalURL($qs)), $this->msg('mobile-frontend-watchlist-more')); } $out = $this->getOutput(); $out->addHtml($html); $out->addModules('skins.minerva.special.watchlist.scripts'); $out->addModuleStyles(array('skins.minerva.special.styles', 'skins.minerva.special.watchlist.styles', 'mobile.pagelist.styles', 'mobile.pagesummary.styles', 'mobile.special.pagefeed.styles')); }
/** * Determine the correct domain to use for the stopMobileRedirect cookie * * Will use $wgMFStopRedirectCookieHost if it's set, otherwise will use * result of getBaseDomain() * @return string */ public function getStopMobileRedirectCookieDomain() { $mfStopRedirectCookieHost = $this->getMFConfig()->get('MFStopRedirectCookieHost'); if (!$mfStopRedirectCookieHost) { self::$mfStopRedirectCookieHost = $this->getBaseDomain(); } else { self::$mfStopRedirectCookieHost = $mfStopRedirectCookieHost; } return self::$mfStopRedirectCookieHost; }
/** * Removes content inappropriate for mobile devices * @param bool $removeDefaults Whether default settings at $wgMFRemovableClasses should be used * @return array */ public function filterContent($removeDefaults = true) { $ctx = MobileContext::singleton(); $mfRemovableClasses = $ctx->getMFConfig()->get('MFRemovableClasses'); if ($removeDefaults) { $this->remove($mfRemovableClasses['base']); if ($ctx->isBetaGroupMember()) { $this->remove($mfRemovableClasses['beta']); } } if ($this->removeMedia) { $this->doRemoveImages(); } return parent::filterContent(); }