示例#1
0
 /**
  * If patrol is possible, output a patrol UI box. This is called from the
  * footer section of ordinary page views. If patrol is not possible or not
  * desired, does nothing.
  * Side effect: When the patrol link is build, this method will call
  * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
  *
  * @return bool
  */
 public function showPatrolFooter()
 {
     global $wgUseNPPatrol, $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $outputPage = $this->getContext()->getOutput();
     $user = $this->getContext()->getUser();
     $cache = wfGetMainCache();
     $rc = false;
     if (!$this->getTitle()->quickUserCan('patrol', $user) || !($wgUseRCPatrol || $wgUseNPPatrol)) {
         // Patrolling is disabled or the user isn't allowed to
         return false;
     }
     // New page patrol: Get the timestamp of the oldest revison which
     // the revision table holds for the given page. Then we look
     // whether it's within the RC lifespan and if it is, we try
     // to get the recentchanges row belonging to that entry
     // (with rc_new = 1).
     if ($this->mRevision && !RecentChange::isInRCLifespan($this->mRevision->getTimestamp(), 21600)) {
         // The current revision is already older than what could be in the RC table
         // 6h tolerance because the RC might not be cleaned out regularly
         return false;
     }
     // Check for cached results
     $key = wfMemcKey('NotPatrollablePage', $this->getTitle()->getArticleID());
     if ($cache->get($key)) {
         return false;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $oldestRevisionTimestamp = $dbr->selectField('revision', 'MIN( rev_timestamp )', array('rev_page' => $this->getTitle()->getArticleID()), __METHOD__);
     if ($oldestRevisionTimestamp && RecentChange::isInRCLifespan($oldestRevisionTimestamp, 21600)) {
         // 6h tolerance because the RC might not be cleaned out regularly
         $rc = RecentChange::newFromConds(array('rc_new' => 1, 'rc_timestamp' => $oldestRevisionTimestamp, 'rc_namespace' => $this->getTitle()->getNamespace(), 'rc_cur_id' => $this->getTitle()->getArticleID()), __METHOD__, array('USE INDEX' => 'new_name_timestamp'));
     } else {
         // Cache the information we gathered above in case we can't patrol
         // Don't cache in case we can patrol as this could change
         $cache->set($key, '1');
     }
     if (!$rc) {
         // Don't cache: This can be hit if the page gets accessed very fast after
         // its creation or in case we have high slave lag. In case the revision is
         // too old, we will already return above.
         return false;
     }
     if ($rc->getAttribute('rc_patrolled')) {
         // Patrolled RC entry around
         // Cache the information we gathered above in case we can't patrol
         // Don't cache in case we can patrol as this could change
         $cache->set($key, '1');
         return false;
     }
     if ($rc->getPerformer()->equals($user)) {
         // Don't show a patrol link for own creations. If the user could
         // patrol them, they already would be patrolled
         return false;
     }
     $rcid = $rc->getAttribute('rc_id');
     $token = $user->getEditToken($rcid);
     $outputPage->preventClickjacking();
     if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
         $outputPage->addModules('mediawiki.page.patrol.ajax');
     }
     $link = Linker::linkKnown($this->getTitle(), wfMessage('markaspatrolledtext')->escaped(), array(), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token));
     $outputPage->addHTML("<div class='patrollink'>" . wfMessage('markaspatrolledlink')->rawParams($link)->escaped() . '</div>');
     return true;
 }
 /**
  * Returns an array of meta data needed to build a "mark as patrolled" link and
  * adds the mediawiki.page.patrol.ajax to the output.
  *
  * @return array|false An array of meta data for a patrol link (rcid & token)
  *  or false if no link is needed
  */
 protected function getMarkPatrolledLinkInfo()
 {
     global $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $user = $this->getUser();
     // Prepare a change patrol link, if applicable
     if ($wgUseRCPatrol && $this->mNewPage->quickUserCan('patrol', $user) && RecentChange::isInRCLifespan($this->mNewRev->getTimestamp(), 21600)) {
         // Look for an unpatrolled change corresponding to this diff
         $db = wfGetDB(DB_SLAVE);
         $change = RecentChange::newFromConds(array('rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_patrolled' => 0), __METHOD__);
         if ($change && !$change->getPerformer()->equals($user)) {
             $rcid = $change->getAttribute('rc_id');
         } else {
             // None found or the page has been created by the current user.
             // If the user could patrol this it already would be patrolled
             $rcid = 0;
         }
         // Build the link
         if ($rcid) {
             $this->getOutput()->preventClickjacking();
             if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
                 $this->getOutput()->addModules('mediawiki.page.patrol.ajax');
             }
             $token = $user->getEditToken($rcid);
             return array('rcid' => $rcid, 'token' => $token);
         }
     }
     // No mark as patrolled link applicable
     return false;
 }
 /**
  * @covers RecentChange::isInRCLifespan
  * @dataProvider provideIsInRCLifespan
  */
 public function testIsInRCLifespan($maxAge, $timestamp, $tolerance, $expected)
 {
     $this->setMwGlobals('wgRCMaxAge', $maxAge);
     $this->assertEquals($expected, RecentChange::isInRCLifespan($timestamp, $tolerance));
 }
