@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Convert dashboard read/display pathways to the new panel storage format

Summary:
Depends on D20406. Ref T13272. This gets about half of Dashboards working with the new "duplicate panel friendly" storage format. Followups will fix the write pathways.

Collateral damage here includes:

- Remove the old Dashboard/Panel edge type. We have a new, more general edge type for "container X uses panel Y", and we don't need this edge type for anything else.
- Remove "attachPanels()" from Dashboard. Only rendering actually needs this, and it can just load the panels.
- Remove "attachPanelPHIDs()" from Dashboard. We can look at the panel refs to figure this out.
- Remove "attachProjects()" from Dashboard. Nothing uses this and it's not a very modern approach.
- `getPanelPHIDs()` just looks at the config now.
- Deleted some `LayoutConfig`-related code which is broken/obsolete.

Test Plan:
- Viewed various dashboards which were created before the changes, saw them render correctly.
- Viewed a dashboard with two of the same panel! AMAZING!

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272

Differential Revision: https://secure.phabricator.com/D20407

+189 -424
+4 -4
src/__phutil_library_map__.php
··· 2914 2914 'PhabricatorDashboardConsoleController' => 'applications/dashboard/controller/PhabricatorDashboardConsoleController.php', 2915 2915 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', 2916 2916 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 2917 - 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardDashboardHasPanelEdgeType.php', 2918 2917 'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php', 2919 2918 'PhabricatorDashboardDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardDatasource.php', 2920 2919 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardEditController.php', ··· 2945 2944 'PhabricatorDashboardPanelEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPanelEditConduitAPIMethod.php', 2946 2945 'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelEditController.php', 2947 2946 'PhabricatorDashboardPanelEditEngine' => 'applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php', 2948 - 'PhabricatorDashboardPanelHasDashboardEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardPanelHasDashboardEdgeType.php', 2949 2947 'PhabricatorDashboardPanelListController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelListController.php', 2950 2948 'PhabricatorDashboardPanelNameTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelNameTransaction.php', 2951 2949 'PhabricatorDashboardPanelNgrams' => 'applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php', 2952 2950 'PhabricatorDashboardPanelPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php', 2953 2951 'PhabricatorDashboardPanelPropertyTransaction' => 'applications/dashboard/xaction/panel/PhabricatorDashboardPanelPropertyTransaction.php', 2954 2952 'PhabricatorDashboardPanelQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelQuery.php', 2953 + 'PhabricatorDashboardPanelRef' => 'applications/dashboard/layoutconfig/PhabricatorDashboardPanelRef.php', 2954 + 'PhabricatorDashboardPanelRefList' => 'applications/dashboard/layoutconfig/PhabricatorDashboardPanelRefList.php', 2955 2955 'PhabricatorDashboardPanelRenderController' => 'applications/dashboard/controller/panel/PhabricatorDashboardPanelRenderController.php', 2956 2956 'PhabricatorDashboardPanelRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php', 2957 2957 'PhabricatorDashboardPanelSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php', ··· 8914 8914 'PhabricatorDashboardConsoleController' => 'PhabricatorDashboardController', 8915 8915 'PhabricatorDashboardController' => 'PhabricatorController', 8916 8916 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 8917 - 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'PhabricatorEdgeType', 8918 8917 'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType', 8919 8918 'PhabricatorDashboardDatasource' => 'PhabricatorTypeaheadDatasource', 8920 8919 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', ··· 8952 8951 'PhabricatorDashboardPanelEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 8953 8952 'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController', 8954 8953 'PhabricatorDashboardPanelEditEngine' => 'PhabricatorEditEngine', 8955 - 'PhabricatorDashboardPanelHasDashboardEdgeType' => 'PhabricatorEdgeType', 8956 8954 'PhabricatorDashboardPanelListController' => 'PhabricatorDashboardController', 8957 8955 'PhabricatorDashboardPanelNameTransaction' => 'PhabricatorDashboardPanelTransactionType', 8958 8956 'PhabricatorDashboardPanelNgrams' => 'PhabricatorSearchNgrams', 8959 8957 'PhabricatorDashboardPanelPHIDType' => 'PhabricatorPHIDType', 8960 8958 'PhabricatorDashboardPanelPropertyTransaction' => 'PhabricatorDashboardPanelTransactionType', 8961 8959 'PhabricatorDashboardPanelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 8960 + 'PhabricatorDashboardPanelRef' => 'Phobject', 8961 + 'PhabricatorDashboardPanelRefList' => 'Phobject', 8962 8962 'PhabricatorDashboardPanelRenderController' => 'PhabricatorDashboardController', 8963 8963 'PhabricatorDashboardPanelRenderingEngine' => 'Phobject', 8964 8964 'PhabricatorDashboardPanelSearchEngine' => 'PhabricatorApplicationSearchEngine',
-1
src/applications/dashboard/controller/PhabricatorDashboardAddPanelController.php
··· 10 10 $dashboard = id(new PhabricatorDashboardQuery()) 11 11 ->setViewer($viewer) 12 12 ->withIDs(array($id)) 13 - ->needPanels(true) 14 13 ->requireCapabilities( 15 14 array( 16 15 PhabricatorPolicyCapability::CAN_VIEW,
-1
src/applications/dashboard/controller/PhabricatorDashboardMovePanelController.php
··· 15 15 $dashboard = id(new PhabricatorDashboardQuery()) 16 16 ->setViewer($viewer) 17 17 ->withIDs(array($id)) 18 - ->needPanels(true) 19 18 ->requireCapabilities( 20 19 array( 21 20 PhabricatorPolicyCapability::CAN_VIEW,
-11
src/applications/dashboard/controller/PhabricatorDashboardRemovePanelController.php
··· 47 47 48 48 if ($request->isFormPost()) { 49 49 $xactions = array(); 50 - $xactions[] = id(new PhabricatorDashboardTransaction()) 51 - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 52 - ->setMetadataValue( 53 - 'edge:type', 54 - PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST) 55 - ->setNewValue( 56 - array( 57 - '-' => array( 58 - $v_panel => $v_panel, 59 - ), 60 - )); 61 50 62 51 $layout_config->removePanel($v_panel); 63 52 $dashboard->setLayoutConfigFromObject($layout_config);
-1
src/applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php
··· 14 14 $dashboard = id(new PhabricatorDashboardQuery()) 15 15 ->setViewer($viewer) 16 16 ->withIDs(array($id)) 17 - ->needPanels(true) 18 17 ->executeOne(); 19 18 if (!$dashboard) { 20 19 return new Aphront404Response();
-103
src/applications/dashboard/edge/PhabricatorDashboardDashboardHasPanelEdgeType.php
··· 1 - <?php 2 - 3 - final class PhabricatorDashboardDashboardHasPanelEdgeType 4 - extends PhabricatorEdgeType { 5 - 6 - const EDGECONST = 45; 7 - 8 - public function getInverseEdgeConstant() { 9 - return PhabricatorDashboardPanelHasDashboardEdgeType::EDGECONST; 10 - } 11 - 12 - public function shouldWriteInverseTransactions() { 13 - return true; 14 - } 15 - 16 - public function getTransactionAddString( 17 - $actor, 18 - $add_count, 19 - $add_edges) { 20 - 21 - return pht( 22 - '%s added %s panel(s): %s.', 23 - $actor, 24 - $add_count, 25 - $add_edges); 26 - } 27 - 28 - public function getTransactionRemoveString( 29 - $actor, 30 - $rem_count, 31 - $rem_edges) { 32 - 33 - return pht( 34 - '%s removed %s panel(s): %s.', 35 - $actor, 36 - $rem_count, 37 - $rem_edges); 38 - } 39 - 40 - public function getTransactionEditString( 41 - $actor, 42 - $total_count, 43 - $add_count, 44 - $add_edges, 45 - $rem_count, 46 - $rem_edges) { 47 - 48 - return pht( 49 - '%s edited panel(s), added %s: %s; removed %s: %s.', 50 - $actor, 51 - $add_count, 52 - $add_edges, 53 - $rem_count, 54 - $rem_edges); 55 - } 56 - 57 - public function getFeedAddString( 58 - $actor, 59 - $object, 60 - $add_count, 61 - $add_edges) { 62 - 63 - return pht( 64 - '%s added %s panel(s) for %s: %s.', 65 - $actor, 66 - $add_count, 67 - $object, 68 - $add_edges); 69 - } 70 - 71 - public function getFeedRemoveString( 72 - $actor, 73 - $object, 74 - $rem_count, 75 - $rem_edges) { 76 - 77 - return pht( 78 - '%s removed %s panel(s) for %s: %s.', 79 - $actor, 80 - $rem_count, 81 - $object, 82 - $rem_edges); 83 - } 84 - 85 - public function getFeedEditString( 86 - $actor, 87 - $object, 88 - $total_count, 89 - $add_count, 90 - $add_edges, 91 - $rem_count, 92 - $rem_edges) { 93 - 94 - return pht( 95 - '%s edited panel(s) for %s, added %s: %s; removed %s: %s.', 96 - $actor, 97 - $object, 98 - $add_count, 99 - $add_edges, 100 - $rem_count, 101 - $rem_edges); 102 - } 103 - }
-103
src/applications/dashboard/edge/PhabricatorDashboardPanelHasDashboardEdgeType.php
··· 1 - <?php 2 - 3 - final class PhabricatorDashboardPanelHasDashboardEdgeType 4 - extends PhabricatorEdgeType { 5 - 6 - const EDGECONST = 46; 7 - 8 - public function getInverseEdgeConstant() { 9 - return PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST; 10 - } 11 - 12 - public function shouldWriteInverseTransactions() { 13 - return true; 14 - } 15 - 16 - public function getTransactionAddString( 17 - $actor, 18 - $add_count, 19 - $add_edges) { 20 - 21 - return pht( 22 - '%s added %s dashboard(s): %s.', 23 - $actor, 24 - $add_count, 25 - $add_edges); 26 - } 27 - 28 - public function getTransactionRemoveString( 29 - $actor, 30 - $rem_count, 31 - $rem_edges) { 32 - 33 - return pht( 34 - '%s removed %s dashboard(s): %s.', 35 - $actor, 36 - $rem_count, 37 - $rem_edges); 38 - } 39 - 40 - public function getTransactionEditString( 41 - $actor, 42 - $total_count, 43 - $add_count, 44 - $add_edges, 45 - $rem_count, 46 - $rem_edges) { 47 - 48 - return pht( 49 - '%s edited dashboard(s), added %s: %s; removed %s: %s.', 50 - $actor, 51 - $add_count, 52 - $add_edges, 53 - $rem_count, 54 - $rem_edges); 55 - } 56 - 57 - public function getFeedAddString( 58 - $actor, 59 - $object, 60 - $add_count, 61 - $add_edges) { 62 - 63 - return pht( 64 - '%s added %s dashboard(s) for %s: %s.', 65 - $actor, 66 - $add_count, 67 - $object, 68 - $add_edges); 69 - } 70 - 71 - public function getFeedRemoveString( 72 - $actor, 73 - $object, 74 - $rem_count, 75 - $rem_edges) { 76 - 77 - return pht( 78 - '%s removed %s dashboard(s) for %s: %s.', 79 - $actor, 80 - $rem_count, 81 - $object, 82 - $rem_edges); 83 - } 84 - 85 - public function getFeedEditString( 86 - $actor, 87 - $object, 88 - $total_count, 89 - $add_count, 90 - $add_edges, 91 - $rem_count, 92 - $rem_edges) { 93 - 94 - return pht( 95 - '%s edited dashboard(s) for %s, added %s: %s; removed %s: %s.', 96 - $actor, 97 - $object, 98 - $add_count, 99 - $add_edges, 100 - $rem_count, 101 - $rem_edges); 102 - } 103 - }
-32
src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
··· 11 11 return pht('Dashboards'); 12 12 } 13 13 14 - public static function addPanelToDashboard( 15 - PhabricatorUser $actor, 16 - PhabricatorContentSource $content_source, 17 - PhabricatorDashboardPanel $panel, 18 - PhabricatorDashboard $dashboard, 19 - $column) { 20 - 21 - $xactions = array(); 22 - $xactions[] = id(new PhabricatorDashboardTransaction()) 23 - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 24 - ->setMetadataValue( 25 - 'edge:type', 26 - PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST) 27 - ->setNewValue( 28 - array( 29 - '+' => array( 30 - $panel->getPHID() => $panel->getPHID(), 31 - ), 32 - )); 33 - 34 - $layout_config = $dashboard->getLayoutConfigObject(); 35 - $layout_config->setPanelLocation($column, $panel->getPHID()); 36 - $dashboard->setLayoutConfigFromObject($layout_config); 37 - 38 - $editor = id(new PhabricatorDashboardTransactionEditor()) 39 - ->setActor($actor) 40 - ->setContentSource($content_source) 41 - ->setContinueOnMissingFields(true) 42 - ->setContinueOnNoEffect(true) 43 - ->applyTransactions($dashboard, $xactions); 44 - } 45 - 46 14 public function getTransactionTypes() { 47 15 $types = parent::getTransactionTypes(); 48 16
+37 -37
src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php
··· 31 31 32 32 public function renderDashboard() { 33 33 require_celerity_resource('phabricator-dashboard-css'); 34 - $dashboard = $this->dashboard; 35 - $viewer = $this->viewer; 34 + $dashboard = $this->getDashboard(); 35 + $viewer = $this->getViewer(); 36 36 37 37 $is_editable = $this->arrangeMode; 38 38 39 - $layout_config = $dashboard->getLayoutConfigObject(); 40 - $panel_grid_locations = $layout_config->getPanelLocations(); 41 - $panels = mpull($dashboard->getPanels(), null, 'getPHID'); 42 - $dashboard_id = celerity_generate_unique_node_id(); 43 - $result = id(new AphrontMultiColumnView()) 44 - ->setID($dashboard_id) 45 - ->setFluidLayout(true) 46 - ->setGutter(AphrontMultiColumnView::GUTTER_LARGE); 47 - 48 39 if ($is_editable) { 49 40 $h_mode = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_EDIT; 50 41 } else { 51 42 $h_mode = PhabricatorDashboardPanelRenderingEngine::HEADER_MODE_NORMAL; 52 43 } 53 44 54 - $panel_phids = array(); 55 - foreach ($panel_grid_locations as $panel_column_locations) { 56 - foreach ($panel_column_locations as $panel_phid) { 57 - $panel_phids[] = $panel_phid; 58 - } 45 + $panel_phids = $dashboard->getPanelPHIDs(); 46 + if ($panel_phids) { 47 + $panels = id(new PhabricatorDashboardPanelQuery()) 48 + ->setViewer($viewer) 49 + ->withPHIDs($panel_phids) 50 + ->execute(); 51 + $panels = mpull($panels, null, 'getPHID'); 52 + 53 + $handles = $viewer->loadHandles($panel_phids); 54 + } else { 55 + $panels = array(); 56 + $handles = array(); 59 57 } 60 - $handles = $viewer->loadHandles($panel_phids); 61 58 62 - foreach ($panel_grid_locations as $column => $panel_column_locations) { 63 - $panel_phids = $panel_column_locations; 59 + $ref_list = $dashboard->getPanelRefList(); 60 + $columns = $ref_list->getColumns(); 64 61 65 - // TODO: This list may contain duplicates when the dashboard itself 66 - // does not? Perhaps this is related to T10612. For now, just unique 67 - // the list before moving on. 68 - $panel_phids = array_unique($panel_phids); 62 + $dashboard_id = celerity_generate_unique_node_id(); 63 + 64 + $result = id(new AphrontMultiColumnView()) 65 + ->setID($dashboard_id) 66 + ->setFluidLayout(true) 67 + ->setGutter(AphrontMultiColumnView::GUTTER_LARGE); 68 + 69 + foreach ($columns as $column) { 70 + $column_views = array(); 71 + foreach ($column->getPanelRefs() as $panel_ref) { 72 + $panel_phid = $panel_ref->getPanelPHID(); 69 73 70 - $column_result = array(); 71 - foreach ($panel_phids as $panel_phid) { 72 74 $panel_engine = id(new PhabricatorDashboardPanelRenderingEngine()) 73 75 ->setViewer($viewer) 74 76 ->setDashboardID($dashboard->getID()) ··· 85 87 $panel_engine->setPanel($panel); 86 88 } 87 89 88 - $column_result[] = $panel_engine->renderPanel(); 90 + $column_views[] = $panel_engine->renderPanel(); 89 91 } 90 - $column_class = $layout_config->getColumnClass( 91 - $column, 92 - $is_editable); 92 + 93 + $column_classes = $column->getClasses(); 94 + 93 95 if ($is_editable) { 94 - $column_result[] = $this->renderAddPanelPlaceHolder($column); 95 - $column_result[] = $this->renderAddPanelUI($column); 96 + $column_views[] = $this->renderAddPanelPlaceHolder(); 97 + $column_views[] = $this->renderAddPanelUI($column->getColumnKey()); 96 98 } 99 + 97 100 $result->addColumn( 98 - $column_result, 99 - $column_class, 101 + $column_views, 102 + implode(' ', $column_classes), 100 103 $sigil = 'dashboard-column', 101 104 $metadata = array('columnID' => $column)); 102 105 } ··· 120 123 return $view; 121 124 } 122 125 123 - private function renderAddPanelPlaceHolder($column) { 124 - $dashboard = $this->dashboard; 125 - $panels = $dashboard->getPanels(); 126 - 126 + private function renderAddPanelPlaceHolder() { 127 127 return javelin_tag( 128 128 'span', 129 129 array(
+10
src/applications/dashboard/layoutconfig/PhabricatorDashboardColumn.php
··· 5 5 6 6 private $columnKey; 7 7 private $classes = array(); 8 + private $refs = array(); 8 9 9 10 public function setColumnKey($column_key) { 10 11 $this->columnKey = $column_key; ··· 22 23 23 24 public function getClasses() { 24 25 return $this->classes; 26 + } 27 + 28 + public function addPanelRef(PhabricatorDashboardPanelRef $ref) { 29 + $this->refs[] = $ref; 30 + return $this; 31 + } 32 + 33 + public function getPanelRefs() { 34 + return $this->refs; 25 35 } 26 36 27 37 }
+37
src/applications/dashboard/layoutconfig/PhabricatorDashboardPanelRef.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelRef 4 + extends Phobject { 5 + 6 + private $panelPHID; 7 + private $panelKey; 8 + private $columnKey; 9 + 10 + public function setPanelPHID($panel_phid) { 11 + $this->panelPHID = $panel_phid; 12 + return $this; 13 + } 14 + 15 + public function getPanelPHID() { 16 + return $this->panelPHID; 17 + } 18 + 19 + public function setColumnKey($column_key) { 20 + $this->columnKey = $column_key; 21 + return $this; 22 + } 23 + 24 + public function getColumnKey() { 25 + return $this->columnKey; 26 + } 27 + 28 + public function setPanelKey($panel_key) { 29 + $this->panelKey = $panel_key; 30 + return $this; 31 + } 32 + 33 + public function getPanelKey() { 34 + return $this->panelKey; 35 + } 36 + 37 + }
+76
src/applications/dashboard/layoutconfig/PhabricatorDashboardPanelRefList.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelRefList 4 + extends Phobject { 5 + 6 + private $refs; 7 + private $columns; 8 + 9 + public static function newFromDictionary($config) { 10 + if (!is_array($config)) { 11 + $config = array(); 12 + } 13 + 14 + $mode_map = PhabricatorDashboardLayoutMode::getAllLayoutModes(); 15 + $mode_key = idx($config, 'layoutMode'); 16 + if (!isset($mode_map[$mode_key])) { 17 + $mode_key = head_key($mode_map); 18 + } 19 + $mode = $mode_map[$mode_key]; 20 + 21 + $columns = $mode->getLayoutModeColumns(); 22 + $columns = mpull($columns, null, 'getColumnKey'); 23 + $default_column = head($columns); 24 + 25 + $panels = idx($config, 'panels'); 26 + if (!is_array($panels)) { 27 + $panels = array(); 28 + } 29 + 30 + $seen_panels = array(); 31 + $refs = array(); 32 + foreach ($panels as $panel) { 33 + $panel_phid = idx($panel, 'panelPHID'); 34 + if (!strlen($panel_phid)) { 35 + continue; 36 + } 37 + 38 + $panel_key = idx($panel, 'panelKey'); 39 + if (!strlen($panel_key)) { 40 + continue; 41 + } 42 + 43 + if (isset($seen_panels[$panel_key])) { 44 + continue; 45 + } 46 + $seen_panels[$panel_key] = true; 47 + 48 + $column_key = idx($panel, 'columnKey'); 49 + $column = idx($columns, $column_key, $default_column); 50 + 51 + $ref = id(new PhabricatorDashboardPanelRef()) 52 + ->setPanelPHID($panel_phid) 53 + ->setPanelKey($panel_key) 54 + ->setColumnKey($column->getColumnKey()); 55 + 56 + $column->addPanelRef($ref); 57 + $refs[] = $ref; 58 + } 59 + 60 + $list = new self(); 61 + 62 + $list->columns = $columns; 63 + $list->refs = $refs; 64 + 65 + return $list; 66 + } 67 + 68 + public function getColumns() { 69 + return $this->columns; 70 + } 71 + 72 + public function getPanelRefs() { 73 + return $this->refs; 74 + } 75 + 76 + }
-65
src/applications/dashboard/query/PhabricatorDashboardQuery.php
··· 9 9 private $authorPHIDs; 10 10 private $canEdit; 11 11 12 - private $needPanels; 13 - private $needProjects; 14 - 15 12 public function withIDs(array $ids) { 16 13 $this->ids = $ids; 17 14 return $this; ··· 32 29 return $this; 33 30 } 34 31 35 - public function needPanels($need_panels) { 36 - $this->needPanels = $need_panels; 37 - return $this; 38 - } 39 - 40 - public function needProjects($need_projects) { 41 - $this->needProjects = $need_projects; 42 - return $this; 43 - } 44 - 45 32 public function withCanEdit($can_edit) { 46 33 $this->canEdit = $can_edit; 47 34 return $this; ··· 72 59 PhabricatorPolicyCapability::CAN_EDIT, 73 60 )) 74 61 ->apply($dashboards); 75 - } 76 - 77 - if ($this->needPanels) { 78 - $edge_query = id(new PhabricatorEdgeQuery()) 79 - ->withSourcePHIDs($phids) 80 - ->withEdgeTypes( 81 - array( 82 - PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST, 83 - )); 84 - $edge_query->execute(); 85 - 86 - $panel_phids = $edge_query->getDestinationPHIDs(); 87 - if ($panel_phids) { 88 - // NOTE: We explicitly disable policy exceptions when loading panels. 89 - // If a particular panel is invalid or not visible to the viewer, 90 - // we'll still render the dashboard, just not that panel. 91 - 92 - $panels = id(new PhabricatorDashboardPanelQuery()) 93 - ->setParentQuery($this) 94 - ->setRaisePolicyExceptions(false) 95 - ->setViewer($this->getViewer()) 96 - ->withPHIDs($panel_phids) 97 - ->execute(); 98 - $panels = mpull($panels, null, 'getPHID'); 99 - } else { 100 - $panels = array(); 101 - } 102 - 103 - foreach ($dashboards as $dashboard) { 104 - $dashboard_phids = $edge_query->getDestinationPHIDs( 105 - array($dashboard->getPHID())); 106 - $dashboard_panels = array_select_keys($panels, $dashboard_phids); 107 - 108 - $dashboard->attachPanelPHIDs($dashboard_phids); 109 - $dashboard->attachPanels($dashboard_panels); 110 - } 111 - } 112 - 113 - if ($this->needProjects) { 114 - $edge_query = id(new PhabricatorEdgeQuery()) 115 - ->withSourcePHIDs($phids) 116 - ->withEdgeTypes( 117 - array( 118 - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, 119 - )); 120 - $edge_query->execute(); 121 - 122 - foreach ($dashboards as $dashboard) { 123 - $project_phids = $edge_query->getDestinationPHIDs( 124 - array($dashboard->getPHID())); 125 - $dashboard->attachProjectPHIDs($project_phids); 126 - } 127 62 } 128 63 129 64 return $dashboards;
+1 -12
src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
··· 12 12 } 13 13 14 14 public function newQuery() { 15 - return id(new PhabricatorDashboardQuery()) 16 - ->needPanels(true); 15 + return id(new PhabricatorDashboardQuery()); 17 16 } 18 17 19 18 public function canUseInPanelContext() { ··· 137 136 if ($dashboard->isArchived()) { 138 137 $item->setDisabled(true); 139 138 $bg_color = 'bg-grey'; 140 - } 141 - 142 - $panels = $dashboard->getPanels(); 143 - foreach ($panels as $panel) { 144 - $item->addAttribute($panel->getName()); 145 - } 146 - 147 - if (empty($panels)) { 148 - $empty = phutil_tag('em', array(), pht('No panels.')); 149 - $item->addAttribute($empty); 150 139 } 151 140 152 141 $icon = id(new PHUIIconView())
+24 -52
src/applications/dashboard/storage/PhabricatorDashboard.php
··· 24 24 const STATUS_ACTIVE = 'active'; 25 25 const STATUS_ARCHIVED = 'archived'; 26 26 27 - private $panelPHIDs = self::ATTACHABLE; 28 27 private $panels = self::ATTACHABLE; 29 28 private $edgeProjectPHIDs = self::ATTACHABLE; 30 29 30 + private $panelRefList; 31 31 32 32 public static function initializeNewDashboard(PhabricatorUser $actor) { 33 33 return id(new PhabricatorDashboard()) ··· 37 37 ->setEditPolicy($actor->getPHID()) 38 38 ->setStatus(self::STATUS_ACTIVE) 39 39 ->setAuthorPHID($actor->getPHID()) 40 - ->attachPanels(array()) 41 - ->attachPanelPHIDs(array()); 40 + ->attachPanels(array()); 42 41 } 43 42 44 43 public static function getStatusNameMap() { ··· 76 75 public function setRawLayoutMode($mode) { 77 76 $config = $this->getRawLayoutConfig(); 78 77 $config['layoutMode'] = $mode; 78 + 79 + // If a cached panel ref list exists, clear it. 80 + $this->panelRefList = null; 81 + 79 82 return $this->setLayoutConfig($config); 80 83 } 81 84 ··· 89 92 return $config; 90 93 } 91 94 92 - public function getLayoutConfigObject() { 93 - return PhabricatorDashboardLayoutConfig::newFromDictionary( 94 - $this->getLayoutConfig()); 95 + public function isArchived() { 96 + return ($this->getStatus() == self::STATUS_ARCHIVED); 95 97 } 96 98 97 - public function setLayoutConfigFromObject( 98 - PhabricatorDashboardLayoutConfig $object) { 99 - 100 - $this->setLayoutConfig($object->toDictionary()); 101 - 102 - // See PHI385. Dashboard panel mutations rely on changes to the Dashboard 103 - // object persisting when transactions are applied, but this assumption is 104 - // no longer valid after T13054. For now, just save the dashboard 105 - // explicitly. 106 - $this->save(); 107 - 108 - return $this; 99 + public function getURI() { 100 + return urisprintf('/dashboard/view/%d/', $this->getID()); 109 101 } 110 102 111 - public function getProjectPHIDs() { 112 - return $this->assertAttached($this->edgeProjectPHIDs); 103 + public function getObjectName() { 104 + return pht('Dashboard %d', $this->getID()); 113 105 } 114 106 115 - public function attachProjectPHIDs(array $phids) { 116 - $this->edgeProjectPHIDs = $phids; 117 - return $this; 107 + public function getPanelRefList() { 108 + if (!$this->panelRefList) { 109 + $this->panelRefList = $this->newPanelRefList(); 110 + } 111 + return $this->panelRefList; 118 112 } 119 113 120 - public function attachPanelPHIDs(array $phids) { 121 - $this->panelPHIDs = $phids; 122 - return $this; 114 + private function newPanelRefList() { 115 + $raw_config = $this->getLayoutConfig(); 116 + return PhabricatorDashboardPanelRefList::newFromDictionary($raw_config); 123 117 } 124 118 125 119 public function getPanelPHIDs() { 126 - return $this->assertAttached($this->panelPHIDs); 127 - } 128 - 129 - public function attachPanels(array $panels) { 130 - assert_instances_of($panels, 'PhabricatorDashboardPanel'); 131 - $this->panels = $panels; 132 - return $this; 133 - } 134 - 135 - public function getPanels() { 136 - return $this->assertAttached($this->panels); 137 - } 138 - 139 - public function isArchived() { 140 - return ($this->getStatus() == self::STATUS_ARCHIVED); 141 - } 142 - 143 - public function getURI() { 144 - return urisprintf('/dashboard/view/%d/', $this->getID()); 145 - } 146 - 147 - public function getObjectName() { 148 - return pht('Dashboard %d', $this->getID()); 120 + $ref_list = $this->getPanelRefList(); 121 + $phids = mpull($ref_list->getPanelRefs(), 'getPanelPHID'); 122 + return array_unique($phids); 149 123 } 150 124 151 125 /* -( PhabricatorApplicationTransactionInterface )------------------------- */ ··· 216 190 /* -( PhabricatorDashboardPanelContainerInterface )------------------------ */ 217 191 218 192 public function getDashboardPanelContainerPanelPHIDs() { 219 - return PhabricatorEdgeQuery::loadDestinationPHIDs( 220 - $this->getPHID(), 221 - PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST); 193 + return $this->getPanelPHIDs(); 222 194 } 223 195 224 196 }
-1
src/applications/dashboard/storage/PhabricatorDashboardInstall.php
··· 43 43 $dashboard = id(new PhabricatorDashboardQuery()) 44 44 ->setViewer($viewer) 45 45 ->withPHIDs(array($dashboard_install->getDashboardPHID())) 46 - ->needPanels(true) 47 46 ->executeOne(); 48 47 } 49 48
-1
src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php
··· 54 54 $dashboard = id(new PhabricatorDashboardQuery()) 55 55 ->setViewer($viewer) 56 56 ->withPHIDs(array($dashboard_phid)) 57 - ->needPanels(true) 58 57 ->executeOne(); 59 58 if (!$dashboard) { 60 59 return $this->newEmptyView(