示例#1
0
 /**
  * @return PageProps
  */
 public static function getInstance()
 {
     if (self::$instance === null) {
         self::$instance = new self();
     }
     return self::$instance;
 }
 public function execute()
 {
     # Only operate on existing pages
     $pages = $this->getPageSet()->getGoodTitles();
     $this->params = $this->extractRequestParams();
     if ($this->params['continue']) {
         $continueValue = intval($this->params['continue']);
         $this->dieContinueUsageIf(strval($continueValue) !== $this->params['continue']);
         $filteredPages = [];
         foreach ($pages as $id => $page) {
             if ($id >= $continueValue) {
                 $filteredPages[$id] = $page;
             }
         }
         $pages = $filteredPages;
     }
     if (!count($pages)) {
         # Nothing to do
         return;
     }
     $pageProps = PageProps::getInstance();
     $result = $this->getResult();
     if ($this->params['prop']) {
         $propnames = $this->params['prop'];
         $properties = $pageProps->getProperties($pages, $propnames);
     } else {
         $properties = $pageProps->getAllProperties($pages);
     }
     ksort($properties);
     foreach ($properties as $page => $props) {
         if (!$this->addPageProps($result, $page, $props)) {
             break;
         }
     }
 }
 /**
  * @dataProvider provideCategoryContent
  * @covers WikiCategoryPage::isHidden
  */
 public function testHiddenCategory_PropertyIsSet($isHidden)
 {
     $categoryTitle = Title::makeTitle(NS_CATEGORY, 'CategoryPage');
     $categoryPage = WikiCategoryPage::factory($categoryTitle);
     $pageProps = $this->getMockPageProps();
     $pageProps->expects($this->once())->method('getProperties')->with($categoryTitle, 'hiddencat')->will($this->returnValue($isHidden ? [$categoryTitle->getArticleID() => ''] : []));
     $scopedOverride = PageProps::overrideInstance($pageProps);
     $this->assertEquals($isHidden, $categoryPage->isHidden());
     ScopedCallback::consume($scopedOverride);
 }
示例#4
0
 /**
  * @dataProvider provideCategoryContent
  * @covers RecentChange::newForCategorization
  */
 public function testHiddenCategoryChange($isHidden)
 {
     $categoryTitle = Title::newFromText('CategoryPage', NS_CATEGORY);
     $pageProps = $this->getMockPageProps();
     $pageProps->expects($this->once())->method('getProperties')->with($categoryTitle, 'hiddencat')->will($this->returnValue($isHidden ? [$categoryTitle->getArticleID() => ''] : []));
     $scopedOverride = PageProps::overrideInstance($pageProps);
     $rc = RecentChange::newForCategorization('0', $categoryTitle, $this->user, $this->user_comment, $this->title, $categoryTitle->getLatestRevID(), $categoryTitle->getLatestRevID(), '0', false);
     $this->assertEquals($isHidden, $rc->getParam('hidden-cat'));
     ScopedCallback::consume($scopedOverride);
 }
示例#5
0
 /**
  * Returns page information in an easily-manipulated format. Array keys are used so extensions
  * may add additional information in arbitrary positions. Array values are arrays with one
  * element to be rendered as a header, arrays with two elements to be rendered as a table row.
  *
  * @return array
  */
 protected function pageInfo()
 {
     global $wgContLang;
     $user = $this->getUser();
     $lang = $this->getLanguage();
     $title = $this->getTitle();
     $id = $title->getArticleID();
     $config = $this->context->getConfig();
     $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
     $pageCounts = $this->pageCounts($this->page);
     $pageProperties = [];
     $props = PageProps::getInstance()->getAllProperties($title);
     if (isset($props[$id])) {
         $pageProperties = $props[$id];
     }
     // Basic information
     $pageInfo = [];
     $pageInfo['header-basic'] = [];
     // Display title
     $displayTitle = $title->getPrefixedText();
     if (isset($pageProperties['displaytitle'])) {
         $displayTitle = $pageProperties['displaytitle'];
     }
     $pageInfo['header-basic'][] = [$this->msg('pageinfo-display-title'), $displayTitle];
     // Is it a redirect? If so, where to?
     if ($title->isRedirect()) {
         $pageInfo['header-basic'][] = [$this->msg('pageinfo-redirectsto'), Linker::link($this->page->getRedirectTarget()) . $this->msg('word-separator')->escaped() . $this->msg('parentheses')->rawParams(Linker::link($this->page->getRedirectTarget(), $this->msg('pageinfo-redirectsto-info')->escaped(), [], ['action' => 'info']))->escaped()];
     }
     // Default sort key
     $sortKey = $title->getCategorySortkey();
     if (isset($pageProperties['defaultsort'])) {
         $sortKey = $pageProperties['defaultsort'];
     }
     $sortKey = htmlspecialchars($sortKey);
     $pageInfo['header-basic'][] = [$this->msg('pageinfo-default-sort'), $sortKey];
     // Page length (in bytes)
     $pageInfo['header-basic'][] = [$this->msg('pageinfo-length'), $lang->formatNum($title->getLength())];
     // Page ID (number not localised, as it's a database ID)
     $pageInfo['header-basic'][] = [$this->msg('pageinfo-article-id'), $id];
     // Language in which the page content is (supposed to be) written
     $pageLang = $title->getPageLanguage()->getCode();
     if ($config->get('PageLanguageUseDB') && $this->getTitle()->userCan('pagelang', $this->getUser())) {
         // Link to Special:PageLanguage with pre-filled page title if user has permissions
         $titleObj = SpecialPage::getTitleFor('PageLanguage', $title->getPrefixedText());
         $langDisp = Linker::link($titleObj, $this->msg('pageinfo-language')->escaped());
     } else {
         // Display just the message
         $langDisp = $this->msg('pageinfo-language')->escaped();
     }
     $pageInfo['header-basic'][] = [$langDisp, Language::fetchLanguageName($pageLang, $lang->getCode()) . ' ' . $this->msg('parentheses', $pageLang)->escaped()];
     // Content model of the page
     $modelHtml = htmlspecialchars(ContentHandler::getLocalizedName($title->getContentModel()));
     // If the user can change it, add a link to Special:ChangeContentModel
     if ($title->quickUserCan('editcontentmodel')) {
         $modelHtml .= ' ' . $this->msg('parentheses')->rawParams($linkRenderer->makeLink(SpecialPage::getTitleValueFor('ChangeContentModel', $title->getPrefixedText()), $this->msg('pageinfo-content-model-change')->text()))->escaped();
     }
     $pageInfo['header-basic'][] = [$this->msg('pageinfo-content-model'), $modelHtml];
     if ($title->inNamespace(NS_USER)) {
         $pageUser = User::newFromName($title->getRootText());
         if ($pageUser && $pageUser->getId() && !$pageUser->isHidden()) {
             $pageInfo['header-basic'][] = [$this->msg('pageinfo-user-id'), $pageUser->getId()];
         }
     }
     // Search engine status
     $pOutput = new ParserOutput();
     if (isset($pageProperties['noindex'])) {
         $pOutput->setIndexPolicy('noindex');
     }
     if (isset($pageProperties['index'])) {
         $pOutput->setIndexPolicy('index');
     }
     // Use robot policy logic
     $policy = $this->page->getRobotPolicy('view', $pOutput);
     $pageInfo['header-basic'][] = [$this->msg('pageinfo-robot-policy'), $this->msg("pageinfo-robot-{$policy['index']}")];
     $unwatchedPageThreshold = $config->get('UnwatchedPageThreshold');
     if ($user->isAllowed('unwatchedpages') || $unwatchedPageThreshold !== false && $pageCounts['watchers'] >= $unwatchedPageThreshold) {
         // Number of page watchers
         $pageInfo['header-basic'][] = [$this->msg('pageinfo-watchers'), $lang->formatNum($pageCounts['watchers'])];
         if ($config->get('ShowUpdatedMarker') && isset($pageCounts['visitingWatchers'])) {
             $minToDisclose = $config->get('UnwatchedPageSecret');
             if ($pageCounts['visitingWatchers'] > $minToDisclose || $user->isAllowed('unwatchedpages')) {
                 $pageInfo['header-basic'][] = [$this->msg('pageinfo-visiting-watchers'), $lang->formatNum($pageCounts['visitingWatchers'])];
             } else {
                 $pageInfo['header-basic'][] = [$this->msg('pageinfo-visiting-watchers'), $this->msg('pageinfo-few-visiting-watchers')];
             }
         }
     } elseif ($unwatchedPageThreshold !== false) {
         $pageInfo['header-basic'][] = [$this->msg('pageinfo-watchers'), $this->msg('pageinfo-few-watchers')->numParams($unwatchedPageThreshold)];
     }
     // Redirects to this page
     $whatLinksHere = SpecialPage::getTitleFor('Whatlinkshere', $title->getPrefixedText());
     $pageInfo['header-basic'][] = [Linker::link($whatLinksHere, $this->msg('pageinfo-redirects-name')->escaped(), [], ['hidelinks' => 1, 'hidetrans' => 1, 'hideimages' => $title->getNamespace() == NS_FILE]), $this->msg('pageinfo-redirects-value')->numParams(count($title->getRedirectsHere()))];
     // Is it counted as a content page?
     if ($this->page->isCountable()) {
         $pageInfo['header-basic'][] = [$this->msg('pageinfo-contentpage'), $this->msg('pageinfo-contentpage-yes')];
     }
     // Subpages of this page, if subpages are enabled for the current NS
     if (MWNamespace::hasSubpages($title->getNamespace())) {
         $prefixIndex = SpecialPage::getTitleFor('Prefixindex', $title->getPrefixedText() . '/');
         $pageInfo['header-basic'][] = [Linker::link($prefixIndex, $this->msg('pageinfo-subpages-name')->escaped()), $this->msg('pageinfo-subpages-value')->numParams($pageCounts['subpages']['total'], $pageCounts['subpages']['redirects'], $pageCounts['subpages']['nonredirects'])];
     }
     if ($title->inNamespace(NS_CATEGORY)) {
         $category = Category::newFromTitle($title);
         // $allCount is the total number of cat members,
         // not the count of how many members are normal pages.
         $allCount = (int) $category->getPageCount();
         $subcatCount = (int) $category->getSubcatCount();
         $fileCount = (int) $category->getFileCount();
         $pagesCount = $allCount - $subcatCount - $fileCount;
         $pageInfo['category-info'] = [[$this->msg('pageinfo-category-total'), $lang->formatNum($allCount)], [$this->msg('pageinfo-category-pages'), $lang->formatNum($pagesCount)], [$this->msg('pageinfo-category-subcats'), $lang->formatNum($subcatCount)], [$this->msg('pageinfo-category-files'), $lang->formatNum($fileCount)]];
     }
     // Page protection
     $pageInfo['header-restrictions'] = [];
     // Is this page affected by the cascading protection of something which includes it?
     if ($title->isCascadeProtected()) {
         $cascadingFrom = '';
         $sources = $title->getCascadeProtectionSources()[0];
         foreach ($sources as $sourceTitle) {
             $cascadingFrom .= Html::rawElement('li', [], Linker::linkKnown($sourceTitle));
         }
         $cascadingFrom = Html::rawElement('ul', [], $cascadingFrom);
         $pageInfo['header-restrictions'][] = [$this->msg('pageinfo-protect-cascading-from'), $cascadingFrom];
     }
     // Is out protection set to cascade to other pages?
     if ($title->areRestrictionsCascading()) {
         $pageInfo['header-restrictions'][] = [$this->msg('pageinfo-protect-cascading'), $this->msg('pageinfo-protect-cascading-yes')];
     }
     // Page protection
     foreach ($title->getRestrictionTypes() as $restrictionType) {
         $protectionLevel = implode(', ', $title->getRestrictions($restrictionType));
         if ($protectionLevel == '') {
             // Allow all users
             $message = $this->msg('protect-default')->escaped();
         } else {
             // Administrators only
             // Messages: protect-level-autoconfirmed, protect-level-sysop
             $message = $this->msg("protect-level-{$protectionLevel}");
             if ($message->isDisabled()) {
                 // Require "$1" permission
                 $message = $this->msg("protect-fallback", $protectionLevel)->parse();
             } else {
                 $message = $message->escaped();
             }
         }
         $expiry = $title->getRestrictionExpiry($restrictionType);
         $formattedexpiry = $this->msg('parentheses', $this->getLanguage()->formatExpiry($expiry))->escaped();
         $message .= $this->msg('word-separator')->escaped() . $formattedexpiry;
         // Messages: restriction-edit, restriction-move, restriction-create,
         // restriction-upload
         $pageInfo['header-restrictions'][] = [$this->msg("restriction-{$restrictionType}"), $message];
     }
     if (!$this->page->exists()) {
         return $pageInfo;
     }
     // Edit history
     $pageInfo['header-edits'] = [];
     $firstRev = $this->page->getOldestRevision();
     $lastRev = $this->page->getRevision();
     $batch = new LinkBatch();
     if ($firstRev) {
         $firstRevUser = $firstRev->getUserText(Revision::FOR_THIS_USER);
         if ($firstRevUser !== '') {
             $firstRevUserTitle = Title::makeTitle(NS_USER, $firstRevUser);
             $batch->addObj($firstRevUserTitle);
             $batch->addObj($firstRevUserTitle->getTalkPage());
         }
     }
     if ($lastRev) {
         $lastRevUser = $lastRev->getUserText(Revision::FOR_THIS_USER);
         if ($lastRevUser !== '') {
             $lastRevUserTitle = Title::makeTitle(NS_USER, $lastRevUser);
             $batch->addObj($lastRevUserTitle);
             $batch->addObj($lastRevUserTitle->getTalkPage());
         }
     }
     $batch->execute();
     if ($firstRev) {
         // Page creator
         $pageInfo['header-edits'][] = [$this->msg('pageinfo-firstuser'), Linker::revUserTools($firstRev)];
         // Date of page creation
         $pageInfo['header-edits'][] = [$this->msg('pageinfo-firsttime'), Linker::linkKnown($title, htmlspecialchars($lang->userTimeAndDate($firstRev->getTimestamp(), $user)), [], ['oldid' => $firstRev->getId()])];
     }
     if ($lastRev) {
         // Latest editor
         $pageInfo['header-edits'][] = [$this->msg('pageinfo-lastuser'), Linker::revUserTools($lastRev)];
         // Date of latest edit
         $pageInfo['header-edits'][] = [$this->msg('pageinfo-lasttime'), Linker::linkKnown($title, htmlspecialchars($lang->userTimeAndDate($this->page->getTimestamp(), $user)), [], ['oldid' => $this->page->getLatest()])];
     }
     // Total number of edits
     $pageInfo['header-edits'][] = [$this->msg('pageinfo-edits'), $lang->formatNum($pageCounts['edits'])];
     // Total number of distinct authors
     if ($pageCounts['authors'] > 0) {
         $pageInfo['header-edits'][] = [$this->msg('pageinfo-authors'), $lang->formatNum($pageCounts['authors'])];
     }
     // Recent number of edits (within past 30 days)
     $pageInfo['header-edits'][] = [$this->msg('pageinfo-recent-edits', $lang->formatDuration($config->get('RCMaxAge'))), $lang->formatNum($pageCounts['recent_edits'])];
     // Recent number of distinct authors
     $pageInfo['header-edits'][] = [$this->msg('pageinfo-recent-authors'), $lang->formatNum($pageCounts['recent_authors'])];
     // Array of MagicWord objects
     $magicWords = MagicWord::getDoubleUnderscoreArray();
     // Array of magic word IDs
     $wordIDs = $magicWords->names;
     // Array of IDs => localized magic words
     $localizedWords = $wgContLang->getMagicWords();
     $listItems = [];
     foreach ($pageProperties as $property => $value) {
         if (in_array($property, $wordIDs)) {
             $listItems[] = Html::element('li', [], $localizedWords[$property][1]);
         }
     }
     $localizedList = Html::rawElement('ul', [], implode('', $listItems));
     $hiddenCategories = $this->page->getHiddenCategories();
     if (count($listItems) > 0 || count($hiddenCategories) > 0 || $pageCounts['transclusion']['from'] > 0 || $pageCounts['transclusion']['to'] > 0) {
         $options = ['LIMIT' => $config->get('PageInfoTransclusionLimit')];
         $transcludedTemplates = $title->getTemplateLinksFrom($options);
         if ($config->get('MiserMode')) {
             $transcludedTargets = [];
         } else {
             $transcludedTargets = $title->getTemplateLinksTo($options);
         }
         // Page properties
         $pageInfo['header-properties'] = [];
         // Magic words
         if (count($listItems) > 0) {
             $pageInfo['header-properties'][] = [$this->msg('pageinfo-magic-words')->numParams(count($listItems)), $localizedList];
         }
         // Hidden categories
         if (count($hiddenCategories) > 0) {
             $pageInfo['header-properties'][] = [$this->msg('pageinfo-hidden-categories')->numParams(count($hiddenCategories)), Linker::formatHiddenCategories($hiddenCategories)];
         }
         // Transcluded templates
         if ($pageCounts['transclusion']['from'] > 0) {
             if ($pageCounts['transclusion']['from'] > count($transcludedTemplates)) {
                 $more = $this->msg('morenotlisted')->escaped();
             } else {
                 $more = null;
             }
             $templateListFormatter = new TemplatesOnThisPageFormatter($this->getContext(), $linkRenderer);
             $pageInfo['header-properties'][] = [$this->msg('pageinfo-templates')->numParams($pageCounts['transclusion']['from']), $templateListFormatter->format($transcludedTemplates, false, $more)];
         }
         if (!$config->get('MiserMode') && $pageCounts['transclusion']['to'] > 0) {
             if ($pageCounts['transclusion']['to'] > count($transcludedTargets)) {
                 $more = Linker::link($whatLinksHere, $this->msg('moredotdotdot')->escaped(), [], ['hidelinks' => 1, 'hideredirs' => 1]);
             } else {
                 $more = null;
             }
             $templateListFormatter = new TemplatesOnThisPageFormatter($this->getContext(), $linkRenderer);
             $pageInfo['header-properties'][] = [$this->msg('pageinfo-transclusions')->numParams($pageCounts['transclusion']['to']), $templateListFormatter->format($transcludedTargets, false, $more)];
         }
     }
     return $pageInfo;
 }
