public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $name = $request->getURIData('name');
     $service = id(new AlmanacServiceQuery())->setViewer($viewer)->withNames(array($name))->executeOne();
     if (!$service) {
         return new Aphront404Response();
     }
     $title = pht('Service %s', $service->getName());
     $property_list = $this->buildPropertyList($service);
     $action_list = $this->buildActionList($service);
     $property_list->setActionList($action_list);
     $header = id(new PHUIHeaderView())->setUser($viewer)->setHeader($service->getName())->setPolicyObject($service);
     $box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($property_list);
     $messages = $service->getServiceType()->getStatusMessages($service);
     if ($messages) {
         $box->setFormErrors($messages);
     }
     if ($service->getIsLocked()) {
         $this->addLockMessage($box, pht('This service is locked, and can not be edited.'));
     }
     $bindings = $this->buildBindingList($service);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($service->getName());
     $timeline = $this->buildTransactionTimeline($service, new AlmanacServiceTransactionQuery());
     $timeline->setShouldTerminate(true);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($box, $bindings, $this->buildAlmanacPropertiesTable($service), $timeline));
 }
 public function buildRequest()
 {
     $request = new AphrontRequest($this->getHost(), $this->getPath());
     $request->setRequestData($_GET + $_POST);
     $request->setApplicationConfiguration($this);
     return $request;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $books = id(new DivinerBookQuery())->setViewer($viewer)->execute();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->setBorder(true);
     $crumbs->addTextCrumb(pht('Books'));
     $query_button = id(new PHUIButtonView())->setTag('a')->setHref($this->getApplicationURI('query/'))->setText(pht('Advanced Search'))->setIcon('fa-search');
     $header = id(new PHUIHeaderView())->setHeader(pht('Documentation Books'))->addActionLink($query_button);
     $document = new PHUIDocumentViewPro();
     $document->setHeader($header);
     $document->addClass('diviner-view');
     if ($books) {
         $books = msort($books, 'getTitle');
         $list = array();
         foreach ($books as $book) {
             $item = id(new DivinerBookItemView())->setTitle($book->getTitle())->setHref('/book/' . $book->getName() . '/')->setSubtitle($book->getPreface());
             $list[] = $item;
         }
         $list = id(new PHUIBoxView())->addPadding(PHUI::PADDING_MEDIUM_TOP)->appendChild($list);
         $document->appendChild($list);
     } else {
         $text = pht("(NOTE) **Looking for Phabricator documentation?** " . "If you're looking for help and information about Phabricator, " . "you can [[https://secure.phabricator.com/diviner/ | " . "browse the public Phabricator documentation]] on the live site.\n\n" . "Diviner is the documentation generator used to build the " . "Phabricator documentation.\n\n" . "You haven't generated any Diviner documentation books yet, so " . "there's nothing to show here. If you'd like to generate your own " . "local copy of the Phabricator documentation and have it appear " . "here, run this command:\n\n" . "  %s\n\n", 'phabricator/ $ ./bin/diviner generate');
         $text = new PHUIRemarkupView($viewer, $text);
         $document->appendChild($text);
     }
     return $this->newPage()->setTitle(pht('Documentation Books'))->setCrumbs($crumbs)->appendChild(array($document));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $dashboard = id(new PhabricatorDashboardQuery())->setViewer($viewer)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$dashboard) {
         return new Aphront404Response();
     }
     $view_uri = $this->getApplicationURI('manage/' . $dashboard->getID() . '/');
     if ($request->isFormPost()) {
         if ($dashboard->isArchived()) {
             $new_status = PhabricatorDashboard::STATUS_ACTIVE;
         } else {
             $new_status = PhabricatorDashboard::STATUS_ARCHIVED;
         }
         $xactions = array();
         $xactions[] = id(new PhabricatorDashboardTransaction())->setTransactionType(PhabricatorDashboardTransaction::TYPE_STATUS)->setNewValue($new_status);
         id(new PhabricatorDashboardTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->applyTransactions($dashboard, $xactions);
         return id(new AphrontRedirectResponse())->setURI($view_uri);
     }
     if ($dashboard->isArchived()) {
         $title = pht('Activate Dashboard');
         $body = pht('This dashboard will become active again.');
         $button = pht('Activate Dashboard');
     } else {
         $title = pht('Archive Dashboard');
         $body = pht('This dashboard will be marked as archived.');
         $button = pht('Archive Dashboard');
     }
     return $this->newDialog()->setTitle($title)->appendChild($body)->addCancelButton($view_uri)->addSubmitButton($button);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $initiative = id(new FundInitiativeQuery())->setViewer($viewer)->withIDs(array($id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne();
     if (!$initiative) {
         return new Aphront404Response();
     }
     $initiative_uri = '/' . $initiative->getMonogram();
     $is_close = !$initiative->isClosed();
     if ($request->isFormPost()) {
         $type_status = FundInitiativeTransaction::TYPE_STATUS;
         if ($is_close) {
             $new_status = FundInitiative::STATUS_CLOSED;
         } else {
             $new_status = FundInitiative::STATUS_OPEN;
         }
         $xaction = id(new FundInitiativeTransaction())->setTransactionType($type_status)->setNewValue($new_status);
         $editor = id(new FundInitiativeEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true);
         $editor->applyTransactions($initiative, array($xaction));
         return id(new AphrontRedirectResponse())->setURI($initiative_uri);
     }
     if ($is_close) {
         $title = pht('Close Initiative?');
         $body = pht('Really close this initiative? Users will no longer be able to ' . 'back it.');
         $button_text = pht('Close Initiative');
     } else {
         $title = pht('Reopen Initiative?');
         $body = pht('Really reopen this initiative?');
         $button_text = pht('Reopen Initiative');
     }
     return $this->newDialog()->setTitle($title)->appendParagraph($body)->addCancelButton($initiative_uri)->addSubmitButton($button_text);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $timeline = null;
     $url = id(new PhabricatorPhurlURLQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$url) {
         return new Aphront404Response();
     }
     $title = $url->getMonogram();
     $page_title = $title . ' ' . $url->getName();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title, $url->getURI());
     $timeline = $this->buildTransactionTimeline($url, new PhabricatorPhurlURLTransactionQuery());
     $header = $this->buildHeaderView($url);
     $actions = $this->buildActionView($url);
     $properties = $this->buildPropertyView($url);
     $properties->setActionList($actions);
     $url_error = id(new PHUIInfoView())->setErrors(array(pht('This URL is invalid due to a bad protocol.')))->setIsHidden($url->isValid());
     $box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties)->setInfoView($url_error);
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     $add_comment_header = $is_serious ? pht('Add Comment') : pht('More Cowbell');
     $draft = PhabricatorDraft::newFromUserAndKey($viewer, $url->getPHID());
     $comment_uri = $this->getApplicationURI('/phurl/comment/' . $url->getID() . '/');
     $add_comment_form = id(new PhabricatorApplicationTransactionCommentView())->setUser($viewer)->setObjectPHID($url->getPHID())->setDraft($draft)->setHeaderText($add_comment_header)->setAction($comment_uri)->setSubmitButtonName(pht('Add Comment'));
     return $this->buildApplicationPage(array($crumbs, $box, $timeline, $add_comment_form), array('title' => $page_title, 'pageObjects' => array($url->getPHID())));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $blog = id(new PhameBlogQuery())->setViewer($viewer)->withIDs(array($id))->needProfileImage(true)->executeOne();
     if (!$blog) {
         return new Aphront404Response();
     }
     if ($blog->isArchived()) {
         $header_icon = 'fa-ban';
         $header_name = pht('Archived');
         $header_color = 'dark';
     } else {
         $header_icon = 'fa-check';
         $header_name = pht('Active');
         $header_color = 'bluegrey';
     }
     $picture = $blog->getProfileImageURI();
     $header = id(new PHUIHeaderView())->setHeader($blog->getName())->setUser($viewer)->setPolicyObject($blog)->setImage($picture)->setStatus($header_icon, $header_color, $header_name);
     $actions = $this->renderActions($blog, $viewer);
     $properties = $this->renderProperties($blog, $viewer, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/'));
     $crumbs->addTextCrumb($blog->getName());
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $timeline = $this->buildTransactionTimeline($blog, new PhameBlogTransactionQuery());
     $timeline->setShouldTerminate(true);
     return $this->newPage()->setTitle($blog->getName())->setCrumbs($crumbs)->appendChild(array($object_box, $timeline));
 }
 public function processRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     $tokens = id(new PhabricatorAuthTemporaryTokenQuery())->setViewer($viewer)->withObjectPHIDs(array($viewer->getPHID()))->execute();
     $rows = array();
     foreach ($tokens as $token) {
         if ($token->isRevocable()) {
             $button = javelin_tag('a', array('href' => '/auth/token/revoke/' . $token->getID() . '/', 'class' => 'small grey button', 'sigil' => 'workflow'), pht('Revoke'));
         } else {
             $button = javelin_tag('a', array('class' => 'small grey button disabled'), pht('Revoke'));
         }
         if ($token->getTokenExpires() >= time()) {
             $expiry = phabricator_datetime($token->getTokenExpires(), $viewer);
         } else {
             $expiry = pht('Expired');
         }
         $rows[] = array($token->getTokenReadableTypeName(), $expiry, $button);
     }
     $table = new AphrontTableView($rows);
     $table->setNoDataString(pht("You don't have any active tokens."));
     $table->setHeaders(array(pht('Type'), pht('Expires'), pht('')));
     $table->setColumnClasses(array('wide', 'right', 'action'));
     $terminate_button = id(new PHUIButtonView())->setText(pht('Revoke All'))->setHref('/auth/token/revoke/all/')->setTag('a')->setWorkflow(true)->setIcon('fa-exclamation-triangle');
     $header = id(new PHUIHeaderView())->setHeader(pht('Temporary Tokens'))->addActionLink($terminate_button);
     $panel = id(new PHUIObjectBoxView())->setHeader($header)->setTable($table);
     return $panel;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $board_id = $request->getURIData('projectID');
     $board = id(new PhabricatorProjectQuery())->setViewer($viewer)->withIDs(array($board_id))->needImages(true)->executeOne();
     if (!$board) {
         return new Aphront404Response();
     }
     $this->setProject($board);
     // Perform layout of no tasks to load and populate the columns in the
     // correct order.
     $layout_engine = id(new PhabricatorBoardLayoutEngine())->setViewer($viewer)->setBoardPHIDs(array($board->getPHID()))->setObjectPHIDs(array())->setFetchAllBoards(true)->executeLayout();
     $columns = $layout_engine->getColumns($board->getPHID());
     $board_id = $board->getID();
     $header = $this->buildHeaderView($board);
     $actions = $this->buildActionView($board);
     $properties = $this->buildPropertyView($board);
     $properties->setActionList($actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Workboard'), "/project/board/{$board_id}/");
     $crumbs->addTextCrumb(pht('Manage'));
     $box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $nav = $this->getProfileMenu();
     $title = array(pht('Manage Workboard'), $board->getDisplayName());
     $columns_list = $this->buildColumnsList($board, $columns);
     return $this->newPage()->setTitle($title)->setNavigation($nav)->setCrumbs($crumbs)->appendChild(array($box, $columns_list));
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $limit = 500;
     $offset = $request->getInt('offset', 0);
     $drequest = $this->getDiffusionRequest();
     $branch = $drequest->loadBranch();
     $messages = $this->loadLintMessages($branch, $limit, $offset);
     $is_dir = substr('/' . $drequest->getPath(), -1) == '/';
     $authors = $this->loadViewerHandles(ipull($messages, 'authorPHID'));
     $rows = array();
     foreach ($messages as $message) {
         $path = phutil_tag('a', array('href' => $drequest->generateURI(array('action' => 'lint', 'path' => $message['path']))), substr($message['path'], strlen($drequest->getPath()) + 1));
         $line = phutil_tag('a', array('href' => $drequest->generateURI(array('action' => 'browse', 'path' => $message['path'], 'line' => $message['line'], 'commit' => $branch->getLintCommit()))), $message['line']);
         $author = $message['authorPHID'];
         if ($author && $authors[$author]) {
             $author = $authors[$author]->renderLink();
         }
         $rows[] = array($path, $line, $author, ArcanistLintSeverity::getStringForSeverity($message['severity']), $message['name'], $message['description']);
     }
     $table = id(new AphrontTableView($rows))->setHeaders(array(pht('Path'), pht('Line'), pht('Author'), pht('Severity'), pht('Name'), pht('Description')))->setColumnClasses(array('', 'n'))->setColumnVisibility(array($is_dir));
     $content = array();
     $pager = id(new AphrontPagerView())->setPageSize($limit)->setOffset($offset)->setHasMorePages(count($messages) >= $limit)->setURI($request->getRequestURI(), 'offset');
     $content[] = id(new PHUIObjectBoxView())->setHeaderText(pht('Lint Details'))->appendChild($table);
     $crumbs = $this->buildCrumbs(array('branch' => true, 'path' => true, 'view' => 'lint'));
     return $this->buildApplicationPage(array($crumbs, $content, $pager), array('title' => array(pht('Lint'), $drequest->getRepository()->getCallsign())));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $id = $request->getURIData('class');
     $classes = id(new PhutilSymbolLoader())->setAncestorClass('PhabricatorUIExample')->loadObjects();
     $classes = msort($classes, 'getName');
     $nav = new AphrontSideNavFilterView();
     $nav->setBaseURI(new PhutilURI($this->getApplicationURI('view/')));
     foreach ($classes as $class => $obj) {
         $name = $obj->getName();
         $nav->addFilter($class, $name);
     }
     $selected = $nav->selectFilter($id, head_key($classes));
     $example = $classes[$selected];
     $example->setRequest($this->getRequest());
     $result = $example->renderExample();
     if ($result instanceof AphrontResponse) {
         // This allows examples to generate dialogs, etc., for demonstration.
         return $result;
     }
     require_celerity_resource('phabricator-ui-example-css');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($example->getName());
     $note = id(new PHUIInfoView())->setTitle(pht('%s (%s)', $example->getName(), get_class($example)))->appendChild($example->getDescription())->setSeverity(PHUIInfoView::SEVERITY_NODATA);
     $nav->appendChild(array($crumbs, $note, $result));
     return $this->buildApplicationPage($nav, array('title' => $example->getName()));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $stories = id(new PhabricatorNotificationQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->withKeys(array($request->getStr('key')))->execute();
     if (!$stories) {
         return $this->buildEmptyResponse();
     }
     $story = head($stories);
     if ($story->getAuthorPHID() === $viewer->getPHID()) {
         // Don't show the user individual notifications about their own
         // actions. Primarily, this stops pages from showing notifications
         // immediately after you click "Submit" on a comment form if the
         // notification server returns faster than the web server.
         // TODO: It would be nice to retain the "page updated" bubble on copies
         // of the page that are open in other tabs, but there isn't an obvious
         // way to do this easily.
         return $this->buildEmptyResponse();
     }
     $builder = id(new PhabricatorNotificationBuilder(array($story)))->setUser($viewer)->setShowTimestamps(false);
     $content = $builder->buildView()->render();
     $dict = $builder->buildDict();
     $data = $dict[0];
     $response = array('pertinent' => true, 'primaryObjectPHID' => $story->getPrimaryObjectPHID(), 'desktopReady' => $data['desktopReady'], 'href' => $data['href'], 'icon' => $data['icon'], 'title' => $data['title'], 'body' => $data['body'], 'content' => hsprintf('%s', $content));
     return id(new AphrontAjaxResponse())->setContent($response);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $dashboard_uri = $this->getApplicationURI('view/' . $id . '/');
     // TODO: This UI should drop a lot of capabilities if the user can't
     // edit the dashboard, but we should still let them in for "Install" and
     // "View History".
     $dashboard = id(new PhabricatorDashboardQuery())->setViewer($viewer)->withIDs(array($id))->needPanels(true)->executeOne();
     if (!$dashboard) {
         return new Aphront404Response();
     }
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $dashboard, PhabricatorPolicyCapability::CAN_EDIT);
     $title = $dashboard->getName();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID()), $dashboard_uri);
     $crumbs->addTextCrumb(pht('Manage'));
     $crumbs->setBorder(true);
     $header = $this->buildHeaderView($dashboard);
     $curtain = $this->buildCurtainview($dashboard);
     $properties = $this->buildPropertyView($dashboard);
     $timeline = $this->buildTransactionTimeline($dashboard, new PhabricatorDashboardTransactionQuery());
     $info_view = null;
     if (!$can_edit) {
         $no_edit = pht('You do not have permission to edit this dashboard. If you want to ' . 'make changes, make a copy first.');
         $info_view = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->setErrors(array($no_edit));
     }
     $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())->setViewer($viewer)->setDashboard($dashboard)->setArrangeMode($can_edit)->renderDashboard();
     $dashboard_box = id(new PHUIBoxView())->addClass('dashboard-preview-box')->appendChild($rendered_dashboard);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setCurtain($curtain)->setMainColumn(array($info_view, $properties, $timeline))->setFooter($dashboard_box);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $config = $this->loadConfigForEdit();
     if (!$config) {
         return id(new Aphront404Response());
     }
     $engine_key = $config->getEngineKey();
     $key = $config->getIdentifier();
     $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/";
     $type = PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE;
     if ($request->isFormPost()) {
         $xactions = array();
         $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction())->setTransactionType($type)->setNewValue(!$config->getIsDisabled());
         $editor = id(new PhabricatorEditEngineConfigurationEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect(true);
         $editor->applyTransactions($config, $xactions);
         return id(new AphrontRedirectResponse())->setURI($cancel_uri);
     }
     if ($config->getIsDisabled()) {
         $title = pht('Enable Form');
         $body = pht('Enable this form? Users who can see it will be able to use it to ' . 'create objects.');
         $button = pht('Enable Form');
     } else {
         $title = pht('Disable Form');
         $body = pht('Disable this form? Users will no longer be able to use it.');
         $button = pht('Disable Form');
     }
     return $this->newDialog()->setTitle($title)->appendParagraph($body)->addSubmitButton($button)->addCancelbutton($cancel_uri);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     // If the user already has a full session, just kick them out of here.
     $has_partial_session = $viewer->hasSession() && $viewer->getSession()->getIsPartial();
     if (!$has_partial_session) {
         return id(new AphrontRedirectResponse())->setURI('/');
     }
     $engine = new PhabricatorAuthSessionEngine();
     // If this cookie is set, the user is headed into a high security area
     // after login (normally because of a password reset) so if they are
     // able to pass the checkpoint we just want to put their account directly
     // into high security mode, rather than prompt them again for the same
     // set of credentials.
     $jump_into_hisec = $request->getCookie(PhabricatorCookies::COOKIE_HISEC);
     try {
         $token = $engine->requireHighSecuritySession($viewer, $request, '/logout/', $jump_into_hisec);
     } catch (PhabricatorAuthHighSecurityRequiredException $ex) {
         $form = id(new PhabricatorAuthSessionEngine())->renderHighSecurityForm($ex->getFactors(), $ex->getFactorValidationResults(), $viewer, $request);
         return $this->newDialog()->setTitle(pht('Provide Multi-Factor Credentials'))->setShortTitle(pht('Multi-Factor Login'))->setWidth(AphrontDialogView::WIDTH_FORM)->addHiddenInput(AphrontRequest::TYPE_HISEC, true)->appendParagraph(pht('Welcome, %s. To complete the login process, provide your ' . 'multi-factor credentials.', phutil_tag('strong', array(), $viewer->getUsername())))->appendChild($form->buildLayoutView())->setSubmitURI($request->getPath())->addCancelButton($ex->getCancelURI())->addSubmitButton(pht('Continue'));
     }
     // Upgrade the partial session to a full session.
     $engine->upgradePartialSession($viewer);
     // TODO: It might be nice to add options like "bind this session to my IP"
     // here, even for accounts without multi-factor auth attached to them.
     $next = PhabricatorCookies::getNextURICookie($request);
     $request->clearCookie(PhabricatorCookies::COOKIE_NEXTURI);
     $request->clearCookie(PhabricatorCookies::COOKIE_HISEC);
     if (!PhabricatorEnv::isValidLocalURIForLink($next)) {
         $next = '/';
     }
     return id(new AphrontRedirectResponse())->setURI($next);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $blueprint = id(new DrydockBlueprintQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$blueprint) {
         return new Aphront404Response();
     }
     $title = $blueprint->getBlueprintName();
     $header = id(new PHUIHeaderView())->setHeader($title)->setUser($viewer)->setPolicyObject($blueprint);
     if ($blueprint->getIsDisabled()) {
         $header->setStatus('fa-ban', 'red', pht('Disabled'));
     } else {
         $header->setStatus('fa-check', 'bluegrey', pht('Active'));
     }
     $actions = $this->buildActionListView($blueprint);
     $properties = $this->buildPropertyListView($blueprint, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Blueprint %d', $blueprint->getID()));
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $field_list = PhabricatorCustomField::getObjectFields($blueprint, PhabricatorCustomField::ROLE_VIEW);
     $field_list->setViewer($viewer)->readFieldsFromStorage($blueprint);
     $field_list->appendFieldsToPropertyList($blueprint, $viewer, $properties);
     $resource_box = $this->buildResourceBox($blueprint);
     $authorizations_box = $this->buildAuthorizationsBox($blueprint);
     $timeline = $this->buildTransactionTimeline($blueprint, new DrydockBlueprintTransactionQuery());
     $timeline->setShouldTerminate(true);
     $log_query = id(new DrydockLogQuery())->withBlueprintPHIDs(array($blueprint->getPHID()));
     $log_box = $this->buildLogBox($log_query, $this->getApplicationURI("blueprint/{$id}/logs/query/all/"));
     return $this->buildApplicationPage(array($crumbs, $object_box, $resource_box, $authorizations_box, $log_box, $timeline), array('title' => $title));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     if ($request->isFormPost()) {
         $uri = new PhutilURI('/fact/chart/');
         $uri->setQueryParam('y1', $request->getStr('y1'));
         return id(new AphrontRedirectResponse())->setURI($uri);
     }
     $types = array('+N:*', '+N:DREV', 'updated');
     $engines = PhabricatorFactEngine::loadAllEngines();
     $specs = PhabricatorFactSpec::newSpecsForFactTypes($engines, $types);
     $facts = id(new PhabricatorFactAggregate())->loadAllWhere('factType IN (%Ls)', $types);
     $rows = array();
     foreach ($facts as $fact) {
         $spec = $specs[$fact->getFactType()];
         $name = $spec->getName();
         $value = $spec->formatValueForDisplay($viewer, $fact->getValueX());
         $rows[] = array($name, $value);
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array(pht('Fact'), pht('Value')));
     $table->setColumnClasses(array('wide', 'n'));
     $panel = new PHUIObjectBoxView();
     $panel->setHeaderText(pht('Facts'));
     $panel->setTable($table);
     $chart_form = $this->buildChartForm();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Home'));
     $title = pht('Facts');
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild(array($chart_form, $panel));
 }
 protected function processDiffusionRequest(AphrontRequest $request)
 {
     $viewer = $request->getUser();
     $this->requireApplicationCapability(DiffusionCreateRepositoriesCapability::CAPABILITY);
     if ($request->isFormPost()) {
         if ($request->getStr('type')) {
             switch ($request->getStr('type')) {
                 case 'create':
                     $uri = $this->getApplicationURI('create/');
                     break;
                 case 'import':
                 default:
                     $uri = $this->getApplicationURI('import/');
                     break;
             }
             return id(new AphrontRedirectResponse())->setURI($uri);
         }
     }
     $doc_href = PhabricatorEnv::getDoclink('Diffusion User Guide: Repository Hosting');
     $doc_link = phutil_tag('a', array('href' => $doc_href, 'target' => '_blank'), pht('Diffusion User Guide: Repository Hosting'));
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild(id(new AphrontFormRadioButtonControl())->setName('type')->addButton('create', pht('Create a New Hosted Repository'), array(pht('Create a new, empty repository which Phabricator will host. ' . 'For instructions on configuring repository hosting, see %s.', $doc_link)))->addButton('import', pht('Import an Existing External Repository'), pht("Import a repository hosted somewhere else, like GitHub, " . "Bitbucket, or your organization's existing servers. " . "Phabricator will read changes from the repository but will " . "not host or manage it. The authoritative master version of " . "the repository will stay where it is now.")))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Continue'))->addCancelButton($this->getApplicationURI()));
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('New Repository'));
     $form_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Create or Import Repository'))->setForm($form);
     return $this->buildApplicationPage(array($crumbs, $form_box), array('title' => pht('New Repository')));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $id = $request->getURIData('id');
     $user = id(new PhabricatorPeopleQuery())->setViewer($viewer)->withIDs(array($id))->needProfile(true)->needProfileImage(true)->executeOne();
     if (!$user) {
         return new Aphront404Response();
     }
     $this->setUser($user);
     $profile = $user->loadUserProfile();
     $picture = $user->getProfileImageURI();
     $profile_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon());
     $profile_icon = id(new PHUIIconView())->setIcon($profile_icon);
     $profile_title = $profile->getDisplayTitle();
     $header = id(new PHUIHeaderView())->setHeader($user->getFullName())->setSubheader(array($profile_icon, $profile_title))->setImage($picture);
     $actions = $this->buildActionList($user);
     $properties = $this->buildPropertyView($user);
     $properties->setActionList($actions);
     $name = $user->getUsername();
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $nav = $this->getProfileMenu();
     $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE);
     $timeline = $this->buildTransactionTimeline($user, new PhabricatorPeopleTransactionQuery());
     $timeline->setShouldTerminate(true);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Manage'));
     return $this->newPage()->setTitle(array(pht('Manage User'), $user->getUsername()))->setNavigation($nav)->setCrumbs($crumbs)->appendChild(array($object_box, $timeline));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $question = id(new PonderQuestionQuery())->setViewer($viewer)->withIDs(array($id))->needAnswers(true)->needViewerVotes(true)->executeOne();
     if (!$question) {
         return new Aphront404Response();
     }
     $question->attachVotes($viewer->getPHID());
     $question_xactions = $this->buildQuestionTransactions($question);
     $answers = $this->buildAnswers($question->getAnswers());
     $authors = mpull($question->getAnswers(), null, 'getAuthorPHID');
     if (isset($authors[$viewer->getPHID()])) {
         $answer_add_panel = id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->appendChild(pht('You have already answered this question. You can not answer ' . 'twice, but you can edit your existing answer.'));
     } else {
         $answer_add_panel = new PonderAddAnswerView();
         $answer_add_panel->setQuestion($question)->setUser($viewer)->setActionURI('/ponder/answer/add/');
     }
     $header = new PHUIHeaderView();
     $header->setHeader($question->getTitle());
     $header->setUser($viewer);
     $header->setPolicyObject($question);
     if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) {
         $header->setStatus('fa-square-o', 'bluegrey', pht('Open'));
     } else {
         $header->setStatus('fa-check-square-o', 'dark', pht('Closed'));
     }
     $actions = $this->buildActionListView($question);
     $properties = $this->buildPropertyListView($question, $actions);
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
     $crumbs->addTextCrumb('Q' . $id, '/Q' . $id);
     $ponder_view = phutil_tag('div', array('class' => 'ponder-question-view'), array($crumbs, $object_box, $question_xactions, $answers, $answer_add_panel));
     return $this->buildApplicationPage(array($ponder_view), array('title' => 'Q' . $question->getID() . ' ' . $question->getTitle(), 'pageObjects' => array_merge(array($question->getPHID()), mpull($question->getAnswers(), 'getPHID'))));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $response = $this->loadDiffusionContextForEdit();
     if ($response) {
         return $response;
     }
     $viewer = $this->getViewer();
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     if (!$repository->supportsStaging()) {
         return new Aphront404Response();
     }
     $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
     $v_area = $repository->getHumanReadableDetail('staging-uri');
     if ($request->isFormPost()) {
         $v_area = $request->getStr('area');
         $xactions = array();
         $template = id(new PhabricatorRepositoryTransaction());
         $type_encoding = PhabricatorRepositoryTransaction::TYPE_STAGING_URI;
         $xactions[] = id(clone $template)->setTransactionType($type_encoding)->setNewValue($v_area);
         id(new PhabricatorRepositoryEditor())->setContinueOnNoEffect(true)->setContentSourceFromRequest($request)->setActor($viewer)->applyTransactions($repository, $xactions);
         return id(new AphrontRedirectResponse())->setURI($edit_uri);
     }
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Edit Staging'));
     $title = pht('Edit %s', $repository->getName());
     $form = id(new AphrontFormView())->setUser($viewer)->appendRemarkupInstructions(pht("To make it easier to run integration tests and builds on code " . "under review, you can configure a **Staging Area**. When `arc` " . "creates a diff, it will push a copy of the changes to the " . "configured staging area with a corresponding tag." . "\n\n" . "IMPORTANT: This feature is new, experimental, and not supported. " . "Use it at your own risk."))->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Staging Area URI'))->setName('area')->setValue($v_area))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save'))->addCancelButton($edit_uri));
     $object_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setForm($form);
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($object_box);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $pager = new PHUIPagerView();
     $pager->setURI($request->getRequestURI(), 'page');
     $pager->setOffset($request->getInt('page'));
     $query = id(new PhabricatorTokenReceiverQuery());
     $objects = $query->setViewer($viewer)->executeWithOffsetPager($pager);
     $counts = $query->getTokenCounts();
     $handles = array();
     $phids = array();
     if ($counts) {
         $phids = mpull($objects, 'getPHID');
         $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs($phids)->execute();
     }
     $list = new PHUIObjectItemListView();
     foreach ($phids as $object) {
         $count = idx($counts, $object, 0);
         $item = id(new PHUIObjectItemView());
         $handle = $handles[$object];
         $item->setHeader($handle->getFullName());
         $item->setHref($handle->getURI());
         $item->addAttribute(pht('Tokens: %s', $count));
         $list->addItem($item);
     }
     $title = pht('Token Leader Board');
     $box = id(new PHUIObjectBoxView())->setHeaderText($title)->setObjectList($list);
     $nav = $this->buildSideNav();
     $nav->setCrumbs($this->buildApplicationCrumbs()->addTextCrumb($title));
     $nav->selectFilter('leaders/');
     $nav->appendChild($box);
     $nav->appendChild($pager);
     return $this->newPage()->setTitle($title)->appendChild($nav);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $paste = id(new PhabricatorPasteQuery())->setViewer($viewer)->withIDs(array($id))->needContent(true)->executeOne();
     if (!$paste) {
         return new Aphront404Response();
     }
     $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($paste->getFilePHID()))->executeOne();
     if (!$file) {
         return new Aphront400Response();
     }
     $forks = id(new PhabricatorPasteQuery())->setViewer($viewer)->withParentPHIDs(array($paste->getPHID()))->execute();
     $fork_phids = mpull($forks, 'getPHID');
     $header = $this->buildHeaderView($paste);
     $actions = $this->buildActionView($viewer, $paste, $file);
     $properties = $this->buildPropertyView($paste, $fork_phids, $actions);
     $object_box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     $source_code = $this->buildSourceCodeView($paste, null, $this->highlightMap);
     $source_code = id(new PHUIBoxView())->appendChild($source_code)->addMargin(PHUI::MARGIN_LARGE_LEFT)->addMargin(PHUI::MARGIN_LARGE_RIGHT)->addMargin(PHUI::MARGIN_LARGE_TOP);
     $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView())->addTextCrumb('P' . $paste->getID(), '/P' . $paste->getID());
     $timeline = $this->buildTransactionTimeline($paste, new PhabricatorPasteTransactionQuery());
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
     $add_comment_header = $is_serious ? pht('Add Comment') : pht('Eat Paste');
     $draft = PhabricatorDraft::newFromUserAndKey($viewer, $paste->getPHID());
     $add_comment_form = id(new PhabricatorApplicationTransactionCommentView())->setUser($viewer)->setObjectPHID($paste->getPHID())->setDraft($draft)->setHeaderText($add_comment_header)->setAction($this->getApplicationURI('/comment/' . $paste->getID() . '/'))->setSubmitButtonName(pht('Add Comment'));
     return $this->buildApplicationPage(array($crumbs, $object_box, $source_code, $timeline, $add_comment_form), array('title' => $paste->getFullName(), 'pageObjects' => array($paste->getPHID())));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     if ($request->isFormPost()) {
         $log = PhabricatorUserLog::initializeNewLog($viewer, $viewer->getPHID(), PhabricatorUserLog::ACTION_LOGOUT);
         $log->save();
         // Destroy the user's session in the database so logout works even if
         // their cookies have some issues. We'll detect cookie issues when they
         // try to login again and tell them to clear any junk.
         $phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
         if (strlen($phsid)) {
             $session = id(new PhabricatorAuthSessionQuery())->setViewer($viewer)->withSessionKeys(array($phsid))->executeOne();
             if ($session) {
                 $session->delete();
             }
         }
         $request->clearCookie(PhabricatorCookies::COOKIE_SESSION);
         return id(new AphrontRedirectResponse())->setURI('/auth/loggedout/');
     }
     if ($viewer->getPHID()) {
         $dialog = id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Log out of Phabricator?'))->appendChild(pht('Are you sure you want to log out?'))->addSubmitButton(pht('Logout'))->addCancelButton('/');
         return id(new AphrontDialogResponse())->setDialog($dialog);
     }
     return id(new AphrontRedirectResponse())->setURI('/');
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $accounts = id(new PhortuneAccountQuery())->setViewer($viewer)->withMemberPHIDs(array($viewer->getPHID()))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->execute();
     $merchants = id(new PhortuneMerchantQuery())->setViewer($viewer)->withMemberPHIDs(array($viewer->getPHID()))->execute();
     $title = pht('Accounts');
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Accounts'));
     $crumbs->setBorder(true);
     $payment_list = id(new PHUIObjectItemListView())->setUser($viewer)->setNoDataString(pht('You are not a member of any payment accounts. Payment ' . 'accounts are used to make purchases.'));
     foreach ($accounts as $account) {
         $item = id(new PHUIObjectItemView())->setSubhead(pht('Account %d', $account->getID()))->setHeader($account->getName())->setHref($this->getApplicationURI($account->getID() . '/'))->setObject($account)->setIcon('fa-credit-card');
         $payment_list->addItem($item);
     }
     $payment_header = id(new PHUIHeaderView())->setHeader(pht('Payment Accounts'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setHref($this->getApplicationURI('account/edit/'))->setIcon('fa-plus')->setText(pht('Create Account')));
     $payment_box = id(new PHUIObjectBoxView())->setHeader($payment_header)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setObjectList($payment_list);
     $merchant_list = id(new PHUIObjectItemListView())->setUser($viewer)->setNoDataString(pht('You do not control any merchant accounts. Merchant accounts are ' . 'used to receive payments.'));
     foreach ($merchants as $merchant) {
         $item = id(new PHUIObjectItemView())->setSubhead(pht('Merchant %d', $merchant->getID()))->setHeader($merchant->getName())->setHref($this->getApplicationURI('/merchant/' . $merchant->getID() . '/'))->setObject($merchant)->setIcon('fa-bank');
         $merchant_list->addItem($item);
     }
     $merchant_header = id(new PHUIHeaderView())->setHeader(pht('Merchant Accounts'))->addActionLink(id(new PHUIButtonView())->setTag('a')->setHref($this->getApplicationURI('merchant/'))->setIcon('fa-list')->setText(pht('View All Merchants')));
     $merchant_box = id(new PHUIObjectBoxView())->setHeader($merchant_header)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setObjectList($merchant_list);
     $header = id(new PHUIHeaderView())->setHeader(pht('Accounts'));
     $view = id(new PHUITwoColumnView())->setHeader($header)->setFooter(array($payment_box, $merchant_box));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $dashboard_uri = $this->getApplicationURI('view/' . $id . '/');
     // TODO: This UI should drop a lot of capabilities if the user can't
     // edit the dashboard, but we should still let them in for "Install" and
     // "View History".
     $dashboard = id(new PhabricatorDashboardQuery())->setViewer($viewer)->withIDs(array($id))->needPanels(true)->executeOne();
     if (!$dashboard) {
         return new Aphront404Response();
     }
     $can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $dashboard, PhabricatorPolicyCapability::CAN_EDIT);
     $title = $dashboard->getName();
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID()), $dashboard_uri);
     $crumbs->addTextCrumb(pht('Manage'));
     $header = $this->buildHeaderView($dashboard);
     $actions = $this->buildActionView($dashboard);
     $properties = $this->buildPropertyView($dashboard);
     $properties->setActionList($actions);
     $box = id(new PHUIObjectBoxView())->setHeader($header)->addPropertyList($properties);
     if (!$can_edit) {
         $no_edit = pht('You do not have permission to edit this dashboard. If you want to ' . 'make changes, make a copy first.');
         $box->setInfoView(id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->setErrors(array($no_edit)));
     }
     $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine())->setViewer($viewer)->setDashboard($dashboard)->setArrangeMode($can_edit)->renderDashboard();
     return $this->buildApplicationPage(array($crumbs, $box, $rendered_dashboard), array('title' => $title));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $querykey = $request->getURIData('queryKey');
     $controller = id(new PhabricatorApplicationSearchController())->setQueryKey($querykey)->setSearchEngine(new DrydockLogSearchEngine())->setNavigation($this->buildSideNavView());
     return $this->delegateToController($controller);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $this->getViewer();
     $buildable = id(new HarbormasterBuildableQuery())->setViewer($viewer)->withIDs(array($request->getURIData('id')))->needBuildableHandles(true)->needContainerHandles(true)->executeOne();
     if (!$buildable) {
         return new Aphront404Response();
     }
     $id = $buildable->getID();
     // Pull builds and build targets.
     $builds = id(new HarbormasterBuildQuery())->setViewer($viewer)->withBuildablePHIDs(array($buildable->getPHID()))->needBuildTargets(true)->execute();
     list($lint, $unit) = $this->renderLintAndUnit($buildable, $builds);
     $buildable->attachBuilds($builds);
     $object = $buildable->getBuildableObject();
     $build_list = $this->buildBuildList($buildable);
     $title = pht('Buildable %d', $id);
     $header = id(new PHUIHeaderView())->setHeader($title)->setUser($viewer)->setPolicyObject($buildable);
     $box = id(new PHUIObjectBoxView())->setHeader($header);
     $timeline = $this->buildTransactionTimeline($buildable, new HarbormasterBuildableTransactionQuery());
     $timeline->setShouldTerminate(true);
     $actions = $this->buildActionList($buildable);
     $this->buildPropertyLists($box, $buildable, $actions);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($buildable->getMonogram());
     return $this->buildApplicationPage(array($crumbs, $box, $lint, $unit, $build_list, $timeline), array('title' => $title));
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $id = $request->getURIData('id');
     $ssh_key = id(new PhabricatorAuthSSHKeyQuery())->setViewer($viewer)->withIDs(array($id))->executeOne();
     if (!$ssh_key) {
         return new Aphront404Response();
     }
     $this->setSSHKeyObject($ssh_key->getObject());
     $title = pht('SSH Key %d', $ssh_key->getID());
     $curtain = $this->buildCurtain($ssh_key);
     $details = $this->buildPropertySection($ssh_key);
     $header = id(new PHUIHeaderView())->setUser($viewer)->setHeader($ssh_key->getName())->setHeaderIcon('fa-key');
     if ($ssh_key->getIsActive()) {
         $header->setStatus('fa-check', 'bluegrey', pht('Active'));
     } else {
         $header->setStatus('fa-ban', 'dark', pht('Deactivated'));
     }
     $header->addActionLink(id(new PHUIButtonView())->setTag('a')->setText(pht('View Active Keys'))->setHref($ssh_key->getObject()->getSSHPublicKeyManagementURI($viewer))->setIcon('fa-list-ul'));
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     $crumbs->setBorder(true);
     $timeline = $this->buildTransactionTimeline($ssh_key, new PhabricatorAuthSSHKeyTransactionQuery());
     $timeline->setShouldTerminate(true);
     $view = id(new PHUITwoColumnView())->setHeader($header)->setCurtain($curtain)->setMainColumn(array($details, $timeline));
     return $this->newPage()->setTitle($title)->setCrumbs($crumbs)->appendChild($view);
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     $post = id(new PhamePostQuery())->setViewer($viewer)->withIDs(array($request->getURIData('id')))->executeOne();
     if (!$post) {
         return new Aphront404Response();
     }
     $blog = $post->getBlog();
     $crumbs = $this->buildApplicationCrumbs();
     if ($blog) {
         $crumbs->addTextCrumb($blog->getName(), $this->getApplicationURI('blog/view/' . $blog->getID() . '/'));
     } else {
         $crumbs->addTextCrumb(pht('[No Blog]'), null);
     }
     $crumbs->addTextCrumb($post->getTitle(), $this->getApplicationURI('post/view/' . $post->getID() . '/'));
     $crumbs->setBorder(true);
     $actions = $this->renderActions($post, $viewer);
     $properties = $this->renderProperties($post, $viewer);
     $action_button = id(new PHUIButtonView())->setTag('a')->setText(pht('Actions'))->setHref('#')->setIconFont('fa-bars')->addClass('phui-mobile-menu')->setDropdownMenu($actions);
     $header = id(new PHUIHeaderView())->setHeader($post->getTitle())->setUser($viewer)->setPolicyObject($post)->addActionLink($action_button);
     $document = id(new PHUIDocumentViewPro())->setHeader($header)->setPropertyList($properties);
     if ($post->isDraft()) {
         $document->appendChild(id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_NOTICE)->setTitle(pht('Draft Post'))->appendChild(pht('Only you can see this draft until you publish it. ' . 'Use "Preview / Publish" to publish this post.')));
     }
     if (!$post->getBlog()) {
         $document->appendChild(id(new PHUIInfoView())->setSeverity(PHUIInfoView::SEVERITY_WARNING)->setTitle(pht('Not On A Blog'))->appendChild(pht('This post is not associated with a blog (the blog may have ' . 'been deleted). Use "Move Post" to move it to a new blog.')));
     }
     $engine = id(new PhabricatorMarkupEngine())->setViewer($viewer)->addObject($post, PhamePost::MARKUP_FIELD_BODY)->process();
     $document->appendChild(phutil_tag('div', array('class' => 'phabricator-remarkup'), $engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY)));
     $timeline = $this->buildTransactionTimeline($post, id(new PhamePostTransactionQuery())->withTransactionTypes(array(PhabricatorTransactions::TYPE_COMMENT)));
     $timeline = phutil_tag_div('phui-document-view-pro-box', $timeline);
     $add_comment = $this->buildCommentForm($post);
     return $this->newPage()->setTitle($post->getTitle())->addClass('pro-white-background')->setPageObjectPHIDs(array($post->getPHID()))->setCrumbs($crumbs)->appendChild(array($document, $timeline, $add_comment));
 }