@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhrequentTrackController
4 extends PhrequentController {
5
6 private $verb;
7 private $phid;
8
9 public function willProcessRequest(array $data) {
10 $this->phid = $data['phid'];
11 $this->verb = $data['verb'];
12 }
13
14 public function processRequest() {
15 $request = $this->getRequest();
16 $viewer = $request->getUser();
17
18 $phid = $this->phid;
19 $handle = id(new PhabricatorHandleQuery())
20 ->setViewer($viewer)
21 ->withPHIDs(array($phid))
22 ->executeOne();
23 $done_uri = $handle->getURI();
24
25 $current_timer = null;
26 switch ($this->verb) {
27 case 'start':
28 $button_text = pht('Start Tracking');
29 $title_text = pht('Start Tracking Time');
30 $inner_text = pht('What time did you start working?');
31 $action_text = pht('Start Timer');
32 $label_text = pht('Start Time');
33 break;
34 case 'stop':
35 $button_text = pht('Stop Tracking');
36 $title_text = pht('Stop Tracking Time');
37 $inner_text = pht('What time did you stop working?');
38 $action_text = pht('Stop Timer');
39 $label_text = pht('Stop Time');
40
41
42 $current_timer = id(new PhrequentUserTimeQuery())
43 ->setViewer($viewer)
44 ->withUserPHIDs(array($viewer->getPHID()))
45 ->withObjectPHIDs(array($phid))
46 ->withEnded(PhrequentUserTimeQuery::ENDED_NO)
47 ->executeOne();
48 if (!$current_timer) {
49 return $this->newDialog()
50 ->setTitle(pht('Not Tracking Time'))
51 ->appendParagraph(
52 pht('You are not currently tracking time on this object.'))
53 ->addCancelButton($done_uri);
54 }
55 break;
56 default:
57 return new Aphront404Response();
58 }
59
60 $errors = array();
61 $v_note = null;
62 $e_date = null;
63
64 $timestamp = AphrontFormDateControlValue::newFromEpoch(
65 $viewer,
66 time());
67
68 if ($request->isDialogFormPost()) {
69 $v_note = $request->getStr('note');
70 $timestamp = AphrontFormDateControlValue::newFromRequest(
71 $request,
72 'epoch');
73
74 if (!$timestamp->isValid()) {
75 $errors[] = pht('Please choose a valid date.');
76 $e_date = pht('Invalid');
77 } else {
78 $max_time = PhabricatorTime::getNow();
79 if ($timestamp->getEpoch() > $max_time) {
80 if ($this->isStoppingTracking()) {
81 $errors[] = pht(
82 'You can not stop tracking time at a future time. Enter the '.
83 'current time, or a time in the past.');
84 } else {
85 $errors[] = pht(
86 'You can not start tracking time at a future time. Enter the '.
87 'current time, or a time in the past.');
88 }
89 $e_date = pht('Invalid');
90 }
91
92 if ($this->isStoppingTracking()) {
93 $min_time = $current_timer->getDateStarted();
94 if ($min_time > $timestamp->getEpoch()) {
95 $errors[] = pht('Stop time must be after start time.');
96 $e_date = pht('Invalid');
97 }
98 }
99 }
100
101 if (!$errors) {
102 $editor = new PhrequentTrackingEditor();
103 if ($this->isStartingTracking()) {
104 $editor->startTracking(
105 $viewer,
106 $this->phid,
107 $timestamp->getEpoch());
108 } else if ($this->isStoppingTracking()) {
109 $editor->stopTracking(
110 $viewer,
111 $this->phid,
112 $timestamp->getEpoch(),
113 $v_note);
114 }
115
116 return id(new AphrontRedirectResponse())->setURI($done_uri);
117 }
118
119 }
120
121 $dialog = $this->newDialog()
122 ->setTitle($title_text)
123 ->setWidth(AphrontDialogView::WIDTH_FORM)
124 ->setErrors($errors)
125 ->appendParagraph($inner_text);
126
127 $form = new PHUIFormLayoutView();
128
129 if ($this->isStoppingTracking()) {
130 $start_time = $current_timer->getDateStarted();
131 $start_string = pht(
132 '%s (%s ago)',
133 phabricator_datetime($start_time, $viewer),
134 phutil_format_relative_time(PhabricatorTime::getNow() - $start_time));
135
136 $form->appendChild(
137 id(new AphrontFormStaticControl())
138 ->setLabel(pht('Started At'))
139 ->setValue($start_string));
140 }
141
142 $form->appendChild(
143 id(new AphrontFormDateControl())
144 ->setUser($viewer)
145 ->setName('epoch')
146 ->setLabel($action_text)
147 ->setError($e_date)
148 ->setValue($timestamp));
149
150 if ($this->isStoppingTracking()) {
151 $form->appendChild(
152 id(new AphrontFormTextControl())
153 ->setLabel(pht('Note'))
154 ->setName('note')
155 ->setValue($v_note));
156 }
157
158 $dialog->appendChild($form);
159
160 $dialog->addCancelButton($done_uri);
161
162 $dialog->addSubmitButton($action_text);
163
164 return $dialog;
165 }
166
167 private function isStartingTracking() {
168 return $this->verb === 'start';
169 }
170
171 private function isStoppingTracking() {
172 return $this->verb === 'stop';
173 }
174}