mirror of
https://we.phorge.it/source/phorge.git
synced 2025-03-19 07:40:09 +01:00
Maniphest - use subscribers framework properly
Summary: Fixes T5604. This should fix some random bugs, lets us move forward more easily, and all that good stuff about killing code debt. Test Plan: - Conduit method maniphest.createtask - verified creating user subscribed - verified subscription transaction - Conduit method maniphest.update - verified subscribers set as specified to ccPHIDs parameter - verified subscription transaction - Herald - verified herald rule to add subscriber worked - verified no subscribers removed accidentally - edit controller - test create and verify author gets added IFF they put themselves in subscribers control box - test update gets set to exactly what user enters - lipsum generator'd tasks work - bulk add subscribers works - bulk remove subscriber works - detail controller - added myself by leaving a comment - added another user via explicit action - added another user via implicit mention - task merge via search attach controller - mail reply handler - add subscriber via ./bin/mail receive-test - unsubscribe via ./bin/mail receive-test Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T5604 Differential Revision: https://secure.phabricator.com/D10965
This commit is contained in:
parent
3297bc2ed9
commit
7d96870570
27 changed files with 195 additions and 230 deletions
|
@ -0,0 +1,9 @@
|
||||||
|
INSERT IGNORE INTO {$NAMESPACE}_maniphest.edge (src, type, dst)
|
||||||
|
SELECT taskPHID, 21, subscriberPHID
|
||||||
|
FROM {$NAMESPACE}_maniphest.maniphest_tasksubscriber
|
||||||
|
WHERE subscriberPHID != '';
|
||||||
|
|
||||||
|
INSERT IGNORE INTO {$NAMESPACE}_maniphest.edge (src, type, dst)
|
||||||
|
SELECT subscriberPHID, 22, taskPHID
|
||||||
|
FROM {$NAMESPACE}_maniphest.maniphest_tasksubscriber
|
||||||
|
WHERE subscriberPHID != '';
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
|
||||||
|
DROP ccPHIDs;
|
|
@ -1001,7 +1001,6 @@ phutil_register_library_map(array(
|
||||||
'ManiphestSearchIndexer' => 'applications/maniphest/search/ManiphestSearchIndexer.php',
|
'ManiphestSearchIndexer' => 'applications/maniphest/search/ManiphestSearchIndexer.php',
|
||||||
'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php',
|
'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php',
|
||||||
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
|
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
|
||||||
'ManiphestSubscribeController' => 'applications/maniphest/controller/ManiphestSubscribeController.php',
|
|
||||||
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
|
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
|
||||||
'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/ManiphestTaskDescriptionPreviewController.php',
|
'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/ManiphestTaskDescriptionPreviewController.php',
|
||||||
'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php',
|
'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php',
|
||||||
|
@ -4071,9 +4070,9 @@ phutil_register_library_map(array(
|
||||||
'ManiphestSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
|
'ManiphestSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||||
'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
||||||
'ManiphestSubpriorityController' => 'ManiphestController',
|
'ManiphestSubpriorityController' => 'ManiphestController',
|
||||||
'ManiphestSubscribeController' => 'ManiphestController',
|
|
||||||
'ManiphestTask' => array(
|
'ManiphestTask' => array(
|
||||||
'ManiphestDAO',
|
'ManiphestDAO',
|
||||||
|
'PhabricatorSubscribableInterface',
|
||||||
'PhabricatorMarkupInterface',
|
'PhabricatorMarkupInterface',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorTokenReceiverInterface',
|
'PhabricatorTokenReceiverInterface',
|
||||||
|
|
|
@ -139,7 +139,7 @@ final class HeraldManiphestTaskAdapter extends HeraldAdapter {
|
||||||
case self::FIELD_ASSIGNEE:
|
case self::FIELD_ASSIGNEE:
|
||||||
return $this->getTask()->getOwnerPHID();
|
return $this->getTask()->getOwnerPHID();
|
||||||
case self::FIELD_CC:
|
case self::FIELD_CC:
|
||||||
return $this->getTask()->getCCPHIDs();
|
return $this->getTask()->getSubscriberPHIDs();
|
||||||
case self::FIELD_PROJECTS:
|
case self::FIELD_PROJECTS:
|
||||||
return PhabricatorEdgeQuery::loadDestinationPHIDs(
|
return PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||||
$this->getTask()->getPHID(),
|
$this->getTask()->getPHID(),
|
||||||
|
|
|
@ -66,8 +66,6 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
|
||||||
),
|
),
|
||||||
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
|
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
|
||||||
'subpriority/' => 'ManiphestSubpriorityController',
|
'subpriority/' => 'ManiphestSubpriorityController',
|
||||||
'subscribe/(?P<action>add|rem)/(?P<id>[1-9]\d*)/'
|
|
||||||
=> 'ManiphestSubscribeController',
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,8 @@ abstract class ManiphestConduitAPIMethod extends ConduitAPIMethod {
|
||||||
$task->setDescription((string)$request->getValue('description'));
|
$task->setDescription((string)$request->getValue('description'));
|
||||||
$changes[ManiphestTransaction::TYPE_STATUS] =
|
$changes[ManiphestTransaction::TYPE_STATUS] =
|
||||||
ManiphestTaskStatus::getDefaultStatus();
|
ManiphestTaskStatus::getDefaultStatus();
|
||||||
|
$changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
|
||||||
|
array('+' => array($request->getUser()->getPHID()));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$comments = $request->getValue('comments');
|
$comments = $request->getValue('comments');
|
||||||
|
@ -111,7 +113,8 @@ abstract class ManiphestConduitAPIMethod extends ConduitAPIMethod {
|
||||||
|
|
||||||
$ccs = $request->getValue('ccPHIDs');
|
$ccs = $request->getValue('ccPHIDs');
|
||||||
if ($ccs !== null) {
|
if ($ccs !== null) {
|
||||||
$changes[ManiphestTransaction::TYPE_CCS] = $ccs;
|
$changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
|
||||||
|
array('=' => array_fuse($ccs));
|
||||||
}
|
}
|
||||||
|
|
||||||
$transactions = array();
|
$transactions = array();
|
||||||
|
@ -228,6 +231,13 @@ abstract class ManiphestConduitAPIMethod extends ConduitAPIMethod {
|
||||||
$event->setUser($request->getUser());
|
$event->setUser($request->getUser());
|
||||||
$event->setConduitRequest($request);
|
$event->setConduitRequest($request);
|
||||||
PhutilEventEngine::dispatchEvent($event);
|
PhutilEventEngine::dispatchEvent($event);
|
||||||
|
|
||||||
|
// reload the task now that we've done all the fun stuff
|
||||||
|
return id(new ManiphestTaskQuery())
|
||||||
|
->setViewer($request->getUser())
|
||||||
|
->withPHIDs(array($task->getPHID()))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
|
->executeOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildTaskInfoDictionaries(array $tasks) {
|
protected function buildTaskInfoDictionaries(array $tasks) {
|
||||||
|
@ -265,7 +275,7 @@ abstract class ManiphestConduitAPIMethod extends ConduitAPIMethod {
|
||||||
'phid' => $task->getPHID(),
|
'phid' => $task->getPHID(),
|
||||||
'authorPHID' => $task->getAuthorPHID(),
|
'authorPHID' => $task->getAuthorPHID(),
|
||||||
'ownerPHID' => $task->getOwnerPHID(),
|
'ownerPHID' => $task->getOwnerPHID(),
|
||||||
'ccPHIDs' => $task->getCCPHIDs(),
|
'ccPHIDs' => $task->getSubscriberPHIDs(),
|
||||||
'status' => $task->getStatus(),
|
'status' => $task->getStatus(),
|
||||||
'statusName' => ManiphestTaskStatus::getTaskStatusName(
|
'statusName' => ManiphestTaskStatus::getTaskStatusName(
|
||||||
$task->getStatus()),
|
$task->getStatus()),
|
||||||
|
|
|
@ -28,7 +28,7 @@ final class ManiphestCreateTaskConduitAPIMethod
|
||||||
protected function execute(ConduitAPIRequest $request) {
|
protected function execute(ConduitAPIRequest $request) {
|
||||||
$task = ManiphestTask::initializeNewTask($request->getUser());
|
$task = ManiphestTask::initializeNewTask($request->getUser());
|
||||||
|
|
||||||
$this->applyRequest($task, $request, $is_new = true);
|
$task = $this->applyRequest($task, $request, $is_new = true);
|
||||||
|
|
||||||
return $this->buildTaskInfoDictionary($task);
|
return $this->buildTaskInfoDictionary($task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ final class ManiphestInfoConduitAPIMethod extends ManiphestConduitAPIMethod {
|
||||||
$task = id(new ManiphestTaskQuery())
|
$task = id(new ManiphestTaskQuery())
|
||||||
->setViewer($request->getUser())
|
->setViewer($request->getUser())
|
||||||
->withIDs(array($task_id))
|
->withIDs(array($task_id))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$task) {
|
if (!$task) {
|
||||||
throw new ConduitException('ERR_BAD_TASK');
|
throw new ConduitException('ERR_BAD_TASK');
|
||||||
|
|
|
@ -64,6 +64,7 @@ class ManiphestQueryConduitAPIMethod extends ManiphestConduitAPIMethod {
|
||||||
$query = new ManiphestTaskQuery();
|
$query = new ManiphestTaskQuery();
|
||||||
|
|
||||||
$query->setViewer($request->getUser());
|
$query->setViewer($request->getUser());
|
||||||
|
$query->needSubscriberPHIDs(true);
|
||||||
|
|
||||||
$task_ids = $request->getValue('ids');
|
$task_ids = $request->getValue('ids');
|
||||||
if ($task_ids) {
|
if ($task_ids) {
|
||||||
|
|
|
@ -38,11 +38,13 @@ final class ManiphestUpdateConduitAPIMethod extends ManiphestConduitAPIMethod {
|
||||||
$task = id(new ManiphestTaskQuery())
|
$task = id(new ManiphestTaskQuery())
|
||||||
->setViewer($request->getUser())
|
->setViewer($request->getUser())
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
} else {
|
} else {
|
||||||
$task = id(new ManiphestTaskQuery())
|
$task = id(new ManiphestTaskQuery())
|
||||||
->setViewer($request->getUser())
|
->setViewer($request->getUser())
|
||||||
->withPHIDs(array($phid))
|
->withPHIDs(array($phid))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +60,7 @@ final class ManiphestUpdateConduitAPIMethod extends ManiphestConduitAPIMethod {
|
||||||
throw new ConduitException('ERR-BAD-TASK');
|
throw new ConduitException('ERR-BAD-TASK');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->applyRequest($task, $request, $is_new = false);
|
$task = $this->applyRequest($task, $request, $is_new = false);
|
||||||
|
|
||||||
return $this->buildTaskInfoDictionary($task);
|
return $this->buildTaskInfoDictionary($task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ final class ManiphestBatchEditController extends ManiphestController {
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
PhabricatorPolicyCapability::CAN_EDIT,
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
))
|
))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
$actions = $request->getStr('actions');
|
$actions = $request->getStr('actions');
|
||||||
|
@ -171,8 +172,8 @@ final class ManiphestBatchEditController extends ManiphestController {
|
||||||
'priority' => ManiphestTransaction::TYPE_PRIORITY,
|
'priority' => ManiphestTransaction::TYPE_PRIORITY,
|
||||||
'add_project' => ManiphestTransaction::TYPE_PROJECTS,
|
'add_project' => ManiphestTransaction::TYPE_PROJECTS,
|
||||||
'remove_project' => ManiphestTransaction::TYPE_PROJECTS,
|
'remove_project' => ManiphestTransaction::TYPE_PROJECTS,
|
||||||
'add_ccs' => ManiphestTransaction::TYPE_CCS,
|
'add_ccs' => PhabricatorTransactions::TYPE_SUBSCRIBERS,
|
||||||
'remove_ccs' => ManiphestTransaction::TYPE_CCS,
|
'remove_ccs' => PhabricatorTransactions::TYPE_SUBSCRIBERS,
|
||||||
);
|
);
|
||||||
|
|
||||||
$edge_edit_types = array(
|
$edge_edit_types = array(
|
||||||
|
@ -215,8 +216,8 @@ final class ManiphestBatchEditController extends ManiphestController {
|
||||||
case ManiphestTransaction::TYPE_PROJECTS:
|
case ManiphestTransaction::TYPE_PROJECTS:
|
||||||
$current = $task->getProjectPHIDs();
|
$current = $task->getProjectPHIDs();
|
||||||
break;
|
break;
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
$current = $task->getCCPHIDs();
|
$current = $task->getSubscriberPHIDs();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,7 +247,7 @@ final class ManiphestBatchEditController extends ManiphestController {
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
if (empty($value)) {
|
if (empty($value)) {
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
@ -274,12 +275,7 @@ final class ManiphestBatchEditController extends ManiphestController {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ManiphestTransaction::TYPE_PROJECTS:
|
case ManiphestTransaction::TYPE_PROJECTS:
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
$is_remove = $action['action'] == 'remove_project';
|
||||||
$remove_actions = array(
|
|
||||||
'remove_project' => true,
|
|
||||||
'remove_ccs' => true,
|
|
||||||
);
|
|
||||||
$is_remove = isset($remove_actions[$action['action']]);
|
|
||||||
|
|
||||||
$current = array_fill_keys($current, true);
|
$current = array_fill_keys($current, true);
|
||||||
$value = array_fill_keys($value, true);
|
$value = array_fill_keys($value, true);
|
||||||
|
@ -308,6 +304,39 @@ final class ManiphestBatchEditController extends ManiphestController {
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = array_keys($new);
|
$value = array_keys($new);
|
||||||
|
break;
|
||||||
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
|
$is_remove = $action['action'] == 'remove_ccs';
|
||||||
|
|
||||||
|
$current = array_fill_keys($current, true);
|
||||||
|
|
||||||
|
$new = array();
|
||||||
|
$did_something = false;
|
||||||
|
|
||||||
|
if ($is_remove) {
|
||||||
|
foreach ($value as $phid) {
|
||||||
|
if (isset($current[$phid])) {
|
||||||
|
$new[$phid] = true;
|
||||||
|
$did_something = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($new) {
|
||||||
|
$value = array('-' => array_keys($new));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$new = array();
|
||||||
|
foreach ($value as $phid) {
|
||||||
|
$new[$phid] = true;
|
||||||
|
$did_something = true;
|
||||||
|
}
|
||||||
|
if ($new) {
|
||||||
|
$value = array('+' => array_keys($new));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$did_something) {
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestSubscribeController extends ManiphestController {
|
|
||||||
|
|
||||||
private $id;
|
|
||||||
private $action;
|
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
|
||||||
$this->id = $data['id'];
|
|
||||||
$this->action = $data['action'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function processRequest() {
|
|
||||||
|
|
||||||
$request = $this->getRequest();
|
|
||||||
$user = $request->getUser();
|
|
||||||
|
|
||||||
$task = id(new ManiphestTaskQuery())
|
|
||||||
->setViewer($user)
|
|
||||||
->withIDs(array($this->id))
|
|
||||||
->executeOne();
|
|
||||||
if (!$task) {
|
|
||||||
return new Aphront404Response();
|
|
||||||
}
|
|
||||||
|
|
||||||
$ccs = $task->getCCPHIDs();
|
|
||||||
switch ($this->action) {
|
|
||||||
case 'add':
|
|
||||||
$ccs[] = $user->getPHID();
|
|
||||||
break;
|
|
||||||
case 'rem':
|
|
||||||
$ccs = array_diff($ccs, array($user->getPHID()));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return new Aphront400Response();
|
|
||||||
}
|
|
||||||
|
|
||||||
$xaction = id(new ManiphestTransaction())
|
|
||||||
->setTransactionType(ManiphestTransaction::TYPE_CCS)
|
|
||||||
->setNewValue($ccs);
|
|
||||||
|
|
||||||
$editor = id(new ManiphestTransactionEditor())
|
|
||||||
->setActor($user)
|
|
||||||
->setContentSourceFromRequest($request)
|
|
||||||
->setContinueOnNoEffect(true)
|
|
||||||
->setContinueOnMissingFields(true)
|
|
||||||
->applyTransactions($task, array($xaction));
|
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI('/T'.$task->getID());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,6 +23,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$task = id(new ManiphestTaskQuery())
|
$task = id(new ManiphestTaskQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withIDs(array($this->id))
|
->withIDs(array($this->id))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$task) {
|
if (!$task) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
|
@ -65,12 +66,6 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$edges = idx($query->execute(), $phid);
|
$edges = idx($query->execute(), $phid);
|
||||||
$phids = array_fill_keys($query->getDestinationPHIDs(), true);
|
$phids = array_fill_keys($query->getDestinationPHIDs(), true);
|
||||||
|
|
||||||
foreach ($task->getCCPHIDs() as $phid) {
|
|
||||||
$phids[$phid] = true;
|
|
||||||
}
|
|
||||||
foreach ($task->getProjectPHIDs() as $phid) {
|
|
||||||
$phids[$phid] = true;
|
|
||||||
}
|
|
||||||
if ($task->getOwnerPHID()) {
|
if ($task->getOwnerPHID()) {
|
||||||
$phids[$task->getOwnerPHID()] = true;
|
$phids[$task->getOwnerPHID()] = true;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +137,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
PhabricatorTransactions::TYPE_COMMENT => pht('Comment'),
|
PhabricatorTransactions::TYPE_COMMENT => pht('Comment'),
|
||||||
ManiphestTransaction::TYPE_STATUS => pht('Change Status'),
|
ManiphestTransaction::TYPE_STATUS => pht('Change Status'),
|
||||||
ManiphestTransaction::TYPE_OWNER => pht('Reassign / Claim'),
|
ManiphestTransaction::TYPE_OWNER => pht('Reassign / Claim'),
|
||||||
ManiphestTransaction::TYPE_CCS => pht('Add CCs'),
|
PhabricatorTransactions::TYPE_SUBSCRIBERS => pht('Add CCs'),
|
||||||
ManiphestTransaction::TYPE_PRIORITY => pht('Change Priority'),
|
ManiphestTransaction::TYPE_PRIORITY => pht('Change Priority'),
|
||||||
ManiphestTransaction::TYPE_PROJECTS => pht('Associate Projects'),
|
ManiphestTransaction::TYPE_PROJECTS => pht('Associate Projects'),
|
||||||
);
|
);
|
||||||
|
@ -267,7 +262,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$control_map = array(
|
$control_map = array(
|
||||||
ManiphestTransaction::TYPE_STATUS => 'resolution',
|
ManiphestTransaction::TYPE_STATUS => 'resolution',
|
||||||
ManiphestTransaction::TYPE_OWNER => 'assign_to',
|
ManiphestTransaction::TYPE_OWNER => 'assign_to',
|
||||||
ManiphestTransaction::TYPE_CCS => 'ccs',
|
PhabricatorTransactions::TYPE_SUBSCRIBERS => 'ccs',
|
||||||
ManiphestTransaction::TYPE_PRIORITY => 'priority',
|
ManiphestTransaction::TYPE_PRIORITY => 'priority',
|
||||||
ManiphestTransaction::TYPE_PROJECTS => 'projects',
|
ManiphestTransaction::TYPE_PROJECTS => 'projects',
|
||||||
);
|
);
|
||||||
|
@ -289,7 +284,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
'limit' => 1,
|
'limit' => 1,
|
||||||
'placeholder' => $users_source->getPlaceholderText(),
|
'placeholder' => $users_source->getPlaceholderText(),
|
||||||
),
|
),
|
||||||
ManiphestTransaction::TYPE_CCS => array(
|
PhabricatorTransactions::TYPE_SUBSCRIBERS => array(
|
||||||
'id' => 'cc-tokenizer',
|
'id' => 'cc-tokenizer',
|
||||||
'src' => $mailable_source->getDatasourceURI(),
|
'src' => $mailable_source->getDatasourceURI(),
|
||||||
'placeholder' => $mailable_source->getPlaceholderText(),
|
'placeholder' => $mailable_source->getPlaceholderText(),
|
||||||
|
@ -397,7 +392,6 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
private function buildActionView(ManiphestTask $task) {
|
private function buildActionView(ManiphestTask $task) {
|
||||||
$viewer = $this->getRequest()->getUser();
|
$viewer = $this->getRequest()->getUser();
|
||||||
$viewer_phid = $viewer->getPHID();
|
$viewer_phid = $viewer->getPHID();
|
||||||
$viewer_is_cc = in_array($viewer_phid, $task->getCCPHIDs());
|
|
||||||
|
|
||||||
$id = $task->getID();
|
$id = $task->getID();
|
||||||
$phid = $task->getPHID();
|
$phid = $task->getPHID();
|
||||||
|
@ -420,26 +414,6 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
->setDisabled(!$can_edit)
|
->setDisabled(!$can_edit)
|
||||||
->setWorkflow(!$can_edit));
|
->setWorkflow(!$can_edit));
|
||||||
|
|
||||||
if ($task->getOwnerPHID() === $viewer_phid) {
|
|
||||||
$view->addAction(
|
|
||||||
id(new PhabricatorActionView())
|
|
||||||
->setName(pht('Automatically Subscribed'))
|
|
||||||
->setDisabled(true)
|
|
||||||
->setIcon('fa-check-circle'));
|
|
||||||
} else {
|
|
||||||
$action = $viewer_is_cc ? 'rem' : 'add';
|
|
||||||
$name = $viewer_is_cc ? pht('Unsubscribe') : pht('Subscribe');
|
|
||||||
$icon = $viewer_is_cc ? 'fa-minus-circle' : 'fa-plus-circle';
|
|
||||||
|
|
||||||
$view->addAction(
|
|
||||||
id(new PhabricatorActionView())
|
|
||||||
->setName($name)
|
|
||||||
->setHref("/maniphest/subscribe/{$action}/{$id}/")
|
|
||||||
->setRenderAsForm(true)
|
|
||||||
->setUser($viewer)
|
|
||||||
->setIcon($icon));
|
|
||||||
}
|
|
||||||
|
|
||||||
$view->addAction(
|
$view->addAction(
|
||||||
id(new PhabricatorActionView())
|
id(new PhabricatorActionView())
|
||||||
->setName(pht('Merge Duplicates In'))
|
->setName(pht('Merge Duplicates In'))
|
||||||
|
@ -490,14 +464,6 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
||||||
pht('Priority'),
|
pht('Priority'),
|
||||||
ManiphestTaskPriority::getTaskPriorityName($task->getPriority()));
|
ManiphestTaskPriority::getTaskPriorityName($task->getPriority()));
|
||||||
|
|
||||||
$handles = $this->getLoadedHandles();
|
|
||||||
$cc_handles = array_select_keys($handles, $task->getCCPHIDs());
|
|
||||||
$subscriber_html = id(new SubscriptionListStringBuilder())
|
|
||||||
->setObjectPHID($task->getPHID())
|
|
||||||
->setHandles($cc_handles)
|
|
||||||
->buildPropertyString();
|
|
||||||
$view->addProperty(pht('Subscribers'), $subscriber_html);
|
|
||||||
|
|
||||||
$view->addProperty(
|
$view->addProperty(
|
||||||
pht('Author'),
|
pht('Author'),
|
||||||
$this->getHandle($task->getAuthorPHID())->renderLink());
|
$this->getHandle($task->getAuthorPHID())->renderLink());
|
||||||
|
|
|
@ -38,6 +38,7 @@ final class ManiphestTaskEditController extends ManiphestController {
|
||||||
PhabricatorPolicyCapability::CAN_EDIT,
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
))
|
))
|
||||||
->withIDs(array($this->id))
|
->withIDs(array($this->id))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$task) {
|
if (!$task) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
|
@ -215,7 +216,7 @@ final class ManiphestTaskEditController extends ManiphestController {
|
||||||
$task->setDescription($new_desc);
|
$task->setDescription($new_desc);
|
||||||
$task->setPriority($request->getInt('priority'));
|
$task->setPriority($request->getInt('priority'));
|
||||||
$task->setOwnerPHID($owner_phid);
|
$task->setOwnerPHID($owner_phid);
|
||||||
$task->setCCPHIDs($request->getArr('cc'));
|
$task->attachSubscriberPHIDs($request->getArr('cc'));
|
||||||
$task->attachProjectPHIDs($request->getArr('projects'));
|
$task->attachProjectPHIDs($request->getArr('projects'));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -227,7 +228,8 @@ final class ManiphestTaskEditController extends ManiphestController {
|
||||||
$changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
|
$changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
|
||||||
}
|
}
|
||||||
|
|
||||||
$changes[ManiphestTransaction::TYPE_CCS] = $request->getArr('cc');
|
$changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
|
||||||
|
array('=' => $request->getArr('cc'));
|
||||||
|
|
||||||
if ($can_edit_projects) {
|
if ($can_edit_projects) {
|
||||||
$projects = $request->getArr('projects');
|
$projects = $request->getArr('projects');
|
||||||
|
@ -436,19 +438,20 @@ final class ManiphestTaskEditController extends ManiphestController {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!$task->getID()) {
|
if (!$task->getID()) {
|
||||||
$task->setCCPHIDs(array(
|
$task->attachSubscriberPHIDs(array(
|
||||||
$user->getPHID(),
|
$user->getPHID(),
|
||||||
));
|
));
|
||||||
if ($template_id) {
|
if ($template_id) {
|
||||||
$template_task = id(new ManiphestTaskQuery())
|
$template_task = id(new ManiphestTaskQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withIDs(array($template_id))
|
->withIDs(array($template_id))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if ($template_task) {
|
if ($template_task) {
|
||||||
$cc_phids = array_unique(array_merge(
|
$cc_phids = array_unique(array_merge(
|
||||||
$template_task->getCCPHIDs(),
|
$template_task->getSubscriberPHIDs(),
|
||||||
array($user->getPHID())));
|
array($user->getPHID())));
|
||||||
$task->setCCPHIDs($cc_phids);
|
$task->attachSubscriberPHIDs($cc_phids);
|
||||||
$task->attachProjectPHIDs($template_task->getProjectPHIDs());
|
$task->attachProjectPHIDs($template_task->getProjectPHIDs());
|
||||||
$task->setOwnerPHID($template_task->getOwnerPHID());
|
$task->setOwnerPHID($template_task->getOwnerPHID());
|
||||||
$task->setPriority($template_task->getPriority());
|
$task->setPriority($template_task->getPriority());
|
||||||
|
@ -486,7 +489,7 @@ final class ManiphestTaskEditController extends ManiphestController {
|
||||||
|
|
||||||
$phids = array_merge(
|
$phids = array_merge(
|
||||||
array($task->getOwnerPHID()),
|
array($task->getOwnerPHID()),
|
||||||
$task->getCCPHIDs(),
|
$task->getSubscriberPHIDs(),
|
||||||
$task->getProjectPHIDs());
|
$task->getProjectPHIDs());
|
||||||
|
|
||||||
if ($parent_task) {
|
if ($parent_task) {
|
||||||
|
@ -512,8 +515,8 @@ final class ManiphestTaskEditController extends ManiphestController {
|
||||||
$assigned_value = array();
|
$assigned_value = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($task->getCCPHIDs()) {
|
if ($task->getSubscriberPHIDs()) {
|
||||||
$cc_value = array_select_keys($handles, $task->getCCPHIDs());
|
$cc_value = array_select_keys($handles, $task->getSubscriberPHIDs());
|
||||||
} else {
|
} else {
|
||||||
$cc_value = array();
|
$cc_value = array();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,22 +58,19 @@ final class ManiphestTransactionPreviewController extends ManiphestController {
|
||||||
}
|
}
|
||||||
$transaction->setNewValue($value);
|
$transaction->setNewValue($value);
|
||||||
break;
|
break;
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
if ($value) {
|
if ($value) {
|
||||||
$value = json_decode($value);
|
$value = json_decode($value);
|
||||||
}
|
}
|
||||||
if (!$value) {
|
if (!$value) {
|
||||||
$value = array();
|
$value = array();
|
||||||
}
|
}
|
||||||
$phids = $value;
|
$phids = array();
|
||||||
|
foreach ($value as $cc_phid) {
|
||||||
foreach ($task->getCCPHIDs() as $cc_phid) {
|
|
||||||
$phids[] = $cc_phid;
|
$phids[] = $cc_phid;
|
||||||
$value[] = $cc_phid;
|
|
||||||
}
|
}
|
||||||
|
$transaction->setOldValue(array());
|
||||||
$transaction->setOldValue($task->getCCPHIDs());
|
$transaction->setNewValue($phids);
|
||||||
$transaction->setNewValue($value);
|
|
||||||
break;
|
break;
|
||||||
case ManiphestTransaction::TYPE_PROJECTS:
|
case ManiphestTransaction::TYPE_PROJECTS:
|
||||||
if ($value) {
|
if ($value) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class ManiphestTransactionSaveController extends ManiphestController {
|
||||||
$task = id(new ManiphestTaskQuery())
|
$task = id(new ManiphestTaskQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withIDs(array($request->getStr('taskID')))
|
->withIDs(array($request->getStr('taskID')))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$task) {
|
if (!$task) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
|
@ -33,7 +34,7 @@ final class ManiphestTransactionSaveController extends ManiphestController {
|
||||||
|
|
||||||
$cc_transaction = new ManiphestTransaction();
|
$cc_transaction = new ManiphestTransaction();
|
||||||
$cc_transaction
|
$cc_transaction
|
||||||
->setTransactionType(ManiphestTransaction::TYPE_CCS);
|
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS);
|
||||||
|
|
||||||
$transaction = new ManiphestTransaction();
|
$transaction = new ManiphestTransaction();
|
||||||
$transaction
|
$transaction
|
||||||
|
@ -64,7 +65,7 @@ final class ManiphestTransactionSaveController extends ManiphestController {
|
||||||
'+' => array_fuse($projects),
|
'+' => array_fuse($projects),
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
|
||||||
// Accumulate the new explicit CCs into the array that we'll add in
|
// Accumulate the new explicit CCs into the array that we'll add in
|
||||||
// the CC transaction later.
|
// the CC transaction later.
|
||||||
$added_ccs = array_merge($added_ccs, $request->getArr('ccs'));
|
$added_ccs = array_merge($added_ccs, $request->getArr('ccs'));
|
||||||
|
@ -135,19 +136,21 @@ final class ManiphestTransactionSaveController extends ManiphestController {
|
||||||
if (!$user_owns_task) {
|
if (!$user_owns_task) {
|
||||||
// If we aren't making the user the new task owner and they aren't the
|
// If we aren't making the user the new task owner and they aren't the
|
||||||
// existing task owner, add them to CC unless they're aleady CC'd.
|
// existing task owner, add them to CC unless they're aleady CC'd.
|
||||||
if (!in_array($user->getPHID(), $task->getCCPHIDs())) {
|
if (!in_array($user->getPHID(), $task->getSubscriberPHIDs())) {
|
||||||
$added_ccs[] = $user->getPHID();
|
$added_ccs[] = $user->getPHID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evade no-effect detection in the new editor stuff until we can switch
|
// Evade no-effect detection in the new editor stuff until we can switch
|
||||||
// to subscriptions.
|
// to subscriptions.
|
||||||
$added_ccs = array_filter(array_diff($added_ccs, $task->getCCPHIDs()));
|
$added_ccs = array_filter(array_diff(
|
||||||
|
$added_ccs,
|
||||||
|
$task->getSubscriberPHIDs()));
|
||||||
|
|
||||||
if ($added_ccs) {
|
if ($added_ccs) {
|
||||||
// We've added CCs, so include a CC transaction.
|
// We've added CCs, so include a CC transaction.
|
||||||
$all_ccs = array_merge($task->getCCPHIDs(), $added_ccs);
|
$all_ccs = array_merge($task->getSubscriberPHIDs(), $added_ccs);
|
||||||
$cc_transaction->setNewValue($all_ccs);
|
$cc_transaction->setNewValue(array('=' => $all_ccs));
|
||||||
$transactions[] = $cc_transaction;
|
$transactions[] = $cc_transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ final class ManiphestTransactionEditor
|
||||||
$types[] = ManiphestTransaction::TYPE_TITLE;
|
$types[] = ManiphestTransaction::TYPE_TITLE;
|
||||||
$types[] = ManiphestTransaction::TYPE_DESCRIPTION;
|
$types[] = ManiphestTransaction::TYPE_DESCRIPTION;
|
||||||
$types[] = ManiphestTransaction::TYPE_OWNER;
|
$types[] = ManiphestTransaction::TYPE_OWNER;
|
||||||
$types[] = ManiphestTransaction::TYPE_CCS;
|
|
||||||
$types[] = ManiphestTransaction::TYPE_SUBPRIORITY;
|
$types[] = ManiphestTransaction::TYPE_SUBPRIORITY;
|
||||||
$types[] = ManiphestTransaction::TYPE_PROJECT_COLUMN;
|
$types[] = ManiphestTransaction::TYPE_PROJECT_COLUMN;
|
||||||
$types[] = ManiphestTransaction::TYPE_MERGED_INTO;
|
$types[] = ManiphestTransaction::TYPE_MERGED_INTO;
|
||||||
|
@ -62,8 +61,6 @@ final class ManiphestTransactionEditor
|
||||||
return $object->getDescription();
|
return $object->getDescription();
|
||||||
case ManiphestTransaction::TYPE_OWNER:
|
case ManiphestTransaction::TYPE_OWNER:
|
||||||
return nonempty($object->getOwnerPHID(), null);
|
return nonempty($object->getOwnerPHID(), null);
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
|
||||||
return array_values(array_unique($object->getCCPHIDs()));
|
|
||||||
case ManiphestTransaction::TYPE_PROJECT_COLUMN:
|
case ManiphestTransaction::TYPE_PROJECT_COLUMN:
|
||||||
// These are pre-populated.
|
// These are pre-populated.
|
||||||
return $xaction->getOldValue();
|
return $xaction->getOldValue();
|
||||||
|
@ -82,8 +79,6 @@ final class ManiphestTransactionEditor
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case ManiphestTransaction::TYPE_PRIORITY:
|
case ManiphestTransaction::TYPE_PRIORITY:
|
||||||
return (int)$xaction->getNewValue();
|
return (int)$xaction->getNewValue();
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
|
||||||
return array_values(array_unique($xaction->getNewValue()));
|
|
||||||
case ManiphestTransaction::TYPE_OWNER:
|
case ManiphestTransaction::TYPE_OWNER:
|
||||||
return nonempty($xaction->getNewValue(), null);
|
return nonempty($xaction->getNewValue(), null);
|
||||||
case ManiphestTransaction::TYPE_STATUS:
|
case ManiphestTransaction::TYPE_STATUS:
|
||||||
|
@ -106,10 +101,6 @@ final class ManiphestTransactionEditor
|
||||||
$new = $xaction->getNewValue();
|
$new = $xaction->getNewValue();
|
||||||
|
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
|
||||||
sort($old);
|
|
||||||
sort($new);
|
|
||||||
return ($old !== $new);
|
|
||||||
case ManiphestTransaction::TYPE_PROJECT_COLUMN:
|
case ManiphestTransaction::TYPE_PROJECT_COLUMN:
|
||||||
$new_column_phids = $new['columnPHIDs'];
|
$new_column_phids = $new['columnPHIDs'];
|
||||||
$old_column_phids = $old['columnPHIDs'];
|
$old_column_phids = $old['columnPHIDs'];
|
||||||
|
@ -155,8 +146,6 @@ final class ManiphestTransactionEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
return $object->setOwnerPHID($phid);
|
return $object->setOwnerPHID($phid);
|
||||||
case ManiphestTransaction::TYPE_CCS:
|
|
||||||
return $object->setCCPHIDs($xaction->getNewValue());
|
|
||||||
case ManiphestTransaction::TYPE_SUBPRIORITY:
|
case ManiphestTransaction::TYPE_SUBPRIORITY:
|
||||||
$data = $xaction->getNewValue();
|
$data = $xaction->getNewValue();
|
||||||
$new_sub = $this->getNextSubpriority(
|
$new_sub = $this->getNextSubpriority(
|
||||||
|
@ -433,10 +422,6 @@ final class ManiphestTransactionEditor
|
||||||
protected function getMailCC(PhabricatorLiskDAO $object) {
|
protected function getMailCC(PhabricatorLiskDAO $object) {
|
||||||
$phids = array();
|
$phids = array();
|
||||||
|
|
||||||
foreach ($object->getCCPHIDs() as $phid) {
|
|
||||||
$phids[] = $phid;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (parent::getMailCC($object) as $phid) {
|
foreach (parent::getMailCC($object) as $phid) {
|
||||||
$phids[] = $phid;
|
$phids[] = $phid;
|
||||||
}
|
}
|
||||||
|
@ -561,22 +546,16 @@ final class ManiphestTransactionEditor
|
||||||
HeraldAdapter $adapter,
|
HeraldAdapter $adapter,
|
||||||
HeraldTranscript $transcript) {
|
HeraldTranscript $transcript) {
|
||||||
|
|
||||||
// TODO: Convert these to transactions. The way Maniphest deals with these
|
$this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
|
||||||
// transactions is currently unconventional and messy.
|
$xactions = array();
|
||||||
|
|
||||||
$save_again = false;
|
|
||||||
$cc_phids = $adapter->getCcPHIDs();
|
$cc_phids = $adapter->getCcPHIDs();
|
||||||
if ($cc_phids) {
|
if ($cc_phids) {
|
||||||
$existing_cc = $object->getCCPHIDs();
|
$xactions[] = id(new ManiphestTransaction())
|
||||||
$new_cc = array_unique(array_merge($cc_phids, $existing_cc));
|
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||||
$object->setCCPHIDs($new_cc);
|
->setNewValue(array('+' => $cc_phids));
|
||||||
$object->save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
|
|
||||||
|
|
||||||
$xactions = array();
|
|
||||||
|
|
||||||
$assign_phid = $adapter->getAssignPHID();
|
$assign_phid = $adapter->getAssignPHID();
|
||||||
if ($assign_phid) {
|
if ($assign_phid) {
|
||||||
$xactions[] = id(new ManiphestTransaction())
|
$xactions[] = id(new ManiphestTransaction())
|
||||||
|
|
|
@ -28,8 +28,8 @@ final class PhabricatorManiphestTaskTestDataGenerator
|
||||||
$this->generateTaskStatus();
|
$this->generateTaskStatus();
|
||||||
$changes[ManiphestTransaction::TYPE_PRIORITY] =
|
$changes[ManiphestTransaction::TYPE_PRIORITY] =
|
||||||
$this->generateTaskPriority();
|
$this->generateTaskPriority();
|
||||||
$changes[ManiphestTransaction::TYPE_CCS] =
|
$changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
|
||||||
$this->getCCPHIDs();
|
array('=' => $this->getCCPHIDs());
|
||||||
$transactions = array();
|
$transactions = array();
|
||||||
foreach ($changes as $type => $value) {
|
foreach ($changes as $type => $value) {
|
||||||
$transaction = clone $template;
|
$transaction = clone $template;
|
||||||
|
|
|
@ -106,14 +106,14 @@ final class ManiphestReplyHandler extends PhabricatorMailReplyHandler {
|
||||||
break;
|
break;
|
||||||
case 'unsubscribe':
|
case 'unsubscribe':
|
||||||
$is_unsub = true;
|
$is_unsub = true;
|
||||||
$ttype = ManiphestTransaction::TYPE_CCS;
|
$ttype = PhabricatorTransactions::TYPE_SUBSCRIBERS;
|
||||||
$ccs = $task->getCCPHIDs();
|
$ccs = $task->getSubscriberPHIDs();
|
||||||
foreach ($ccs as $k => $phid) {
|
foreach ($ccs as $k => $phid) {
|
||||||
if ($phid == $user->getPHID()) {
|
if ($phid == $user->getPHID()) {
|
||||||
unset($ccs[$k]);
|
unset($ccs[$k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$new_value = array_values($ccs);
|
$new_value = array('=' => array_values($ccs));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ final class ManiphestReplyHandler extends PhabricatorMailReplyHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
$ccs = $mail->loadCCPHIDs();
|
$ccs = $mail->loadCCPHIDs();
|
||||||
$old_ccs = $task->getCCPHIDs();
|
$old_ccs = $task->getSubscriberPHIDs();
|
||||||
$new_ccs = array_merge($old_ccs, $ccs);
|
$new_ccs = array_merge($old_ccs, $ccs);
|
||||||
if (!$is_unsub) {
|
if (!$is_unsub) {
|
||||||
$new_ccs[] = $user->getPHID();
|
$new_ccs[] = $user->getPHID();
|
||||||
|
@ -144,8 +144,9 @@ final class ManiphestReplyHandler extends PhabricatorMailReplyHandler {
|
||||||
|
|
||||||
if (array_diff($new_ccs, $old_ccs)) {
|
if (array_diff($new_ccs, $old_ccs)) {
|
||||||
$cc_xaction = clone $template;
|
$cc_xaction = clone $template;
|
||||||
$cc_xaction->setTransactionType(ManiphestTransaction::TYPE_CCS);
|
$cc_xaction->setTransactionType(
|
||||||
$cc_xaction->setNewValue($new_ccs);
|
PhabricatorTransactions::TYPE_SUBSCRIBERS);
|
||||||
|
$cc_xaction->setNewValue(array('=' => $new_ccs));
|
||||||
$xactions[] = $cc_xaction;
|
$xactions[] = $cc_xaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ final class ManiphestTaskMailReceiver extends PhabricatorObjectMailReceiver {
|
||||||
$results = id(new ManiphestTaskQuery())
|
$results = id(new ManiphestTaskQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
return head($results);
|
return head($results);
|
||||||
|
|
|
@ -50,6 +50,8 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
const ORDER_MODIFIED = 'order-modified';
|
const ORDER_MODIFIED = 'order-modified';
|
||||||
const ORDER_TITLE = 'order-title';
|
const ORDER_TITLE = 'order-title';
|
||||||
|
|
||||||
|
private $needSubscriberPHIDs;
|
||||||
|
|
||||||
const DEFAULT_PAGE_SIZE = 1000;
|
const DEFAULT_PAGE_SIZE = 1000;
|
||||||
|
|
||||||
public function withAuthors(array $authors) {
|
public function withAuthors(array $authors) {
|
||||||
|
@ -178,6 +180,11 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function needSubscriberPHIDs($bool) {
|
||||||
|
$this->needSubscriberPHIDs = $bool;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function loadPage() {
|
public function loadPage() {
|
||||||
// TODO: (T603) It is possible for a user to find the PHID of a project
|
// TODO: (T603) It is possible for a user to find the PHID of a project
|
||||||
// they can't see, then query for tasks in that project and deduce the
|
// they can't see, then query for tasks in that project and deduce the
|
||||||
|
@ -196,7 +203,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
$where[] = $this->buildPrioritiesWhereClause($conn);
|
$where[] = $this->buildPrioritiesWhereClause($conn);
|
||||||
$where[] = $this->buildAuthorWhereClause($conn);
|
$where[] = $this->buildAuthorWhereClause($conn);
|
||||||
$where[] = $this->buildOwnerWhereClause($conn);
|
$where[] = $this->buildOwnerWhereClause($conn);
|
||||||
$where[] = $this->buildSubscriberWhereClause($conn);
|
|
||||||
$where[] = $this->buildProjectWhereClause($conn);
|
$where[] = $this->buildProjectWhereClause($conn);
|
||||||
$where[] = $this->buildAnyProjectWhereClause($conn);
|
$where[] = $this->buildAnyProjectWhereClause($conn);
|
||||||
$where[] = $this->buildAnyUserProjectWhereClause($conn);
|
$where[] = $this->buildAnyUserProjectWhereClause($conn);
|
||||||
|
@ -332,12 +338,14 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function didFilterPage(array $tasks) {
|
protected function didFilterPage(array $tasks) {
|
||||||
|
$phids = mpull($tasks, 'getPHID');
|
||||||
|
|
||||||
// TODO: Eventually, we should make this optional and introduce a
|
// TODO: Eventually, we should make this optional and introduce a
|
||||||
// needProjectPHIDs() method, but for now there's a lot of code which
|
// needProjectPHIDs() method, but for now there's a lot of code which
|
||||||
// assumes the data is always populated.
|
// assumes the data is always populated.
|
||||||
|
|
||||||
$edge_query = id(new PhabricatorEdgeQuery())
|
$edge_query = id(new PhabricatorEdgeQuery())
|
||||||
->withSourcePHIDs(mpull($tasks, 'getPHID'))
|
->withSourcePHIDs($phids)
|
||||||
->withEdgeTypes(
|
->withEdgeTypes(
|
||||||
array(
|
array(
|
||||||
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
|
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
|
||||||
|
@ -345,8 +353,19 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
$edge_query->execute();
|
$edge_query->execute();
|
||||||
|
|
||||||
foreach ($tasks as $task) {
|
foreach ($tasks as $task) {
|
||||||
$phids = $edge_query->getDestinationPHIDs(array($task->getPHID()));
|
$project_phids = $edge_query->getDestinationPHIDs(
|
||||||
$task->attachProjectPHIDs($phids);
|
array($task->getPHID()));
|
||||||
|
$task->attachProjectPHIDs($project_phids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->needSubscriberPHIDs) {
|
||||||
|
$subscriber_sets = id(new PhabricatorSubscribersQuery())
|
||||||
|
->withObjectPHIDs($phids)
|
||||||
|
->execute();
|
||||||
|
foreach ($tasks as $task) {
|
||||||
|
$subscribers = idx($subscriber_sets, $task->getPHID(), array());
|
||||||
|
$task->attachSubscriberPHIDs($subscribers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tasks;
|
return $tasks;
|
||||||
|
@ -497,17 +516,6 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
$fulltext_results);
|
$fulltext_results);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildSubscriberWhereClause(AphrontDatabaseConnection $conn) {
|
|
||||||
if (!$this->subscriberPHIDs) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return qsprintf(
|
|
||||||
$conn,
|
|
||||||
'subscriber.subscriberPHID IN (%Ls)',
|
|
||||||
$this->subscriberPHIDs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function buildProjectWhereClause(AphrontDatabaseConnection $conn) {
|
private function buildProjectWhereClause(AphrontDatabaseConnection $conn) {
|
||||||
if (!$this->projectPHIDs && !$this->includeNoProject) {
|
if (!$this->projectPHIDs && !$this->includeNoProject) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -708,11 +716,14 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->subscriberPHIDs) {
|
if ($this->subscriberPHIDs) {
|
||||||
$subscriber_dao = new ManiphestTaskSubscriber();
|
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'JOIN %T subscriber ON subscriber.taskPHID = task.phid',
|
'JOIN %T e_ccs ON e_ccs.src = task.phid '.
|
||||||
$subscriber_dao->getTableName());
|
'AND e_ccs.type = %s '.
|
||||||
|
'AND e_ccs.dst in (%Ls)',
|
||||||
|
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
||||||
|
PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER,
|
||||||
|
$this->subscriberPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($this->groupBy) {
|
switch ($this->groupBy) {
|
||||||
|
|
|
@ -54,21 +54,6 @@ final class ManiphestSearchIndexer extends PhabricatorSearchDocumentIndexer {
|
||||||
$task->getDateCreated());
|
$task->getDateCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to load handles here since non-users may subscribe (mailing
|
|
||||||
// lists, e.g.)
|
|
||||||
$ccs = $task->getCCPHIDs();
|
|
||||||
$handles = id(new PhabricatorHandleQuery())
|
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
|
||||||
->withPHIDs($ccs)
|
|
||||||
->execute();
|
|
||||||
foreach ($ccs as $cc) {
|
|
||||||
$doc->addRelationship(
|
|
||||||
PhabricatorSearchRelationship::RELATIONSHIP_SUBSCRIBER,
|
|
||||||
$handles[$cc]->getPHID(),
|
|
||||||
$handles[$cc]->getType(),
|
|
||||||
time());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $doc;
|
return $doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
final class ManiphestTask extends ManiphestDAO
|
final class ManiphestTask extends ManiphestDAO
|
||||||
implements
|
implements
|
||||||
|
PhabricatorSubscribableInterface,
|
||||||
PhabricatorMarkupInterface,
|
PhabricatorMarkupInterface,
|
||||||
PhabricatorPolicyInterface,
|
PhabricatorPolicyInterface,
|
||||||
PhabricatorTokenReceiverInterface,
|
PhabricatorTokenReceiverInterface,
|
||||||
|
@ -17,7 +18,6 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
|
|
||||||
protected $authorPHID;
|
protected $authorPHID;
|
||||||
protected $ownerPHID;
|
protected $ownerPHID;
|
||||||
protected $ccPHIDs = array();
|
|
||||||
|
|
||||||
protected $status;
|
protected $status;
|
||||||
protected $priority;
|
protected $priority;
|
||||||
|
@ -33,10 +33,10 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
|
|
||||||
protected $attached = array();
|
protected $attached = array();
|
||||||
protected $projectPHIDs = array();
|
protected $projectPHIDs = array();
|
||||||
private $subscribersNeedUpdate;
|
|
||||||
|
|
||||||
protected $ownerOrdering;
|
protected $ownerOrdering;
|
||||||
|
|
||||||
|
private $subscriberPHIDs = self::ATTACHABLE;
|
||||||
private $groupByProjectPHID = self::ATTACHABLE;
|
private $groupByProjectPHID = self::ATTACHABLE;
|
||||||
private $customFields = self::ATTACHABLE;
|
private $customFields = self::ATTACHABLE;
|
||||||
private $edgeProjectPHIDs = self::ATTACHABLE;
|
private $edgeProjectPHIDs = self::ATTACHABLE;
|
||||||
|
@ -56,7 +56,8 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
->setAuthorPHID($actor->getPHID())
|
->setAuthorPHID($actor->getPHID())
|
||||||
->setViewPolicy($view_policy)
|
->setViewPolicy($view_policy)
|
||||||
->setEditPolicy($edit_policy)
|
->setEditPolicy($edit_policy)
|
||||||
->attachProjectPHIDs(array());
|
->attachProjectPHIDs(array())
|
||||||
|
->attachSubscriberPHIDs(array());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
|
@ -141,8 +142,8 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
return PhabricatorPHID::generateNewPHID(ManiphestTaskPHIDType::TYPECONST);
|
return PhabricatorPHID::generateNewPHID(ManiphestTaskPHIDType::TYPECONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCCPHIDs() {
|
public function getSubscriberPHIDs() {
|
||||||
return array_values(nonempty($this->ccPHIDs, array()));
|
return $this->assertAttached($this->subscriberPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProjectPHIDs() {
|
public function getProjectPHIDs() {
|
||||||
|
@ -154,15 +155,13 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCCPHIDs(array $phids) {
|
public function attachSubscriberPHIDs(array $phids) {
|
||||||
$this->ccPHIDs = array_values($phids);
|
$this->subscriberPHIDs = $phids;
|
||||||
$this->subscribersNeedUpdate = true;
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setOwnerPHID($phid) {
|
public function setOwnerPHID($phid) {
|
||||||
$this->ownerPHID = nonempty($phid, null);
|
$this->ownerPHID = nonempty($phid, null);
|
||||||
$this->subscribersNeedUpdate = true;
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,13 +193,6 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
|
|
||||||
$result = parent::save();
|
$result = parent::save();
|
||||||
|
|
||||||
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;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +209,22 @@ final class ManiphestTask extends ManiphestDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function isAutomaticallySubscribed($phid) {
|
||||||
|
return ($phid == $this->getOwnerPHID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldShowSubscribersProperty() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldAllowSubscription($phid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Markup Interface )--------------------------------------------------- */
|
/* -( Markup Interface )--------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deprecated; delete me.
|
||||||
|
*/
|
||||||
final class ManiphestTaskSubscriber extends ManiphestDAO {
|
final class ManiphestTaskSubscriber extends ManiphestDAO {
|
||||||
|
|
||||||
protected $taskPHID;
|
protected $taskPHID;
|
||||||
|
|
|
@ -7,7 +7,6 @@ final class ManiphestTransaction
|
||||||
const TYPE_STATUS = 'status';
|
const TYPE_STATUS = 'status';
|
||||||
const TYPE_DESCRIPTION = 'description';
|
const TYPE_DESCRIPTION = 'description';
|
||||||
const TYPE_OWNER = 'reassign';
|
const TYPE_OWNER = 'reassign';
|
||||||
const TYPE_CCS = 'ccs';
|
|
||||||
const TYPE_PROJECTS = 'projects';
|
const TYPE_PROJECTS = 'projects';
|
||||||
const TYPE_PRIORITY = 'priority';
|
const TYPE_PRIORITY = 'priority';
|
||||||
const TYPE_EDGE = 'edge';
|
const TYPE_EDGE = 'edge';
|
||||||
|
@ -21,6 +20,12 @@ final class ManiphestTransaction
|
||||||
// NOTE: this type is deprecated. Keep it around for legacy installs
|
// NOTE: this type is deprecated. Keep it around for legacy installs
|
||||||
// so any transactions render correctly.
|
// so any transactions render correctly.
|
||||||
const TYPE_ATTACH = 'attach';
|
const TYPE_ATTACH = 'attach';
|
||||||
|
/**
|
||||||
|
* TYPE_CCS is legacy and depracted in favor of
|
||||||
|
* PhabricatorTransactions::TYPE_SUBSCRIBERS; keep it around for legacy
|
||||||
|
* transaction-rendering.
|
||||||
|
*/
|
||||||
|
const TYPE_CCS = 'ccs';
|
||||||
|
|
||||||
|
|
||||||
const MAILTAG_STATUS = 'maniphest-status';
|
const MAILTAG_STATUS = 'maniphest-status';
|
||||||
|
|
|
@ -143,6 +143,7 @@ final class PhabricatorSearchAttachController
|
||||||
$targets = id(new ManiphestTaskQuery())
|
$targets = id(new ManiphestTaskQuery())
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withPHIDs(array_keys($phids))
|
->withPHIDs(array_keys($phids))
|
||||||
|
->needSubscriberPHIDs(true)
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
if (empty($targets)) {
|
if (empty($targets)) {
|
||||||
|
@ -156,9 +157,13 @@ final class PhabricatorSearchAttachController
|
||||||
->setContinueOnMissingFields(true);
|
->setContinueOnMissingFields(true);
|
||||||
|
|
||||||
$cc_vector = array();
|
$cc_vector = array();
|
||||||
$cc_vector[] = $task->getCCPHIDs();
|
// since we loaded this via a generic object query, go ahead and get the
|
||||||
|
// attach the cc phids now
|
||||||
|
$task->attachSubscriberPHIDs(
|
||||||
|
PhabricatorSubscribersQuery::loadSubscribersForPHID($task->getPHID()));
|
||||||
|
$cc_vector[] = $task->getSubscriberPHIDs();
|
||||||
foreach ($targets as $target) {
|
foreach ($targets as $target) {
|
||||||
$cc_vector[] = $target->getCCPHIDs();
|
$cc_vector[] = $target->getSubscriberPHIDs();
|
||||||
$cc_vector[] = array(
|
$cc_vector[] = array(
|
||||||
$target->getAuthorPHID(),
|
$target->getAuthorPHID(),
|
||||||
$target->getOwnerPHID(),
|
$target->getOwnerPHID(),
|
||||||
|
@ -178,8 +183,8 @@ final class PhabricatorSearchAttachController
|
||||||
$all_ccs = array_unique($all_ccs);
|
$all_ccs = array_unique($all_ccs);
|
||||||
|
|
||||||
$add_ccs = id(new ManiphestTransaction())
|
$add_ccs = id(new ManiphestTransaction())
|
||||||
->setTransactionType(ManiphestTransaction::TYPE_CCS)
|
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||||
->setNewValue($all_ccs);
|
->setNewValue(array('=' => $all_ccs));
|
||||||
|
|
||||||
$merged_from_txn = id(new ManiphestTransaction())
|
$merged_from_txn = id(new ManiphestTransaction())
|
||||||
->setTransactionType(ManiphestTransaction::TYPE_MERGED_FROM)
|
->setTransactionType(ManiphestTransaction::TYPE_MERGED_FROM)
|
||||||
|
|
|
@ -23,8 +23,6 @@ final class PhabricatorSubscriptionsListController
|
||||||
if ($object instanceof PhabricatorSubscribableInterface) {
|
if ($object instanceof PhabricatorSubscribableInterface) {
|
||||||
$subscriber_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
$subscriber_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
||||||
$phid);
|
$phid);
|
||||||
} else if ($object instanceof ManiphestTask) {
|
|
||||||
$subscriber_phids = $object->getCCPHIDs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$handle_phids = $subscriber_phids;
|
$handle_phids = $subscriber_phids;
|
||||||
|
|
Loading…
Add table
Reference in a new issue