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
|
|
|
* Accessor and mutator for watchlist entries.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
|
|
*/
|
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.
|
|
|
|
|
*
|
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 {
|
2014-05-11 15:34:55 +00:00
|
|
|
/** @var Title */
|
2016-01-29 19:39:23 +00:00
|
|
|
private $mTitle;
|
2014-05-11 15:34:55 +00:00
|
|
|
|
|
|
|
|
/** @var User */
|
2016-01-29 19:39:23 +00:00
|
|
|
private $mUser;
|
2014-05-11 15:34:55 +00:00
|
|
|
|
|
|
|
|
/** @var int */
|
2016-01-29 19:39:23 +00:00
|
|
|
private $mCheckRights;
|
2014-05-11 15:34:55 +00:00
|
|
|
|
|
|
|
|
/** @var bool */
|
|
|
|
|
private $loaded = false;
|
|
|
|
|
|
|
|
|
|
/** @var bool */
|
|
|
|
|
private $watched;
|
|
|
|
|
|
|
|
|
|
/** @var string */
|
|
|
|
|
private $timestamp;
|
2003-11-09 11:45:12 +00:00
|
|
|
|
2015-04-15 00:53:53 +00:00
|
|
|
/**
|
|
|
|
|
* Constant to specify that user rights 'editmywatchlist' and
|
|
|
|
|
* 'viewmywatchlist' should not be checked.
|
|
|
|
|
* @since 1.22
|
|
|
|
|
*/
|
|
|
|
|
const IGNORE_USER_RIGHTS = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constant to specify that user rights 'editmywatchlist' and
|
|
|
|
|
* 'viewmywatchlist' should be checked.
|
|
|
|
|
* @since 1.22
|
|
|
|
|
*/
|
|
|
|
|
const CHECK_USER_RIGHTS = 1;
|
|
|
|
|
|
2005-01-27 17:56:04 +00:00
|
|
|
/**
|
|
|
|
|
* Create a WatchedItem object with the given user and title
|
2013-06-13 18:02:55 +00:00
|
|
|
* @since 1.22 $checkRights parameter added
|
2014-04-20 19:16:57 +00:00
|
|
|
* @param User $user The user to use for (un)watching
|
|
|
|
|
* @param Title $title The title we're going to (un)watch
|
|
|
|
|
* @param int $checkRights Whether to check the 'viewmywatchlist' and 'editmywatchlist' rights.
|
2013-06-13 18:02:55 +00:00
|
|
|
* Pass either WatchedItem::IGNORE_USER_RIGHTS or WatchedItem::CHECK_USER_RIGHTS.
|
2014-04-20 19:16:57 +00:00
|
|
|
* @return WatchedItem
|
2005-01-27 17:56:04 +00:00
|
|
|
*/
|
2014-05-11 15:34:55 +00:00
|
|
|
public static function fromUserTitle( $user, $title,
|
|
|
|
|
$checkRights = WatchedItem::CHECK_USER_RIGHTS
|
|
|
|
|
) {
|
2003-11-09 11:45:12 +00:00
|
|
|
$wl = new WatchedItem;
|
2007-05-02 15:36:17 +00:00
|
|
|
$wl->mUser = $user;
|
|
|
|
|
$wl->mTitle = $title;
|
2013-06-13 18:02:55 +00:00
|
|
|
$wl->mCheckRights = $checkRights;
|
2012-11-17 14:26:01 +00:00
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
return $wl;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-17 14:26:01 +00:00
|
|
|
/**
|
|
|
|
|
* Title being watched
|
|
|
|
|
* @return Title
|
|
|
|
|
*/
|
|
|
|
|
protected function getTitle() {
|
|
|
|
|
return $this->mTitle;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-15 20:13:54 +00:00
|
|
|
/**
|
|
|
|
|
* Helper to retrieve the title namespace
|
|
|
|
|
* @return int
|
|
|
|
|
*/
|
2012-11-17 14:26:01 +00:00
|
|
|
protected function getTitleNs() {
|
|
|
|
|
return $this->getTitle()->getNamespace();
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-15 20:13:54 +00:00
|
|
|
/**
|
|
|
|
|
* Helper to retrieve the title DBkey
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2012-11-17 14:26:01 +00:00
|
|
|
protected function getTitleDBkey() {
|
|
|
|
|
return $this->getTitle()->getDBkey();
|
|
|
|
|
}
|
2014-03-15 20:13:54 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper to retrieve the user id
|
|
|
|
|
* @return int
|
|
|
|
|
*/
|
2012-11-17 14:26:01 +00:00
|
|
|
protected function getUserId() {
|
|
|
|
|
return $this->mUser->getId();
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2012-02-10 19:35:14 +00:00
|
|
|
* Return an array of conditions to select or update the appropriate database
|
|
|
|
|
* row.
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2012-02-10 19:35:14 +00:00
|
|
|
private function dbCond() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2012-11-17 14:26:01 +00:00
|
|
|
'wl_user' => $this->getUserId(),
|
|
|
|
|
'wl_namespace' => $this->getTitleNs(),
|
|
|
|
|
'wl_title' => $this->getTitleDBkey(),
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2012-02-10 19:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Load the object from the database
|
|
|
|
|
*/
|
|
|
|
|
private function load() {
|
|
|
|
|
if ( $this->loaded ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$this->loaded = true;
|
|
|
|
|
|
2013-05-23 18:38:05 +00:00
|
|
|
// Only loggedin user can have a watchlist
|
|
|
|
|
if ( $this->mUser->isAnon() ) {
|
|
|
|
|
$this->watched = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-27 13:49:56 +00:00
|
|
|
// some pages cannot be watched
|
|
|
|
|
if ( !$this->getTitle()->isWatchable() ) {
|
|
|
|
|
$this->watched = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
# Pages and their talk pages are considered equivalent for watching;
|
|
|
|
|
# remember that talk namespaces are numbered as page namespace+1.
|
2004-07-18 08:48:43 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2012-02-10 19:35:14 +00:00
|
|
|
$row = $dbr->selectRow( 'watchlist', 'wl_notificationtimestamp',
|
|
|
|
|
$this->dbCond(), __METHOD__ );
|
|
|
|
|
|
|
|
|
|
if ( $row === false ) {
|
|
|
|
|
$this->watched = false;
|
|
|
|
|
} else {
|
|
|
|
|
$this->watched = true;
|
|
|
|
|
$this->timestamp = $row->wl_notificationtimestamp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-13 18:02:55 +00:00
|
|
|
/**
|
|
|
|
|
* Check permissions
|
2014-04-20 19:16:57 +00:00
|
|
|
* @param string $what 'viewmywatchlist' or 'editmywatchlist'
|
2014-08-23 20:34:25 +00:00
|
|
|
* @return bool
|
2013-06-13 18:02:55 +00:00
|
|
|
*/
|
|
|
|
|
private function isAllowed( $what ) {
|
|
|
|
|
return !$this->mCheckRights || $this->mUser->isAllowed( $what );
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
/**
|
|
|
|
|
* Is mTitle being watched by mUser?
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function isWatched() {
|
2013-06-13 18:02:55 +00:00
|
|
|
if ( !$this->isAllowed( 'viewmywatchlist' ) ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
$this->load();
|
|
|
|
|
return $this->watched;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the notification timestamp of this entry.
|
|
|
|
|
*
|
2014-04-23 11:39:49 +00:00
|
|
|
* @return bool|null|string False if the page is not watched, the value of
|
2014-04-20 19:16:57 +00:00
|
|
|
* the wl_notificationtimestamp field otherwise
|
2012-02-10 19:35:14 +00:00
|
|
|
*/
|
|
|
|
|
public function getNotificationTimestamp() {
|
2013-06-13 18:02:55 +00:00
|
|
|
if ( !$this->isAllowed( 'viewmywatchlist' ) ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
$this->load();
|
|
|
|
|
if ( $this->watched ) {
|
|
|
|
|
return $this->timestamp;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reset the notification timestamp of this entry
|
|
|
|
|
*
|
2014-04-20 19:16:57 +00:00
|
|
|
* @param bool $force Whether to force the write query to be executed even if the
|
|
|
|
|
* page is not watched or the notification timestamp is already NULL.
|
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
|
|
|
* @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
|
2012-02-10 19:35:14 +00:00
|
|
|
*/
|
2015-04-15 00:53:53 +00:00
|
|
|
public function resetNotificationTimestamp(
|
2016-01-29 19:10:26 +00:00
|
|
|
$force = '', $oldid = 0
|
2015-04-15 00:53:53 +00:00
|
|
|
) {
|
2013-05-23 18:38:05 +00:00
|
|
|
// Only loggedin user can have a watchlist
|
2013-06-13 18:02:55 +00:00
|
|
|
if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
|
2013-05-23 18:38:05 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
if ( $force != 'force' ) {
|
|
|
|
|
$this->load();
|
|
|
|
|
if ( !$this->watched || $this->timestamp === null ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
$title = $this->getTitle();
|
|
|
|
|
if ( !$oldid ) {
|
|
|
|
|
// No oldid given, assuming latest revision; clear the timestamp.
|
|
|
|
|
$notificationTimestamp = null;
|
|
|
|
|
} elseif ( !$title->getNextRevisionID( $oldid ) ) {
|
|
|
|
|
// Oldid given and is the latest revision for this title; clear the timestamp.
|
|
|
|
|
$notificationTimestamp = null;
|
|
|
|
|
} else {
|
|
|
|
|
// See if the version marked as read is more recent than the one we're viewing.
|
|
|
|
|
// Call load() if it wasn't called before due to $force.
|
|
|
|
|
$this->load();
|
|
|
|
|
|
|
|
|
|
if ( $this->timestamp === null ) {
|
|
|
|
|
// This can only happen if $force is enabled.
|
|
|
|
|
$notificationTimestamp = null;
|
|
|
|
|
} else {
|
|
|
|
|
// Oldid given and isn't the latest; update the timestamp.
|
|
|
|
|
// This will result in no further notification emails being sent!
|
2015-04-13 19:18:31 +00:00
|
|
|
$notificationTimestamp = Revision::getTimestampFromId( $title, $oldid );
|
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
|
|
|
// We need to go one second to the future because of various strict comparisons
|
|
|
|
|
// throughout the codebase
|
|
|
|
|
$ts = new MWTimestamp( $notificationTimestamp );
|
|
|
|
|
$ts->timestamp->add( new DateInterval( 'PT1S' ) );
|
|
|
|
|
$notificationTimestamp = $ts->getTimestamp( TS_MW );
|
|
|
|
|
|
|
|
|
|
if ( $notificationTimestamp < $this->timestamp ) {
|
|
|
|
|
if ( $force != 'force' ) {
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
// This is a little silly…
|
|
|
|
|
$notificationTimestamp = $this->timestamp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-15 00:53:53 +00:00
|
|
|
// If the page is watched by the user (or may be watched), update the timestamp
|
2016-01-29 19:10:26 +00:00
|
|
|
$job = new ActivityUpdateJob(
|
|
|
|
|
$title,
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2016-01-29 19:10:26 +00:00
|
|
|
'type' => 'updateWatchlistNotification',
|
|
|
|
|
'userid' => $this->getUserId(),
|
|
|
|
|
'notifTime' => $notificationTimestamp,
|
|
|
|
|
'curTime' => time()
|
2016-02-17 09:09:32 +00:00
|
|
|
]
|
2016-01-29 19:10:26 +00:00
|
|
|
);
|
|
|
|
|
// Try to run this post-send
|
|
|
|
|
DeferredUpdates::addCallableUpdate( function() use ( $job ) {
|
|
|
|
|
$job->run();
|
|
|
|
|
} );
|
2015-04-15 00:53:53 +00:00
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
$this->timestamp = null;
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-27 17:56:04 +00:00
|
|
|
/**
|
2014-08-15 21:04:10 +00:00
|
|
|
* @param WatchedItem[] $items
|
2013-05-23 18:38:05 +00:00
|
|
|
* @return bool
|
2005-01-27 17:56:04 +00:00
|
|
|
*/
|
2014-08-25 16:25:39 +00:00
|
|
|
public static function batchAddWatch( array $items ) {
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2014-08-15 21:04:10 +00:00
|
|
|
if ( wfReadOnly() ) {
|
2013-05-23 18:38:05 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$rows = [];
|
2014-08-15 21:04:10 +00:00
|
|
|
foreach ( $items as $item ) {
|
|
|
|
|
// Only loggedin user can have a watchlist
|
|
|
|
|
if ( $item->mUser->isAnon() || !$item->isAllowed( 'editmywatchlist' ) ) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2016-02-17 09:09:32 +00:00
|
|
|
$rows[] = [
|
2014-08-15 21:04:10 +00:00
|
|
|
'wl_user' => $item->getUserId(),
|
|
|
|
|
'wl_namespace' => MWNamespace::getSubject( $item->getTitleNs() ),
|
|
|
|
|
'wl_title' => $item->getTitleDBkey(),
|
|
|
|
|
'wl_notificationtimestamp' => null,
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2014-08-15 21:04:10 +00:00
|
|
|
// Every single watched page needs now to be listed in watchlist;
|
|
|
|
|
// namespace:page and namespace_talk:page need separate entries:
|
2016-02-17 09:09:32 +00:00
|
|
|
$rows[] = [
|
2014-08-15 21:04:10 +00:00
|
|
|
'wl_user' => $item->getUserId(),
|
|
|
|
|
'wl_namespace' => MWNamespace::getTalk( $item->getTitleNs() ),
|
|
|
|
|
'wl_title' => $item->getTitleDBkey(),
|
2013-02-03 20:05:24 +00:00
|
|
|
'wl_notificationtimestamp' => null
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2014-08-15 21:04:10 +00:00
|
|
|
$item->watched = true;
|
|
|
|
|
}
|
2004-12-18 03:47:11 +00:00
|
|
|
|
2014-08-15 21:04:10 +00:00
|
|
|
if ( !$rows ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2004-06-11 15:54:29 +00:00
|
|
|
|
2014-08-15 21:04:10 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2014-08-25 17:16:36 +00:00
|
|
|
foreach ( array_chunk( $rows, 100 ) as $toInsert ) {
|
2014-08-15 21:04:10 +00:00
|
|
|
// Use INSERT IGNORE to avoid overwriting the notification timestamp
|
|
|
|
|
// if there's already an entry for this page
|
|
|
|
|
$dbw->insert( 'watchlist', $toInsert, __METHOD__, 'IGNORE' );
|
|
|
|
|
}
|
2012-02-10 19:35:14 +00:00
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-15 21:04:10 +00:00
|
|
|
/**
|
|
|
|
|
* Given a title and user (assumes the object is setup), add the watch to the database.
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function addWatch() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return self::batchAddWatch( [ $this ] );
|
2014-08-15 21:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
2008-09-15 17:40:12 +00:00
|
|
|
/**
|
|
|
|
|
* Same as addWatch, only the opposite.
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function removeWatch() {
|
2011-02-13 19:12:24 +00:00
|
|
|
|
2013-05-23 18:38:05 +00:00
|
|
|
// Only loggedin user can have a watchlist
|
2013-06-13 18:02:55 +00:00
|
|
|
if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
|
2013-05-23 18:38:05 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-14 17:55:04 +00:00
|
|
|
$success = false;
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2005-08-02 13:35:19 +00:00
|
|
|
$dbw->delete( 'watchlist',
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2012-11-17 14:26:01 +00:00
|
|
|
'wl_user' => $this->getUserId(),
|
2013-02-03 20:05:24 +00:00
|
|
|
'wl_namespace' => MWNamespace::getSubject( $this->getTitleNs() ),
|
2012-11-17 14:26:01 +00:00
|
|
|
'wl_title' => $this->getTitleDBkey(),
|
2016-02-17 09:09:32 +00:00
|
|
|
], __METHOD__
|
2004-12-18 03:47:11 +00:00
|
|
|
);
|
2005-05-14 17:55:04 +00:00
|
|
|
if ( $dbw->affectedRows() ) {
|
|
|
|
|
$success = true;
|
|
|
|
|
}
|
2004-12-18 03:47:11 +00:00
|
|
|
|
2013-03-04 08:44:38 +00:00
|
|
|
# the following code compensates the new behavior, introduced by the
|
2005-01-27 17:56:04 +00:00
|
|
|
# enotif patch, that every single watched page needs now to be listed
|
|
|
|
|
# in watchlist namespace:page and namespace_talk:page had separate
|
|
|
|
|
# entries: clear them
|
2004-12-18 03:47:11 +00:00
|
|
|
$dbw->delete( 'watchlist',
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2012-11-17 14:26:01 +00:00
|
|
|
'wl_user' => $this->getUserId(),
|
2013-02-03 20:05:24 +00:00
|
|
|
'wl_namespace' => MWNamespace::getTalk( $this->getTitleNs() ),
|
2012-11-17 14:26:01 +00:00
|
|
|
'wl_title' => $this->getTitleDBkey(),
|
2016-02-17 09:09:32 +00:00
|
|
|
], __METHOD__
|
2004-07-18 08:48:43 +00:00
|
|
|
);
|
2005-08-02 13:35:19 +00:00
|
|
|
|
2004-07-18 08:48:43 +00:00
|
|
|
if ( $dbw->affectedRows() ) {
|
2005-05-14 17:55:04 +00:00
|
|
|
$success = true;
|
|
|
|
|
}
|
2011-02-13 19:12:24 +00:00
|
|
|
|
2012-02-10 19:35:14 +00:00
|
|
|
$this->watched = false;
|
|
|
|
|
|
2005-05-14 17:55:04 +00:00
|
|
|
return $success;
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2016-01-26 16:36:05 +00:00
|
|
|
* @deprecated since 1.27. See WatchedItemStore::duplicateEntry
|
2005-11-26 00:54:07 +00:00
|
|
|
*
|
2016-01-26 16:36:05 +00:00
|
|
|
* @param Title $oldTitle
|
|
|
|
|
* @param Title $newTitle
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2016-01-26 16:36:05 +00:00
|
|
|
public static function duplicateEntries( Title $oldTitle, Title $newTitle ) {
|
|
|
|
|
$store = WatchedItemStore::getDefaultInstance();
|
|
|
|
|
$store->duplicateEntry( $oldTitle->getSubjectPage(), $newTitle->getSubjectPage() );
|
|
|
|
|
$store->duplicateEntry( $oldTitle->getTalkPage(), $newTitle->getTalkPage() );
|
2005-11-26 00:54:07 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|