示例#4
0
 /**
  * Get a link to mark the change as patrolled, or '' if there's either no
  * revision to patrol or the user is not allowed to to it.
  * Side effect: When the patrol link is build, this method will call
  * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
  *
  * @return string
  */
 protected function markPatrolledLink()
 {
     global $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $user = $this->getUser();
     if ($this->mMarkPatrolledLink === null) {
         // Prepare a change patrol link, if applicable
         if ($wgUseRCPatrol && $this->mNewPage->quickUserCan('patrol', $user) && RecentChange::isInRCLifespan($this->mNewRev->getTimestamp(), 21600)) {
             // Look for an unpatrolled change corresponding to this diff
             $db = wfGetDB(DB_SLAVE);
             $change = RecentChange::newFromConds(array('rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_patrolled' => 0), __METHOD__, array('USE INDEX' => 'rc_timestamp'));
             if ($change && $change->getPerformer()->getName() !== $user->getName()) {
                 $rcid = $change->getAttribute('rc_id');
             } else {
                 // None found or the page has been created by the current user.
                 // If the user could patrol this it already would be patrolled
                 $rcid = 0;
             }
             // Build the link
             if ($rcid) {
                 $this->getOutput()->preventClickjacking();
                 if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
                     $this->getOutput()->addModules('mediawiki.page.patrol.ajax');
                 }
                 $token = $user->getEditToken($rcid);
                 $this->mMarkPatrolledLink = ' <span class="patrollink">[' . Linker::linkKnown($this->mNewPage, $this->msg('markaspatrolleddiff')->escaped(), array(), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token)) . ']</span>';
             } else {
                 $this->mMarkPatrolledLink = '';
             }
         } else {
             $this->mMarkPatrolledLink = '';
         }
     }
     return $this->mMarkPatrolledLink;
 }
