getViewer(); $username = $request->getURIData('username'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withUsernames(array($username)) ->needProfileImage(true) ->needAvailability(true) ->executeOne(); if (!$user) { return new Aphront404Response(); } $this->setUser($user); $header = $this->buildProfileHeader(); $properties = $this->buildPropertyView($user); $name = $user->getUsername(); $feed = $this->buildPeopleFeed($user, $viewer); $view_all = id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-list-ul') ->setText(pht('View All')) ->setHref('/feed/?userPHIDs='.$user->getPHID()); $feed_header = id(new PHUIHeaderView()) ->setHeader(pht('Recent Activity')) ->addActionLink($view_all); $feed = id(new PHUIObjectBoxView()) ->setHeader($feed_header) ->addClass('project-view-feed') ->appendChild($feed); $projects = $this->buildProjectsView($user); $calendar = $this->buildCalendarDayView($user); $home = id(new PHUITwoColumnView()) ->setHeader($header) ->addClass('project-view-home') ->addClass('project-view-people-home') ->setMainColumn( array( $properties, $feed, )) ->setSideColumn( array( $projects, $calendar, )); $navigation = $this->newNavigation( $user, PhabricatorPeopleProfileMenuEngine::ITEM_PROFILE); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); return $this->newPage() ->setTitle($user->getUsername()) ->setNavigation($navigation) ->setCrumbs($crumbs) ->setPageObjectPHIDs( array( $user->getPHID(), )) ->appendChild( array( $home, )); } /** * @return PHUIObjectBoxView|null */ private function buildPropertyView( PhabricatorUser $user) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setViewer($viewer) ->setObject($user); $field_list = PhabricatorCustomField::getObjectFields( $user, PhabricatorCustomField::ROLE_VIEW); $field_list->appendFieldsToPropertyList($user, $viewer, $view); if (!$view->hasAnyProperties()) { return null; } $header = id(new PHUIHeaderView()) ->setHeader(pht('User Details')); $view = id(new PHUIObjectBoxView()) ->appendChild($view) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addClass('project-view-properties'); return $view; } /** * @return PHUIObjectBoxView */ private function buildProjectsView( PhabricatorUser $user) { $viewer = $this->getViewer(); $projects = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withMemberPHIDs(array($user->getPHID())) ->needImages(true) ->withStatuses( array( PhabricatorProjectStatus::STATUS_ACTIVE, )) ->execute(); $header = id(new PHUIHeaderView()) ->setHeader(pht('Projects')); if (!empty($projects)) { $limit = 5; $render_phids = array_slice($projects, 0, $limit); $list = id(new PhabricatorProjectListView()) ->setViewer($viewer) ->setProjects($render_phids); $header_text = pht( 'Projects (%s)', phutil_count($projects)); $header = id(new PHUIHeaderView()) ->setHeader($header_text) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-list-ul') ->setText(pht('View All')) ->setHref('/project/?member='.$user->getPHID().'#R')); } else { $list = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) ->appendChild(pht('User is not a member of any projects.')); } $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->appendChild($list) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); return $box; } /** * @return PHUIObjectBoxView|null */ private function buildCalendarDayView(PhabricatorUser $user) { $viewer = $this->getViewer(); $class = PhabricatorCalendarApplication::class; if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { return null; } // Don't show calendar information for disabled users, since it's probably // not useful or accurate and may be misleading. if ($user->getIsDisabled()) { return null; } $midnight = PhabricatorTime::getTodayMidnightDateTime($viewer); $week_end = clone $midnight; $week_end = $week_end->modify('+3 days'); $range_start = $midnight->format('U'); $range_end = $week_end->format('U'); $events = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) ->withDateRange($range_start, $range_end) ->withInvitedPHIDs(array($user->getPHID())) ->withIsCancelled(false) ->needRSVPs(array($viewer->getPHID())) ->execute(); $event_views = array(); foreach ($events as $event) { $viewer_is_invited = $event->isRSVPInvited($viewer->getPHID()); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $event, PhabricatorPolicyCapability::CAN_EDIT); $epoch_min = $event->getStartDateTimeEpoch(); $epoch_max = $event->getEndDateTimeEpoch(); $event_view = id(new AphrontCalendarEventView()) ->setCanEdit($can_edit) ->setEventID($event->getID()) ->setEpochRange($epoch_min, $epoch_max) ->setIsAllDay($event->getIsAllDay()) ->setIcon($event->getIcon()) ->setViewerIsInvited($viewer_is_invited) ->setName($event->getName()) ->setDatetimeSummary($event->renderEventDate($viewer, true)) ->setURI($event->getURI()); $event_views[] = $event_view; } $event_views = msort($event_views, 'getEpochStart'); $day_view = id(new PHUICalendarWeekView()) ->setViewer($viewer) ->setView('week') ->setEvents($event_views) ->setWeekLength(3) ->render(); $header = id(new PHUIHeaderView()) ->setHeader(pht('Calendar')) ->setHref( urisprintf( '/calendar/?invited=%s#R', $user->getUsername())); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->appendChild($day_view) ->addClass('calendar-profile-box') ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); return $box; } private function buildPeopleFeed( PhabricatorUser $user, $viewer) { $query = id(new PhabricatorFeedQuery()) ->setViewer($viewer) ->withFilterPHIDs(array($user->getPHID())) ->setLimit(100) ->setReturnPartialResultsOnOverheat(true); $stories = $query->execute(); $overheated_view = null; $is_overheated = $query->getIsOverheated(); if ($is_overheated) { $overheated_message = PhabricatorApplicationSearchController::newOverheatedError( (bool)$stories); $overheated_view = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setTitle(pht('Query Overheated')) ->setErrors( array( $overheated_message, )); } $builder = new PhabricatorFeedBuilder($stories); $builder->setUser($viewer); $builder->setShowHovercards(true); $builder->setNoDataString(pht('To begin on such a grand journey, '. 'requires but just a single step.')); $view = $builder->buildView(); return array( $overheated_view, $view->render(), ); } }