public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $pager = new AphrontPagerView();
     $pager->setOffset($request->getInt('page'));
     $pager->setURI($request->getRequestURI(), 'page');
     $timers = id(new PhabricatorTimer())->loadAllWhere('1 = 1 ORDER BY id DESC LIMIT %d, %d', $pager->getOffset(), $pager->getPageSize() + 1);
     $timers = $pager->sliceResults($timers);
     $phids = mpull($timers, 'getAuthorPHID');
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $rows = array();
     foreach ($timers as $timer) {
         $edit_button = null;
         $delete_button = null;
         if ($user->getIsAdmin() || $user->getPHID() == $timer->getAuthorPHID()) {
             $edit_button = phutil_render_tag('a', array('class' => 'small button grey', 'href' => '/countdown/edit/' . $timer->getID() . '/'), 'Edit');
             $delete_button = javelin_render_tag('a', array('class' => 'small button grey', 'href' => '/countdown/delete/' . $timer->getID() . '/', 'sigil' => 'workflow'), 'Delete');
         }
         $rows[] = array(phutil_escape_html($timer->getID()), $handles[$timer->getAuthorPHID()]->renderLink(), phutil_render_tag('a', array('href' => '/countdown/' . $timer->getID() . '/'), phutil_escape_html($timer->getTitle())), phabricator_format_timestamp($timer->getDatepoint()), $edit_button, $delete_button);
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('ID', 'Author', 'Title', 'End Date', '', ''));
     $table->setColumnClasses(array(null, null, 'wide pri', null, 'action', 'action'));
     $panel = id(new AphrontPanelView())->appendChild($table)->setHeader('Timers')->setCreateButton('Create Timer', '/countdown/edit/')->appendChild($pager);
     return $this->buildStandardPageResponse($panel, array('title' => 'Countdown', 'tab' => 'list'));
 }
 private function renderBasicInformation($project, $profile)
 {
     $blurb = nonempty($profile->getBlurb(), '//Nothing is known about this elusive project.//');
     $engine = PhabricatorMarkupEngine::newProfileMarkupEngine();
     $blurb = $engine->markupText($blurb);
     $affiliations = $project->loadAffiliations();
     $phids = array_merge(array($project->getAuthorPHID()), $project->getSubprojectPHIDs(), mpull($affiliations, 'getUserPHID'));
     $phids = array_unique($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $affiliated = array();
     foreach ($affiliations as $affiliation) {
         $user = $handles[$affiliation->getUserPHID()]->renderLink();
         $role = phutil_escape_html($affiliation->getRole());
         $status = null;
         if ($affiliation->getStatus() == 'former') {
             $role = '<em>Former ' . $role . '</em>';
         }
         $affiliated[] = '<li>' . $user . ' &mdash; ' . $role . $status . '</li>';
     }
     if ($affiliated) {
         $affiliated = '<ul>' . implode("\n", $affiliated) . '</ul>';
     } else {
         $affiliated = '<p><em>No one is affiliated with this project.</em></p>';
     }
     if ($project->getSubprojectPHIDs()) {
         $table = $this->renderSubprojectTable($handles, $project->getSubprojectPHIDs());
         $subproject_list = $table->render();
     } else {
         $subproject_list = '<p><em>There are no projects attached for such specie.</em></p>';
     }
     $timestamp = phabricator_format_timestamp($project->getDateCreated());
     $status = PhabricatorProjectStatus::getNameForStatus($project->getStatus());
     $content = '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">Basic Information</h1>
     <div class="phabricator-profile-info-pane">
       <table class="phabricator-profile-info-table">
         <tr>
           <th>Creator</th>
           <td>' . $handles[$project->getAuthorPHID()]->renderLink() . '</td>
         </tr>
         <tr>
           <th>Status</th>
           <td><strong>' . phutil_escape_html($status) . '</strong></td>
         </tr>
         <tr>
           <th>Created</th>
           <td>' . $timestamp . '</td>
         </tr>
         <tr>
           <th>PHID</th>
           <td>' . phutil_escape_html($project->getPHID()) . '</td>
         </tr>
         <tr>
           <th>Blurb</th>
           <td>' . $blurb . '</td>
         </tr>
       </table>
     </div>
   </div>';
     $content .= '<div class="phabricator-profile-info-group">' . '<h1 class="phabricator-profile-info-header">Resources</h1>' . '<div class="phabricator-profile-info-pane">' . $affiliated . '</div>' . '</div>';
     $content .= '<div class="phabricator-profile-info-group">' . '<h1 class="phabricator-profile-info-header">Subprojects</h1>' . '<div class="phabricator-profile-info-pane">' . $subproject_list . '</div>' . '</div>';
     $query = id(new ManiphestTaskQuery())->withProjects(array($project->getPHID()))->withStatus(ManiphestTaskQuery::STATUS_OPEN)->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)->setLimit(10)->setCalculateRows(true);
     $tasks = $query->execute();
     $count = $query->getRowCount();
     $phids = mpull($tasks, 'getOwnerPHID');
     $phids = array_filter($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $task_views = array();
     foreach ($tasks as $task) {
         $view = id(new ManiphestTaskSummaryView())->setTask($task)->setHandles($handles)->setUser($this->getRequest()->getUser());
         $task_views[] = $view->render();
     }
     if (empty($tasks)) {
         $task_views = '<em>No open tasks.</em>';
     } else {
         $task_views = implode('', $task_views);
     }
     $open = number_format($count);
     $more_link = phutil_render_tag('a', array('href' => '/maniphest/view/all/?projects=' . $project->getPHID()), "View All Open Tasks »");
     $content .= '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">' . "Open Tasks ({$open})" . '</h1>' . '<div class="phabricator-profile-info-pane">' . $task_views . '<div class="phabricator-profile-info-pane-more-link">' . $more_link . '</div>' . '</div>
   </div>';
     return $content;
 }
 private function renderBasicInformation($user, $profile)
 {
     $blurb = nonempty($profile->getBlurb(), '//Nothing is known about this rare specimen.//');
     $engine = PhabricatorMarkupEngine::newProfileMarkupEngine();
     $blurb = $engine->markupText($blurb);
     $content = '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">Basic Information</h1>
     <div class="phabricator-profile-info-pane">
       <table class="phabricator-profile-info-table">
         <tr>
           <th>PHID</th>
           <td>' . phutil_escape_html($user->getPHID()) . '</td>
         </tr>
         <tr>
           <th>User Since</th>
           <td>' . phabricator_format_timestamp($user->getDateCreated()) . '</td>
         </tr>
       </table>
     </div>
   </div>';
     $content .= '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">Flavor Text</h1>
     <div class="phabricator-profile-info-pane">
       <table class="phabricator-profile-info-table">
         <tr>
           <th>Blurb</th>
           <td>' . $blurb . '</td>
         </tr>
       </table>
     </div>
   </div>';
     return $content;
 }
 private function renderRevisionTable(array $revisions, $header, $nodata, array $handles, array $reviewer_map)
 {
     $rows = array();
     foreach ($revisions as $revision) {
         $status = DifferentialRevisionStatus::getNameForRevisionStatus($revision->getStatus());
         $reviewers = idx($reviewer_map, $revision->getID(), array());
         if ($reviewers) {
             $first = reset($reviewers);
             if (count($reviewers) > 1) {
                 $suffix = ' (+' . (count($reviewers) - 1) . ')';
             } else {
                 $suffix = null;
             }
             $reviewers = $handles[$first]->renderLink() . $suffix;
         } else {
             $reviewers = '<em>None</em>';
         }
         $rows[] = array('D' . $revision->getID(), '<strong>' . phutil_render_tag('a', array('href' => '/D' . $revision->getID()), phutil_escape_html($revision->getTitle())) . '</strong>', phutil_escape_html($status), number_format($revision->getLineCount()), $handles[$revision->getAuthorPHID()]->renderLink(), $reviewers, phabricator_format_timestamp($revision->getDateModified()), phabricator_format_timestamp($revision->getDateCreated()));
     }
     $table = new AphrontTableView($rows);
     $table->setHeaders(array('ID', 'Revision', 'Status', 'Lines', 'Author', 'Reviewers', 'Updated', 'Created'));
     $table->setColumnClasses(array(null, 'wide', null, null, null, null, null, null));
     if ($nodata !== null) {
         $table->setNoDataString($nodata);
     }
     $panel = new AphrontPanelView();
     $panel->setHeader($header);
     $panel->appendChild($table);
     return $panel;
 }
 private function renderBasicInformation($user, $profile)
 {
     $blurb = nonempty($profile->getBlurb(), '//Nothing is known about this rare specimen.//');
     $engine = PhabricatorMarkupEngine::newProfileMarkupEngine();
     $blurb = $engine->markupText($blurb);
     $commit_list = phutil_render_tag('a', array('href' => '/diffusion/author/' . phutil_escape_uri($user->getUsername())), 'Recent Commits');
     $content = '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">Basic Information</h1>
     <div class="phabricator-profile-info-pane">
       <table class="phabricator-profile-info-table">
         <tr>
           <th>PHID</th>
           <td>' . phutil_escape_html($user->getPHID()) . '</td>
         </tr>
         <tr>
           <th>User Since</th>
           <td>' . phabricator_format_timestamp($user->getDateCreated()) . '</td>
         </tr>
       </table>
     </div>
   </div>';
     $content .= '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">Flavor Text</h1>
     <div class="phabricator-profile-info-pane">
       <table class="phabricator-profile-info-table">
         <tr>
           <th>Blurb</th>
           <td>' . $blurb . '</td>
         </tr>
       </table>
     </div>
   </div>';
     $content .= '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">Recent Activities</h1>
     <div class="phabricator-profile-info-pane">
       <table class="phabricator-profile-info-table">
         <tr>
           <th>Commits</th>
           <td>' . $commit_list . '</td>
         </tr>
       </table>
     </div>
   </div>';
     return $content;
 }
 private function processGithubRequest()
 {
     $request = $this->getRequest();
     $repository = $this->repository;
     $repository_id = $repository->getID();
     $token = $repository->getDetail('github-token');
     $path = '/github-post-receive/' . $repository_id . '/' . $token . '/';
     $post_uri = PhabricatorEnv::getURI($path);
     $gitform = new AphrontFormLayoutView();
     $gitform->setBackgroundShading(true)->setPadded(true)->appendChild('<p class="aphront-form-instructions">You can configure GitHub to ' . 'notify Phabricator after changes are pushed. Log into GitHub, go ' . 'to "Admin" &rarr; "Service Hooks" &rarr; "Post-Receive URLs", and ' . 'add this URL to the list. Obviously, this will only work if your ' . 'Phabricator installation is accessible from the internet.</p>')->appendChild('<p class="aphront-form-instructions"> If things are working ' . 'properly, push notifications should appear below once you make some ' . 'commits.</p>')->appendChild(id(new AphrontFormTextControl())->setLabel('URL')->setCaption('Set this as a GitHub "Post-Receive URL".')->setValue($post_uri))->appendChild('<br /><br />')->appendChild('<h1>Recent Commit Notifications</h1>');
     $notifications = id(new PhabricatorRepositoryGitHubNotification())->loadAllWhere('repositoryPHID = %s ORDER BY id DESC limit 10', $repository->getPHID());
     $rows = array();
     foreach ($notifications as $notification) {
         $rows[] = array(phutil_escape_html($notification->getRemoteAddress()), phabricator_format_timestamp($notification->getDateCreated()), $notification->getPayload() ? phutil_escape_html(substr($notification->getPayload(), 0, 32) . '...') : 'Empty');
     }
     $notification_table = new AphrontTableView($rows);
     $notification_table->setHeaders(array('Remote Address', 'Received', 'Payload'));
     $notification_table->setColumnClasses(array(null, null, 'wide'));
     $notification_table->setNoDataString('Phabricator has not yet received any commit notifications for this ' . 'repository from GitHub.');
     $gitform->appendChild($notification_table);
     $github = new AphrontPanelView();
     $github->setHeader('GitHub Integration');
     $github->appendChild($gitform);
     $github->setWidth(AphrontPanelView::WIDTH_FORM);
     $nav = $this->sideNav;
     $nav->appendChild($github);
     return $this->buildStandardPageResponse($nav, array('title' => 'Repository Github Integration'));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $provider = $this->provider;
     $notice = null;
     $provider_name = $provider->getProviderName();
     $provider_key = $provider->getProviderKey();
     $oauth_info = id(new PhabricatorUserOAuthInfo())->loadOneWhere('userID = %d AND oauthProvider = %s', $user->getID(), $provider->getProviderKey());
     $form = new AphrontFormView();
     $form->setUser($user);
     $forms = array();
     $forms[] = $form;
     if (!$oauth_info) {
         $form->appendChild('<p class="aphront-form-instructions">There is currently no ' . $provider_name . ' account linked to your Phabricator account. You ' . 'can link an account, which will allow you to use it to log into ' . 'Phabricator.</p>');
         switch ($provider_key) {
             case PhabricatorOAuthProvider::PROVIDER_GITHUB:
                 $form->appendChild('<p class="aphront-form-instructions">Additionally, you must ' . 'link your Github account before Phabricator can access any ' . 'information about hosted repositories.</p>');
                 break;
         }
         $auth_uri = $provider->getAuthURI();
         $client_id = $provider->getClientID();
         $redirect_uri = $provider->getRedirectURI();
         $form->setAction($auth_uri)->setMethod('GET')->addHiddenInput('redirect_uri', $redirect_uri)->addHiddenInput('client_id', $client_id)->appendChild(id(new AphrontFormSubmitControl())->setValue('Link ' . $provider_name . " Account »"));
     } else {
         $form->appendChild('<p class="aphront-form-instructions">Your account is linked with ' . 'a ' . $provider_name . ' account. You may use your ' . $provider_name . ' ' . 'credentials to log into Phabricator.</p>')->appendChild(id(new AphrontFormStaticControl())->setLabel($provider_name . ' ID')->setValue($oauth_info->getOAuthUID()))->appendChild(id(new AphrontFormStaticControl())->setLabel($provider_name . ' Name')->setValue($oauth_info->getAccountName()))->appendChild(id(new AphrontFormStaticControl())->setLabel($provider_name . ' URI')->setValue($oauth_info->getAccountURI()));
         if (!$provider->isProviderLinkPermanent()) {
             $unlink = 'Unlink ' . $provider_name . ' Account';
             $unlink_form = new AphrontFormView();
             $unlink_form->setUser($user)->appendChild('<p class="aphront-form-instructions">You may unlink this account ' . 'from your ' . $provider_name . ' account. This will prevent you from ' . 'logging in with your ' . $provider_name . ' credentials.</p>')->appendChild(id(new AphrontFormSubmitControl())->addCancelButton('/oauth/' . $provider_key . '/unlink/', $unlink));
             $forms['Unlink Account'] = $unlink_form;
         }
         $expires = $oauth_info->getTokenExpires();
         if ($expires) {
             if ($expires <= time()) {
                 $expires = "Expired";
             } else {
                 $expires = phabricator_format_timestamp($expires);
             }
         } else {
             $expires = 'No Information Available';
         }
         $scope = $oauth_info->getTokenScope();
         if (!$scope) {
             $scope = 'No Information Available';
         }
         $status = $oauth_info->getTokenStatus();
         $status = PhabricatorUserOAuthInfo::getReadableTokenStatus($status);
         $token_form = new AphrontFormView();
         $token_form->setUser($user)->appendChild('<p class="aphront-from-instructions">insert rap about tokens</p>')->appendChild(id(new AphrontFormStaticControl())->setLabel('Token Status')->setValue($status))->appendChild(id(new AphrontFormStaticControl())->setLabel('Expires')->setValue($expires))->appendChild(id(new AphrontFormStaticControl())->setLabel('Scope')->setValue($scope));
         $forms['Account Token Information'] = $token_form;
     }
     $panel = new AphrontPanelView();
     $panel->setHeader($provider_name . ' Account Settings');
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
     foreach ($forms as $name => $form) {
         if ($name) {
             $panel->appendChild('<br /><br /><h1>' . $name . '</h1>');
         }
         $panel->appendChild($form);
     }
     return id(new AphrontNullView())->appendChild(array($notice, $panel));
 }
 public function render()
 {
     require_celerity_resource('differential-core-view-css');
     require_celerity_resource('differential-revision-history-css');
     $data = array(array('name' => 'Base', 'id' => null, 'desc' => 'Base', 'age' => null, 'obj' => null));
     $seq = 0;
     foreach ($this->diffs as $diff) {
         $data[] = array('name' => 'Diff ' . ++$seq, 'id' => $diff->getID(), 'desc' => $diff->getDescription(), 'age' => $diff->getDateCreated(), 'obj' => $diff);
     }
     $max_id = $diff->getID();
     $idx = 0;
     $rows = array();
     $disable = false;
     $radios = array();
     $last_base = null;
     foreach ($data as $row) {
         $name = phutil_escape_html($row['name']);
         $id = phutil_escape_html($row['id']);
         $old_class = null;
         $new_class = null;
         if ($id) {
             $new_checked = $this->selectedDiffID == $id;
             $new = javelin_render_tag('input', array('type' => 'radio', 'name' => 'id', 'value' => $id, 'checked' => $new_checked ? 'checked' : null, 'sigil' => 'differential-new-radio'));
             if ($new_checked) {
                 $new_class = " revhistory-new-now";
                 $disable = true;
             }
         } else {
             $new = null;
         }
         if ($max_id != $id) {
             $uniq = celerity_generate_unique_node_id();
             $old_checked = $this->selectedVersusDiffID == $id;
             $old = phutil_render_tag('input', array('type' => 'radio', 'name' => 'vs', 'value' => $id, 'id' => $uniq, 'checked' => $old_checked ? 'checked' : null, 'disabled' => $disable ? 'disabled' : null));
             $radios[] = $uniq;
             if ($old_checked) {
                 $old_class = " revhistory-old-now";
             }
         } else {
             $old = null;
         }
         $desc = $row['desc'];
         if ($row['age']) {
             $age = phabricator_format_timestamp($row['age']);
         } else {
             $age = null;
         }
         if (++$idx % 2) {
             $class = ' class="alt"';
         } else {
             $class = null;
         }
         if ($row['obj']) {
             $lint = self::renderDiffLintStar($row['obj']);
             $unit = self::renderDiffUnitStar($row['obj']);
         } else {
             $lint = null;
             $unit = null;
         }
         $base = $this->renderBaseRevision($diff);
         if ($last_base !== null && $base !== $last_base) {
             // TODO: Render some kind of notice about rebases.
         }
         $last_base = $base;
         $rows[] = '<tr' . $class . '>' . '<td class="revhistory-name">' . $name . '</td>' . '<td class="revhistory-id">' . $id . '</td>' . '<td class="revhistory-base">' . phutil_escape_html($base) . '</td>' . '<td class="revhistory-desc">' . phutil_escape_html($desc) . '</td>' . '<td class="revhistory-age">' . $age . '</td>' . '<td class="revhistory-star">' . $lint . '</td>' . '<td class="revhistory-star">' . $unit . '</td>' . '<td class="revhistory-old' . $old_class . '">' . $old . '</td>' . '<td class="revhistory-new' . $new_class . '">' . $new . '</td>' . '</tr>';
     }
     Javelin::initBehavior('differential-diff-radios', array('radios' => $radios));
     $options = array('ignore-all' => 'Ignore Most', 'ignore-trailing' => 'Ignore Trailing', 'show-all' => 'Show All');
     $select = '<select name="whitespace">';
     foreach ($options as $value => $label) {
         $select .= phutil_render_tag('option', array('value' => $value, 'selected' => $value == $this->selectedWhitespace ? 'selected' : null), phutil_escape_html($label));
     }
     $select .= '</select>';
     return '<div class="differential-revision-history differential-panel">' . '<h1>Revision Update History</h1>' . '<form>' . '<table class="differential-revision-history-table">' . '<tr>' . '<th>Diff</th>' . '<th>ID</th>' . '<th>Base</th>' . '<th>Description</th>' . '<th>Created</th>' . '<th>Lint</th>' . '<th>Unit</th>' . '</tr>' . implode("\n", $rows) . '<tr>' . '<td colspan="8" class="diff-differ-submit">' . '<label>Whitespace Changes: ' . $select . '</label>' . '<button>Show Diff</button>' . '</td>' . '</tr>' . '</table>' . '</form>' . '</div>';
 }