/**
  * 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;
 }
 /**
  * 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;
 }
 /**
  * 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);
 }
Exemplo n.º 7
0
 /**
  * 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;
 }
 /**
  * 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;
 }
Exemplo n.º 12
0
 /**
  * @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.');
     }
 }
Exemplo n.º 14
0
 /**
  * @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;
 }
 /**
  * Creates a new set of object for the actual test context, including a new
  * outputpage and skintemplate.
  *
  * @param string $mode The mode for the test cases (desktop, mobile)
  * @return array Array of objects, including MobileContext (context),
  * SkinTemplate (sk) and OutputPage (out)
  */
 protected function getContextSetup($mode, $mfXAnalyticsItems)
 {
     // Create a new MobileContext object for this test
     MobileContext::setInstance(null);
     // create a new instance of MobileContext
     $context = MobileContext::singleton();
     // create a DerivativeContext to use in MobileContext later
     $mainContext = new DerivativeContext(RequestContext::getMain());
     // create a new, empty OutputPage
     $out = new OutputPage($context);
     // create a new, empty SkinTemplate
     $sk = new SkinTemplate();
     // create a new Title (main page)
     $title = Title::newMainPage();
     // create a FauxRequest to use instead of a WebRequest object (FauxRequest forces
     // the creation of a FauxResponse, which allows to investigate sent header values)
     $request = new FauxRequest();
     // set the new request object to the context
     $mainContext->setRequest($request);
     // set the main page title to the context
     $mainContext->setTitle($title);
     // set the context to the SkinTemplate
     $sk->setContext($mainContext);
     // set the OutputPage to the context
     $mainContext->setOutput($out);
     // set the DerivativeContext as a base to MobileContext
     $context->setContext($mainContext);
     // set the mode to MobileContext
     $context->setUseFormat($mode);
     // if there are any XAnalytics items, add them
     foreach ($mfXAnalyticsItems as $key => $val) {
         $context->addAnalyticsLogItem($key, $val);
     }
     // set the newly created MobileContext object as the current instance to use
     MobileContext::setInstance($context);
     // return the stuff
     return array('out' => $out, 'sk' => $sk, 'context' => $context);
 }
 /**
  * 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();
     }
 }
 /**
  * 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 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;
 }
Exemplo n.º 21
0
 /**
  * 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;
 }
 /**
  * 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();
 }
 /**
  * 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;
 }
 /**
  * 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'));
 }
 /**
  * Get the url for the mobile diff special page to use in Desktop footer
  * @return boolean|string Return URL or false when revision id's not set
  */
 public static function getMobileUrlFromDesktop()
 {
     $req = MobileContext::singleton()->getRequest();
     $rev2 = $req->getText('diff');
     $rev1 = $req->getText('oldid');
     if ($rev1 == 'prev' || $rev1 == 'next') {
         // Actually, both do the same, WTF
         $rev1 = '';
     }
     // redirect requests to the diff page to mobile view
     if (!$rev2) {
         if ($rev1) {
             $rev2 = $rev1;
             $rev1 = '';
         } else {
             return false;
         }
     }
     if ($rev1) {
         $rev = static::getRevision($rev1);
         if ($rev) {
             // the diff parameter could be the string prev or next - deal with these cases
             if ($rev2 === 'prev') {
                 $prev = $rev->getPrevious();
                 // yes this is confusing - this is how it works arrgghh
                 $rev2 = $rev1;
                 $rev1 = $prev ? $prev->getId() : '';
             } elseif ($rev2 === 'next') {
                 $next = $rev->getNext();
                 $rev2 = $next ? $next->getId() : '';
             } else {
                 $rev2 = static::getRevision($rev2);
                 $rev2 = $rev2 ? $rev2->getId() : '';
             }
         } else {
             $rev2 = '';
         }
     }
     if ($rev2) {
         $subpage = $rev1 ? $rev1 . '...' . $rev2 : $rev2;
         $title = SpecialPage::getTitleFor('MobileDiff', $subpage);
         return $title->getLocalURL();
     }
     return false;
 }
 /**
  * Build the HTML containing the 1x1 images
  * @return string
  */
 static function getEdgeLoginHTML()
 {
     global $wgCentralAuthLoginWiki, $wgCentralAuthAutoLoginWikis;
     // Put images inside a div so that other code that manipulates page content can
     // explicitly ignore them.
     $html = Xml::openElement('div', array('id' => 'central-auth-images', 'style' => 'position: absolute;'));
     foreach ($wgCentralAuthAutoLoginWikis as $wiki) {
         $wiki = WikiMap::getWiki($wiki);
         // Use WikiReference::getFullUrl(), returns a protocol-relative URL if needed
         $params = array('type' => '1x1', 'from' => wfWikiID());
         $url = wfAppendQuery($wiki->getFullUrl('Special:CentralAutoLogin/start'), $params);
         if (self::isMobileDomain()) {
             $params['mobile'] = 1;
             // Do autologin on the mobile domain for each wiki
             $url = MobileContext::singleton()->getMobileUrl(wfAppendQuery($wiki->getFullUrl('Special:CentralAutoLogin/start'), $params));
         }
         $html .= Xml::element('img', array('src' => $url, 'alt' => '', 'title' => '', 'width' => 1, 'height' => 1, 'style' => 'border: none;'));
     }
     if ($wgCentralAuthLoginWiki) {
         $wiki = WikiMap::getWiki($wgCentralAuthLoginWiki);
         // Use WikiReference::getFullUrl(), returns a protocol-relative URL if needed
         $url = wfAppendQuery($wiki->getFullUrl('Special:CentralAutoLogin/refreshCookies'), array('type' => '1x1', 'wikiid' => wfWikiID(), 'proto' => RequestContext::getMain()->getRequest()->detectProtocol()));
         $html .= Xml::element('img', array('src' => $url, 'alt' => '', 'title' => '', 'width' => 1, 'height' => 1, 'style' => 'border: none;'));
     }
     $html .= Xml::closeElement('div');
     return $html;
 }
 /**
  * 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;
 }
 /**
  * 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();
 }