1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 16:22:43 +01:00

Track closed date and closing user for tasks explicitly

Summary:
Ref T4434. Although some of the use cases for this data are better fits for Facts, this data is reasonable to track separately.

I have an approximate view of it already ("closed, ordered by date modified") that's useful to review things that were fixed recently. This lets us make that view more effective.

This just adds (and populates) the storage. Followups will add Conduit, Export, Search, and UI support.

This is slightly tricky because merges work oddly (see T13020).

Test Plan:
  - Ran migration, checked database for sensible results.
  - Created a task in open/closed status, got the right database values.
  - Modified a task to close/open it, got the right values.
  - Merged an open task, got updates.

Maniphest Tasks: T4434

Differential Revision: https://secure.phabricator.com/D19037
This commit is contained in:
epriestley 2018-02-08 14:20:32 -08:00
parent d1e273daf6
commit f028aa6f60
6 changed files with 106 additions and 2 deletions

View file

@ -0,0 +1,5 @@
ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
ADD closedEpoch INT UNSIGNED;
ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
ADD closerPHID VARBINARY(64);

View file

@ -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;
}
}

View file

@ -44,6 +44,9 @@ final class ManiphestTask extends ManiphestDAO
protected $points;
protected $subtype;
protected $closedEpoch;
protected $closerPHID;
private $subscriberPHIDs = self::ATTACHABLE;
private $groupByProjectPHID = self::ATTACHABLE;
private $customFields = self::ATTACHABLE;
@ -90,6 +93,8 @@ final class ManiphestTask extends ManiphestDAO
'points' => 'double?',
'bridgedObjectPHID' => 'phid?',
'subtype' => 'text64',
'closedEpoch' => 'epoch?',
'closerPHID' => 'phid?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_phid' => null,
@ -131,6 +136,12 @@ final class ManiphestTask extends ManiphestDAO
'key_subtype' => array(
'columns' => array('subtype'),
),
'key_closed' => array(
'columns' => array('closedEpoch'),
),
'key_closer' => array(
'columns' => array('closerPHID', 'closedEpoch'),
),
),
) + parent::getConfiguration();
}

View file

@ -10,7 +10,7 @@ final class ManiphestTaskMergedIntoTransaction
}
public function applyInternalEffects($object, $value) {
$object->setStatus(ManiphestTaskStatus::getDuplicateStatus());
$this->updateStatus($object, ManiphestTaskStatus::getDuplicateStatus());
}
public function getActionName() {

View file

@ -10,7 +10,7 @@ final class ManiphestTaskStatusTransaction
}
public function applyInternalEffects($object, $value) {
$object->setStatus($value);
$this->updateStatus($object, $value);
}
public function shouldHide() {

View file

@ -3,4 +3,27 @@
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);
}
}
}