2004-02-18 02:15:00 +00:00
|
|
|
<?php
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2012-05-09 17:55:56 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
|
|
|
*
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @file
|
|
|
|
|
* @ingroup Watchlist
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2016-04-15 16:29:05 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2016-04-20 08:29:21 +00:00
|
|
|
use MediaWiki\Linker\LinkTarget;
|
2003-11-09 11:45:12 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2012-05-09 17:55:56 +00:00
|
|
|
* Representation of a pair of user and title for watchlist entries.
|
|
|
|
|
*
|
2016-02-01 11:53:01 +00:00
|
|
|
* @author Tim Starling
|
|
|
|
|
* @author Addshore
|
|
|
|
|
*
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @ingroup Watchlist
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2003-11-09 11:45:12 +00:00
|
|
|
class WatchedItem {
|
|
|
|
|
|
2015-04-15 00:53:53 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @deprecated since 1.27, see User::IGNORE_USER_RIGHTS
|
2015-04-15 00:53:53 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
const IGNORE_USER_RIGHTS = User::IGNORE_USER_RIGHTS;
|
2015-04-15 00:53:53 +00:00
|
|
|
|
|
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @deprecated since 1.27, see User::CHECK_USER_RIGHTS
|
2015-04-15 00:53:53 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
const CHECK_USER_RIGHTS = User::CHECK_USER_RIGHTS;
|
2015-04-15 00:53:53 +00:00
|
|
|
|
2005-01-27 17:56:04 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @deprecated Internal class use only
|
2005-01-27 17:56:04 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
const DEPRECATED_USAGE_TIMESTAMP = -100;
|
2003-11-09 11:45:12 +00:00
|
|
|
|
2012-11-17 14:26:01 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @var bool
|
|
|
|
|
* @deprecated Internal class use only
|
2012-11-17 14:26:01 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
public $checkRights = User::CHECK_USER_RIGHTS;
|
2012-11-17 14:26:01 +00:00
|
|
|
|
2014-03-15 20:13:54 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @var Title
|
|
|
|
|
* @deprecated Internal class use only
|
2014-03-15 20:13:54 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
private $title;
|
2012-11-17 14:26:01 +00:00
|
|
|
|
2014-03-15 20:13:54 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @var LinkTarget
|
2014-03-15 20:13:54 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
private $linkTarget;
|
2014-03-15 20:13:54 +00:00
|
|
|
|
|
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @var User
|
2014-03-15 20:13:54 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
private $user;
|
2012-11-17 14:26:01 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @var null|string the value of the wl_notificationtimestamp field
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
private $notificationTimestamp;
|
2012-02-10 19:35:14 +00:00
|
|
|
|
|
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @param User $user
|
|
|
|
|
* @param LinkTarget $linkTarget
|
|
|
|
|
* @param null|string $notificationTimestamp the value of the wl_notificationtimestamp field
|
|
|
|
|
* @param bool|null $checkRights DO NOT USE - used internally for backward compatibility
|
2012-02-10 19:35:14 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
public function __construct(
|
|
|
|
|
User $user,
|
|
|
|
|
LinkTarget $linkTarget,
|
|
|
|
|
$notificationTimestamp,
|
|
|
|
|
$checkRights = null
|
|
|
|
|
) {
|
|
|
|
|
$this->user = $user;
|
|
|
|
|
$this->linkTarget = $linkTarget;
|
|
|
|
|
$this->notificationTimestamp = $notificationTimestamp;
|
|
|
|
|
if ( $checkRights !== null ) {
|
|
|
|
|
$this->checkRights = $checkRights;
|
2012-02-10 19:35:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-13 18:02:55 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @return User
|
2013-06-13 18:02:55 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
public function getUser() {
|
|
|
|
|
return $this->user;
|
2013-06-13 18:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @return LinkTarget
|
2012-02-10 19:35:14 +00:00
|
|
|
*/
|
2016-02-01 11:53:01 +00:00
|
|
|
public function getLinkTarget() {
|
|
|
|
|
return $this->linkTarget;
|
2012-02-10 19:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the notification timestamp of this entry.
|
|
|
|
|
*
|
2016-02-01 11:53:01 +00:00
|
|
|
* @return bool|null|string
|
2012-02-10 19:35:14 +00:00
|
|
|
*/
|
|
|
|
|
public function getNotificationTimestamp() {
|
2016-02-01 11:53:01 +00:00
|
|
|
// Back compat for objects constructed using self::fromUserTitle
|
|
|
|
|
if ( $this->notificationTimestamp === self::DEPRECATED_USAGE_TIMESTAMP ) {
|
|
|
|
|
// wfDeprecated( __METHOD__, '1.27' );
|
|
|
|
|
if ( $this->checkRights && !$this->user->isAllowed( 'viewmywatchlist' ) ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-04-15 16:29:05 +00:00
|
|
|
$item = MediaWikiServices::getInstance()->getWatchedItemStore()
|
2016-02-01 11:53:01 +00:00
|
|
|
->loadWatchedItem( $this->user, $this->linkTarget );
|
|
|
|
|
if ( $item ) {
|
|
|
|
|
$this->notificationTimestamp = $item->getNotificationTimestamp();
|
|
|
|
|
} else {
|
|
|
|
|
$this->notificationTimestamp = false;
|
|
|
|
|
}
|
2012-02-10 19:35:14 +00:00
|
|
|
}
|
2016-02-01 11:53:01 +00:00
|
|
|
return $this->notificationTimestamp;
|
2012-02-10 19:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* Back compat pre 1.27 with the WatchedItemStore introduction
|
|
|
|
|
* @todo remove in 1.28/9
|
|
|
|
|
* -------------------------------------------------
|
2012-02-10 19:35:14 +00:00
|
|
|
*/
|
2013-05-23 18:38:05 +00:00
|
|
|
|
2016-02-01 11:53:01 +00:00
|
|
|
/**
|
|
|
|
|
* @return Title
|
|
|
|
|
* @deprecated Internal class use only
|
|
|
|
|
*/
|
|
|
|
|
public function getTitle() {
|
|
|
|
|
if ( !$this->title ) {
|
2016-04-20 05:21:09 +00:00
|
|
|
$this->title = Title::newFromLinkTarget( $this->linkTarget );
|
2012-02-10 19:35:14 +00:00
|
|
|
}
|
2016-02-01 11:53:01 +00:00
|
|
|
return $this->title;
|
|
|
|
|
}
|
2012-02-10 19:35:14 +00:00
|
|
|
|
2016-02-01 11:53:01 +00:00
|
|
|
/**
|
|
|
|
|
* @deprecated since 1.27 Use the constructor, WatchedItemStore::getWatchedItem()
|
|
|
|
|
* or WatchedItemStore::loadWatchedItem()
|
|
|
|
|
*/
|
|
|
|
|
public static function fromUserTitle( $user, $title, $checkRights = User::CHECK_USER_RIGHTS ) {
|
2016-05-04 16:14:24 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.27' );
|
2016-02-01 11:53:01 +00:00
|
|
|
return new self( $user, $title, self::DEPRECATED_USAGE_TIMESTAMP, (bool)$checkRights );
|
|
|
|
|
}
|
Correctly update wl_notificationtimestamp when viewing old revisions
== Prelude ==
wl_notificationtimestamp controls sending the user e-mail
notifications about changes to pages, as well as showing the "updated
since last visit" markers on history pages, recent changes and
watchlist.
== The bug ==
Previously, on every view of a page, the notification timestamp was
cleared, regardless of whether the user as actually viewing the latest
revision. When viewing a diff, however, the timestamp was cleared only
if one of the revisions being compared was the latest one of its page.
The same behavior applied to talk page message indicators (which are
actually stored sepately to cater to anonymous users).
This was inconsistent and surprising when one was attempting to, say,
go through the 50 new posts to a discussion page in a peacemeal
fashion.
== The fix ==
If the revision being viewed is the latest (or can't be determined),
the timestamp is cleared as previously, as this is necessary to
reenable e-mail notifications for given user and page.
If the revision isn't the latest, the timestamp is updated to
revision's timestamp plus one second. This uses up to two simple
(selectField) indexed queries per page view, only fired when we
do not already know we're looking at the latest version.
Talk page indicator is updated to point at the next revision after the
one being viewed, or cleared if viewing the latest revision. The
UserClearNewTalkNotification hook gained $oldid as the second argument
(a backwards-compatible change). In Skin, we no longer ignore the
indicator being present if we're viewing the talk page, as it might
still be valid.
== The bonus ==
Comments and formatting was updated in a few places, including
tables.sql and Wiki.php.
The following functions gained a second, optional $oldid parameter
(holy indirection, Batman!):
* WikiPage#doViewUpdates()
* User#clearNotification()
* WatchedItem#resetNotificationTimestamp()
DifferenceEngine gained a public method mapDiffPrevNext() used
to parse the ids from URL parameters like oldid=12345&diff=prev,
factored out of loadRevisionIds(). A bug where the NewDifferenceEngine
hook would not be called in some cases, dating back to its
introduction in r45518, was fixed in the process.
Bug: 41759
Change-Id: I4144ba1987b8d7a7e8b24f4f067eedac2ae44459
2013-09-16 10:31:40 +00:00
|
|
|
|
2014-08-15 21:04:10 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @deprecated since 1.27 Use User::addWatch()
|
2014-08-15 21:04:10 +00:00
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function addWatch() {
|
2016-05-04 16:14:24 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.27' );
|
2016-02-01 11:53:01 +00:00
|
|
|
$this->user->addWatch( $this->getTitle(), $this->checkRights );
|
|
|
|
|
return true;
|
2014-08-15 21:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
2008-09-15 17:40:12 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @deprecated since 1.27 Use User::removeWatch()
|
2008-09-15 17:40:12 +00:00
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function removeWatch() {
|
2016-05-04 16:14:24 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.27' );
|
2016-02-01 11:53:01 +00:00
|
|
|
if ( $this->checkRights && !$this->user->isAllowed( 'editmywatchlist' ) ) {
|
2013-05-23 18:38:05 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-01 11:53:01 +00:00
|
|
|
$this->user->removeWatch( $this->getTitle(), $this->checkRights );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2013-05-23 18:38:05 +00:00
|
|
|
|
2016-02-01 11:53:01 +00:00
|
|
|
/**
|
|
|
|
|
* @deprecated since 1.27 Use User::isWatched()
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function isWatched() {
|
2016-05-04 16:14:24 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.27' );
|
2016-02-01 11:53:01 +00:00
|
|
|
return $this->user->isWatched( $this->getTitle(), $this->checkRights );
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2016-02-01 11:53:01 +00:00
|
|
|
* @deprecated since 1.27 Use WatchedItemStore::duplicateAllAssociatedEntries()
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2016-01-26 16:36:05 +00:00
|
|
|
public static function duplicateEntries( Title $oldTitle, Title $newTitle ) {
|
2016-05-04 16:14:24 +00:00
|
|
|
wfDeprecated( __METHOD__, '1.27' );
|
2016-04-15 16:29:05 +00:00
|
|
|
$store = MediaWikiServices::getInstance()->getWatchedItemStore();
|
2016-02-01 11:53:01 +00:00
|
|
|
$store->duplicateAllAssociatedEntries( $oldTitle, $newTitle );
|
2005-11-26 00:54:07 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|