diff --git a/resources/sql/patches/054.subscribers.sql b/resources/sql/patches/054.subscribers.sql new file mode 100644 index 0000000000..263aa1b692 --- /dev/null +++ b/resources/sql/patches/054.subscribers.sql @@ -0,0 +1,6 @@ +CREATE TABLE phabricator_maniphest.maniphest_tasksubscriber ( + taskPHID varchar(64) BINARY NOT NULL, + subscriberPHID varchar(64) BINARY NOT NULL, + PRIMARY KEY (subscriberPHID, taskPHID), + UNIQUE KEY (taskPHID, subscriberPHID) +); diff --git a/scripts/search/reindex_maniphest.php b/scripts/search/reindex_maniphest.php index 62550d56d2..45a99b4788 100755 --- a/scripts/search/reindex_maniphest.php +++ b/scripts/search/reindex_maniphest.php @@ -26,6 +26,7 @@ $tasks = id(new ManiphestTask())->loadAll(); echo "Updating relationships for ".count($tasks)." tasks"; foreach ($tasks as $task) { ManiphestTaskProject::updateTaskProjects($task); + ManiphestTaskSubscriber::updateTaskSubscribers($task); echo '.'; } echo "\nDone.\n"; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4ce8f7c0ef..cddac1af23 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -277,6 +277,7 @@ phutil_register_library_map(array( 'ManiphestTaskProject' => 'applications/maniphest/storage/taskproject', 'ManiphestTaskQuery' => 'applications/maniphest/query', 'ManiphestTaskStatus' => 'applications/maniphest/constants/status', + 'ManiphestTaskSubscriber' => 'applications/maniphest/storage/subscriber', 'ManiphestTaskSummaryView' => 'applications/maniphest/view/tasksummary', 'ManiphestTransaction' => 'applications/maniphest/storage/transaction', 'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail', @@ -788,6 +789,7 @@ phutil_register_library_map(array( 'ManiphestTaskPriority' => 'ManiphestConstants', 'ManiphestTaskProject' => 'ManiphestDAO', 'ManiphestTaskStatus' => 'ManiphestConstants', + 'ManiphestTaskSubscriber' => 'ManiphestDAO', 'ManiphestTaskSummaryView' => 'ManiphestView', 'ManiphestTransaction' => 'ManiphestDAO', 'ManiphestTransactionDetailView' => 'ManiphestView', diff --git a/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php b/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php index b57e8c55e2..7303c65dd2 100644 --- a/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php +++ b/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php @@ -54,9 +54,10 @@ class ManiphestTaskListController extends ManiphestController { $views = array( 'User Tasks', - 'action' => 'Assigned', - 'created' => 'Created', - 'triage' => 'Need Triage', + 'action' => 'Assigned', + 'created' => 'Created', + 'subscribed' => 'Subscribed', + 'triage' => 'Need Triage', '
', 'All Tasks', 'alltriage' => 'Need Triage', @@ -70,6 +71,7 @@ class ManiphestTaskListController extends ManiphestController { $has_filter = array( 'action' => true, 'created' => true, + 'subscribed' => true, 'triage' => true, ); @@ -270,6 +272,9 @@ class ManiphestTaskListController extends ManiphestController { case 'created': $query->withAuthors($user_phids); break; + case 'subscribed': + $query->withSubscribers($user_phids); + break; case 'triage': $query->withOwners($user_phids); $query->withPriority(ManiphestTaskPriority::PRIORITY_TRIAGE); diff --git a/src/applications/maniphest/query/ManiphestTaskQuery.php b/src/applications/maniphest/query/ManiphestTaskQuery.php index 1db3f02539..08f543dcc3 100644 --- a/src/applications/maniphest/query/ManiphestTaskQuery.php +++ b/src/applications/maniphest/query/ManiphestTaskQuery.php @@ -28,6 +28,7 @@ final class ManiphestTaskQuery { private $ownerPHIDs = array(); private $includeUnowned = null; private $projectPHIDs = array(); + private $subscriberPHIDs = array(); private $status = 'status-any'; const STATUS_ANY = 'status-any'; @@ -89,6 +90,11 @@ final class ManiphestTaskQuery { return $this; } + public function withSubscribers(array $subscribers) { + $this->subscriberPHIDs = $subscribers; + return $this; + } + public function setGroupBy($group) { $this->groupBy = $group; return $this; @@ -139,6 +145,7 @@ final class ManiphestTaskQuery { $where[] = $this->buildPriorityWhereClause($conn); $where[] = $this->buildAuthorWhereClause($conn); $where[] = $this->buildOwnerWhereClause($conn); + $where[] = $this->buildSubscriberWhereClause($conn); $where[] = $this->buildProjectWhereClause($conn); $where = array_filter($where); @@ -150,6 +157,7 @@ final class ManiphestTaskQuery { $join = array(); $join[] = $this->buildProjectJoinClause($conn); + $join[] = $this->buildSubscriberJoinClause($conn); $join = array_filter($join); if ($join) { @@ -272,6 +280,17 @@ final class ManiphestTaskQuery { } } + private function buildSubscriberWhereClause($conn) { + if (!$this->subscriberPHIDs) { + return null; + } + + return qsprintf( + $conn, + 'subscriber.subscriberPHID IN (%Ls)', + $this->subscriberPHIDs); + } + private function buildProjectWhereClause($conn) { if (!$this->projectPHIDs) { return null; @@ -295,6 +314,18 @@ final class ManiphestTaskQuery { $project_dao->getTableName()); } + private function buildSubscriberJoinClause($conn) { + if (!$this->subscriberPHIDs) { + return null; + } + + $subscriber_dao = new ManiphestTaskSubscriber(); + return qsprintf( + $conn, + 'JOIN %T subscriber ON subscriber.taskPHID = task.phid', + $subscriber_dao->getTableName()); + } + private function buildOrderClause($conn) { $order = array(); diff --git a/src/applications/maniphest/query/__init__.php b/src/applications/maniphest/query/__init__.php index 19b4f9fc8c..86a637a392 100644 --- a/src/applications/maniphest/query/__init__.php +++ b/src/applications/maniphest/query/__init__.php @@ -7,6 +7,7 @@ phutil_require_module('phabricator', 'applications/maniphest/constants/owner'); +phutil_require_module('phabricator', 'applications/maniphest/storage/subscriber'); phutil_require_module('phabricator', 'applications/maniphest/storage/task'); phutil_require_module('phabricator', 'applications/maniphest/storage/taskproject'); phutil_require_module('phabricator', 'storage/qsprintf'); diff --git a/src/applications/maniphest/storage/subscriber/ManiphestTaskSubscriber.php b/src/applications/maniphest/storage/subscriber/ManiphestTaskSubscriber.php new file mode 100644 index 0000000000..a5b9222910 --- /dev/null +++ b/src/applications/maniphest/storage/subscriber/ManiphestTaskSubscriber.php @@ -0,0 +1,65 @@ + self::IDS_MANUAL, + self::CONFIG_TIMESTAMPS => false, + ); + } + + public static function updateTaskSubscribers(ManiphestTask $task) { + $dao = new ManiphestTaskSubscriber(); + $conn = $dao->establishConnection('w'); + + $sql = array(); + $subscribers = $task->getCCPHIDs(); + $subscribers[] = $task->getOwnerPHID(); + $subscribers = array_unique($subscribers); + + foreach ($subscribers as $subscriber_phid) { + $sql[] = qsprintf( + $conn, + '(%s, %s)', + $task->getPHID(), + $subscriber_phid); + } + + queryfx( + $conn, + 'DELETE FROM %T WHERE taskPHID = %s', + $dao->getTableName(), + $task->getPHID()); + if ($sql) { + queryfx( + $conn, + 'INSERT INTO %T (taskPHID, subscriberPHID) VALUES %Q', + $dao->getTableName(), + implode(', ', $sql)); + } + } + +} diff --git a/src/applications/maniphest/storage/subscriber/__init__.php b/src/applications/maniphest/storage/subscriber/__init__.php new file mode 100644 index 0000000000..6fe3a8de86 --- /dev/null +++ b/src/applications/maniphest/storage/subscriber/__init__.php @@ -0,0 +1,14 @@ +ccPHIDs = $phids; + $this->subscribersNeedUpdate = true; + return $this; + } + + public function setOwnerPHID($phid) { + $this->ownerPHID = $phid; + $this->subscribersNeedUpdate = true; + return $this; + } + public function save() { if (!$this->mailKey) { $this->mailKey = sha1(Filesystem::readRandomBytes(20)); @@ -84,6 +97,13 @@ class ManiphestTask extends ManiphestDAO { $this->projectsNeedUpdate = false; } + if ($this->subscribersNeedUpdate) { + // If we've changed the subscriber PHIDs for this task, update the link + // table. + ManiphestTaskSubscriber::updateTaskSubscribers($this); + $this->subscribersNeedUpdate = false; + } + return $result; } diff --git a/src/applications/maniphest/storage/task/__init__.php b/src/applications/maniphest/storage/task/__init__.php index 14ba412113..42038f4e2d 100644 --- a/src/applications/maniphest/storage/task/__init__.php +++ b/src/applications/maniphest/storage/task/__init__.php @@ -7,6 +7,7 @@ phutil_require_module('phabricator', 'applications/maniphest/storage/base'); +phutil_require_module('phabricator', 'applications/maniphest/storage/subscriber'); phutil_require_module('phabricator', 'applications/maniphest/storage/taskproject'); phutil_require_module('phabricator', 'applications/phid/constants'); phutil_require_module('phabricator', 'applications/phid/storage/phid');