mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-04 20:52:43 +01:00
fae23e0860
Summary: Ref T5476. Currently, the task edit code assumes it knows what the UI looks like and sends back where on the column an item should be inserted. This is buggy after adding filters, and relatively complex. Instead, send down the ordering on the whole column and sort it in the UI. This is a bit simpler overall and more general. It makes it easier to further generalize this code for T5476. Test Plan: - Edited a task on a board, changing priority. Saw it reorder properly. - Edited a task on a board in a field of other tasks at the same top-level priority. Saw it refresh without reordering. Reviewers: chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T5476 Differential Revision: https://secure.phabricator.com/D9832
315 lines
7.8 KiB
PHP
315 lines
7.8 KiB
PHP
<?php
|
|
|
|
final class ManiphestTask extends ManiphestDAO
|
|
implements
|
|
PhabricatorMarkupInterface,
|
|
PhabricatorPolicyInterface,
|
|
PhabricatorTokenReceiverInterface,
|
|
PhabricatorFlaggableInterface,
|
|
PhrequentTrackableInterface,
|
|
PhabricatorCustomFieldInterface,
|
|
PhabricatorDestructableInterface {
|
|
|
|
const MARKUP_FIELD_DESCRIPTION = 'markup:desc';
|
|
|
|
protected $authorPHID;
|
|
protected $ownerPHID;
|
|
protected $ccPHIDs = array();
|
|
|
|
protected $status;
|
|
protected $priority;
|
|
protected $subpriority = 0;
|
|
|
|
protected $title = '';
|
|
protected $originalTitle = '';
|
|
protected $description = '';
|
|
protected $originalEmailSource;
|
|
protected $mailKey;
|
|
protected $viewPolicy = PhabricatorPolicies::POLICY_USER;
|
|
protected $editPolicy = PhabricatorPolicies::POLICY_USER;
|
|
|
|
protected $attached = array();
|
|
protected $projectPHIDs = array();
|
|
private $projectsNeedUpdate;
|
|
private $subscribersNeedUpdate;
|
|
|
|
protected $ownerOrdering;
|
|
|
|
private $groupByProjectPHID = self::ATTACHABLE;
|
|
private $customFields = self::ATTACHABLE;
|
|
|
|
public static function initializeNewTask(PhabricatorUser $actor) {
|
|
$app = id(new PhabricatorApplicationQuery())
|
|
->setViewer($actor)
|
|
->withClasses(array('PhabricatorApplicationManiphest'))
|
|
->executeOne();
|
|
|
|
$view_policy = $app->getPolicy(ManiphestCapabilityDefaultView::CAPABILITY);
|
|
$edit_policy = $app->getPolicy(ManiphestCapabilityDefaultEdit::CAPABILITY);
|
|
|
|
return id(new ManiphestTask())
|
|
->setStatus(ManiphestTaskStatus::getDefaultStatus())
|
|
->setPriority(ManiphestTaskPriority::getDefaultPriority())
|
|
->setAuthorPHID($actor->getPHID())
|
|
->setViewPolicy($view_policy)
|
|
->setEditPolicy($edit_policy);
|
|
}
|
|
|
|
public function getConfiguration() {
|
|
return array(
|
|
self::CONFIG_AUX_PHID => true,
|
|
self::CONFIG_SERIALIZATION => array(
|
|
'ccPHIDs' => self::SERIALIZATION_JSON,
|
|
'attached' => self::SERIALIZATION_JSON,
|
|
'projectPHIDs' => self::SERIALIZATION_JSON,
|
|
),
|
|
) + parent::getConfiguration();
|
|
}
|
|
|
|
public function loadDependsOnTaskPHIDs() {
|
|
return PhabricatorEdgeQuery::loadDestinationPHIDs(
|
|
$this->getPHID(),
|
|
PhabricatorEdgeConfig::TYPE_TASK_DEPENDS_ON_TASK);
|
|
}
|
|
|
|
public function loadDependedOnByTaskPHIDs() {
|
|
return PhabricatorEdgeQuery::loadDestinationPHIDs(
|
|
$this->getPHID(),
|
|
PhabricatorEdgeConfig::TYPE_TASK_DEPENDED_ON_BY_TASK);
|
|
}
|
|
|
|
public function getAttachedPHIDs($type) {
|
|
return array_keys(idx($this->attached, $type, array()));
|
|
}
|
|
|
|
public function generatePHID() {
|
|
return PhabricatorPHID::generateNewPHID(ManiphestPHIDTypeTask::TYPECONST);
|
|
}
|
|
|
|
public function getCCPHIDs() {
|
|
return array_values(nonempty($this->ccPHIDs, array()));
|
|
}
|
|
|
|
public function setProjectPHIDs(array $phids) {
|
|
$this->projectPHIDs = array_values($phids);
|
|
$this->projectsNeedUpdate = true;
|
|
return $this;
|
|
}
|
|
|
|
public function getProjectPHIDs() {
|
|
return array_values(nonempty($this->projectPHIDs, array()));
|
|
}
|
|
|
|
public function setCCPHIDs(array $phids) {
|
|
$this->ccPHIDs = array_values($phids);
|
|
$this->subscribersNeedUpdate = true;
|
|
return $this;
|
|
}
|
|
|
|
public function setOwnerPHID($phid) {
|
|
$this->ownerPHID = nonempty($phid, null);
|
|
$this->subscribersNeedUpdate = true;
|
|
return $this;
|
|
}
|
|
|
|
public function setTitle($title) {
|
|
$this->title = $title;
|
|
if (!$this->getID()) {
|
|
$this->originalTitle = $title;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function getMonogram() {
|
|
return 'T'.$this->getID();
|
|
}
|
|
|
|
public function attachGroupByProjectPHID($phid) {
|
|
$this->groupByProjectPHID = $phid;
|
|
return $this;
|
|
}
|
|
|
|
public function getGroupByProjectPHID() {
|
|
return $this->assertAttached($this->groupByProjectPHID);
|
|
}
|
|
|
|
public function save() {
|
|
if (!$this->mailKey) {
|
|
$this->mailKey = Filesystem::readRandomCharacters(20);
|
|
}
|
|
|
|
$result = parent::save();
|
|
|
|
if ($this->projectsNeedUpdate) {
|
|
// If we've changed the project PHIDs for this task, update the link
|
|
// table.
|
|
ManiphestTaskProject::updateTaskProjects($this);
|
|
$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;
|
|
}
|
|
|
|
public function isClosed() {
|
|
return ManiphestTaskStatus::isClosedStatus($this->getStatus());
|
|
}
|
|
|
|
public function getPrioritySortVector() {
|
|
return array(
|
|
$this->getPriority(),
|
|
-$this->getSubpriority(),
|
|
);
|
|
}
|
|
|
|
|
|
/* -( Markup Interface )--------------------------------------------------- */
|
|
|
|
|
|
/**
|
|
* @task markup
|
|
*/
|
|
public function getMarkupFieldKey($field) {
|
|
$hash = PhabricatorHash::digest($this->getMarkupText($field));
|
|
$id = $this->getID();
|
|
return "maniphest:T{$id}:{$field}:{$hash}";
|
|
}
|
|
|
|
|
|
/**
|
|
* @task markup
|
|
*/
|
|
public function getMarkupText($field) {
|
|
return $this->getDescription();
|
|
}
|
|
|
|
|
|
/**
|
|
* @task markup
|
|
*/
|
|
public function newMarkupEngine($field) {
|
|
return PhabricatorMarkupEngine::newManiphestMarkupEngine();
|
|
}
|
|
|
|
|
|
/**
|
|
* @task markup
|
|
*/
|
|
public function didMarkupText(
|
|
$field,
|
|
$output,
|
|
PhutilMarkupEngine $engine) {
|
|
return $output;
|
|
}
|
|
|
|
|
|
/**
|
|
* @task markup
|
|
*/
|
|
public function shouldUseMarkupCache($field) {
|
|
return (bool)$this->getID();
|
|
}
|
|
|
|
|
|
/* -( Policy Interface )--------------------------------------------------- */
|
|
|
|
|
|
public function getCapabilities() {
|
|
return array(
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
);
|
|
}
|
|
|
|
public function getPolicy($capability) {
|
|
switch ($capability) {
|
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
|
return $this->getViewPolicy();
|
|
case PhabricatorPolicyCapability::CAN_EDIT:
|
|
return $this->getEditPolicy();
|
|
}
|
|
}
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
|
|
|
|
// The owner of a task can always view and edit it.
|
|
$owner_phid = $this->getOwnerPHID();
|
|
if ($owner_phid) {
|
|
$user_phid = $user->getPHID();
|
|
if ($user_phid == $owner_phid) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function describeAutomaticCapability($capability) {
|
|
return pht(
|
|
'The owner of a task can always view and edit it.');
|
|
}
|
|
|
|
|
|
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
|
|
|
|
|
|
public function getUsersToNotifyOfTokenGiven() {
|
|
// Sort of ambiguous who this was intended for; just let them both know.
|
|
return array_filter(
|
|
array_unique(
|
|
array(
|
|
$this->getAuthorPHID(),
|
|
$this->getOwnerPHID(),
|
|
)));
|
|
}
|
|
|
|
|
|
/* -( PhabricatorCustomFieldInterface )------------------------------------ */
|
|
|
|
|
|
public function getCustomFieldSpecificationForRole($role) {
|
|
return PhabricatorEnv::getEnvConfig('maniphest.fields');
|
|
}
|
|
|
|
public function getCustomFieldBaseClass() {
|
|
return 'ManiphestCustomField';
|
|
}
|
|
|
|
public function getCustomFields() {
|
|
return $this->assertAttached($this->customFields);
|
|
}
|
|
|
|
public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
|
|
$this->customFields = $fields;
|
|
return $this;
|
|
}
|
|
|
|
|
|
/* -( PhabricatorDestructableInterface )----------------------------------- */
|
|
|
|
|
|
public function destroyObjectPermanently(
|
|
PhabricatorDestructionEngine $engine) {
|
|
|
|
$this->openTransaction();
|
|
|
|
// TODO: Once this implements PhabricatorTransactionInterface, this
|
|
// will be handled automatically and can be removed.
|
|
$xactions = id(new ManiphestTransaction())->loadAllWhere(
|
|
'objectPHID = %s',
|
|
$this->getPHID());
|
|
foreach ($xactions as $xaction) {
|
|
$engine->destroyObject($xaction);
|
|
}
|
|
|
|
$this->delete();
|
|
$this->saveTransaction();
|
|
}
|
|
|
|
}
|