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);
 }
 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);
     }
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $phid = $this->phid;
     $handle = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(array($phid))->executeOne();
     $done_uri = $handle->getURI();
     $current_timer = null;
     switch ($this->verb) {
         case 'start':
             $button_text = pht('Start Tracking');
             $title_text = pht('Start Tracking Time');
             $inner_text = pht('What time did you start working?');
             $action_text = pht('Start Timer');
             $label_text = pht('Start Time');
             break;
         case 'stop':
             $button_text = pht('Stop Tracking');
             $title_text = pht('Stop Tracking Time');
             $inner_text = pht('What time did you stop working?');
             $action_text = pht('Stop Timer');
             $label_text = pht('Stop Time');
             $current_timer = id(new PhrequentUserTimeQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->withObjectPHIDs(array($phid))->withEnded(PhrequentUserTimeQuery::ENDED_NO)->executeOne();
             if (!$current_timer) {
                 return $this->newDialog()->setTitle(pht('Not Tracking Time'))->appendParagraph(pht('You are not currently tracking time on this object.'))->addCancelButton($done_uri);
             }
             break;
         default:
             return new Aphront404Response();
     }
     $errors = array();
     $v_note = null;
     $e_date = null;
     $timestamp = AphrontFormDateControlValue::newFromEpoch($viewer, time());
     if ($request->isDialogFormPost()) {
         $v_note = $request->getStr('note');
         $timestamp = AphrontFormDateControlValue::newFromRequest($request, 'epoch');
         if (!$timestamp->isValid()) {
             $errors[] = pht('Please choose a valid date.');
             $e_date = pht('Invalid');
         } else {
             $max_time = PhabricatorTime::getNow();
             if ($timestamp->getEpoch() > $max_time) {
                 if ($this->isStoppingTracking()) {
                     $errors[] = pht('You can not stop tracking time at a future time. Enter the ' . 'current time, or a time in the past.');
                 } else {
                     $errors[] = pht('You can not start tracking time at a future time. Enter the ' . 'current time, or a time in the past.');
                 }
                 $e_date = pht('Invalid');
             }
             if ($this->isStoppingTracking()) {
                 $min_time = $current_timer->getDateStarted();
                 if ($min_time > $timestamp->getEpoch()) {
                     $errors[] = pht('Stop time must be after start time.');
                     $e_date = pht('Invalid');
                 }
             }
         }
         if (!$errors) {
             $editor = new PhrequentTrackingEditor();
             if ($this->isStartingTracking()) {
                 $editor->startTracking($viewer, $this->phid, $timestamp->getEpoch());
             } else {
                 if ($this->isStoppingTracking()) {
                     $editor->stopTracking($viewer, $this->phid, $timestamp->getEpoch(), $v_note);
                 }
             }
             return id(new AphrontRedirectResponse())->setURI($done_uri);
         }
     }
     $dialog = $this->newDialog()->setTitle($title_text)->setWidth(AphrontDialogView::WIDTH_FORM)->setErrors($errors)->appendParagraph($inner_text);
     $form = new PHUIFormLayoutView();
     if ($this->isStoppingTracking()) {
         $start_time = $current_timer->getDateStarted();
         $start_string = pht('%s (%s ago)', phabricator_datetime($start_time, $viewer), phutil_format_relative_time(PhabricatorTime::getNow() - $start_time));
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Started At'))->setValue($start_string));
     }
     $form->appendChild(id(new AphrontFormDateControl())->setUser($viewer)->setName('epoch')->setLabel($action_text)->setError($e_date)->setValue($timestamp));
     if ($this->isStoppingTracking()) {
         $form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Note'))->setName('note')->setValue($v_note));
     }
     $dialog->appendChild($form);
     $dialog->addCancelButton($done_uri);
     $dialog->addSubmitButton($action_text);
     return $dialog;
 }