jenkins-bot has submitted this change and it was merged.

Change subject: Add filter to ApiEchoNotifications
......................................................................


Add filter to ApiEchoNotifications

It lets you query for read/unread/all notifications.

Bug: T119890
Change-Id: I5d09b5ff9474c77577734e9ceb0bcbcad6c99c0c
---
M includes/api/ApiEchoNotifications.php
M includes/mapper/NotificationMapper.php
2 files changed, 91 insertions(+), 55 deletions(-)

Approvals:
  Legoktm: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/includes/api/ApiEchoNotifications.php 
b/includes/api/ApiEchoNotifications.php
index ba539fe..0c2ac92 100644
--- a/includes/api/ApiEchoNotifications.php
+++ b/includes/api/ApiEchoNotifications.php
@@ -24,7 +24,7 @@
                        if ( $params['groupbysection'] ) {
                                foreach ( $params['sections'] as $section ) {
                                        $result[$section] = 
$this->getSectionPropList(
-                                               $user, $section, 
$params['limit'],
+                                               $user, $section, 
$params['filter'], $params['limit'],
                                                $params[$section . 'continue'], 
$params['format'], $params[$section . 'unreadfirst']
                                        );
                                        $this->getResult()->setIndexedTagName( 
$result[$section]['list'], 'notification' );
@@ -39,7 +39,7 @@
                                $result = $this->getPropList(
                                        $user,
                                        
$attributeManager->getUserEnabledEventsbySections( $user, 'web', 
$params['sections'] ),
-                                       $params['limit'], $params['continue'], 
$params['format']
+                                       $params['filter'], $params['limit'], 
$params['continue'], $params['format']
                                );
                                $this->getResult()->setIndexedTagName( 
$result['list'], 'notification' );
                                // 'index' is built on top of 'list'
@@ -65,13 +65,14 @@
         * Internal method for getting the property 'list' data for individual 
section
         * @param User $user
         * @param string $section 'alert' or 'message'
+        * @param string $filter 'all', 'read' or 'unread'
         * @param int $limit
         * @param string $continue
         * @param string $format
         * @param boolean $unreadFirst
         * @return array
         */
-       protected function getSectionPropList( User $user, $section, $limit, 
$continue, $format, $unreadFirst = false ) {
+       protected function getSectionPropList( User $user, $section, $filter, 
$limit, $continue, $format, $unreadFirst = false ) {
                $attributeManager = EchoAttributeManager::newFromGlobalVars();
                $sectionEvents = 
$attributeManager->getUserEnabledEventsbySections( $user, 'web', array( 
$section ) );
 
@@ -82,7 +83,7 @@
                        );
                } else {
                        $result = $this->getPropList(
-                               $user, $sectionEvents, $limit, $continue, 
$format, $unreadFirst
+                               $user, $sectionEvents, $filter, $limit, 
$continue, $format, $unreadFirst
                        );
                }
 
@@ -95,13 +96,14 @@
         * of a set of sections or a single section
         * @param User $user
         * @param string[] $eventTypes
+        * @param string $filter 'all', 'read' or 'unread'
         * @param int $limit
         * @param string $continue
         * @param string $format
         * @param boolean $unreadFirst
         * @return array
         */
-       protected function getPropList( User $user, array $eventTypes, $limit, 
$continue, $format, $unreadFirst = false ) {
+       protected function getPropList( User $user, array $eventTypes, $filter, 
$limit, $continue, $format, $unreadFirst = false ) {
                $result = array(
                        'list' => array(),
                        'continue' => null
@@ -109,57 +111,66 @@
 
                $notifMapper = new EchoNotificationMapper();
 
-               // Prefer unread notifications. We don't care about next offset 
in this case
-               if ( $unreadFirst ) {
-                       // query for unread notifications past 'continue' 
(offset)
+               // check if we want both read & unread...
+               if ( in_array( 'read', $filter ) && in_array( '!read', $filter 
) ) {
+                       // Prefer unread notifications. We don't care about 
next offset in this case
+                       if ( $unreadFirst ) {
+                               // query for unread notifications past 
'continue' (offset)
+                               $notifs = $notifMapper->fetchUnreadByUser( 
$user, $limit + 1, $continue, $eventTypes );
+
+                               /*
+                                * 'continue' has a timestamp & id (to start 
with, in case
+                                * there would be multiple events with that 
same timestamp)
+                                * Unread notifications should always load 
first, but may be
+                                * older than read ones, but we can work with 
current
+                                * 'continue' format:
+                                * * if there's no continue, first load unread 
notifications
+                                * * if there's a continue, fetch unread 
notifications first
+                                * * if there are no unread ones, continue 
must've been
+                                *   about read notifications: fetch 'em
+                                * * if there are unread ones but first one 
doesn't match
+                                *   continue id, it must've been about read 
notifications:
+                                *   discard unread & fetch read
+                                */
+                               if ( $notifs && $continue ) {
+                                       /** @var EchoNotification $first */
+                                       $first = reset( $notifs );
+                                       $continueId = intval( trim( strrchr( 
$continue, '|' ), '|' ) );
+                                       if ( $first->getEvent()->getID() !== 
$continueId ) {
+                                               // notification doesn't match 
continue id, it must've been
+                                               // about read notifications: 
discard all unread ones
+                                               $notifs = array();
+                                       }
+                               }
+
+                               // If there are less unread notifications than 
we requested,
+                               // then fill the result with some read 
notifications
+                               $count = count( $notifs );
+                               // we need 1 more than $limit, so we can 
respond 'continue'
+                               if ( $count <= $limit ) {
+                                       // Query planner should be smart enough 
that passing a short list of ids to exclude
+                                       // will only visit at most that number 
of extra rows.
+                                       $mixedNotifs = 
$notifMapper->fetchByUser(
+                                               $user,
+                                               $limit - $count + 1,
+                                               // if there were unread 
notifications, 'continue' was for
+                                               // unread notifications and we 
should start fetching read
+                                               // notifications from start
+                                               $count > 0 ? null : $continue,
+                                               $eventTypes,
+                                               array_keys( $notifs )
+                                       );
+                                       foreach ( $mixedNotifs as $notif ) {
+                                               
$notifs[$notif->getEvent()->getId()] = $notif;
+                                       }
+                               }
+                       } else {
+                               $notifs = $notifMapper->fetchByUser( $user, 
$limit + 1, $continue, $eventTypes );
+                       }
+               } elseif ( in_array( 'read', $filter ) ) {
+                       $notifs = $notifMapper->fetchReadByUser( $user, $limit 
+ 1, $continue, $eventTypes );
+               } else { // = if ( in_array( '!read', $filter ) ) {
                        $notifs = $notifMapper->fetchUnreadByUser( $user, 
$limit + 1, $continue, $eventTypes );
-
-                       /*
-                        * 'continue' has a timestamp & id (to start with, in 
case there
-                        * would be multiple events with that same timestamp)
-                        * Unread notifications should always load first, but 
may be older
-                        * than read ones, but we can work with current 
'continue' format:
-                        * * if there is no continue, first load unread 
notifications
-                        * * if there is a continue, fetch unread notifications 
first:
-                        * * if there are no unread ones, continue must've been 
about read:
-                        *   fetch 'em
-                        * * if there are unread ones but first one doesn't 
match continue
-                        *   id, it must've been about read: discard unread & 
fetch read
-                        */
-                       if ( $notifs && $continue ) {
-                               /** @var EchoNotification $first */
-                               $first = reset( $notifs );
-                               $continueId = intval( trim( strrchr( $continue, 
'|' ), '|' ) );
-                               if ( $first->getEvent()->getID() !== 
$continueId ) {
-                                       // notification doesn't match continue 
id, it must've been
-                                       // about read notifications: discard 
all unread ones
-                                       $notifs = array();
-                               }
-                       }
-
-                       // If there are less unread notifications than we 
requested,
-                       // then fill the result with some read notifications
-                       $count = count( $notifs );
-                       // we need 1 more than $limit, so we can respond 
'continue'
-                       if ( $count <= $limit ) {
-                               // Query planner should be smart enough that 
passing a short list of ids to exclude
-                               // will only visit at most that number of extra 
rows.
-                               $mixedNotifs = $notifMapper->fetchByUser(
-                                       $user,
-                                       $limit - $count + 1,
-                                       // if there were unread notifications, 
'continue' was for
-                                       // unread notifications and we should 
start fetching read
-                                       // notifications from start
-                                       $count > 0 ? null : $continue,
-                                       $eventTypes,
-                                       array_keys( $notifs )
-                               );
-                               foreach ( $mixedNotifs as $notif ) {
-                                       $notifs[$notif->getEvent()->getId()] = 
$notif;
-                               }
-                       }
-               } else {
-                       $notifs = $notifMapper->fetchByUser( $user, $limit + 1, 
$continue, $eventTypes );
                }
 
                foreach ( $notifs as $notif ) {
@@ -224,6 +235,14 @@
        public function getAllowedParams() {
                $sections = EchoAttributeManager::$sections;
                $params = array(
+                       'filter' => array(
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_DFLT => 'read|!read',
+                               ApiBase::PARAM_TYPE => array(
+                                       'read',
+                                       '!read',
+                               ),
+                       ),
                        'prop' => array(
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_TYPE => array(
diff --git a/includes/mapper/NotificationMapper.php 
b/includes/mapper/NotificationMapper.php
index 93a41f0..bdcdc8b 100644
--- a/includes/mapper/NotificationMapper.php
+++ b/includes/mapper/NotificationMapper.php
@@ -105,6 +105,23 @@
        }
 
        /**
+        * Get read notifications by user in the amount specified by limit 
order by
+        * notification timestamp in descending order.  We have an index to 
retrieve
+        * unread notifications but it's not optimized for ordering by 
timestamp.  The
+        * descending order is only allowed if we keep the notification in low 
volume,
+        * which is done via a deleteJob
+        * @param User $user
+        * @param int $limit
+        * @param string $continue Used for offset
+        * @param string[] $eventTypes
+        * @param int $dbSource Use master or slave database
+        * @return EchoNotification[]
+        */
+       public function fetchReadByUser( User $user, $limit, $continue, array 
$eventTypes = array(), $dbSource = DB_SLAVE ) {
+               return $this->fetchByUserInternal( $user, $limit, $continue, 
$eventTypes, array( 'notification_read_timestamp IS NOT NULL' ), $dbSource );
+       }
+
+       /**
         * Get Notification by user in batch along with limit, offset etc
         *
         * @param User $user the user to get notifications for

-- 
To view, visit https://gerrit.wikimedia.org/r/258162
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I5d09b5ff9474c77577734e9ceb0bcbcad6c99c0c
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/extensions/Echo
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Matthias Mullie <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to