2016-05-27 21:10:04 +00:00
|
|
|
<?php
|
|
|
|
|
2018-08-30 01:03:16 +00:00
|
|
|
class ApiEchoUnreadNotificationPages extends ApiQueryBase {
|
|
|
|
use ApiCrossWiki;
|
|
|
|
|
2016-05-27 21:10:04 +00:00
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
|
|
|
protected $crossWikiSummary = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param ApiQuery $query
|
|
|
|
* @param string $moduleName
|
|
|
|
*/
|
|
|
|
public function __construct( $query, $moduleName ) {
|
|
|
|
parent::__construct( $query, $moduleName, 'unp' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-11-03 19:16:56 +00:00
|
|
|
* @throws ApiUsageException
|
2016-05-27 21:10:04 +00:00
|
|
|
*/
|
|
|
|
public function execute() {
|
|
|
|
// To avoid API warning, register the parameter used to bust browser cache
|
|
|
|
$this->getMain()->getVal( '_' );
|
|
|
|
|
2020-12-22 15:36:58 +00:00
|
|
|
if ( !$this->getUser()->isRegistered() ) {
|
2016-11-03 19:16:56 +00:00
|
|
|
$this->dieWithError( 'apierror-mustbeloggedin-generic', 'login-required' );
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$params = $this->extractRequestParams();
|
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
$result = [];
|
2019-04-19 15:04:52 +00:00
|
|
|
if ( in_array( wfWikiID(), $this->getRequestedWikis() ) ) {
|
2016-06-22 22:14:48 +00:00
|
|
|
$result[wfWikiID()] = $this->getFromLocal( $params['limit'], $params['grouppages'] );
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( $this->getRequestedForeignWikis() ) {
|
2016-08-03 18:48:22 +00:00
|
|
|
$result += $this->getUnreadNotificationPagesFromForeign();
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2018-08-30 01:03:16 +00:00
|
|
|
$apis = $this->getForeignNotifications()->getApiEndpoints( $this->getRequestedWikis() );
|
2016-05-27 21:10:04 +00:00
|
|
|
foreach ( $result as $wiki => $data ) {
|
|
|
|
$result[$wiki]['source'] = $apis[$wiki];
|
2016-12-05 18:51:07 +00:00
|
|
|
$result[$wiki]['pages'] = $data['pages'] ?: [];
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$this->getResult()->addValue( 'query', $this->getModuleName(), $result );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param int $limit
|
2016-06-22 22:14:48 +00:00
|
|
|
* @param bool $groupPages
|
2016-05-27 21:10:04 +00:00
|
|
|
* @return array
|
2019-11-07 19:35:03 +00:00
|
|
|
* @phan-return array{pages:array[],totalCount:int}
|
2016-05-27 21:10:04 +00:00
|
|
|
*/
|
2016-06-22 22:14:48 +00:00
|
|
|
protected function getFromLocal( $limit, $groupPages ) {
|
2016-10-04 18:35:30 +00:00
|
|
|
$attributeManager = EchoAttributeManager::newFromGlobalVars();
|
|
|
|
$enabledTypes = $attributeManager->getUserEnabledEvents( $this->getUser(), 'web' );
|
|
|
|
|
2017-09-24 05:23:47 +00:00
|
|
|
$dbr = MWEchoDbFactory::newFromDefault()->getEchoDb( DB_REPLICA );
|
2016-06-22 22:14:48 +00:00
|
|
|
// If $groupPages is true, we need to fetch all pages and apply the ORDER BY and LIMIT ourselves
|
|
|
|
// after grouping.
|
2016-12-05 18:51:07 +00:00
|
|
|
$extraOptions = $groupPages ? [] : [ 'ORDER BY' => 'count DESC', 'LIMIT' => $limit ];
|
2016-05-27 21:10:04 +00:00
|
|
|
$rows = $dbr->select(
|
2016-12-05 18:51:07 +00:00
|
|
|
[ 'echo_event', 'echo_notification' ],
|
|
|
|
[ 'event_page_id', 'count' => 'COUNT(*)' ],
|
|
|
|
[
|
2016-05-27 21:10:04 +00:00
|
|
|
'notification_user' => $this->getUser()->getId(),
|
|
|
|
'notification_read_timestamp' => null,
|
2016-07-21 13:53:08 +00:00
|
|
|
'event_deleted' => 0,
|
2016-10-04 18:35:30 +00:00
|
|
|
'event_type' => $enabledTypes,
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
2016-05-27 21:10:04 +00:00
|
|
|
__METHOD__,
|
2016-12-05 18:51:07 +00:00
|
|
|
[
|
2016-05-27 21:10:04 +00:00
|
|
|
'GROUP BY' => 'event_page_id',
|
2016-12-05 18:51:07 +00:00
|
|
|
] + $extraOptions,
|
|
|
|
[ 'echo_notification' => [ 'INNER JOIN', 'notification_event = event_id' ] ]
|
2016-05-27 21:10:04 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
if ( $rows === false ) {
|
2019-11-07 19:35:03 +00:00
|
|
|
return [
|
|
|
|
'pages' => [],
|
|
|
|
'totalCount' => 0,
|
|
|
|
];
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 22:14:48 +00:00
|
|
|
$nullCount = 0;
|
2016-12-05 18:51:07 +00:00
|
|
|
$pageCounts = [];
|
2016-05-27 21:10:04 +00:00
|
|
|
foreach ( $rows as $row ) {
|
2016-06-22 22:14:48 +00:00
|
|
|
if ( $row->event_page_id !== null ) {
|
2020-08-11 09:33:33 +00:00
|
|
|
$pageCounts[(int)$row->event_page_id] = intval( $row->count );
|
2016-06-22 22:14:48 +00:00
|
|
|
} else {
|
|
|
|
$nullCount = intval( $row->count );
|
|
|
|
}
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 22:14:48 +00:00
|
|
|
$titles = Title::newFromIDs( array_keys( $pageCounts ) );
|
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
$groupCounts = [];
|
2016-05-27 21:10:04 +00:00
|
|
|
foreach ( $titles as $title ) {
|
2016-06-22 22:14:48 +00:00
|
|
|
if ( $groupPages ) {
|
|
|
|
// If $title is a talk page, add its count to its subject page's count
|
|
|
|
$pageName = $title->getSubjectPage()->getPrefixedText();
|
|
|
|
} else {
|
|
|
|
$pageName = $title->getPrefixedText();
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:33:33 +00:00
|
|
|
$count = $pageCounts[$title->getArticleID()] ?? 0;
|
2016-06-22 22:14:48 +00:00
|
|
|
if ( isset( $groupCounts[$pageName] ) ) {
|
|
|
|
$groupCounts[$pageName] += $count;
|
|
|
|
} else {
|
|
|
|
$groupCounts[$pageName] = $count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$userPageName = $this->getUser()->getUserPage()->getPrefixedText();
|
|
|
|
if ( $nullCount > 0 && $groupPages ) {
|
|
|
|
// Add the count for NULL (not associated with any page) to the count for the user page
|
|
|
|
if ( isset( $groupCounts[$userPageName] ) ) {
|
|
|
|
$groupCounts[$userPageName] += $nullCount;
|
|
|
|
} else {
|
|
|
|
$groupCounts[$userPageName] = $nullCount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
arsort( $groupCounts );
|
|
|
|
if ( $groupPages ) {
|
|
|
|
$groupCounts = array_slice( $groupCounts, 0, $limit );
|
|
|
|
}
|
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
$result = [];
|
2016-06-22 22:14:48 +00:00
|
|
|
foreach ( $groupCounts as $pageName => $count ) {
|
|
|
|
if ( $groupPages ) {
|
|
|
|
$title = Title::newFromText( $pageName );
|
2017-07-31 22:08:26 +00:00
|
|
|
$pages = [ $title->getSubjectPage()->getPrefixedText() ];
|
|
|
|
if ( $title->canHaveTalkPage() ) {
|
|
|
|
$pages[] = $title->getTalkPage()->getPrefixedText();
|
|
|
|
}
|
2016-06-22 22:14:48 +00:00
|
|
|
if ( $pageName === $userPageName ) {
|
|
|
|
$pages[] = null;
|
|
|
|
}
|
2016-12-05 18:51:07 +00:00
|
|
|
$pageDescription = [
|
2016-06-22 22:14:48 +00:00
|
|
|
'ns' => $title->getNamespace(),
|
|
|
|
'title' => $title->getPrefixedText(),
|
|
|
|
'unprefixed' => $title->getText(),
|
|
|
|
'pages' => $pages,
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2016-06-22 22:14:48 +00:00
|
|
|
} else {
|
2016-12-05 18:51:07 +00:00
|
|
|
$pageDescription = [ 'title' => $pageName ];
|
2016-06-22 22:14:48 +00:00
|
|
|
}
|
2016-12-05 18:51:07 +00:00
|
|
|
$result[] = $pageDescription + [
|
2016-06-22 22:14:48 +00:00
|
|
|
'count' => $count,
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2016-06-22 22:14:48 +00:00
|
|
|
}
|
|
|
|
if ( !$groupPages && $nullCount > 0 ) {
|
2016-12-05 18:51:07 +00:00
|
|
|
$result[] = [
|
2016-06-22 22:14:48 +00:00
|
|
|
'title' => null,
|
|
|
|
'count' => $nullCount,
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
2016-12-05 18:51:07 +00:00
|
|
|
return [
|
2016-06-22 16:11:34 +00:00
|
|
|
'pages' => $result,
|
|
|
|
'totalCount' => MWEchoNotifUser::newFromUser( $this->getUser() )->getLocalNotificationCount(),
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-11-07 19:35:03 +00:00
|
|
|
* @return array[]
|
2016-05-27 21:10:04 +00:00
|
|
|
*/
|
2016-08-03 18:48:22 +00:00
|
|
|
protected function getUnreadNotificationPagesFromForeign() {
|
2016-12-05 18:51:07 +00:00
|
|
|
$result = [];
|
2016-08-03 18:48:22 +00:00
|
|
|
foreach ( $this->getFromForeign() as $wiki => $data ) {
|
2016-05-27 21:10:04 +00:00
|
|
|
$result[$wiki] = $data['query'][$this->getModuleName()][$wiki];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-08-13 07:25:22 +00:00
|
|
|
* @return array[]
|
2016-05-27 21:10:04 +00:00
|
|
|
*/
|
|
|
|
public function getAllowedParams() {
|
|
|
|
global $wgEchoMaxUpdateCount;
|
|
|
|
|
2018-08-30 01:03:16 +00:00
|
|
|
return $this->getCrossWikiParams() + [
|
2016-12-05 18:51:07 +00:00
|
|
|
'grouppages' => [
|
2016-06-22 22:14:48 +00:00
|
|
|
ApiBase::PARAM_TYPE => 'boolean',
|
|
|
|
ApiBase::PARAM_DFLT => false,
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
|
|
|
'limit' => [
|
2016-05-27 21:10:04 +00:00
|
|
|
ApiBase::PARAM_TYPE => 'limit',
|
2016-06-22 22:14:48 +00:00
|
|
|
ApiBase::PARAM_DFLT => 10,
|
2016-05-27 21:10:04 +00:00
|
|
|
ApiBase::PARAM_MIN => 1,
|
|
|
|
ApiBase::PARAM_MAX => $wgEchoMaxUpdateCount,
|
|
|
|
ApiBase::PARAM_MAX2 => $wgEchoMaxUpdateCount,
|
2016-12-05 18:51:07 +00:00
|
|
|
],
|
2016-05-27 21:10:04 +00:00
|
|
|
// there is no `offset` or `continue` value: the set of possible
|
|
|
|
// notifications is small enough to allow fetching all of them at
|
|
|
|
// once, and any sort of fetching would be unreliable because
|
|
|
|
// they're sorted based on count of notifications, which could
|
|
|
|
// change in between requests
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @see ApiBase::getExamplesMessages()
|
2018-08-13 07:25:22 +00:00
|
|
|
* @return string[]
|
2016-05-27 21:10:04 +00:00
|
|
|
*/
|
|
|
|
protected function getExamplesMessages() {
|
2016-12-05 18:51:07 +00:00
|
|
|
return [
|
2016-05-27 21:10:04 +00:00
|
|
|
'action=query&meta=unreadnotificationpages' => 'apihelp-query+unreadnotificationpages-example-1',
|
2016-12-05 18:51:07 +00:00
|
|
|
];
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getHelpUrls() {
|
2019-08-27 06:13:35 +00:00
|
|
|
return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Echo_(Notifications)/API';
|
2016-05-27 21:10:04 +00:00
|
|
|
}
|
|
|
|
}
|