mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Make "profile menu" configuration mostly work
Summary: Ref T10054. This does a big chunk of the legwork to let users reconfigure profile menus (currently, just project menus). This includes: - Editing builtin items (e.g., you can rename the default items). - Creating new items (for now, only links are available). This does not yet include: - Hiding items. - Reordering items. - Lots of fancy types of items (dashboards, etc). - Any UI changes. - Documentation (does feature: TODO link for documentation). Test Plan: {F1060695} {F1060696} {F1060697} Reviewers: chad Reviewed By: chad Maniphest Tasks: T10054 Differential Revision: https://secure.phabricator.com/D15010
This commit is contained in:
parent
bb6df2e5f3
commit
f24318f308
26 changed files with 999 additions and 39 deletions
13
resources/sql/autopatches/20160113.propanel.1.storage.sql
Normal file
13
resources/sql/autopatches/20160113.propanel.1.storage.sql
Normal file
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE {$NAMESPACE}_search.search_profilepanelconfiguration (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
profilePHID VARBINARY(64) NOT NULL,
|
||||
panelKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
builtinKey VARCHAR(64) COLLATE {$COLLATE_TEXT},
|
||||
panelOrder INT UNSIGNED,
|
||||
visibility VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
panelProperties LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
KEY `key_profile` (profilePHID, panelOrder)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
19
resources/sql/autopatches/20160113.propanel.2.xaction.sql
Normal file
19
resources/sql/autopatches/20160113.propanel.2.xaction.sql
Normal file
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE {$NAMESPACE}_search.search_profilepanelconfigurationtransaction (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
authorPHID VARBINARY(64) NOT NULL,
|
||||
objectPHID VARBINARY(64) NOT NULL,
|
||||
viewPolicy VARBINARY(64) NOT NULL,
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
commentPHID VARBINARY(64) DEFAULT NULL,
|
||||
commentVersion INT UNSIGNED NOT NULL,
|
||||
transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (`phid`),
|
||||
KEY `key_object` (`objectPHID`)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
|
@ -2831,7 +2831,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProfilePanelConfiguration' => 'applications/search/storage/PhabricatorProfilePanelConfiguration.php',
|
||||
'PhabricatorProfilePanelConfigurationQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationQuery.php',
|
||||
'PhabricatorProfilePanelConfigurationTransaction' => 'applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php',
|
||||
'PhabricatorProfilePanelEditEngine' => 'applications/search/editor/PhabricatorProfilePanelEditEngine.php',
|
||||
'PhabricatorProfilePanelEditor' => 'applications/search/editor/PhabricatorProfilePanelEditor.php',
|
||||
'PhabricatorProfilePanelEngine' => 'applications/search/engine/PhabricatorProfilePanelEngine.php',
|
||||
'PhabricatorProfilePanelIconSet' => 'applications/search/profilepanel/PhabricatorProfilePanelIconSet.php',
|
||||
'PhabricatorProfilePanelInterface' => 'applications/search/interface/PhabricatorProfilePanelInterface.php',
|
||||
'PhabricatorProfilePanelPHIDType' => 'applications/search/phidtype/PhabricatorProfilePanelPHIDType.php',
|
||||
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
|
||||
|
@ -2896,6 +2899,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php',
|
||||
'PhabricatorProjectOrUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserFunctionDatasource.php',
|
||||
'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php',
|
||||
'PhabricatorProjectPanelController' => 'applications/project/controller/PhabricatorProjectPanelController.php',
|
||||
'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
|
||||
'PhabricatorProjectProjectHasMemberEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasMemberEdgeType.php',
|
||||
'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php',
|
||||
|
@ -7188,10 +7192,14 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSearchDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
),
|
||||
'PhabricatorProfilePanelConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorProfilePanelConfigurationTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'PhabricatorProfilePanelEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhabricatorProfilePanelEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorProfilePanelEngine' => 'Phobject',
|
||||
'PhabricatorProfilePanelIconSet' => 'PhabricatorIconSet',
|
||||
'PhabricatorProfilePanelPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorProject' => array(
|
||||
'PhabricatorProjectDAO',
|
||||
|
@ -7277,6 +7285,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
|
||||
'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver',
|
||||
'PhabricatorProjectPanelController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
|
||||
'PhabricatorProjectProjectHasMemberEdgeType' => 'PhabricatorEdgeType',
|
||||
'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType',
|
||||
|
|
|
@ -635,4 +635,18 @@ abstract class PhabricatorApplication
|
|||
return $base.'(?:query/(?P<queryKey>[^/]+)/)?';
|
||||
}
|
||||
|
||||
protected function getPanelRouting($controller) {
|
||||
$edit_route = $this->getEditRoutePattern();
|
||||
|
||||
return array(
|
||||
'(?P<panelAction>view)/(?P<panelID>[^/]+)/' => $controller,
|
||||
'(?P<panelAction>hide)/(?P<panelID>[^/]+)/' => $controller,
|
||||
'(?P<panelAction>configure)/' => $controller,
|
||||
'(?P<panelAction>edit)/'.$edit_route => $controller,
|
||||
'(?P<panelAction>new)/(?<panelKey>[^/]+)/'.$edit_route => $controller,
|
||||
'(?P<panelAction>builtin)/(?<panelID>[^/]+)/'.$edit_route
|
||||
=> $controller,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -61,6 +61,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
|
|||
=> 'PhabricatorProjectEditPictureController',
|
||||
$this->getEditRoutePattern('edit/')
|
||||
=> 'PhabricatorProjectEditController',
|
||||
'(?P<projectID>[1-9]\d*)/panel/'
|
||||
=> $this->getPanelRouting('PhabricatorProjectPanelController'),
|
||||
'subprojects/(?P<id>[1-9]\d*)/'
|
||||
=> 'PhabricatorProjectSubprojectsController',
|
||||
'milestones/(?P<id>[1-9]\d*)/'
|
||||
|
|
|
@ -18,7 +18,10 @@ abstract class PhabricatorProjectController extends PhabricatorController {
|
|||
$viewer = $this->getViewer();
|
||||
$request = $this->getRequest();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
$id = nonempty(
|
||||
$request->getURIData('projectID'),
|
||||
$request->getURIData('id'));
|
||||
|
||||
$slug = $request->getURIData('slug');
|
||||
|
||||
if ($slug) {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProjectPanelController
|
||||
extends PhabricatorProjectController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$response = $this->loadProject();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$project = $this->getProject();
|
||||
|
||||
return id(new PhabricatorProfilePanelEngine())
|
||||
->setProfileObject($project)
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,36 @@ final class PhabricatorProjectDetailsProfilePanel
|
|||
|
||||
const PANELKEY = 'project.details';
|
||||
|
||||
public function getPanelTypeName() {
|
||||
return pht('Project Details');
|
||||
}
|
||||
|
||||
private function getDefaultName() {
|
||||
return pht('Project Details');
|
||||
}
|
||||
|
||||
public function getDisplayName(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
$name = $config->getPanelProperty('name');
|
||||
|
||||
if (strlen($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return $this->getDefaultName();
|
||||
}
|
||||
|
||||
public function buildEditEngineFields(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setPlaceholder($this->getDefaultName())
|
||||
->setValue($config->getPanelProperty('name')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
|
|
|
@ -5,6 +5,36 @@ final class PhabricatorProjectMembersProfilePanel
|
|||
|
||||
const PANELKEY = 'project.members';
|
||||
|
||||
public function getPanelTypeName() {
|
||||
return pht('Project Members');
|
||||
}
|
||||
|
||||
private function getDefaultName() {
|
||||
return pht('Members');
|
||||
}
|
||||
|
||||
public function getDisplayName(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
$name = $config->getPanelProperty('name');
|
||||
|
||||
if (strlen($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return $this->getDefaultName();
|
||||
}
|
||||
|
||||
public function buildEditEngineFields(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setPlaceholder($this->getDefaultName())
|
||||
->setValue($config->getPanelProperty('name')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
|
@ -12,7 +42,7 @@ final class PhabricatorProjectMembersProfilePanel
|
|||
|
||||
$id = $project->getID();
|
||||
|
||||
$name = pht('Members');
|
||||
$name = $this->getDisplayName($config);
|
||||
$icon = 'fa-group';
|
||||
$href = "/project/members/{$id}/";
|
||||
|
||||
|
|
|
@ -5,6 +5,36 @@ final class PhabricatorProjectWorkboardProfilePanel
|
|||
|
||||
const PANELKEY = 'project.workboard';
|
||||
|
||||
public function getPanelTypeName() {
|
||||
return pht('Project Workboard');
|
||||
}
|
||||
|
||||
private function getDefaultName() {
|
||||
return pht('Workboard');
|
||||
}
|
||||
|
||||
public function getDisplayName(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
$name = $config->getPanelProperty('name');
|
||||
|
||||
if (strlen($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return $this->getDefaultName();
|
||||
}
|
||||
|
||||
public function buildEditEngineFields(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setPlaceholder($this->getDefaultName())
|
||||
->setValue($config->getPanelProperty('name')),
|
||||
);
|
||||
}
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
$viewer = $this->getViewer();
|
||||
|
@ -29,7 +59,7 @@ final class PhabricatorProjectWorkboardProfilePanel
|
|||
|
||||
$id = $project->getID();
|
||||
$href = "/project/board/{$id}/";
|
||||
$name = pht('Workboard');
|
||||
$name = $this->getDisplayName($config);
|
||||
|
||||
$item = id(new PHUIListItemView())
|
||||
->setRenderNameAsTooltip(true)
|
||||
|
|
|
@ -658,36 +658,36 @@ final class PhabricatorProject extends PhabricatorProjectDAO
|
|||
public function getBuiltinProfilePanels() {
|
||||
$panels = array();
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
$panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin()
|
||||
->setBuiltinKey(self::PANEL_PROFILE)
|
||||
->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY);
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
$panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin()
|
||||
->setBuiltinKey(self::PANEL_WORKBOARD)
|
||||
->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY);
|
||||
|
||||
// TODO: This is temporary.
|
||||
$href = urisprintf(
|
||||
$uri = urisprintf(
|
||||
'/maniphest/?statuses=open()&projects=%s#R',
|
||||
$this->getPHID());
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
$panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin()
|
||||
->setBuiltinKey('tasks')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'fa-anchor')
|
||||
->setPanelProperty('icon', 'maniphest')
|
||||
->setPanelProperty('name', pht('Open Tasks'))
|
||||
->setPanelProperty('href', $href);
|
||||
->setPanelProperty('uri', $uri);
|
||||
|
||||
// TODO: This is temporary.
|
||||
$id = $this->getID();
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
$panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin()
|
||||
->setBuiltinKey('feed')
|
||||
->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY)
|
||||
->setPanelProperty('icon', 'fa-newspaper-o')
|
||||
->setPanelProperty('icon', 'feed')
|
||||
->setPanelProperty('name', pht('Feed'))
|
||||
->setPanelProperty('href', "/project/feed/{$id}/");
|
||||
->setPanelProperty('uri', "/project/feed/{$id}/");
|
||||
|
||||
$panels[] = id(new PhabricatorProfilePanelConfiguration())
|
||||
$panels[] = PhabricatorProfilePanelConfiguration::initializeNewBuiltin()
|
||||
->setBuiltinKey(self::PANEL_MEMBERS)
|
||||
->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY);
|
||||
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
const ENGINECONST = 'search.profilepanel';
|
||||
|
||||
private $panelEngine;
|
||||
private $profileObject;
|
||||
private $newPanelConfiguration;
|
||||
private $isBuiltin;
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setPanelEngine(PhabricatorProfilePanelEngine $engine) {
|
||||
$this->panelEngine = $engine;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPanelEngine() {
|
||||
return $this->panelEngine;
|
||||
}
|
||||
|
||||
public function setProfileObject(
|
||||
PhabricatorProfilePanelInterface $profile_object) {
|
||||
$this->profileObject = $profile_object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProfileObject() {
|
||||
return $this->profileObject;
|
||||
}
|
||||
|
||||
public function setNewPanelConfiguration(
|
||||
PhabricatorProfilePanelConfiguration $configuration) {
|
||||
$this->newPanelConfiguration = $configuration;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNewPanelConfiguration() {
|
||||
return $this->newPanelConfiguration;
|
||||
}
|
||||
|
||||
public function setIsBuiltin($is_builtin) {
|
||||
$this->isBuiltin = $is_builtin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsBuiltin() {
|
||||
return $this->isBuiltin;
|
||||
}
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Profile Panels');
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Edit Profile Panel Configurations');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht('This engine is used to modify menu items on profiles.');
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorSearchApplication';
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
if (!$this->newPanelConfiguration) {
|
||||
throw new Exception(
|
||||
pht('Profile panels can not be generated without an object context.'));
|
||||
}
|
||||
|
||||
return clone $this->newPanelConfiguration;
|
||||
}
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return id(new PhabricatorProfilePanelConfigurationQuery());
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
if ($this->getIsBuiltin()) {
|
||||
return pht('Edit Builtin Item');
|
||||
} else {
|
||||
return pht('Create Menu Item');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getObjectCreateButtonText($object) {
|
||||
if ($this->getIsBuiltin()) {
|
||||
return pht('Save Changes');
|
||||
} else {
|
||||
return pht('Create Menu Item');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Menu Item: %s', $object->getDisplayName());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('Edit Menu Item');
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Edit Menu Item');
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return $this->getPanelEngine()->getConfigureURI();
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $this->getPanelEngine()->getConfigureURI();
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
$panel = $object->getPanel();
|
||||
$fields = $panel->buildEditEngineFields($object);
|
||||
|
||||
$type_property =
|
||||
PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY;
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$field
|
||||
->setTransactionType($type_property)
|
||||
->setMetadataValue('property.key', $field->getKey());
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorSearchApplication';
|
||||
}
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Profile Panels');
|
||||
}
|
||||
|
||||
public function getTransactionTypes() {
|
||||
$types = parent::getTransactionTypes();
|
||||
|
||||
$types[] = PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY;
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
protected function getCustomTransactionOldValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY:
|
||||
$key = $xaction->getMetadataValue('property.key');
|
||||
return $object->getPanelProperty($key, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCustomTransactionNewValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY:
|
||||
return $xaction->getNewValue();
|
||||
}
|
||||
}
|
||||
|
||||
protected function applyCustomInternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY:
|
||||
$key = $xaction->getMetadataValue('property.key');
|
||||
$value = $xaction->getNewValue();
|
||||
$object->setPanelProperty($key, $value);
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function applyCustomExternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY:
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
private $viewer;
|
||||
private $profileObject;
|
||||
private $panels;
|
||||
private $controller;
|
||||
|
||||
public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
|
@ -25,6 +26,103 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
return $this->profileObject;
|
||||
}
|
||||
|
||||
public function setController(PhabricatorController $controller) {
|
||||
$this->controller = $controller;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getController() {
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
public function buildResponse() {
|
||||
$controller = $this->getController();
|
||||
|
||||
$viewer = $controller->getViewer();
|
||||
$this->setViewer($viewer);
|
||||
|
||||
$request = $controller->getRequest();
|
||||
|
||||
$panel_action = $request->getURIData('panelAction');
|
||||
$panel_id = $request->getURIData('panelID');
|
||||
|
||||
$panel_list = $this->loadPanels();
|
||||
|
||||
$selected_panel = null;
|
||||
if (strlen($panel_id)) {
|
||||
$panel_id_int = (int)$panel_id;
|
||||
foreach ($panel_list as $panel) {
|
||||
if ($panel_id_int) {
|
||||
if ((int)$panel->getID() === $panel_id) {
|
||||
$selected_panel = $panel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$builtin_key = $panel->getBuiltinKey();
|
||||
if ($builtin_key === (string)$panel_id) {
|
||||
$selected_panel = $panel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($panel_action) {
|
||||
case 'view':
|
||||
case 'info':
|
||||
case 'hide':
|
||||
case 'builtin':
|
||||
if (!$selected_panel) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$navigation = $this->buildNavigation();
|
||||
$navigation->selectFilter('panel.configure');
|
||||
|
||||
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
|
||||
|
||||
switch ($panel_action) {
|
||||
case 'view':
|
||||
$content = $this->buildPanelViewContent($selected_panel);
|
||||
break;
|
||||
case 'configure':
|
||||
$content = $this->buildPanelConfigureContent($panel_list);
|
||||
$crumbs->addTextCrumb(pht('Configure Menu'));
|
||||
break;
|
||||
case 'new':
|
||||
$panel_key = $request->getURIData('panelKey');
|
||||
$content = $this->buildPanelNewContent($panel_key);
|
||||
break;
|
||||
case 'builtin':
|
||||
$content = $this->buildPanelBuiltinContent($selected_panel);
|
||||
break;
|
||||
case 'edit':
|
||||
$content = $this->buildPanelEditContent();
|
||||
break;
|
||||
default:
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Unsupported panel action "%s".',
|
||||
$panel_action));
|
||||
}
|
||||
|
||||
if ($content instanceof AphrontResponse) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if ($content instanceof AphrontResponseProducerInterface) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
return $controller->newPage()
|
||||
->setTitle(pht('Profile Stuff'))
|
||||
->setNavigation($navigation)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
||||
public function buildNavigation() {
|
||||
$nav = id(new AphrontSideNavFilterView())
|
||||
->setIconNav(true)
|
||||
|
@ -60,6 +158,11 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
}
|
||||
}
|
||||
|
||||
$configure_item = $this->newConfigureMenuItem();
|
||||
if ($configure_item) {
|
||||
$nav->addMenuItem($configure_item);
|
||||
}
|
||||
|
||||
$nav->selectFilter(null);
|
||||
|
||||
return $nav;
|
||||
|
@ -75,10 +178,25 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
|
||||
private function loadPanels() {
|
||||
$viewer = $this->getViewer();
|
||||
$object = $this->getProfileObject();
|
||||
|
||||
$panels = $this->loadBuiltinProfilePanels();
|
||||
|
||||
// TODO: Load persisted panels.
|
||||
$stored_panels = id(new PhabricatorProfilePanelConfigurationQuery())
|
||||
->setViewer($viewer)
|
||||
->withProfilePHIDs(array($object->getPHID()))
|
||||
->execute();
|
||||
|
||||
// Merge the stored panels into the builtin panels. If a builtin panel has
|
||||
// a stored version, replace the defaults with the stored changes.
|
||||
foreach ($stored_panels as $stored_panel) {
|
||||
$builtin_key = $stored_panel->getBuiltinKey();
|
||||
if ($builtin_key !== null) {
|
||||
$panels[$builtin_key] = $stored_panel;
|
||||
} else {
|
||||
$panels[] = $stored_panel;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($panels as $panel) {
|
||||
$impl = $panel->getPanel();
|
||||
|
@ -86,6 +204,10 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
$impl->setViewer($viewer);
|
||||
}
|
||||
|
||||
// Normalize keys since callers shouldn't rely on this array being
|
||||
// partially keyed.
|
||||
$panels = array_values($panels);
|
||||
|
||||
return $panels;
|
||||
}
|
||||
|
||||
|
@ -128,6 +250,7 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
}
|
||||
|
||||
$builtin
|
||||
->setProfilePHID($object->getPHID())
|
||||
->attachPanel($panel)
|
||||
->attachProfileObject($object)
|
||||
->setPanelOrder($order);
|
||||
|
@ -149,4 +272,208 @@ final class PhabricatorProfilePanelEngine extends Phobject {
|
|||
}
|
||||
}
|
||||
|
||||
private function newConfigureMenuItem() {
|
||||
if (!PhabricatorEnv::getEnvConfig('phabricator.show-prototypes')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$object = $this->getProfileObject();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$object,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
return id(new PHUIListItemView())
|
||||
->setName('Configure Menu')
|
||||
->setKey('panel.configure')
|
||||
->setIcon('fa-gear')
|
||||
->setHref($this->getPanelURI('configure/'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit)
|
||||
->setRenderNameAsTooltip(true);
|
||||
}
|
||||
|
||||
public function getConfigureURI() {
|
||||
return $this->getPanelURI('configure/');
|
||||
}
|
||||
|
||||
private function getPanelURI($path) {
|
||||
$project = $this->getProfileObject();
|
||||
$id = $project->getID();
|
||||
return "/project/{$id}/panel/{$path}";
|
||||
}
|
||||
|
||||
private function buildPanelConfigureContent(array $panels) {
|
||||
$viewer = $this->getViewer();
|
||||
$object = $this->getProfileObject();
|
||||
|
||||
PhabricatorPolicyFilter::requireCapability(
|
||||
$viewer,
|
||||
$object,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
foreach ($panels as $panel) {
|
||||
$id = $panel->getID();
|
||||
$builtin_key = $panel->getBuiltinKey();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$panel,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$item = id(new PHUIObjectItemView());
|
||||
|
||||
$name = $panel->getDisplayName();
|
||||
$type = $panel->getPanelTypeName();
|
||||
if (!strlen(trim($name))) {
|
||||
$name = pht('Untitled "%s" Item', $type);
|
||||
}
|
||||
|
||||
$item->setHeader($name);
|
||||
$item->addAttribute($type);
|
||||
|
||||
if ($can_edit) {
|
||||
if ($id) {
|
||||
$item->setHref($this->getPanelURI("edit/{$id}/"));
|
||||
} else {
|
||||
$item->setHref($this->getPanelURI("builtin/{$builtin_key}/"));
|
||||
}
|
||||
}
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
$action_view = id(new PhabricatorActionListView())
|
||||
->setUser($viewer);
|
||||
|
||||
$panel_types = PhabricatorProfilePanel::getAllPanels();
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setLabel(true)
|
||||
->setName(pht('Add New Menu Item...')));
|
||||
|
||||
foreach ($panel_types as $panel_type) {
|
||||
if (!$panel_type->canAddToObject($object)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$panel_key = $panel_type->getPanelKey();
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon($panel_type->getPanelTypeIcon())
|
||||
->setName($panel_type->getPanelTypeName())
|
||||
->setHref($this->getPanelURI("new/{$panel_key}/")));
|
||||
}
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setLabel(true)
|
||||
->setName(pht('Documentation')));
|
||||
|
||||
$action_view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-book')
|
||||
->setName(pht('TODO: Write Documentation')));
|
||||
|
||||
$action_button = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setText(pht('Configure Menu'))
|
||||
->setHref('#')
|
||||
->setIconFont('fa-gear')
|
||||
->setDropdownMenu($action_view);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Profile Menu Items'))
|
||||
->addActionLink($action_button);
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->setObjectList($list);
|
||||
|
||||
return $box;
|
||||
}
|
||||
|
||||
private function buildPanelNewContent($panel_key) {
|
||||
$panel_types = PhabricatorProfilePanel::getAllPanels();
|
||||
$panel_type = idx($panel_types, $panel_key);
|
||||
if (!$panel_type) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$object = $this->getProfileObject();
|
||||
if (!$panel_type->canAddToObject($object)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$configuration =
|
||||
PhabricatorProfilePanelConfiguration::initializeNewPanelConfiguration(
|
||||
$object,
|
||||
$panel_type);
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
PhabricatorPolicyFilter::requireCapability(
|
||||
$viewer,
|
||||
$configuration,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$controller = $this->getController();
|
||||
|
||||
return id(new PhabricatorProfilePanelEditEngine())
|
||||
->setPanelEngine($this)
|
||||
->setProfileObject($object)
|
||||
->setNewPanelConfiguration($configuration)
|
||||
->setController($controller)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
private function buildPanelEditContent() {
|
||||
$viewer = $this->getViewer();
|
||||
$object = $this->getProfileObject();
|
||||
$controller = $this->getController();
|
||||
|
||||
return id(new PhabricatorProfilePanelEditEngine())
|
||||
->setPanelEngine($this)
|
||||
->setProfileObject($object)
|
||||
->setController($controller)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
private function buildPanelBuiltinContent(
|
||||
PhabricatorProfilePanelConfiguration $configuration) {
|
||||
|
||||
// If this builtin panel has already been persisted, redirect to the
|
||||
// edit page.
|
||||
$id = $configuration->getID();
|
||||
if ($id) {
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($this->getPanelURI("edit/{$id}/"));
|
||||
}
|
||||
|
||||
// Otherwise, act like we're creating a new panel, we're just starting
|
||||
// with the builtin template.
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
PhabricatorPolicyFilter::requireCapability(
|
||||
$viewer,
|
||||
$configuration,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$object = $this->getProfileObject();
|
||||
$controller = $this->getController();
|
||||
|
||||
return id(new PhabricatorProfilePanelEditEngine())
|
||||
->setIsBuiltin(true)
|
||||
->setPanelEngine($this)
|
||||
->setProfileObject($object)
|
||||
->setNewPanelConfiguration($configuration)
|
||||
->setController($controller)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,19 +5,89 @@ final class PhabricatorLinkProfilePanel
|
|||
|
||||
const PANELKEY = 'link';
|
||||
|
||||
public function getPanelTypeIcon() {
|
||||
return 'fa-link';
|
||||
}
|
||||
|
||||
public function getPanelTypeName() {
|
||||
return pht('Link');
|
||||
}
|
||||
|
||||
public function canAddToObject(
|
||||
PhabricatorProfilePanelInterface $object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDisplayName(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return $this->getLinkName($config);
|
||||
}
|
||||
|
||||
public function buildEditEngineFields(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return array(
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setIsRequired(true)
|
||||
->setValue($this->getLinkName($config)),
|
||||
id(new PhabricatorTextEditField())
|
||||
->setKey('uri')
|
||||
->setLabel(pht('URI'))
|
||||
->setIsRequired(true)
|
||||
->setValue($this->getLinkURI($config)),
|
||||
id(new PhabricatorIconSetEditField())
|
||||
->setKey('icon')
|
||||
->setLabel(pht('Icon'))
|
||||
->setIconSet(new PhabricatorProfilePanelIconSet())
|
||||
->setValue($this->getLinkIcon($config)),
|
||||
);
|
||||
}
|
||||
|
||||
private function getLinkName(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return $config->getPanelProperty('name');
|
||||
}
|
||||
|
||||
private function getLinkIcon(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return $config->getPanelProperty('icon', 'link');
|
||||
}
|
||||
|
||||
private function getLinkURI(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return $config->getPanelProperty('uri');
|
||||
}
|
||||
|
||||
private function isValidLinkURI($uri) {
|
||||
return PhabricatorEnv::isValidURIForLink($uri);
|
||||
}
|
||||
|
||||
protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
|
||||
$icon = $config->getPanelProperty('icon');
|
||||
$name = $config->getPanelProperty('name');
|
||||
$href = $config->getPanelProperty('href');
|
||||
$icon = $this->getLinkIcon($config);
|
||||
$name = $this->getLinkName($config);
|
||||
$href = $this->getLinkURI($config);
|
||||
|
||||
if (!$this->isValidLinkURI($href)) {
|
||||
$href = '#';
|
||||
}
|
||||
|
||||
$icon_object = id(new PhabricatorProfilePanelIconSet())
|
||||
->getIcon($icon);
|
||||
if ($icon_object) {
|
||||
$icon_class = $icon_object->getIcon();
|
||||
} else {
|
||||
$icon_class = 'fa-link';
|
||||
}
|
||||
|
||||
$item = id(new PHUIListItemView())
|
||||
->setRenderNameAsTooltip(true)
|
||||
->setType(PHUIListItemView::TYPE_ICON_NAV)
|
||||
->setHref($href)
|
||||
->setName($name)
|
||||
->setIcon($icon);
|
||||
->setIcon($icon_class);
|
||||
|
||||
return array(
|
||||
$item,
|
||||
|
|
|
@ -12,6 +12,25 @@ abstract class PhabricatorProfilePanel extends Phobject {
|
|||
abstract protected function newNavigationMenuItems(
|
||||
PhabricatorProfilePanelConfiguration $config);
|
||||
|
||||
public function getPanelTypeIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract public function getPanelTypeName();
|
||||
|
||||
abstract public function getDisplayName(
|
||||
PhabricatorProfilePanelConfiguration $config);
|
||||
|
||||
public function buildEditEngineFields(
|
||||
PhabricatorProfilePanelConfiguration $config) {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function canAddToObject(
|
||||
PhabricatorProfilePanelInterface $object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
return $this;
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorProfilePanelIconSet
|
||||
extends PhabricatorIconSet {
|
||||
|
||||
const ICONSETKEY = 'profilepanel';
|
||||
|
||||
public function getSelectIconTitleText() {
|
||||
return pht('Choose Item Icon');
|
||||
}
|
||||
|
||||
protected function newIcons() {
|
||||
$list = array(
|
||||
array(
|
||||
'key' => 'link',
|
||||
'icon' => 'fa-link',
|
||||
'name' => pht('Link'),
|
||||
),
|
||||
array(
|
||||
'key' => 'maniphest',
|
||||
'icon' => 'fa-anchor',
|
||||
'name' => pht('Maniphest'),
|
||||
),
|
||||
array(
|
||||
'key' => 'feed',
|
||||
'icon' => 'fa-newspaper-o',
|
||||
'name' => pht('Feed'),
|
||||
),
|
||||
);
|
||||
|
||||
$icons = array();
|
||||
foreach ($list as $spec) {
|
||||
$icons[] = id(new PhabricatorIconSetIcon())
|
||||
->setKey($spec['key'])
|
||||
->setIcon($spec['icon'])
|
||||
->setLabel($spec['name']);
|
||||
}
|
||||
|
||||
return $icons;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ final class PhabricatorProfilePanelConfigurationQuery
|
|||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $profileObjectPHIDs;
|
||||
private $profilePHIDs;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
|
@ -17,8 +17,8 @@ final class PhabricatorProfilePanelConfigurationQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withProfileObjectPHIDs(array $phids) {
|
||||
$this->profileObjectPHIDs = $phids;
|
||||
public function withProfilePHIDs(array $phids) {
|
||||
$this->profilePHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -47,16 +47,54 @@ final class PhabricatorProfilePanelConfigurationQuery
|
|||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->profileObjectPHIDs !== null) {
|
||||
if ($this->profilePHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'profileObjectPHID IN (%Ls)',
|
||||
$this->profileObjectPHIDs);
|
||||
'profilePHID IN (%Ls)',
|
||||
$this->profilePHIDs);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $page) {
|
||||
$panels = PhabricatorProfilePanel::getAllPanels();
|
||||
foreach ($page as $key => $panel) {
|
||||
$panel_type = idx($panels, $panel->getPanelKey());
|
||||
if (!$panel_type) {
|
||||
$this->didRejectResult($panel);
|
||||
unset($page[$key]);
|
||||
continue;
|
||||
}
|
||||
$panel->attachPanel($panel_type);
|
||||
}
|
||||
|
||||
if (!$page) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$profile_phids = mpull($page, 'getProfilePHID');
|
||||
|
||||
$profiles = id(new PhabricatorObjectQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setParentQuery($this)
|
||||
->withPHIDs($profile_phids)
|
||||
->execute();
|
||||
$profiles = mpull($profiles, null, 'getPHID');
|
||||
|
||||
foreach ($page as $key => $panel) {
|
||||
$profile = idx($profiles, $panel->getProfilePHID());
|
||||
if (!$profile) {
|
||||
$this->didRejectResult($panel);
|
||||
unset($page[$key]);
|
||||
continue;
|
||||
}
|
||||
$panel->attachProfileObject($profile);
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorSearchApplication';
|
||||
}
|
||||
|
|
|
@ -4,26 +4,34 @@ final class PhabricatorProfilePanelConfiguration
|
|||
extends PhabricatorSearchDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
PhabricatorExtendedPolicyInterface,
|
||||
PhabricatorApplicationTransactionInterface {
|
||||
|
||||
protected $profilePHID;
|
||||
protected $panelKey;
|
||||
protected $builtinKey;
|
||||
protected $panelOrder;
|
||||
protected $isDisabled;
|
||||
protected $visibility;
|
||||
protected $panelProperties = array();
|
||||
|
||||
private $profileObject = self::ATTACHABLE;
|
||||
private $panel = self::ATTACHABLE;
|
||||
|
||||
const VISIBILITY_VISIBLE = 'visible';
|
||||
const VISIBILITY_DISABLED = 'disabled';
|
||||
|
||||
public static function initializeNewBuiltin() {
|
||||
return id(new self())
|
||||
->setVisibility(self::VISIBILITY_VISIBLE);
|
||||
}
|
||||
|
||||
public static function initializeNewPanelConfiguration(
|
||||
PhabricatorProfilePanelInterface $profile_object,
|
||||
PhabricatorProfilePanel $panel) {
|
||||
|
||||
return id(new self())
|
||||
return self::initializeNewBuiltin()
|
||||
->setProfilePHID($profile_object->getPHID())
|
||||
->setPanelKey($panel->getPanelKey())
|
||||
->setIsDisabled(0)
|
||||
->attachPanel($panel)
|
||||
->attachProfileObject($profile_object);
|
||||
}
|
||||
|
@ -36,9 +44,9 @@ final class PhabricatorProfilePanelConfiguration
|
|||
),
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'panelKey' => 'text64',
|
||||
'builtinKey' => 'text64',
|
||||
'panelOrder' => 'uint32',
|
||||
'isDisabled' => 'bool',
|
||||
'builtinKey' => 'text64?',
|
||||
'panelOrder' => 'uint32?',
|
||||
'visibility' => 'text32',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_profile' => array(
|
||||
|
@ -48,6 +56,11 @@ final class PhabricatorProfilePanelConfiguration
|
|||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(
|
||||
PhabricatorProfilePanelPHIDType::TYPECONST);
|
||||
}
|
||||
|
||||
public function attachPanel(PhabricatorProfilePanel $panel) {
|
||||
$this->panel = $panel;
|
||||
return $this;
|
||||
|
@ -67,10 +80,6 @@ final class PhabricatorProfilePanelConfiguration
|
|||
return $this->assertAttached($this->profileObject);
|
||||
}
|
||||
|
||||
public function buildNavigationMenuItems() {
|
||||
return $this->getPanel()->buildNavigationMenuItems($this);
|
||||
}
|
||||
|
||||
public function setPanelProperty($key, $value) {
|
||||
$this->panelProperties[$key] = $value;
|
||||
return $this;
|
||||
|
@ -80,6 +89,18 @@ final class PhabricatorProfilePanelConfiguration
|
|||
return idx($this->panelProperties, $key, $default);
|
||||
}
|
||||
|
||||
public function buildNavigationMenuItems() {
|
||||
return $this->getPanel()->buildNavigationMenuItems($this);
|
||||
}
|
||||
|
||||
public function getPanelTypeName() {
|
||||
return $this->getPanel()->getPanelTypeName();
|
||||
}
|
||||
|
||||
public function getDisplayName() {
|
||||
return $this->getPanel()->getDisplayName($this);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
@ -121,4 +142,27 @@ final class PhabricatorProfilePanelConfiguration
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
||||
public function getApplicationTransactionEditor() {
|
||||
return new PhabricatorProfilePanelEditor();
|
||||
}
|
||||
|
||||
public function getApplicationTransactionObject() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionTemplate() {
|
||||
return new PhabricatorProfilePanelConfigurationTransaction();
|
||||
}
|
||||
|
||||
public function willRenderTimeline(
|
||||
PhabricatorApplicationTransactionView $timeline,
|
||||
AphrontRequest $request) {
|
||||
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
final class PhabricatorProfilePanelConfigurationTransaction
|
||||
extends PhabricatorApplicationTransaction {
|
||||
|
||||
const TYPE_PROPERTY = 'profilepanel.property';
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'search';
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ final class PhabricatorEditEngineConfigurationListController
|
|||
$engine = PhabricatorEditEngine::getByKey($viewer, $engine_key)
|
||||
->setViewer($viewer);
|
||||
|
||||
if (!$engine->isEngineConfigurable()) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$items = array();
|
||||
$items[] = id(new PHUIListItemView())
|
||||
->setType(PHUIListItemView::TYPE_LABEL)
|
||||
|
|
|
@ -72,6 +72,10 @@ abstract class PhabricatorEditEngineController
|
|||
$engine = $config->getEngine();
|
||||
}
|
||||
|
||||
if (!$engine->isEngineConfigurable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,10 @@ abstract class PhabricatorEditEngine
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* -( Managing Fields )---------------------------------------------------- */
|
||||
|
||||
|
@ -1005,8 +1009,11 @@ abstract class PhabricatorEditEngine
|
|||
}
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($header_text)
|
||||
->addActionLink($action_button);
|
||||
->setHeader($header_text);
|
||||
|
||||
if ($action_button) {
|
||||
$header->addActionLink($action_button);
|
||||
}
|
||||
|
||||
$crumbs = $this->buildCrumbs($object, $final = true);
|
||||
|
||||
|
@ -1066,6 +1073,10 @@ abstract class PhabricatorEditEngine
|
|||
}
|
||||
|
||||
private function buildEditFormActionButton($object) {
|
||||
if (!$this->isEngineConfigurable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$action_view = id(new PhabricatorActionListView())
|
||||
|
|
|
@ -3,8 +3,26 @@
|
|||
final class PhabricatorTextEditField
|
||||
extends PhabricatorEditField {
|
||||
|
||||
private $placeholder;
|
||||
|
||||
public function setPlaceholder($placeholder) {
|
||||
$this->placeholder = $placeholder;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPlaceholder() {
|
||||
return $this->placeholder;
|
||||
}
|
||||
|
||||
protected function newControl() {
|
||||
return new AphrontFormTextControl();
|
||||
$control = new AphrontFormTextControl();
|
||||
|
||||
$placeholder = $this->getPlaceholder();
|
||||
if (strlen($placeholder)) {
|
||||
$control->setPlaceholder($placeholder);
|
||||
}
|
||||
|
||||
return $control;
|
||||
}
|
||||
|
||||
protected function newConduitParameterType() {
|
||||
|
|
|
@ -62,6 +62,10 @@ final class PhabricatorEditEngineSearchEngine
|
|||
$list = id(new PHUIObjectItemListView())
|
||||
->setUser($viewer);
|
||||
foreach ($engines as $engine) {
|
||||
if (!$engine->isEngineConfigurable()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$engine_key = $engine->getEngineKey();
|
||||
$query_uri = "/transactions/editengine/{$engine_key}/";
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ Use {nav My Deprecated Calls} to find calls to deprecated methods you have
|
|||
made, and {nav Deprecated Call Logs} to find deprecated calls by all users.
|
||||
|
||||
You can also search for calls by specific users. For example, it may be useful
|
||||
to serach for any bot accounts you run to make sure they aren't calling
|
||||
to search for any bot accounts you run to make sure they aren't calling
|
||||
outdated APIs.
|
||||
|
||||
The most common cause of calls to deprecated methods is users running very
|
||||
|
|
Loading…
Reference in a new issue