1
0
Fork 0
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:
epriestley 2016-01-12 10:27:39 -08:00
parent 1eab16c395
commit 7bde92b9c9
21 changed files with 664 additions and 63 deletions

View file

@ -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',

View file

@ -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;
}

View file

@ -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() {

View file

@ -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);

View file

@ -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'));

View file

@ -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'));

View file

@ -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'));

View file

@ -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();

View file

@ -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'));

View file

@ -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,
);
}
}

View file

@ -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,
);
}
}

View file

@ -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,
);
}
}

View file

@ -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;
}
}

View 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.'));
}
}
}

View file

@ -0,0 +1,7 @@
<?php
interface PhabricatorProfilePanelInterface {
public function getBuiltinProfilePanels();
}

View file

@ -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());
}
}
}

View file

@ -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,
);
}
}

View file

@ -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();
}
}

View file

@ -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';
}
}

View file

@ -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,
),
);
}
}

View file

@ -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;
}
}