mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-18 18:51:12 +01:00
Begin modularizing profile panel/link construction
Summary: Ref T10054. This has no product impact, but prepares us for customizable side nav on "profiles" (today, projects; probably users some day; and maybe other stuff down the road). Test Plan: Clicked all links on a profile, everything was exactly the same as before. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15007
This commit is contained in:
parent
1eab16c395
commit
7bde92b9c9
21 changed files with 664 additions and 63 deletions
|
@ -2419,6 +2419,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorLegalpadDocumentPHIDType' => 'applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php',
|
||||
'PhabricatorLegalpadSignaturePolicyRule' => 'applications/legalpad/policyrule/PhabricatorLegalpadSignaturePolicyRule.php',
|
||||
'PhabricatorLibraryTestCase' => '__tests__/PhabricatorLibraryTestCase.php',
|
||||
'PhabricatorLinkProfilePanel' => 'applications/search/profilepanel/PhabricatorLinkProfilePanel.php',
|
||||
'PhabricatorLipsumArtist' => 'applications/lipsum/image/PhabricatorLipsumArtist.php',
|
||||
'PhabricatorLipsumGenerateWorkflow' => 'applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php',
|
||||
'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php',
|
||||
|
@ -2826,6 +2827,13 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php',
|
||||
'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php',
|
||||
'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php',
|
||||
'PhabricatorProfilePanel' => 'applications/search/profilepanel/PhabricatorProfilePanel.php',
|
||||
'PhabricatorProfilePanelConfiguration' => 'applications/search/storage/PhabricatorProfilePanelConfiguration.php',
|
||||
'PhabricatorProfilePanelConfigurationQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationQuery.php',
|
||||
'PhabricatorProfilePanelConfigurationTransaction' => 'applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php',
|
||||
'PhabricatorProfilePanelEngine' => 'applications/search/engine/PhabricatorProfilePanelEngine.php',
|
||||
'PhabricatorProfilePanelInterface' => 'applications/search/interface/PhabricatorProfilePanelInterface.php',
|
||||
'PhabricatorProfilePanelPHIDType' => 'applications/search/phidtype/PhabricatorProfilePanelPHIDType.php',
|
||||
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
|
||||
'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php',
|
||||
'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php',
|
||||
|
@ -2856,6 +2864,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php',
|
||||
'PhabricatorProjectDatasource' => 'applications/project/typeahead/PhabricatorProjectDatasource.php',
|
||||
'PhabricatorProjectDescriptionField' => 'applications/project/customfield/PhabricatorProjectDescriptionField.php',
|
||||
'PhabricatorProjectDetailsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php',
|
||||
'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php',
|
||||
'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php',
|
||||
'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php',
|
||||
|
@ -2877,6 +2886,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectMembersDatasource' => 'applications/project/typeahead/PhabricatorProjectMembersDatasource.php',
|
||||
'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php',
|
||||
'PhabricatorProjectMembersPolicyRule' => 'applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php',
|
||||
'PhabricatorProjectMembersProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php',
|
||||
'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php',
|
||||
'PhabricatorProjectMilestonesController' => 'applications/project/controller/PhabricatorProjectMilestonesController.php',
|
||||
'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php',
|
||||
|
@ -2909,6 +2919,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php',
|
||||
'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php',
|
||||
'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php',
|
||||
'PhabricatorProjectWorkboardProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php',
|
||||
'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php',
|
||||
'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php',
|
||||
'PhabricatorProjectsFulltextEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsFulltextEngineExtension.php',
|
||||
|
@ -6700,6 +6711,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorLegalpadDocumentPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorLegalpadSignaturePolicyRule' => 'PhabricatorPolicyRule',
|
||||
'PhabricatorLibraryTestCase' => 'PhutilLibraryTestCase',
|
||||
'PhabricatorLinkProfilePanel' => 'PhabricatorProfilePanel',
|
||||
'PhabricatorLipsumArtist' => 'Phobject',
|
||||
'PhabricatorLipsumGenerateWorkflow' => 'PhabricatorLipsumManagementWorkflow',
|
||||
'PhabricatorLipsumManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
|
@ -7171,6 +7183,16 @@ phutil_register_library_map(array(
|
|||
),
|
||||
'PhabricatorPolicyType' => 'PhabricatorPolicyConstants',
|
||||
'PhabricatorPonderApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorProfilePanel' => 'Phobject',
|
||||
'PhabricatorProfilePanelConfiguration' => array(
|
||||
'PhabricatorSearchDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
),
|
||||
'PhabricatorProfilePanelConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorProfilePanelConfigurationTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'PhabricatorProfilePanelEngine' => 'Phobject',
|
||||
'PhabricatorProfilePanelPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorProject' => array(
|
||||
'PhabricatorProjectDAO',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
|
@ -7182,6 +7204,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorFulltextInterface',
|
||||
'PhabricatorConduitResultInterface',
|
||||
'PhabricatorProfilePanelInterface',
|
||||
),
|
||||
'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction',
|
||||
'PhabricatorProjectApplication' => 'PhabricatorApplication',
|
||||
|
@ -7223,6 +7246,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorProjectDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorProjectDescriptionField' => 'PhabricatorProjectStandardCustomField',
|
||||
'PhabricatorProjectDetailsProfilePanel' => 'PhabricatorProfilePanel',
|
||||
'PhabricatorProjectEditController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController',
|
||||
|
@ -7243,6 +7267,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule',
|
||||
'PhabricatorProjectMembersProfilePanel' => 'PhabricatorProfilePanel',
|
||||
'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectMilestonesController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectMoveController' => 'PhabricatorProjectController',
|
||||
|
@ -7278,6 +7303,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'PhabricatorProjectViewController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectWatchController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel',
|
||||
'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||
'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField',
|
||||
'PhabricatorProjectsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||
|
|
|
@ -6,7 +6,7 @@ abstract class PhabricatorProjectBoardController
|
|||
public function buildIconNavView(PhabricatorProject $project) {
|
||||
$id = $project->getID();
|
||||
$nav = parent::buildIconNavView($project);
|
||||
$nav->selectFilter("board/{$id}/");
|
||||
$nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD);
|
||||
$nav->addClass('project-board-nav');
|
||||
return $nav;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@ abstract class PhabricatorProjectController extends PhabricatorController {
|
|||
public function buildSideNavView($for_app = false) {
|
||||
$project = $this->getProject();
|
||||
|
||||
|
||||
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
||||
|
@ -115,65 +117,13 @@ abstract class PhabricatorProjectController extends PhabricatorController {
|
|||
}
|
||||
|
||||
public function buildIconNavView(PhabricatorProject $project) {
|
||||
$this->setProject($project);
|
||||
$viewer = $this->getViewer();
|
||||
$id = $project->getID();
|
||||
$picture = $project->getProfileImageURI();
|
||||
$name = $project->getName();
|
||||
|
||||
$columns = id(new PhabricatorProjectColumnQuery())
|
||||
$engine = id(new PhabricatorProfilePanelEngine())
|
||||
->setViewer($viewer)
|
||||
->withProjectPHIDs(array($project->getPHID()))
|
||||
->execute();
|
||||
if ($columns) {
|
||||
$board_icon = 'fa-columns';
|
||||
} else {
|
||||
$board_icon = 'fa-columns grey';
|
||||
}
|
||||
->setProfileObject($project);
|
||||
|
||||
$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;
|
||||
return $engine->buildNavigation();
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
|
|
|
@ -281,7 +281,7 @@ final class PhabricatorProjectEditPictureController
|
|||
->setForm($upload_form);
|
||||
|
||||
$nav = $this->buildIconNavView($project);
|
||||
$nav->selectFilter("edit/{$id}/");
|
||||
$nav->selectFilter(PhabricatorProject::PANEL_PROFILE);
|
||||
$nav->appendChild($form_box);
|
||||
$nav->appendChild($upload_box);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ final class PhabricatorProjectFeedController
|
|||
->appendChild($feed);
|
||||
|
||||
$nav = $this->buildIconNavView($project);
|
||||
$nav->selectFilter("feed/{$id}/");
|
||||
$nav->selectFilter('feed');
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Feed'));
|
||||
|
|
|
@ -96,7 +96,7 @@ final class PhabricatorProjectMembersEditController
|
|||
$member_list = $this->renderMemberList($project, $handles);
|
||||
|
||||
$nav = $this->buildIconNavView($project);
|
||||
$nav->selectFilter("members/{$id}/");
|
||||
$nav->selectFilter(PhabricatorProject::PANEL_MEMBERS);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Members'));
|
||||
|
|
|
@ -77,7 +77,7 @@ final class PhabricatorProjectMilestonesController
|
|||
->renderList());
|
||||
|
||||
$nav = $this->buildIconNavView($project);
|
||||
$nav->selectFilter("milestones/{$id}/");
|
||||
$nav->selectFilter(PhabricatorProject::PANEL_MILESTONES);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Milestones'));
|
||||
|
|
|
@ -44,7 +44,7 @@ final class PhabricatorProjectProfileController
|
|||
$timeline->setShouldTerminate(true);
|
||||
|
||||
$nav = $this->buildIconNavView($project);
|
||||
$nav->selectFilter("profile/{$id}/");
|
||||
$nav->selectFilter(PhabricatorProject::PANEL_PROFILE);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ final class PhabricatorProjectSubprojectsController
|
|||
->renderList());
|
||||
|
||||
$nav = $this->buildIconNavView($project);
|
||||
$nav->selectFilter("subprojects/{$id}/");
|
||||
$nav->selectFilter(PhabricatorProject::PANEL_SUBPROJECTS);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Subprojects'));
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectDetailsProfilePanel
|
||||
extends PhabricatorProfilePanel {
|
||||
|
||||
const PANELKEY = 'project.details';
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
$project = $config->getProfileObject();
|
||||
|
||||
$id = $project->getID();
|
||||
$picture = $project->getProfileImageURI();
|
||||
$name = $project->getName();
|
||||
|
||||
$href = "/project/profile/{$id}/";
|
||||
|
||||
$item = id(new PHUIListItemView())
|
||||
->setRenderNameAsTooltip(true)
|
||||
->setType(PHUIListItemView::TYPE_ICON_NAV)
|
||||
->setHref($href)
|
||||
->setName($name)
|
||||
->setProfileImage($picture);
|
||||
|
||||
return array(
|
||||
$item,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectMembersProfilePanel
|
||||
extends PhabricatorProfilePanel {
|
||||
|
||||
const PANELKEY = 'project.members';
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
$project = $config->getProfileObject();
|
||||
|
||||
$id = $project->getID();
|
||||
|
||||
$name = pht('Members');
|
||||
$icon = 'fa-group';
|
||||
$href = "/project/members/{$id}/";
|
||||
|
||||
$item = id(new PHUIListItemView())
|
||||
->setRenderNameAsTooltip(true)
|
||||
->setType(PHUIListItemView::TYPE_ICON_NAV)
|
||||
->setHref($href)
|
||||
->setName($name)
|
||||
->setIcon($icon);
|
||||
|
||||
return array(
|
||||
$item,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectWorkboardProfilePanel
|
||||
extends PhabricatorProfilePanel {
|
||||
|
||||
const PANELKEY = 'project.workboard';
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
// Workboards are only available if Maniphest is installed.
|
||||
$class = 'PhabricatorManiphestApplication';
|
||||
if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$project = $config->getProfileObject();
|
||||
|
||||
$columns = id(new PhabricatorProjectColumnQuery())
|
||||
->setViewer($viewer)
|
||||
->withProjectPHIDs(array($project->getPHID()))
|
||||
->execute();
|
||||
if ($columns) {
|
||||
$icon = 'fa-columns';
|
||||
} else {
|
||||
$icon = 'fa-columns grey';
|
||||
}
|
||||
|
||||
$id = $project->getID();
|
||||
$href = "/project/board/{$id}/";
|
||||
$name = pht('Workboard');
|
||||
|
||||
$item = id(new PHUIListItemView())
|
||||
->setRenderNameAsTooltip(true)
|
||||
->setType(PHUIListItemView::TYPE_ICON_NAV)
|
||||
->setHref($href)
|
||||
->setName($name)
|
||||
->setIcon($icon);
|
||||
|
||||
return array(
|
||||
$item,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,8 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
|||
PhabricatorCustomFieldInterface,
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorFulltextInterface,
|
||||
PhabricatorConduitResultInterface {
|
||||
PhabricatorConduitResultInterface,
|
||||
PhabricatorProfilePanelInterface {
|
||||
|
||||
protected $name;
|
||||
protected $status = PhabricatorProjectStatus::STATUS_ACTIVE;
|
||||
|
@ -49,6 +50,12 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
|||
|
||||
const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken';
|
||||
|
||||
const PANEL_PROFILE = 'project.profile';
|
||||
const PANEL_WORKBOARD = 'project.workboard';
|
||||
const PANEL_MEMBERS = 'project.members';
|
||||
const PANEL_MILESTONES = 'project.milestones';
|
||||
const PANEL_SUBPROJECTS = 'project.subprojects';
|
||||
|
||||
public static function initializeNewProject(PhabricatorUser $actor) {
|
||||
$app = id(new PhabricatorApplicationQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
|
@ -644,4 +651,47 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
|||
return array();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorProfilePanelInterface )----------------------------------- */
|
||||
|
||||
|
||||
public function getBuiltinProfilePanels() {
|
||||
$panels = array();
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
->setBuiltinKey(self::PANEL_PROFILE)
|
||||
->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY);
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
->setBuiltinKey(self::PANEL_WORKBOARD)
|
||||
->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY);
|
||||
|
||||
// TODO: This is temporary.
|
||||
$href = urisprintf(
|
||||
'/maniphest/?statuses=open()&projects=%s#R',
|
||||
$this->getPHID());
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
->setBuiltinKey('tasks')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'fa-anchor')
|
||||
->setPanelProperty('name', pht('Open Tasks'))
|
||||
->setPanelProperty('href', $href);
|
||||
|
||||
// TODO: This is temporary.
|
||||
$id = $this->getID();
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
->setBuiltinKey('feed')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'fa-newspaper-o')
|
||||
->setPanelProperty('name', pht('Feed'))
|
||||
->setPanelProperty('href', "/project/feed/{$id}/");
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
->setBuiltinKey(self::PANEL_MEMBERS)
|
||||
->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY);
|
||||
|
||||
return $panels;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
152
src/applications/search/engine/PhabricatorProfilePanelEngine.php
Normal file
152
src/applications/search/engine/PhabricatorProfilePanelEngine.php
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelEngine extends Phobject {
|
||||
|
||||
private $viewer;
|
||||
private $profileObject;
|
||||
private $panels;
|
||||
|
||||
public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getViewer() {
|
||||
return $this->viewer;
|
||||
}
|
||||
|
||||
public function setProfileObject(
|
||||
PhabricatorProfilePanelInterface $profile_object) {
|
||||
$this->profileObject = $profile_object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProfileObject() {
|
||||
return $this->profileObject;
|
||||
}
|
||||
|
||||
public function buildNavigation() {
|
||||
$nav = id(new AphrontSideNavFilterView())
|
||||
->setIconNav(true)
|
||||
->setBaseURI(new PhutilURI('/project/'));
|
||||
|
||||
$panels = $this->getPanels();
|
||||
|
||||
foreach ($panels as $panel) {
|
||||
$items = $panel->buildNavigationMenuItems();
|
||||
foreach ($items as $item) {
|
||||
$this->validateNavigationMenuItem($item);
|
||||
}
|
||||
|
||||
// If the panel produced only a single item which does not otherwise
|
||||
// have a key, try to automatically assign it a reasonable key. This
|
||||
// makes selecting the correct item simpler.
|
||||
|
||||
if (count($items) == 1) {
|
||||
$item = head($items);
|
||||
if ($item->getKey() === null) {
|
||||
$builtin_key = $panel->getBuiltinKey();
|
||||
$panel_phid = $panel->getPHID();
|
||||
if ($builtin_key !== null) {
|
||||
$item->setKey($builtin_key);
|
||||
} else if ($panel_phid !== null) {
|
||||
$item->setKey($panel_phid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($items as $item) {
|
||||
$nav->addMenuItem($item);
|
||||
}
|
||||
}
|
||||
|
||||
$nav->selectFilter(null);
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
private function getPanels() {
|
||||
if ($this->panels === null) {
|
||||
$this->panels = $this->loadPanels();
|
||||
}
|
||||
|
||||
return $this->panels;
|
||||
}
|
||||
|
||||
private function loadPanels() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$panels = $this->loadBuiltinProfilePanels();
|
||||
|
||||
// TODO: Load persisted panels.
|
||||
|
||||
foreach ($panels as $panel) {
|
||||
$impl = $panel->getPanel();
|
||||
|
||||
$impl->setViewer($viewer);
|
||||
}
|
||||
|
||||
return $panels;
|
||||
}
|
||||
|
||||
private function loadBuiltinProfilePanels() {
|
||||
$object = $this->getProfileObject();
|
||||
$builtins = $object->getBuiltinProfilePanels();
|
||||
|
||||
$panels = PhabricatorProfilePanel::getAllPanels();
|
||||
|
||||
$order = 1;
|
||||
$map = array();
|
||||
foreach ($builtins as $builtin) {
|
||||
$builtin_key = $builtin->getBuiltinKey();
|
||||
|
||||
if (!$builtin_key) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Object produced a builtin panel with no builtin panel key! '.
|
||||
'Builtin panels must have a unique key.'));
|
||||
}
|
||||
|
||||
if (isset($map[$builtin_key])) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Object produced two panels with the same builtin key ("%s"). '.
|
||||
'Each panel must have a unique builtin key.',
|
||||
$builtin_key));
|
||||
}
|
||||
|
||||
$panel_key = $builtin->getPanelKey();
|
||||
|
||||
$panel = idx($panels, $panel_key);
|
||||
if (!$panel) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Builtin panel ("%s") specifies a bad panel key ("%s"); there '.
|
||||
'is no corresponding panel implementation available.',
|
||||
$builtin_key,
|
||||
$panel_key));
|
||||
}
|
||||
|
||||
$builtin
|
||||
->attachPanel($panel)
|
||||
->attachProfileObject($object)
|
||||
->setPanelOrder($order);
|
||||
|
||||
$map[$builtin_key] = $builtin;
|
||||
|
||||
$order++;
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
private function validateNavigationMenuItem($item) {
|
||||
if (!($item instanceof PHUIListItemView)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Expected buildNavigationMenuItems() to return a list of '.
|
||||
'PHUIListItemView objects, but got a surprise.'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
interface PhabricatorProfilePanelInterface {
|
||||
|
||||
public function getBuiltinProfilePanels();
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelPHIDType
|
||||
extends PhabricatorPHIDType {
|
||||
|
||||
const TYPECONST = 'PANL';
|
||||
|
||||
public function getTypeName() {
|
||||
return pht('Profile Panel');
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
return new PhabricatorProfilePanelConfiguration();
|
||||
}
|
||||
|
||||
public function getPHIDTypeApplicationClass() {
|
||||
return 'PhabricatorSearchApplication';
|
||||
}
|
||||
|
||||
protected function buildQueryForObjects(
|
||||
PhabricatorObjectQuery $object_query,
|
||||
array $phids) {
|
||||
return id(new PhabricatorProfilePanelConfigurationQuery())
|
||||
->withPHIDs($phids);
|
||||
}
|
||||
|
||||
public function loadHandles(
|
||||
PhabricatorHandleQuery $query,
|
||||
array $handles,
|
||||
array $objects) {
|
||||
|
||||
foreach ($handles as $phid => $handle) {
|
||||
$config = $objects[$phid];
|
||||
|
||||
$handle->setName(pht('Profile Panel'));
|
||||
$handle->setURI($config->getURI());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorLinkProfilePanel
|
||||
extends PhabricatorProfilePanel {
|
||||
|
||||
const PANELKEY = 'link';
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
$icon = $config->getPanelProperty('icon');
|
||||
$name = $config->getPanelProperty('name');
|
||||
$href = $config->getPanelProperty('href');
|
||||
|
||||
$item = id(new PHUIListItemView())
|
||||
->setRenderNameAsTooltip(true)
|
||||
->setType(PHUIListItemView::TYPE_ICON_NAV)
|
||||
->setHref($href)
|
||||
->setName($name)
|
||||
->setIcon($icon);
|
||||
|
||||
return array(
|
||||
$item,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorProfilePanel extends Phobject {
|
||||
|
||||
private $viewer;
|
||||
|
||||
final public function buildNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return $this->newNavigationMenuItems($config);
|
||||
}
|
||||
|
||||
abstract protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config);
|
||||
|
||||
public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getViewer() {
|
||||
return $this->viewer;
|
||||
}
|
||||
|
||||
final public function getPanelKey() {
|
||||
return $this->getPhobjectClassConstant('PANELKEY');
|
||||
}
|
||||
|
||||
final public static function getAllPanels() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getPanelKey')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelConfigurationQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $profileObjectPHIDs;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withProfileObjectPHIDs(array $phids) {
|
||||
$this->profileObjectPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new PhabricatorProfilePanelConfiguration();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->profileObjectPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'profileObjectPHID IN (%Ls)',
|
||||
$this->profileObjectPHIDs);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorSearchApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelConfiguration
|
||||
extends PhabricatorSearchDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
|
||||
protected $profilePHID;
|
||||
protected $panelKey;
|
||||
protected $builtinKey;
|
||||
protected $panelOrder;
|
||||
protected $isDisabled;
|
||||
protected $panelProperties = array();
|
||||
|
||||
private $profileObject = self::ATTACHABLE;
|
||||
private $panel = self::ATTACHABLE;
|
||||
|
||||
public static function initializeNewPanelConfiguration(
|
||||
PhabricatorProfilePanelInterface $profile_object,
|
||||
PhabricatorProfilePanel $panel) {
|
||||
|
||||
return id(new self())
|
||||
->setProfilePHID($profile_object->getPHID())
|
||||
->setPanelKey($panel->getPanelKey())
|
||||
->setIsDisabled(0)
|
||||
->attachPanel($panel)
|
||||
->attachProfileObject($profile_object);
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'panelProperties' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'panelKey' => 'text64',
|
||||
'builtinKey' => 'text64',
|
||||
'panelOrder' => 'uint32',
|
||||
'isDisabled' => 'bool',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_profile' => array(
|
||||
'columns' => array('profilePHID', 'panelOrder'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function attachPanel(PhabricatorProfilePanel $panel) {
|
||||
$this->panel = $panel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPanel() {
|
||||
return $this->assertAttached($this->panel);
|
||||
}
|
||||
|
||||
public function attachProfileObject(
|
||||
PhabricatorProfilePanelInterface $profile_object) {
|
||||
$this->profileObject = $profile_object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProfileObject() {
|
||||
return $this->assertAttached($this->profileObject);
|
||||
}
|
||||
|
||||
public function buildNavigationMenuItems() {
|
||||
return $this->getPanel()->buildNavigationMenuItems($this);
|
||||
}
|
||||
|
||||
public function setPanelProperty($key, $value) {
|
||||
$this->panelProperties[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPanelProperty($key, $default = null) {
|
||||
return idx($this->panelProperties, $key, $default);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return PhabricatorPolicies::getMostOpenPolicy();
|
||||
}
|
||||
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return $this->getProfileObject()->hasAutomaticCapability(
|
||||
$capability,
|
||||
$viewer);
|
||||
}
|
||||
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
|
||||
|
||||
|
||||
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
|
||||
return array(
|
||||
array(
|
||||
$this->getProfileObject(),
|
||||
$capability,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelConfigurationTransaction
|
||||
extends PhabricatorApplicationTransaction {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'search';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return PhabricatorProfilePanelPHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionCommentObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue