id = idx($data, 'id'); $this->page = idx($data, 'page'); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $query = id(new PhabricatorProjectQuery()) ->setViewer($user) ->withIDs(array($this->id)) ->needMembers(true); $project = $query->executeOne(); $this->project = $project; if (!$project) { return new Aphront404Response(); } $profile = $project->loadProfile(); if (!$profile) { $profile = new PhabricatorProjectProfile(); } $picture = $profile->loadProfileImageURI(); $nav_view = $this->buildLocalNavigation($project); $this->page = $nav_view->selectFilter($this->page, 'dashboard'); require_celerity_resource('phabricator-profile-css'); $tasks = $this->renderTasksPage($project, $profile); $query = new PhabricatorFeedQuery(); $query->setFilterPHIDs( array( $project->getPHID(), )); $query->setLimit(50); $query->setViewer($this->getRequest()->getUser()); $stories = $query->execute(); $feed = $this->renderStories($stories); $about = $this->renderAboutPage($project, $profile); $people = $this->renderPeoplePage($project, $profile); $col1 = hsprintf('%s%s', $about, $people); $content = id(new AphrontMultiColumnView()) ->addColumn($col1) ->addColumn($feed) ->setFluidLayout(true); $content = hsprintf( '
%s%s
', $tasks, $content); $header = new PhabricatorProfileHeaderView(); $header->setName($project->getName()); $header->setDescription( phutil_utf8_shorten($profile->getBlurb(), 1024)); $header->setProfilePicture($picture); $action = null; if (!$project->isUserMember($user->getPHID())) { $can_join = PhabricatorPolicyCapability::CAN_JOIN; if (PhabricatorPolicyFilter::hasCapability($user, $project, $can_join)) { $class = 'green'; } else { $class = 'grey disabled'; } $action = phabricator_form( $user, array( 'action' => '/project/update/'.$project->getID().'/join/', 'method' => 'post', ), phutil_tag( 'button', array( 'class' => $class, ), pht('Join Project'))); } else { $action = javelin_tag( 'a', array( 'href' => '/project/update/'.$project->getID().'/leave/', 'sigil' => 'workflow', 'class' => 'grey button', ), pht('Leave Project...')); } $header->addAction($action); $nav_view->appendChild($header); $header->appendChild($content); return $this->buildApplicationPage( $nav_view, array( 'title' => pht('%s Project', $project->getName()), 'device' => true, 'dust' => true, )); } private function renderAboutPage( PhabricatorProject $project, PhabricatorProjectProfile $profile) { $viewer = $this->getRequest()->getUser(); $blurb = $profile->getBlurb(); $blurb = phutil_escape_html_newlines($blurb); $phids = array($project->getAuthorPHID()); $phids = array_unique($phids); $handles = $this->loadViewerHandles($phids); $timestamp = phabricator_datetime($project->getDateCreated(), $viewer); $about = hsprintf( '

%s

%s %s
%s %s
PHID %s
%s %s
', pht('About This Project'), pht('Creator'), $handles[$project->getAuthorPHID()]->renderLink(), pht('Created'), $timestamp, $project->getPHID(), pht('Blurb'), $blurb); return $about; } private function renderPeoplePage( PhabricatorProject $project, PhabricatorProjectProfile $profile) { $member_phids = $project->getMemberPHIDs(); $handles = $this->loadViewerHandles($member_phids); $affiliated = array(); foreach ($handles as $phids => $handle) { $affiliated[] = phutil_tag('li', array(), $handle->renderLink()); } if ($affiliated) { $affiliated = phutil_tag('ul', array(), $affiliated); } else { $affiliated = hsprintf('

%s

', pht( 'No one is affiliated with this project.')); } return hsprintf( '
'. '

%s

'. '
%s
'. '
', pht('People'), $affiliated); } private function renderFeedPage( PhabricatorProject $project, PhabricatorProjectProfile $profile) { $query = new PhabricatorFeedQuery(); $query->setFilterPHIDs(array($project->getPHID())); $query->setViewer($this->getRequest()->getUser()); $query->setLimit(100); $stories = $query->execute(); if (!$stories) { return pht('There are no stories about this project.'); } return $this->renderStories($stories); } private function renderStories(array $stories) { assert_instances_of($stories, 'PhabricatorFeedStory'); $builder = new PhabricatorFeedBuilder($stories); $builder->setUser($this->getRequest()->getUser()); $view = $builder->buildView(); return hsprintf( '
'. '%s'. '
', $view->render()); } private function renderTasksPage( PhabricatorProject $project, PhabricatorProjectProfile $profile) { $user = $this->getRequest()->getUser(); $query = id(new ManiphestTaskQuery()) ->withAnyProjects(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_merge( $phids, array_mergev(mpull($tasks, 'getProjectPHIDs'))); $phids = array_filter($phids); $handles = $this->loadViewerHandles($phids); $task_list = new ManiphestTaskListView(); $task_list->setUser($user); $task_list->setTasks($tasks); $task_list->setHandles($handles); $open = number_format($count); $more_link = phutil_tag( 'a', array( 'href' => '/maniphest/view/all/?projects='.$project->getPHID(), ), pht("View All Open Tasks \xC2\xBB")); $content = hsprintf( '

%s

'. '
'. '%s'. ''. '
', pht('Open Tasks (%s)', $open), $task_list, $more_link); return $content; } public function buildApplicationMenu() { return $this->buildLocalNavigation($this->project)->getMenu(); } }