Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/sql/autopatches/20180208.maniphest.01.close.sql b/resources/sql/autopatches/20180208.maniphest.01.close.sql
new file mode 100644
index 0000000000..856300e9ba
--- /dev/null
+++ b/resources/sql/autopatches/20180208.maniphest.01.close.sql
@@ -0,0 +1,5 @@
+ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
+ ADD closedEpoch INT UNSIGNED;
+
+ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
+ ADD closerPHID VARBINARY(64);
diff --git a/resources/sql/autopatches/20180208.maniphest.02.populate.php b/resources/sql/autopatches/20180208.maniphest.02.populate.php
new file mode 100644
index 0000000000..16aa2bf57b
--- /dev/null
+++ b/resources/sql/autopatches/20180208.maniphest.02.populate.php
@@ -0,0 +1,65 @@
+<?php
+
+$table = new ManiphestTask();
+$conn = $table->establishConnection('w');
+$viewer = PhabricatorUser::getOmnipotentUser();
+
+foreach (new LiskMigrationIterator($table) as $task) {
+ if ($task->getClosedEpoch()) {
+ // Task already has a closed date.
+ continue;
+ }
+
+ $status = $task->getStatus();
+ if (!ManiphestTaskStatus::isClosedStatus($status)) {
+ // Task isn't closed.
+ continue;
+ }
+
+ // Look through the transactions from newest to oldest until we find one
+ // where the task was closed. A merge also counts as a close, even though
+ // it doesn't currently produce a separate transaction.
+
+ $type_merge = ManiphestTaskStatusTransaction::TRANSACTIONTYPE;
+ $type_status = ManiphestTaskMergedIntoTransaction::TRANSACTIONTYPE;
+
+ $xactions = id(new ManiphestTransactionQuery())
+ ->setViewer($viewer)
+ ->withObjectPHIDs(array($task->getPHID()))
+ ->withTransactionTypes(
+ array(
+ $type_merge,
+ $type_status,
+ ))
+ ->execute();
+ foreach ($xactions as $xaction) {
+ $old = $xaction->getOldValue();
+ $new = $xaction->getNewValue();
+
+ $type = $xaction->getTransactionType();
+
+ // If this is a status change, but is not a close, don't use it.
+ // (We always use merges, even though it's possible to merge a task which
+ // was previously closed: we can't tell when this happens very easily.)
+ if ($type === $type_status) {
+ if (!ManiphestTaskStatus::isClosedStatus($new)) {
+ continue;
+ }
+
+ if ($old && ManiphestTaskStatus::isClosedStatus($old)) {
+ continue;
+ }
+ }
+
+ queryfx(
+ $conn,
+ 'UPDATE %T SET closedEpoch = %d, closerPHID = %ns
+ WHERE id = %d',
+ $table->getTableName(),
+ $xaction->getDateCreated(),
+ $xaction->getAuthorPHID(),
+ $task->getID());
+
+ break;
+ }
+}
diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php
index e19886d3ff..7ff70abd80 100644
--- a/src/applications/maniphest/storage/ManiphestTask.php
+++ b/src/applications/maniphest/storage/ManiphestTask.php
@@ -1,605 +1,616 @@
<?php
final class ManiphestTask extends ManiphestDAO
implements
PhabricatorSubscribableInterface,
PhabricatorMarkupInterface,
PhabricatorPolicyInterface,
PhabricatorTokenReceiverInterface,
PhabricatorFlaggableInterface,
PhabricatorMentionableInterface,
PhrequentTrackableInterface,
PhabricatorCustomFieldInterface,
PhabricatorDestructibleInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorProjectInterface,
PhabricatorSpacesInterface,
PhabricatorConduitResultInterface,
PhabricatorFulltextInterface,
PhabricatorFerretInterface,
DoorkeeperBridgedObjectInterface,
PhabricatorEditEngineSubtypeInterface,
PhabricatorEditEngineLockableInterface {
const MARKUP_FIELD_DESCRIPTION = 'markup:desc';
protected $authorPHID;
protected $ownerPHID;
protected $status;
protected $priority;
protected $subpriority = 0;
protected $title = '';
protected $description = '';
protected $originalEmailSource;
protected $mailKey;
protected $viewPolicy = PhabricatorPolicies::POLICY_USER;
protected $editPolicy = PhabricatorPolicies::POLICY_USER;
protected $ownerOrdering;
protected $spacePHID;
protected $bridgedObjectPHID;
protected $properties = array();
protected $points;
protected $subtype;
+ protected $closedEpoch;
+ protected $closerPHID;
+
private $subscriberPHIDs = self::ATTACHABLE;
private $groupByProjectPHID = self::ATTACHABLE;
private $customFields = self::ATTACHABLE;
private $edgeProjectPHIDs = self::ATTACHABLE;
private $bridgedObject = self::ATTACHABLE;
public static function initializeNewTask(PhabricatorUser $actor) {
$app = id(new PhabricatorApplicationQuery())
->setViewer($actor)
->withClasses(array('PhabricatorManiphestApplication'))
->executeOne();
$view_policy = $app->getPolicy(ManiphestDefaultViewCapability::CAPABILITY);
$edit_policy = $app->getPolicy(ManiphestDefaultEditCapability::CAPABILITY);
return id(new ManiphestTask())
->setStatus(ManiphestTaskStatus::getDefaultStatus())
->setPriority(ManiphestTaskPriority::getDefaultPriority())
->setAuthorPHID($actor->getPHID())
->setViewPolicy($view_policy)
->setEditPolicy($edit_policy)
->setSpacePHID($actor->getDefaultSpacePHID())
->setSubtype(PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT)
->attachProjectPHIDs(array())
->attachSubscriberPHIDs(array());
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'properties' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'ownerPHID' => 'phid?',
'status' => 'text64',
'priority' => 'uint32',
'title' => 'sort',
'description' => 'text',
'mailKey' => 'bytes20',
'ownerOrdering' => 'text64?',
'originalEmailSource' => 'text255?',
'subpriority' => 'double',
'points' => 'double?',
'bridgedObjectPHID' => 'phid?',
'subtype' => 'text64',
+ 'closedEpoch' => 'epoch?',
+ 'closerPHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
'phid' => array(
'columns' => array('phid'),
'unique' => true,
),
'priority' => array(
'columns' => array('priority', 'status'),
),
'status' => array(
'columns' => array('status'),
),
'ownerPHID' => array(
'columns' => array('ownerPHID', 'status'),
),
'authorPHID' => array(
'columns' => array('authorPHID', 'status'),
),
'ownerOrdering' => array(
'columns' => array('ownerOrdering'),
),
'priority_2' => array(
'columns' => array('priority', 'subpriority'),
),
'key_dateCreated' => array(
'columns' => array('dateCreated'),
),
'key_dateModified' => array(
'columns' => array('dateModified'),
),
'key_title' => array(
'columns' => array('title(64)'),
),
'key_bridgedobject' => array(
'columns' => array('bridgedObjectPHID'),
'unique' => true,
),
'key_subtype' => array(
'columns' => array('subtype'),
),
+ 'key_closed' => array(
+ 'columns' => array('closedEpoch'),
+ ),
+ 'key_closer' => array(
+ 'columns' => array('closerPHID', 'closedEpoch'),
+ ),
),
) + parent::getConfiguration();
}
public function loadDependsOnTaskPHIDs() {
return PhabricatorEdgeQuery::loadDestinationPHIDs(
$this->getPHID(),
ManiphestTaskDependsOnTaskEdgeType::EDGECONST);
}
public function loadDependedOnByTaskPHIDs() {
return PhabricatorEdgeQuery::loadDestinationPHIDs(
$this->getPHID(),
ManiphestTaskDependedOnByTaskEdgeType::EDGECONST);
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(ManiphestTaskPHIDType::TYPECONST);
}
public function getSubscriberPHIDs() {
return $this->assertAttached($this->subscriberPHIDs);
}
public function getProjectPHIDs() {
return $this->assertAttached($this->edgeProjectPHIDs);
}
public function attachProjectPHIDs(array $phids) {
$this->edgeProjectPHIDs = $phids;
return $this;
}
public function attachSubscriberPHIDs(array $phids) {
$this->subscriberPHIDs = $phids;
return $this;
}
public function setOwnerPHID($phid) {
$this->ownerPHID = nonempty($phid, null);
return $this;
}
public function getMonogram() {
return 'T'.$this->getID();
}
public function getURI() {
return '/'.$this->getMonogram();
}
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();
return $result;
}
public function isClosed() {
return ManiphestTaskStatus::isClosedStatus($this->getStatus());
}
public function isLocked() {
return ManiphestTaskStatus::isLockedStatus($this->getStatus());
}
public function setProperty($key, $value) {
$this->properties[$key] = $value;
return $this;
}
public function getProperty($key, $default = null) {
return idx($this->properties, $key, $default);
}
public function getCoverImageFilePHID() {
return idx($this->properties, 'cover.filePHID');
}
public function getCoverImageThumbnailPHID() {
return idx($this->properties, 'cover.thumbnailPHID');
}
public function getWorkboardOrderVectors() {
return array(
PhabricatorProjectColumn::ORDER_PRIORITY => array(
(int)-$this->getPriority(),
(double)-$this->getSubpriority(),
(int)-$this->getID(),
),
);
}
public function getPriorityKeyword() {
$priority = $this->getPriority();
$keyword = ManiphestTaskPriority::getKeywordForTaskPriority($priority);
if ($keyword !== null) {
return $keyword;
}
return ManiphestTaskPriority::UNKNOWN_PRIORITY_KEYWORD;
}
private function comparePriorityTo(ManiphestTask $other) {
$upri = $this->getPriority();
$vpri = $other->getPriority();
if ($upri != $vpri) {
return ($upri - $vpri);
}
$usub = $this->getSubpriority();
$vsub = $other->getSubpriority();
if ($usub != $vsub) {
return ($usub - $vsub);
}
$uid = $this->getID();
$vid = $other->getID();
if ($uid != $vid) {
return ($uid - $vid);
}
return 0;
}
public function isLowerPriorityThan(ManiphestTask $other) {
return ($this->comparePriorityTo($other) < 0);
}
public function isHigherPriorityThan(ManiphestTask $other) {
return ($this->comparePriorityTo($other) > 0);
}
public function getWorkboardProperties() {
return array(
'status' => $this->getStatus(),
'points' => (double)$this->getPoints(),
);
}
/* -( PhabricatorSubscribableInterface )----------------------------------- */
public function isAutomaticallySubscribed($phid) {
return ($phid == $this->getOwnerPHID());
}
/* -( Markup Interface )--------------------------------------------------- */
/**
* @task markup
*/
public function getMarkupFieldKey($field) {
$content = $this->getMarkupText($field);
return PhabricatorMarkupEngine::digestRemarkupContent($this, $content);
}
/**
* @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_INTERACT,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_INTERACT:
if ($this->isLocked()) {
return PhabricatorPolicies::POLICY_NOONE;
} else {
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;
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new ManiphestTransactionEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new ManiphestTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorSpacesInterface )----------------------------------------- */
public function getSpacePHID() {
return $this->spacePHID;
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('title')
->setType('string')
->setDescription(pht('The title of the task.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('description')
->setType('remarkup')
->setDescription(pht('The task description.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('authorPHID')
->setType('phid')
->setDescription(pht('Original task author.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('ownerPHID')
->setType('phid?')
->setDescription(pht('Current task owner, if task is assigned.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('status')
->setType('map<string, wild>')
->setDescription(pht('Information about task status.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('priority')
->setType('map<string, wild>')
->setDescription(pht('Information about task priority.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('points')
->setType('points')
->setDescription(pht('Point value of the task.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('subtype')
->setType('string')
->setDescription(pht('Subtype of the task.')),
);
}
public function getFieldValuesForConduit() {
$status_value = $this->getStatus();
$status_info = array(
'value' => $status_value,
'name' => ManiphestTaskStatus::getTaskStatusName($status_value),
'color' => ManiphestTaskStatus::getStatusColor($status_value),
);
$priority_value = (int)$this->getPriority();
$priority_info = array(
'value' => $priority_value,
'subpriority' => (double)$this->getSubpriority(),
'name' => ManiphestTaskPriority::getTaskPriorityName($priority_value),
'color' => ManiphestTaskPriority::getTaskPriorityColor($priority_value),
);
return array(
'name' => $this->getTitle(),
'description' => array(
'raw' => $this->getDescription(),
),
'authorPHID' => $this->getAuthorPHID(),
'ownerPHID' => $this->getOwnerPHID(),
'status' => $status_info,
'priority' => $priority_info,
'points' => $this->getPoints(),
'subtype' => $this->getSubtype(),
);
}
public function getConduitSearchAttachments() {
return array(
id(new PhabricatorBoardColumnsSearchEngineAttachment())
->setAttachmentKey('columns'),
);
}
public function newSubtypeObject() {
$subtype_key = $this->getEditEngineSubtype();
$subtype_map = $this->newEditEngineSubtypeMap();
return idx($subtype_map, $subtype_key);
}
/* -( PhabricatorFulltextInterface )--------------------------------------- */
public function newFulltextEngine() {
return new ManiphestTaskFulltextEngine();
}
/* -( DoorkeeperBridgedObjectInterface )----------------------------------- */
public function getBridgedObject() {
return $this->assertAttached($this->bridgedObject);
}
public function attachBridgedObject(
DoorkeeperExternalObject $object = null) {
$this->bridgedObject = $object;
return $this;
}
/* -( PhabricatorEditEngineSubtypeInterface )------------------------------ */
public function getEditEngineSubtype() {
return $this->getSubtype();
}
public function setEditEngineSubtype($value) {
return $this->setSubtype($value);
}
public function newEditEngineSubtypeMap() {
$config = PhabricatorEnv::getEnvConfig('maniphest.subtypes');
return PhabricatorEditEngineSubtype::newSubtypeMap($config);
}
/* -( PhabricatorEditEngineLockableInterface )----------------------------- */
public function newEditEngineLock() {
return new ManiphestTaskEditEngineLock();
}
/* -( PhabricatorFerretInterface )----------------------------------------- */
public function newFerretEngine() {
return new ManiphestTaskFerretEngine();
}
}
diff --git a/src/applications/maniphest/xaction/ManiphestTaskMergedIntoTransaction.php b/src/applications/maniphest/xaction/ManiphestTaskMergedIntoTransaction.php
index cd0cad6a39..630f5190ce 100644
--- a/src/applications/maniphest/xaction/ManiphestTaskMergedIntoTransaction.php
+++ b/src/applications/maniphest/xaction/ManiphestTaskMergedIntoTransaction.php
@@ -1,47 +1,47 @@
<?php
final class ManiphestTaskMergedIntoTransaction
extends ManiphestTaskTransactionType {
const TRANSACTIONTYPE = 'mergedinto';
public function generateOldValue($object) {
return null;
}
public function applyInternalEffects($object, $value) {
- $object->setStatus(ManiphestTaskStatus::getDuplicateStatus());
+ $this->updateStatus($object, ManiphestTaskStatus::getDuplicateStatus());
}
public function getActionName() {
return pht('Merged');
}
public function getTitle() {
$new = $this->getNewValue();
return pht(
'%s closed this task as a duplicate of %s.',
$this->renderAuthor(),
$this->renderHandle($new));
}
public function getTitleForFeed() {
$new = $this->getNewValue();
return pht(
'%s merged task %s into %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderHandle($new));
}
public function getIcon() {
return 'fa-check';
}
public function getColor() {
return 'indigo';
}
}
diff --git a/src/applications/maniphest/xaction/ManiphestTaskStatusTransaction.php b/src/applications/maniphest/xaction/ManiphestTaskStatusTransaction.php
index dd51a63799..6f4b558e05 100644
--- a/src/applications/maniphest/xaction/ManiphestTaskStatusTransaction.php
+++ b/src/applications/maniphest/xaction/ManiphestTaskStatusTransaction.php
@@ -1,240 +1,240 @@
<?php
final class ManiphestTaskStatusTransaction
extends ManiphestTaskTransactionType {
const TRANSACTIONTYPE = 'status';
public function generateOldValue($object) {
return $object->getStatus();
}
public function applyInternalEffects($object, $value) {
- $object->setStatus($value);
+ $this->updateStatus($object, $value);
}
public function shouldHide() {
if ($this->getOldValue() === null) {
return true;
} else {
return false;
}
}
public function getActionStrength() {
return 1.3;
}
public function getActionName() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$action = ManiphestTaskStatus::getStatusActionName($new);
if ($action) {
return $action;
}
$old_closed = ManiphestTaskStatus::isClosedStatus($old);
$new_closed = ManiphestTaskStatus::isClosedStatus($new);
if ($new_closed && !$old_closed) {
return pht('Closed');
} else if (!$new_closed && $old_closed) {
return pht('Reopened');
} else {
return pht('Changed Status');
}
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$old_closed = ManiphestTaskStatus::isClosedStatus($old);
$new_closed = ManiphestTaskStatus::isClosedStatus($new);
$old_name = ManiphestTaskStatus::getTaskStatusName($old);
$new_name = ManiphestTaskStatus::getTaskStatusName($new);
$commit_phid = $this->getMetadataValue('commitPHID');
if ($new_closed && !$old_closed) {
if ($new == ManiphestTaskStatus::getDuplicateStatus()) {
if ($commit_phid) {
return pht(
'%s closed this task as a duplicate by committing %s.',
$this->renderAuthor(),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s closed this task as a duplicate.',
$this->renderAuthor());
}
} else {
if ($commit_phid) {
return pht(
'%s closed this task as %s by committing %s.',
$this->renderAuthor(),
$this->renderValue($new_name),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s closed this task as %s.',
$this->renderAuthor(),
$this->renderValue($new_name));
}
}
} else if (!$new_closed && $old_closed) {
if ($commit_phid) {
return pht(
'%s reopened this task as %s by committing %s.',
$this->renderAuthor(),
$this->renderValue($new_name),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s reopened this task as %s.',
$this->renderAuthor(),
$this->renderValue($new_name));
}
} else {
if ($commit_phid) {
return pht(
'%s changed the task status from %s to %s by committing %s.',
$this->renderAuthor(),
$this->renderValue($old_name),
$this->renderValue($new_name),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s changed the task status from %s to %s.',
$this->renderAuthor(),
$this->renderValue($old_name),
$this->renderValue($new_name));
}
}
}
public function getTitleForFeed() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$old_closed = ManiphestTaskStatus::isClosedStatus($old);
$new_closed = ManiphestTaskStatus::isClosedStatus($new);
$old_name = ManiphestTaskStatus::getTaskStatusName($old);
$new_name = ManiphestTaskStatus::getTaskStatusName($new);
$commit_phid = $this->getMetadataValue('commitPHID');
if ($new_closed && !$old_closed) {
if ($new == ManiphestTaskStatus::getDuplicateStatus()) {
if ($commit_phid) {
return pht(
'%s closed %s as a duplicate by committing %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s closed %s as a duplicate.',
$this->renderAuthor(),
$this->renderObject());
}
} else {
if ($commit_phid) {
return pht(
'%s closed %s as %s by committing %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderValue($new_name),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s closed %s as %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderValue($new_name));
}
}
} else if (!$new_closed && $old_closed) {
if ($commit_phid) {
return pht(
'%s reopened %s as %s by committing %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderValue($new_name),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s reopened %s as "%s".',
$this->renderAuthor(),
$this->renderObject(),
$new_name);
}
} else {
if ($commit_phid) {
return pht(
'%s changed the status of %s from %s to %s by committing %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderValue($old_name),
$this->renderValue($new_name),
$this->renderHandle($commit_phid));
} else {
return pht(
'%s changed the status of %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderValue($old_name),
$this->renderValue($new_name));
}
}
}
public function getIcon() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$action = ManiphestTaskStatus::getStatusIcon($new);
if ($action !== null) {
return $action;
}
if (ManiphestTaskStatus::isClosedStatus($new)) {
return 'fa-check';
} else {
return 'fa-pencil';
}
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
$color = ManiphestTaskStatus::getStatusColor($new);
if ($color !== null) {
return $color;
}
if (ManiphestTaskStatus::isOpenStatus($new)) {
return 'green';
} else {
return 'indigo';
}
}
public function getTransactionTypeForConduit($xaction) {
return 'status';
}
public function getFieldValuesForConduit($xaction, $data) {
return array(
'old' => $xaction->getOldValue(),
'new' => $xaction->getNewValue(),
);
}
}
diff --git a/src/applications/maniphest/xaction/ManiphestTaskTransactionType.php b/src/applications/maniphest/xaction/ManiphestTaskTransactionType.php
index c59de163c6..836e7765b8 100644
--- a/src/applications/maniphest/xaction/ManiphestTaskTransactionType.php
+++ b/src/applications/maniphest/xaction/ManiphestTaskTransactionType.php
@@ -1,6 +1,29 @@
<?php
abstract class ManiphestTaskTransactionType
extends PhabricatorModularTransactionType {
+ protected function updateStatus($object, $new_value) {
+ $old_value = $object->getStatus();
+ $object->setStatus($new_value);
+
+ // If this status change closes or opens the task, update the closed
+ // date and actor PHID.
+ $old_closed = ManiphestTaskStatus::isClosedStatus($old_value);
+ $new_closed = ManiphestTaskStatus::isClosedStatus($new_value);
+
+ $is_close = ($new_closed && !$old_closed);
+ $is_open = (!$new_closed && $old_closed);
+
+ if ($is_close) {
+ $object
+ ->setClosedEpoch(PhabricatorTime::getNow())
+ ->setCloserPHID($this->getActingAsPHID());
+ } else if ($is_open) {
+ $object
+ ->setClosedEpoch(null)
+ ->setCloserPHID(null);
+ }
+ }
+
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Nov 5, 11:59 PM (17 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
321334
Default Alt Text
(29 KB)

Event Timeline