mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 20:10:55 +01:00
Conduit APIs to start and stop tracking time in phrequent
Summary: This adds methods to start and stop tracking any arbitrary PHID in phrequent. Currently, this uses copy-pasted code from PhrequentTrackController. I had to do this because the code to start/stop was not abstracted into a common class. Once the code to start/stop working is extracted into a re-usable class, the conduit API can use this as well. Test Plan: I called the functions with a PHID of a task and ensured that the fields in the phrequent database table was being updated correctly. Reviewers: skyronic, #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: maxhodak, erik.fercak, aran, epriestley, Korvin Maniphest Tasks: T3569, T3970 Differential Revision: https://secure.phabricator.com/D7326
This commit is contained in:
parent
9a679bf374
commit
2101c3b689
9 changed files with 273 additions and 42 deletions
|
@ -225,6 +225,10 @@ phutil_register_library_map(array(
|
|||
'ConduitAPI_phragment_Method' => 'applications/phragment/conduit/ConduitAPI_phragment_Method.php',
|
||||
'ConduitAPI_phragment_getpatch_Method' => 'applications/phragment/conduit/ConduitAPI_phragment_getpatch_Method.php',
|
||||
'ConduitAPI_phragment_queryfragments_Method' => 'applications/phragment/conduit/ConduitAPI_phragment_queryfragments_Method.php',
|
||||
'ConduitAPI_phrequent_Method' => 'applications/phrequent/conduit/ConduitAPI_phrequent_Method.php',
|
||||
'ConduitAPI_phrequent_pop_Method' => 'applications/phrequent/conduit/ConduitAPI_phrequent_pop_Method.php',
|
||||
'ConduitAPI_phrequent_push_Method' => 'applications/phrequent/conduit/ConduitAPI_phrequent_push_Method.php',
|
||||
'ConduitAPI_phrequent_tracking_Method' => 'applications/phrequent/conduit/ConduitAPI_phrequent_tracking_Method.php',
|
||||
'ConduitAPI_phriction_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_Method.php',
|
||||
'ConduitAPI_phriction_edit_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_edit_Method.php',
|
||||
'ConduitAPI_phriction_history_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_history_Method.php',
|
||||
|
@ -2547,6 +2551,7 @@ phutil_register_library_map(array(
|
|||
'PhrequentTimeBlockTestCase' => 'applications/phrequent/storage/__tests__/PhrequentTimeBlockTestCase.php',
|
||||
'PhrequentTrackController' => 'applications/phrequent/controller/PhrequentTrackController.php',
|
||||
'PhrequentTrackableInterface' => 'applications/phrequent/interface/PhrequentTrackableInterface.php',
|
||||
'PhrequentTrackingEditor' => 'applications/phrequent/editor/PhrequentTrackingEditor.php',
|
||||
'PhrequentUIEventListener' => 'applications/phrequent/event/PhrequentUIEventListener.php',
|
||||
'PhrequentUserTime' => 'applications/phrequent/storage/PhrequentUserTime.php',
|
||||
'PhrequentUserTimeQuery' => 'applications/phrequent/query/PhrequentUserTimeQuery.php',
|
||||
|
@ -2937,6 +2942,10 @@ phutil_register_library_map(array(
|
|||
'ConduitAPI_phragment_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_phragment_getpatch_Method' => 'ConduitAPI_phragment_Method',
|
||||
'ConduitAPI_phragment_queryfragments_Method' => 'ConduitAPI_phragment_Method',
|
||||
'ConduitAPI_phrequent_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_phrequent_pop_Method' => 'ConduitAPI_phrequent_Method',
|
||||
'ConduitAPI_phrequent_push_Method' => 'ConduitAPI_phrequent_Method',
|
||||
'ConduitAPI_phrequent_tracking_Method' => 'ConduitAPI_phrequent_Method',
|
||||
'ConduitAPI_phriction_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_phriction_edit_Method' => 'ConduitAPI_phriction_Method',
|
||||
'ConduitAPI_phriction_history_Method' => 'ConduitAPI_phriction_Method',
|
||||
|
@ -5517,6 +5526,7 @@ phutil_register_library_map(array(
|
|||
'PhrequentTimeBlock' => 'Phobject',
|
||||
'PhrequentTimeBlockTestCase' => 'PhabricatorTestCase',
|
||||
'PhrequentTrackController' => 'PhrequentController',
|
||||
'PhrequentTrackingEditor' => 'PhabricatorEditor',
|
||||
'PhrequentUIEventListener' => 'PhabricatorEventListener',
|
||||
'PhrequentUserTime' =>
|
||||
array(
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
abstract class ConduitAPI_phrequent_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getApplication() {
|
||||
return PhabricatorApplication::getByClass(
|
||||
'PhabricatorApplicationPhrequent');
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
final class ConduitAPI_phrequent_pop_Method
|
||||
extends ConduitAPI_phrequent_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Stop tracking time on an object by popping it from the stack.');
|
||||
}
|
||||
|
||||
public function getMethodStatus() {
|
||||
return self::METHOD_STATUS_UNSTABLE;
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'objectPHID' => 'phid',
|
||||
'stopTime' => 'int',
|
||||
'note' => 'string'
|
||||
);
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'phid';
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$user = $request->getUser();
|
||||
$object_phid = $request->getValue('objectPHID');
|
||||
$timestamp = $request->getValue('stopTime');
|
||||
$note = $request->getValue('note');
|
||||
if ($timestamp === null) {
|
||||
$timestamp = time();
|
||||
}
|
||||
|
||||
$editor = new PhrequentTrackingEditor();
|
||||
|
||||
if (!$object_phid) {
|
||||
return $editor->stopTrackingTop($user, $timestamp, $note);
|
||||
} else {
|
||||
return $editor->stopTracking($user, $object_phid, $timestamp, $note);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
final class ConduitAPI_phrequent_push_Method
|
||||
extends ConduitAPI_phrequent_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht(
|
||||
'Start tracking time on an object by '.
|
||||
'pushing it on the tracking stack.');
|
||||
}
|
||||
|
||||
public function getMethodStatus() {
|
||||
return self::METHOD_STATUS_UNSTABLE;
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'objectPHID' => 'required phid',
|
||||
'startTime' => 'int'
|
||||
);
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'phid';
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$user = $request->getUser();
|
||||
$object_phid = $request->getValue('objectPHID');
|
||||
$timestamp = $request->getValue('startTime');
|
||||
if ($timestamp === null) {
|
||||
$timestamp = time();
|
||||
}
|
||||
|
||||
$editor = new PhrequentTrackingEditor();
|
||||
return $editor->startTracking($user, $object_phid, $timestamp);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
final class ConduitAPI_phrequent_tracking_Method
|
||||
extends ConduitAPI_phrequent_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht(
|
||||
'Returns current objects being tracked in Phrequent.');
|
||||
}
|
||||
|
||||
public function getMethodStatus() {
|
||||
return self::METHOD_STATUS_UNSTABLE;
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'array';
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$user = $request->getUser();
|
||||
|
||||
$times = id(new PhrequentUserTimeQuery())
|
||||
->setViewer($user)
|
||||
->needPreemptingEvents(true)
|
||||
->withUserPHIDs(array($user->getPHID()))
|
||||
->execute();
|
||||
|
||||
$now = time();
|
||||
|
||||
$results = id(new PhrequentTimeBlock($times))
|
||||
->getCurrentWorkStack($now);
|
||||
|
||||
return array('data' => $results);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,6 +14,7 @@ final class PhrequentTrackController
|
|||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$editor = new PhrequentTrackingEditor();
|
||||
|
||||
$phid = $this->phid;
|
||||
$handle = id(new PhabricatorHandleQuery())
|
||||
|
@ -61,9 +62,9 @@ final class PhrequentTrackController
|
|||
|
||||
if (!$err) {
|
||||
if ($this->isStartingTracking()) {
|
||||
$this->startTracking($user, $this->phid, $timestamp);
|
||||
$editor->startTracking($user, $this->phid, $timestamp);
|
||||
} else if ($this->isStoppingTracking()) {
|
||||
$this->stopTracking($user, $this->phid, $timestamp, $note);
|
||||
$editor->stopTracking($user, $this->phid, $timestamp, $note);
|
||||
}
|
||||
return id(new AphrontRedirectResponse());
|
||||
}
|
||||
|
@ -108,39 +109,4 @@ final class PhrequentTrackController
|
|||
private function isStoppingTracking() {
|
||||
return $this->verb === 'stop';
|
||||
}
|
||||
|
||||
private function startTracking($user, $phid, $timestamp) {
|
||||
$usertime = new PhrequentUserTime();
|
||||
$usertime->setDateStarted($timestamp);
|
||||
$usertime->setUserPHID($user->getPHID());
|
||||
$usertime->setObjectPHID($phid);
|
||||
$usertime->save();
|
||||
}
|
||||
|
||||
private function stopTracking($user, $phid, $timestamp, $note) {
|
||||
if (!PhrequentUserTimeQuery::isUserTrackingObject($user, $phid)) {
|
||||
// Don't do anything, it's not being tracked.
|
||||
return;
|
||||
}
|
||||
|
||||
$usertime_dao = new PhrequentUserTime();
|
||||
$conn = $usertime_dao->establishConnection('r');
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'UPDATE %T usertime '.
|
||||
'SET usertime.dateEnded = %d, '.
|
||||
'usertime.note = %s '.
|
||||
'WHERE usertime.userPHID = %s '.
|
||||
'AND usertime.objectPHID = %s '.
|
||||
'AND usertime.dateEnded IS NULL '.
|
||||
'ORDER BY usertime.dateStarted, usertime.id DESC '.
|
||||
'LIMIT 1',
|
||||
$usertime_dao->getTableName(),
|
||||
$timestamp,
|
||||
$note,
|
||||
$user->getPHID(),
|
||||
$phid);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
final class PhrequentTrackingEditor extends PhabricatorEditor {
|
||||
|
||||
public function startTracking(PhabricatorUser $user, $phid, $timestamp) {
|
||||
$usertime = new PhrequentUserTime();
|
||||
$usertime->setDateStarted($timestamp);
|
||||
$usertime->setUserPHID($user->getPHID());
|
||||
$usertime->setObjectPHID($phid);
|
||||
$usertime->save();
|
||||
|
||||
return $phid;
|
||||
}
|
||||
|
||||
public function stopTracking(
|
||||
PhabricatorUser $user,
|
||||
$phid,
|
||||
$timestamp,
|
||||
$note) {
|
||||
|
||||
if (!PhrequentUserTimeQuery::isUserTrackingObject($user, $phid)) {
|
||||
// Don't do anything, it's not being tracked.
|
||||
return null;
|
||||
}
|
||||
|
||||
$usertime_dao = new PhrequentUserTime();
|
||||
$conn = $usertime_dao->establishConnection('r');
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'UPDATE %T usertime '.
|
||||
'SET usertime.dateEnded = %d, '.
|
||||
'usertime.note = %s '.
|
||||
'WHERE usertime.userPHID = %s '.
|
||||
'AND usertime.objectPHID = %s '.
|
||||
'AND usertime.dateEnded IS NULL '.
|
||||
'ORDER BY usertime.dateStarted, usertime.id DESC '.
|
||||
'LIMIT 1',
|
||||
$usertime_dao->getTableName(),
|
||||
$timestamp,
|
||||
$note,
|
||||
$user->getPHID(),
|
||||
$phid);
|
||||
|
||||
return $phid;
|
||||
}
|
||||
|
||||
public function stopTrackingTop(PhabricatorUser $user, $timestamp, $note) {
|
||||
$times = id(new PhrequentUserTimeQuery())
|
||||
->setViewer($user)
|
||||
->withUserPHIDs(array($user->getPHID()))
|
||||
->withEnded(PhrequentUserTimeQuery::ENDED_NO)
|
||||
->setOrder(PhrequentUserTimeQuery::ORDER_STARTED_DESC)
|
||||
->execute();
|
||||
|
||||
if (count($times) === 0) {
|
||||
// Nothing to stop tracking.
|
||||
return null;
|
||||
}
|
||||
|
||||
$current = head($times);
|
||||
|
||||
return $this->stopTracking(
|
||||
$user,
|
||||
$current->getObjectPHID(),
|
||||
$timestamp,
|
||||
$note);
|
||||
}
|
||||
|
||||
}
|
|
@ -186,7 +186,7 @@ final class PhrequentSearchEngine
|
|||
$usertime->getUserPHID() === $viewer->getPHID()) {
|
||||
$item->addAction(
|
||||
id(new PHUIListItemView())
|
||||
->setIcon('fa-time-o')
|
||||
->setIcon('fa-stop')
|
||||
->addSigil('phrequent-stop-tracking')
|
||||
->setWorkflow(true)
|
||||
->setRenderNameAsTooltip(true)
|
||||
|
|
|
@ -37,12 +37,12 @@ final class PhrequentTimeBlock extends Phobject {
|
|||
$timeline = array();
|
||||
$timeline[] = array(
|
||||
'event' => $event,
|
||||
'at' => $event->getDateStarted(),
|
||||
'at' => (int)$event->getDateStarted(),
|
||||
'type' => 'start',
|
||||
);
|
||||
$timeline[] = array(
|
||||
'event' => $event,
|
||||
'at' => nonempty($event->getDateEnded(), $now),
|
||||
'at' => (int)nonempty($event->getDateEnded(), $now),
|
||||
'type' => 'end',
|
||||
);
|
||||
|
||||
|
@ -54,12 +54,12 @@ final class PhrequentTimeBlock extends Phobject {
|
|||
$same_object = ($preempt->getObjectPHID() == $base_phid);
|
||||
$timeline[] = array(
|
||||
'event' => $preempt,
|
||||
'at' => $preempt->getDateStarted(),
|
||||
'at' => (int)$preempt->getDateStarted(),
|
||||
'type' => $same_object ? 'start' : 'push',
|
||||
);
|
||||
$timeline[] = array(
|
||||
'event' => $preempt,
|
||||
'at' => nonempty($preempt->getDateEnded(), $now),
|
||||
'at' => (int)nonempty($preempt->getDateEnded(), $now),
|
||||
'type' => $same_object ? 'end' : 'pop',
|
||||
);
|
||||
}
|
||||
|
@ -185,6 +185,42 @@ final class PhrequentTimeBlock extends Phobject {
|
|||
return $object_ranges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current list of work.
|
||||
*/
|
||||
public function getCurrentWorkStack($now, $include_inactive = false) {
|
||||
$ranges = $this->getObjectTimeRanges($now);
|
||||
|
||||
$results = array();
|
||||
foreach ($ranges as $phid => $blocks) {
|
||||
$total = 0;
|
||||
foreach ($blocks as $block) {
|
||||
$total += $block[1] - $block[0];
|
||||
}
|
||||
|
||||
$type = 'inactive';
|
||||
foreach ($blocks as $block) {
|
||||
if ($block[1] === $now) {
|
||||
if ($block[0] === $block[1]) {
|
||||
$type = 'suspended';
|
||||
} else {
|
||||
$type = 'active';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($include_inactive || $type !== 'inactive') {
|
||||
$results[] = array(
|
||||
'phid' => $phid,
|
||||
'time' => $total,
|
||||
'type' => $type);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge a list of time ranges (pairs of `<start, end>` epochs) so that no
|
||||
|
|
Loading…
Reference in a new issue