1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-28 14:39:36 +01:00
phorge-phorge/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php

322 lines
7.9 KiB
PHP
Raw Normal View History

<?php
final class PhabricatorProfileMenuItemConfiguration
extends PhabricatorSearchDAO
implements
PhabricatorPolicyInterface,
PhabricatorExtendedPolicyInterface,
PhabricatorApplicationTransactionInterface {
protected $profilePHID;
protected $menuItemKey;
protected $builtinKey;
protected $menuItemOrder;
protected $visibility;
protected $customPHID;
protected $menuItemProperties = array();
private $profileObject = self::ATTACHABLE;
private $menuItem = self::ATTACHABLE;
private $isHeadItem = false;
private $isTailItem = false;
const VISIBILITY_DEFAULT = 'default';
const VISIBILITY_VISIBLE = 'visible';
const VISIBILITY_DISABLED = 'disabled';
public function getTableName() {
// For now, this class uses an older table name.
return 'search_profilepanelconfiguration';
}
public static function initializeNewBuiltin() {
return id(new self())
->setVisibility(self::VISIBILITY_VISIBLE);
}
public static function initializeNewItem(
$profile_object,
PhabricatorProfileMenuItem $item,
$custom_phid) {
return self::initializeNewBuiltin()
->setProfilePHID($profile_object->getPHID())
->setMenuItemKey($item->getMenuItemKey())
->attachMenuItem($item)
->attachProfileObject($profile_object)
->setCustomPHID($custom_phid);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'menuItemProperties' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(
'menuItemKey' => 'text64',
'builtinKey' => 'text64?',
'menuItemOrder' => 'uint32?',
'customPHID' => 'phid?',
'visibility' => 'text32',
),
self::CONFIG_KEY_SCHEMA => array(
'key_profile' => array(
'columns' => array('profilePHID', 'menuItemOrder'),
),
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorProfileMenuItemPHIDType::TYPECONST);
}
public function attachMenuItem(PhabricatorProfileMenuItem $item) {
$this->menuItem = $item;
return $this;
}
public function getMenuItem() {
return $this->assertAttached($this->menuItem);
}
public function attachProfileObject($profile_object) {
$this->profileObject = $profile_object;
return $this;
}
public function getProfileObject() {
return $this->assertAttached($this->profileObject);
}
public function setMenuItemProperty($key, $value) {
$this->menuItemProperties[$key] = $value;
return $this;
}
public function getMenuItemProperty($key, $default = null) {
return idx($this->menuItemProperties, $key, $default);
}
public function getMenuItemTypeName() {
return $this->getMenuItem()->getMenuItemTypeName();
}
public function getDisplayName() {
return $this->getMenuItem()->getDisplayName($this);
}
public function canMakeDefault() {
return $this->getMenuItem()->canMakeDefault($this);
}
public function canHideMenuItem() {
return $this->getMenuItem()->canHideMenuItem($this);
}
public function shouldEnableForObject($object) {
return $this->getMenuItem()->shouldEnableForObject($object);
}
In ProfileMenu, put more structure between "stored/configured items" and "display items" Summary: Depends on D20356. Ref T13275. See also T12871 and T12949. Currently, the whole "ProfileMenu" API operates around //stored// items. However, stored items are allowed to produce zero or more //display// items, and we sometimes want to highlight display item X but render stored item Y (as is the case with "Link" items pointing at `?filter=xyz` on Workboards). For the most part, this either: doesn't work; or works by chance; or is kind of glued together with hope and prayer (as in D20353). Put an actual structural layer in place between "stored/configured item" and "display item" that can link them together more clearly. Now: - The list of `ItemConfiguration` objects (stored/configured items) is used to build an `ItemViewList`. - This handles the selection/highlighting/default state, and knows which display items are related to which stored items. - When we're all done figuring out what we're going to select and what we're going to highlight, it pops out an actual View which can build the HTML. This requires API changes which are not included in this change, see next change. This doesn't really do anything on its own, but builds toward a more satisfying fix for T12871. I'd hoped to avoid doing this for now, but wasn't able to get a patch I felt good about for T12871 built without fixing this first. Test Plan: See next change. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13275 Differential Revision: https://secure.phabricator.com/D20357
2019-03-31 11:48:44 -07:00
public function willGetMenuItemViewList(array $items) {
return $this->getMenuItem()->willGetMenuItemViewList($items);
}
public function getMenuItemViewList() {
return $this->getMenuItem()->getMenuItemViewList($this);
}
public function validateTransactions(array $map) {
$item = $this->getMenuItem();
$fields = $item->buildEditEngineFields($this);
$errors = array();
foreach ($fields as $field) {
$field_key = $field->getKey();
$xactions = idx($map, $field_key, array());
$value = $this->getMenuItemProperty($field_key);
$field_errors = $item->validateTransactions(
$this,
$field_key,
$value,
$xactions);
foreach ($field_errors as $error) {
$errors[] = $error;
}
}
return $errors;
}
public function getSortVector() {
// Sort custom items above global items.
if ($this->getCustomPHID()) {
$is_global = 0;
} else {
$is_global = 1;
}
// Sort "head" items above other items and "tail" items after other items.
if ($this->getIsHeadItem()) {
$force_position = 0;
} else if ($this->getIsTailItem()) {
$force_position = 2;
} else {
$force_position = 1;
}
// Sort items with an explicit order above items without an explicit order,
// so any newly created builtins go to the bottom.
$order = $this->getMenuItemOrder();
if ($order !== null) {
$has_order = 0;
} else {
$has_order = 1;
}
return id(new PhutilSortVector())
->addInt($is_global)
->addInt($force_position)
->addInt($has_order)
->addInt((int)$order)
->addInt((int)$this->getID());
}
public function isDisabled() {
if (!$this->canHideMenuItem()) {
return false;
}
return ($this->getVisibility() === self::VISIBILITY_DISABLED);
}
public function isDefault() {
return ($this->getVisibility() === self::VISIBILITY_DEFAULT);
}
public function getItemIdentifier() {
$id = $this->getID();
if ($id) {
return (int)$id;
}
return $this->getBuiltinKey();
}
public function getDefaultMenuItemKey() {
if ($this->getBuiltinKey()) {
return $this->getBuiltinKey();
}
return $this->getPHID();
}
public function newPageContent() {
return $this->getMenuItem()->newPageContent($this);
}
public function setIsHeadItem($is_head_item) {
$this->isHeadItem = $is_head_item;
return $this;
}
public function getIsHeadItem() {
return $this->isHeadItem;
}
public function setIsTailItem($is_tail_item) {
$this->isTailItem = $is_tail_item;
return $this;
}
public function getIsTailItem() {
return $this->isTailItem;
}
public function matchesIdentifier($identifier) {
if (!strlen($identifier)) {
return false;
}
if (ctype_digit($identifier)) {
if ((int)$this->getID() === (int)$identifier) {
return true;
}
}
if ((string)$this->getBuiltinKey() === (string)$identifier) {
return true;
}
return false;
}
/* -( 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);
}
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
// If this is an item with a custom PHID (like a personal menu item),
// we only require that the user can edit the corresponding custom
// object (usually their own user profile), not the object that the
// menu appears on (which may be an Application like Favorites or Home).
if ($capability == PhabricatorPolicyCapability::CAN_EDIT) {
if ($this->getCustomPHID()) {
return array(
array(
$this->getCustomPHID(),
$capability,
),
);
}
}
return array(
array(
$this->getProfileObject(),
$capability,
),
);
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorProfileMenuEditor();
}
public function getApplicationTransactionTemplate() {
return new PhabricatorProfileMenuItemConfigurationTransaction();
}
}