示例#6
0
 public function augmentAll(SearchResultSet $resultSet)
 {
     $titles = $resultSet->extractTitles();
     return PageProps::getInstance()->getProperties($titles, $this->propnames);
 }
示例#7
0
 /**
  * Test that getting all properties clears the single properties
  * that have been cached by getting a property, saving a new value for
  * the property, getting all properties (which clears the cached single
  * properties), then getting the property again. The new value for the
  * property rather than the cached value of the property should be
  * returned.
  */
 public function testClearCache()
 {
     $pageProps = PageProps::getInstance();
     $page1ID = $this->title1->getArticleID();
     $pageProps->getProperty($this->title1, "property1");
     $new_value = "another value";
     $this->setProperty($page1ID, "property1", $new_value);
     $pageProps->getProperties($this->title1);
     $result = $pageProps->getProperty($this->title1, "property1");
     $this->assertArrayHasKey($page1ID, $result, "Found property");
     $this->assertEquals($result[$page1ID], "another value", "Clear cache");
 }
示例#8
0
 /**
  * Checks if a category is hidden.
  *
  * @since 1.27
  *
  * @return bool
  */
 public function isHidden()
 {
     $pageId = $this->getTitle()->getArticleID();
     $pageProps = PageProps::getInstance()->getProperties($this->getTitle(), 'hiddencat');
     return isset($pageProps[$pageId]) ? true : false;
 }