示例#5
0
 /**
  * If patrol is possible, output a patrol UI box. This is called from the
  * footer section of ordinary page views. If patrol is not possible or not
  * desired, does nothing.
  * Side effect: When the patrol link is build, this method will call
  * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
  *
  * @return bool
  */
 public function showPatrolFooter()
 {
     global $wgUseNPPatrol, $wgUseRCPatrol, $wgUseFilePatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $outputPage = $this->getContext()->getOutput();
     $user = $this->getContext()->getUser();
     $title = $this->getTitle();
     $rc = false;
     if (!$title->quickUserCan('patrol', $user) || !($wgUseRCPatrol || $wgUseNPPatrol || $wgUseFilePatrol && $title->inNamespace(NS_FILE))) {
         // Patrolling is disabled or the user isn't allowed to
         return false;
     }
     if ($this->mRevision && !RecentChange::isInRCLifespan($this->mRevision->getTimestamp(), 21600)) {
         // The current revision is already older than what could be in the RC table
         // 6h tolerance because the RC might not be cleaned out regularly
         return false;
     }
     // Check for cached results
     $key = wfMemcKey('unpatrollable-page', $title->getArticleID());
     $cache = ObjectCache::getMainWANInstance();
     if ($cache->get($key)) {
         return false;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $oldestRevisionTimestamp = $dbr->selectField('revision', 'MIN( rev_timestamp )', ['rev_page' => $title->getArticleID()], __METHOD__);
     // New page patrol: Get the timestamp of the oldest revison which
     // the revision table holds for the given page. Then we look
     // whether it's within the RC lifespan and if it is, we try
     // to get the recentchanges row belonging to that entry
     // (with rc_new = 1).
     $recentPageCreation = false;
     if ($oldestRevisionTimestamp && RecentChange::isInRCLifespan($oldestRevisionTimestamp, 21600)) {
         // 6h tolerance because the RC might not be cleaned out regularly
         $recentPageCreation = true;
         $rc = RecentChange::newFromConds(['rc_new' => 1, 'rc_timestamp' => $oldestRevisionTimestamp, 'rc_namespace' => $title->getNamespace(), 'rc_cur_id' => $title->getArticleID()], __METHOD__);
         if ($rc) {
             // Use generic patrol message for new pages
             $markPatrolledMsg = wfMessage('markaspatrolledtext');
         }
     }
     // File patrol: Get the timestamp of the latest upload for this page,
     // check whether it is within the RC lifespan and if it is, we try
     // to get the recentchanges row belonging to that entry
     // (with rc_type = RC_LOG, rc_log_type = upload).
     $recentFileUpload = false;
     if ((!$rc || $rc->getAttribute('rc_patrolled')) && $wgUseFilePatrol && $title->getNamespace() === NS_FILE) {
         // Retrieve timestamp of most recent upload
         $newestUploadTimestamp = $dbr->selectField('image', 'MAX( img_timestamp )', ['img_name' => $title->getDBkey()], __METHOD__);
         if ($newestUploadTimestamp && RecentChange::isInRCLifespan($newestUploadTimestamp, 21600)) {
             // 6h tolerance because the RC might not be cleaned out regularly
             $recentFileUpload = true;
             $rc = RecentChange::newFromConds(['rc_type' => RC_LOG, 'rc_log_type' => 'upload', 'rc_timestamp' => $newestUploadTimestamp, 'rc_namespace' => NS_FILE, 'rc_cur_id' => $title->getArticleID()], __METHOD__, ['USE INDEX' => 'rc_timestamp']);
             if ($rc) {
                 // Use patrol message specific to files
                 $markPatrolledMsg = wfMessage('markaspatrolledtext-file');
             }
         }
     }
     if (!$recentPageCreation && !$recentFileUpload) {
         // Page creation and latest upload (for files) is too old to be in RC
         // We definitely can't patrol so cache the information
         // When a new file version is uploaded, the cache is cleared
         $cache->set($key, '1');
         return false;
     }
     if (!$rc) {
         // Don't cache: This can be hit if the page gets accessed very fast after
         // its creation / latest upload or in case we have high slave lag. In case
         // the revision is too old, we will already return above.
         return false;
     }
     if ($rc->getAttribute('rc_patrolled')) {
         // Patrolled RC entry around
         // Cache the information we gathered above in case we can't patrol
         // Don't cache in case we can patrol as this could change
         $cache->set($key, '1');
         return false;
     }
     if ($rc->getPerformer()->equals($user)) {
         // Don't show a patrol link for own creations/uploads. If the user could
         // patrol them, they already would be patrolled
         return false;
     }
     $rcid = $rc->getAttribute('rc_id');
     $token = $user->getEditToken($rcid);
     $outputPage->preventClickjacking();
     if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
         $outputPage->addModules('mediawiki.page.patrol.ajax');
     }
     $link = Linker::linkKnown($title, $markPatrolledMsg->escaped(), [], ['action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token]);
     $outputPage->addHTML("<div class='patrollink' data-mw='interface'>" . wfMessage('markaspatrolledlink')->rawParams($link)->escaped() . '</div>');
     return true;
 }
示例#6
0
 /**
  * Returns an array of meta data needed to build a "mark as patrolled" link and
  * adds the mediawiki.page.patrol.ajax to the output.
  *
  * @return array|false An array of meta data for a patrol link (rcid & token)
  *  or false if no link is needed
  */
 protected function getMarkPatrolledLinkInfo()
 {
     global $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $user = $this->getUser();
     // Prepare a change patrol link, if applicable
     if ($wgUseRCPatrol && $this->mNewPage->quickUserCan('patrol', $user) && RecentChange::isInRCLifespan($this->mNewRev->getTimestamp(), 21600)) {
         // Look for an unpatrolled change corresponding to this diff
         $db = wfGetDB(DB_REPLICA);
         $change = RecentChange::newFromConds(['rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_patrolled' => 0], __METHOD__);
         if ($change && !$change->getPerformer()->equals($user)) {
             $rcid = $change->getAttribute('rc_id');
         } else {
             // None found or the page has been created by the current user.
             // If the user could patrol this it already would be patrolled
             $rcid = 0;
         }
         // Allow extensions to possibly change the rcid here
         // For example the rcid might be set to zero due to the user
         // being the same as the performer of the change but an extension
         // might still want to show it under certain conditions
         Hooks::run('DifferenceEngineMarkPatrolledRCID', [&$rcid, $this, $change, $user]);
         // Build the link
         if ($rcid) {
             $this->getOutput()->preventClickjacking();
             if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
                 $this->getOutput()->addModules('mediawiki.page.patrol.ajax');
             }
             $token = $user->getEditToken($rcid);
             return ['rcid' => $rcid, 'token' => $token];
         }
     }
     // No mark as patrolled link applicable
     return false;
 }
 public function markPatrolledLink()
 {
     global $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $user = $this->getUser();
     if ($this->mMarkPatrolledLink === null) {
         // Prepare a change patrol link, if applicable
         if ($wgUseRCPatrol && $this->mNewPage->quickUserCan('patrol', $user) && RecentChange::isInRCLifespan($this->mNewRev->getTimestamp(), 21600)) {
             // Look for an unpatrolled change corresponding to this diff
             $db = wfGetDB(DB_SLAVE);
             $change = RecentChange::newFromConds(array('rc_timestamp' => $db->timestamp($this->mNewRev->getTimestamp()), 'rc_this_oldid' => $this->mNewid, 'rc_patrolled' => 0), __METHOD__, array('USE INDEX' => 'rc_timestamp'));
             if ($change && $change->getPerformer()->getName() !== $user->getName()) {
                 $rcid = $change->getAttribute('rc_id');
             } else {
                 // None found or the page has been created by the current user.
                 // If the user could patrol this it already would be patrolled
                 $rcid = 0;
             }
             // WIKIHOW - we might want to change the rcid here
             // for example the rcid might be set to zero due to the user being the same
             // as the performer of the change but on wikihow we still want to show it
             // under certain conditions
             wfRunHooks('DifferenceEngineMarkPatrolledRCID', array(&$rcid, $this, $change, $user));
             // Build the link
             if ($rcid) {
                 $this->getOutput()->preventClickjacking();
                 if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
                     $this->getOutput()->addModules('mediawiki.page.patrol.ajax');
                 }
                 $token = $user->getEditToken($rcid);
                 $this->mMarkPatrolledLink = ' <span class="patrollink">[' . Linker::linkKnown($this->mNewPage, $this->msg('markaspatrolleddiff')->escaped(), array(), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token)) . ']</span>';
                 // WIKIHOW - added this hook to change the markpatrolled link
                 wfRunHooks('DifferenceEngineMarkPatrolledLink', array($this, &$this->mMarkPatrolledLink, $rcid, $token));
             } else {
                 $this->mMarkPatrolledLink = '';
             }
         } else {
             $this->mMarkPatrolledLink = '';
         }
     }
     return $this->mMarkPatrolledLink;
 }