public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $task = id(new PhabricatorWorkerActiveTask())->load($id);
     if (!$task) {
         $tasks = id(new PhabricatorWorkerArchiveTaskQuery())->withIDs(array($id))->execute();
         $task = reset($tasks);
     }
     $header = new PHUIHeaderView();
     if (!$task) {
         $title = pht('Task Does Not Exist');
         $header->setHeader(pht('Task %d Missing', $id));
         $error_view = new PHUIInfoView();
         $error_view->setTitle(pht('No Such Task'));
         $error_view->appendChild(phutil_tag('p', array(), pht('This task may have recently been garbage collected.')));
         $error_view->setSeverity(PHUIInfoView::SEVERITY_NODATA);
         $content = $error_view;
     } else {
         $title = pht('Task %d', $task->getID());
         $header->setHeader(pht('Task %d: %s', $task->getID(), $task->getTaskClass()));
         $properties = $this->buildPropertyListView($task);
         $object_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->addPropertyList($properties);
         $retry_head = id(new PHUIHeaderView())->setHeader(pht('Retries'));
         $retry_info = $this->buildRetryListView($task);
         $retry_box = id(new PHUIObjectBoxView())->setHeader($retry_head)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->addPropertyList($retry_info);
         $content = array($object_box, $retry_box);
     }
     $header->setHeaderIcon('fa-sort');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     $crumbs->setBorder(true);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter($content);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $task = id(new PhabricatorWorkerActiveTask())->load($this->id);
     if (!$task) {
         $tasks = id(new PhabricatorWorkerArchiveTaskQuery())->withIDs(array($this->id))->execute();
         $task = reset($tasks);
     }
     if (!$task) {
         $title = pht('Task Does Not Exist');
         $error_view = new PHUIInfoView();
         $error_view->setTitle(pht('No Such Task'));
         $error_view->appendChild(phutil_tag('p', array(), pht('This task may have recently been garbage collected.')));
         $error_view->setSeverity(PHUIInfoView::SEVERITY_NODATA);
         $content = $error_view;
     } else {
         $title = pht('Task %d', $task->getID());
         $header = id(new PHUIHeaderView())->setHeader(pht('Task %d (%s)', $task->getID(), $task->getTaskClass()));
         $properties = $this->buildPropertyListView($task);
         $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
         $retry_head = id(new PHUIHeaderView())->setHeader(pht('Retries'));
         $retry_info = $this->buildRetryListView($task);
         $retry_box = id(new PHUIObjectBoxView())->setHeader($retry_head)->addPropertyList($retry_info);
         $content = array($object_box, $retry_box);
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     return $this->buildApplicationPage(array($crumbs, $content), array('title' => $title));
 }
 protected function buildErrorView($error_message)
 {
     $error = new PHUIInfoView();
     $error->setSeverity(PHUIInfoView::SEVERITY_ERROR);
     $error->setTitle($error_message);
     return $error;
 }
 protected function renderErrorPage($title, array $messages)
 {
     $view = new PHUIInfoView();
     $view->setTitle($title);
     $view->setErrors($messages);
     return $this->buildApplicationPage($view, array('title' => $title));
 }
 protected function renderErrorPage($title, array $messages)
 {
     $view = new PHUIInfoView();
     $view->setTitle($title);
     $view->setErrors($messages);
     return $this->newPage()->setTitle($title)->appendChild($view);
 }
 private function processImportRequest($request)
 {
     $admin = $request->getUser();
     $usernames = $request->getArr('usernames');
     $emails = $request->getArr('email');
     $names = $request->getArr('name');
     $notice_view = new PHUIInfoView();
     $notice_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
     $notice_view->setTitle(pht('Import Successful'));
     $notice_view->setErrors(array(pht('Successfully imported users from LDAP')));
     $list = new PHUIObjectItemListView();
     $list->setNoDataString(pht('No users imported?'));
     foreach ($usernames as $username) {
         $user = new PhabricatorUser();
         $user->setUsername($username);
         $user->setRealname($names[$username]);
         $email_obj = id(new PhabricatorUserEmail())->setAddress($emails[$username])->setIsVerified(1);
         try {
             id(new PhabricatorUserEditor())->setActor($admin)->createNewUser($user, $email_obj);
             id(new PhabricatorExternalAccount())->setUserPHID($user->getPHID())->setAccountType('ldap')->setAccountDomain('self')->setAccountID($username)->save();
             $header = pht('Successfully added %s', $username);
             $attribute = null;
             $color = 'fa-check green';
         } catch (Exception $ex) {
             $header = pht('Failed to add %s', $username);
             $attribute = $ex->getMessage();
             $color = 'fa-times red';
         }
         $item = id(new PHUIObjectItemView())->setHeader($header)->addAttribute($attribute)->setStatusIcon($color);
         $list->addItem($item);
     }
     return array($notice_view, $list);
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $xscript = id(new HeraldTranscriptQuery())->setViewer($viewer)->withIDs(array($this->id))->executeOne();
     if (!$xscript) {
         return new Aphront404Response();
     }
     require_celerity_resource('herald-test-css');
     $nav = $this->buildSideNav();
     $object_xscript = $xscript->getObjectTranscript();
     if (!$object_xscript) {
         $notice = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->setTitle(pht('Old Transcript'))->appendChild(phutil_tag('p', array(), pht('Details of this transcript have been garbage collected.')));
         $nav->appendChild($notice);
     } else {
         $map = HeraldAdapter::getEnabledAdapterMap($viewer);
         $object_type = $object_xscript->getType();
         if (empty($map[$object_type])) {
             // TODO: We should filter these out in the Query, but we have to load
             // the objectTranscript right now, which is potentially enormous. We
             // should denormalize the object type, or move the data into a separate
             // table, and then filter this earlier (and thus raise a better error).
             // For now, just block access so we don't violate policies.
             throw new Exception(pht('This transcript has an invalid or inaccessible adapter.'));
         }
         $this->adapter = HeraldAdapter::getAdapterForContentType($object_type);
         $filter = $this->getFilterPHIDs();
         $this->filterTranscript($xscript, $filter);
         $phids = array_merge($filter, $this->getTranscriptPHIDs($xscript));
         $phids = array_unique($phids);
         $phids = array_filter($phids);
         $handles = $this->loadViewerHandles($phids);
         $this->handles = $handles;
         if ($xscript->getDryRun()) {
             $notice = new PHUIInfoView();
             $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
             $notice->setTitle(pht('Dry Run'));
             $notice->appendChild(pht('This was a dry run to test Herald rules, ' . 'no actions were executed.'));
             $nav->appendChild($notice);
         }
         $warning_panel = $this->buildWarningPanel($xscript);
         $nav->appendChild($warning_panel);
         $apply_xscript_panel = $this->buildApplyTranscriptPanel($xscript);
         $nav->appendChild($apply_xscript_panel);
         $action_xscript_panel = $this->buildActionTranscriptPanel($xscript);
         $nav->appendChild($action_xscript_panel);
         $object_xscript_panel = $this->buildObjectTranscriptPanel($xscript);
         $nav->appendChild($object_xscript_panel);
     }
     $crumbs = id($this->buildApplicationCrumbs())->addTextCrumb(pht('Transcripts'), $this->getApplicationURI('/transcript/'))->addTextCrumb($xscript->getID());
     $nav->setCrumbs($crumbs);
     return $this->buildApplicationPage($nav, array('title' => pht('Transcript')));
 }
 public function processRequest()
 {
     try {
         $status = PhabricatorNotificationClient::getServerStatus();
         $status = $this->renderServerStatus($status);
     } catch (Exception $ex) {
         $status = new PHUIInfoView();
         $status->setTitle(pht('Notification Server Issue'));
         $status->appendChild(hsprintf('%s<br /><br />' . '<strong>%s</strong> %s', pht('Unable to determine server status. This probably means the server ' . 'is not in great shape. The specific issue encountered was:'), get_class($ex), phutil_escape_html_newlines($ex->getMessage())));
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Status'));
     return $this->buildApplicationPage(array($crumbs, $status), array('title' => pht('Notification Server Status'), 'device' => false));
 }
 public function render()
 {
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $commit = $drequest->getCommit();
     if ($commit) {
         $commit = $repository->formatCommitName($commit);
     } else {
         $commit = 'HEAD';
     }
     $reason = $this->browseResultSet->getReasonForEmptyResultSet();
     switch ($reason) {
         case DiffusionBrowseResultSet::REASON_IS_NONEXISTENT:
             $title = pht('Path Does Not Exist');
             // TODO: Under git, this error message should be more specific. It
             // may exist on some other branch.
             $body = pht('This path does not exist anywhere.');
             $severity = PHUIInfoView::SEVERITY_ERROR;
             break;
         case DiffusionBrowseResultSet::REASON_IS_EMPTY:
             $title = pht('Empty Directory');
             $body = pht('This path was an empty directory at %s.', $commit);
             $severity = PHUIInfoView::SEVERITY_NOTICE;
             break;
         case DiffusionBrowseResultSet::REASON_IS_DELETED:
             $deleted = $this->browseResultSet->getDeletedAtCommit();
             $existed = $this->browseResultSet->getExistedAtCommit();
             $existed_text = $repository->formatCommitName($existed);
             $existed_href = $drequest->generateURI(array('action' => 'browse', 'path' => $drequest->getPath(), 'commit' => $existed, 'params' => array('view' => $this->view)));
             $existed_link = phutil_tag('a', array('href' => $existed_href), $existed_text);
             $title = pht('Path Was Deleted');
             $body = pht('This path does not exist at %s. It was deleted in %s and last ' . 'existed at %s.', $commit, self::linkCommit($drequest->getRepository(), $deleted), $existed_link);
             $severity = PHUIInfoView::SEVERITY_WARNING;
             break;
         case DiffusionBrowseResultSet::REASON_IS_UNTRACKED_PARENT:
             $subdir = $drequest->getRepository()->getDetail('svn-subpath');
             $title = pht('Directory Not Tracked');
             $body = pht("This repository is configured to track only one subdirectory " . "of the entire repository ('%s'), but you aren't looking at " . "something in that subdirectory, so no information is available.", $subdir);
             $severity = PHUIInfoView::SEVERITY_WARNING;
             break;
         default:
             throw new Exception(pht('Unknown failure reason: %s', $reason));
     }
     $error_view = new PHUIInfoView();
     $error_view->setSeverity($severity);
     $error_view->setTitle($title);
     $error_view->appendChild(phutil_tag('p', array(), $body));
     return $error_view->render();
 }
 public function processRequest(AphrontRequest $request)
 {
     $user = $this->getUser();
     $viewer = $request->getUser();
     id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession($viewer, $request, '/settings/');
     if ($request->isFormPost()) {
         if (!$request->isDialogFormPost()) {
             $dialog = new AphrontDialogView();
             $dialog->setUser($viewer);
             $dialog->setTitle(pht('Really regenerate session?'));
             $dialog->setSubmitURI($this->getPanelURI());
             $dialog->addSubmitButton(pht('Regenerate'));
             $dialog->addCancelbutton($this->getPanelURI());
             $dialog->appendChild(phutil_tag('p', array(), pht('Really destroy the old certificate? Any established ' . 'sessions will be terminated.')));
             return id(new AphrontDialogResponse())->setDialog($dialog);
         }
         $sessions = id(new PhabricatorAuthSessionQuery())->setViewer($user)->withIdentityPHIDs(array($user->getPHID()))->withSessionTypes(array(PhabricatorAuthSession::TYPE_CONDUIT))->execute();
         foreach ($sessions as $session) {
             $session->delete();
         }
         // This implicitly regenerates the certificate.
         $user->setConduitCertificate(null);
         $user->save();
         return id(new AphrontRedirectResponse())->setURI($this->getPanelURI('?regenerated=true'));
     }
     if ($request->getStr('regenerated')) {
         $notice = new PHUIInfoView();
         $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $notice->setTitle(pht('Certificate Regenerated'));
         $notice->appendChild(phutil_tag('p', array(), pht('Your old certificate has been destroyed and you have been issued ' . 'a new certificate. Sessions established under the old certificate ' . 'are no longer valid.')));
         $notice = $notice->render();
     } else {
         $notice = null;
     }
     Javelin::initBehavior('select-on-click');
     $cert_form = new AphrontFormView();
     $cert_form->setUser($viewer)->appendChild(phutil_tag('p', array('class' => 'aphront-form-instructions'), pht('This certificate allows you to authenticate over Conduit, ' . 'the Phabricator API. Normally, you just run %s to install it.', phutil_tag('tt', array(), 'arc install-certificate'))))->appendChild(id(new AphrontFormTextAreaControl())->setLabel(pht('Certificate'))->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)->setReadonly(true)->setSigil('select-on-click')->setValue($user->getConduitCertificate()));
     $cert_form = id(new PHUIObjectBoxView())->setHeaderText(pht('Arcanist Certificate'))->setForm($cert_form);
     $regen_instruction = pht('You can regenerate this certificate, which ' . 'will invalidate the old certificate and create a new one.');
     $regen_form = new AphrontFormView();
     $regen_form->setUser($viewer)->setAction($this->getPanelURI())->setWorkflow(true)->appendChild(phutil_tag('p', array('class' => 'aphront-form-instructions'), $regen_instruction))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Regenerate Certificate')));
     $regen_form = id(new PHUIObjectBoxView())->setHeaderText(pht('Regenerate Certificate'))->setForm($regen_form);
     return array($notice, $cert_form, $regen_form);
 }
