Differential D19384 Diff 46374 src/applications/notification/controller/PhabricatorNotificationPanelController.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/notification/controller/PhabricatorNotificationPanelController.php
| <?php | <?php | ||||
| final class PhabricatorNotificationPanelController | final class PhabricatorNotificationPanelController | ||||
| extends PhabricatorNotificationController { | extends PhabricatorNotificationController { | ||||
| public function handleRequest(AphrontRequest $request) { | public function handleRequest(AphrontRequest $request) { | ||||
| $viewer = $request->getViewer(); | $viewer = $request->getViewer(); | ||||
| $unread_count = $viewer->getUnreadNotificationCount(); | |||||
| $warning = $this->prunePhantomNotifications($unread_count); | |||||
| $query = id(new PhabricatorNotificationQuery()) | $query = id(new PhabricatorNotificationQuery()) | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->withUserPHIDs(array($viewer->getPHID())) | ->withUserPHIDs(array($viewer->getPHID())) | ||||
| ->setLimit(10); | ->setLimit(10); | ||||
| $stories = $query->execute(); | $stories = $query->execute(); | ||||
| $clear_ui_class = 'phabricator-notification-clear-all'; | $clear_ui_class = 'phabricator-notification-clear-all'; | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | $header = phutil_tag( | ||||
| 'class' => 'phabricator-notification-header', | 'class' => 'phabricator-notification-header', | ||||
| ), | ), | ||||
| array( | array( | ||||
| $notifications_link, | $notifications_link, | ||||
| $clear_ui, | $clear_ui, | ||||
| )); | )); | ||||
| $content = hsprintf( | $content = hsprintf( | ||||
| '%s%s%s', | '%s%s%s%s', | ||||
| $header, | $header, | ||||
| $warning, | |||||
| $content, | $content, | ||||
| $connection_ui); | $connection_ui); | ||||
| $unread_count = $viewer->getUnreadNotificationCount(); | |||||
| $json = array( | $json = array( | ||||
| 'content' => $content, | 'content' => $content, | ||||
| 'number' => (int)$unread_count, | 'number' => (int)$unread_count, | ||||
| ); | ); | ||||
| return id(new AphrontAjaxResponse())->setContent($json); | return id(new AphrontAjaxResponse())->setContent($json); | ||||
| } | } | ||||
| private function prunePhantomNotifications($unread_count) { | |||||
| // See T8953. If you have an unread notification about an object you | |||||
| // do not have permission to view, it isn't possible to clear it by | |||||
| // visiting the object. Identify these notifications and mark them as | |||||
| // read. | |||||
| $viewer = $this->getViewer(); | |||||
| if (!$unread_count) { | |||||
| return null; | |||||
| } | |||||
| $table = new PhabricatorFeedStoryNotification(); | |||||
| $conn = $table->establishConnection('r'); | |||||
| $rows = queryfx_all( | |||||
| $conn, | |||||
| 'SELECT chronologicalKey, primaryObjectPHID FROM %T | |||||
| WHERE userPHID = %s AND hasViewed = 0', | |||||
| $table->getTableName(), | |||||
| $viewer->getPHID()); | |||||
| if (!$rows) { | |||||
| return null; | |||||
| } | |||||
| $map = array(); | |||||
| foreach ($rows as $row) { | |||||
| $map[$row['primaryObjectPHID']][] = $row['chronologicalKey']; | |||||
| } | |||||
| $handles = $viewer->loadHandles(array_keys($map)); | |||||
| $purge_keys = array(); | |||||
| foreach ($handles as $handle) { | |||||
| $phid = $handle->getPHID(); | |||||
| if ($handle->isComplete()) { | |||||
| continue; | |||||
| } | |||||
| foreach ($map[$phid] as $chronological_key) { | |||||
| $purge_keys[] = $chronological_key; | |||||
| } | |||||
| } | |||||
| if (!$purge_keys) { | |||||
| return null; | |||||
| } | |||||
| $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||||
| $conn = $table->establishConnection('w'); | |||||
| queryfx( | |||||
| $conn, | |||||
| 'UPDATE %T SET hasViewed = 1 | |||||
| WHERE userPHID = %s AND chronologicalKey IN (%Ls)', | |||||
| $table->getTableName(), | |||||
| $viewer->getPHID(), | |||||
| $purge_keys); | |||||
| PhabricatorUserCache::clearCache( | |||||
| PhabricatorUserNotificationCountCacheType::KEY_COUNT, | |||||
| $viewer->getPHID()); | |||||
| unset($unguarded); | |||||
| return phutil_tag( | |||||
| 'div', | |||||
| array( | |||||
| 'class' => 'phabricator-notification phabricator-notification-warning', | |||||
| ), | |||||
| pht( | |||||
| '%s notification(s) about objects which no longer exist or which '. | |||||
| 'you can no longer see were discarded.', | |||||
| phutil_count($purge_keys))); | |||||
| } | |||||
| } | } | ||||