1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 01:08:50 +02:00

Fully modularize the "Quick Actions" menu

Summary:
Ref T10077. Currently, we issue 6+ queries on every page to build this menu, since the menu is built application-by-application.

Build the menu with dedicated modules instead so a single "EditEngine" module can provide all of them with one query.

I'd like to reduce this to 0 queries but I'm not totally sure what we want to do with this menu.

This change removes these items, because EditEngine can not currently provide them:

  - Calendar: Eventually via EditEngine eventually.
  - Conpherence: Probably via EditEngine, doesn't seem too important.
  - People: Maybe via EditEngine, doesn't seem too important? "Welcome" is likely better?
  - Pholio: Eventually via EditEngine.

It adds a bunch of other items as a side effect:

{F1677151}

This reduces the queries issued on every page by ~5.

This also makes quick create actions visible while logged out (see T7073).

Test Plan:
  - Viewed menu while logged in.
  - Viewed menu while logged out.
  - Viewed standalone version of menu.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10077

Differential Revision: https://secure.phabricator.com/D16045
This commit is contained in:
epriestley 2016-06-05 07:26:47 -07:00
parent aa4ba0fa92
commit 7969f66dfe
14 changed files with 151 additions and 146 deletions

View file

@ -2370,6 +2370,7 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationTransactionQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php',
'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php',
'PhabricatorEditEngineController' => 'applications/transactions/controller/PhabricatorEditEngineController.php',
'PhabricatorEditEngineCreateQuickActions' => 'applications/settings/quickmenu/PhabricatorEditEngineCreateQuickActions.php',
'PhabricatorEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditEngineExtension.php',
'PhabricatorEditEngineExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditEngineExtensionModule.php',
'PhabricatorEditEngineListController' => 'applications/transactions/controller/PhabricatorEditEngineListController.php',
@ -3191,6 +3192,7 @@ phutil_register_library_map(array(
'PhabricatorQueryOrderItem' => 'infrastructure/query/order/PhabricatorQueryOrderItem.php',
'PhabricatorQueryOrderTestCase' => 'infrastructure/query/order/__tests__/PhabricatorQueryOrderTestCase.php',
'PhabricatorQueryOrderVector' => 'infrastructure/query/order/PhabricatorQueryOrderVector.php',
'PhabricatorQuickActions' => 'applications/settings/quickmenu/PhabricatorQuickActions.php',
'PhabricatorRateLimitRequestExceptionHandler' => 'aphront/handler/PhabricatorRateLimitRequestExceptionHandler.php',
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
'PhabricatorRecipientHasBadgeEdgeType' => 'applications/badges/edge/PhabricatorRecipientHasBadgeEdgeType.php',
@ -6962,6 +6964,7 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineController' => 'PhabricatorApplicationTransactionController',
'PhabricatorEditEngineCreateQuickActions' => 'PhabricatorQuickActions',
'PhabricatorEditEngineExtension' => 'Phobject',
'PhabricatorEditEngineExtensionModule' => 'PhabricatorConfigModule',
'PhabricatorEditEngineListController' => 'PhabricatorEditEngineController',
@ -7916,6 +7919,7 @@ phutil_register_library_map(array(
'Phobject',
'Iterator',
),
'PhabricatorQuickActions' => 'Phobject',
'PhabricatorRateLimitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorRecipientHasBadgeEdgeType' => 'PhabricatorEdgeType',

View file

@ -335,17 +335,6 @@ abstract class PhabricatorApplication
}
/**
* Build items for the "quick create" menu.
*
* @param PhabricatorUser The viewing user.
* @return list<PHUIListItemView> List of menu items.
*/
public function getQuickCreateItems(PhabricatorUser $viewer) {
return array();
}
/* -( Application Management )--------------------------------------------- */

View file

@ -73,18 +73,6 @@ final class PhabricatorCalendarApplication extends PhabricatorApplication {
);
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
$items = array();
$item = id(new PHUIListItemView())
->setName(pht('Calendar Event'))
->setIcon('fa-calendar')
->setHref($this->getBaseURI().'event/create/');
$items[] = $item;
return $items;
}
public function getMailCommandObjects() {
return array(
'event' => array(

View file

@ -48,19 +48,6 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication {
);
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
$items = array();
$item = id(new PHUIListItemView())
->setName(pht('Conpherence Room'))
->setIcon('fa-comments')
->setWorkflow(true)
->setHref($this->getBaseURI().'new/');
$items[] = $item;
return $items;
}
public function getQuicksandURIPatternBlacklist() {
return array(
'/conpherence/.*',

View file

@ -42,51 +42,29 @@ final class PhabricatorHomeApplication extends PhabricatorApplication {
PhabricatorUser $user,
PhabricatorController $controller = null) {
$quick_create_items = $this->loadAllQuickCreateItems($user);
$items = array();
$create_id = celerity_generate_unique_node_id();
if ($user->isLoggedIn() &&
$user->isUserActivated() &&
$quick_create_items) {
$create_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'aphlict-dropdown',
array(
'bubbleID' => $create_id,
'dropdownID' => 'phabricator-quick-create-menu',
'local' => true,
'desktop' => true,
'right' => true,
));
Javelin::initBehavior(
'aphlict-dropdown',
array(
'bubbleID' => $create_id,
'dropdownID' => 'phabricator-quick-create-menu',
'local' => true,
'desktop' => true,
'right' => true,
));
$item = id(new PHUIListItemView())
->setName(pht('Create New...'))
->setIcon('fa-plus')
->addClass('core-menu-item')
->setHref('/home/create/')
->addSigil('quick-create-menu')
->setID($create_id)
->setAural(pht('Quick Create'))
->setOrder(300);
$items[] = $item;
}
return $items;
}
public function loadAllQuickCreateItems(PhabricatorUser $viewer) {
$applications = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withInstalled(true)
->execute();
$items = array();
foreach ($applications as $application) {
$app_items = $application->getQuickCreateItems($viewer);
foreach ($app_items as $app_item) {
$items[] = $app_item;
}
}
$item = id(new PHUIListItemView())
->setName(pht('Quick Actions'))
->setIcon('fa-plus')
->addClass('core-menu-item')
->setHref('/home/create/')
->addSigil('quick-create-menu')
->setID($create_id)
->setAural(pht('Quick Actions'))
->setOrder(300);
$items[] = $item;
return $items;
}
@ -95,7 +73,7 @@ final class PhabricatorHomeApplication extends PhabricatorApplication {
PhabricatorUser $viewer,
PhabricatorController $controller = null) {
$items = $this->loadAllQuickCreateItems($viewer);
$items = PhabricatorQuickActions::loadMenuItemsForUser($viewer);
$view = null;
if ($items) {

View file

@ -6,7 +6,7 @@ final class PhabricatorHomeQuickCreateController
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$items = $this->getCurrentApplication()->loadAllQuickCreateItems($viewer);
$items = PhabricatorQuickActions::loadMenuItemsForUser($viewer);
$list = id(new PHUIObjectItemListView())
->setUser($viewer);

View file

@ -90,12 +90,6 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
return $status;
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
return id(new ManiphestEditEngine())
->setViewer($viewer)
->loadQuickCreateItems();
}
public function supportsEmailIntegration() {
return true;
}

View file

@ -76,12 +76,6 @@ final class PhabricatorPasteApplication extends PhabricatorApplication {
);
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
return id(new PhabricatorPasteEditEngine())
->setViewer($viewer)
->loadQuickCreateItems();
}
public function getMailCommandObjects() {
return array(
'paste' => array(

View file

@ -127,31 +127,6 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
return $status;
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
$items = array();
$can_create = PhabricatorPolicyFilter::hasCapability(
$viewer,
$this,
PeopleCreateUsersCapability::CAPABILITY);
if ($can_create) {
$item = id(new PHUIListItemView())
->setName(pht('User Account'))
->setIcon('fa-users')
->setHref($this->getBaseURI().'create/');
$items[] = $item;
} else if ($viewer->getIsAdmin()) {
$item = id(new PHUIListItemView())
->setName(pht('Bot Account'))
->setIcon('fa-android')
->setHref($this->getBaseURI().'new/bot/');
$items[] = $item;
}
return $items;
}
public function getApplicationSearchDocumentTypes() {
return array(
PhabricatorPeopleUserPHIDType::TYPECONST,

View file

@ -59,18 +59,6 @@ final class PhabricatorPholioApplication extends PhabricatorApplication {
);
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
$items = array();
$item = id(new PHUIListItemView())
->setName(pht('Pholio Mock'))
->setIcon('fa-picture-o')
->setHref($this->getBaseURI().'create/');
$items[] = $item;
return $items;
}
protected function getCustomCapabilities() {
return array(
PholioDefaultViewCapability::CAPABILITY => array(

View file

@ -108,12 +108,6 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
);
}
public function getQuickCreateItems(PhabricatorUser $viewer) {
return id(new PhabricatorProjectEditEngine())
->setViewer($viewer)
->loadQuickCreateItems();
}
protected function getCustomCapabilities() {
return array(
ProjectCreateProjectsCapability::CAPABILITY => array(),

View file

@ -0,0 +1,46 @@
<?php
final class PhabricatorEditEngineCreateQuickActions
extends PhabricatorQuickActions {
const QUICKACTIONSKEY = 'editengine.create';
public function getQuickMenuItems() {
$viewer = $this->getViewer();
$engines = PhabricatorEditEngine::getAllEditEngines();
foreach ($engines as $key => $engine) {
if (!$engine->hasQuickCreateActions()) {
unset($engines[$key]);
}
}
if (!$engines) {
return array();
}
$engine_keys = array_keys($engines);
$configs = id(new PhabricatorEditEngineConfigurationQuery())
->setViewer($viewer)
->withEngineKeys($engine_keys)
->withIsDefault(true)
->withIsDisabled(false)
->execute();
$configs = msort($configs, 'getCreateSortKey');
$configs = mgroup($configs, 'getEngineKey');
$items = array();
foreach ($engines as $key => $engine) {
$engine_configs = idx($configs, $key, array());
$engine_items = $engine->newQuickCreateActions($engine_configs);
foreach ($engine_items as $engine_item) {
$items[] = $engine_item;
}
}
return $items;
}
}

View file

@ -0,0 +1,54 @@
<?php
abstract class PhabricatorQuickActions extends Phobject {
private $viewer;
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
return $this->viewer;
}
public function isEnabled() {
return true;
}
abstract public function getQuickMenuItems();
final public function getQuickActionsKey() {
return $this->getPhobjectClassConstant('QUICKACTIONSKEY');
}
public static function getAllQuickActions() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getQuickActionsKey')
->execute();
}
public static function loadMenuItemsForUser(PhabricatorUser $viewer) {
$actions = self::getAllQuickActions();
foreach ($actions as $key => $action) {
$action->setViewer($viewer);
if (!$action->isEnabled()) {
unset($actions[$key]);
continue;
}
}
$items = array();
foreach ($actions as $key => $action) {
foreach ($action->getQuickMenuItems() as $item) {
$items[] = $item;
}
}
return $items;
}
}

View file

@ -1972,20 +1972,34 @@ abstract class PhabricatorEditEngine
return $application->getIcon();
}
public function loadQuickCreateItems() {
$items = array();
if (!$this->hasCreateCapability()) {
return $items;
public function hasQuickCreateActions() {
if (!$this->isEngineConfigurable()) {
return false;
}
$configs = $this->loadUsableConfigurationsForCreate();
return true;
}
public function newQuickCreateActions(array $configs) {
$items = array();
if (!$configs) {
// No items to add.
} else if (count($configs) == 1) {
return array();
}
// If the viewer is logged in and can't create objects, don't show the
// menu item. If they're logged out, we assume they could create objects
// if they logged in, so we show the item as a hint about how to
// accomplish the action.
if ($this->getViewer()->isLoggedIn()) {
if (!$this->hasCreateCapability()) {
return array();
}
}
if (count($configs) == 1) {
$config = head($configs);
$items[] = $this->newQuickCreateItem($config);
$items[] = $this->newQuickCreateAction($config);
} else {
$group_name = $this->getQuickCreateMenuHeaderText();
@ -1994,7 +2008,7 @@ abstract class PhabricatorEditEngine
->setName($group_name);
foreach ($configs as $config) {
$items[] = $this->newQuickCreateItem($config)
$items[] = $this->newQuickCreateAction($config)
->setIndented(true);
}
}
@ -2017,7 +2031,7 @@ abstract class PhabricatorEditEngine
return $configs;
}
private function newQuickCreateItem(
private function newQuickCreateAction(
PhabricatorEditEngineConfiguration $config) {
$item_name = $config->getName();