本文整理汇总了PHP中urisprintf函数的典型用法代码示例。如果您正苦于以下问题:PHP urisprintf函数的具体用法?PHP urisprintf怎么用?PHP urisprintf使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了urisprintf函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。
示例1: getBuiltinProfilePanels
protected function getBuiltinProfilePanels($object)
{
$viewer = $this->getViewer();
$panels = array();
$panels[] = $this->newPanel()->setBuiltinKey(self::PANEL_PROFILE)->setPanelKey(PhabricatorPeopleDetailsProfilePanel::PANELKEY);
// TODO: Convert this into a proper panel type.
$have_calendar = PhabricatorApplication::isClassInstalledForViewer('PhabricatorCalendarApplication', $viewer);
if ($have_calendar) {
$uri = urisprintf('/p/%s/calendar/', $object->getUsername());
$panels[] = $this->newPanel()->setBuiltinKey('calendar')->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)->setPanelProperty('icon', 'calendar')->setPanelProperty('name', pht('Calendar'))->setPanelProperty('uri', $uri);
}
$have_maniphest = PhabricatorApplication::isClassInstalledForViewer('PhabricatorManiphestApplication', $viewer);
if ($have_maniphest) {
$uri = urisprintf('/maniphest/?statuses=open()&assigned=%s#R', $object->getPHID());
$panels[] = $this->newPanel()->setBuiltinKey('tasks')->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)->setPanelProperty('icon', 'maniphest')->setPanelProperty('name', pht('Open Tasks'))->setPanelProperty('uri', $uri);
}
$have_differential = PhabricatorApplication::isClassInstalledForViewer('PhabricatorDifferentialApplication', $viewer);
if ($have_differential) {
$uri = urisprintf('/differential/?authors=%s#R', $object->getPHID());
$panels[] = $this->newPanel()->setBuiltinKey('revisions')->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)->setPanelProperty('icon', 'differential')->setPanelProperty('name', pht('Revisions'))->setPanelProperty('uri', $uri);
}
$have_diffusion = PhabricatorApplication::isClassInstalledForViewer('PhabricatorDiffusionApplication', $viewer);
if ($have_diffusion) {
$uri = urisprintf('/audit/?authors=%s#R', $object->getPHID());
$panels[] = $this->newPanel()->setBuiltinKey('commits')->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)->setPanelProperty('icon', 'diffusion')->setPanelProperty('name', pht('Commits'))->setPanelProperty('uri', $uri);
}
$panels[] = $this->newPanel()->setBuiltinKey(self::PANEL_MANAGE)->setPanelKey(PhabricatorPeopleManageProfilePanel::PANELKEY);
return $panels;
}
示例2: buildIconNavView
public function buildIconNavView(PhabricatorProject $project)
{
$this->setProject($project);
$viewer = $this->getViewer();
$id = $project->getID();
$picture = $project->getProfileImageURI();
$name = $project->getName();
$columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
if ($columns) {
$board_icon = 'fa-columns';
} else {
$board_icon = 'fa-columns grey';
}
$nav = new AphrontSideNavFilterView();
$nav->setIconNav(true);
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addIcon("profile/{$id}/", $name, null, $picture);
$class = 'PhabricatorManiphestApplication';
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
$phid = $project->getPHID();
$nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
$query_uri = urisprintf('/maniphest/?statuses=open()&projects=%s#R', $phid);
$nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
}
$nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o');
$nav->addIcon("members/{$id}/", pht('Members'), 'fa-group');
$nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil');
return $nav;
}
示例3: getJumpResponse
public static function getJumpResponse(PhabricatorUser $viewer, $jump)
{
$jump = trim($jump);
$help_href = PhabricatorEnv::getDocLink('Jump Nav User Guide');
$patterns = array('/^help/i' => 'uri:' . $help_href, '/^a$/i' => 'uri:/audit/', '/^f$/i' => 'uri:/feed/', '/^d$/i' => 'uri:/differential/', '/^r$/i' => 'uri:/diffusion/', '/^t$/i' => 'uri:/maniphest/', '/^p$/i' => 'uri:/project/', '/^u$/i' => 'uri:/people/', '/^p\\s+(.+)$/i' => 'project', '/^u\\s+(\\S+)$/i' => 'user', '/^task:\\s*(.+)/i' => 'create-task', '/^(?:s|symbol)\\s+(\\S+)/i' => 'find-symbol', '/^r\\s+(.+)$/i' => 'find-repository');
foreach ($patterns as $pattern => $effect) {
$matches = null;
if (preg_match($pattern, $jump, $matches)) {
if (!strncmp($effect, 'uri:', 4)) {
return id(new AphrontRedirectResponse())->setURI(substr($effect, 4));
} else {
switch ($effect) {
case 'user':
return id(new AphrontRedirectResponse())->setURI('/p/' . $matches[1] . '/');
case 'project':
$project = self::findCloselyNamedProject($matches[1]);
if ($project) {
return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
} else {
$jump = $matches[1];
}
break;
case 'find-symbol':
$context = '';
$symbol = $matches[1];
$parts = array();
if (preg_match('/(.*)(?:\\.|::|->)(.*)/', $symbol, $parts)) {
$context = '&context=' . phutil_escape_uri($parts[1]);
$symbol = $parts[2];
}
return id(new AphrontRedirectResponse())->setURI("/diffusion/symbol/{$symbol}/?jump=true{$context}");
case 'find-repository':
$name = $matches[1];
$repositories = id(new PhabricatorRepositoryQuery())->setViewer($viewer)->withNameContains($name)->execute();
if (count($repositories) == 1) {
// Just one match, jump to repository.
$uri = '/diffusion/' . head($repositories)->getCallsign() . '/';
} else {
// More than one match, jump to search.
$uri = urisprintf('/diffusion/?order=name&name=%s', $name);
}
return id(new AphrontRedirectResponse())->setURI($uri);
case 'create-task':
return id(new AphrontRedirectResponse())->setURI('/maniphest/task/create/?title=' . phutil_escape_uri($matches[1]));
default:
throw new Exception("Unknown jump effect '{$effect}'!");
}
}
}
}
// If none of the patterns matched, look for an object by name.
$objects = id(new PhabricatorObjectQuery())->setViewer($viewer)->withNames(array($jump))->execute();
if (count($objects) == 1) {
$handle = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs(mpull($objects, 'getPHID'))->executeOne();
return id(new AphrontRedirectResponse())->setURI($handle->getURI());
}
return null;
}
示例4: buildApplicationCrumbs
protected function buildApplicationCrumbs()
{
$crumbs = parent::buildApplicationCrumbs();
$user = $this->getUser();
if ($user) {
$crumbs->addTextCrumb($user->getUsername(), urisprintf('/p/%s/', $user->getUsername()));
}
return $crumbs;
}
示例5: newNavigationMenuItems
protected function newNavigationMenuItems(PhabricatorProfilePanelConfiguration $config)
{
$user = $config->getProfileObject();
$picture = $user->getProfileImageURI();
$name = $user->getUsername();
$href = urisprintf('/p/%s/', $user->getUsername());
$item = $this->newItem()->setHref($href)->setName($name)->setProfileImage($picture);
return array($item);
}
示例6: getBuiltinProfilePanels
protected function getBuiltinProfilePanels($object)
{
$panels = array();
$panels[] = $this->newPanel()->setBuiltinKey(PhabricatorProject::PANEL_PROFILE)->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY);
$panels[] = $this->newPanel()->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD)->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY);
// TODO: This is temporary.
$uri = urisprintf('/maniphest/?statuses=open()&projects=%s#R', $object->getPHID());
$panels[] = $this->newPanel()->setBuiltinKey('tasks')->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)->setPanelProperty('icon', 'maniphest')->setPanelProperty('name', pht('Open Tasks'))->setPanelProperty('uri', $uri);
$panels[] = $this->newPanel()->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS)->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY);
return $panels;
}
示例7: processAddFactorForm
public function processAddFactorForm(AphrontFormView $form, AphrontRequest $request, PhabricatorUser $user)
{
$totp_token_type = PhabricatorAuthTOTPKeyTemporaryTokenType::TOKENTYPE;
$key = $request->getStr('totpkey');
if (strlen($key)) {
// If the user is providing a key, make sure it's a key we generated.
// This raises the barrier to theoretical attacks where an attacker might
// provide a known key (such attacks are already prevented by CSRF, but
// this is a second barrier to overcome).
// (We store and verify the hash of the key, not the key itself, to limit
// how useful the data in the table is to an attacker.)
$temporary_token = id(new PhabricatorAuthTemporaryTokenQuery())->setViewer($user)->withTokenResources(array($user->getPHID()))->withTokenTypes(array($totp_token_type))->withExpired(false)->withTokenCodes(array(PhabricatorHash::digest($key)))->executeOne();
if (!$temporary_token) {
// If we don't have a matching token, regenerate the key below.
$key = null;
}
}
if (!strlen($key)) {
$key = self::generateNewTOTPKey();
// Mark this key as one we generated, so the user is allowed to submit
// a response for it.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
id(new PhabricatorAuthTemporaryToken())->setTokenResource($user->getPHID())->setTokenType($totp_token_type)->setTokenExpires(time() + phutil_units('1 hour in seconds'))->setTokenCode(PhabricatorHash::digest($key))->save();
unset($unguarded);
}
$code = $request->getStr('totpcode');
$e_code = true;
if ($request->getExists('totp')) {
$okay = self::verifyTOTPCode($user, new PhutilOpaqueEnvelope($key), $code);
if ($okay) {
$config = $this->newConfigForUser($user)->setFactorName(pht('Mobile App (TOTP)'))->setFactorSecret($key);
return $config;
} else {
if (!strlen($code)) {
$e_code = pht('Required');
} else {
$e_code = pht('Invalid');
}
}
}
$form->addHiddenInput('totp', true);
$form->addHiddenInput('totpkey', $key);
$form->appendRemarkupInstructions(pht('First, download an authenticator application on your phone. Two ' . 'applications which work well are **Authy** and **Google ' . 'Authenticator**, but any other TOTP application should also work.'));
$form->appendInstructions(pht('Launch the application on your phone, and add a new entry for ' . 'this Phabricator install. When prompted, scan the QR code or ' . 'manually enter the key shown below into the application.'));
$prod_uri = new PhutilURI(PhabricatorEnv::getProductionURI('/'));
$issuer = $prod_uri->getDomain();
$uri = urisprintf('otpauth://totp/%s:%s?secret=%s&issuer=%s', $issuer, $user->getUsername(), $key, $issuer);
$qrcode = $this->renderQRCode($uri);
$form->appendChild($qrcode);
$form->appendChild(id(new AphrontFormStaticControl())->setLabel(pht('Key'))->setValue(phutil_tag('strong', array(), $key)));
$form->appendInstructions(pht('(If given an option, select that this key is "Time Based", not ' . '"Counter Based".)'));
$form->appendInstructions(pht('After entering the key, the application should display a numeric ' . 'code. Enter that code below to confirm that you have configured ' . 'the authenticator correctly:'));
$form->appendChild(id(new PHUIFormNumberControl())->setLabel(pht('TOTP Code'))->setName('totpcode')->setValue($code)->setError($e_code));
}
示例8: buildPackagesView
private function buildPackagesView(PhabricatorPackagesPublisher $publisher)
{
$viewer = $this->getViewer();
$packages = id(new PhabricatorPackagesPackageQuery())->setViewer($viewer)->withPublisherPHIDs(array($publisher->getPHID()))->setLimit(25)->execute();
$packages_list = id(new PhabricatorPackagesPackageListView())->setViewer($viewer)->setPackages($packages);
$all_href = urisprintf('package/?publisher=%s#R', $publisher->getPHID());
$all_href = $this->getApplicationURI($all_href);
$view_all = id(new PHUIButtonView())->setTag('a')->setIcon('fa-search')->setText(pht('View All'))->setHref($all_href);
$header = id(new PHUIHeaderView())->setHeader(pht('Packages'))->addActionLink($view_all);
$packages_view = id(new PHUIObjectBoxView())->setHeader($header)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setObjectList($packages_list);
return $packages_view;
}
示例9: buildNeedsTriagePanel
private function buildNeedsTriagePanel(array $projects)
{
assert_instances_of($projects, 'PhabricatorProject');
$needs_triage = PhabricatorEnv::getEnvConfig('maniphest.priorities.needs-triage');
if (!$needs_triage) {
return null;
}
$user = $this->getRequest()->getUser();
if (!$user->isLoggedIn()) {
return null;
}
if ($projects) {
$task_query = id(new ManiphestTaskQuery())->setViewer($user)->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())->withPriorities(array($needs_triage))->withEdgeLogicPHIDs(PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, PhabricatorQueryConstraint::OPERATOR_OR, mpull($projects, 'getPHID'))->needProjectPHIDs(true)->setLimit(10);
$tasks = $task_query->execute();
} else {
$tasks = array();
}
if (!$tasks) {
return $this->renderMiniPanel(pht('No "Needs Triage" Tasks'), pht('No tasks in projects you are a member of need triage.'));
}
$title = pht('Needs Triage');
$href = urisprintf('/maniphest/?statuses=open()&priorities=%s&projects=projects(%s)#R', $needs_triage, $user->getPHID());
$panel = new PHUIObjectBoxView();
$panel->setHeader($this->renderSectionHeader($title, $href));
$panel->setObjectList($this->buildTaskListView($tasks));
return $panel;
}
示例10: testurisprintf
public function testurisprintf()
{
$this->assertEqual('x.com?a=huh%3F', urisprintf('x.com?a=%s', 'huh?'));
$this->assertEqual('/a/origin%252Fmaster/z/', urisprintf('/a/%p/z/', 'origin/master'));
$this->assertEqual('y.com?%21&%23', vurisprintf('y.com?%s&%s', array('!', '#')));
}
示例11: buildSprintIconNavView
public function buildSprintIconNavView(PhabricatorProject $project)
{
$viewer = $this->getViewer();
$id = $project->getID();
$picture = $project->getProfileImageURI();
$name = $project->getName();
$enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile');
$phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri');
$phragile_uri = new PhutilURI($phragile_base_uri . $id);
$columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
if ($columns) {
$board_icon = 'fa-columns';
} else {
$board_icon = 'fa-columns grey';
}
$nav = new AphrontSideNavFilterView();
$nav->setIconNav(true);
if ($this->isSprint($project) !== false) {
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addIcon("profile/{$id}/", $name, null, $picture, null);
$nav->addIcon("burn/{$id}/", pht('Burndown'), 'fa-fire', null, null);
if ($enable_phragile) {
$nav->addIcon("sprints/{$id}/", pht('Phragile'), 'fa-pie-chart', null, $phragile_uri);
}
$nav->addIcon("board/{$id}/", pht('Sprint Board'), $board_icon, null, null);
$nav->addIcon('.', pht('Sprint List'), 'fa-bar-chart', null, null);
} else {
$nav->setBaseURI(new PhutilURI($this->getProjectsURI()));
$nav->addIcon("profile/{$id}/", $name, null, $picture);
$nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
}
$class = 'PhabricatorManiphestApplication';
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
$phid = $project->getPHID();
$query_uri = urisprintf('/maniphest/?statuses=open()&projects=%s#R', $phid);
$nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
}
$nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o', null, null);
$nav->addIcon("members/{$id}/", pht('Members'), 'fa-group', null, null);
$nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil', null, null);
return $nav;
}
示例12: renderTasksPage
private function renderTasksPage(PhabricatorProject $project)
{
$user = $this->getRequest()->getUser();
$query = id(new ManiphestTaskQuery())->setViewer($user)->withAnyProjects(array($project->getPHID()))->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)->setLimit(10);
$tasks = $query->execute();
$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);
$phid = $project->getPHID();
$view_uri = urisprintf('/maniphest/?statuses=%s&allProjects=%s#R', implode(',', ManiphestTaskStatus::getOpenStatusConstants()), $phid);
$create_uri = '/maniphest/task/create/?projects=' . $phid;
$icon = id(new PHUIIconView())->setIconFont('fa-list');
$button_view = id(new PHUIButtonView())->setTag('a')->setText(pht('View All'))->setHref($view_uri)->setIcon($icon);
$icon_new = id(new PHUIIconView())->setIconFont('fa-plus');
$button_add = id(new PHUIButtonView())->setTag('a')->setText(pht('New Task'))->setHref($create_uri)->setIcon($icon_new);
$header = id(new PHUIHeaderView())->setHeader(pht('Open Tasks'))->addActionLink($button_add)->addActionLink($button_view);
$content = id(new PHUIObjectBoxView())->setHeader($header)->appendChild($task_list);
return $content;
}
示例13: verifyRemotePermissions
private function verifyRemotePermissions($viewer, $revision, $repository)
{
$github_user = $this->account->getUsername();
$github_repo = $this->findGitHubRepo($repository);
$uri = urisprintf('https://api.github.com/repos/%s/collaborators/%s', $github_repo, $github_user);
$uri = new PhutilURI($uri);
$uri->setQueryParam('access_token', $this->getAccessToken());
list($status, $body, $headers) = id(new HTTPSFuture($uri))->resolve();
// Likely status codes:
// 204 No Content: Has permissions. Token might be too weak.
// 404 Not Found: Not a collaborator.
// 401 Unauthorized: Token is bad/revoked.
$no_permission = $status->getStatusCode() == 404;
if ($no_permission) {
throw new Exception(pht("You don't have permission to push to this repository. " . "Push permissions for this repository are managed on GitHub."));
}
$scopes = BaseHTTPFuture::getHeader($headers, 'X-OAuth-Scopes');
if (strpos($scopes, 'public_repo') === false) {
$provider_key = $this->provider->getProviderKey();
$refresh_token_uri = new PhutilURI("/auth/refresh/{$provider_key}/");
$refresh_token_uri->setQueryParam('scope', 'public_repo');
return id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Stronger token needed'))->appendChild(pht('In order to complete this action, you need a ' . 'stronger GitHub token.'))->setSubmitURI($refresh_token_uri)->addCancelButton('/D' . $revision->getId())->setDisableWorkflowOnSubmit(true)->addSubmitButton(pht('Refresh Account Link'));
}
}
示例14: buildCalendarDayView
private function buildCalendarDayView(PhabricatorUser $user)
{
$viewer = $this->getViewer();
$class = 'PhabricatorCalendarApplication';
if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
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');
$query = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withDateRange($range_start, $range_end)->withInvitedPHIDs(array($user->getPHID()))->withIsCancelled(false);
$statuses = $query->execute();
$phids = mpull($statuses, 'getUserPHID');
$events = array();
foreach ($statuses as $status) {
$viewer_is_invited = $status->getIsUserInvited($user->getPHID());
$can_edit = PhabricatorPolicyFilter::hasCapability($viewer, $status, PhabricatorPolicyCapability::CAN_EDIT);
$event = id(new AphrontCalendarEventView())->setCanEdit($can_edit)->setEventID($status->getID())->setEpochRange($status->getDateFrom(), $status->getDateTo())->setIsAllDay($status->getIsAllDay())->setIcon($status->getIcon())->setViewerIsInvited($viewer_is_invited)->setName($status->getName())->setURI($status->getURI());
$events[] = $event;
}
$events = msort($events, 'getEpochStart');
$day_view = id(new PHUICalendarWeekView())->setViewer($viewer)->setView('week')->setEvents($events)->setWeekLength(3)->render();
$header = id(new PHUIHeaderView())->setHeader(pht('Calendar'))->setHref(urisprintf('/calendar/?invitedPHIDs=%s#R', $user->getPHID()));
$box = id(new PHUIObjectBoxView())->setHeader($header)->appendChild($day_view)->setBackground(PHUIObjectBoxView::GREY);
return $box;
}
示例15: buildIconNavView
public function buildIconNavView(PhabricatorProject $project)
{
$this->setProject($project);
$viewer = $this->getViewer();
$id = $project->getID();
$picture = $project->getProfileImageURI();
$name = $project->getName();
$columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
if ($columns) {
$board_icon = 'fa-columns';
} else {
$board_icon = 'fa-columns grey';
}
$nav = new AphrontSideNavFilterView();
$nav->setIconNav(true);
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$nav->addIcon("profile/{$id}/", $name, null, $picture);
$class = 'PhabricatorManiphestApplication';
if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
$phid = $project->getPHID();
$nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
$query_uri = urisprintf('/maniphest/?statuses=open()&projects=%s#R', $phid);
$nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
}
$nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o');
$nav->addIcon("members/{$id}/", pht('Members'), 'fa-group');
if (false && PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
if ($project->supportsSubprojects()) {
$subprojects_icon = 'fa-sitemap';
} else {
$subprojects_icon = 'fa-sitemap grey';
}
$key = PhabricatorProjectIconSet::getMilestoneIconKey();
$milestones_icon = PhabricatorProjectIconSet::getIconIcon($key);
if (!$project->supportsMilestones()) {
$milestones_icon = "{$milestones_icon} grey";
}
$nav->addIcon("subprojects/{$id}/", pht('Subprojects'), $subprojects_icon);
$nav->addIcon("milestones/{$id}/", pht('Milestones'), $milestones_icon);
}
return $nav;
}