Example #11
0
 public function renderExample()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $sevs = array(PHUIInfoView::SEVERITY_ERROR => pht('Error'), PHUIInfoView::SEVERITY_WARNING => pht('Warning'), PHUIInfoView::SEVERITY_NODATA => pht('No Data'), PHUIInfoView::SEVERITY_NOTICE => pht('Notice'), PHUIInfoView::SEVERITY_SUCCESS => pht('Success'));
     $button = id(new PHUIButtonView())->setTag('a')->setText(pht('Resolve Issue'))->setHref('#');
     $views = array();
     // Only Title
     foreach ($sevs as $sev => $title) {
         $view = new PHUIInfoView();
         $view->setSeverity($sev);
         $view->setTitle($title);
         $views[] = $view;
     }
     $views[] = phutil_tag('br', array(), null);
     // Only Body
     foreach ($sevs as $sev => $title) {
         $view = new PHUIInfoView();
         $view->setSeverity($sev);
         $view->appendChild(pht('Several issues were encountered.'));
         $view->addButton($button);
         $views[] = $view;
     }
     $views[] = phutil_tag('br', array(), null);
     // Only Errors
     foreach ($sevs as $sev => $title) {
         $view = new PHUIInfoView();
         $view->setSeverity($sev);
         $view->setErrors(array(pht('Overcooked.'), pht('Too much salt.'), pht('Full of sand.')));
         $views[] = $view;
     }
     $views[] = phutil_tag('br', array(), null);
     // All
     foreach ($sevs as $sev => $title) {
         $view = new PHUIInfoView();
         $view->setSeverity($sev);
         $view->setTitle($title);
         $view->appendChild(pht('Several issues were encountered.'));
         $view->setErrors(array(pht('Overcooked.'), pht('Too much salt.'), pht('Full of sand.')));
         $views[] = $view;
     }
     return $views;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $email = $viewer->loadPrimaryEmail();
     if ($viewer->getIsEmailVerified()) {
         return id(new AphrontRedirectResponse())->setURI('/');
     }
     $email_address = $email->getAddress();
     $sent = null;
     if ($request->isFormPost()) {
         $email->sendVerificationEmail($viewer);
         $sent = new PHUIInfoView();
         $sent->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $sent->setTitle(pht('Email Sent'));
         $sent->appendChild(pht('Another verification email was sent to %s.', phutil_tag('strong', array(), $email_address)));
     }
     $must_verify = pht('You must verify your email address to login. You should have a ' . 'new email message from Phabricator with verification instructions ' . 'in your inbox (%s).', phutil_tag('strong', array(), $email_address));
     $send_again = pht('If you did not receive an email, you can click the button below ' . 'to try sending another one.');
     $dialog = id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Check Your Email'))->appendParagraph($must_verify)->appendParagraph($send_again)->addSubmitButton(pht('Send Another Email'));
     return $this->buildApplicationPage(array($sent, $dialog), array('title' => pht('Must Verify Email')));
 }
 private function renderMiniPanel($title, $body)
 {
     $panel = new PHUIInfoView();
     $panel->setSeverity(PHUIInfoView::SEVERITY_NODATA);
     $panel->appendChild(phutil_tag('p', array(), array(phutil_tag('strong', array(), $title . ': '), $body)));
     $this->minipanels[] = $panel;
 }
 public function handleRequest(AphrontRequest $request)
 {
     if (!PhabricatorPasswordAuthProvider::getPasswordProvider()) {
         return new Aphront400Response();
     }
     $e_email = true;
     $e_captcha = true;
     $errors = array();
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     if ($request->isFormPost()) {
         $e_email = null;
         $e_captcha = pht('Again');
         $captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request);
         if (!$captcha_ok) {
             $errors[] = pht('Captcha response is incorrect, try again.');
             $e_captcha = pht('Invalid');
         }
         $email = $request->getStr('email');
         if (!strlen($email)) {
             $errors[] = pht('You must provide an email address.');
             $e_email = pht('Required');
         }
         if (!$errors) {
             // NOTE: Don't validate the email unless the captcha is good; this makes
             // it expensive to fish for valid email addresses while giving the user
             // a better error if they goof their email.
             $target_email = id(new PhabricatorUserEmail())->loadOneWhere('address = %s', $email);
             $target_user = null;
             if ($target_email) {
                 $target_user = id(new PhabricatorUser())->loadOneWhere('phid = %s', $target_email->getUserPHID());
             }
             if (!$target_user) {
                 $errors[] = pht('There is no account associated with that email address.');
                 $e_email = pht('Invalid');
             }
             // If this address is unverified, only send a reset link to it if
             // the account has no verified addresses. This prevents an opportunistic
             // attacker from compromising an account if a user adds an email
             // address but mistypes it and doesn't notice.
             // (For a newly created account, all the addresses may be unverified,
             // which is why we'll send to an unverified address in that case.)
             if ($target_email && !$target_email->getIsVerified()) {
                 $verified_addresses = id(new PhabricatorUserEmail())->loadAllWhere('userPHID = %s AND isVerified = 1', $target_email->getUserPHID());
                 if ($verified_addresses) {
                     $errors[] = pht('That email address is not verified. You can only send ' . 'password reset links to a verified address.');
                     $e_email = pht('Unverified');
                 }
             }
             if (!$errors) {
                 $engine = new PhabricatorAuthSessionEngine();
                 $uri = $engine->getOneTimeLoginURI($target_user, null, PhabricatorAuthSessionEngine::ONETIME_RESET);
                 if ($is_serious) {
                     $body = pht("You can use this link to reset your Phabricator password:"******"\n\n  %s\n", $uri);
                 } else {
                     $body = pht("Condolences on forgetting your password. You can use this " . "link to reset it:\n\n" . "  %s\n\n" . "After you set a new password, consider writing it down on a " . "sticky note and attaching it to your monitor so you don't " . "forget again! Choosing a very short, easy-to-remember password " . "like \"cat\" or \"1234\" might also help.\n\n" . "Best Wishes,\nPhabricator\n", $uri);
                 }
                 $mail = id(new PhabricatorMetaMTAMail())->setSubject(pht('[Phabricator] Password Reset'))->setForceDelivery(true)->addRawTos(array($target_email->getAddress()))->setBody($body)->saveAndSend();
                 return $this->newDialog()->setTitle(pht('Check Your Email'))->setShortTitle(pht('Email Sent'))->appendParagraph(pht('An email has been sent with a link you can use to login.'))->addCancelButton('/', pht('Done'));
             }
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new PHUIInfoView();
         $error_view->setErrors($errors);
     }
     $email_auth = new PHUIFormLayoutView();
     $email_auth->appendChild($error_view);
     $email_auth->setUser($request->getUser())->setFullWidth(true)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Email'))->setName('email')->setValue($request->getStr('email'))->setError($e_email))->appendChild(id(new AphrontFormRecaptchaControl())->setLabel(pht('Captcha'))->setError($e_captcha));
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Reset Password'));
     $dialog = new AphrontDialogView();
     $dialog->setUser($request->getUser());
     $dialog->setTitle(pht('Forgot Password / Email Login'));
     $dialog->appendChild($email_auth);
     $dialog->addSubmitButton(pht('Send Email'));
     $dialog->setSubmitURI('/login/email/');
     return $this->buildApplicationPage(array($crumbs, $dialog), array('title' => pht('Forgot Password')));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $response_type = $request->getStr('responseType', 'task');
     $order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER);
     $can_edit_assign = $this->hasApplicationCapability(ManiphestEditAssignCapability::CAPABILITY);
     $can_edit_policies = $this->hasApplicationCapability(ManiphestEditPoliciesCapability::CAPABILITY);
     $can_edit_priority = $this->hasApplicationCapability(ManiphestEditPriorityCapability::CAPABILITY);
     $can_edit_projects = $this->hasApplicationCapability(ManiphestEditProjectsCapability::CAPABILITY);
     $can_edit_status = $this->hasApplicationCapability(ManiphestEditStatusCapability::CAPABILITY);
     $can_create_projects = PhabricatorPolicyFilter::hasCapability($viewer, PhabricatorApplication::getByClass('PhabricatorProjectApplication'), ProjectCreateProjectsCapability::CAPABILITY);
     $parent_task = null;
     $template_id = null;
     if ($id) {
         $task = id(new ManiphestTaskQuery())->setViewer($viewer)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->withIDs(array($id))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->executeOne();
         if (!$task) {
             return new Aphront404Response();
         }
     } else {
         $task = ManiphestTask::initializeNewTask($viewer);
         // We currently do not allow you to set the task status when creating
         // a new task, although now that statuses are custom it might make
         // sense.
         $can_edit_status = false;
         // These allow task creation with defaults.
         if (!$request->isFormPost()) {
             $task->setTitle($request->getStr('title'));
             if ($can_edit_projects) {
                 $projects = $request->getStr('projects');
                 if ($projects) {
                     $tokens = $request->getStrList('projects');
                     $type_project = PhabricatorProjectProjectPHIDType::TYPECONST;
                     foreach ($tokens as $key => $token) {
                         if (phid_get_type($token) == $type_project) {
                             // If this is formatted like a PHID, leave it as-is.
                             continue;
                         }
                         if (preg_match('/^#/', $token)) {
                             // If this already has a "#", leave it as-is.
                             continue;
                         }
                         // Add a "#" prefix.
                         $tokens[$key] = '#' . $token;
                     }
                     $default_projects = id(new PhabricatorObjectQuery())->setViewer($viewer)->withNames($tokens)->execute();
                     $default_projects = mpull($default_projects, 'getPHID');
                     if ($default_projects) {
                         $task->attachProjectPHIDs($default_projects);
                     }
                 }
             }
             if ($can_edit_priority) {
                 $priority = $request->getInt('priority');
                 if ($priority !== null) {
                     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
                     if (isset($priority_map[$priority])) {
                         $task->setPriority($priority);
                     }
                 }
             }
             $task->setDescription($request->getStr('description'));
             if ($can_edit_assign) {
                 $assign = $request->getStr('assign');
                 if (strlen($assign)) {
                     $assign_user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withUsernames(array($assign))->executeOne();
                     if (!$assign_user) {
                         $assign_user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withPHIDs(array($assign))->executeOne();
                     }
                     if ($assign_user) {
                         $task->setOwnerPHID($assign_user->getPHID());
                     }
                 }
             }
         }
         $template_id = $request->getInt('template');
         // You can only have a parent task if you're creating a new task.
         $parent_id = $request->getInt('parent');
         if (strlen($parent_id)) {
             $parent_task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($parent_id))->executeOne();
             if (!$parent_task) {
                 return new Aphront404Response();
             }
             if (!$template_id) {
                 $template_id = $parent_id;
             }
         }
     }
     $errors = array();
     $e_title = true;
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_EDIT);
     $field_list->setViewer($viewer);
     $field_list->readFieldsFromStorage($task);
     $aux_fields = $field_list->getFields();
     $v_space = $task->getSpacePHID();
     if ($request->isFormPost()) {
         $changes = array();
         $new_title = $request->getStr('title');
         $new_desc = $request->getStr('description');
         $new_status = $request->getStr('status');
         $v_space = $request->getStr('spacePHID');
         if (!$task->getID()) {
             $workflow = 'create';
         } else {
             $workflow = '';
         }
         $changes[ManiphestTransaction::TYPE_TITLE] = $new_title;
         $changes[ManiphestTransaction::TYPE_DESCRIPTION] = $new_desc;
         if ($can_edit_status) {
             $changes[ManiphestTransaction::TYPE_STATUS] = $new_status;
         } else {
             if (!$task->getID()) {
                 // Create an initial status transaction for the burndown chart.
                 // TODO: We can probably remove this once Facts comes online.
                 $changes[ManiphestTransaction::TYPE_STATUS] = $task->getStatus();
             }
         }
         $owner_tokenizer = $request->getArr('assigned_to');
         $owner_phid = reset($owner_tokenizer);
         if (!strlen($new_title)) {
             $e_title = pht('Required');
             $errors[] = pht('Title is required.');
         }
         $old_values = array();
         foreach ($aux_fields as $aux_arr_key => $aux_field) {
             // TODO: This should be buildFieldTransactionsFromRequest() once we
             // switch to ApplicationTransactions properly.
             $aux_old_value = $aux_field->getOldValueForApplicationTransactions();
             $aux_field->readValueFromRequest($request);
             $aux_new_value = $aux_field->getNewValueForApplicationTransactions();
             // TODO: We're faking a call to the ApplicaitonTransaction validation
             // logic here. We need valid objects to pass, but they aren't used
             // in a meaningful way. For now, build User objects. Once the Maniphest
             // objects exist, this will switch over automatically. This is a big
             // hack but shouldn't be long for this world.
             $placeholder_editor = id(new PhabricatorUserProfileEditor())->setActor($viewer);
             $field_errors = $aux_field->validateApplicationTransactions($placeholder_editor, PhabricatorTransactions::TYPE_CUSTOMFIELD, array(id(new ManiphestTransaction())->setOldValue($aux_old_value)->setNewValue($aux_new_value)));
             foreach ($field_errors as $error) {
                 $errors[] = $error->getMessage();
             }
             $old_values[$aux_field->getFieldKey()] = $aux_old_value;
         }
         if ($errors) {
             $task->setTitle($new_title);
             $task->setDescription($new_desc);
             $task->setPriority($request->getInt('priority'));
             $task->setOwnerPHID($owner_phid);
             $task->attachSubscriberPHIDs($request->getArr('cc'));
             $task->attachProjectPHIDs($request->getArr('projects'));
         } else {
             if ($can_edit_priority) {
                 $changes[ManiphestTransaction::TYPE_PRIORITY] = $request->getInt('priority');
             }
             if ($can_edit_assign) {
                 $changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
             }
             $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] = array('=' => $request->getArr('cc'));
             if ($can_edit_projects) {
                 $projects = $request->getArr('projects');
                 $changes[PhabricatorTransactions::TYPE_EDGE] = $projects;
                 $column_phid = $request->getStr('columnPHID');
                 // allow for putting a task in a project column at creation -only-
                 if (!$task->getID() && $column_phid && $projects) {
                     $column = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs($projects)->withPHIDs(array($column_phid))->executeOne();
                     if ($column) {
                         $changes[ManiphestTransaction::TYPE_PROJECT_COLUMN] = array('new' => array('projectPHID' => $column->getProjectPHID(), 'columnPHIDs' => array($column_phid)), 'old' => array('projectPHID' => $column->getProjectPHID(), 'columnPHIDs' => array()));
                     }
                 }
             }
             if ($can_edit_policies) {
                 $changes[PhabricatorTransactions::TYPE_SPACE] = $v_space;
                 $changes[PhabricatorTransactions::TYPE_VIEW_POLICY] = $request->getStr('viewPolicy');
                 $changes[PhabricatorTransactions::TYPE_EDIT_POLICY] = $request->getStr('editPolicy');
             }
             $template = new ManiphestTransaction();
             $transactions = array();
             foreach ($changes as $type => $value) {
                 $transaction = clone $template;
                 $transaction->setTransactionType($type);
                 if ($type == ManiphestTransaction::TYPE_PROJECT_COLUMN) {
                     $transaction->setNewValue($value['new']);
                     $transaction->setOldValue($value['old']);
                 } else {
                     if ($type == PhabricatorTransactions::TYPE_EDGE) {
                         $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
                         $transaction->setMetadataValue('edge:type', $project_type)->setNewValue(array('=' => array_fuse($value)));
                     } else {
                         $transaction->setNewValue($value);
                     }
                 }
                 $transactions[] = $transaction;
             }
             if ($aux_fields) {
                 foreach ($aux_fields as $aux_field) {
                     $transaction = clone $template;
                     $transaction->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD);
                     $aux_key = $aux_field->getFieldKey();
                     $transaction->setMetadataValue('customfield:key', $aux_key);
                     $old = idx($old_values, $aux_key);
                     $new = $aux_field->getNewValueForApplicationTransactions();
                     $transaction->setOldValue($old);
                     $transaction->setNewValue($new);
                     $transactions[] = $transaction;
                 }
             }
             if ($transactions) {
                 $is_new = !$task->getID();
                 $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
                 $event->setUser($viewer);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
                 $task = $event->getValue('task');
                 $transactions = $event->getValue('transactions');
                 $editor = id(new ManiphestTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->applyTransactions($task, $transactions);
                 $event = new PhabricatorEvent(PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK, array('task' => $task, 'new' => $is_new, 'transactions' => $transactions));
                 $event->setUser($viewer);
                 $event->setAphrontRequest($request);
                 PhutilEventEngine::dispatchEvent($event);
             }
             if ($parent_task) {
                 // TODO: This should be transactional now.
                 id(new PhabricatorEdgeEditor())->addEdge($parent_task->getPHID(), ManiphestTaskDependsOnTaskEdgeType::EDGECONST, $task->getPHID())->save();
                 $workflow = $parent_task->getID();
             }
             if ($request->isAjax()) {
                 switch ($response_type) {
                     case 'card':
                         $owner = null;
                         if ($task->getOwnerPHID()) {
                             $owner = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(array($task->getOwnerPHID()))->executeOne();
                         }
                         $project = $this->getSprintProjectforTask($viewer, $projects);
                         $tasks = id(new SprintBoardTaskCard())->setViewer($viewer)->setProject($project)->setTask($task)->setOwner($owner)->setCanEdit(true)->getItem();
                         $column = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withPHIDs(array($request->getStr('columnPHID')))->executeOne();
                         if (!$column) {
                             return new Aphront404Response();
                         }
                         // re-load projects for accuracy as they are not re-loaded via
                         // the editor
                         $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs($task->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
                         $task->attachProjectPHIDs($project_phids);
                         $remove_from_board = false;
                         if (!in_array($column->getProjectPHID(), $project_phids)) {
                             $remove_from_board = true;
                         }
                         $positions = id(new PhabricatorProjectColumnPositionQuery())->setViewer($viewer)->withColumns(array($column))->execute();
                         $task_phids = mpull($positions, 'getObjectPHID');
                         $column_tasks = id(new ManiphestTaskQuery())->setViewer($viewer)->withPHIDs($task_phids)->execute();
                         if ($order == PhabricatorProjectColumn::ORDER_NATURAL) {
                             // TODO: This is a little bit awkward, because PHP and JS use
                             // slightly different sort order parameters to achieve the same
                             // effect. It would be good to unify this a bit at some point.
                             $sort_map = array();
                             foreach ($positions as $position) {
                                 $sort_map[$position->getObjectPHID()] = array(-$position->getSequence(), $position->getID());
                             }
                         } else {
                             $sort_map = mpull($column_tasks, 'getPrioritySortVector', 'getPHID');
                         }
                         $data = array('sortMap' => $sort_map, 'removeFromBoard' => $remove_from_board);
                         break;
                     case 'task':
                     default:
                         $tasks = $this->renderSingleTask($task);
                         $data = array();
                         break;
                 }
                 return id(new AphrontAjaxResponse())->setContent(array('tasks' => $tasks, 'data' => $data));
             }
             $redirect_uri = '/T' . $task->getID();
             if ($workflow) {
                 $redirect_uri .= '?workflow=' . $workflow;
             }
             return id(new AphrontRedirectResponse())->setURI($redirect_uri);
         }
     } else {
         if (!$task->getID()) {
             $task->attachSubscriberPHIDs(array($viewer->getPHID()));
             if ($template_id) {
                 $template_task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($template_id))->needSubscriberPHIDs(true)->needProjectPHIDs(true)->executeOne();
                 if ($template_task) {
                     $cc_phids = array_unique(array_merge($template_task->getSubscriberPHIDs(), array($viewer->getPHID())));
                     $task->attachSubscriberPHIDs($cc_phids);
                     $task->attachProjectPHIDs($template_task->getProjectPHIDs());
                     $task->setOwnerPHID($template_task->getOwnerPHID());
                     $task->setPriority($template_task->getPriority());
                     $task->setViewPolicy($template_task->getViewPolicy());
                     $task->setEditPolicy($template_task->getEditPolicy());
                     $v_space = $template_task->getSpacePHID();
                     $template_fields = PhabricatorCustomField::getObjectFields($template_task, PhabricatorCustomField::ROLE_EDIT);
                     $fields = $template_fields->getFields();
                     foreach ($fields as $key => $field) {
                         if (!$field->shouldCopyWhenCreatingSimilarTask()) {
                             unset($fields[$key]);
                         }
                         if (empty($aux_fields[$key])) {
                             unset($fields[$key]);
                         }
                     }
                     if ($fields) {
                         id(new PhabricatorCustomFieldList($fields))->setViewer($viewer)->readFieldsFromStorage($template_task);
                         foreach ($fields as $key => $field) {
                             $aux_fields[$key]->setValueFromStorage($field->getValueForStorage());
                         }
                     }
                 }
             }
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new PHUIInfoView();
         $error_view->setErrors($errors);
     }
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     if ($task->getOwnerPHID()) {
         $assigned_value = array($task->getOwnerPHID());
     } else {
         $assigned_value = array();
     }
     if ($task->getSubscriberPHIDs()) {
         $cc_value = $task->getSubscriberPHIDs();
     } else {
         $cc_value = array();
     }
     if ($task->getProjectPHIDs()) {
         $projects_value = $task->getProjectPHIDs();
     } else {
         $projects_value = array();
     }
     $cancel_id = nonempty($task->getID(), $template_id);
     if ($cancel_id) {
         $cancel_uri = '/T' . $cancel_id;
     } else {
         $cancel_uri = '/maniphest/';
     }
     if ($task->getID()) {
         $button_name = pht('Save Task');
         $header_name = pht('Edit Task');
     } else {
         if ($parent_task) {
             $cancel_uri = '/T' . $parent_task->getID();
             $button_name = pht('Create Task');
             $header_name = pht('Create New Subtask');
         } else {
             $button_name = pht('Create Task');
             $header_name = pht('Create New Task');
         }
     }
     require_celerity_resource('maniphest-task-edit-css');
     $project_tokenizer_id = celerity_generate_unique_node_id();
     $form = new AphrontFormView();
     $form->setUser($viewer)->addHiddenInput('template', $template_id)->addHiddenInput('responseType', $response_type)->addHiddenInput('order', $order)->addHiddenInput('ungrippable', $request->getStr('ungrippable'))->addHiddenInput('columnPHID', $request->getStr('columnPHID'));
     if ($parent_task) {
         $form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Parent Task'))->setValue($viewer->renderHandle($parent_task->getPHID())))->addHiddenInput('parent', $parent_task->getID());
     }
     $form->appendChild(id(new AphrontFormTextAreaControl())->setLabel(pht('Title'))->setName('title')->setError($e_title)->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)->setValue($task->getTitle()));
     if ($can_edit_status) {
         // See T4819.
         $status_map = ManiphestTaskStatus::getTaskStatusMap();
         $dup_status = ManiphestTaskStatus::getDuplicateStatus();
         if ($task->getStatus() != $dup_status) {
             unset($status_map[$dup_status]);
         }
         $form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Status'))->setName('status')->setValue($task->getStatus())->setOptions($status_map));
     }
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($task)->execute();
     if ($can_edit_assign) {
         $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Assigned To'))->setName('assigned_to')->setValue($assigned_value)->setUser($viewer)->setDatasource(new PhabricatorPeopleDatasource())->setLimit(1));
     }
     $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('CC'))->setName('cc')->setValue($cc_value)->setUser($viewer)->setDatasource(new PhabricatorMetaMTAMailableDatasource()));
     if ($can_edit_priority) {
         $form->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Priority'))->setName('priority')->setOptions($priority_map)->setValue($task->getPriority()));
     }
     if ($can_edit_policies) {
         $form->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_VIEW)->setPolicyObject($task)->setPolicies($policies)->setSpacePHID($v_space)->setName('viewPolicy'))->appendChild(id(new AphrontFormPolicyControl())->setUser($viewer)->setCapability(PhabricatorPolicyCapability::CAN_EDIT)->setPolicyObject($task)->setPolicies($policies)->setName('editPolicy'));
     }
     if ($can_edit_projects) {
         $caption = null;
         if ($can_create_projects) {
             $caption = javelin_tag('a', array('href' => '/project/create/', 'mustcapture' => true, 'sigil' => 'project-create'), pht('Create New Project'));
         }
         $form->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setValue($projects_value)->setID($project_tokenizer_id)->setCaption($caption)->setDatasource(new PhabricatorProjectDatasource()));
     }
     $field_list->appendFieldsToForm($form);
     require_celerity_resource('phui-info-view-css');
     Javelin::initBehavior('project-create', array('tokenizerID' => $project_tokenizer_id));
     $description_control = id(new PhabricatorRemarkupControl())->setLabel(pht('Description'))->setName('description')->setID('description-textarea')->setValue($task->getDescription())->setUser($viewer);
     $form->appendChild($description_control);
     if ($request->isAjax()) {
         $dialog = id(new AphrontDialogView())->setUser($viewer)->setWidth(AphrontDialogView::WIDTH_FULL)->setTitle($header_name)->appendChild(array($error_view, $form->buildLayoutView()))->addCancelButton($cancel_uri)->addSubmitButton($button_name);
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     $form->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($button_name));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText($header_name)->setFormErrors($errors)->setForm($form);
     $preview = id(new PHUIRemarkupPreviewPanel())->setHeader(pht('Description Preview'))->setControlID('description-textarea')->setPreviewURI($this->getApplicationURI('task/descriptionpreview/'));
     if ($task->getID()) {
         $page_objects = array($task->getPHID());
     } else {
         $page_objects = array();
     }
     $crumbs = $this->buildApplicationCrumbs();
     if ($task->getID()) {
         $crumbs->addTextCrumb('T' . $task->getID(), '/T' . $task->getID());
     }
     $crumbs->addTextCrumb($header_name);
     $title = $header_name;
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->setPageObjectPHIDs($page_objects)->appendChild(array($form_box, $preview));
 }
 private function buildMergesTable(PhabricatorRepositoryCommit $commit)
 {
     $viewer = $this->getViewer();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $merges = $this->getCommitMerges();
     if (!$merges) {
         return null;
     }
     $limit = $this->getMergeDisplayLimit();
     $caption = null;
     if (count($merges) > $limit) {
         $merges = array_slice($merges, 0, $limit);
         $caption = new PHUIInfoView();
         $caption->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $caption->appendChild(pht('This commit merges a very large number of changes. ' . 'Only the first %s are shown.', new PhutilNumber($limit)));
     }
     $history_table = id(new DiffusionHistoryTableView())->setUser($viewer)->setDiffusionRequest($drequest)->setHistory($merges);
     $history_table->loadRevisions();
     $panel = new PHUIObjectBoxView();
     $panel->setHeaderText(pht('Merged Changes'));
     $panel->setTable($history_table);
     if ($caption) {
         $panel->setInfoView($caption);
     }
     return $panel;
 }
 private function browseFile()
 {
     $viewer = $this->getViewer();
     $request = $this->getRequest();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $before = $request->getStr('before');
     if ($before) {
         return $this->buildBeforeResponse($before);
     }
     $path = $drequest->getPath();
     $preferences = $viewer->loadPreferences();
     $show_blame = $request->getBool('blame', $preferences->getPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_BLAME, false));
     $show_color = $request->getBool('color', $preferences->getPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_COLOR, true));
     $view = $request->getStr('view');
     if ($request->isFormPost() && $view != 'raw' && $viewer->isLoggedIn()) {
         $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_BLAME, $show_blame);
         $preferences->setPreference(PhabricatorUserPreferences::PREFERENCE_DIFFUSION_COLOR, $show_color);
         $preferences->save();
         $uri = $request->getRequestURI()->alter('blame', null)->alter('color', null);
         return id(new AphrontRedirectResponse())->setURI($uri);
     }
     // We need the blame information if blame is on and we're building plain
     // text, or blame is on and this is an Ajax request. If blame is on and
     // this is a colorized request, we don't show blame at first (we ajax it
     // in afterward) so we don't need to query for it.
     $needs_blame = $show_blame && !$show_color || $show_blame && $request->isAjax();
     $params = array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath());
     $byte_limit = null;
     if ($view !== 'raw') {
         $byte_limit = PhabricatorFileStorageEngine::getChunkThreshold();
         $time_limit = 10;
         $params += array('timeout' => $time_limit, 'byteLimit' => $byte_limit);
     }
     $response = $this->callConduitWithDiffusionRequest('diffusion.filecontentquery', $params);
     $hit_byte_limit = $response['tooHuge'];
     $hit_time_limit = $response['tooSlow'];
     $file_phid = $response['filePHID'];
     if ($hit_byte_limit) {
         $corpus = $this->buildErrorCorpus(pht('This file is larger than %s byte(s), and too large to display ' . 'in the web UI.', phutil_format_bytes($byte_limit)));
     } else {
         if ($hit_time_limit) {
             $corpus = $this->buildErrorCorpus(pht('This file took too long to load from the repository (more than ' . '%s second(s)).', new PhutilNumber($time_limit)));
         } else {
             $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($file_phid))->executeOne();
             if (!$file) {
                 throw new Exception(pht('Failed to load content file!'));
             }
             if ($view === 'raw') {
                 return $file->getRedirectResponse();
             }
             $data = $file->loadFileData();
             if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) {
                 $file_uri = $file->getBestURI();
                 if ($file->isViewableImage()) {
                     $corpus = $this->buildImageCorpus($file_uri);
                 } else {
                     $corpus = $this->buildBinaryCorpus($file_uri, $data);
                 }
             } else {
                 $this->loadLintMessages();
                 $this->coverage = $drequest->loadCoverage();
                 // Build the content of the file.
                 $corpus = $this->buildCorpus($show_blame, $show_color, $data, $needs_blame, $drequest, $path, $data);
             }
         }
     }
     if ($request->isAjax()) {
         return id(new AphrontAjaxResponse())->setContent($corpus);
     }
     require_celerity_resource('diffusion-source-css');
     // Render the page.
     $view = $this->buildActionView($drequest);
     $action_list = $this->enrichActionView($view, $drequest, $show_blame, $show_color);
     $properties = $this->buildPropertyView($drequest, $action_list);
     $object_box = id(new PHUIObjectBoxView())->setHeader($this->buildHeaderView($drequest))->addPropertyList($properties);
     $content = array();
     $content[] = $object_box;
     $follow = $request->getStr('follow');
     if ($follow) {
         $notice = new PHUIInfoView();
         $notice->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $notice->setTitle(pht('Unable to Continue'));
         switch ($follow) {
             case 'first':
                 $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit is the first commit in the repository.'));
                 break;
             case 'created':
                 $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit created the file.'));
                 break;
         }
         $content[] = $notice;
     }
     $renamed = $request->getStr('renamed');
     if ($renamed) {
         $notice = new PHUIInfoView();
         $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $notice->setTitle(pht('File Renamed'));
         $notice->appendChild(pht('File history passes through a rename from "%s" to "%s".', $drequest->getPath(), $renamed));
         $content[] = $notice;
     }
     $content[] = $corpus;
     $content[] = $this->buildOpenRevisions();
     $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'browse'));
     $basename = basename($this->getDiffusionRequest()->getPath());
     return $this->newPage()->setTitle(array($basename, $repository->getDisplayName()))->setCrumbs($crumbs)->appendChild($content);
 }
 private function browseFile()
 {
     $viewer = $this->getViewer();
     $request = $this->getRequest();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $before = $request->getStr('before');
     if ($before) {
         return $this->buildBeforeResponse($before);
     }
     $path = $drequest->getPath();
     $blame_key = PhabricatorDiffusionBlameSetting::SETTINGKEY;
     $color_key = PhabricatorDiffusionColorSetting::SETTINGKEY;
     $show_blame = $request->getBool('blame', $viewer->getUserSetting($blame_key));
     $show_color = $request->getBool('color', $viewer->getUserSetting($color_key));
     $view = $request->getStr('view');
     if ($request->isFormPost() && $view != 'raw' && $viewer->isLoggedIn()) {
         $preferences = PhabricatorUserPreferences::loadUserPreferences($viewer);
         $editor = id(new PhabricatorUserPreferencesEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true);
         $xactions = array();
         $xactions[] = $preferences->newTransaction($blame_key, $show_blame);
         $xactions[] = $preferences->newTransaction($color_key, $show_color);
         $editor->applyTransactions($preferences, $xactions);
         $uri = $request->getRequestURI()->alter('blame', null)->alter('color', null);
         return id(new AphrontRedirectResponse())->setURI($uri);
     }
     // We need the blame information if blame is on and we're building plain
     // text, or blame is on and this is an Ajax request. If blame is on and
     // this is a colorized request, we don't show blame at first (we ajax it
     // in afterward) so we don't need to query for it.
     $needs_blame = $show_blame && !$show_color || $show_blame && $request->isAjax();
     $params = array('commit' => $drequest->getCommit(), 'path' => $drequest->getPath());
     $byte_limit = null;
     if ($view !== 'raw') {
         $byte_limit = PhabricatorFileStorageEngine::getChunkThreshold();
         $time_limit = 10;
         $params += array('timeout' => $time_limit, 'byteLimit' => $byte_limit);
     }
     $response = $this->callConduitWithDiffusionRequest('diffusion.filecontentquery', $params);
     $hit_byte_limit = $response['tooHuge'];
     $hit_time_limit = $response['tooSlow'];
     $file_phid = $response['filePHID'];
     if ($hit_byte_limit) {
         $corpus = $this->buildErrorCorpus(pht('This file is larger than %s byte(s), and too large to display ' . 'in the web UI.', phutil_format_bytes($byte_limit)));
     } else {
         if ($hit_time_limit) {
             $corpus = $this->buildErrorCorpus(pht('This file took too long to load from the repository (more than ' . '%s second(s)).', new PhutilNumber($time_limit)));
         } else {
             $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($file_phid))->executeOne();
             if (!$file) {
                 throw new Exception(pht('Failed to load content file!'));
             }
             if ($view === 'raw') {
                 return $file->getRedirectResponse();
             }
             $data = $file->loadFileData();
             $ref = $this->getGitLFSRef($repository, $data);
             if ($ref) {
                 if ($view == 'git-lfs') {
                     $file = $this->loadGitLFSFile($ref);
                     // Rename the file locally so we generate a better vanity URI for
                     // it. In storage, it just has a name like "lfs-13f9a94c0923...",
                     // since we don't get any hints about possible human-readable names
                     // at upload time.
                     $basename = basename($drequest->getPath());
                     $file->makeEphemeral();
                     $file->setName($basename);
                     return $file->getRedirectResponse();
                 } else {
                     $corpus = $this->buildGitLFSCorpus($ref);
                 }
             } else {
                 if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) {
                     $file_uri = $file->getBestURI();
                     if ($file->isViewableImage()) {
                         $corpus = $this->buildImageCorpus($file_uri);
                     } else {
                         $corpus = $this->buildBinaryCorpus($file_uri, $data);
                     }
                 } else {
                     $this->loadLintMessages();
                     $this->coverage = $drequest->loadCoverage();
                     // Build the content of the file.
                     $corpus = $this->buildCorpus($show_blame, $show_color, $data, $needs_blame, $drequest, $path, $data);
                 }
             }
         }
     }
     if ($request->isAjax()) {
         return id(new AphrontAjaxResponse())->setContent($corpus);
     }
     require_celerity_resource('diffusion-source-css');
     // Render the page.
     $view = $this->buildCurtain($drequest);
     $curtain = $this->enrichCurtain($view, $drequest, $show_blame, $show_color);
     $properties = $this->buildPropertyView($drequest);
     $header = $this->buildHeaderView($drequest);
     $header->setHeaderIcon('fa-file-code-o');
     $content = array();
     $follow = $request->getStr('follow');
     if ($follow) {
         $notice = new PHUIInfoView();
         $notice->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $notice->setTitle(pht('Unable to Continue'));
         switch ($follow) {
             case 'first':
                 $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit is the first commit in the repository.'));
                 break;
             case 'created':
                 $notice->appendChild(pht('Unable to continue tracing the history of this file because ' . 'this commit created the file.'));
                 break;
         }
         $content[] = $notice;
     }
     $renamed = $request->getStr('renamed');
     if ($renamed) {
         $notice = new PHUIInfoView();
         $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $notice->setTitle(pht('File Renamed'));
         $notice->appendChild(pht('File history passes through a rename from "%s" to "%s".', $drequest->getPath(), $renamed));
         $content[] = $notice;
     }
     $content[] = $corpus;
     $content[] = $this->buildOpenRevisions();
     $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'browse'));
     $crumbs->setBorder(true);
     $basename = basename($this->getDiffusionRequest()->getPath());
     $view = id(new PHUITwoColumnView())->setHeader($header)->setCurtain($curtain)->setMainColumn(array($content));
     if ($properties) {
         $view->addPropertySection(pht('Details'), $properties);
     }
     $title = array($basename, $repository->getDisplayName());
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($view));
 }
 public function handleException(Exception $ex)
 {
     $request = $this->getRequest();
     // For Conduit requests, return a Conduit response.
     if ($request->isConduit()) {
         $response = new ConduitAPIResponse();
         $response->setErrorCode(get_class($ex));
         $response->setErrorInfo($ex->getMessage());
         return id(new AphrontJSONResponse())->setAddJSONShield(false)->setContent($response->toDictionary());
     }
     // For non-workflow requests, return a Ajax response.
     if ($request->isAjax() && !$request->isWorkflow()) {
         // Log these; they don't get shown on the client and can be difficult
         // to debug.
         phlog($ex);
         $response = new AphrontAjaxResponse();
         $response->setError(array('code' => get_class($ex), 'info' => $ex->getMessage()));
         return $response;
     }
     $user = $request->getUser();
     if (!$user) {
         // If we hit an exception very early, we won't have a user.
         $user = new PhabricatorUser();
     }
     if ($ex instanceof PhabricatorSystemActionRateLimitException) {
         $dialog = id(new AphrontDialogView())->setTitle(pht('Slow Down!'))->setUser($user)->setErrors(array(pht('You are being rate limited.')))->appendParagraph($ex->getMessage())->appendParagraph($ex->getRateExplanation())->addCancelButton('/', pht('Okaaaaaaaaaaaaaay...'));
         $response = new AphrontDialogResponse();
         $response->setDialog($dialog);
         return $response;
     }
     if ($ex instanceof PhabricatorAuthHighSecurityRequiredException) {
         $form = id(new PhabricatorAuthSessionEngine())->renderHighSecurityForm($ex->getFactors(), $ex->getFactorValidationResults(), $user, $request);
         $dialog = id(new AphrontDialogView())->setUser($user)->setTitle(pht('Entering High Security'))->setShortTitle(pht('Security Checkpoint'))->setWidth(AphrontDialogView::WIDTH_FORM)->addHiddenInput(AphrontRequest::TYPE_HISEC, true)->setErrors(array(pht('You are taking an action which requires you to enter ' . 'high security.')))->appendParagraph(pht('High security mode helps protect your account from security ' . 'threats, like session theft or someone messing with your stuff ' . 'while you\'re grabbing a coffee. To enter high security mode, ' . 'confirm your credentials.'))->appendChild($form->buildLayoutView())->appendParagraph(pht('Your account will remain in high security mode for a short ' . 'period of time. When you are finished taking sensitive ' . 'actions, you should leave high security.'))->setSubmitURI($request->getPath())->addCancelButton($ex->getCancelURI())->addSubmitButton(pht('Enter High Security'));
         $request_parameters = $request->getPassthroughRequestParameters($respect_quicksand = true);
         foreach ($request_parameters as $key => $value) {
             $dialog->addHiddenInput($key, $value);
         }
         $response = new AphrontDialogResponse();
         $response->setDialog($dialog);
         return $response;
     }
     if ($ex instanceof PhabricatorPolicyException) {
         if (!$user->isLoggedIn()) {
             // If the user isn't logged in, just give them a login form. This is
             // probably a generally more useful response than a policy dialog that
             // they have to click through to get a login form.
             //
             // Possibly we should add a header here like "you need to login to see
             // the thing you are trying to look at".
             $login_controller = new PhabricatorAuthStartController();
             $login_controller->setRequest($request);
             $auth_app_class = 'PhabricatorAuthApplication';
             $auth_app = PhabricatorApplication::getByClass($auth_app_class);
             $login_controller->setCurrentApplication($auth_app);
             return $login_controller->handleRequest($request);
         }
         $content = array(phutil_tag('div', array('class' => 'aphront-policy-rejection'), $ex->getRejection()));
         $list = null;
         if ($ex->getCapabilityName()) {
             $list = $ex->getMoreInfo();
             foreach ($list as $key => $item) {
                 $list[$key] = $item;
             }
             $content[] = phutil_tag('div', array('class' => 'aphront-capability-details'), pht('Users with the "%s" capability:', $ex->getCapabilityName()));
         }
         $dialog = id(new AphrontDialogView())->setTitle($ex->getTitle())->setClass('aphront-access-dialog')->setUser($user)->appendChild($content);
         if ($list) {
             $dialog->appendList($list);
         }
         if ($this->getRequest()->isAjax()) {
             $dialog->addCancelButton('/', pht('Close'));
         } else {
             $dialog->addCancelButton('/', pht('OK'));
         }
         $response = new AphrontDialogResponse();
         $response->setDialog($dialog);
         return $response;
     }
     if ($ex instanceof AphrontUsageException) {
         $error = new PHUIInfoView();
         $error->setTitle($ex->getTitle());
         $error->appendChild($ex->getMessage());
         $view = new PhabricatorStandardPageView();
         $view->setRequest($this->getRequest());
         $view->appendChild($error);
         $response = new AphrontWebpageResponse();
         $response->setContent($view->render());
         $response->setHTTPResponseCode(500);
         return $response;
     }
     // Always log the unhandled exception.
     phlog($ex);
     $class = get_class($ex);
     $message = $ex->getMessage();
     if ($ex instanceof AphrontSchemaQueryException) {
         $message .= "\n\n" . pht("NOTE: This usually indicates that the MySQL schema has not been " . "properly upgraded. Run '%s' to ensure your schema is up to date.", 'bin/storage upgrade');
     }
     if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
         $trace = id(new AphrontStackTraceView())->setUser($user)->setTrace($ex->getTrace());
     } else {
         $trace = null;
     }
     $content = phutil_tag('div', array('class' => 'aphront-unhandled-exception'), array(phutil_tag('div', array('class' => 'exception-message'), $message), $trace));
     $dialog = new AphrontDialogView();
     $dialog->setTitle(pht('Unhandled Exception ("%s")', $class))->setClass('aphront-exception-dialog')->setUser($user)->appendChild($content);
     if ($this->getRequest()->isAjax()) {
         $dialog->addCancelButton('/', pht('Close'));
     }
     $response = new AphrontDialogResponse();
     $response->setDialog($dialog);
     $response->setHTTPResponseCode(500);
     return $response;
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $e_title = null;
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     $task = id(new ManiphestTaskQuery())->setViewer($user)->withIDs(array($this->id))->needSubscriberPHIDs(true)->executeOne();
     if (!$task) {
         return new Aphront404Response();
     }
     $workflow = $request->getStr('workflow');
     $parent_task = null;
     if ($workflow && is_numeric($workflow)) {
         $parent_task = id(new ManiphestTaskQuery())->setViewer($user)->withIDs(array($workflow))->executeOne();
     }
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($user)->readFieldsFromStorage($task);
     $e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST;
     $e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
     $e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
     $e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
     $e_mock = ManiphestTaskHasMockEdgeType::EDGECONST;
     $phid = $task->getPHID();
     $query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($phid))->withEdgeTypes(array($e_commit, $e_dep_on, $e_dep_by, $e_rev, $e_mock));
     $edges = idx($query->execute(), $phid);
     $phids = array_fill_keys($query->getDestinationPHIDs(), true);
     if ($task->getOwnerPHID()) {
         $phids[$task->getOwnerPHID()] = true;
     }
     $phids[$task->getAuthorPHID()] = true;
     $attached = $task->getAttached();
     foreach ($attached as $type => $list) {
         foreach ($list as $phid => $info) {
             $phids[$phid] = true;
         }
     }
     if ($parent_task) {
         $phids[$parent_task->getPHID()] = true;
     }
     $phids = array_keys($phids);
     $handles = $user->loadHandles($phids);
     $info_view = null;
     if ($parent_task) {
         $info_view = new PHUIInfoView();
         $info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/?parent=' . $parent_task->getID())->setText(pht('Create Another Subtask')));
         $info_view->appendChild(hsprintf('Created a subtask of <strong>%s</strong>.', $handles->renderHandle($parent_task->getPHID())));
     } else {
         if ($workflow == 'create') {
             $info_view = new PHUIInfoView();
             $info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
             $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/?template=' . $task->getID())->setText(pht('Similar Task')));
             $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/')->setText(pht('Empty Task')));
             $info_view->appendChild(pht('New task created. Create another?'));
         }
     }
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($user);
     $engine->setContextObject($task);
     $engine->addObject($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION);
     $timeline = $this->buildTransactionTimeline($task, new ManiphestTransactionQuery(), $engine);
     $resolution_types = ManiphestTaskStatus::getTaskStatusMap();
     $transaction_types = array(PhabricatorTransactions::TYPE_COMMENT => pht('Comment'), ManiphestTransaction::TYPE_STATUS => pht('Change Status'), ManiphestTransaction::TYPE_OWNER => pht('Reassign / Claim'), PhabricatorTransactions::TYPE_SUBSCRIBERS => pht('Add CCs'), ManiphestTransaction::TYPE_PRIORITY => pht('Change Priority'), PhabricatorTransactions::TYPE_EDGE => pht('Associate Projects'));
     // Remove actions the user doesn't have permission to take.
     $requires = array(ManiphestTransaction::TYPE_OWNER => ManiphestEditAssignCapability::CAPABILITY, ManiphestTransaction::TYPE_PRIORITY => ManiphestEditPriorityCapability::CAPABILITY, PhabricatorTransactions::TYPE_EDGE => ManiphestEditProjectsCapability::CAPABILITY, ManiphestTransaction::TYPE_STATUS => ManiphestEditStatusCapability::CAPABILITY);
     foreach ($transaction_types as $type => $name) {
         if (isset($requires[$type])) {
             if (!$this->hasApplicationCapability($requires[$type])) {
                 unset($transaction_types[$type]);
             }
         }
     }
     // Don't show an option to change to the current status, or to change to
     // the duplicate status explicitly.
     unset($resolution_types[$task->getStatus()]);
     unset($resolution_types[ManiphestTaskStatus::getDuplicateStatus()]);
     // Don't show owner/priority changes for closed tasks, as they don't make
     // much sense.
     if ($task->isClosed()) {
         unset($transaction_types[ManiphestTransaction::TYPE_PRIORITY]);
         unset($transaction_types[ManiphestTransaction::TYPE_OWNER]);
     }
     $default_claim = array($user->getPHID() => $user->getUsername() . ' (' . $user->getRealName() . ')');
     $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), $task->getPHID());
     if ($draft) {
         $draft_text = $draft->getDraft();
     } else {
         $draft_text = null;
     }
     $projects_source = new PhabricatorProjectDatasource();
     $users_source = new PhabricatorPeopleDatasource();
     $mailable_source = new PhabricatorMetaMTAMailableDatasource();
     $comment_form = new AphrontFormView();
     $comment_form->setUser($user)->setWorkflow(true)->setAction('/maniphest/transaction/save/')->setEncType('multipart/form-data')->addHiddenInput('taskID', $task->getID())->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Action'))->setName('action')->setOptions($transaction_types)->setID('transaction-action'))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Status'))->setName('resolution')->setControlID('resolution')->setControlStyle('display: none')->setOptions($resolution_types))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Assign To'))->setName('assign_to')->setControlID('assign_to')->setControlStyle('display: none')->setID('assign-tokenizer')->setDisableBehavior(true)->setDatasource($users_source))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('CCs'))->setName('ccs')->setControlID('ccs')->setControlStyle('display: none')->setID('cc-tokenizer')->setDisableBehavior(true)->setDatasource($mailable_source))->appendChild(id(new AphrontFormSelectControl())->setLabel(pht('Priority'))->setName('priority')->setOptions($priority_map)->setControlID('priority')->setControlStyle('display: none')->setValue($task->getPriority()))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Projects'))->setName('projects')->setControlID('projects')->setControlStyle('display: none')->setID('projects-tokenizer')->setDisableBehavior(true)->setDatasource($projects_source))->appendChild(id(new AphrontFormFileControl())->setLabel(pht('File'))->setName('file')->setControlID('file')->setControlStyle('display: none'))->appendChild(id(new PhabricatorRemarkupControl())->setUser($user)->setLabel(pht('Comments'))->setName('comments')->setValue($draft_text)->setID('transaction-comments')->setUser($user))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Submit')));
     $control_map = array(ManiphestTransaction::TYPE_STATUS => 'resolution', ManiphestTransaction::TYPE_OWNER => 'assign_to', PhabricatorTransactions::TYPE_SUBSCRIBERS => 'ccs', ManiphestTransaction::TYPE_PRIORITY => 'priority', PhabricatorTransactions::TYPE_EDGE => 'projects');
     $tokenizer_map = array(PhabricatorTransactions::TYPE_EDGE => array('id' => 'projects-tokenizer', 'src' => $projects_source->getDatasourceURI(), 'placeholder' => $projects_source->getPlaceholderText()), ManiphestTransaction::TYPE_OWNER => array('id' => 'assign-tokenizer', 'src' => $users_source->getDatasourceURI(), 'value' => $default_claim, 'limit' => 1, 'placeholder' => $users_source->getPlaceholderText()), PhabricatorTransactions::TYPE_SUBSCRIBERS => array('id' => 'cc-tokenizer', 'src' => $mailable_source->getDatasourceURI(), 'placeholder' => $mailable_source->getPlaceholderText()));
     // TODO: Initializing these behaviors for logged out users fatals things.
     if ($user->isLoggedIn()) {
         Javelin::initBehavior('maniphest-transaction-controls', array('select' => 'transaction-action', 'controlMap' => $control_map, 'tokenizers' => $tokenizer_map));
         Javelin::initBehavior('maniphest-transaction-preview', array('uri' => '/maniphest/transaction/preview/' . $task->getID() . '/', 'preview' => 'transaction-preview', 'comments' => 'transaction-comments', 'action' => 'transaction-action', 'map' => $control_map, 'tokenizers' => $tokenizer_map));
     }
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     $comment_header = $is_serious ? pht('Add Comment') : pht('Weigh In');
     $preview_panel = phutil_tag_div('aphront-panel-preview', phutil_tag('div', array('id' => 'transaction-preview'), phutil_tag_div('aphront-panel-preview-loading-text', pht('Loading preview...'))));
     $object_name = 'T' . $task->getID();
     $actions = $this->buildActionView($task);
     $crumbs = $this->buildApplicationCrumbs()->addTextCrumb($object_name, '/' . $object_name);
     $header = $this->buildHeaderView($task);
     $properties = $this->buildPropertyView($task, $field_list, $edges, $actions, $handles);
     $description = $this->buildDescriptionView($task, $engine);
     if (!$user->isLoggedIn()) {
         // TODO: Eventually, everything should run through this. For now, we're
         // only using it to get a consistent "Login to Comment" button.
         $comment_box = id(new PhabricatorApplicationTransactionCommentView())->setUser($user)->setRequestURI($request->getRequestURI());
         $preview_panel = null;
     } else {
         $comment_box = id(new PHUIObjectBoxView())->setFlush(true)->setHeaderText($comment_header)->appendChild($comment_form);
         $timeline->setQuoteTargetID('transaction-comments');
         $timeline->setQuoteRef($object_name);
     }
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     if ($info_view) {
         $object_box->setInfoView($info_view);
     }
     if ($description) {
         $object_box->addPropertyList($description);
     }
     return $this->buildApplicationPage(array($crumbs, $object_box, $timeline, $comment_box, $preview_panel), array('title' => 'T' . $task->getID() . ' ' . $task->getTitle(), 'pageObjects' => array($task->getPHID())));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $current_version = null;
     if ($id) {
         $document = id(new PhrictionDocumentQuery())->setViewer($viewer)->withIDs(array($id))->needContent(true)->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
         if (!$document) {
             return new Aphront404Response();
         }
         $current_version = $document->getContent()->getVersion();
         $revert = $request->getInt('revert');
         if ($revert) {
             $content = id(new PhrictionContent())->loadOneWhere('documentID = %d AND version = %d', $document->getID(), $revert);
             if (!$content) {
                 return new Aphront404Response();
             }
         } else {
             $content = $document->getContent();
         }
     } else {
         $slug = $request->getStr('slug');
         $slug = PhabricatorSlug::normalize($slug);
         if (!$slug) {
             return new Aphront404Response();
         }
         $document = id(new PhrictionDocumentQuery())->setViewer($viewer)->withSlugs(array($slug))->needContent(true)->executeOne();
         if ($document) {
             $content = $document->getContent();
             $current_version = $content->getVersion();
         } else {
             $document = PhrictionDocument::initializeNewDocument($viewer, $slug);
             $content = $document->getContent();
         }
     }
     if ($request->getBool('nodraft')) {
         $draft = null;
         $draft_key = null;
     } else {
         if ($document->getPHID()) {
             $draft_key = $document->getPHID() . ':' . $content->getVersion();
         } else {
             $draft_key = 'phriction:' . $content->getSlug();
         }
         $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $viewer->getPHID(), $draft_key);
     }
     if ($draft && strlen($draft->getDraft()) && $draft->getDraft() != $content->getContent()) {
         $content_text = $draft->getDraft();
         $discard = phutil_tag('a', array('href' => $request->getRequestURI()->alter('nodraft', true)), pht('discard this draft'));
         $draft_note = new PHUIInfoView();
         $draft_note->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $draft_note->setTitle(pht('Recovered Draft'));
         $draft_note->appendChild(hsprintf('<p>%s</p>', pht('Showing a saved draft of your edits, you can %s.', $discard)));
     } else {
         $content_text = $content->getContent();
         $draft_note = null;
     }
     require_celerity_resource('phriction-document-css');
     $e_title = true;
     $e_content = true;
     $validation_exception = null;
     $notes = null;
     $title = $content->getTitle();
     $overwrite = false;
     $v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID($document->getPHID());
     if ($request->isFormPost()) {
         $title = $request->getStr('title');
         $content_text = $request->getStr('content');
         $notes = $request->getStr('description');
         $current_version = $request->getInt('contentVersion');
         $v_view = $request->getStr('viewPolicy');
         $v_edit = $request->getStr('editPolicy');
         $v_cc = $request->getArr('cc');
         $xactions = array();
         $xactions[] = id(new PhrictionTransaction())->setTransactionType(PhrictionTransaction::TYPE_TITLE)->setNewValue($title);
         $xactions[] = id(new PhrictionTransaction())->setTransactionType(PhrictionTransaction::TYPE_CONTENT)->setNewValue($content_text);
         $xactions[] = id(new PhrictionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)->setNewValue($v_view);
         $xactions[] = id(new PhrictionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)->setNewValue($v_edit);
         $xactions[] = id(new PhrictionTransaction())->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)->setNewValue(array('=' => $v_cc));
         $editor = id(new PhrictionTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setDescription($notes)->setProcessContentVersionError(!$request->getBool('overwrite'))->setContentVersion($current_version);
         try {
             $editor->applyTransactions($document, $xactions);
             if ($draft) {
                 $draft->delete();
             }
             $uri = PhrictionDocument::getSlugURI($document->getSlug());
             return id(new AphrontRedirectResponse())->setURI($uri);
         } catch (PhabricatorApplicationTransactionValidationException $ex) {
             $validation_exception = $ex;
             $e_title = nonempty($ex->getShortMessage(PhrictionTransaction::TYPE_TITLE), true);
             $e_content = nonempty($ex->getShortMessage(PhrictionTransaction::TYPE_CONTENT), true);
             // if we're not supposed to process the content version error, then
             // overwrite that content...!
             if (!$editor->getProcessContentVersionError()) {
                 $overwrite = true;
             }
             $document->setViewPolicy($v_view);
             $document->setEditPolicy($v_edit);
         }
     }
     if ($document->getID()) {
         $panel_header = pht('Edit Document: %s', $content->getTitle());
         $page_title = pht('Edit Document');
         $header_icon = 'fa-pencil';
         if ($overwrite) {
             $submit_button = pht('Overwrite Changes');
         } else {
             $submit_button = pht('Save Changes');
         }
     } else {
         $panel_header = pht('Create New Phriction Document');
         $submit_button = pht('Create Document');
         $page_title = pht('Create Document');
         $header_icon = 'fa-plus-square';
     }
     $uri = $document->getSlug();
     $uri = PhrictionDocument::getSlugURI($uri);
     $uri = PhabricatorEnv::getProductionURI($uri);
     $cancel_uri = PhrictionDocument::getSlugURI($document->getSlug());
     $policies = id(new PhabricatorPolicyQuery())->setViewer($viewer)->setObject($document)->execute();
     $view_capability = PhabricatorPolicyCapability::CAN_VIEW;
     $edit_capability = PhabricatorPolicyCapability::CAN_EDIT;
     $form = id(new AphrontFormView())->setUser($viewer)->addHiddenInput('slug', $document->getSlug())->addHiddenInput('nodraft', $request->getBool('nodraft'))->addHiddenInput('contentVersion', $current_version)->addHiddenInput('overwrite', $overwrite)->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Title'))->setValue($title)->setError($e_title)->setName('title'))->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('URI'))->setValue($uri))->appendChild(id(new PhabricatorRemarkupControl())->setLabel(pht('Content'))->setValue($content_text)->setError($e_content)->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)->setName('content')->setID('document-textarea')->setUser($viewer))->appendControl(id(new AphrontFormTokenizerControl())->setLabel(pht('Subscribers'))->setName('cc')->setValue($v_cc)->setUser($viewer)->setDatasource(new PhabricatorMetaMTAMailableDatasource()))->appendChild(id(new AphrontFormPolicyControl())->setName('viewPolicy')->setPolicyObject($document)->setCapability($view_capability)->setPolicies($policies)->setCaption($document->describeAutomaticCapability($view_capability)))->appendChild(id(new AphrontFormPolicyControl())->setName('editPolicy')->setPolicyObject($document)->setCapability($edit_capability)->setPolicies($policies)->setCaption($document->describeAutomaticCapability($edit_capability)))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Edit Notes'))->setValue($notes)->setError(null)->setName('description'))->appendChild(id(new AphrontFormSubmitControl())->addCancelButton($cancel_uri)->setValue($submit_button));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Document'))->setValidationException($validation_exception)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setForm($form);
     $preview = id(new PHUIRemarkupPreviewPanel())->setHeader($content->getTitle())->setPreviewURI('/phriction/preview/' . $document->getSlug())->setControlID('document-textarea')->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT);
     $crumbs = $this->buildApplicationCrumbs();
     if ($document->getID()) {
         $crumbs->addTextCrumb($content->getTitle(), PhrictionDocument::getSlugURI($document->getSlug()));
         $crumbs->addTextCrumb(pht('Edit'));
     } else {
         $crumbs->addTextCrumb(pht('Create'));
     }
     $crumbs->setBorder(true);
     $header = id(new PHUIHeaderView())->setHeader($panel_header)->setHeaderIcon($header_icon);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($draft_note, $form_box, $preview));
     return $this->newPage()->setTitle($page_title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $this->slug = $request->getURIData('slug');
     $slug = PhabricatorSlug::normalize($this->slug);
     if ($slug != $this->slug) {
         $uri = PhrictionDocument::getSlugURI($slug);
         // Canonicalize pages to their one true URI.
         return id(new AphrontRedirectResponse())->setURI($uri);
     }
     require_celerity_resource('phriction-document-css');
     $document = id(new PhrictionDocumentQuery())->setViewer($viewer)->withSlugs(array($slug))->executeOne();
     $version_note = null;
     $core_content = '';
     $move_notice = '';
     $properties = null;
     $content = null;
     if (!$document) {
         $document = PhrictionDocument::initializeNewDocument($viewer, $slug);
         $create_uri = '/phriction/edit/?slug=' . $slug;
         $notice = new PHUIInfoView();
         $notice->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $notice->setTitle(pht('No content here!'));
         $notice->appendChild(pht('No document found at %s. You can <strong>' . '<a href="%s">create a new document here</a></strong>.', phutil_tag('tt', array(), $slug), $create_uri));
         $core_content = $notice;
         $page_title = pht('Page Not Found');
     } else {
         $version = $request->getInt('v');
         if ($version) {
             $content = id(new PhrictionContent())->loadOneWhere('documentID = %d AND version = %d', $document->getID(), $version);
             if (!$content) {
                 return new Aphront404Response();
             }
             if ($content->getID() != $document->getContentID()) {
                 $vdate = phabricator_datetime($content->getDateCreated(), $viewer);
                 $version_note = new PHUIInfoView();
                 $version_note->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
                 $version_note->appendChild(pht('You are viewing an older version of this document, as it ' . 'appeared on %s.', $vdate));
             }
         } else {
             $content = id(new PhrictionContent())->load($document->getContentID());
         }
         $page_title = $content->getTitle();
         $properties = $this->buildPropertyListView($document, $content, $slug);
         $doc_status = $document->getStatus();
         $current_status = $content->getChangeType();
         if ($current_status == PhrictionChangeType::CHANGE_EDIT || $current_status == PhrictionChangeType::CHANGE_MOVE_HERE) {
             $core_content = $content->renderContent($viewer);
         } else {
             if ($current_status == PhrictionChangeType::CHANGE_DELETE) {
                 $notice = new PHUIInfoView();
                 $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
                 $notice->setTitle(pht('Document Deleted'));
                 $notice->appendChild(pht('This document has been deleted. You can edit it to put new ' . 'content here, or use history to revert to an earlier version.'));
                 $core_content = $notice->render();
             } else {
                 if ($current_status == PhrictionChangeType::CHANGE_STUB) {
                     $notice = new PHUIInfoView();
                     $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
                     $notice->setTitle(pht('Empty Document'));
                     $notice->appendChild(pht('This document is empty. You can edit it to put some proper ' . 'content here.'));
                     $core_content = $notice->render();
                 } else {
                     if ($current_status == PhrictionChangeType::CHANGE_MOVE_AWAY) {
                         $new_doc_id = $content->getChangeRef();
                         $slug_uri = null;
                         // If the new document exists and the viewer can see it, provide a link
                         // to it. Otherwise, render a generic message.
                         $new_docs = id(new PhrictionDocumentQuery())->setViewer($viewer)->withIDs(array($new_doc_id))->execute();
                         if ($new_docs) {
                             $new_doc = head($new_docs);
                             $slug_uri = PhrictionDocument::getSlugURI($new_doc->getSlug());
                         }
                         $notice = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
                         if ($slug_uri) {
                             $notice->appendChild(phutil_tag('p', array(), pht('This document has been moved to %s. You can edit it to put ' . 'new content here, or use history to revert to an earlier ' . 'version.', phutil_tag('a', array('href' => $slug_uri), $slug_uri))));
                         } else {
                             $notice->appendChild(phutil_tag('p', array(), pht('This document has been moved. You can edit it to put new ' . 'contne here, or use history to revert to an earlier ' . 'version.')));
                         }
                         $core_content = $notice->render();
                     } else {
                         throw new Exception(pht("Unknown document status '%s'!", $doc_status));
                     }
                 }
             }
         }
         $move_notice = null;
         if ($current_status == PhrictionChangeType::CHANGE_MOVE_HERE) {
             $from_doc_id = $content->getChangeRef();
             $slug_uri = null;
             // If the old document exists and is visible, provide a link to it.
             $from_docs = id(new PhrictionDocumentQuery())->setViewer($viewer)->withIDs(array($from_doc_id))->execute();
             if ($from_docs) {
                 $from_doc = head($from_docs);
                 $slug_uri = PhrictionDocument::getSlugURI($from_doc->getSlug());
             }
             $move_notice = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
             if ($slug_uri) {
                 $move_notice->appendChild(pht('This document was moved from %s.', phutil_tag('a', array('href' => $slug_uri), $slug_uri)));
             } else {
                 // Render this for consistency, even though it's a bit silly.
                 $move_notice->appendChild(pht('This document was moved from elsewhere.'));
             }
         }
     }
     $children = $this->renderDocumentChildren($slug);
     $actions = $this->buildActionView($viewer, $document);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->setBorder(true);
     $crumb_views = $this->renderBreadcrumbs($slug);
     foreach ($crumb_views as $view) {
         $crumbs->addCrumb($view);
     }
     $action_button = id(new PHUIButtonView())->setTag('a')->setText(pht('Actions'))->setHref('#')->setIconFont('fa-bars')->addClass('phui-mobile-menu')->setDropdownMenu($actions);
     $header = id(new PHUIHeaderView())->setUser($viewer)->setPolicyObject($document)->setHeader($page_title)->addActionLink($action_button);
     if ($content) {
         $header->setEpoch($content->getDateCreated());
     }
     $prop_list = null;
     if ($properties) {
         $prop_list = new PHUIPropertyGroupView();
         $prop_list->addPropertyList($properties);
     }
     $page_content = id(new PHUIDocumentView())->setHeader($header)->appendChild(array($prop_list, $version_note, $move_notice, $core_content));
     return $this->buildApplicationPage(array($crumbs->render(), $page_content, $children), array('pageObjects' => array($document->getPHID()), 'title' => $page_title));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $viewer_is_anonymous = !$user->isLoggedIn();
     $revision = id(new DifferentialRevisionQuery())->withIDs(array($this->revisionID))->setViewer($request->getUser())->needRelationships(true)->needReviewerStatus(true)->needReviewerAuthority(true)->executeOne();
     if (!$revision) {
         return new Aphront404Response();
     }
     $diffs = id(new DifferentialDiffQuery())->setViewer($request->getUser())->withRevisionIDs(array($this->revisionID))->execute();
     $diffs = array_reverse($diffs, $preserve_keys = true);
     if (!$diffs) {
         throw new Exception(pht('This revision has no diffs. Something has gone quite wrong.'));
     }
     $revision->attachActiveDiff(last($diffs));
     $diff_vs = $request->getInt('vs');
     $target_id = $request->getInt('id');
     $target = idx($diffs, $target_id, end($diffs));
     $target_manual = $target;
     if (!$target_id) {
         foreach ($diffs as $diff) {
             if ($diff->getCreationMethod() != 'commit') {
                 $target_manual = $diff;
             }
         }
     }
     if (empty($diffs[$diff_vs])) {
         $diff_vs = null;
     }
     $repository = null;
     $repository_phid = $target->getRepositoryPHID();
     if ($repository_phid) {
         if ($repository_phid == $revision->getRepositoryPHID()) {
             $repository = $revision->getRepository();
         } else {
             $repository = id(new PhabricatorRepositoryQuery())->setViewer($user)->withPHIDs(array($repository_phid))->executeOne();
         }
     }
     list($changesets, $vs_map, $vs_changesets, $rendering_references) = $this->loadChangesetsAndVsMap($target, idx($diffs, $diff_vs), $repository);
     if ($request->getExists('download')) {
         return $this->buildRawDiffResponse($revision, $changesets, $vs_changesets, $vs_map, $repository);
     }
     $map = $vs_map;
     if (!$map) {
         $map = array_fill_keys(array_keys($changesets), 0);
     }
     $old_ids = array();
     $new_ids = array();
     foreach ($map as $id => $vs) {
         if ($vs <= 0) {
             $old_ids[] = $id;
             $new_ids[] = $id;
         } else {
             $new_ids[] = $id;
             $new_ids[] = $vs;
         }
     }
     $props = id(new DifferentialDiffProperty())->loadAllWhere('diffID = %d', $target_manual->getID());
     $props = mpull($props, 'getData', 'getName');
     $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $user->getPHID()));
     foreach ($revision->getAttached() as $type => $phids) {
         foreach ($phids as $phid => $info) {
             $object_phids[] = $phid;
         }
     }
     $field_list = PhabricatorCustomField::getObjectFields($revision, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($user);
     $field_list->readFieldsFromStorage($revision);
     $warning_handle_map = array();
     foreach ($field_list->getFields() as $key => $field) {
         $req = $field->getRequiredHandlePHIDsForRevisionHeaderWarnings();
         foreach ($req as $phid) {
             $warning_handle_map[$key][] = $phid;
             $object_phids[] = $phid;
         }
     }
     $handles = $this->loadViewerHandles($object_phids);
     $request_uri = $request->getRequestURI();
     $limit = 100;
     $large = $request->getStr('large');
     if (count($changesets) > $limit && !$large) {
         $count = count($changesets);
         $warning = new PHUIInfoView();
         $warning->setTitle(pht('Very Large Diff'));
         $warning->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $warning->appendChild(hsprintf('%s <strong>%s</strong>', pht('This diff is very large and affects %s files. ' . 'You may load each file individually or ', new PhutilNumber($count)), phutil_tag('a', array('class' => 'button grey', 'href' => $request_uri->alter('large', 'true')->setFragment('toc')), pht('Show All Files Inline'))));
         $warning = $warning->render();
         $old = array_select_keys($changesets, $old_ids);
         $new = array_select_keys($changesets, $new_ids);
         $query = id(new DifferentialInlineCommentQuery())->setViewer($user)->needHidden(true)->withRevisionPHIDs(array($revision->getPHID()));
         $inlines = $query->execute();
         $inlines = $query->adjustInlinesForChangesets($inlines, $old, $new, $revision);
         $visible_changesets = array();
         foreach ($inlines as $inline) {
             $changeset_id = $inline->getChangesetID();
             if (isset($changesets[$changeset_id])) {
                 $visible_changesets[$changeset_id] = $changesets[$changeset_id];
             }
         }
     } else {
         $warning = null;
         $visible_changesets = $changesets;
     }
     $commit_hashes = mpull($diffs, 'getSourceControlBaseRevision');
     $local_commits = idx($props, 'local:commits', array());
     foreach ($local_commits as $local_commit) {
         $commit_hashes[] = idx($local_commit, 'tree');
         $commit_hashes[] = idx($local_commit, 'local');
     }
     $commit_hashes = array_unique(array_filter($commit_hashes));
     if ($commit_hashes) {
         $commits_for_links = id(new DiffusionCommitQuery())->setViewer($user)->withIdentifiers($commit_hashes)->execute();
         $commits_for_links = mpull($commits_for_links, null, 'getCommitIdentifier');
     } else {
         $commits_for_links = array();
     }
     $revision_detail = id(new DifferentialRevisionDetailView())->setUser($user)->setRevision($revision)->setDiff(end($diffs))->setCustomFields($field_list)->setURI($request->getRequestURI());
     $actions = $this->getRevisionActions($revision);
     $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_MOST);
     $repository = $revision->getRepository();
     if ($repository) {
         $symbol_indexes = $this->buildSymbolIndexes($repository, $visible_changesets);
     } else {
         $symbol_indexes = array();
     }
     $revision_detail->setActions($actions);
     $revision_detail->setUser($user);
     $revision_detail_box = $revision_detail->render();
     $revision_warnings = $this->buildRevisionWarnings($revision, $field_list, $warning_handle_map, $handles);
     if ($revision_warnings) {
         $revision_warnings = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setErrors($revision_warnings);
         $revision_detail_box->setInfoView($revision_warnings);
     }
     $detail_diffs = array_select_keys($diffs, array($diff_vs, $target->getID()));
     $detail_diffs = mpull($detail_diffs, null, 'getPHID');
     $buildables = id(new HarbormasterBuildableQuery())->setViewer($user)->withBuildablePHIDs(array_keys($detail_diffs))->withManualBuildables(false)->needBuilds(true)->needTargets(true)->execute();
     $buildables = mpull($buildables, null, 'getBuildablePHID');
     foreach ($detail_diffs as $diff_phid => $detail_diff) {
         $detail_diff->attachBuildable(idx($buildables, $diff_phid));
     }
     $diff_detail_box = $this->buildDiffDetailView($detail_diffs, $revision, $field_list);
     $comment_view = $this->buildTransactions($revision, $diff_vs ? $diffs[$diff_vs] : $target, $target, $old_ids, $new_ids);
     if (!$viewer_is_anonymous) {
         $comment_view->setQuoteRef('D' . $revision->getID());
         $comment_view->setQuoteTargetID('comment-content');
     }
     $wrap_id = celerity_generate_unique_node_id();
     $comment_view = phutil_tag('div', array('id' => $wrap_id), $comment_view);
     $changeset_view = new DifferentialChangesetListView();
     $changeset_view->setChangesets($changesets);
     $changeset_view->setVisibleChangesets($visible_changesets);
     if (!$viewer_is_anonymous) {
         $changeset_view->setInlineCommentControllerURI('/differential/comment/inline/edit/' . $revision->getID() . '/');
     }
     $changeset_view->setStandaloneURI('/differential/changeset/');
     $changeset_view->setRawFileURIs('/differential/changeset/?view=old', '/differential/changeset/?view=new');
     $changeset_view->setUser($user);
     $changeset_view->setDiff($target);
     $changeset_view->setRenderingReferences($rendering_references);
     $changeset_view->setVsMap($vs_map);
     $changeset_view->setWhitespace($whitespace);
     if ($repository) {
         $changeset_view->setRepository($repository);
     }
     $changeset_view->setSymbolIndexes($symbol_indexes);
     $changeset_view->setTitle(pht('Diff %s', $target->getID()));
     $diff_history = id(new DifferentialRevisionUpdateHistoryView())->setUser($user)->setDiffs($diffs)->setSelectedVersusDiffID($diff_vs)->setSelectedDiffID($target->getID())->setSelectedWhitespace($whitespace)->setCommitsForLinks($commits_for_links);
     $local_view = id(new DifferentialLocalCommitsView())->setUser($user)->setLocalCommits(idx($props, 'local:commits'))->setCommitsForLinks($commits_for_links);
     if ($repository) {
         $other_revisions = $this->loadOtherRevisions($changesets, $target, $repository);
     } else {
         $other_revisions = array();
     }
     $other_view = null;
     if ($other_revisions) {
         $other_view = $this->renderOtherRevisions($other_revisions);
     }
     $toc_view = $this->buildTableOfContents($changesets, $visible_changesets, $target->loadCoverageMap($user));
     $comment_form = null;
     if (!$viewer_is_anonymous) {
         $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID());
         $reviewers = array();
         $ccs = array();
         if ($draft) {
             $reviewers = idx($draft->getMetadata(), 'reviewers', array());
             $ccs = idx($draft->getMetadata(), 'ccs', array());
             if ($reviewers || $ccs) {
                 $handles = $this->loadViewerHandles(array_merge($reviewers, $ccs));
                 $reviewers = array_select_keys($handles, $reviewers);
                 $ccs = array_select_keys($handles, $ccs);
             }
         }
         $comment_form = new DifferentialAddCommentView();
         $comment_form->setRevision($revision);
         $review_warnings = array();
         foreach ($field_list->getFields() as $field) {
             $review_warnings[] = $field->getWarningsForDetailView();
         }
         $review_warnings = array_mergev($review_warnings);
         if ($review_warnings) {
             $review_warnings_panel = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setErrors($review_warnings);
             $comment_form->setInfoView($review_warnings_panel);
         }
         $comment_form->setActions($this->getRevisionCommentActions($revision));
         $action_uri = $this->getApplicationURI('comment/save/' . $revision->getID() . '/');
         $comment_form->setActionURI($action_uri);
         $comment_form->setUser($user);
         $comment_form->setDraft($draft);
         $comment_form->setReviewers(mpull($reviewers, 'getFullName', 'getPHID'));
         $comment_form->setCCs(mpull($ccs, 'getFullName', 'getPHID'));
         // TODO: This just makes the "Z" key work. Generalize this and remove
         // it at some point.
         $comment_form = phutil_tag('div', array('class' => 'differential-add-comment-panel'), $comment_form);
     }
     $pane_id = celerity_generate_unique_node_id();
     Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id));
     Javelin::initBehavior('differential-user-select');
     $page_pane = id(new DifferentialPrimaryPaneView())->setID($pane_id)->appendChild($comment_view);
     $signatures = DifferentialRequiredSignaturesField::loadForRevision($revision);
     $missing_signatures = false;
     foreach ($signatures as $phid => $signed) {
         if (!$signed) {
             $missing_signatures = true;
         }
     }
     if ($missing_signatures) {
         $signature_message = id(new PHUIInfoView())->setErrors(array(array(phutil_tag('strong', array(), pht('Content Hidden:')), ' ', pht('The content of this revision is hidden until the author has ' . 'signed all of the required legal agreements.'))));
         $page_pane->appendChild($signature_message);
     } else {
         $page_pane->appendChild(array($diff_history, $warning, $local_view, $toc_view, $other_view, $changeset_view));
     }
     if ($comment_form) {
         $page_pane->appendChild($comment_form);
     } else {
         // TODO: For now, just use this to get "Login to Comment".
         $page_pane->appendChild(id(new PhabricatorApplicationTransactionCommentView())->setUser($user)->setRequestURI($request->getRequestURI()));
     }
     $object_id = 'D' . $revision->getID();
     $content = array($revision_detail_box, $diff_detail_box, $page_pane);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($object_id, '/' . $object_id);
     $prefs = $user->loadPreferences();
     $pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
     if ($prefs->getPreference($pref_filetree)) {
         $collapsed = $prefs->getPreference(PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED, false);
         $nav = id(new DifferentialChangesetFileTreeSideNavBuilder())->setTitle('D' . $revision->getID())->setBaseURI(new PhutilURI('/D' . $revision->getID()))->setCollapsed((bool) $collapsed)->build($changesets);
         $nav->appendChild($content);
         $nav->setCrumbs($crumbs);
         $content = $nav;
     } else {
         array_unshift($content, $crumbs);
     }
     return $this->buildApplicationPage($content, array('title' => $object_id . ' ' . $revision->getTitle(), 'pageObjects' => array($revision->getPHID())));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $this->revisionID = $request->getURIData('id');
     $viewer_is_anonymous = !$viewer->isLoggedIn();
     $revision = id(new DifferentialRevisionQuery())->withIDs(array($this->revisionID))->setViewer($request->getUser())->needRelationships(true)->needReviewerStatus(true)->needReviewerAuthority(true)->executeOne();
     if (!$revision) {
         return new Aphront404Response();
     }
     $diffs = id(new DifferentialDiffQuery())->setViewer($request->getUser())->withRevisionIDs(array($this->revisionID))->execute();
     $diffs = array_reverse($diffs, $preserve_keys = true);
     if (!$diffs) {
         throw new Exception(pht('This revision has no diffs. Something has gone quite wrong.'));
     }
     $revision->attachActiveDiff(last($diffs));
     $diff_vs = $request->getInt('vs');
     $target_id = $request->getInt('id');
     $target = idx($diffs, $target_id, end($diffs));
     $target_manual = $target;
     if (!$target_id) {
         foreach ($diffs as $diff) {
             if ($diff->getCreationMethod() != 'commit') {
                 $target_manual = $diff;
             }
         }
     }
     if (empty($diffs[$diff_vs])) {
         $diff_vs = null;
     }
     $repository = null;
     $repository_phid = $target->getRepositoryPHID();
     if ($repository_phid) {
         if ($repository_phid == $revision->getRepositoryPHID()) {
             $repository = $revision->getRepository();
         } else {
             $repository = id(new PhabricatorRepositoryQuery())->setViewer($viewer)->withPHIDs(array($repository_phid))->executeOne();
         }
     }
     list($changesets, $vs_map, $vs_changesets, $rendering_references) = $this->loadChangesetsAndVsMap($target, idx($diffs, $diff_vs), $repository);
     if ($request->getExists('download')) {
         return $this->buildRawDiffResponse($revision, $changesets, $vs_changesets, $vs_map, $repository);
     }
     $map = $vs_map;
     if (!$map) {
         $map = array_fill_keys(array_keys($changesets), 0);
     }
     $old_ids = array();
     $new_ids = array();
     foreach ($map as $id => $vs) {
         if ($vs <= 0) {
             $old_ids[] = $id;
             $new_ids[] = $id;
         } else {
             $new_ids[] = $id;
             $new_ids[] = $vs;
         }
     }
     $this->loadDiffProperties($diffs);
     $props = $target_manual->getDiffProperties();
     $object_phids = array_merge($revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array($revision->getAuthorPHID(), $viewer->getPHID()));
     foreach ($revision->getAttached() as $type => $phids) {
         foreach ($phids as $phid => $info) {
             $object_phids[] = $phid;
         }
     }
     $field_list = PhabricatorCustomField::getObjectFields($revision, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer);
     $field_list->readFieldsFromStorage($revision);
     $warning_handle_map = array();
     foreach ($field_list->getFields() as $key => $field) {
         $req = $field->getRequiredHandlePHIDsForRevisionHeaderWarnings();
         foreach ($req as $phid) {
             $warning_handle_map[$key][] = $phid;
             $object_phids[] = $phid;
         }
     }
     $handles = $this->loadViewerHandles($object_phids);
     $request_uri = $request->getRequestURI();
     $limit = 100;
     $large = $request->getStr('large');
     if (count($changesets) > $limit && !$large) {
         $count = count($changesets);
         $warning = new PHUIInfoView();
         $warning->setTitle(pht('Very Large Diff'));
         $warning->setSeverity(PHUIInfoView::SEVERITY_WARNING);
         $warning->appendChild(hsprintf('%s <strong>%s</strong>', pht('This diff is very large and affects %s files. ' . 'You may load each file individually or ', new PhutilNumber($count)), phutil_tag('a', array('class' => 'button grey', 'href' => $request_uri->alter('large', 'true')->setFragment('toc')), pht('Show All Files Inline'))));
         $warning = $warning->render();
         $old = array_select_keys($changesets, $old_ids);
         $new = array_select_keys($changesets, $new_ids);
         $query = id(new DifferentialInlineCommentQuery())->setViewer($viewer)->needHidden(true)->withRevisionPHIDs(array($revision->getPHID()));
         $inlines = $query->execute();
         $inlines = $query->adjustInlinesForChangesets($inlines, $old, $new, $revision);
         $visible_changesets = array();
         foreach ($inlines as $inline) {
             $changeset_id = $inline->getChangesetID();
             if (isset($changesets[$changeset_id])) {
                 $visible_changesets[$changeset_id] = $changesets[$changeset_id];
             }
         }
     } else {
         $warning = null;
         $visible_changesets = $changesets;
     }
     $commit_hashes = mpull($diffs, 'getSourceControlBaseRevision');
     $local_commits = idx($props, 'local:commits', array());
     foreach ($local_commits as $local_commit) {
         $commit_hashes[] = idx($local_commit, 'tree');
         $commit_hashes[] = idx($local_commit, 'local');
     }
     $commit_hashes = array_unique(array_filter($commit_hashes));
     if ($commit_hashes) {
         $commits_for_links = id(new DiffusionCommitQuery())->setViewer($viewer)->withIdentifiers($commit_hashes)->execute();
         $commits_for_links = mpull($commits_for_links, null, 'getCommitIdentifier');
     } else {
         $commits_for_links = array();
     }
     $header = $this->buildHeader($revision);
     $subheader = $this->buildSubheaderView($revision);
     $details = $this->buildDetails($revision, $field_list);
     $curtain = $this->buildCurtain($revision);
     $whitespace = $request->getStr('whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_MOST);
     $repository = $revision->getRepository();
     if ($repository) {
         $symbol_indexes = $this->buildSymbolIndexes($repository, $visible_changesets);
     } else {
         $symbol_indexes = array();
     }
     $revision_warnings = $this->buildRevisionWarnings($revision, $field_list, $warning_handle_map, $handles);
     $info_view = null;
     if ($revision_warnings) {
         $info_view = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setErrors($revision_warnings);
     }
     $detail_diffs = array_select_keys($diffs, array($diff_vs, $target->getID()));
     $detail_diffs = mpull($detail_diffs, null, 'getPHID');
     $this->loadHarbormasterData($detail_diffs);
     $diff_detail_box = $this->buildDiffDetailView($detail_diffs, $revision, $field_list);
     $unit_box = $this->buildUnitMessagesView($target, $revision);
     $comment_view = $this->buildTransactions($revision, $diff_vs ? $diffs[$diff_vs] : $target, $target, $old_ids, $new_ids);
     if (!$viewer_is_anonymous) {
         $comment_view->setQuoteRef('D' . $revision->getID());
         $comment_view->setQuoteTargetID('comment-content');
     }
     $changeset_view = id(new DifferentialChangesetListView())->setChangesets($changesets)->setVisibleChangesets($visible_changesets)->setStandaloneURI('/differential/changeset/')->setRawFileURIs('/differential/changeset/?view=old', '/differential/changeset/?view=new')->setUser($viewer)->setDiff($target)->setRenderingReferences($rendering_references)->setVsMap($vs_map)->setWhitespace($whitespace)->setSymbolIndexes($symbol_indexes)->setTitle(pht('Diff %s', $target->getID()))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY);
     if ($repository) {
         $changeset_view->setRepository($repository);
     }
     if (!$viewer_is_anonymous) {
         $changeset_view->setInlineCommentControllerURI('/differential/comment/inline/edit/' . $revision->getID() . '/');
     }
     $history = id(new DifferentialRevisionUpdateHistoryView())->setUser($viewer)->setDiffs($diffs)->setSelectedVersusDiffID($diff_vs)->setSelectedDiffID($target->getID())->setSelectedWhitespace($whitespace)->setCommitsForLinks($commits_for_links);
     $local_table = id(new DifferentialLocalCommitsView())->setUser($viewer)->setLocalCommits(idx($props, 'local:commits'))->setCommitsForLinks($commits_for_links);
     if ($repository) {
         $other_revisions = $this->loadOtherRevisions($changesets, $target, $repository);
     } else {
         $other_revisions = array();
     }
     $other_view = null;
     if ($other_revisions) {
         $other_view = $this->renderOtherRevisions($other_revisions);
     }
     $toc_view = $this->buildTableOfContents($changesets, $visible_changesets, $target->loadCoverageMap($viewer));
     $tab_group = id(new PHUITabGroupView())->addTab(id(new PHUITabView())->setName(pht('Files'))->setKey('files')->appendChild($toc_view))->addTab(id(new PHUITabView())->setName(pht('History'))->setKey('history')->appendChild($history))->addTab(id(new PHUITabView())->setName(pht('Commits'))->setKey('commits')->appendChild($local_table));
     $stack_graph = id(new DifferentialRevisionGraph())->setViewer($viewer)->setSeedPHID($revision->getPHID())->setLoadEntireGraph(true)->loadGraph();
     if (!$stack_graph->isEmpty()) {
         $stack_table = $stack_graph->newGraphTable();
         $parent_type = DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST;
         $reachable = $stack_graph->getReachableObjects($parent_type);
         foreach ($reachable as $key => $reachable_revision) {
             if ($reachable_revision->isClosed()) {
                 unset($reachable[$key]);
             }
         }
         if ($reachable) {
             $stack_name = pht('Stack (%s Open)', phutil_count($reachable));
             $stack_color = PHUIListItemView::STATUS_FAIL;
         } else {
             $stack_name = pht('Stack');
             $stack_color = null;
         }
         $tab_group->addTab(id(new PHUITabView())->setName($stack_name)->setKey('stack')->setColor($stack_color)->appendChild($stack_table));
     }
     if ($other_view) {
         $tab_group->addTab(id(new PHUITabView())->setName(pht('Similar'))->setKey('similar')->appendChild($other_view));
     }
     $tab_view = id(new PHUIObjectBoxView())->setHeaderText(pht('Revision Contents'))->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->addTabGroup($tab_group);
     $comment_form = null;
     if (!$viewer_is_anonymous) {
         $comment_form = $this->buildCommentForm($revision, $field_list);
     }
     $signatures = DifferentialRequiredSignaturesField::loadForRevision($revision);
     $missing_signatures = false;
     foreach ($signatures as $phid => $signed) {
         if (!$signed) {
             $missing_signatures = true;
         }
     }
     $footer = array();
     $signature_message = null;
     if ($missing_signatures) {
         $signature_message = id(new PHUIInfoView())->setTitle(pht('Content Hidden'))->appendChild(pht('The content of this revision is hidden until the author has ' . 'signed all of the required legal agreements.'));
     } else {
         $anchor = id(new PhabricatorAnchorView())->setAnchorName('toc')->setNavigationMarker(true);
         $footer[] = array($anchor, $warning, $tab_view, $changeset_view);
     }
     if ($comment_form) {
         $footer[] = $comment_form;
     } else {
         // TODO: For now, just use this to get "Login to Comment".
         $footer[] = id(new PhabricatorApplicationTransactionCommentView())->setUser($viewer)->setRequestURI($request->getRequestURI());
     }
     $object_id = 'D' . $revision->getID();
     $operations_box = $this->buildOperationsBox($revision);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($object_id, '/' . $object_id);
     $crumbs->setBorder(true);
     $filetree_on = $viewer->compareUserSetting(PhabricatorShowFiletreeSetting::SETTINGKEY, PhabricatorShowFiletreeSetting::VALUE_ENABLE_FILETREE);
     $nav = null;
     if ($filetree_on) {
         $collapsed_key = PhabricatorFiletreeVisibleSetting::SETTINGKEY;
         $collapsed_value = $viewer->getUserSetting($collapsed_key);
         $nav = id(new DifferentialChangesetFileTreeSideNavBuilder())->setTitle('D' . $revision->getID())->setBaseURI(new PhutilURI('/D' . $revision->getID()))->setCollapsed((bool) $collapsed_value)->build($changesets);
     }
     // Haunt Mode
     $pane_id = celerity_generate_unique_node_id();
     Javelin::initBehavior('differential-keyboard-navigation', array('haunt' => $pane_id));
     Javelin::initBehavior('differential-user-select');
     $view = id(new PHUITwoColumnView())->setHeader($header)->setSubheader($subheader)->setCurtain($curtain)->setID($pane_id)->setMainColumn(array($operations_box, $info_view, $details, $diff_detail_box, $unit_box, $comment_view, $signature_message))->setFooter($footer);
     $page = $this->newPage()->setTitle($object_id . ' ' . $revision->getTitle())->setCrumbs($crumbs)->setPageObjectPHIDs(array($revision->getPHID()))->appendChild($view);
     if ($nav) {
         $page->setNavigation($nav);
     }
     return $page;
 }
 private function buildMergesTable(PhabricatorRepositoryCommit $commit)
 {
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $vcs = $repository->getVersionControlSystem();
     switch ($vcs) {
         case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
             // These aren't supported under SVN.
             return null;
     }
     $limit = 50;
     $merges = $this->callConduitWithDiffusionRequest('diffusion.mergedcommitsquery', array('commit' => $drequest->getCommit(), 'limit' => $limit + 1));
     if (!$merges) {
         return null;
     }
     $merges = DiffusionPathChange::newFromConduit($merges);
     $caption = null;
     if (count($merges) > $limit) {
         $merges = array_slice($merges, 0, $limit);
         $caption = new PHUIInfoView();
         $caption->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $caption->appendChild(pht('This commit merges a very large number of changes. ' . 'Only the first %s are shown.', new PhutilNumber($limit)));
     }
     $history_table = new DiffusionHistoryTableView();
     $history_table->setUser($this->getRequest()->getUser());
     $history_table->setDiffusionRequest($drequest);
     $history_table->setHistory($merges);
     $history_table->loadRevisions();
     $phids = $history_table->getRequiredHandlePHIDs();
     $handles = $this->loadViewerHandles($phids);
     $history_table->setHandles($handles);
     $panel = new PHUIObjectBoxView();
     $panel->setHeaderText(pht('Merged Changes'));
     $panel->setTable($history_table);
     if ($caption) {
         $panel->setInfoView($caption);
     }
     return $panel;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $e_title = null;
     $priority_map = ManiphestTaskPriority::getTaskPriorityMap();
     $task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($id))->needSubscriberPHIDs(true)->executeOne();
     if (!$task) {
         return new Aphront404Response();
     }
     $workflow = $request->getStr('workflow');
     $parent_task = null;
     if ($workflow && is_numeric($workflow)) {
         $parent_task = id(new ManiphestTaskQuery())->setViewer($viewer)->withIDs(array($workflow))->executeOne();
     }
     $field_list = PhabricatorCustomField::getObjectFields($task, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer)->readFieldsFromStorage($task);
     $e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST;
     $e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
     $e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
     $e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
     $e_mock = ManiphestTaskHasMockEdgeType::EDGECONST;
     $phid = $task->getPHID();
     $query = id(new PhabricatorEdgeQuery())->withSourcePHIDs(array($phid))->withEdgeTypes(array($e_commit, $e_dep_on, $e_dep_by, $e_rev, $e_mock));
     $edges = idx($query->execute(), $phid);
     $phids = array_fill_keys($query->getDestinationPHIDs(), true);
     if ($task->getOwnerPHID()) {
         $phids[$task->getOwnerPHID()] = true;
     }
     $phids[$task->getAuthorPHID()] = true;
     $attached = $task->getAttached();
     foreach ($attached as $type => $list) {
         foreach ($list as $phid => $info) {
             $phids[$phid] = true;
         }
     }
     if ($parent_task) {
         $phids[$parent_task->getPHID()] = true;
     }
     $phids = array_keys($phids);
     $handles = $viewer->loadHandles($phids);
     $info_view = null;
     if ($parent_task) {
         $info_view = new PHUIInfoView();
         $info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
         $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/?parent=' . $parent_task->getID())->setText(pht('Create Another Subtask')));
         $info_view->appendChild(hsprintf('Created a subtask of <strong>%s</strong>.', $handles->renderHandle($parent_task->getPHID())));
     } else {
         if ($workflow == 'create') {
             $info_view = new PHUIInfoView();
             $info_view->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
             $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/?template=' . $task->getID())->setText(pht('Similar Task')));
             $info_view->addButton(id(new PHUIButtonView())->setTag('a')->setHref('/maniphest/task/create/')->setText(pht('Empty Task')));
             $info_view->appendChild(pht('New task created. Create another?'));
         }
     }
     $engine = new PhabricatorMarkupEngine();
     $engine->setViewer($viewer);
     $engine->setContextObject($task);
     $engine->addObject($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION);
     $timeline = $this->buildTransactionTimeline($task, new ManiphestTransactionQuery(), $engine);
     $actions = $this->buildActionView($task);
     $monogram = $task->getMonogram();
     $crumbs = $this->buildApplicationCrumbs()->addTextCrumb($monogram, '/' . $monogram);
     $header = $this->buildHeaderView($task);
     $properties = $this->buildPropertyView($task, $field_list, $edges, $actions, $handles);
     $description = $this->buildDescriptionView($task, $engine);
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     if ($description) {
         $object_box->addPropertyList($description);
     }
     $title = pht('%s %s', $monogram, $task->getTitle());
     $comment_view = id(new ManiphestEditEngine())->setViewer($viewer)->buildEditEngineCommentView($task);
     $timeline->setQuoteRef($monogram);
     $comment_view->setTransactionTimeline($timeline);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->setPageObjectPHIDs(array($task->getPHID()))->appendChild(array($info_view, $object_box, $timeline, $comment_view));
 }