diff --git a/bin/hunks b/bin/hunks deleted file mode 120000 index dc2cf5492e..0000000000 --- a/bin/hunks +++ /dev/null @@ -1 +0,0 @@ -../scripts/setup/manage_hunks.php \ No newline at end of file diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 7771a79107..db83e57fc0 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '0b64e988', 'conpherence.pkg.js' => '6249a1cf', - 'core.pkg.css' => '35e6c1ed', + 'core.pkg.css' => '55d12594', 'core.pkg.js' => 'e4260032', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => 'a4ba74b5', @@ -18,10 +18,10 @@ return array( 'diffusion.pkg.js' => '84c8f8fd', 'favicon.ico' => '30672e08', 'maniphest.pkg.css' => '4845691a', - 'maniphest.pkg.js' => '949a7498', + 'maniphest.pkg.js' => '5ab2753f', 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', 'rsrc/css/aphront/dark-console.css' => 'f54bf286', - 'rsrc/css/aphront/dialog-view.css' => '49b2a8a3', + 'rsrc/css/aphront/dialog-view.css' => '938f52c5', 'rsrc/css/aphront/list-filter-view.css' => '5d6f0526', 'rsrc/css/aphront/multi-column.css' => '84cc6640', 'rsrc/css/aphront/notification.css' => '3f6c89c9', @@ -42,7 +42,7 @@ return array( 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/config/config-options.css' => '0ede4c9b', - 'rsrc/css/application/config/config-page.css' => 'b80124ae', + 'rsrc/css/application/config/config-page.css' => 'c1d5121b', 'rsrc/css/application/config/config-template.css' => '8f18fa41', 'rsrc/css/application/config/setup-issue.css' => 'f794cfc3', 'rsrc/css/application/config/unhandled-exception.css' => '4c96257a', @@ -71,7 +71,7 @@ return array( 'rsrc/css/application/diffusion/diffusion-source.css' => '68b30fd3', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2', - 'rsrc/css/application/flag/flag.css' => '5337623f', + 'rsrc/css/application/flag/flag.css' => 'bba8f811', 'rsrc/css/application/harbormaster/harbormaster.css' => 'f491c9f4', 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 'rsrc/css/application/herald/herald.css' => 'dc31f6e9', @@ -83,7 +83,7 @@ return array( 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => '1898e534', 'rsrc/css/application/people/people-profile.css' => '2473d929', - 'rsrc/css/application/phame/phame.css' => '654dd9ef', + 'rsrc/css/application/phame/phame.css' => 'aeb61182', 'rsrc/css/application/pholio/pholio-edit.css' => '07676f51', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio.css' => 'ca89d380', @@ -97,13 +97,13 @@ return array( 'rsrc/css/application/policy/policy.css' => '957ea14c', 'rsrc/css/application/ponder/ponder-view.css' => 'fbd45f96', 'rsrc/css/application/project/project-card-view.css' => '9418c97d', - 'rsrc/css/application/project/project-view.css' => '55d99221', + 'rsrc/css/application/project/project-view.css' => '1e6f7072', 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/search/application-search-view.css' => '8452c849', - 'rsrc/css/application/search/search-results.css' => '7dea472c', + 'rsrc/css/application/search/search-results.css' => '64ad079a', 'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', @@ -117,23 +117,29 @@ return array( 'rsrc/css/font/font-lato.css' => 'c7ccd872', 'rsrc/css/font/phui-font-icon-base.css' => '870a7360', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', - 'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983', + 'rsrc/css/layout/phabricator-source-code-view.css' => '4383192f', 'rsrc/css/phui/calendar/phui-calendar-day.css' => '572b1893', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'fcc9fb41', 'rsrc/css/phui/calendar/phui-calendar-month.css' => '8e10e92c', 'rsrc/css/phui/calendar/phui-calendar.css' => '477acfaa', + 'rsrc/css/phui/object-item/phui-oi-big-ui.css' => '19f9369b', + 'rsrc/css/phui/object-item/phui-oi-color.css' => 'cd2b9b77', + 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'f12cbc9f', + 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6', + 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'bff632a4', + 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea', 'rsrc/css/phui/phui-action-list.css' => 'e1d48300', 'rsrc/css/phui/phui-action-panel.css' => '91c7b835', 'rsrc/css/phui/phui-badge.css' => '3baef8db', 'rsrc/css/phui/phui-basic-nav-view.css' => '7093573b', 'rsrc/css/phui/phui-big-info-view.css' => 'bd903741', - 'rsrc/css/phui/phui-box.css' => '5c8387cf', - 'rsrc/css/phui/phui-button.css' => '4a5fbe3d', + 'rsrc/css/phui/phui-box.css' => '33b629f8', + 'rsrc/css/phui/phui-button.css' => '43f4912e', 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 'rsrc/css/phui/phui-cms.css' => 'be43c8a8', 'rsrc/css/phui/phui-comment-form.css' => 'c953b75e', 'rsrc/css/phui/phui-comment-panel.css' => 'f50152ad', - 'rsrc/css/phui/phui-crumbs-view.css' => '195ac419', + 'rsrc/css/phui/phui-crumbs-view.css' => 'f82868f2', 'rsrc/css/phui/phui-curtain-view.css' => '947bf1a4', 'rsrc/css/phui/phui-document-pro.css' => 'c354e312', 'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf', @@ -154,7 +160,6 @@ return array( 'rsrc/css/phui/phui-lightbox.css' => '0a035e40', 'rsrc/css/phui/phui-list.css' => '9da2aa00', 'rsrc/css/phui/phui-object-box.css' => '6b487c57', - 'rsrc/css/phui/phui-object-item-list-view.css' => '87278fa0', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', 'rsrc/css/phui/phui-profile-menu.css' => '4768721a', @@ -163,13 +168,13 @@ return array( 'rsrc/css/phui/phui-segment-bar-view.css' => '46342871', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => 'd5263e49', - 'rsrc/css/phui/phui-tag-view.css' => '6bbd83e2', + 'rsrc/css/phui/phui-tag-view.css' => '84d65f26', 'rsrc/css/phui/phui-timeline-view.css' => 'bc523970', - 'rsrc/css/phui/phui-two-column-view.css' => 'ee61d056', + 'rsrc/css/phui/phui-two-column-view.css' => '7babf5b9', 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'b60ef38a', 'rsrc/css/phui/workboards/phui-workboard.css' => '16441d5e', - 'rsrc/css/phui/workboards/phui-workcard.css' => '0c62d7c5', - 'rsrc/css/phui/workboards/phui-workpanel.css' => '92197373', + 'rsrc/css/phui/workboards/phui-workcard.css' => '00979e40', + 'rsrc/css/phui/workboards/phui-workpanel.css' => 'a3a63478', 'rsrc/css/sprite-login.css' => '587d92d7', 'rsrc/css/sprite-tokens.css' => '9cdfd599', 'rsrc/css/syntax/syntax-default.css' => '9923583c', @@ -420,7 +425,7 @@ return array( 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', 'rsrc/js/application/maniphest/behavior-batch-editor.js' => '782ab6e7', - 'rsrc/js/application/maniphest/behavior-batch-selector.js' => '7b98d7c5', + 'rsrc/js/application/maniphest/behavior-batch-selector.js' => '0825c27a', 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'e4232876', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '71237763', @@ -544,7 +549,7 @@ return array( 'almanac-css' => 'dbb9b3af', 'aphront-bars' => '231ac33c', 'aphront-dark-console-css' => 'f54bf286', - 'aphront-dialog-view-css' => '49b2a8a3', + 'aphront-dialog-view-css' => '938f52c5', 'aphront-list-filter-view-css' => '5d6f0526', 'aphront-multi-column-view-css' => '84cc6640', 'aphront-panel-view-css' => '8427b78d', @@ -558,7 +563,7 @@ return array( 'changeset-view-manager' => 'a2828756', 'conduit-api-css' => '7bc725c4', 'config-options-css' => '0ede4c9b', - 'config-page-css' => 'b80124ae', + 'config-page-css' => 'c1d5121b', 'conpherence-durable-column-view' => 'd82e130c', 'conpherence-header-pane-css' => '1c81cda6', 'conpherence-menu-css' => '4f51db5a', @@ -654,7 +659,7 @@ return array( 'javelin-behavior-line-chart' => 'e4232876', 'javelin-behavior-load-blame' => '42126667', 'javelin-behavior-maniphest-batch-editor' => '782ab6e7', - 'javelin-behavior-maniphest-batch-selector' => '7b98d7c5', + 'javelin-behavior-maniphest-batch-selector' => '0825c27a', 'javelin-behavior-maniphest-list-editor' => 'a9f88de2', 'javelin-behavior-maniphest-subpriority-editor' => '71237763', 'javelin-behavior-owners-path-editor' => '7a68dda3', @@ -790,7 +795,7 @@ return array( 'phabricator-feed-css' => 'ecd4ec57', 'phabricator-file-upload' => '680ea2c8', 'phabricator-filetree-view-css' => 'fccf9f82', - 'phabricator-flag-css' => '5337623f', + 'phabricator-flag-css' => 'bba8f811', 'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut-manager' => '4a021c10', 'phabricator-main-menu-view' => 'f03e17be', @@ -802,10 +807,10 @@ return array( 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => '8d40ae75', 'phabricator-remarkup-css' => '8606d9c6', - 'phabricator-search-results-css' => '7dea472c', + 'phabricator-search-results-css' => '64ad079a', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-slowvote-css' => 'a94b7230', - 'phabricator-source-code-view-css' => 'cbeef983', + 'phabricator-source-code-view-css' => '4383192f', 'phabricator-standard-page-view' => '894d8a25', 'phabricator-textareautils' => '320810c8', 'phabricator-title' => '485aaa6c', @@ -822,7 +827,7 @@ return array( 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 'phabricator-zindex-css' => 'd1270942', - 'phame-css' => '654dd9ef', + 'phame-css' => 'aeb61182', 'pholio-css' => 'ca89d380', 'pholio-edit-css' => '07676f51', 'pholio-inline-comments-css' => '8e545e49', @@ -836,8 +841,8 @@ return array( 'phui-badge-view-css' => '3baef8db', 'phui-basic-nav-view-css' => '7093573b', 'phui-big-info-view-css' => 'bd903741', - 'phui-box-css' => '5c8387cf', - 'phui-button-css' => '4a5fbe3d', + 'phui-box-css' => '33b629f8', + 'phui-button-css' => '43f4912e', 'phui-calendar-css' => '477acfaa', 'phui-calendar-day-css' => '572b1893', 'phui-calendar-list-css' => 'fcc9fb41', @@ -846,7 +851,7 @@ return array( 'phui-cms-css' => 'be43c8a8', 'phui-comment-form-css' => 'c953b75e', 'phui-comment-panel-css' => 'f50152ad', - 'phui-crumbs-view-css' => '195ac419', + 'phui-crumbs-view-css' => 'f82868f2', 'phui-curtain-view-css' => '947bf1a4', 'phui-document-summary-view-css' => '9ca48bdf', 'phui-document-view-css' => 'c32e8dec', @@ -870,7 +875,12 @@ return array( 'phui-lightbox-css' => '0a035e40', 'phui-list-view-css' => '9da2aa00', 'phui-object-box-css' => '6b487c57', - 'phui-object-item-list-view-css' => '87278fa0', + 'phui-oi-big-ui-css' => '19f9369b', + 'phui-oi-color-css' => 'cd2b9b77', + 'phui-oi-drag-ui-css' => 'f12cbc9f', + 'phui-oi-flush-ui-css' => '9d9685d6', + 'phui-oi-list-view-css' => 'bff632a4', + 'phui-oi-simple-ui-css' => 'a8beebea', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', 'phui-profile-menu-css' => '4768721a', @@ -879,14 +889,14 @@ return array( 'phui-segment-bar-view-css' => '46342871', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => 'd5263e49', - 'phui-tag-view-css' => '6bbd83e2', + 'phui-tag-view-css' => '84d65f26', 'phui-theme-css' => '798c69b8', 'phui-timeline-view-css' => 'bc523970', - 'phui-two-column-view-css' => 'ee61d056', + 'phui-two-column-view-css' => '7babf5b9', 'phui-workboard-color-css' => 'b60ef38a', 'phui-workboard-view-css' => '16441d5e', - 'phui-workcard-view-css' => '0c62d7c5', - 'phui-workpanel-view-css' => '92197373', + 'phui-workcard-view-css' => '00979e40', + 'phui-workpanel-view-css' => 'a3a63478', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', 'phuix-autocomplete' => '6d86ce8b', @@ -898,7 +908,7 @@ return array( 'policy-transaction-detail-css' => '82100a43', 'ponder-view-css' => 'fbd45f96', 'project-card-view-css' => '9418c97d', - 'project-view-css' => '55d99221', + 'project-view-css' => '1e6f7072', 'releeph-core' => '9b3c5733', 'releeph-preview-branch' => 'b7a6f4a5', 'releeph-request-differential-create-dialog' => '8d8b92cd', @@ -961,6 +971,12 @@ return array( 'phabricator-prefab', 'phuix-icon-view', ), + '0825c27a' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + ), '08675c6d' => array( 'javelin-behavior', 'javelin-behavior-device', @@ -1040,6 +1056,9 @@ return array( '185bbd53' => array( 'javelin-install', ), + '19f9369b' => array( + 'phui-oi-list-view-css', + ), '1aa4c968' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1522,12 +1541,6 @@ return array( 'owners-path-editor', 'javelin-behavior', ), - '7b98d7c5' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - ), '7cbe244b' => array( 'javelin-install', 'javelin-util', @@ -1650,9 +1663,6 @@ return array( 'javelin-dom', 'javelin-request', ), - 92197373 => array( - 'phui-workcard-view-css', - ), '92b9ec77' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1718,6 +1728,9 @@ return array( 'javelin-workflow', 'javelin-stratcom', ), + '9d9685d6' => array( + 'phui-oi-list-view-css', + ), '9f36c42d' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1747,6 +1760,9 @@ return array( 'javelin-behavior-device', 'javelin-vector', ), + 'a3a63478' => array( + 'phui-workcard-view-css', + ), 'a464fe03' => array( 'javelin-behavior', 'javelin-uri', @@ -1762,6 +1778,9 @@ return array( 'javelin-stratcom', 'javelin-dom', ), + 'a8beebea' => array( + 'phui-oi-list-view-css', + ), 'a8d8459d' => array( 'javelin-behavior', 'javelin-dom', @@ -1980,6 +1999,9 @@ return array( 'javelin-util', 'phabricator-notification-css', ), + 'cd2b9b77' => array( + 'phui-oi-list-view-css', + ), 'd0c516d5' => array( 'javelin-behavior', 'javelin-dom', @@ -2149,6 +2171,9 @@ return array( 'f03e17be' => array( 'phui-theme-css', ), + 'f12cbc9f' => array( + 'phui-oi-list-view-css', + ), 'f2e58483' => array( 'javelin-behavior', 'javelin-dom', @@ -2285,7 +2310,12 @@ return array( 'phabricator-nav-view-css', 'phui-basic-nav-view-css', 'phui-crumbs-view-css', - 'phui-object-item-list-view-css', + 'phui-oi-list-view-css', + 'phui-oi-color-css', + 'phui-oi-big-ui-css', + 'phui-oi-drag-ui-css', + 'phui-oi-simple-ui-css', + 'phui-oi-flush-ui-css', 'global-drag-and-drop-css', 'phui-spacing-css', 'phui-form-css', diff --git a/resources/celerity/packages.php b/resources/celerity/packages.php index affa180dc1..95cf5303ef 100644 --- a/resources/celerity/packages.php +++ b/resources/celerity/packages.php @@ -117,7 +117,12 @@ return array( 'phabricator-nav-view-css', 'phui-basic-nav-view-css', 'phui-crumbs-view-css', - 'phui-object-item-list-view-css', + 'phui-oi-list-view-css', + 'phui-oi-color-css', + 'phui-oi-big-ui-css', + 'phui-oi-drag-ui-css', + 'phui-oi-simple-ui-css', + 'phui-oi-flush-ui-css', 'global-drag-and-drop-css', 'phui-spacing-css', 'phui-form-css', diff --git a/resources/sql/autopatches/20140521.projectslug.2.mig.php b/resources/sql/autopatches/20140521.projectslug.2.mig.php index ca6ccf886a..e0ad4b5070 100644 --- a/resources/sql/autopatches/20140521.projectslug.2.mig.php +++ b/resources/sql/autopatches/20140521.projectslug.2.mig.php @@ -4,27 +4,30 @@ $project_table = new PhabricatorProject(); $table_name = $project_table->getTableName(); $conn_w = $project_table->establishConnection('w'); $slug_table_name = id(new PhabricatorProjectSlug())->getTableName(); -$time = time(); +$time = PhabricatorTime::getNow(); -echo pht('Migrating project phriction slugs...')."\n"; +echo pht('Migrating projects to slugs...')."\n"; foreach (new LiskMigrationIterator($project_table) as $project) { $id = $project->getID(); echo pht('Migrating project %d...', $id)."\n"; - $phriction_slug = rtrim($project->getPhrictionSlug(), '/'); + + $slug_text = PhabricatorSlug::normalizeProjectSlug($project->getName()); $slug = id(new PhabricatorProjectSlug()) - ->loadOneWhere('slug = %s', $phriction_slug); + ->loadOneWhere('slug = %s', $slug_text); + if ($slug) { echo pht('Already migrated %d... Continuing.', $id)."\n"; continue; } + queryfx( $conn_w, 'INSERT INTO %T (projectPHID, slug, dateCreated, dateModified) '. 'VALUES (%s, %s, %d, %d)', $slug_table_name, $project->getPHID(), - $phriction_slug, + $slug_text, $time, $time); echo pht('Migrated %d.', $id)."\n"; diff --git a/resources/sql/autopatches/20160122.project.1.boarddefault.php b/resources/sql/autopatches/20160122.project.1.boarddefault.php index 8765184629..0ffce8d834 100644 --- a/resources/sql/autopatches/20160122.project.1.boarddefault.php +++ b/resources/sql/autopatches/20160122.project.1.boarddefault.php @@ -7,7 +7,7 @@ $project_table = new PhabricatorProject(); $conn_w = $project_table->establishConnection('w'); -$panel_table = id(new PhabricatorProfilePanelConfiguration()); +$panel_table = id(new PhabricatorProfileMenuItemConfiguration()); $panel_conn = $panel_table->establishConnection('w'); foreach (new LiskMigrationIterator($project_table) as $project) { @@ -50,9 +50,9 @@ foreach (new LiskMigrationIterator($project_table) as $project) { $panel_table->getTableName(), $panel_table->generatePHID(), $project->getPHID(), - PhabricatorProjectWorkboardProfilePanel::PANELKEY, - PhabricatorProject::PANEL_WORKBOARD, - PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT, + PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY, + PhabricatorProject::ITEM_WORKBOARD, + PhabricatorProfileMenuItemConfiguration::VISIBILITY_DEFAULT, '{}', 2, PhabricatorTime::getNow(), diff --git a/resources/sql/autopatches/20161210.dashboards.01.author.sql b/resources/sql/autopatches/20161210.dashboards.01.author.sql new file mode 100644 index 0000000000..405ed5727c --- /dev/null +++ b/resources/sql/autopatches/20161210.dashboards.01.author.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard + ADD authorPHID VARBINARY(64) NOT NULL; diff --git a/resources/sql/autopatches/20161210.dashboards.02.author.php b/resources/sql/autopatches/20161210.dashboards.02.author.php new file mode 100644 index 0000000000..84f6fbf8d7 --- /dev/null +++ b/resources/sql/autopatches/20161210.dashboards.02.author.php @@ -0,0 +1,39 @@ +establishConnection('w'); + +$txn_table = new PhabricatorDashboardTransaction(); +$txn_conn = $table->establishConnection('r'); + +echo pht("Building Dashboard authorPHIDs...\n"); + +foreach (new LiskMigrationIterator($table) as $dashboard) { + + if ($dashboard->getAuthorPHID()) { + continue; + } + + $author_row = queryfx_one( + $txn_conn, + 'SELECT authorPHID FROM %T WHERE objectPHID = %s ORDER BY id ASC LIMIT 1', + $txn_table->getTableName(), + $dashboard->getPHID()); + + if (!$author_row) { + $author_phid = id(new PhabricatorDashboardApplication())->getPHID(); + } else { + $author_phid = $author_row['authorPHID']; + } + + queryfx( + $conn_w, + 'UPDATE %T SET authorPHID = %s WHERE id = %d', + $table->getTableName(), + $author_phid, + $dashboard->getID()); +} + +echo pht("Done\n"); diff --git a/resources/sql/autopatches/20161211.menu.01.itemkey.sql b/resources/sql/autopatches/20161211.menu.01.itemkey.sql new file mode 100644 index 0000000000..71bfe257f0 --- /dev/null +++ b/resources/sql/autopatches/20161211.menu.01.itemkey.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration + CHANGE panelKey menuItemKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20161211.menu.02.itemprops.sql b/resources/sql/autopatches/20161211.menu.02.itemprops.sql new file mode 100644 index 0000000000..cb9e296d42 --- /dev/null +++ b/resources/sql/autopatches/20161211.menu.02.itemprops.sql @@ -0,0 +1,3 @@ +ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration + CHANGE panelProperties menuItemProperties + LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20161211.menu.03.order.sql b/resources/sql/autopatches/20161211.menu.03.order.sql new file mode 100644 index 0000000000..01291ad4c6 --- /dev/null +++ b/resources/sql/autopatches/20161211.menu.03.order.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration + CHANGE panelOrder menuItemOrder INT UNSIGNED; diff --git a/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql b/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql new file mode 100644 index 0000000000..00c52d19cb --- /dev/null +++ b/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard_panel + ADD authorPHID VARBINARY(64) NOT NULL; diff --git a/resources/sql/autopatches/20161212.dashboardpanel.02.author.php b/resources/sql/autopatches/20161212.dashboardpanel.02.author.php new file mode 100644 index 0000000000..bc87aef91c --- /dev/null +++ b/resources/sql/autopatches/20161212.dashboardpanel.02.author.php @@ -0,0 +1,39 @@ +establishConnection('w'); + +$txn_table = new PhabricatorDashboardPanelTransaction(); +$txn_conn = $table->establishConnection('r'); + +echo pht("Building Dashboard Panel authorPHIDs...\n"); + +foreach (new LiskMigrationIterator($table) as $panel) { + + if ($panel->getAuthorPHID()) { + continue; + } + + $panel_row = queryfx_one( + $txn_conn, + 'SELECT authorPHID FROM %T WHERE objectPHID = %s ORDER BY id ASC LIMIT 1', + $txn_table->getTableName(), + $panel->getPHID()); + + if (!$panel_row) { + $author_phid = id(new PhabricatorDashboardApplication())->getPHID(); + } else { + $author_phid = $panel_row['authorPHID']; + } + + queryfx( + $conn_w, + 'UPDATE %T SET authorPHID = %s WHERE id = %d', + $table->getTableName(), + $author_phid, + $panel->getID()); +} + +echo pht("Done\n"); diff --git a/resources/sql/autopatches/20161212.dashboards.01.icon.sql b/resources/sql/autopatches/20161212.dashboards.01.icon.sql new file mode 100644 index 0000000000..e2783ab5bc --- /dev/null +++ b/resources/sql/autopatches/20161212.dashboards.01.icon.sql @@ -0,0 +1,5 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard + ADD icon VARCHAR(32) NOT NULL; + +UPDATE {$NAMESPACE}_dashboard.dashboard + SET icon = 'fa-dashboard'; diff --git a/resources/sql/autopatches/20161213.diff.01.hunks.php b/resources/sql/autopatches/20161213.diff.01.hunks.php new file mode 100644 index 0000000000..c6394defce --- /dev/null +++ b/resources/sql/autopatches/20161213.diff.01.hunks.php @@ -0,0 +1,38 @@ +establishConnection('w'); +$src_table = 'differential_hunk'; +$dst_table = 'differential_hunk_modern'; + +echo tsprintf( + "%s\n", + pht('Migrating old hunks...')); + +foreach (new LiskRawMigrationIterator($conn, $src_table) as $row) { + queryfx( + $conn, + 'INSERT INTO %T + (changesetID, oldOffset, oldLen, newOffset, newLen, + dataType, dataEncoding, dataFormat, data, + dateCreated, dateModified) + VALUES + (%d, %d, %d, %d, %d, + %s, %s, %s, %s, + %d, %d)', + $dst_table, + $row['changesetID'], + $row['oldOffset'], + $row['oldLen'], + $row['newOffset'], + $row['newLen'], + DifferentialModernHunk::DATATYPE_TEXT, + 'utf8', + DifferentialModernHunk::DATAFORMAT_RAW, + $row['changes'], + $row['dateCreated'], + $row['dateModified']); +} + +echo tsprintf( + "%s\n", + pht('Done.')); diff --git a/resources/sql/autopatches/20161216.dashboard.ngram.01.sql b/resources/sql/autopatches/20161216.dashboard.ngram.01.sql new file mode 100644 index 0000000000..8fd237fe82 --- /dev/null +++ b/resources/sql/autopatches/20161216.dashboard.ngram.01.sql @@ -0,0 +1,15 @@ +CREATE TABLE {$NAMESPACE}_dashboard.dashboard_dashboard_ngrams ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + objectID INT UNSIGNED NOT NULL, + ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, + KEY `key_object` (objectID), + KEY `key_ngram` (ngram, objectID) +) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; + +CREATE TABLE {$NAMESPACE}_dashboard.dashboard_dashboardpanel_ngrams ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + objectID INT UNSIGNED NOT NULL, + ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, + KEY `key_object` (objectID), + KEY `key_ngram` (ngram, objectID) +) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20161216.dashboard.ngram.02.php b/resources/sql/autopatches/20161216.dashboard.ngram.02.php new file mode 100644 index 0000000000..a7abc99b23 --- /dev/null +++ b/resources/sql/autopatches/20161216.dashboard.ngram.02.php @@ -0,0 +1,21 @@ +getPHID(), + array( + 'force' => true, + )); +} + +$table_dbp = new PhabricatorDashboardPanel(); + +foreach (new LiskMigrationIterator($table_dbp) as $panel) { + PhabricatorSearchWorker::queueDocumentForIndexing( + $panel->getPHID(), + array( + 'force' => true, + )); +} diff --git a/resources/sql/patches/090.forceuniqueprojectnames.php b/resources/sql/patches/090.forceuniqueprojectnames.php index a3e029d50a..486856c1c3 100644 --- a/resources/sql/patches/090.forceuniqueprojectnames.php +++ b/resources/sql/patches/090.forceuniqueprojectnames.php @@ -96,7 +96,9 @@ function rename_project($project, $projects) { if ($other->getID() == $project->getID()) { continue; } - if ($other->getPhrictionSlug() == $new_slug) { + + $other_slug = PhabricatorSlug::normalizeProjectSlug($other->getName()); + if ($other_slug == $new_slug) { $okay = false; break; } diff --git a/scripts/setup/manage_hunks.php b/scripts/setup/manage_hunks.php deleted file mode 100755 index a2d35779de..0000000000 --- a/scripts/setup/manage_hunks.php +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env php -setTagline(pht('manage hunks')); -$args->setSynopsis(<<parseStandardArguments(); - -$workflows = id(new PhutilClassMapQuery()) - ->setAncestorClass('PhabricatorHunksManagementWorkflow') - ->execute(); -$workflows[] = new PhutilHelpArgumentWorkflow(); -$args->parseWorkflows($workflows); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 97799da03e..b3438afc96 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -351,10 +351,10 @@ phutil_register_library_map(array( 'DifferentialAddCommentView' => 'applications/differential/view/DifferentialAddCommentView.php', 'DifferentialAdjustmentMapTestCase' => 'applications/differential/storage/__tests__/DifferentialAdjustmentMapTestCase.php', 'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php', - 'DifferentialApplyPatchField' => 'applications/differential/customfield/DifferentialApplyPatchField.php', 'DifferentialAsanaRepresentationField' => 'applications/differential/customfield/DifferentialAsanaRepresentationField.php', + 'DifferentialAuditorsCommitMessageField' => 'applications/differential/field/DifferentialAuditorsCommitMessageField.php', 'DifferentialAuditorsField' => 'applications/differential/customfield/DifferentialAuditorsField.php', - 'DifferentialAuthorField' => 'applications/differential/customfield/DifferentialAuthorField.php', + 'DifferentialBlameRevisionCommitMessageField' => 'applications/differential/field/DifferentialBlameRevisionCommitMessageField.php', 'DifferentialBlameRevisionField' => 'applications/differential/customfield/DifferentialBlameRevisionField.php', 'DifferentialBlockHeraldAction' => 'applications/differential/herald/DifferentialBlockHeraldAction.php', 'DifferentialBlockingReviewerDatasource' => 'applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php', @@ -379,15 +379,16 @@ phutil_register_library_map(array( 'DifferentialChangesetTwoUpRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpRenderer.php', 'DifferentialChangesetTwoUpTestRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpTestRenderer.php', 'DifferentialChangesetViewController' => 'applications/differential/controller/DifferentialChangesetViewController.php', - 'DifferentialChildRevisionsField' => 'applications/differential/customfield/DifferentialChildRevisionsField.php', 'DifferentialCloseConduitAPIMethod' => 'applications/differential/conduit/DifferentialCloseConduitAPIMethod.php', 'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php', 'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php', + 'DifferentialCommitMessageCustomField' => 'applications/differential/field/DifferentialCommitMessageCustomField.php', + 'DifferentialCommitMessageField' => 'applications/differential/field/DifferentialCommitMessageField.php', 'DifferentialCommitMessageParser' => 'applications/differential/parser/DifferentialCommitMessageParser.php', 'DifferentialCommitMessageParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php', 'DifferentialCommitsField' => 'applications/differential/customfield/DifferentialCommitsField.php', 'DifferentialConduitAPIMethod' => 'applications/differential/conduit/DifferentialConduitAPIMethod.php', - 'DifferentialConflictsField' => 'applications/differential/customfield/DifferentialConflictsField.php', + 'DifferentialConflictsCommitMessageField' => 'applications/differential/field/DifferentialConflictsCommitMessageField.php', 'DifferentialController' => 'applications/differential/controller/DifferentialController.php', 'DifferentialCoreCustomField' => 'applications/differential/customfield/DifferentialCoreCustomField.php', 'DifferentialCreateCommentConduitAPIMethod' => 'applications/differential/conduit/DifferentialCreateCommentConduitAPIMethod.php', @@ -430,7 +431,6 @@ phutil_register_library_map(array( 'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php', 'DifferentialDraft' => 'applications/differential/storage/DifferentialDraft.php', - 'DifferentialEditPolicyField' => 'applications/differential/customfield/DifferentialEditPolicyField.php', 'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', 'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', 'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php', @@ -444,7 +444,7 @@ phutil_register_library_map(array( 'DifferentialGetRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRevisionConduitAPIMethod.php', 'DifferentialGetWorkingCopy' => 'applications/differential/DifferentialGetWorkingCopy.php', 'DifferentialGitHubLandingStrategy' => 'applications/differential/landing/DifferentialGitHubLandingStrategy.php', - 'DifferentialGitSVNIDField' => 'applications/differential/customfield/DifferentialGitSVNIDField.php', + 'DifferentialGitSVNIDCommitMessageField' => 'applications/differential/field/DifferentialGitSVNIDCommitMessageField.php', 'DifferentialHarbormasterField' => 'applications/differential/customfield/DifferentialHarbormasterField.php', 'DifferentialHiddenComment' => 'applications/differential/storage/DifferentialHiddenComment.php', 'DifferentialHostField' => 'applications/differential/customfield/DifferentialHostField.php', @@ -461,6 +461,7 @@ phutil_register_library_map(array( 'DifferentialInlineCommentMailView' => 'applications/differential/mail/DifferentialInlineCommentMailView.php', 'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/DifferentialInlineCommentPreviewController.php', 'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php', + 'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php', 'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php', 'DifferentialLandingActionMenuEventListener' => 'applications/differential/landing/DifferentialLandingActionMenuEventListener.php', 'DifferentialLandingStrategy' => 'applications/differential/landing/DifferentialLandingStrategy.php', @@ -472,14 +473,11 @@ phutil_register_library_map(array( 'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php', 'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php', 'DifferentialModernHunk' => 'applications/differential/storage/DifferentialModernHunk.php', - 'DifferentialNextStepField' => 'applications/differential/customfield/DifferentialNextStepField.php', - 'DifferentialParentRevisionsField' => 'applications/differential/customfield/DifferentialParentRevisionsField.php', 'DifferentialParseCacheGarbageCollector' => 'applications/differential/garbagecollector/DifferentialParseCacheGarbageCollector.php', 'DifferentialParseCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php', 'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php', 'DifferentialPathField' => 'applications/differential/customfield/DifferentialPathField.php', 'DifferentialProjectReviewersField' => 'applications/differential/customfield/DifferentialProjectReviewersField.php', - 'DifferentialProjectsField' => 'applications/differential/customfield/DifferentialProjectsField.php', 'DifferentialQueryConduitAPIMethod' => 'applications/differential/conduit/DifferentialQueryConduitAPIMethod.php', 'DifferentialQueryDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialQueryDiffsConduitAPIMethod.php', 'DifferentialRawDiffRenderer' => 'applications/differential/render/DifferentialRawDiffRenderer.php', @@ -493,16 +491,18 @@ phutil_register_library_map(array( 'DifferentialResponsibleDatasource' => 'applications/differential/typeahead/DifferentialResponsibleDatasource.php', 'DifferentialResponsibleUserDatasource' => 'applications/differential/typeahead/DifferentialResponsibleUserDatasource.php', 'DifferentialResponsibleViewerFunctionDatasource' => 'applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php', + 'DifferentialRevertPlanCommitMessageField' => 'applications/differential/field/DifferentialRevertPlanCommitMessageField.php', 'DifferentialRevertPlanField' => 'applications/differential/customfield/DifferentialRevertPlanField.php', - 'DifferentialReviewedByField' => 'applications/differential/customfield/DifferentialReviewedByField.php', - 'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php', + 'DifferentialReviewedByCommitMessageField' => 'applications/differential/field/DifferentialReviewedByCommitMessageField.php', 'DifferentialReviewerDatasource' => 'applications/differential/typeahead/DifferentialReviewerDatasource.php', 'DifferentialReviewerForRevisionEdgeType' => 'applications/differential/edge/DifferentialReviewerForRevisionEdgeType.php', + 'DifferentialReviewerProxy' => 'applications/differential/storage/DifferentialReviewerProxy.php', 'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php', 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php', 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php', 'DifferentialReviewersAddReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php', 'DifferentialReviewersAddSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php', + 'DifferentialReviewersCommitMessageField' => 'applications/differential/field/DifferentialReviewersCommitMessageField.php', 'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php', 'DifferentialReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersHeraldAction.php', 'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php', @@ -517,7 +517,9 @@ phutil_register_library_map(array( 'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependedOnByRevisionEdgeType.php', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependsOnRevisionEdgeType.php', + 'DifferentialRevisionEditConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php', 'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', + 'DifferentialRevisionEditEngine' => 'applications/differential/editor/DifferentialRevisionEditEngine.php', 'DifferentialRevisionFulltextEngine' => 'applications/differential/search/DifferentialRevisionFulltextEngine.php', 'DifferentialRevisionGraph' => 'infrastructure/graph/DifferentialRevisionGraph.php', 'DifferentialRevisionHasChildRelationship' => 'applications/differential/relationships/DifferentialRevisionHasChildRelationship.php', @@ -529,7 +531,7 @@ phutil_register_library_map(array( 'DifferentialRevisionHasTaskRelationship' => 'applications/differential/relationships/DifferentialRevisionHasTaskRelationship.php', 'DifferentialRevisionHeraldField' => 'applications/differential/herald/DifferentialRevisionHeraldField.php', 'DifferentialRevisionHeraldFieldGroup' => 'applications/differential/herald/DifferentialRevisionHeraldFieldGroup.php', - 'DifferentialRevisionIDField' => 'applications/differential/customfield/DifferentialRevisionIDField.php', + 'DifferentialRevisionIDCommitMessageField' => 'applications/differential/field/DifferentialRevisionIDCommitMessageField.php', 'DifferentialRevisionLandController' => 'applications/differential/controller/DifferentialRevisionLandController.php', 'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php', 'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php', @@ -543,23 +545,33 @@ phutil_register_library_map(array( 'DifferentialRevisionRelationshipSource' => 'applications/search/relationship/DifferentialRevisionRelationshipSource.php', 'DifferentialRevisionRepositoryHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryHeraldField.php', 'DifferentialRevisionRepositoryProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryProjectsHeraldField.php', + 'DifferentialRevisionRepositoryTransaction' => 'applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php', 'DifferentialRevisionRequiredActionResultBucket' => 'applications/differential/query/DifferentialRevisionRequiredActionResultBucket.php', 'DifferentialRevisionResultBucket' => 'applications/differential/query/DifferentialRevisionResultBucket.php', 'DifferentialRevisionReviewersHeraldField' => 'applications/differential/herald/DifferentialRevisionReviewersHeraldField.php', + 'DifferentialRevisionReviewersTransaction' => 'applications/differential/xaction/DifferentialRevisionReviewersTransaction.php', 'DifferentialRevisionSearchConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionSearchConduitAPIMethod.php', 'DifferentialRevisionSearchEngine' => 'applications/differential/query/DifferentialRevisionSearchEngine.php', 'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php', 'DifferentialRevisionSummaryHeraldField' => 'applications/differential/herald/DifferentialRevisionSummaryHeraldField.php', + 'DifferentialRevisionSummaryTransaction' => 'applications/differential/xaction/DifferentialRevisionSummaryTransaction.php', + 'DifferentialRevisionTestPlanTransaction' => 'applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php', 'DifferentialRevisionTitleHeraldField' => 'applications/differential/herald/DifferentialRevisionTitleHeraldField.php', + 'DifferentialRevisionTitleTransaction' => 'applications/differential/xaction/DifferentialRevisionTitleTransaction.php', + 'DifferentialRevisionTransactionType' => 'applications/differential/xaction/DifferentialRevisionTransactionType.php', 'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/DifferentialRevisionUpdateHistoryView.php', 'DifferentialRevisionViewController' => 'applications/differential/controller/DifferentialRevisionViewController.php', 'DifferentialSchemaSpec' => 'applications/differential/storage/DifferentialSchemaSpec.php', 'DifferentialSetDiffPropertyConduitAPIMethod' => 'applications/differential/conduit/DifferentialSetDiffPropertyConduitAPIMethod.php', 'DifferentialStoredCustomField' => 'applications/differential/customfield/DifferentialStoredCustomField.php', - 'DifferentialSubscribersField' => 'applications/differential/customfield/DifferentialSubscribersField.php', + 'DifferentialSubscribersCommitMessageField' => 'applications/differential/field/DifferentialSubscribersCommitMessageField.php', + 'DifferentialSummaryCommitMessageField' => 'applications/differential/field/DifferentialSummaryCommitMessageField.php', 'DifferentialSummaryField' => 'applications/differential/customfield/DifferentialSummaryField.php', + 'DifferentialTagsCommitMessageField' => 'applications/differential/field/DifferentialTagsCommitMessageField.php', + 'DifferentialTasksCommitMessageField' => 'applications/differential/field/DifferentialTasksCommitMessageField.php', + 'DifferentialTestPlanCommitMessageField' => 'applications/differential/field/DifferentialTestPlanCommitMessageField.php', 'DifferentialTestPlanField' => 'applications/differential/customfield/DifferentialTestPlanField.php', - 'DifferentialTitleField' => 'applications/differential/customfield/DifferentialTitleField.php', + 'DifferentialTitleCommitMessageField' => 'applications/differential/field/DifferentialTitleCommitMessageField.php', 'DifferentialTransaction' => 'applications/differential/storage/DifferentialTransaction.php', 'DifferentialTransactionComment' => 'applications/differential/storage/DifferentialTransactionComment.php', 'DifferentialTransactionEditor' => 'applications/differential/editor/DifferentialTransactionEditor.php', @@ -569,7 +581,6 @@ phutil_register_library_map(array( 'DifferentialUnitStatus' => 'applications/differential/constants/DifferentialUnitStatus.php', 'DifferentialUnitTestResult' => 'applications/differential/constants/DifferentialUnitTestResult.php', 'DifferentialUpdateRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateRevisionConduitAPIMethod.php', - 'DifferentialViewPolicyField' => 'applications/differential/customfield/DifferentialViewPolicyField.php', 'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php', 'DiffusionAuditorFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php', 'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php', @@ -1787,7 +1798,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php', 'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php', 'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php', - 'PhabricatorApplicationProfilePanel' => 'applications/search/profilepanel/PhabricatorApplicationProfilePanel.php', + 'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php', 'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php', 'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php', 'PhabricatorApplicationSearchEngine' => 'applications/search/engine/PhabricatorApplicationSearchEngine.php', @@ -2425,23 +2436,28 @@ phutil_register_library_map(array( 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardDashboardHasPanelEdgeType.php', 'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php', + 'PhabricatorDashboardDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardDatasource.php', 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php', + 'PhabricatorDashboardIconSet' => 'applications/dashboard/icon/PhabricatorDashboardIconSet.php', 'PhabricatorDashboardInstall' => 'applications/dashboard/storage/PhabricatorDashboardInstall.php', 'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/PhabricatorDashboardInstallController.php', 'PhabricatorDashboardLayoutConfig' => 'applications/dashboard/layoutconfig/PhabricatorDashboardLayoutConfig.php', 'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php', 'PhabricatorDashboardManageController' => 'applications/dashboard/controller/PhabricatorDashboardManageController.php', 'PhabricatorDashboardMovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardMovePanelController.php', + 'PhabricatorDashboardNgrams' => 'applications/dashboard/storage/PhabricatorDashboardNgrams.php', 'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php', 'PhabricatorDashboardPanelArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php', 'PhabricatorDashboardPanelCoreCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCoreCustomField.php', 'PhabricatorDashboardPanelCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCustomField.php', + 'PhabricatorDashboardPanelDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php', 'PhabricatorDashboardPanelEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPanelEditConduitAPIMethod.php', 'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/PhabricatorDashboardPanelEditController.php', 'PhabricatorDashboardPanelEditEngine' => 'applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php', 'PhabricatorDashboardPanelEditproController' => 'applications/dashboard/controller/PhabricatorDashboardPanelEditproController.php', 'PhabricatorDashboardPanelHasDashboardEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardPanelHasDashboardEdgeType.php', 'PhabricatorDashboardPanelListController' => 'applications/dashboard/controller/PhabricatorDashboardPanelListController.php', + 'PhabricatorDashboardPanelNgrams' => 'applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php', 'PhabricatorDashboardPanelPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php', 'PhabricatorDashboardPanelQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelQuery.php', 'PhabricatorDashboardPanelRenderController' => 'applications/dashboard/controller/PhabricatorDashboardPanelRenderController.php', @@ -2455,6 +2471,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php', 'PhabricatorDashboardPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelType.php', 'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php', + 'PhabricatorDashboardProfileMenuItem' => 'applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php', 'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', 'PhabricatorDashboardQueryPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php', 'PhabricatorDashboardRemarkupRule' => 'applications/dashboard/remarkup/PhabricatorDashboardRemarkupRule.php', @@ -2505,7 +2522,8 @@ phutil_register_library_map(array( 'PhabricatorDisabledUserController' => 'applications/auth/controller/PhabricatorDisabledUserController.php', 'PhabricatorDisplayPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDisplayPreferencesSettingsPanel.php', 'PhabricatorDisqusAuthProvider' => 'applications/auth/provider/PhabricatorDisqusAuthProvider.php', - 'PhabricatorDividerProfilePanel' => 'applications/search/profilepanel/PhabricatorDividerProfilePanel.php', + 'PhabricatorDividerEditField' => 'applications/transactions/editfield/PhabricatorDividerEditField.php', + 'PhabricatorDividerProfileMenuItem' => 'applications/search/menuitem/PhabricatorDividerProfileMenuItem.php', 'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php', 'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php', 'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php', @@ -2547,6 +2565,7 @@ phutil_register_library_map(array( 'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php', 'PhabricatorEditEngineController' => 'applications/transactions/controller/PhabricatorEditEngineController.php', 'PhabricatorEditEngineCreateQuickActions' => 'applications/settings/quickmenu/PhabricatorEditEngineCreateQuickActions.php', + 'PhabricatorEditEngineDatasource' => 'applications/transactions/typeahead/PhabricatorEditEngineDatasource.php', 'PhabricatorEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditEngineExtension.php', 'PhabricatorEditEngineExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditEngineExtensionModule.php', 'PhabricatorEditEngineListController' => 'applications/transactions/controller/PhabricatorEditEngineListController.php', @@ -2783,8 +2802,6 @@ phutil_register_library_map(array( 'PhabricatorHomeQuickCreateController' => 'applications/home/controller/PhabricatorHomeQuickCreateController.php', 'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php', 'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php', - 'PhabricatorHunksManagementMigrateWorkflow' => 'applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php', - 'PhabricatorHunksManagementWorkflow' => 'applications/differential/management/PhabricatorHunksManagementWorkflow.php', 'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php', 'PhabricatorIDsSearchField' => 'applications/search/field/PhabricatorIDsSearchField.php', 'PhabricatorIRCProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php', @@ -2828,7 +2845,7 @@ phutil_register_library_map(array( 'PhabricatorLegalpadDocumentPHIDType' => 'applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php', 'PhabricatorLegalpadSignaturePolicyRule' => 'applications/legalpad/policyrule/PhabricatorLegalpadSignaturePolicyRule.php', 'PhabricatorLibraryTestCase' => '__tests__/PhabricatorLibraryTestCase.php', - 'PhabricatorLinkProfilePanel' => 'applications/search/profilepanel/PhabricatorLinkProfilePanel.php', + 'PhabricatorLinkProfileMenuItem' => 'applications/search/menuitem/PhabricatorLinkProfileMenuItem.php', 'PhabricatorLipsumArtist' => 'applications/lipsum/image/PhabricatorLipsumArtist.php', 'PhabricatorLipsumContentSource' => 'infrastructure/contentsource/PhabricatorLipsumContentSource.php', 'PhabricatorLipsumGenerateWorkflow' => 'applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php', @@ -2966,7 +2983,7 @@ phutil_register_library_map(array( 'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php', 'PhabricatorMonospacedFontSetting' => 'applications/settings/setting/PhabricatorMonospacedFontSetting.php', 'PhabricatorMonospacedTextareasSetting' => 'applications/settings/setting/PhabricatorMonospacedTextareasSetting.php', - 'PhabricatorMotivatorProfilePanel' => 'applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php', + 'PhabricatorMotivatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php', 'PhabricatorMultiColumnUIExample' => 'applications/uiexample/examples/PhabricatorMultiColumnUIExample.php', 'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php', 'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php', @@ -3244,7 +3261,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleCreateGuidanceContext' => 'applications/people/guidance/PhabricatorPeopleCreateGuidanceContext.php', 'PhabricatorPeopleDatasource' => 'applications/people/typeahead/PhabricatorPeopleDatasource.php', 'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php', - 'PhabricatorPeopleDetailsProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php', + 'PhabricatorPeopleDetailsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php', 'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php', 'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', 'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', @@ -3258,14 +3275,14 @@ phutil_register_library_map(array( 'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleMainMenuBarExtension' => 'applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php', - 'PhabricatorPeopleManageProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php', + 'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php', 'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php', 'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php', 'PhabricatorPeopleOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleOwnerDatasource.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php', 'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php', - 'PhabricatorPeopleProfilePanelEngine' => 'applications/people/engine/PhabricatorPeopleProfilePanelEngine.php', + 'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php', 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', 'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php', 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php', @@ -3364,16 +3381,16 @@ phutil_register_library_map(array( 'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php', 'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php', 'PhabricatorProfileMenuCollapsedSetting' => 'applications/settings/setting/PhabricatorProfileMenuCollapsedSetting.php', - 'PhabricatorProfilePanel' => 'applications/search/profilepanel/PhabricatorProfilePanel.php', - 'PhabricatorProfilePanelConfiguration' => 'applications/search/storage/PhabricatorProfilePanelConfiguration.php', - 'PhabricatorProfilePanelConfigurationQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationQuery.php', - 'PhabricatorProfilePanelConfigurationTransaction' => 'applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php', - 'PhabricatorProfilePanelConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.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', - 'PhabricatorProfilePanelPHIDType' => 'applications/search/phidtype/PhabricatorProfilePanelPHIDType.php', + 'PhabricatorProfileMenuEditEngine' => 'applications/search/editor/PhabricatorProfileMenuEditEngine.php', + 'PhabricatorProfileMenuEditor' => 'applications/search/editor/PhabricatorProfileMenuEditor.php', + 'PhabricatorProfileMenuEngine' => 'applications/search/engine/PhabricatorProfileMenuEngine.php', + 'PhabricatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorProfileMenuItem.php', + 'PhabricatorProfileMenuItemConfiguration' => 'applications/search/storage/PhabricatorProfileMenuItemConfiguration.php', + 'PhabricatorProfileMenuItemConfigurationQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php', + 'PhabricatorProfileMenuItemConfigurationTransaction' => 'applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php', + 'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php', + 'PhabricatorProfileMenuItemIconSet' => 'applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php', + 'PhabricatorProfileMenuItemPHIDType' => 'applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php', 'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php', 'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php', 'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php', @@ -3411,7 +3428,7 @@ phutil_register_library_map(array( 'PhabricatorProjectDatasource' => 'applications/project/typeahead/PhabricatorProjectDatasource.php', 'PhabricatorProjectDefaultController' => 'applications/project/controller/PhabricatorProjectDefaultController.php', 'PhabricatorProjectDescriptionField' => 'applications/project/customfield/PhabricatorProjectDescriptionField.php', - 'PhabricatorProjectDetailsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php', + 'PhabricatorProjectDetailsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php', 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', @@ -3432,16 +3449,17 @@ phutil_register_library_map(array( 'PhabricatorProjectLogicalUserDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php', 'PhabricatorProjectLogicalViewerDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php', 'PhabricatorProjectManageController' => 'applications/project/controller/PhabricatorProjectManageController.php', - 'PhabricatorProjectManageProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php', + 'PhabricatorProjectManageProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php', 'PhabricatorProjectMaterializedMemberEdgeType' => 'applications/project/edge/PhabricatorProjectMaterializedMemberEdgeType.php', 'PhabricatorProjectMemberListView' => 'applications/project/view/PhabricatorProjectMemberListView.php', 'PhabricatorProjectMemberOfProjectEdgeType' => 'applications/project/edge/PhabricatorProjectMemberOfProjectEdgeType.php', 'PhabricatorProjectMembersAddController' => 'applications/project/controller/PhabricatorProjectMembersAddController.php', 'PhabricatorProjectMembersDatasource' => 'applications/project/typeahead/PhabricatorProjectMembersDatasource.php', 'PhabricatorProjectMembersPolicyRule' => 'applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php', - 'PhabricatorProjectMembersProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php', + 'PhabricatorProjectMembersProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php', 'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php', 'PhabricatorProjectMembersViewController' => 'applications/project/controller/PhabricatorProjectMembersViewController.php', + 'PhabricatorProjectMenuItemController' => 'applications/project/controller/PhabricatorProjectMenuItemController.php', 'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php', 'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php', 'PhabricatorProjectNoProjectsDatasource' => 'applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php', @@ -3449,10 +3467,10 @@ 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', - 'PhabricatorProjectPointsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php', + 'PhabricatorProjectPointsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', - 'PhabricatorProjectProfilePanelEngine' => 'applications/project/engine/PhabricatorProjectProfilePanelEngine.php', + 'PhabricatorProjectProfileMenuEngine' => 'applications/project/engine/PhabricatorProjectProfileMenuEngine.php', + 'PhabricatorProjectProfileMenuItem' => 'applications/search/menuitem/PhabricatorProjectProfileMenuItem.php', 'PhabricatorProjectProjectHasMemberEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasMemberEdgeType.php', 'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php', 'PhabricatorProjectProjectPHIDType' => 'applications/project/phid/PhabricatorProjectProjectPHIDType.php', @@ -3468,7 +3486,7 @@ phutil_register_library_map(array( 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectSubprojectWarningController' => 'applications/project/controller/PhabricatorProjectSubprojectWarningController.php', 'PhabricatorProjectSubprojectsController' => 'applications/project/controller/PhabricatorProjectSubprojectsController.php', - 'PhabricatorProjectSubprojectsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php', + 'PhabricatorProjectSubprojectsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php', 'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php', 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', 'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php', @@ -3481,7 +3499,7 @@ phutil_register_library_map(array( 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', 'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php', 'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php', - 'PhabricatorProjectWorkboardProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php', + 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', @@ -3818,6 +3836,7 @@ phutil_register_library_map(array( 'PhabricatorStreamingProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorStreamingProtocolAdapter.php', 'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php', 'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php', + 'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php', 'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php', 'PhabricatorSubscribedToObjectEdgeType' => 'applications/transactions/edges/PhabricatorSubscribedToObjectEdgeType.php', 'PhabricatorSubscribersEditField' => 'applications/transactions/editfield/PhabricatorSubscribersEditField.php', @@ -4966,10 +4985,10 @@ phutil_register_library_map(array( 'DifferentialAddCommentView' => 'AphrontView', 'DifferentialAdjustmentMapTestCase' => 'PhutilTestCase', 'DifferentialAffectedPath' => 'DifferentialDAO', - 'DifferentialApplyPatchField' => 'DifferentialCustomField', 'DifferentialAsanaRepresentationField' => 'DifferentialCustomField', + 'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialAuditorsField' => 'DifferentialStoredCustomField', - 'DifferentialAuthorField' => 'DifferentialCustomField', + 'DifferentialBlameRevisionCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialBlameRevisionField' => 'DifferentialStoredCustomField', 'DifferentialBlockHeraldAction' => 'HeraldAction', 'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', @@ -4997,15 +5016,16 @@ phutil_register_library_map(array( 'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetViewController' => 'DifferentialController', - 'DifferentialChildRevisionsField' => 'DifferentialCustomField', 'DifferentialCloseConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCommentPreviewController' => 'DifferentialController', 'DifferentialCommentSaveController' => 'DifferentialController', + 'DifferentialCommitMessageCustomField' => 'DifferentialCommitMessageField', + 'DifferentialCommitMessageField' => 'Phobject', 'DifferentialCommitMessageParser' => 'Phobject', 'DifferentialCommitMessageParserTestCase' => 'PhabricatorTestCase', 'DifferentialCommitsField' => 'DifferentialCustomField', 'DifferentialConduitAPIMethod' => 'ConduitAPIMethod', - 'DifferentialConflictsField' => 'DifferentialCustomField', + 'DifferentialConflictsCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialController' => 'PhabricatorController', 'DifferentialCoreCustomField' => 'DifferentialCustomField', 'DifferentialCreateCommentConduitAPIMethod' => 'DifferentialConduitAPIMethod', @@ -5055,7 +5075,6 @@ phutil_register_library_map(array( 'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DifferentialDraft' => 'DifferentialDAO', - 'DifferentialEditPolicyField' => 'DifferentialCoreCustomField', 'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialFieldParseException' => 'Exception', 'DifferentialFieldValidationException' => 'Exception', @@ -5069,7 +5088,7 @@ phutil_register_library_map(array( 'DifferentialGetRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetWorkingCopy' => 'Phobject', 'DifferentialGitHubLandingStrategy' => 'DifferentialLandingStrategy', - 'DifferentialGitSVNIDField' => 'DifferentialCustomField', + 'DifferentialGitSVNIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialHarbormasterField' => 'DifferentialCustomField', 'DifferentialHiddenComment' => 'DifferentialDAO', 'DifferentialHostField' => 'DifferentialCustomField', @@ -5092,6 +5111,7 @@ phutil_register_library_map(array( 'DifferentialInlineCommentMailView' => 'DifferentialMailView', 'DifferentialInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery', + 'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField', 'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener', 'DifferentialLandingStrategy' => 'Phobject', @@ -5103,14 +5123,11 @@ phutil_register_library_map(array( 'DifferentialMailView' => 'Phobject', 'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField', 'DifferentialModernHunk' => 'DifferentialHunk', - 'DifferentialNextStepField' => 'DifferentialCustomField', - 'DifferentialParentRevisionsField' => 'DifferentialCustomField', 'DifferentialParseCacheGarbageCollector' => 'PhabricatorGarbageCollector', 'DifferentialParseCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialParseRenderTestCase' => 'PhabricatorTestCase', 'DifferentialPathField' => 'DifferentialCustomField', 'DifferentialProjectReviewersField' => 'DifferentialCustomField', - 'DifferentialProjectsField' => 'DifferentialCoreCustomField', 'DifferentialQueryConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialQueryDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialRawDiffRenderer' => 'Phobject', @@ -5124,16 +5141,18 @@ phutil_register_library_map(array( 'DifferentialResponsibleDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialResponsibleUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialResponsibleViewerFunctionDatasource' => 'PhabricatorTypeaheadDatasource', + 'DifferentialRevertPlanCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialRevertPlanField' => 'DifferentialStoredCustomField', - 'DifferentialReviewedByField' => 'DifferentialCoreCustomField', - 'DifferentialReviewer' => 'Phobject', + 'DifferentialReviewedByCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialReviewerForRevisionEdgeType' => 'PhabricatorEdgeType', + 'DifferentialReviewerProxy' => 'Phobject', 'DifferentialReviewerStatus' => 'Phobject', 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddSelfHeraldAction' => 'DifferentialReviewersHeraldAction', + 'DifferentialReviewersCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialReviewersField' => 'DifferentialCoreCustomField', 'DifferentialReviewersHeraldAction' => 'HeraldAction', 'DifferentialReviewersView' => 'AphrontView', @@ -5164,7 +5183,9 @@ phutil_register_library_map(array( 'DifferentialRevisionControlSystem' => 'Phobject', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType', + 'DifferentialRevisionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DifferentialRevisionEditController' => 'DifferentialController', + 'DifferentialRevisionEditEngine' => 'PhabricatorEditEngine', 'DifferentialRevisionFulltextEngine' => 'PhabricatorFulltextEngine', 'DifferentialRevisionGraph' => 'PhabricatorObjectGraph', 'DifferentialRevisionHasChildRelationship' => 'DifferentialRevisionRelationship', @@ -5176,7 +5197,7 @@ phutil_register_library_map(array( 'DifferentialRevisionHasTaskRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHeraldField' => 'HeraldField', 'DifferentialRevisionHeraldFieldGroup' => 'HeraldFieldGroup', - 'DifferentialRevisionIDField' => 'DifferentialCustomField', + 'DifferentialRevisionIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialRevisionLandController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListView' => 'AphrontView', @@ -5190,24 +5211,34 @@ phutil_register_library_map(array( 'DifferentialRevisionRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'DifferentialRevisionRepositoryHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionRepositoryProjectsHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionRepositoryTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionRequiredActionResultBucket' => 'DifferentialRevisionResultBucket', 'DifferentialRevisionResultBucket' => 'PhabricatorSearchResultBucket', 'DifferentialRevisionReviewersHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionReviewersTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DifferentialRevisionStatus' => 'Phobject', 'DifferentialRevisionSummaryHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionSummaryTransaction' => 'DifferentialRevisionTransactionType', + 'DifferentialRevisionTestPlanTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionTitleHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionTitleTransaction' => 'DifferentialRevisionTransactionType', + 'DifferentialRevisionTransactionType' => 'PhabricatorModularTransactionType', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DifferentialSetDiffPropertyConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialStoredCustomField' => 'DifferentialCustomField', - 'DifferentialSubscribersField' => 'DifferentialCoreCustomField', + 'DifferentialSubscribersCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialSummaryCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialSummaryField' => 'DifferentialCoreCustomField', + 'DifferentialTagsCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTasksCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTestPlanCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanField' => 'DifferentialCoreCustomField', - 'DifferentialTitleField' => 'DifferentialCoreCustomField', - 'DifferentialTransaction' => 'PhabricatorApplicationTransaction', + 'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTransaction' => 'PhabricatorModularTransaction', 'DifferentialTransactionComment' => 'PhabricatorApplicationTransactionComment', 'DifferentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'DifferentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', @@ -5216,7 +5247,6 @@ phutil_register_library_map(array( 'DifferentialUnitStatus' => 'Phobject', 'DifferentialUnitTestResult' => 'Phobject', 'DifferentialUpdateRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', - 'DifferentialViewPolicyField' => 'DifferentialCoreCustomField', 'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionAuditorFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction', @@ -6610,7 +6640,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationLaunchView' => 'AphrontTagView', 'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController', - 'PhabricatorApplicationProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorApplicationSearchEngine' => 'Phobject', @@ -7354,6 +7384,7 @@ phutil_register_library_map(array( 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorProjectInterface', + 'PhabricatorNgramsInterface', ), 'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController', 'PhabricatorDashboardApplication' => 'PhabricatorApplication', @@ -7363,13 +7394,16 @@ phutil_register_library_map(array( 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'PhabricatorEdgeType', 'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType', + 'PhabricatorDashboardDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardIconSet' => 'PhabricatorIconSet', 'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO', 'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController', 'PhabricatorDashboardLayoutConfig' => 'Phobject', 'PhabricatorDashboardListController' => 'PhabricatorDashboardController', 'PhabricatorDashboardManageController' => 'PhabricatorDashboardController', 'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorDashboardPanel' => array( 'PhabricatorDashboardDAO', 'PhabricatorApplicationTransactionInterface', @@ -7377,6 +7411,7 @@ phutil_register_library_map(array( 'PhabricatorCustomFieldInterface', 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', + 'PhabricatorNgramsInterface', ), 'PhabricatorDashboardPanelArchiveController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelCoreCustomField' => array( @@ -7384,12 +7419,14 @@ phutil_register_library_map(array( 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorDashboardPanelCustomField' => 'PhabricatorCustomField', + 'PhabricatorDashboardPanelDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorDashboardPanelEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelEditEngine' => 'PhabricatorEditEngine', 'PhabricatorDashboardPanelEditproController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelHasDashboardEdgeType' => 'PhabricatorEdgeType', 'PhabricatorDashboardPanelListController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardPanelNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorDashboardPanelPHIDType' => 'PhabricatorPHIDType', 'PhabricatorDashboardPanelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDashboardPanelRenderController' => 'PhabricatorDashboardController', @@ -7403,6 +7440,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorDashboardPanelType' => 'Phobject', 'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDashboardQueryPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardRemarkupRule' => 'PhabricatorObjectRemarkupRule', @@ -7452,7 +7490,8 @@ phutil_register_library_map(array( 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDisplayPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDisqusAuthProvider' => 'PhabricatorOAuth2AuthProvider', - 'PhabricatorDividerProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorDividerEditField' => 'PhabricatorEditField', + 'PhabricatorDividerProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDivinerApplication' => 'PhabricatorApplication', 'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication', 'PhabricatorDraft' => 'PhabricatorDraftDAO', @@ -7501,6 +7540,7 @@ phutil_register_library_map(array( 'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineController' => 'PhabricatorApplicationTransactionController', 'PhabricatorEditEngineCreateQuickActions' => 'PhabricatorQuickActions', + 'PhabricatorEditEngineDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorEditEngineExtension' => 'Phobject', 'PhabricatorEditEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorEditEngineListController' => 'PhabricatorEditEngineController', @@ -7775,8 +7815,6 @@ phutil_register_library_map(array( 'PhabricatorHomeQuickCreateController' => 'PhabricatorHomeController', 'PhabricatorHovercardEngineExtension' => 'Phobject', 'PhabricatorHovercardEngineExtensionModule' => 'PhabricatorConfigModule', - 'PhabricatorHunksManagementMigrateWorkflow' => 'PhabricatorHunksManagementWorkflow', - 'PhabricatorHunksManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorIDsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorIDsSearchField' => 'PhabricatorSearchField', 'PhabricatorIRCProtocolAdapter' => 'PhabricatorProtocolAdapter', @@ -7820,7 +7858,7 @@ phutil_register_library_map(array( 'PhabricatorLegalpadDocumentPHIDType' => 'PhabricatorPHIDType', 'PhabricatorLegalpadSignaturePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorLibraryTestCase' => 'PhutilLibraryTestCase', - 'PhabricatorLinkProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorLinkProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorLipsumArtist' => 'Phobject', 'PhabricatorLipsumContentSource' => 'PhabricatorContentSource', 'PhabricatorLipsumGenerateWorkflow' => 'PhabricatorLipsumManagementWorkflow', @@ -7968,7 +8006,7 @@ phutil_register_library_map(array( 'PhabricatorModularTransactionType' => 'Phobject', 'PhabricatorMonospacedFontSetting' => 'PhabricatorStringSetting', 'PhabricatorMonospacedTextareasSetting' => 'PhabricatorSelectSetting', - 'PhabricatorMotivatorProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorMotivatorProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorMultiColumnUIExample' => 'PhabricatorUIExample', 'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorMultimeterApplication' => 'PhabricatorApplication', @@ -8310,7 +8348,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleCreateGuidanceContext' => 'PhabricatorGuidanceContext', 'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController', - 'PhabricatorPeopleDetailsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorPeopleDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController', 'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', 'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', @@ -8324,14 +8362,14 @@ phutil_register_library_map(array( 'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', - 'PhabricatorPeopleManageProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleNewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController', - 'PhabricatorPeopleProfilePanelEngine' => 'PhabricatorProfilePanelEngine', + 'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', @@ -8450,21 +8488,21 @@ phutil_register_library_map(array( 'PhabricatorPolicyType' => 'PhabricatorPolicyConstants', 'PhabricatorPonderApplication' => 'PhabricatorApplication', 'PhabricatorProfileMenuCollapsedSetting' => 'PhabricatorInternalSetting', - 'PhabricatorProfilePanel' => 'Phobject', - 'PhabricatorProfilePanelConfiguration' => array( + 'PhabricatorProfileMenuEditEngine' => 'PhabricatorEditEngine', + 'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor', + 'PhabricatorProfileMenuEngine' => 'Phobject', + 'PhabricatorProfileMenuItem' => 'Phobject', + 'PhabricatorProfileMenuItemConfiguration' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), - 'PhabricatorProfilePanelConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', - 'PhabricatorProfilePanelConfigurationTransaction' => 'PhabricatorApplicationTransaction', - 'PhabricatorProfilePanelConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', - 'PhabricatorProfilePanelEditEngine' => 'PhabricatorEditEngine', - 'PhabricatorProfilePanelEditor' => 'PhabricatorApplicationTransactionEditor', - 'PhabricatorProfilePanelEngine' => 'Phobject', - 'PhabricatorProfilePanelIconSet' => 'PhabricatorIconSet', - 'PhabricatorProfilePanelPHIDType' => 'PhabricatorPHIDType', + 'PhabricatorProfileMenuItemConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorProfileMenuItemConfigurationTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhabricatorProfileMenuItemIconSet' => 'PhabricatorIconSet', + 'PhabricatorProfileMenuItemPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProject' => array( 'PhabricatorProjectDAO', 'PhabricatorApplicationTransactionInterface', @@ -8525,7 +8563,7 @@ phutil_register_library_map(array( 'PhabricatorProjectDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectDefaultController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectDescriptionField' => 'PhabricatorProjectStandardCustomField', - 'PhabricatorProjectDetailsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', @@ -8545,16 +8583,17 @@ phutil_register_library_map(array( 'PhabricatorProjectLogicalUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalViewerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectManageController' => 'PhabricatorProjectController', - 'PhabricatorProjectManageProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectMaterializedMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMemberListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMembersAddController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule', - 'PhabricatorProjectMembersProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectMembersProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersViewController' => 'PhabricatorProjectController', + 'PhabricatorProjectMenuItemController' => 'PhabricatorProjectController', 'PhabricatorProjectMoveController' => 'PhabricatorProjectController', 'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorProjectNoProjectsDatasource' => 'PhabricatorTypeaheadDatasource', @@ -8562,10 +8601,10 @@ phutil_register_library_map(array( 'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver', - 'PhabricatorProjectPanelController' => 'PhabricatorProjectController', - 'PhabricatorProjectPointsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectPointsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', - 'PhabricatorProjectProfilePanelEngine' => 'PhabricatorProfilePanelEngine', + 'PhabricatorProjectProfileMenuEngine' => 'PhabricatorProfileMenuEngine', + 'PhabricatorProjectProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectProjectHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectPHIDType' => 'PhabricatorPHIDType', @@ -8584,7 +8623,7 @@ phutil_register_library_map(array( 'PhabricatorProjectStatus' => 'Phobject', 'PhabricatorProjectSubprojectWarningController' => 'PhabricatorProjectController', 'PhabricatorProjectSubprojectsController' => 'PhabricatorProjectController', - 'PhabricatorProjectSubprojectsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectSubprojectsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor', @@ -8597,7 +8636,7 @@ phutil_register_library_map(array( 'PhabricatorProjectWatchController' => 'PhabricatorProjectController', 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject', - 'PhabricatorProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', @@ -9010,6 +9049,7 @@ phutil_register_library_map(array( 'PhabricatorStreamingProtocolAdapter' => 'PhabricatorProtocolAdapter', 'PhabricatorStringListEditField' => 'PhabricatorEditField', 'PhabricatorStringSetting' => 'PhabricatorSetting', + 'PhabricatorSubmitEditField' => 'PhabricatorEditField', 'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorSubscribersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php index aee2c63032..e7b3b85c63 100644 --- a/src/aphront/configuration/AphrontApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontApplicationConfiguration.php @@ -303,18 +303,7 @@ abstract class AphrontApplicationConfiguration extends Phobject { phlog($unexpected_output); if ($response instanceof AphrontWebpageResponse) { - echo phutil_tag( - 'div', - array( - 'style' => - 'background: #eeddff;'. - 'white-space: pre-wrap;'. - 'z-index: 200000;'. - 'position: relative;'. - 'padding: 8px;'. - 'font-family: monospace', - ), - $unexpected_output); + $response->setUnexpectedOutput($unexpected_output); } } diff --git a/src/aphront/response/AphrontWebpageResponse.php b/src/aphront/response/AphrontWebpageResponse.php index bda0d94244..de642f9b19 100644 --- a/src/aphront/response/AphrontWebpageResponse.php +++ b/src/aphront/response/AphrontWebpageResponse.php @@ -3,14 +3,46 @@ final class AphrontWebpageResponse extends AphrontHTMLResponse { private $content; + private $unexpectedOutput; public function setContent($content) { $this->content = $content; return $this; } + public function setUnexpectedOutput($unexpected_output) { + $this->unexpectedOutput = $unexpected_output; + return $this; + } + + public function getUnexpectedOutput() { + return $this->unexpectedOutput; + } + public function buildResponseString() { - return hsprintf('%s', $this->content); + $unexpected_output = $this->getUnexpectedOutput(); + if (strlen($unexpected_output)) { + $style = array( + 'background: linear-gradient(180deg, #eeddff, #ddbbff);', + 'white-space: pre-wrap;', + 'z-index: 200000;', + 'position: relative;', + 'padding: 16px;', + 'font-family: monospace;', + 'text-shadow: 1px 1px 1px white;', + ); + + $unexpected_header = phutil_tag( + 'div', + array( + 'style' => implode(' ', $style), + ), + $unexpected_output); + } else { + $unexpected_header = ''; + } + + return hsprintf('%s%s', $unexpected_header, $this->content); } } diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 89a3c6cb7a..23a759d2aa 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -627,18 +627,18 @@ abstract class PhabricatorApplication return $base.'(?:query/(?P[^/]+)/)?'; } - protected function getPanelRouting($controller) { + protected function getProfileMenuRouting($controller) { $edit_route = $this->getEditRoutePattern(); return array( - '(?Pview)/(?P[^/]+)/' => $controller, - '(?Phide)/(?P[^/]+)/' => $controller, - '(?Pdefault)/(?P[^/]+)/' => $controller, - '(?Pconfigure)/' => $controller, - '(?Preorder)/' => $controller, - '(?Pedit)/'.$edit_route => $controller, - '(?Pnew)/(?[^/]+)/'.$edit_route => $controller, - '(?Pbuiltin)/(?[^/]+)/'.$edit_route + '(?Pview)/(?P[^/]+)/' => $controller, + '(?Phide)/(?P[^/]+)/' => $controller, + '(?Pdefault)/(?P[^/]+)/' => $controller, + '(?Pconfigure)/' => $controller, + '(?Preorder)/' => $controller, + '(?Pedit)/'.$edit_route => $controller, + '(?Pnew)/(?[^/]+)/'.$edit_route => $controller, + '(?Pbuiltin)/(?[^/]+)/'.$edit_route => $controller, ); } diff --git a/src/applications/config/controller/PhabricatorConfigVersionController.php b/src/applications/config/controller/PhabricatorConfigVersionController.php index 15877ddbd7..8f43192b3b 100644 --- a/src/applications/config/controller/PhabricatorConfigVersionController.php +++ b/src/applications/config/controller/PhabricatorConfigVersionController.php @@ -39,8 +39,20 @@ final class PhabricatorConfigVersionController $versions = $this->loadVersions($viewer); $version_property_list = id(new PHUIPropertyListView()); - foreach ($versions as $name => $version) { - $version_property_list->addProperty($name, $version); + foreach ($versions as $name => $info) { + $version = $info['version']; + + if ($info['branchpoint']) { + $display = pht( + '%s (branched from %s on %s)', + $version, + $info['branchpoint'], + $info['upstream']); + } else { + $display = $version; + } + + $version_property_list->addProperty($name, $display); } $phabricator_root = dirname(phutil_get_library_root('phabricator')); @@ -67,16 +79,109 @@ final class PhabricatorConfigVersionController $other_libraries = array_diff($all_libraries, $specs); $specs = array_merge($specs, $other_libraries); - $futures = array(); + $log_futures = array(); + $remote_futures = array(); + foreach ($specs as $lib) { $root = dirname(phutil_get_library_root($lib)); - $futures[$lib] = - id(new ExecFuture('git log --format=%s -n 1 --', '%H %ct')) + + $log_command = csprintf( + 'git log --format=%s -n 1 --', + '%H %ct'); + + $remote_command = csprintf( + 'git remote -v'); + + $log_futures[$lib] = id(new ExecFuture('%C', $log_command)) + ->setCWD($root); + + $remote_futures[$lib] = id(new ExecFuture('%C', $remote_command)) ->setCWD($root); } + $all_futures = array_merge($log_futures, $remote_futures); + + id(new FutureIterator($all_futures)) + ->resolveAll(); + + // A repository may have a bunch of remotes, but we're only going to look + // for remotes we host to try to figure out where this repository branched. + $upstream_pattern = '(github\.com/phacility/|secure\.phabricator\.com/)'; + + $upstream_futures = array(); + $lib_upstreams = array(); + foreach ($specs as $lib) { + $remote_future = $remote_futures[$lib]; + + list($err, $stdout) = $remote_future->resolve(); + if ($err) { + // If this fails for whatever reason, just move on. + continue; + } + + // These look like this, with a tab separating the first two fields: + // remote-name http://remote.uri/ (push) + + $upstreams = array(); + + $remotes = phutil_split_lines($stdout, false); + foreach ($remotes as $remote) { + $remote_pattern = '/^([^\t]+)\t([^ ]+) \(([^)]+)\)\z/'; + $matches = null; + if (!preg_match($remote_pattern, $remote, $matches)) { + continue; + } + + // Remote URIs are either "push" or "fetch": we only care about "fetch" + // URIs. + $type = $matches[3]; + if ($type != 'fetch') { + continue; + } + + $uri = $matches[2]; + $is_upstream = preg_match($upstream_pattern, $uri); + if (!$is_upstream) { + continue; + } + + $name = $matches[1]; + $upstreams[$name] = $name; + } + + // If we have several suitable upstreams, try to pick the one named + // "origin", if it exists. Otherwise, just pick the first one. + if (isset($upstreams['origin'])) { + $upstream = $upstreams['origin']; + } else if ($upstreams) { + $upstream = head($upstreams); + } else { + $upstream = null; + } + + if (!$upstream) { + continue; + } + + $lib_upstreams[$lib] = $upstream; + + $merge_base_command = csprintf( + 'git merge-base HEAD %s/master --', + $upstream); + + $root = dirname(phutil_get_library_root($lib)); + + $upstream_futures[$lib] = id(new ExecFuture('%C', $merge_base_command)) + ->setCWD($root); + } + + if ($upstream_futures) { + id(new FutureIterator($upstream_futures)) + ->resolveAll(); + } + $results = array(); - foreach ($futures as $key => $future) { + foreach ($log_futures as $lib => $future) { list($err, $stdout) = $future->resolve(); if (!$err) { list($hash, $epoch) = explode(' ', $stdout); @@ -84,7 +189,29 @@ final class PhabricatorConfigVersionController } else { $version = pht('Unknown'); } - $results[$key] = $version; + + $result = array( + 'version' => $version, + 'upstream' => null, + 'branchpoint' => null, + ); + + $upstream_future = idx($upstream_futures, $lib); + if ($upstream_future) { + list($err, $stdout) = $upstream_future->resolve(); + if (!$err) { + $branchpoint = trim($stdout); + if (strlen($branchpoint)) { + // We only list a branchpoint if it differs from HEAD. + if ($branchpoint != $hash) { + $result['upstream'] = $lib_upstreams[$lib]; + $result['branchpoint'] = trim($stdout); + } + } + } + } + + $results[$lib] = $result; } return $results; diff --git a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php index 45604f6872..806cd02db3 100644 --- a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php +++ b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php @@ -98,16 +98,6 @@ EODOC You can disable the "To:" and "Cc:" footers in mail if users prefer smaller messages. EODOC -)); - - $bulk_description = $this->deformat(pht(<<deformat(pht(<<getName(); + $v_icon = $dashboard->getIcon(); $v_layout_mode = $dashboard->getLayoutConfigObject()->getLayoutMode(); $e_name = true; $validation_exception = null; if ($request->isFormPost() && $request->getStr('edit')) { $v_name = $request->getStr('name'); + $v_icon = $request->getStr('icon'); $v_layout_mode = $request->getStr('layout_mode'); $v_view_policy = $request->getStr('viewPolicy'); $v_edit_policy = $request->getStr('editPolicy'); @@ -81,6 +83,7 @@ final class PhabricatorDashboardEditController $xactions = array(); $type_name = PhabricatorDashboardTransaction::TYPE_NAME; + $type_icon = PhabricatorDashboardTransaction::TYPE_ICON; $type_layout_mode = PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE; $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY; @@ -91,6 +94,9 @@ final class PhabricatorDashboardEditController $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType($type_layout_mode) ->setNewValue($v_layout_mode); + $xactions[] = id(new PhabricatorDashboardTransaction()) + ->setTransactionType($type_icon) + ->setNewValue($v_icon); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType($type_view_policy) ->setNewValue($v_view_policy); @@ -146,6 +152,12 @@ final class PhabricatorDashboardEditController ->setName('layout_mode') ->setValue($v_layout_mode) ->setOptions($layout_mode_options)) + ->appendChild( + id(new PHUIFormIconSetControl()) + ->setLabel(pht('Icon')) + ->setName('icon') + ->setIconSet(new PhabricatorDashboardIconSet()) + ->setValue($v_icon)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') diff --git a/src/applications/dashboard/controller/PhabricatorDashboardManageController.php b/src/applications/dashboard/controller/PhabricatorDashboardManageController.php index 4e31b2d2ae..9724db21f7 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardManageController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardManageController.php @@ -109,7 +109,7 @@ final class PhabricatorDashboardManageController ->setHeader($dashboard->getName()) ->setPolicyObject($dashboard) ->setStatus($status_icon, $status_color, $status_name) - ->setHeaderIcon('fa-dashboard') + ->setHeaderIcon($dashboard->getIcon()) ->addActionLink($button); } diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php index b85498c13c..787d1c63ee 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php @@ -400,7 +400,7 @@ final class PhabricatorDashboardPanelEditController $viewer = $request->getUser(); $copy = PhabricatorDashboardPanel::initializeNewPanel($viewer); - $copy = PhabricatorDashboardPanel::copyPanel($copy, $panel); + $copy = PhabricatorDashboardPanel::copyPanel($copy, $panel, $viewer); $copy->openTransaction(); $copy->save(); diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php b/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php index 48940dde60..c9be8bf013 100644 --- a/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php +++ b/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php @@ -28,12 +28,16 @@ final class PhabricatorDashboardPanelEditEngine return pht('Edit Dashboard Panels'); } + protected function supportsSearch() { + return true; + } + public function getSummaryText() { return pht('This engine is used to modify dashboard panels.'); } public function getEngineApplicationClass() { - return 'PhabricatorSearchApplication'; + return 'PhabricatorDashboardApplication'; } protected function newEditableObject() { diff --git a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php index 6cb7810d0b..792f6f9aa5 100644 --- a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php +++ b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php @@ -51,6 +51,7 @@ final class PhabricatorDashboardTransactionEditor $types[] = PhabricatorTransactions::TYPE_EDGE; $types[] = PhabricatorDashboardTransaction::TYPE_NAME; + $types[] = PhabricatorDashboardTransaction::TYPE_ICON; $types[] = PhabricatorDashboardTransaction::TYPE_STATUS; $types[] = PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE; @@ -66,6 +67,11 @@ final class PhabricatorDashboardTransactionEditor return null; } return $object->getName(); + case PhabricatorDashboardTransaction::TYPE_ICON: + if ($this->getIsNewObject()) { + return null; + } + return $object->getIcon(); case PhabricatorDashboardTransaction::TYPE_STATUS: if ($this->getIsNewObject()) { return null; @@ -87,6 +93,7 @@ final class PhabricatorDashboardTransactionEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorDashboardTransaction::TYPE_NAME: + case PhabricatorDashboardTransaction::TYPE_ICON: case PhabricatorDashboardTransaction::TYPE_STATUS: case PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE: return $xaction->getNewValue(); @@ -101,6 +108,9 @@ final class PhabricatorDashboardTransactionEditor case PhabricatorDashboardTransaction::TYPE_NAME: $object->setName($xaction->getNewValue()); return; + case PhabricatorDashboardTransaction::TYPE_ICON: + $object->setIcon($xaction->getNewValue()); + return; case PhabricatorDashboardTransaction::TYPE_STATUS: $object->setStatus($xaction->getNewValue()); return; @@ -130,6 +140,7 @@ final class PhabricatorDashboardTransactionEditor switch ($xaction->getTransactionType()) { case PhabricatorDashboardTransaction::TYPE_NAME: + case PhabricatorDashboardTransaction::TYPE_ICON: case PhabricatorDashboardTransaction::TYPE_STATUS: case PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE: return; diff --git a/src/applications/dashboard/icon/PhabricatorDashboardIconSet.php b/src/applications/dashboard/icon/PhabricatorDashboardIconSet.php new file mode 100644 index 0000000000..1bd12609b7 --- /dev/null +++ b/src/applications/dashboard/icon/PhabricatorDashboardIconSet.php @@ -0,0 +1,45 @@ + pht('Home'), + 'fa-th-large' => pht('Blocks'), + 'fa-columns' => pht('Columns'), + 'fa-bookmark' => pht('Page Saver'), + + 'fa-book' => pht('Knowledge'), + 'fa-bomb' => pht('Kaboom'), + 'fa-pie-chart' => pht('Apple Blueberry'), + 'fa-bar-chart' => pht('Serious Business'), + + 'fa-bell' => pht('Ding Ding'), + 'fa-credit-card' => pht('Plastic Debt'), + 'fa-code' => pht('PHP is Life'), + 'fa-sticky-note' => pht('To Self'), + + 'fa-newspaper-o' => pht('Stay Woke'), + 'fa-server' => pht('Metallica'), + 'fa-hashtag' => pht('Corned Beef'), + 'fa-group' => pht('Triplets'), + ); + + $icons = array(); + foreach ($map as $key => $label) { + $icons[] = id(new PhabricatorIconSetIcon()) + ->setKey($key) + ->setLabel($label); + } + + return $icons; + } + +} diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php index 3a6589a32c..ac72c9ce6f 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php @@ -7,6 +7,7 @@ final class PhabricatorDashboardPanelQuery private $phids; private $archived; private $panelTypes; + private $authorPHIDs; public function withIDs(array $ids) { $this->ids = $ids; @@ -28,6 +29,17 @@ final class PhabricatorDashboardPanelQuery return $this; } + public function withAuthorPHIDs(array $authors) { + $this->authorPHIDs = $authors; + return $this; + } + + public function withNameNgrams($ngrams) { + return $this->withNgramsConstraint( + id(new PhabricatorDashboardPanelNgrams()), + $ngrams); + } + protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } @@ -75,6 +87,13 @@ final class PhabricatorDashboardPanelQuery $this->panelTypes); } + if ($this->authorPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'authorPHID IN (%Ls)', + $this->authorPHIDs); + } + return $where; } @@ -82,4 +101,8 @@ final class PhabricatorDashboardPanelQuery return 'PhabricatorDashboardApplication'; } + protected function getPrimaryTableAlias() { + return 'dashboard_panel'; + } + } diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php index 113ed8ff94..89e77997d8 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php @@ -34,12 +34,28 @@ final class PhabricatorDashboardPanelSearchEngine $query->withPanelTypes(array($map['paneltype'])); } + if ($map['authorPHIDs']) { + $query->withAuthorPHIDs($map['authorPHIDs']); + } + + if ($map['name'] !== null) { + $query->withNameNgrams($map['name']); + } + return $query; } protected function buildCustomSearchFields() { return array( + id(new PhabricatorSearchTextField()) + ->setLabel(pht('Name Contains')) + ->setKey('name') + ->setDescription(pht('Search for panels by name substring.')), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Authored By')) + ->setKey('authorPHIDs') + ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()), id(new PhabricatorSearchSelectField()) ->setKey('status') ->setLabel(pht('Status')) @@ -60,19 +76,32 @@ final class PhabricatorDashboardPanelSearchEngine } protected function getBuiltinQueryNames() { - return array( - 'active' => pht('Active Panels'), - 'all' => pht('All Panels'), - ); + $names = array(); + + if ($this->requireViewer()->isLoggedIn()) { + $names['authored'] = pht('Authored'); + } + + $names['active'] = pht('Active Panels'); + $names['all'] = pht('All Panels'); + + return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); + $viewer = $this->requireViewer(); switch ($query_key) { case 'active': return $query->setParameter('status', 'active'); + case 'authored': + return $query->setParameter( + 'authorPHIDs', + array( + $viewer->getPHID(), + )); case 'all': return $query; } diff --git a/src/applications/dashboard/query/PhabricatorDashboardQuery.php b/src/applications/dashboard/query/PhabricatorDashboardQuery.php index 55cd447c7a..a54cfbc47c 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardQuery.php +++ b/src/applications/dashboard/query/PhabricatorDashboardQuery.php @@ -6,6 +6,7 @@ final class PhabricatorDashboardQuery private $ids; private $phids; private $statuses; + private $authorPHIDs; private $needPanels; private $needProjects; @@ -25,6 +26,11 @@ final class PhabricatorDashboardQuery return $this; } + public function withAuthorPHIDs(array $authors) { + $this->authorPHIDs = $authors; + return $this; + } + public function needPanels($need_panels) { $this->needPanels = $need_panels; return $this; @@ -35,6 +41,12 @@ final class PhabricatorDashboardQuery return $this; } + public function withNameNgrams($ngrams) { + return $this->withNgramsConstraint( + id(new PhabricatorDashboardNgrams()), + $ngrams); + } + protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } @@ -121,6 +133,13 @@ final class PhabricatorDashboardQuery $this->statuses); } + if ($this->authorPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'authorPHID IN (%Ls)', + $this->authorPHIDs); + } + return $where; } @@ -128,4 +147,8 @@ final class PhabricatorDashboardQuery return 'PhabricatorDashboardApplication'; } + protected function getPrimaryTableAlias() { + return 'dashboard'; + } + } diff --git a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php index 26c71c1bab..c6c6ab1233 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php +++ b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php @@ -18,6 +18,14 @@ final class PhabricatorDashboardSearchEngine protected function buildCustomSearchFields() { return array( + id(new PhabricatorSearchTextField()) + ->setLabel(pht('Name Contains')) + ->setKey('name') + ->setDescription(pht('Search for dashboards by name substring.')), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Authored By')) + ->setKey('authorPHIDs') + ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()), id(new PhabricatorSearchCheckboxesField()) ->setKey('statuses') ->setLabel(pht('Status')) @@ -30,19 +38,32 @@ final class PhabricatorDashboardSearchEngine } protected function getBuiltinQueryNames() { - return array( - 'open' => pht('Active Dashboards'), - 'all' => pht('All Dashboards'), - ); + $names = array(); + + if ($this->requireViewer()->isLoggedIn()) { + $names['authored'] = pht('Authored'); + } + + $names['open'] = pht('Active Dashboards'); + $names['all'] = pht('All Dashboards'); + + return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); + $viewer = $this->requireViewer(); switch ($query_key) { case 'all': return $query; + case 'authored': + return $query->setParameter( + 'authorPHIDs', + array( + $viewer->getPHID(), + )); case 'open': return $query->setParameter( 'statuses', @@ -61,6 +82,14 @@ final class PhabricatorDashboardSearchEngine $query->withStatuses($map['statuses']); } + if ($map['authorPHIDs']) { + $query->withAuthorPHIDs($map['authorPHIDs']); + } + + if ($map['name'] !== null) { + $query->withNameNgrams($map['name']); + } + return $query; } diff --git a/src/applications/dashboard/storage/PhabricatorDashboard.php b/src/applications/dashboard/storage/PhabricatorDashboard.php index 2930ca7674..fb50cba692 100644 --- a/src/applications/dashboard/storage/PhabricatorDashboard.php +++ b/src/applications/dashboard/storage/PhabricatorDashboard.php @@ -9,12 +9,15 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO PhabricatorPolicyInterface, PhabricatorFlaggableInterface, PhabricatorDestructibleInterface, - PhabricatorProjectInterface { + PhabricatorProjectInterface, + PhabricatorNgramsInterface { protected $name; + protected $authorPHID; protected $viewPolicy; protected $editPolicy; protected $status; + protected $icon; protected $layoutConfig = array(); const STATUS_ACTIVE = 'active'; @@ -28,9 +31,11 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO public static function initializeNewDashboard(PhabricatorUser $actor) { return id(new PhabricatorDashboard()) ->setName('') + ->setIcon('fa-dashboard') ->setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setEditPolicy($actor->getPHID()) ->setStatus(self::STATUS_ACTIVE) + ->setAuthorPHID($actor->getPHID()) ->attachPanels(array()) ->attachPanelPHIDs(array()); } @@ -59,8 +64,10 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO 'layoutConfig' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'name' => 'text255', + 'name' => 'sort255', 'status' => 'text32', + 'icon' => 'text32', + 'authorPHID' => 'phid', ), ) + parent::getConfiguration(); } @@ -113,6 +120,10 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO return ($this->getStatus() == self::STATUS_ARCHIVED); } + public function getViewURI() { + return '/dashboard/view/'.$this->getID().'/'; + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ @@ -180,4 +191,14 @@ final class PhabricatorDashboard extends PhabricatorDashboardDAO } +/* -( PhabricatorNgramInterface )------------------------------------------ */ + + + public function newNgrams() { + return array( + id(new PhabricatorDashboardNgrams()) + ->setValue($this->getName()), + ); + } + } diff --git a/src/applications/dashboard/storage/PhabricatorDashboardNgrams.php b/src/applications/dashboard/storage/PhabricatorDashboardNgrams.php new file mode 100644 index 0000000000..7884ec43f9 --- /dev/null +++ b/src/applications/dashboard/storage/PhabricatorDashboardNgrams.php @@ -0,0 +1,18 @@ +setName('') + ->setAuthorPHID($actor->getPHID()) ->setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setEditPolicy($actor->getPHID()); } public static function copyPanel( PhabricatorDashboardPanel $dst, - PhabricatorDashboardPanel $src) { + PhabricatorDashboardPanel $src, + PhabricatorUser $user) { $dst->name = $src->name; $dst->panelType = $src->panelType; $dst->properties = $src->properties; + $dst->authorPHID = $user->getPHID(); return $dst; } @@ -46,8 +51,9 @@ final class PhabricatorDashboardPanel 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'name' => 'text255', + 'name' => 'sort255', 'panelType' => 'text64', + 'authorPHID' => 'phid', 'isArchived' => 'bool', ), ) + parent::getConfiguration(); @@ -192,4 +198,15 @@ final class PhabricatorDashboardPanel $this->saveTransaction(); } + +/* -( PhabricatorNgramInterface )------------------------------------------ */ + + + public function newNgrams() { + return array( + id(new PhabricatorDashboardPanelNgrams()) + ->setValue($this->getName()), + ); + } + } diff --git a/src/applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php b/src/applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php new file mode 100644 index 0000000000..536da8b751 --- /dev/null +++ b/src/applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php @@ -0,0 +1,18 @@ +executeQuery($query); + $results = array(); + foreach ($dashboards as $dashboard) { + $result = id(new PhabricatorTypeaheadResult()) + ->setName($dashboard->getName()) + ->setPHID($dashboard->getPHID()) + ->addAttribute(pht('Dashboard')); + + if ($dashboard->isArchived()) { + $result->setClosed(pht('Archived')); + } + + $results[] = $result; + } + + return $this->filterResultsAgainstTokens($results); + } + +} diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php new file mode 100644 index 0000000000..35c8c5c212 --- /dev/null +++ b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php @@ -0,0 +1,46 @@ +executeQuery($query); + $results = array(); + foreach ($panels as $panel) { + $impl = $panel->getImplementation(); + if ($impl) { + $type_text = $impl->getPanelTypeName(); + } else { + $type_text = nonempty($panel->getPanelType(), pht('Unknown Type')); + } + + $result = id(new PhabricatorTypeaheadResult()) + ->setName($panel->getName()) + ->setPHID($panel->getPHID()) + ->addAttribute($type_text); + + if ($panel->getIsArchived()) { + $result->setClosed(pht('Archived')); + } + + $results[] = $result; + } + + return $this->filterResultsAgainstTokens($results); + } + +} diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php index 589dfe239d..b5a3ea95dc 100644 --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -65,7 +65,9 @@ final class PhabricatorDifferentialApplication extends PhabricatorApplication { ), 'changeset/' => 'DifferentialChangesetViewController', 'revision/' => array( - 'edit/(?:(?P[1-9]\d*)/)?' + $this->getEditRoutePattern('edit/') + => 'DifferentialRevisionEditController', + $this->getEditRoutePattern('attach/(?P[^/]+)/to/') => 'DifferentialRevisionEditController', 'land/(?:(?P[1-9]\d*))/(?P[^/]+)/' => 'DifferentialRevisionLandController', diff --git a/src/applications/differential/conduit/DifferentialConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialConduitAPIMethod.php index fdcf4395dd..34843b5609 100644 --- a/src/applications/differential/conduit/DifferentialConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialConduitAPIMethod.php @@ -53,21 +53,16 @@ abstract class DifferentialConduitAPIMethod extends ConduitAPIMethod { $viewer = $request->getUser(); - $field_list = PhabricatorCustomField::getObjectFields( - $revision, - DifferentialCustomField::ROLE_COMMITMESSAGEEDIT); - - $field_list - ->setViewer($viewer) - ->readFieldsFromStorage($revision); - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); + // We're going to build the body of a "differential.revision.edit" API + // request, then just call that code directly. $xactions = array(); + $xactions[] = array( + 'type' => DifferentialRevisionEditEngine::KEY_UPDATE, + 'value' => $diff->getPHID(), + ); - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) - ->setNewValue($diff->getPHID()); - + $field_map = DifferentialCommitMessageField::newEnabledFields($viewer); $values = $request->getValue('fields', array()); foreach ($values as $key => $value) { $field = idx($field_map, $key); @@ -79,70 +74,48 @@ abstract class DifferentialConduitAPIMethod extends ConduitAPIMethod { continue; } - $role = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS; - if (!$field->shouldEnableForRole($role)) { - continue; - } - - // TODO: This is fairly similar to PhabricatorCustomField's - // buildFieldTransactionsFromRequest() method, but that's currently not - // easy to reuse. - - $transaction_type = $field->getApplicationTransactionType(); - $xaction = id(new DifferentialTransaction()) - ->setTransactionType($transaction_type); - - if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { - // For TYPE_CUSTOMFIELD transactions only, we provide the old value - // as an input. - $old_value = $field->getOldValueForApplicationTransactions(); - $xaction->setOldValue($old_value); - } - // The transaction itself will be validated so this is somewhat // redundant, but this validator will sometimes give us a better error // message or a better reaction to a bad value type. - $field->validateCommitMessageValue($value); - $field->readValueFromCommitMessage($value); + $value = $field->readFieldValueFromConduit($value); - $xaction - ->setNewValue($field->getNewValueForApplicationTransactions()); - - if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { - // For TYPE_CUSTOMFIELD transactions, add the field key in metadata. - $xaction->setMetadataValue('customfield:key', $field->getFieldKey()); + foreach ($field->getFieldTransactions($value) as $xaction) { + $xactions[] = $xaction; } - - $metadata = $field->getApplicationTransactionMetadata(); - foreach ($metadata as $meta_key => $meta_value) { - $xaction->setMetadataValue($meta_key, $meta_value); - } - - $xactions[] = $xaction; } $message = $request->getValue('message'); if (strlen($message)) { - // This is a little awkward, and should maybe move inside the transaction - // editor. It largely exists for legacy reasons. + // This is a little awkward, and should move elsewhere or be removed. It + // largely exists for legacy reasons. See some discussion in T7899. $first_line = head(phutil_split_lines($message, false)); + + $first_line = id(new PhutilUTF8StringTruncator()) + ->setMaximumBytes(250) + ->setMaximumGlyphs(80) + ->truncateString($first_line); + $diff->setDescription($first_line); $diff->save(); - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) - ->attachComment( - id(new DifferentialTransactionComment()) - ->setContent($message)); + $xactions[] = array( + 'type' => PhabricatorCommentEditEngineExtension::EDITKEY, + 'value' => $message, + ); } - $editor = id(new DifferentialTransactionEditor()) - ->setActor($viewer) - ->setContentSource($request->newContentSource()) - ->setContinueOnNoEffect(true) - ->setContinueOnMissingFields(true); + $method = 'differential.revision.edit'; + $params = array( + 'transactions' => $xactions, + ); - $editor->applyTransactions($revision, $xactions); + if ($revision->getID()) { + $params['objectIdentifier'] = $revision->getID(); + } + + return id(new ConduitCall($method, $params, $strict = true)) + ->setUser($viewer) + ->execute(); } protected function loadCustomFieldsForRevisions( diff --git a/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php index 95b4309c70..371d57cd9c 100644 --- a/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php @@ -45,16 +45,18 @@ final class DifferentialCreateRevisionConduitAPIMethod $revision = DifferentialRevision::initializeNewRevision($viewer); $revision->attachReviewerStatus(array()); - $this->applyFieldEdit( + $result = $this->applyFieldEdit( $request, $revision, $diff, $request->getValue('fields', array()), $message = null); + $revision_id = $result['object']['id']; + return array( - 'revisionid' => $revision->getID(), - 'uri' => PhabricatorEnv::getURI('/D'.$revision->getID()), + 'revisionid' => $revision_id, + 'uri' => PhabricatorEnv::getURI('/D'.$revision_id), ); } diff --git a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php index 288a8c4ca9..2c5c936679 100644 --- a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php @@ -47,94 +47,77 @@ final class DifferentialGetCommitMessageConduitAPIMethod } } else { $revision = DifferentialRevision::initializeNewRevision($viewer); - $revision->attachReviewerStatus(array()); - $revision->attachActiveDiff(null); } - $is_edit = $request->getValue('edit'); - $is_create = ($is_edit == 'create'); + // There are three modes here: "edit", "create", and "read" (which has + // no value for the "edit" parameter). - $field_list = PhabricatorCustomField::getObjectFields( - $revision, - ($is_edit - ? DifferentialCustomField::ROLE_COMMITMESSAGEEDIT - : DifferentialCustomField::ROLE_COMMITMESSAGE)); + // In edit or create mode, we hide read-only fields. In create mode, we + // show "Field:" templates for some fields even if they are empty. + $edit_mode = $request->getValue('edit'); - $field_list - ->setViewer($viewer) - ->readFieldsFromStorage($revision); + $is_any_edit = (bool)strlen($edit_mode); + $is_create = ($edit_mode == 'create'); - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); + $field_list = DifferentialCommitMessageField::newEnabledFields($viewer); - if ($is_edit) { - $fields = $request->getValue('fields', array()); - foreach ($fields as $field => $value) { - $custom_field = idx($field_map, $field); - if (!$custom_field) { - // Just ignore this, these workflows don't make strong distictions - // about field editability on the client side. - continue; - } - if ($is_create || - $custom_field->shouldOverwriteWhenCommitMessageIsEdited()) { - $custom_field->readValueFromCommitMessage($value); + $custom_storage = $this->loadCustomFieldStorage($viewer, $revision); + foreach ($field_list as $field) { + $field->setCustomFieldStorage($custom_storage); + } + + // If we're editing the message, remove fields like "Conflicts" and + // "git-svn-id" which should not be presented to the user for editing. + if ($is_any_edit) { + foreach ($field_list as $field_key => $field) { + if (!$field->isFieldEditable()) { + unset($field_list[$field_key]); } } } - $phids = array(); - foreach ($field_list->getFields() as $key => $field) { - $field_phids = $field->getRequiredHandlePHIDsForCommitMessage(); - if (!is_array($field_phids)) { - throw new Exception( - pht( - 'Custom field "%s" was expected to return an array of handle '. - 'PHIDs required for commit message rendering, but returned "%s" '. - 'instead.', - $field->getFieldKey(), - gettype($field_phids))); + $overrides = $request->getValue('fields', array()); + + $value_map = array(); + foreach ($field_list as $field_key => $field) { + if (array_key_exists($field_key, $overrides)) { + $field_value = $overrides[$field_key]; + } else { + $field_value = $field->readFieldValueFromObject($revision); } - $phids[$key] = $field_phids; + + // We're calling this method on the value no matter where we got it + // from, so we hit the same validation logic for values which came over + // the wire and which we generated. + $field_value = $field->readFieldValueFromConduit($field_value); + + $value_map[$field_key] = $field_value; } - $all_phids = array_mergev($phids); - if ($all_phids) { - $all_handles = id(new PhabricatorHandleQuery()) - ->setViewer($viewer) - ->withPHIDs($all_phids) - ->execute(); - } else { - $all_handles = array(); - } - - $key_title = id(new DifferentialTitleField())->getFieldKey(); - $default_title = DifferentialTitleField::getDefaultTitle(); + $key_title = DifferentialTitleCommitMessageField::FIELDKEY; $commit_message = array(); - foreach ($field_list->getFields() as $key => $field) { - $handles = array_select_keys($all_handles, $phids[$key]); + foreach ($field_list as $field_key => $field) { + $label = $field->getFieldName(); + $wire_value = $value_map[$field_key]; + $value = $field->renderFieldValue($wire_value); - $label = $field->renderCommitMessageLabel(); - $value = $field->renderCommitMessageValue($handles); + $is_template = ($is_create && $field->isTemplateField()); if (!is_string($value) && !is_null($value)) { throw new Exception( pht( - 'Custom field "%s" was expected to render a string or null value, '. - 'but rendered a "%s" instead.', + 'Commit message field "%s" was expected to render a string or '. + 'null value, but rendered a "%s" instead.', $field->getFieldKey(), gettype($value))); } - $is_title = ($key == $key_title); + $is_title = ($field_key == $key_title); if (!strlen($value)) { - if ($is_title) { - $commit_message[] = $default_title; - } else { - if ($is_edit && $field->shouldAppearInCommitMessageTemplate()) { - $commit_message[] = $label.': '; - } + if ($is_template) { + $commit_message[] = $label.': '; } } else { if ($is_title) { @@ -153,46 +136,31 @@ final class DifferentialGetCommitMessageConduitAPIMethod } } - if ($is_edit) { - $tip = $this->getProTip($field_list); - if ($tip !== null) { - $commit_message[] = "\n".$tip; + return implode("\n\n", $commit_message); + } + + private function loadCustomFieldStorage( + PhabricatorUser $viewer, + DifferentialRevision $revision) { + $custom_field_list = PhabricatorCustomField::getObjectFields( + $revision, + DifferentialCustomField::ROLE_COMMITMESSAGE); + $custom_field_list + ->setViewer($viewer) + ->readFieldsFromStorage($revision); + + $custom_field_map = array(); + foreach ($custom_field_list->getFields() as $custom_field) { + if (!$custom_field->shouldUseStorage()) { + continue; } + $custom_field_key = $custom_field->getFieldKey(); + $custom_field_value = $custom_field->getValueForStorage(); + $custom_field_map[$custom_field_key] = $custom_field_value; } - $commit_message = implode("\n\n", $commit_message); - - return $commit_message; + return $custom_field_map; } - private function getProTip() { - // Any field can provide tips, whether it normally appears on commit - // messages or not. - $field_list = PhabricatorCustomField::getObjectFields( - new DifferentialRevision(), - PhabricatorCustomField::ROLE_DEFAULT); - - $tips = array(); - foreach ($field_list->getFields() as $key => $field) { - $tips[] = $field->getProTips(); - } - $tips = array_mergev($tips); - - if (!$tips) { - return null; - } - - shuffle($tips); - - $tip = pht('Tip: %s', head($tips)); - $tip = wordwrap($tip, 78, "\n", true); - - $lines = explode("\n", $tip); - foreach ($lines as $key => $line) { - $lines[$key] = '# '.$line; - } - - return implode("\n", $lines); - } } diff --git a/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php index dc29ff07a9..59401862f0 100644 --- a/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php @@ -3,8 +3,6 @@ final class DifferentialParseCommitMessageConduitAPIMethod extends DifferentialConduitAPIMethod { - private $errors; - public function getAPIMethodName() { return 'differential.parsecommitmessage'; } @@ -25,63 +23,28 @@ final class DifferentialParseCommitMessageConduitAPIMethod } protected function execute(ConduitAPIRequest $request) { - $viewer = $request->getUser(); - $corpus = $request->getValue('corpus'); + $viewer = $this->getViewer(); + + $parser = DifferentialCommitMessageParser::newStandardParser($viewer); + $is_partial = $request->getValue('partial'); - - $field_list = PhabricatorCustomField::getObjectFields( - new DifferentialRevision(), - DifferentialCustomField::ROLE_COMMITMESSAGE); - $field_list->setViewer($viewer); - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); - - $corpus_map = $this->parseCommitMessage($corpus); - - $values = array(); - foreach ($corpus_map as $field_key => $text_value) { - $field = idx($field_map, $field_key); - - if (!$field) { - throw new Exception( - pht( - 'Parser emitted text value for field key "%s", but no such '. - 'field exists.', - $field_key)); - } - - try { - $values[$field_key] = $field->parseValueFromCommitMessage($text_value); - } catch (DifferentialFieldParseException $ex) { - $this->errors[] = pht( - 'Error parsing field "%s": %s', - $field->renderCommitMessageLabel(), - $ex->getMessage()); - } + if ($is_partial) { + $parser->setRaiseMissingFieldErrors(false); } - if (!$is_partial) { - foreach ($field_map as $key => $field) { - try { - $field->validateCommitMessageValue(idx($values, $key)); - } catch (DifferentialFieldValidationException $ex) { - $this->errors[] = pht( - 'Invalid or missing field "%s": %s', - $field->renderCommitMessageLabel(), - $ex->getMessage()); - } - } - } + $corpus = $request->getValue('corpus'); + $field_map = $parser->parseFields($corpus); + + $errors = $parser->getErrors(); - // grab some extra information about the Differential Revision: field... - $revision_id_field = new DifferentialRevisionIDField(); $revision_id_value = idx( - $corpus_map, - $revision_id_field->getFieldKeyForConduit()); + $field_map, + DifferentialRevisionIDCommitMessageField::FIELDKEY); $revision_id_valid_domain = PhabricatorEnv::getProductionURI(''); return array( - 'errors' => $this->errors, - 'fields' => $values, + 'errors' => $errors, + 'fields' => $field_map, 'revisionIDFieldInfo' => array( 'value' => $revision_id_value, 'validDomain' => $revision_id_valid_domain, @@ -89,17 +52,4 @@ final class DifferentialParseCommitMessageConduitAPIMethod ); } - private function parseCommitMessage($corpus) { - $viewer = $this->getViewer(); - $parser = DifferentialCommitMessageParser::newStandardParser($viewer); - $result = $parser->parseCorpus($corpus); - - $this->errors = array(); - foreach ($parser->getErrors() as $error) { - $this->errors[] = $error; - } - - return $result; - } - } diff --git a/src/applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php new file mode 100644 index 0000000000..cb7c7e2e93 --- /dev/null +++ b/src/applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php @@ -0,0 +1,18 @@ + DifferentialReviewerStatus::STATUS_ADDED, diff --git a/src/applications/differential/controller/DifferentialDiffViewController.php b/src/applications/differential/controller/DifferentialDiffViewController.php index b2c497f6ac..dae65bb200 100644 --- a/src/applications/differential/controller/DifferentialDiffViewController.php +++ b/src/applications/differential/controller/DifferentialDiffViewController.php @@ -23,6 +23,20 @@ final class DifferentialDiffViewController extends DifferentialController { ->setURI('/D'.$diff->getRevisionID().'?id='.$diff->getID()); } + if ($request->isFormPost()) { + $diff_id = $diff->getID(); + $revision_id = $request->getInt('revisionID'); + if ($revision_id) { + $attach_uri = "/revision/attach/{$diff_id}/to/{$revision_id}/"; + } else { + $attach_uri = "/revision/attach/{$diff_id}/to/"; + } + $attach_uri = $this->getApplicationURI($attach_uri); + + return id(new AphrontRedirectResponse()) + ->setURI($attach_uri); + } + $diff_phid = $diff->getPHID(); $buildables = id(new HarbormasterBuildableQuery()) ->setViewer($viewer) @@ -78,13 +92,7 @@ final class DifferentialDiffViewController extends DifferentialController { $select); $form = id(new AphrontFormView()) - ->setUser($request->getUser()) - ->setAction('/differential/revision/edit/') - ->addHiddenInput('diffID', $diff->getID()) - ->addHiddenInput('viaDiffView', 1) - ->addHiddenInput( - id(new DifferentialRepositoryField())->getFieldKey(), - $diff->getRepositoryPHID()) + ->setViewer($viewer) ->appendRemarkupInstructions( pht( 'Review the diff for correctness. When you are satisfied, either '. @@ -98,7 +106,7 @@ final class DifferentialDiffViewController extends DifferentialController { ->setValue(pht('Continue'))); $props = id(new DifferentialDiffProperty())->loadAllWhere( - 'diffID = %d', + 'diffID = %d', $diff->getID()); $props = mpull($props, 'getData', 'getName'); diff --git a/src/applications/differential/controller/DifferentialRevisionEditController.php b/src/applications/differential/controller/DifferentialRevisionEditController.php index eb3aa08521..48fea82f7c 100644 --- a/src/applications/differential/controller/DifferentialRevisionEditController.php +++ b/src/applications/differential/controller/DifferentialRevisionEditController.php @@ -5,34 +5,12 @@ final class DifferentialRevisionEditController public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); - $id = $request->getURIData('id'); - if (!$id) { - $id = $request->getInt('revisionID'); - } + // If we have a Diff ID, this is an "/attach/123/to/456/" action. The + // user just created a diff and is trying to use it to create or update + // a revision. + $diff_id = $request->getURIData('diffID'); - if ($id) { - $revision = id(new DifferentialRevisionQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->needRelationships(true) - ->needReviewerStatus(true) - ->needActiveDiffs(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$revision) { - return new Aphront404Response(); - } - } else { - $revision = DifferentialRevision::initializeNewRevision($viewer); - $revision->attachReviewerStatus(array()); - } - - $diff_id = $request->getInt('diffID'); if ($diff_id) { $diff = id(new DifferentialDiffQuery()) ->setViewer($viewer) @@ -41,174 +19,38 @@ final class DifferentialRevisionEditController if (!$diff) { return new Aphront404Response(); } + if ($diff->getRevisionID()) { - // TODO: Redirect? - throw new Exception( - pht('This diff is already attached to a revision!')); + $revision = $diff->getRevision(); + return $this->newDialog() + ->setTitle(pht('Diff Already Attached')) + ->appendParagraph( + pht( + 'This diff is already attached to a revision.')) + ->addCancelButton($revision->getURI(), pht('Continue')); } } else { $diff = null; } - if (!$diff) { - if (!$revision->getID()) { - throw new Exception( - pht('You can not create a new revision without a diff!')); - } - } else { - // TODO: It would be nice to show the diff being attached in the UI. + $revision_id = $request->getURIData('id'); + if (!$diff && !$revision_id) { + return $this->newDialog() + ->setTitle(pht('Diff Required')) + ->appendParagraph( + pht( + 'You can not create a revision without a diff.')) + ->addCancelButton($this->getApplicationURI()); } - $field_list = PhabricatorCustomField::getObjectFields( - $revision, - PhabricatorCustomField::ROLE_EDIT); - $field_list - ->setViewer($viewer) - ->readFieldsFromStorage($revision); + $engine = id(new DifferentialRevisionEditEngine()) + ->setController($this); - if ($request->getStr('viaDiffView') && $diff) { - $repo_key = id(new DifferentialRepositoryField())->getFieldKey(); - $repository_field = idx( - $field_list->getFields(), - $repo_key); - if ($repository_field) { - $repository_field->setValue($request->getStr($repo_key)); - } - $view_policy_key = id(new DifferentialViewPolicyField())->getFieldKey(); - $view_policy_field = idx( - $field_list->getFields(), - $view_policy_key); - if ($view_policy_field) { - $view_policy_field->setValue($diff->getViewPolicy()); - } - } - - $validation_exception = null; - if ($request->isFormPost() && !$request->getStr('viaDiffView')) { - - $editor = id(new DifferentialTransactionEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - $xactions = $field_list->buildFieldTransactionsFromRequest( - new DifferentialTransaction(), - $request); - - if ($diff) { - $repository_phid = null; - $repository_tokenizer = $request->getArr( - id(new DifferentialRepositoryField())->getFieldKey()); - if ($repository_tokenizer) { - $repository_phid = reset($repository_tokenizer); - } - - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) - ->setNewValue($diff->getPHID()); - - $editor->setRepositoryPHIDOverride($repository_phid); - } - - $comments = $request->getStr('comments'); - if (strlen($comments)) { - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) - ->attachComment( - id(new DifferentialTransactionComment()) - ->setContent($comments)); - } - - try { - $editor->applyTransactions($revision, $xactions); - $revision_uri = '/D'.$revision->getID(); - return id(new AphrontRedirectResponse())->setURI($revision_uri); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - } - } - - - $form = new AphrontFormView(); - $form->setUser($request->getUser()); if ($diff) { - $form->addHiddenInput('diffID', $diff->getID()); + $engine->setDiff($diff); } - if ($revision->getID()) { - $form->setAction('/differential/revision/edit/'.$revision->getID().'/'); - } else { - $form->setAction('/differential/revision/edit/'); - } - - if ($diff && $revision->getID()) { - $form - ->appendChild( - id(new AphrontFormTextAreaControl()) - ->setLabel(pht('Comments')) - ->setName('comments') - ->setCaption(pht("Explain what's new in this diff.")) - ->setValue($request->getStr('comments'))) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Save'))) - ->appendChild( - id(new AphrontFormDividerControl())); - } - - $field_list->appendFieldsToForm($form); - - $submit = id(new AphrontFormSubmitControl()) - ->setValue('Save'); - if ($diff) { - $submit->addCancelButton('/differential/diff/'.$diff->getID().'/'); - } else { - $submit->addCancelButton('/D'.$revision->getID()); - } - - $form->appendChild($submit); - - $crumbs = $this->buildApplicationCrumbs(); - if ($revision->getID()) { - if ($diff) { - $header_icon = 'fa-upload'; - $title = pht('Update Revision'); - $crumbs->addTextCrumb( - 'D'.$revision->getID(), - '/differential/diff/'.$diff->getID().'/'); - } else { - $header_icon = 'fa-pencil'; - $title = pht('Edit Revision: %s', $revision->getTitle()); - $crumbs->addTextCrumb( - 'D'.$revision->getID(), - '/D'.$revision->getID()); - } - } else { - $header_icon = 'fa-plus-square'; - $title = pht('Create New Differential Revision'); - } - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText('Revision') - ->setValidationException($validation_exception) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($form); - - $crumbs->addTextCrumb($title); - $crumbs->setBorder(true); - - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon($header_icon); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter($form_box); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); + return $engine->buildResponse(); } } diff --git a/src/applications/differential/customfield/DifferentialApplyPatchField.php b/src/applications/differential/customfield/DifferentialApplyPatchField.php deleted file mode 100644 index 24665b7f5c..0000000000 --- a/src/applications/differential/customfield/DifferentialApplyPatchField.php +++ /dev/null @@ -1,32 +0,0 @@ -getFieldName(); - } - - public function renderPropertyViewValue(array $handles) { - $mono = $this->getObject()->getMonogram(); - - return phutil_tag('tt', array(), "arc patch {$mono}"); - } - -} diff --git a/src/applications/differential/customfield/DifferentialAuditorsField.php b/src/applications/differential/customfield/DifferentialAuditorsField.php index d84fe0eda8..544f238458 100644 --- a/src/applications/differential/customfield/DifferentialAuditorsField.php +++ b/src/applications/differential/customfield/DifferentialAuditorsField.php @@ -16,7 +16,7 @@ final class DifferentialAuditorsField } public function getValueForStorage() { - return json_encode($this->getValue()); + return phutil_json_encode($this->getValue()); } public function setValueFromStorage($value) { @@ -28,33 +28,28 @@ final class DifferentialAuditorsField return $this; } - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - public function canDisableField() { return false; } - public function getRequiredHandlePHIDsForCommitMessage() { - return nonempty($this->getValue(), array()); + public function shouldAppearInEditEngine() { + return true; } - public function parseCommitMessageValue($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - )); + public function shouldAppearInCommitMessage() { + return true; } - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); + public function shouldAppearInConduitTransactions() { + return true; + } + + protected function newConduitEditParameterType() { + return new ConduitPHIDListParameterType(); + } + + public function shouldAppearInApplicationTransactions() { + return true; } } diff --git a/src/applications/differential/customfield/DifferentialAuthorField.php b/src/applications/differential/customfield/DifferentialAuthorField.php deleted file mode 100644 index fbd74dd2ab..0000000000 --- a/src/applications/differential/customfield/DifferentialAuthorField.php +++ /dev/null @@ -1,38 +0,0 @@ -getFieldName(); - } - - public function getRequiredHandlePHIDsForPropertyView() { - return array($this->getObject()->getAuthorPHID()); - } - - public function renderPropertyViewValue(array $handles) { - return $handles[$this->getObject()->getAuthorPHID()]->renderHovercardLink(); - } - -} diff --git a/src/applications/differential/customfield/DifferentialBlameRevisionField.php b/src/applications/differential/customfield/DifferentialBlameRevisionField.php index ba2220ae30..b2d8872225 100644 --- a/src/applications/differential/customfield/DifferentialBlameRevisionField.php +++ b/src/applications/differential/customfield/DifferentialBlameRevisionField.php @@ -32,6 +32,10 @@ final class DifferentialBlameRevisionField } public function renderPropertyViewValue(array $handles) { + if (!strlen($this->getValue())) { + return null; + } + return $this->getValue(); } @@ -91,27 +95,16 @@ final class DifferentialBlameRevisionField return true; } - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Blame Revision', - 'Blame Rev', - ); - } - - public function renderCommitMessageValue(array $handles) { - return $this->getValue(); - } - public function shouldAppearInConduitDictionary() { return true; } + public function shouldAppearInConduitTransactions() { + return true; + } + + protected function newConduitEditParameterType() { + return new ConduitStringParameterType(); + } + } diff --git a/src/applications/differential/customfield/DifferentialChildRevisionsField.php b/src/applications/differential/customfield/DifferentialChildRevisionsField.php deleted file mode 100644 index 1d9406a448..0000000000 --- a/src/applications/differential/customfield/DifferentialChildRevisionsField.php +++ /dev/null @@ -1,22 +0,0 @@ -isCoreFieldRequired()) { $this->setFieldError(true); diff --git a/src/applications/differential/customfield/DifferentialCustomField.php b/src/applications/differential/customfield/DifferentialCustomField.php index d0980736c4..f210dd0f63 100644 --- a/src/applications/differential/customfield/DifferentialCustomField.php +++ b/src/applications/differential/customfield/DifferentialCustomField.php @@ -20,6 +20,11 @@ abstract class DifferentialCustomField return $this->getFieldKey(); } + // TODO: As above. + public function getModernFieldKey() { + return $this->getFieldKeyForConduit(); + } + public function shouldEnableForRole($role) { switch ($role) { case self::ROLE_COMMITMESSAGE: diff --git a/src/applications/differential/customfield/DifferentialEditPolicyField.php b/src/applications/differential/customfield/DifferentialEditPolicyField.php deleted file mode 100644 index 8175fa2b5b..0000000000 --- a/src/applications/differential/customfield/DifferentialEditPolicyField.php +++ /dev/null @@ -1,50 +0,0 @@ -getEditPolicy(); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - $viewer = $this->getViewer(); - $revision = $this->getObject(); - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($revision) - ->execute(); - - return id(new AphrontFormPolicyControl()) - ->setUser($viewer) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicyObject($revision) - ->setPolicies($policies) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDIT_POLICY; - } - -} diff --git a/src/applications/differential/customfield/DifferentialGitSVNIDField.php b/src/applications/differential/customfield/DifferentialGitSVNIDField.php deleted file mode 100644 index de45c54c7f..0000000000 --- a/src/applications/differential/customfield/DifferentialGitSVNIDField.php +++ /dev/null @@ -1,45 +0,0 @@ -getValue(); if (!$value) { @@ -309,5 +307,12 @@ final class DifferentialJIRAIssuesField return true; } + public function shouldAppearInConduitTransactions() { + return true; + } + + protected function newConduitEditParameterType() { + return new ConduitStringListParameterType(); + } } diff --git a/src/applications/differential/customfield/DifferentialManiphestTasksField.php b/src/applications/differential/customfield/DifferentialManiphestTasksField.php index 56803f60c3..8e70f1da4d 100644 --- a/src/applications/differential/customfield/DifferentialManiphestTasksField.php +++ b/src/applications/differential/customfield/DifferentialManiphestTasksField.php @@ -7,18 +7,10 @@ final class DifferentialManiphestTasksField return 'differential:maniphest-tasks'; } - public function getFieldKeyForConduit() { - return 'maniphestTaskPHIDs'; - } - public function canDisableField() { return false; } - public function shouldAppearInEditView() { - return false; - } - public function getFieldName() { return pht('Maniphest Tasks'); } @@ -45,25 +37,6 @@ final class DifferentialManiphestTasksField DifferentialRevisionHasTaskEdgeType::EDGECONST); } - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDGE; - } - - public function getApplicationTransactionMetadata() { - return array( - 'edge:type' => DifferentialRevisionHasTaskEdgeType::EDGECONST, - ); - } - - public function getNewValueForApplicationTransactions() { - $edges = array(); - foreach ($this->getValue() as $phid) { - $edges[$phid] = $phid; - } - - return array('=' => $edges); - } - public function getRequiredHandlePHIDsForPropertyView() { return $this->getValue(); } @@ -72,44 +45,4 @@ final class DifferentialManiphestTasksField return $this->renderHandleList($handles); } - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Maniphest Task', - 'Maniphest Tasks', - ); - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - ManiphestTaskPHIDType::TYPECONST, - )); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getRequiredHandlePHIDsForPropertyView(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - - public function getProTips() { - return array( - pht( - 'Write "%s" in your summary to automatically close the '. - 'corresponding task when this change lands.', - 'Fixes T123'), - ); - } - } diff --git a/src/applications/differential/customfield/DifferentialNextStepField.php b/src/applications/differential/customfield/DifferentialNextStepField.php deleted file mode 100644 index bf0ed5972d..0000000000 --- a/src/applications/differential/customfield/DifferentialNextStepField.php +++ /dev/null @@ -1,65 +0,0 @@ -getFieldName(); - } - - public function renderPropertyViewValue(array $handles) { - $revision = $this->getObject(); - $diff = $revision->getActiveDiff(); - - $status = $revision->getStatus(); - if ($status != ArcanistDifferentialRevisionStatus::ACCEPTED) { - return null; - } - - $local_vcs = $diff->getSourceControlSystem(); - switch ($local_vcs) { - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: - $bookmark = $diff->getBookmark(); - if (strlen($bookmark)) { - $next_step = csprintf('arc land %R', $bookmark); - } else { - $next_step = csprintf('arc land'); - } - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: - $branch = $diff->getBranch(); - if (strlen($branch)) { - $next_step = csprintf('arc land %R', $branch); - } else { - $next_step = csprintf('arc land'); - } - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - $next_step = csprintf('arc commit'); - break; - default: - return null; - } - - $next_step = phutil_tag('tt', array(), (string)$next_step); - - return $next_step; - } - -} diff --git a/src/applications/differential/customfield/DifferentialParentRevisionsField.php b/src/applications/differential/customfield/DifferentialParentRevisionsField.php deleted file mode 100644 index 5dbc99dd6f..0000000000 --- a/src/applications/differential/customfield/DifferentialParentRevisionsField.php +++ /dev/null @@ -1,44 +0,0 @@ -getObject()->getPHID(), - DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST); - } - -} diff --git a/src/applications/differential/customfield/DifferentialProjectReviewersField.php b/src/applications/differential/customfield/DifferentialProjectReviewersField.php index c900f72659..87ea0c34a3 100644 --- a/src/applications/differential/customfield/DifferentialProjectReviewersField.php +++ b/src/applications/differential/customfield/DifferentialProjectReviewersField.php @@ -57,13 +57,4 @@ final class DifferentialProjectReviewersField return $reviewers; } - public function getProTips() { - return array( - pht( - 'You can add a project as a subscriber or reviewer by writing '. - '"%s" in the appropriate field.', - '#projectname'), - ); - } - } diff --git a/src/applications/differential/customfield/DifferentialProjectsField.php b/src/applications/differential/customfield/DifferentialProjectsField.php deleted file mode 100644 index 425e30e132..0000000000 --- a/src/applications/differential/customfield/DifferentialProjectsField.php +++ /dev/null @@ -1,114 +0,0 @@ -getPHID()) { - return array(); - } - - $projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $revision->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $projects = array_reverse($projects); - - return $projects; - } - - public function getNewValueForApplicationTransactions() { - return array('=' => array_fuse($this->getValue())); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getArr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new PhabricatorProjectDatasource()) - ->setValue($this->getValue()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDGE; - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Tags', - 'Project', - 'Projects', - ); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getValue(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - - public function shouldAppearInConduitDictionary() { - // To improve performance, we exclude this field from Conduit results. - // See T11404 for discussion. In modern "differential.revision.search", - // this information is available efficiently as an attachment. - return false; - } - - public function getApplicationTransactionMetadata() { - return array( - 'edge:type' => PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, - ); - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorProjectProjectPHIDType::TYPECONST, - )); - } - -} diff --git a/src/applications/differential/customfield/DifferentialRepositoryField.php b/src/applications/differential/customfield/DifferentialRepositoryField.php index 7f39d25823..1d403d160a 100644 --- a/src/applications/differential/customfield/DifferentialRepositoryField.php +++ b/src/applications/differential/customfield/DifferentialRepositoryField.php @@ -20,107 +20,6 @@ final class DifferentialRepositoryField return $revision->getRepositoryPHID(); } - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setRepositoryPHID($value); - } - - public function readValueFromRequest(AphrontRequest $request) { - $phids = $request->getArr($this->getFieldKey()); - $first = head($phids); - $this->setValue(nonempty($first, null)); - } - - public function renderEditControl(array $handles) { - if ($this->getValue()) { - $value = array($this->getValue()); - } else { - $value = array(); - } - - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new DiffusionRepositoryDatasource()) - ->setValue($value) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()) - ->setLimit(1); - } - - public function getApplicationTransactionRequiredHandlePHIDs( - PhabricatorApplicationTransaction $xaction) { - - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - $phids = array(); - if ($old) { - $phids[] = $old; - } - if ($new) { - $phids[] = $new; - } - - return $phids; - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if ($old && $new) { - return pht( - '%s changed the repository for this revision from %s to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($old), - $xaction->renderHandleLink($new)); - } else if ($new) { - return pht( - '%s set the repository for this revision to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($new)); - } else { - return pht( - '%s removed %s as the repository for this revision.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($old)); - } - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if ($old && $new) { - return pht( - '%s updated the repository for %s from %s to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $xaction->renderHandleLink($old), - $xaction->renderHandleLink($new)); - } else if ($new) { - return pht( - '%s set the repository for %s to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $xaction->renderHandleLink($new)); - } else { - return pht( - '%s removed the repository for %s. (Repository was %s.)', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $xaction->renderHandleLink($old)); - } - } - public function shouldAppearInPropertyView() { return true; } diff --git a/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php b/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php index 2408daa27c..421c129fdb 100644 --- a/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php +++ b/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php @@ -19,10 +19,6 @@ final class DifferentialRequiredSignaturesField return true; } - public function shouldAppearInEditView() { - return false; - } - protected function readValueFromRevision(DifferentialRevision $revision) { return self::loadForRevision($revision); } diff --git a/src/applications/differential/customfield/DifferentialRevertPlanField.php b/src/applications/differential/customfield/DifferentialRevertPlanField.php index 646116c74e..0fd5531426 100644 --- a/src/applications/differential/customfield/DifferentialRevertPlanField.php +++ b/src/applications/differential/customfield/DifferentialRevertPlanField.php @@ -142,4 +142,12 @@ final class DifferentialRevertPlanField return true; } + public function shouldAppearInConduitTransactions() { + return true; + } + + protected function newConduitEditParameterType() { + return new ConduitStringParameterType(); + } + } diff --git a/src/applications/differential/customfield/DifferentialReviewedByField.php b/src/applications/differential/customfield/DifferentialReviewedByField.php deleted file mode 100644 index 6f49c80fef..0000000000 --- a/src/applications/differential/customfield/DifferentialReviewedByField.php +++ /dev/null @@ -1,72 +0,0 @@ -getReviewerStatus() as $reviewer) { - switch ($reviewer->getStatus()) { - case DifferentialReviewerStatus::STATUS_ACCEPTED: - case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER: - $phids[] = $reviewer->getReviewerPHID(); - break; - } - } - - return $phids; - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - ), - $allow_partial = true); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getValue(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - -} diff --git a/src/applications/differential/customfield/DifferentialReviewersField.php b/src/applications/differential/customfield/DifferentialReviewersField.php index 41a4cf8f26..ad96a22b88 100644 --- a/src/applications/differential/customfield/DifferentialReviewersField.php +++ b/src/applications/differential/customfield/DifferentialReviewersField.php @@ -7,10 +7,6 @@ final class DifferentialReviewersField return 'differential:reviewers'; } - public function getFieldKeyForConduit() { - return 'reviewerPHIDs'; - } - public function getFieldName() { return pht('Reviewers'); } @@ -24,108 +20,6 @@ final class DifferentialReviewersField return $revision->getReviewerStatus(); } - public function getNewValueForApplicationTransactions() { - $specs = array(); - foreach ($this->getValue() as $reviewer) { - $specs[$reviewer->getReviewerPHID()] = array( - 'data' => $reviewer->getEdgeData(), - ); - } - - return array('=' => $specs); - } - - public function readValueFromRequest(AphrontRequest $request) { - $datasource = id(new DifferentialBlockingReviewerDatasource()) - ->setViewer($request->getViewer()); - - $new_phids = $request->getArr($this->getFieldKey()); - $new_phids = $datasource->evaluateTokens($new_phids); - - $reviewers = array(); - foreach ($new_phids as $spec) { - if (!is_array($spec)) { - $reviewers[$spec] = DifferentialReviewerStatus::STATUS_ADDED; - } else { - $reviewers[$spec['phid']] = $spec['type']; - } - } - - $this->updateReviewers($this->getValue(), $reviewers); - } - - private function updateReviewers(array $old_reviewers, array $new_map) { - // Compute a new set of reviewer objects. We're going to respect the new - // reviewer order, add or remove any new or missing reviewers, and respect - // any blocking or unblocking changes. For reviewers who were there before - // and are still there, we're going to keep the old value because it - // may be something like "Accept", "Reject", etc. - - $old_map = mpull($old_reviewers, 'getStatus', 'getReviewerPHID'); - $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; - - $new_reviewers = array(); - foreach ($new_map as $phid => $new) { - $old = idx($old_map, $phid); - - // If we have an old status and this didn't make the reviewer blocking - // or nonblocking, just retain the old status. This makes sure we don't - // throw away rejects, accepts, etc. - if ($old) { - $is_block = ($old !== $status_blocking && $new === $status_blocking); - $is_unblock = ($old === $status_blocking && $new !== $status_blocking); - if (!$is_block && !$is_unblock) { - $new_reviewers[$phid] = $old; - continue; - } - } - - $new_reviewers[$phid] = $new; - } - - foreach ($new_reviewers as $phid => $status) { - $new_reviewers[$phid] = new DifferentialReviewer( - $phid, - array( - 'status' => $status, - )); - } - - $this->setValue($new_reviewers); - } - - public function renderEditControl(array $handles) { - $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; - - $value = array(); - foreach ($this->getValue() as $reviewer) { - $phid = $reviewer->getReviewerPHID(); - if ($reviewer->getStatus() == $status_blocking) { - $value[] = 'blocking('.$phid.')'; - } else { - $value[] = $phid; - } - } - - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new DifferentialReviewerDatasource()) - ->setValue($value) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDGE; - } - - public function getApplicationTransactionMetadata() { - return array( - 'edge:type' => DifferentialRevisionHasReviewerEdgeType::EDGECONST, - ); - } - public function shouldAppearInPropertyView() { return true; } @@ -164,99 +58,6 @@ final class DifferentialReviewersField return $reviewers; } - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Reviewer', - 'Reviewers', - ); - } - - public function parseValueFromCommitMessage($value) { - $results = $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - PhabricatorOwnersPackagePHIDType::TYPECONST, - ), - false, - array('!')); - - return $this->flattenReviewers($results); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return mpull($this->getValue(), 'getReviewerPHID'); - } - - public function readValueFromCommitMessage($value) { - $value = $this->inflateReviewers($value); - - $reviewers = array(); - foreach ($value as $spec) { - $phid = $spec['phid']; - - $is_blocking = isset($spec['suffixes']['!']); - if ($is_blocking) { - $status = DifferentialReviewerStatus::STATUS_BLOCKING; - } else { - $status = DifferentialReviewerStatus::STATUS_ADDED; - } - - $reviewers[$phid] = $status; - } - - $this->updateReviewers( - $this->getObject()->getReviewerStatus(), - $reviewers); - - return $this; - } - - public function renderCommitMessageValue(array $handles) { - $suffixes = array(); - - $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; - - foreach ($this->getValue() as $reviewer) { - if ($reviewer->getStatus() == $status_blocking) { - $phid = $reviewer->getReviewerPHID(); - $suffixes[$phid] = '!'; - } - } - - return $this->renderObjectList($handles, $suffixes); - } - - public function validateCommitMessageValue($value) { - if (!$value) { - return; - } - - $author_phid = $this->getObject()->getAuthorPHID(); - - $config_self_accept_key = 'differential.allow-self-accept'; - $allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key); - - $value = $this->inflateReviewers($value); - foreach ($value as $spec) { - $phid = $spec['phid']; - - if (($phid == $author_phid) && !$allow_self_accept) { - throw new DifferentialFieldValidationException( - pht('The author of a revision can not be a reviewer.')); - } - } - } - public function getRequiredHandlePHIDsForRevisionHeaderWarnings() { return mpull($this->getValue(), 'getReviewerPHID'); } @@ -288,44 +89,4 @@ final class DifferentialReviewersField return $warnings; } - public function getProTips() { - return array( - pht( - 'You can mark a reviewer as blocking by adding an exclamation '. - 'mark ("!") after their name.'), - ); - } - - private function flattenReviewers(array $values) { - // NOTE: For now, `arc` relies on this field returning only scalars, so we - // need to reduce the results into scalars. See T10981. - $result = array(); - - foreach ($values as $value) { - $result[] = $value['phid'].implode('', array_keys($value['suffixes'])); - } - - return $result; - } - - private function inflateReviewers(array $values) { - $result = array(); - - foreach ($values as $value) { - if (substr($value, -1) == '!') { - $value = substr($value, 0, -1); - $suffixes = array('!' => '!'); - } else { - $suffixes = array(); - } - - $result[] = array( - 'phid' => $value, - 'suffixes' => $suffixes, - ); - } - - return $result; - } - } diff --git a/src/applications/differential/customfield/DifferentialSubscribersField.php b/src/applications/differential/customfield/DifferentialSubscribersField.php deleted file mode 100644 index b8423e9879..0000000000 --- a/src/applications/differential/customfield/DifferentialSubscribersField.php +++ /dev/null @@ -1,93 +0,0 @@ -getPHID()) { - return array(); - } - - return PhabricatorSubscribersQuery::loadSubscribersForPHID( - $revision->getPHID()); - } - - public function getNewValueForApplicationTransactions() { - return array('=' => $this->getValue()); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getArr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new PhabricatorMetaMTAMailableDatasource()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_SUBSCRIBERS; - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'CC', - 'CCs', - 'Subscriber', - 'Subscribers', - ); - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - PhabricatorOwnersPackagePHIDType::TYPECONST, - )); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getValue(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - -} diff --git a/src/applications/differential/customfield/DifferentialSummaryField.php b/src/applications/differential/customfield/DifferentialSummaryField.php index 5052e238e0..a11bebca6e 100644 --- a/src/applications/differential/customfield/DifferentialSummaryField.php +++ b/src/applications/differential/customfield/DifferentialSummaryField.php @@ -7,10 +7,6 @@ final class DifferentialSummaryField return 'differential:summary'; } - public function getFieldKeyForConduit() { - return 'summary'; - } - public function getFieldName() { return pht('Summary'); } @@ -27,69 +23,6 @@ final class DifferentialSummaryField return $revision->getSummary(); } - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setSummary($value); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new PhabricatorRemarkupControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the summary for this revision.', - $xaction->renderHandleLink($author_phid)); - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the summary for %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid)); - } - - public function getApplicationTransactionHasChangeDetails( - PhabricatorApplicationTransaction $xaction) { - return true; - } - - public function getApplicationTransactionChangeDetails( - PhabricatorApplicationTransaction $xaction, - PhabricatorUser $viewer) { - return $xaction->renderTextCorpusChangeDetails( - $viewer, - $xaction->getOldValue(), - $xaction->getNewValue()); - } - - public function shouldHideInApplicationTransactions( - PhabricatorApplicationTransaction $xaction) { - return ($xaction->getOldValue() === null); - } - public function shouldAppearInGlobalSearch() { return true; } @@ -125,23 +58,6 @@ final class DifferentialSummaryField return new PHUIRemarkupView($this->getViewer(), $this->getValue()); } - public function getApplicationTransactionRemarkupBlocks( - PhabricatorApplicationTransaction $xaction) { - return array($xaction->getNewValue()); - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - public function shouldAppearInTransactionMail() { return true; } diff --git a/src/applications/differential/customfield/DifferentialTestPlanField.php b/src/applications/differential/customfield/DifferentialTestPlanField.php index 6a1029dba4..c774e81a08 100644 --- a/src/applications/differential/customfield/DifferentialTestPlanField.php +++ b/src/applications/differential/customfield/DifferentialTestPlanField.php @@ -7,10 +7,6 @@ final class DifferentialTestPlanField return 'differential:test-plan'; } - public function getFieldKeyForConduit() { - return 'testPlan'; - } - public function getFieldName() { return pht('Test Plan'); } @@ -27,83 +23,10 @@ final class DifferentialTestPlanField return $revision->getTestPlan(); } - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setTestPlan($value); - } - - protected function isCoreFieldRequired() { - return PhabricatorEnv::getEnvConfig('differential.require-test-plan-field'); - } - public function canDisableField() { return true; } - protected function getCoreFieldRequiredErrorString() { - return pht( - 'You must provide a test plan. Describe the actions you performed '. - 'to verify the behavior of this change.'); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new PhabricatorRemarkupControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the test plan for this revision.', - $xaction->renderHandleLink($author_phid)); - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the test plan for %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid)); - } - - public function getApplicationTransactionHasChangeDetails( - PhabricatorApplicationTransaction $xaction) { - return true; - } - - public function getApplicationTransactionChangeDetails( - PhabricatorApplicationTransaction $xaction, - PhabricatorUser $viewer) { - return $xaction->renderTextCorpusChangeDetails( - $viewer, - $xaction->getOldValue(), - $xaction->getNewValue()); - } - - public function shouldHideInApplicationTransactions( - PhabricatorApplicationTransaction $xaction) { - return ($xaction->getOldValue() === null); - } - public function shouldAppearInGlobalSearch() { return true; } @@ -139,39 +62,6 @@ final class DifferentialTestPlanField return new PHUIRemarkupView($this->getViewer(), $this->getValue()); } - public function getApplicationTransactionRemarkupBlocks( - PhabricatorApplicationTransaction $xaction) { - return array($xaction->getNewValue()); - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Test Plan', - 'Testplan', - 'Tested', - 'Tests', - ); - } - - public function validateCommitMessageValue($value) { - if (!strlen($value) && $this->isCoreFieldRequired()) { - throw new DifferentialFieldValidationException( - $this->getCoreFieldRequiredErrorString()); - } - } - public function shouldAppearInTransactionMail() { return true; } diff --git a/src/applications/differential/customfield/DifferentialTitleField.php b/src/applications/differential/customfield/DifferentialTitleField.php deleted file mode 100644 index 82d6ddc1f3..0000000000 --- a/src/applications/differential/customfield/DifferentialTitleField.php +++ /dev/null @@ -1,125 +0,0 @@ ->'); - } - - protected function readValueFromRevision( - DifferentialRevision $revision) { - return $revision->getTitle(); - } - - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setTitle($value); - } - - protected function getCoreFieldRequiredErrorString() { - return pht('You must choose a title for this revision.'); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - protected function isCoreFieldRequired() { - return true; - } - - public function renderEditControl(array $handles) { - return id(new AphrontFormTextAreaControl()) - ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if (strlen($old)) { - return pht( - '%s retitled this revision from "%s" to "%s".', - $xaction->renderHandleLink($author_phid), - $old, - $new); - } else { - return pht( - '%s created this revision.', - $xaction->renderHandleLink($author_phid)); - } - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if (strlen($old)) { - return pht( - '%s retitled %s, from "%s" to "%s".', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $old, - $new); - } else { - return pht( - '%s created %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid)); - } - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function validateCommitMessageValue($value) { - if (!strlen($value)) { - throw new DifferentialFieldValidationException( - pht( - 'You must provide a revision title in the first line '. - 'of your commit message.')); - } - - if (preg_match('/^<<.*>>$/', $value)) { - throw new DifferentialFieldValidationException( - pht( - 'Replace the line "%s" with a human-readable revision title which '. - 'describes the changes you are making.', - self::getDefaultTitle())); - } - } - -} diff --git a/src/applications/differential/customfield/DifferentialViewPolicyField.php b/src/applications/differential/customfield/DifferentialViewPolicyField.php deleted file mode 100644 index 9b17413fcf..0000000000 --- a/src/applications/differential/customfield/DifferentialViewPolicyField.php +++ /dev/null @@ -1,50 +0,0 @@ -getViewPolicy(); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - $viewer = $this->getViewer(); - $revision = $this->getObject(); - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($revision) - ->execute(); - - return id(new AphrontFormPolicyControl()) - ->setUser($viewer) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicyObject($revision) - ->setPolicies($policies) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_VIEW_POLICY; - } - -} diff --git a/src/applications/differential/editor/DifferentialRevisionEditEngine.php b/src/applications/differential/editor/DifferentialRevisionEditEngine.php new file mode 100644 index 0000000000..8e15238661 --- /dev/null +++ b/src/applications/differential/editor/DifferentialRevisionEditEngine.php @@ -0,0 +1,222 @@ +getViewer(); + return DifferentialRevision::initializeNewRevision($viewer); + } + + protected function newObjectQuery() { + return id(new DifferentialRevisionQuery()) + ->needActiveDiffs(true) + ->needReviewerStatus(true); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Revision'); + } + + protected function getObjectEditTitleText($object) { + $monogram = $object->getMonogram(); + $title = $object->getTitle(); + + $diff = $this->getDiff(); + if ($diff) { + return pht('Update Revision %s: %s', $monogram, $title); + } else { + return pht('Edit Revision %s: %s', $monogram, $title); + } + } + + protected function getObjectEditShortText($object) { + return $object->getMonogram(); + } + + protected function getObjectCreateShortText() { + return pht('Create Revision'); + } + + protected function getObjectName() { + return pht('Revision'); + } + + protected function getObjectViewURI($object) { + return $object->getURI(); + } + + public function setDiff(DifferentialDiff $diff) { + $this->diff = $diff; + return $this; + } + + public function getDiff() { + return $this->diff; + } + + protected function buildCustomEditFields($object) { + + $plan_required = PhabricatorEnv::getEnvConfig( + 'differential.require-test-plan-field'); + $plan_enabled = $this->isCustomFieldEnabled( + $object, + 'differential:test-plan'); + + $diff = $this->getDiff(); + if ($diff) { + $diff_phid = $diff->getPHID(); + } else { + $diff_phid = null; + } + + $is_create = $this->getIsCreate(); + $is_update = ($diff && !$is_create); + + $fields = array(); + + $fields[] = id(new PhabricatorHandlesEditField()) + ->setKey(self::KEY_UPDATE) + ->setLabel(pht('Update Diff')) + ->setDescription(pht('New diff to create or update the revision with.')) + ->setConduitDescription(pht('Create or update a revision with a diff.')) + ->setConduitTypeDescription(pht('PHID of the diff.')) + ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) + ->setHandleParameterType(new AphrontPHIDListHTTPParameterType()) + ->setSingleValue($diff_phid) + ->setIsConduitOnly(!$diff) + ->setIsReorderable(false) + ->setIsDefaultable(false) + ->setIsInvisible(true) + ->setIsLockable(false); + + if ($is_update) { + $fields[] = id(new PhabricatorInstructionsEditField()) + ->setKey('update.help') + ->setValue(pht('Describe the updates you have made to the diff.')); + $fields[] = id(new PhabricatorCommentEditField()) + ->setKey('update.comment') + ->setLabel(pht('Comment')) + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) + ->setIsWebOnly(true) + ->setDescription(pht('Comments providing context for the update.')); + $fields[] = id(new PhabricatorSubmitEditField()) + ->setKey('update.submit') + ->setValue($this->getObjectEditButtonText($object)); + $fields[] = id(new PhabricatorDividerEditField()) + ->setKey('update.note'); + } + + $fields[] = id(new PhabricatorTextEditField()) + ->setKey(DifferentialRevisionTitleTransaction::EDITKEY) + ->setLabel(pht('Title')) + ->setIsRequired(true) + ->setTransactionType( + DifferentialRevisionTitleTransaction::TRANSACTIONTYPE) + ->setDescription(pht('The title of the revision.')) + ->setConduitDescription(pht('Retitle the revision.')) + ->setConduitTypeDescription(pht('New revision title.')) + ->setValue($object->getTitle()); + + $fields[] = id(new PhabricatorRemarkupEditField()) + ->setKey(DifferentialRevisionSummaryTransaction::EDITKEY) + ->setLabel(pht('Summary')) + ->setTransactionType( + DifferentialRevisionSummaryTransaction::TRANSACTIONTYPE) + ->setDescription(pht('The summary of the revision.')) + ->setConduitDescription(pht('Change the revision summary.')) + ->setConduitTypeDescription(pht('New revision summary.')) + ->setValue($object->getSummary()); + + if ($plan_enabled) { + $fields[] = id(new PhabricatorRemarkupEditField()) + ->setKey(DifferentialRevisionTestPlanTransaction::EDITKEY) + ->setLabel(pht('Test Plan')) + ->setIsRequired($plan_required) + ->setTransactionType( + DifferentialRevisionTestPlanTransaction::TRANSACTIONTYPE) + ->setDescription( + pht('Actions performed to verify the behavior of the change.')) + ->setConduitDescription(pht('Update the revision test plan.')) + ->setConduitTypeDescription(pht('New test plan.')) + ->setValue($object->getTestPlan()); + } + + $fields[] = id(new PhabricatorDatasourceEditField()) + ->setKey(DifferentialRevisionReviewersTransaction::EDITKEY) + ->setLabel(pht('Reviewers')) + ->setDatasource(new DifferentialReviewerDatasource()) + ->setUseEdgeTransactions(true) + ->setTransactionType( + DifferentialRevisionReviewersTransaction::TRANSACTIONTYPE) + ->setDescription(pht('Reviewers for this revision.')) + ->setConduitDescription(pht('Change the reviewers for this revision.')) + ->setConduitTypeDescription(pht('New reviewers.')) + ->setValue($object->getReviewerPHIDsForEdit()); + + $fields[] = id(new PhabricatorDatasourceEditField()) + ->setKey('repositoryPHID') + ->setLabel(pht('Repository')) + ->setDatasource(new DiffusionRepositoryDatasource()) + ->setTransactionType( + DifferentialRevisionRepositoryTransaction::TRANSACTIONTYPE) + ->setDescription(pht('The repository the revision belongs to.')) + ->setConduitDescription(pht('Change the repository for this revision.')) + ->setConduitTypeDescription(pht('New repository.')) + ->setSingleValue($object->getRepositoryPHID()); + + // This is a little flimsy, but allows "Maniphest Tasks: ..." to continue + // working properly in commit messages until we fully sort out T5873. + $fields[] = id(new PhabricatorHandlesEditField()) + ->setKey('tasks') + ->setUseEdgeTransactions(true) + ->setIsConduitOnly(true) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue( + 'edge:type', + DifferentialRevisionHasTaskEdgeType::EDGECONST) + ->setDescription(pht('Tasks associated with this revision.')) + ->setConduitDescription(pht('Change associated tasks.')) + ->setConduitTypeDescription(pht('List of tasks.')) + ->setValue(array()); + + return $fields; + } + + private function isCustomFieldEnabled(DifferentialRevision $revision, $key) { + $field_list = PhabricatorCustomField::getObjectFields( + $revision, + PhabricatorCustomField::ROLE_VIEW); + + $fields = $field_list->getFields(); + return isset($fields[$key]); + } + +} diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php index b4828494c0..f1bed835d9 100644 --- a/src/applications/differential/editor/DifferentialTransactionEditor.php +++ b/src/applications/differential/editor/DifferentialTransactionEditor.php @@ -474,7 +474,7 @@ final class DifferentialTransactionEditor $owner_phid = $object->getAuthorPHID(); if ($owner_phid) { - $reviewer = new DifferentialReviewer( + $reviewer = new DifferentialReviewerProxy( $owner_phid, array( 'status' => DifferentialReviewerStatus::STATUS_ADDED, diff --git a/src/applications/differential/field/DifferentialAuditorsCommitMessageField.php b/src/applications/differential/field/DifferentialAuditorsCommitMessageField.php new file mode 100644 index 0000000000..94f629e557 --- /dev/null +++ b/src/applications/differential/field/DifferentialAuditorsCommitMessageField.php @@ -0,0 +1,45 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + )); + } + + public function getCustomFieldKey() { + return 'phabricator:auditors'; + } + + public function isFieldEditable() { + return true; + } + + public function isTemplateField() { + return false; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + protected function readFieldValueFromCustomFieldStorage($value) { + return $this->readJSONFieldValueFromCustomFieldStorage($value, array()); + } + +} diff --git a/src/applications/differential/field/DifferentialBlameRevisionCommitMessageField.php b/src/applications/differential/field/DifferentialBlameRevisionCommitMessageField.php new file mode 100644 index 0000000000..feb17b16c9 --- /dev/null +++ b/src/applications/differential/field/DifferentialBlameRevisionCommitMessageField.php @@ -0,0 +1,22 @@ +getCustomFieldKey(); + return 100000 + $this->getCustomFieldOrder($custom_key); + } + + public function isFieldEnabled() { + $custom_key = $this->getCustomFieldKey(); + return $this->isCustomFieldEnabled($custom_key); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + $custom_key = $this->getCustomFieldKey(); + $value = $this->readCustomFieldValue($revision, $custom_key); + return $value; + } + + protected function readFieldValueFromCustomFieldStorage($value) { + return $value; + } + + protected function readJSONFieldValueFromCustomFieldStorage( + $value, + $default) { + try { + return phutil_json_decode($value); + } catch (PhutilJSONParserException $ex) { + return $default; + } + } + + protected function readCustomFieldValue( + DifferentialRevision $revision, + $key) { + $value = idx($this->getCustomFieldStorage(), $key); + return $this->readFieldValueFromCustomFieldStorage($value); + } + + protected function getCustomFieldOrder($key) { + $field_list = PhabricatorCustomField::getObjectFields( + new DifferentialRevision(), + DifferentialCustomField::ROLE_COMMITMESSAGE); + + $fields = $field_list->getFields(); + + $idx = 0; + foreach ($fields as $field_key => $value) { + if ($key === $field_key) { + return $idx; + } + $idx++; + } + + return $idx; + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => $this->getCommitMessageFieldKey(), + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialCommitMessageField.php b/src/applications/differential/field/DifferentialCommitMessageField.php new file mode 100644 index 0000000000..ebe10bcf88 --- /dev/null +++ b/src/applications/differential/field/DifferentialCommitMessageField.php @@ -0,0 +1,191 @@ +viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + final public function setCustomFieldStorage(array $custom_field_storage) { + $this->customFieldStorage = $custom_field_storage; + return $this; + } + + final public function getCustomFieldStorage() { + return $this->customFieldStorage; + } + + abstract public function getFieldName(); + abstract public function getFieldOrder(); + + public function isFieldEnabled() { + return true; + } + + public function getFieldAliases() { + return array(); + } + + public function validateFieldValue($value) { + return; + } + + public function parseFieldValue($value) { + return $value; + } + + public function isFieldEditable() { + return true; + } + + public function isTemplateField() { + return true; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringFieldValueFromConduit($value); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + return null; + } + + public function renderFieldValue($value) { + if (!strlen($value)) { + return null; + } + + return $value; + } + + public function getFieldTransactions($value) { + if (!$this->isFieldEditable()) { + return array(); + } + throw new PhutilMethodNotImplementedException(); + } + + final public function getCommitMessageFieldKey() { + return $this->getPhobjectClassConstant('FIELDKEY', 64); + } + + final public static function newEnabledFields(PhabricatorUser $viewer) { + $fields = self::getAllFields(); + + $results = array(); + foreach ($fields as $key => $field) { + $field = clone $field; + $field->setViewer($viewer); + if ($field->isFieldEnabled()) { + $results[$key] = $field; + } + } + + return $results; + } + + final public static function getAllFields() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getCommitMessageFieldKey') + ->setSortMethod('getFieldOrder') + ->execute(); + } + + protected function raiseParseException($message) { + throw new DifferentialFieldParseException($message); + } + + protected function raiseValidationException($message) { + throw new DifferentialFieldValidationException($message); + } + + protected function parseObjectList( + $value, + array $types, + $allow_partial = false, + array $suffixes = array()) { + return id(new PhabricatorObjectListQuery()) + ->setViewer($this->getViewer()) + ->setAllowedTypes($types) + ->setObjectList($value) + ->setAllowPartialResults($allow_partial) + ->setSuffixes($suffixes) + ->execute(); + } + + protected function renderHandleList(array $phids, array $suffixes = array()) { + if (!$phids) { + return null; + } + + $handles = $this->getViewer()->loadHandles($phids); + + $out = array(); + foreach ($handles as $handle) { + $phid = $handle->getPHID(); + + if ($handle->getPolicyFiltered()) { + $token = $phid; + } else if ($handle->isComplete()) { + $token = $handle->getCommandLineObjectName(); + } + + $suffix = idx($suffixes, $phid); + $token = $token.$suffix; + + $out[] = $token; + } + + return implode(', ', $out); + } + + protected function readStringFieldValueFromConduit($value) { + if ($value === null) { + return $value; + } + + if (!is_string($value)) { + throw new Exception( + pht( + 'Field "%s" expects a string value, but received a value of type '. + '"%s".', + $this->getCommitMessageFieldKey(), + gettype($value))); + } + + return $value; + } + + protected function readStringListFieldValueFromConduit($value) { + if (!is_array($value)) { + throw new Exception( + pht( + 'Field "%s" expects a list of strings, but received a value of type '. + '"%s".', + $this->getCommitMessageFieldKey(), + gettype($value))); + } + + return $value; + } + + protected function isCustomFieldEnabled($key) { + $field_list = PhabricatorCustomField::getObjectFields( + new DifferentialRevision(), + DifferentialCustomField::ROLE_DEFAULT); + + $fields = $field_list->getFields(); + return isset($fields[$key]); + } + +} diff --git a/src/applications/differential/field/DifferentialConflictsCommitMessageField.php b/src/applications/differential/field/DifferentialConflictsCommitMessageField.php new file mode 100644 index 0000000000..5a4c281157 --- /dev/null +++ b/src/applications/differential/field/DifferentialConflictsCommitMessageField.php @@ -0,0 +1,24 @@ +readJSONFieldValueFromCustomFieldStorage($value, array()); + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + if (!$value) { + return null; + } + + return implode(', ', $value); + } + +} diff --git a/src/applications/differential/field/DifferentialRevertPlanCommitMessageField.php b/src/applications/differential/field/DifferentialRevertPlanCommitMessageField.php new file mode 100644 index 0000000000..0a813130f9 --- /dev/null +++ b/src/applications/differential/field/DifferentialRevertPlanCommitMessageField.php @@ -0,0 +1,16 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + ), + $allow_partial = true); + } + + public function isFieldEditable() { + return false; + } + + public function isTemplateField() { + return false; + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $phids = array(); + foreach ($revision->getReviewerStatus() as $reviewer) { + switch ($reviewer->getStatus()) { + case DifferentialReviewerStatus::STATUS_ACCEPTED: + case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER: + $phids[] = $reviewer->getReviewerPHID(); + break; + } + } + + return $phids; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + +} diff --git a/src/applications/differential/field/DifferentialReviewersCommitMessageField.php b/src/applications/differential/field/DifferentialReviewersCommitMessageField.php new file mode 100644 index 0000000000..0f110b6e3a --- /dev/null +++ b/src/applications/differential/field/DifferentialReviewersCommitMessageField.php @@ -0,0 +1,136 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + PhabricatorOwnersPackagePHIDType::TYPECONST, + ), + false, + array('!')); + + return $this->flattenReviewers($results); + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + + $results = array(); + foreach ($revision->getReviewerStatus() as $reviewer) { + if ($reviewer->getStatus() == $status_blocking) { + $suffixes = array('!' => '!'); + } else { + $suffixes = array(); + } + + $results[] = array( + 'phid' => $reviewer->getReviewerPHID(), + 'suffixes' => $suffixes, + ); + } + + return $this->flattenReviewers($results); + } + + public function renderFieldValue($value) { + $value = $this->inflateReviewers($value); + + $phid_list = array(); + $suffix_map = array(); + foreach ($value as $reviewer) { + $phid = $reviewer['phid']; + $phid_list[] = $phid; + if (isset($reviewer['suffixes']['!'])) { + $suffix_map[$phid] = '!'; + } + } + + return $this->renderHandleList($phid_list, $suffix_map); + } + + public function getFieldTransactions($value) { + $value = $this->inflateReviewers($value); + + $reviewer_list = array(); + foreach ($value as $reviewer) { + $phid = $reviewer['phid']; + if (isset($reviewer['suffixes']['!'])) { + $reviewer_list[] = 'blocking('.$phid.')'; + } else { + $reviewer_list[] = $phid; + } + } + + $xaction_key = DifferentialRevisionReviewersTransaction::EDITKEY; + $xaction_type = "{$xaction_key}.set"; + + return array( + array( + 'type' => $xaction_type, + 'value' => $reviewer_list, + ), + ); + } + + private function flattenReviewers(array $values) { + // NOTE: For now, `arc` relies on this field returning only scalars, so we + // need to reduce the results into scalars. See T10981. + $result = array(); + + foreach ($values as $value) { + $result[] = $value['phid'].implode('', array_keys($value['suffixes'])); + } + + return $result; + } + + private function inflateReviewers(array $values) { + $result = array(); + + foreach ($values as $value) { + if (substr($value, -1) == '!') { + $value = substr($value, 0, -1); + $suffixes = array('!' => '!'); + } else { + $suffixes = array(); + } + + $result[] = array( + 'phid' => $value, + 'suffixes' => $suffixes, + ); + } + + return $result; + } + +} diff --git a/src/applications/differential/customfield/DifferentialRevisionIDField.php b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php similarity index 60% rename from src/applications/differential/customfield/DifferentialRevisionIDField.php rename to src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php index 9d23cf7658..1c4a2c9d60 100644 --- a/src/applications/differential/customfield/DifferentialRevisionIDField.php +++ b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php @@ -1,36 +1,23 @@ revisionID, $this->getObject()->getID()); - if (!$id) { - return null; - } - return PhabricatorEnv::getProductionURI('/D'.$id); - } - - public function readValueFromCommitMessage($value) { - $this->revisionID = $value; - } - private static function parseRevisionIDFromURI($uri_string) { $uri = new PhutilURI($uri_string); $path = $uri->getPath(); @@ -82,4 +57,27 @@ final class DifferentialRevisionIDField return null; } + public function readFieldValueFromObject(DifferentialRevision $revision) { + return $revision->getID(); + } + + public function readFieldValueFromConduit($value) { + if (is_int($value)) { + $value = (string)$value; + } + return $this->readStringFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + if (!strlen($value)) { + return null; + } + + return PhabricatorEnv::getProductionURI('/D'.$value); + } + + public function getFieldTransactions($value) { + return array(); + } + } diff --git a/src/applications/differential/field/DifferentialSubscribersCommitMessageField.php b/src/applications/differential/field/DifferentialSubscribersCommitMessageField.php new file mode 100644 index 0000000000..12d36e4381 --- /dev/null +++ b/src/applications/differential/field/DifferentialSubscribersCommitMessageField.php @@ -0,0 +1,60 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + PhabricatorOwnersPackagePHIDType::TYPECONST, + )); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + return PhabricatorSubscribersQuery::loadSubscribersForPHID( + $revision->getPHID()); + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => PhabricatorSubscriptionsEditEngineExtension::EDITKEY_SET, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialSummaryCommitMessageField.php b/src/applications/differential/field/DifferentialSummaryCommitMessageField.php new file mode 100644 index 0000000000..6b57942470 --- /dev/null +++ b/src/applications/differential/field/DifferentialSummaryCommitMessageField.php @@ -0,0 +1,29 @@ +getSummary(); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => DifferentialRevisionSummaryTransaction::EDITKEY, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialTagsCommitMessageField.php b/src/applications/differential/field/DifferentialTagsCommitMessageField.php new file mode 100644 index 0000000000..fc6267f1ce --- /dev/null +++ b/src/applications/differential/field/DifferentialTagsCommitMessageField.php @@ -0,0 +1,66 @@ +parseObjectList( + $value, + array( + PhabricatorProjectProjectPHIDType::TYPECONST, + )); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $projects = PhabricatorEdgeQuery::loadDestinationPHIDs( + $revision->getPHID(), + PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); + $projects = array_reverse($projects); + + return $projects; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => PhabricatorProjectsEditEngineExtension::EDITKEY_SET, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialTasksCommitMessageField.php b/src/applications/differential/field/DifferentialTasksCommitMessageField.php new file mode 100644 index 0000000000..eea0afef8d --- /dev/null +++ b/src/applications/differential/field/DifferentialTasksCommitMessageField.php @@ -0,0 +1,65 @@ +parseObjectList( + $value, + array( + ManiphestTaskPHIDType::TYPECONST, + )); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $projects = PhabricatorEdgeQuery::loadDestinationPHIDs( + $revision->getPHID(), + DifferentialRevisionHasTaskEdgeType::EDGECONST); + $projects = array_reverse($projects); + + return $projects; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => 'tasks.set', + 'value' => $value, + ), + ); + } +} diff --git a/src/applications/differential/field/DifferentialTestPlanCommitMessageField.php b/src/applications/differential/field/DifferentialTestPlanCommitMessageField.php new file mode 100644 index 0000000000..a477a9036e --- /dev/null +++ b/src/applications/differential/field/DifferentialTestPlanCommitMessageField.php @@ -0,0 +1,53 @@ +isCustomFieldEnabled('differential:test-plan'); + } + + public function validateFieldValue($value) { + $is_required = PhabricatorEnv::getEnvConfig( + 'differential.require-test-plan-field'); + + if ($is_required && !strlen($value)) { + $this->raiseValidationException( + pht( + 'You must provide a test plan. Describe the actions you performed '. + 'to verify the behavior of this change.')); + } + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + return $revision->getTestPlan(); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => DifferentialRevisionTestPlanTransaction::EDITKEY, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialTitleCommitMessageField.php b/src/applications/differential/field/DifferentialTitleCommitMessageField.php new file mode 100644 index 0000000000..6b39796f3a --- /dev/null +++ b/src/applications/differential/field/DifferentialTitleCommitMessageField.php @@ -0,0 +1,59 @@ +'); + } + + public function parseFieldValue($value) { + if ($value === self::getDefaultTitle()) { + $this->raiseParseException( + pht( + 'Replace the default title line with a human-readable revision '. + 'title which describes the changes you are making.')); + } + + return parent::parseFieldValue($value); + } + + public function validateFieldValue($value) { + if (!strlen($value)) { + $this->raiseValidationException( + pht( + 'You must provide a revision title in the first line '. + 'of your commit message.')); + } + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + $value = $revision->getTitle(); + + if (!strlen($value)) { + return self::getDefaultTitle(); + } + + return $value; + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => DifferentialRevisionTitleTransaction::EDITKEY, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php b/src/applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php deleted file mode 100644 index 90c0be1717..0000000000 --- a/src/applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php +++ /dev/null @@ -1,60 +0,0 @@ -setName('migrate') - ->setExamples('**migrate**') - ->setSynopsis(pht('Migrate hunks to modern storage.')) - ->setArguments(array()); - } - - public function execute(PhutilArgumentParser $args) { - $saw_any_rows = false; - $console = PhutilConsole::getConsole(); - - $table = new DifferentialLegacyHunk(); - foreach (new LiskMigrationIterator($table) as $hunk) { - $saw_any_rows = true; - - $id = $hunk->getID(); - $console->writeOut("%s\n", pht('Migrating hunk %d...', $id)); - - $new_hunk = id(new DifferentialModernHunk()) - ->setChangesetID($hunk->getChangesetID()) - ->setOldOffset($hunk->getOldOffset()) - ->setOldLen($hunk->getOldLen()) - ->setNewOffset($hunk->getNewOffset()) - ->setNewLen($hunk->getNewLen()) - ->setChanges($hunk->getChanges()) - ->setDateCreated($hunk->getDateCreated()) - ->setDateModified($hunk->getDateModified()); - - $hunk->openTransaction(); - $new_hunk->save(); - $hunk->delete(); - $hunk->saveTransaction(); - - $old_len = strlen($hunk->getChanges()); - $new_len = strlen($new_hunk->getData()); - if ($old_len) { - $diff_len = ($old_len - $new_len); - $console->writeOut( - "%s\n", - pht( - 'Saved %s bytes (%s).', - new PhutilNumber($diff_len), - sprintf('%.1f%%', 100 * ($diff_len / $old_len)))); - } - } - - if ($saw_any_rows) { - $console->writeOut("%s\n", pht('Done.')); - } else { - $console->writeOut("%s\n", pht('No rows to migrate.')); - } - } - -} diff --git a/src/applications/differential/management/PhabricatorHunksManagementWorkflow.php b/src/applications/differential/management/PhabricatorHunksManagementWorkflow.php deleted file mode 100644 index a56a5f88e7..0000000000 --- a/src/applications/differential/management/PhabricatorHunksManagementWorkflow.php +++ /dev/null @@ -1,4 +0,0 @@ -getFieldKeyForConduit(); - $key_summary = id(new DifferentialSummaryField())->getFieldKeyForConduit(); - - $field_list = PhabricatorCustomField::getObjectFields( - new DifferentialRevision(), - DifferentialCustomField::ROLE_COMMITMESSAGE); - $field_list->setViewer($viewer); - - $label_map = array(); - - foreach ($field_list->getFields() as $field) { - $labels = $field->getCommitMessageLabels(); - $key = $field->getFieldKeyForConduit(); - - foreach ($labels as $label) { - $normal_label = self::normalizeFieldLabel( - $label); - if (!empty($label_map[$normal_label])) { - throw new Exception( - pht( - 'Field label "%s" is parsed by two custom fields: "%s" and '. - '"%s". Each label must be parsed by only one field.', - $label, - $key, - $label_map[$normal_label])); - } - $label_map[$normal_label] = $key; - } - } + $field_list = DifferentialCommitMessageField::newEnabledFields($viewer); return id(new self()) - ->setLabelMap($label_map) + ->setViewer($viewer) + ->setCommitMessageFields($field_list) ->setTitleKey($key_title) ->setSummaryKey($key_summary); } @@ -69,6 +46,59 @@ final class DifferentialCommitMessageParser extends Phobject { /* -( Configuring the Parser )--------------------------------------------- */ + /** + * @task config + */ + public function setViewer(PhabricatorUser $viewer) { + $this->viewer = $viewer; + return $this; + } + + + /** + * @task config + */ + public function getViewer() { + return $this->viewer; + } + + + /** + * @task config + */ + public function setCommitMessageFields($fields) { + assert_instances_of($fields, 'DifferentialCommitMessageField'); + $fields = mpull($fields, null, 'getCommitMessageFieldKey'); + $this->commitMessageFields = $fields; + return $this; + } + + + /** + * @task config + */ + public function getCommitMessageFields() { + return $this->commitMessageFields; + } + + + /** + * @task config + */ + public function setRaiseMissingFieldErrors($raise) { + $this->raiseMissingFieldErrors = $raise; + return $this; + } + + + /** + * @task config + */ + public function getRaiseMissingFieldErrors() { + return $this->raiseMissingFieldErrors; + } + + /** * @task config */ @@ -105,7 +135,7 @@ final class DifferentialCommitMessageParser extends Phobject { public function parseCorpus($corpus) { $this->errors = array(); - $label_map = $this->labelMap; + $label_map = $this->getLabelMap(); $key_title = $this->titleKey; $key_summary = $this->summaryKey; @@ -215,6 +245,57 @@ final class DifferentialCommitMessageParser extends Phobject { } + /** + * @task parse + */ + public function parseFields($corpus) { + $viewer = $this->getViewer(); + $text_map = $this->parseCorpus($corpus); + + $field_map = $this->getCommitMessageFields(); + + $result_map = array(); + foreach ($text_map as $field_key => $text_value) { + $field = idx($field_map, $field_key); + if (!$field) { + // This is a strict error, since we only parse fields which we have + // been told are valid. The caller probably handed us an invalid label + // map. + throw new Exception( + pht( + 'Parser emitted a field with key "%s", but no corresponding '. + 'field definition exists.', + $field_key)); + } + + try { + $result = $field->parseFieldValue($text_value); + $result_map[$field_key] = $result; + } catch (DifferentialFieldParseException $ex) { + $this->errors[] = pht( + 'Error parsing field "%s": %s', + $field->getFieldName(), + $ex->getMessage()); + } + } + + if ($this->getRaiseMissingFieldErrors()) { + foreach ($field_map as $key => $field) { + try { + $field->validateFieldValue(idx($result_map, $key)); + } catch (DifferentialFieldValidationException $ex) { + $this->errors[] = pht( + 'Invalid or missing field "%s": %s', + $field->getFieldName(), + $ex->getMessage()); + } + } + } + + return $result_map; + } + + /** * @task parse */ @@ -237,6 +318,38 @@ final class DifferentialCommitMessageParser extends Phobject { /* -( Internals )---------------------------------------------------------- */ + private function getLabelMap() { + if ($this->labelMap === null) { + $field_list = $this->getCommitMessageFields(); + + $label_map = array(); + foreach ($field_list as $field_key => $field) { + $labels = $field->getFieldAliases(); + $labels[] = $field->getFieldName(); + + foreach ($labels as $label) { + $normal_label = self::normalizeFieldLabel($label); + if (!empty($label_map[$normal_label])) { + throw new Exception( + pht( + 'Field label "%s" is parsed by two custom fields: "%s" and '. + '"%s". Each label must be parsed by only one field.', + $label, + $field_key, + $label_map[$normal_label])); + } + + $label_map[$normal_label] = $field_key; + } + } + + $this->labelMap = $label_map; + } + + return $this->labelMap; + } + + /** * @task internal */ diff --git a/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php b/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php index 669cfed220..320445fd0d 100644 --- a/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php +++ b/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php @@ -41,6 +41,36 @@ final class DifferentialCommitMessageParserTestCase } } + + public function testDifferentialCommitMessageFieldParser() { + $message = << + 'This is the title.', + DifferentialSummaryCommitMessageField::FIELDKEY => + 'This is the summary.', + ); + + $parser = id(new DifferentialCommitMessageParser()) + ->setCommitMessageFields($fields) + ->setTitleKey(DifferentialTitleCommitMessageField::FIELDKEY) + ->setSummaryKey(DifferentialSummaryCommitMessageField::FIELDKEY); + + $actual = $parser->parseFields($message); + + $this->assertEqual($expect, $actual); + } + public function testDifferentialCommitMessageParserNormalization() { $map = array( 'Test Plan' => 'test plan', diff --git a/src/applications/differential/query/DifferentialHunkQuery.php b/src/applications/differential/query/DifferentialHunkQuery.php index 09beb0b6f7..c8e35cb607 100644 --- a/src/applications/differential/query/DifferentialHunkQuery.php +++ b/src/applications/differential/query/DifferentialHunkQuery.php @@ -46,23 +46,9 @@ final class DifferentialHunkQuery $this->buildLimitClause($conn_r)); $modern_results = $table->loadAllFromArray($modern_data); - - // Now, load legacy hunks. - $table = new DifferentialLegacyHunk(); - $conn_r = $table->establishConnection('r'); - - $legacy_data = queryfx_all( - $conn_r, - 'SELECT * FROM %T %Q %Q %Q', - $table->getTableName(), - $this->buildWhereClause($conn_r), - $this->buildOrderClause($conn_r), - $this->buildLimitClause($conn_r)); - $legacy_results = $table->loadAllFromArray($legacy_data); - // Strip all the IDs off since they're not unique and nothing should be // using them. - return array_values(array_merge($legacy_results, $modern_results)); + return array_values($modern_results); } protected function willFilterPage(array $hunks) { diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php index f36a686eb5..6dd690d179 100644 --- a/src/applications/differential/query/DifferentialRevisionQuery.php +++ b/src/applications/differential/query/DifferentialRevisionQuery.php @@ -1008,7 +1008,9 @@ final class DifferentialRevisionQuery $revision_edges = $edges[$revision->getPHID()][$edge_type]; $reviewers = array(); foreach ($revision_edges as $reviewer_phid => $edge) { - $reviewer = new DifferentialReviewer($reviewer_phid, $edge['data']); + $reviewer = new DifferentialReviewerProxy( + $reviewer_phid, + $edge['data']); if ($this->needReviewerAuthority) { if (!$viewer_phid) { diff --git a/src/applications/differential/storage/DifferentialChangeset.php b/src/applications/differential/storage/DifferentialChangeset.php index 4d7b9f5698..448cdb6343 100644 --- a/src/applications/differential/storage/DifferentialChangeset.php +++ b/src/applications/differential/storage/DifferentialChangeset.php @@ -30,8 +30,8 @@ final class DifferentialChangeset extends DifferentialDAO 'awayPaths' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'oldFile' => 'text255?', - 'filename' => 'text255', + 'oldFile' => 'bytes?', + 'filename' => 'bytes', 'changeType' => 'uint32', 'fileType' => 'uint32', 'addLines' => 'uint32', @@ -98,13 +98,6 @@ final class DifferentialChangeset extends DifferentialDAO public function delete() { $this->openTransaction(); - $legacy_hunks = id(new DifferentialLegacyHunk())->loadAllWhere( - 'changesetID = %d', - $this->getID()); - foreach ($legacy_hunks as $legacy_hunk) { - $legacy_hunk->delete(); - } - $modern_hunks = id(new DifferentialModernHunk())->loadAllWhere( 'changesetID = %d', $this->getID()); diff --git a/src/applications/differential/storage/DifferentialReviewer.php b/src/applications/differential/storage/DifferentialReviewerProxy.php similarity index 96% rename from src/applications/differential/storage/DifferentialReviewer.php rename to src/applications/differential/storage/DifferentialReviewerProxy.php index 1ad7fbc8b0..bf38ee27e3 100644 --- a/src/applications/differential/storage/DifferentialReviewer.php +++ b/src/applications/differential/storage/DifferentialReviewerProxy.php @@ -1,6 +1,6 @@ setAuthorPHID($actor->getPHID()) ->attachRelationships(array()) ->attachRepository(null) + ->attachActiveDiff(null) + ->attachReviewerStatus(array()) ->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW); } @@ -403,12 +405,30 @@ final class DifferentialRevision extends DifferentialDAO } public function attachReviewerStatus(array $reviewers) { - assert_instances_of($reviewers, 'DifferentialReviewer'); + assert_instances_of($reviewers, 'DifferentialReviewerProxy'); $this->reviewerStatus = $reviewers; return $this; } + public function getReviewerPHIDsForEdit() { + $reviewers = $this->getReviewerStatus(); + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + + $value = array(); + foreach ($reviewers as $reviewer) { + $phid = $reviewer->getReviewerPHID(); + if ($reviewer->getStatus() == $status_blocking) { + $value[] = 'blocking('.$phid.')'; + } else { + $value[] = $phid; + } + } + + return $value; + } + public function getRepository() { return $this->assertAttached($this->repository); } diff --git a/src/applications/differential/storage/DifferentialTransaction.php b/src/applications/differential/storage/DifferentialTransaction.php index bc52227590..08c66c7fa5 100644 --- a/src/applications/differential/storage/DifferentialTransaction.php +++ b/src/applications/differential/storage/DifferentialTransaction.php @@ -1,6 +1,7 @@ getTransactionType(); + if ($xaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { + switch ($this->getMetadataValue('customfield:key')) { + case 'differential:title': + return new DifferentialRevisionTitleTransaction(); + case 'differential:test-plan': + return new DifferentialRevisionTestPlanTransaction(); + case 'differential:repository': + return new DifferentialRevisionRepositoryTransaction(); + } + } + + return parent::newFallbackModularTransactionType(); + } + public function setIsCommandeerSideEffect($is_side_effect) { $this->isCommandeerSideEffect = $is_side_effect; diff --git a/src/applications/differential/view/DifferentialReviewersView.php b/src/applications/differential/view/DifferentialReviewersView.php index b94e246d73..fd558d85f1 100644 --- a/src/applications/differential/view/DifferentialReviewersView.php +++ b/src/applications/differential/view/DifferentialReviewersView.php @@ -7,7 +7,7 @@ final class DifferentialReviewersView extends AphrontView { private $diff; public function setReviewers(array $reviewers) { - assert_instances_of($reviewers, 'DifferentialReviewer'); + assert_instances_of($reviewers, 'DifferentialReviewerProxy'); $this->reviewers = $reviewers; return $this; } diff --git a/src/applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php b/src/applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php new file mode 100644 index 0000000000..63c7f2c32d --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php @@ -0,0 +1,95 @@ +getRepositoryPHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setRepositoryPHID($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + if ($old && $new) { + return pht( + '%s changed the repository for this revision from %s to %s.', + $this->renderAuthor(), + $this->renderHandle($old), + $this->renderHandle($new)); + } else if ($new) { + return pht( + '%s set the repository for this revision to %s.', + $this->renderAuthor(), + $this->renderHandle($new)); + } else { + return pht( + '%s removed %s as the repository for this revision.', + $this->renderAuthor(), + $this->renderHandle($old)); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + if ($old && $new) { + return pht( + '%s changed the repository for %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderHandle($old), + $this->renderHandle($new)); + } else if ($new) { + return pht( + '%s set the repository for %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderHandle($new)); + } else { + return pht( + '%s removed %s as the repository for %s.', + $this->renderAuthor(), + $this->renderHandle($old), + $this->renderObject()); + } + } + + public function validateTransactions($object, array $xactions) { + $actor = $this->getActor(); + + $errors = array(); + + $old_value = $object->getRepositoryPHID(); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + if (!$new_value) { + continue; + } + + if ($new_value == $old_value) { + continue; + } + + $repository = id(new PhabricatorRepositoryQuery()) + ->setViewer($actor) + ->withPHIDs(array($new_value)) + ->executeOne(); + if (!$repository) { + $errors[] = $this->newInvalidError( + pht( + 'Repository "%s" is not a valid repository, or you do not have '. + 'permission to view it.'), + $xaction); + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionReviewersTransaction.php b/src/applications/differential/xaction/DifferentialRevisionReviewersTransaction.php new file mode 100644 index 0000000000..6ecf738162 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionReviewersTransaction.php @@ -0,0 +1,368 @@ +getReviewerStatus(); + $reviewers = mpull($reviewers, 'getStatus', 'getReviewerPHID'); + return $reviewers; + } + + public function generateNewValue($object, $value) { + $actor = $this->getActor(); + + $datasource = id(new DifferentialBlockingReviewerDatasource()) + ->setViewer($actor); + + $reviewers = $this->generateOldValue($object); + $old_reviewers = $reviewers; + + // First, remove any reviewers we're getting rid of. + $rem = idx($value, '-', array()); + $rem = $datasource->evaluateTokens($rem); + foreach ($rem as $phid) { + unset($reviewers[$phid]); + } + + $add = idx($value, '+', array()); + $add = $datasource->evaluateTokens($add); + $add_map = array(); + foreach ($add as $spec) { + if (!is_array($spec)) { + $phid = $spec; + $status = DifferentialReviewerStatus::STATUS_ADDED; + } else { + $phid = $spec['phid']; + $status = $spec['type']; + } + + $add_map[$phid] = $status; + } + + $set = idx($value, '=', null); + if ($set !== null) { + $set = $datasource->evaluateTokens($set); + foreach ($set as $spec) { + if (!is_array($spec)) { + $phid = $spec; + $status = DifferentialReviewerStatus::STATUS_ADDED; + } else { + $phid = $spec['phid']; + $status = $spec['type']; + } + + $add_map[$phid] = $status; + } + + // We treat setting reviewers as though they were being added to an + // empty list, so we can share more code between pathways. + $reviewers = array(); + } + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + foreach ($add_map as $phid => $new_status) { + $old_status = idx($old_reviewers, $phid); + + // If we have an old status and this didn't make the reviewer blocking + // or nonblocking, just retain the old status. This makes sure we don't + // throw away rejects, accepts, etc. + if ($old_status) { + $was_blocking = ($old_status == $status_blocking); + $now_blocking = ($new_status == $status_blocking); + + $is_block = ($now_blocking && !$was_blocking); + $is_unblock = (!$now_blocking && $was_blocking); + + if (!$is_block && !$is_unblock) { + $reviewers[$phid] = $old_status; + continue; + } + } + + $reviewers[$phid] = $new_status; + } + + return $reviewers; + } + + public function getTransactionHasEffect($object, $old, $new) { + // At least for now, we ignore transactions which ONLY reorder reviewers + // without making any actual changes. + ksort($old); + ksort($new); + return ($old !== $new); + } + + public function applyExternalEffects($object, $value) { + $src_phid = $object->getPHID(); + + $old = $this->generateOldValue($object); + $new = $value; + $edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST; + + $editor = new PhabricatorEdgeEditor(); + + $rem = array_diff_key($old, $new); + foreach ($rem as $dst_phid => $status) { + $editor->removeEdge($src_phid, $edge_type, $dst_phid); + } + + foreach ($new as $dst_phid => $status) { + $old_status = idx($old, $dst_phid); + if ($old_status === $status) { + continue; + } + + $data = array( + 'data' => array( + 'status' => $status, + + // TODO: This seemes like it's buggy before the Modular Transactions + // changes. Figure out what's going on here? We don't have a very + // clean way to get the active diff ID right now. + 'diffID' => null, + ), + ); + + $editor->addEdge($src_phid, $edge_type, $dst_phid, $data); + } + + $editor->save(); + } + + public function getTitle() { + return $this->renderReviewerEditTitle(false); + } + + public function getTitleForFeed() { + return $this->renderReviewerEditTitle(true); + } + + private function renderReviewerEditTitle($is_feed) { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + $rem = array_diff_key($old, $new); + $add = array_diff_key($new, $old); + $rem_phids = array_keys($rem); + $add_phids = array_keys($add); + $total_count = count($rem) + count($add); + + $parts = array(); + + if ($rem && $add) { + if ($is_feed) { + $parts[] = pht( + '%s edited %s reviewer(s) for %s, added %s: %s; removed %s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + $this->renderObject(), + phutil_count($add_phids), + $this->renderHandleList($add_phids), + phutil_count($rem_phids), + $this->renderHandleList($rem_phids)); + } else { + $parts[] = pht( + '%s edited %s reviewer(s), added %s: %s; removed %s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + phutil_count($add_phids), + $this->renderHandleList($add_phids), + phutil_count($rem_phids), + $this->renderHandleList($rem_phids)); + } + } else if ($add) { + if ($is_feed) { + $parts[] = pht( + '%s added %s reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($add_phids), + $this->renderObject(), + $this->renderHandleList($add_phids)); + } else { + $parts[] = pht( + '%s added %s reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($add_phids), + $this->renderHandleList($add_phids)); + } + } else if ($rem) { + if ($is_feed) { + $parts[] = pht( + '%s removed %s reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($rem_phids), + $this->renderObject(), + $this->renderHandleList($rem_phids)); + } else { + $parts[] = pht( + '%s removed %s reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($rem_phids), + $this->renderHandleList($rem_phids)); + } + } + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + $blocks = array(); + $unblocks = array(); + foreach ($new as $phid => $new_status) { + $old_status = idx($old, $phid); + if (!$old_status) { + continue; + } + + $was_blocking = ($old_status == $status_blocking); + $now_blocking = ($new_status == $status_blocking); + + $is_block = ($now_blocking && !$was_blocking); + $is_unblock = (!$now_blocking && $was_blocking); + + if ($is_block) { + $blocks[] = $phid; + } + if ($is_unblock) { + $unblocks[] = $phid; + } + } + + $total_count = count($blocks) + count($unblocks); + + if ($blocks && $unblocks) { + if ($is_feed) { + $parts[] = pht( + '%s changed %s blocking reviewer(s) for %s, added %s: %s; removed '. + '%s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + $this->renderObject(), + phutil_count($blocks), + $this->renderHandleList($blocks), + phutil_count($unblocks), + $this->renderHandleList($unblocks)); + } else { + $parts[] = pht( + '%s changed %s blocking reviewer(s), added %s: %s; removed %s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + phutil_count($blocks), + $this->renderHandleList($blocks), + phutil_count($unblocks), + $this->renderHandleList($unblocks)); + } + } else if ($blocks) { + if ($is_feed) { + $parts[] = pht( + '%s added %s blocking reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($blocks), + $this->renderObject(), + $this->renderHandleList($blocks)); + } else { + $parts[] = pht( + '%s added %s blocking reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($blocks), + $this->renderHandleList($blocks)); + } + } else if ($unblocks) { + if ($is_feed) { + $parts[] = pht( + '%s removed %s blocking reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($unblocks), + $this->renderObject(), + $this->renderHandleList($unblocks)); + } else { + $parts[] = pht( + '%s removed %s blocking reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($unblocks), + $this->renderHandleList($unblocks)); + } + } + + if ($this->isTextMode()) { + return implode(' ', $parts); + } else { + return phutil_implode_html(' ', $parts); + } + } + + public function validateTransactions($object, array $xactions) { + $actor = $this->getActor(); + $errors = array(); + + if (!$xactions) { + // If we aren't applying new reviewer transactions, just bail. We need + // reviewers to be attached to the revision continue validation, and + // they won't always be (for example, when mentioning a revision). + return $errors; + } + + $author_phid = $object->getAuthorPHID(); + $config_self_accept_key = 'differential.allow-self-accept'; + $allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key); + + $old = $this->generateOldValue($object); + foreach ($xactions as $xaction) { + $new = $this->generateNewValue($object, $xaction->getNewValue()); + + $add = array_diff_key($new, $old); + if (!$add) { + continue; + } + + $objects = id(new PhabricatorObjectQuery()) + ->setViewer($actor) + ->withPHIDs(array_keys($add)) + ->execute(); + $objects = mpull($objects, null, 'getPHID'); + + foreach ($add as $phid => $status) { + if (!isset($objects[$phid])) { + $errors[] = $this->newInvalidError( + pht( + 'Reviewer "%s" is not a valid object.', + $phid), + $xaction); + continue; + } + + switch (phid_get_type($phid)) { + case PhabricatorPeopleUserPHIDType::TYPECONST: + case PhabricatorOwnersPackagePHIDType::TYPECONST: + case PhabricatorProjectProjectPHIDType::TYPECONST: + break; + default: + $errors[] = $this->newInvalidError( + pht( + 'Reviewer "%s" must be a user, a package, or a project.', + $phid), + $xaction); + continue 2; + } + + // NOTE: This weird behavior around commandeering is a bit unorthodox, + // but this restriction is an unusual one. + + $is_self = ($phid === $author_phid); + if ($is_self && !$allow_self_accept) { + if (!$xaction->getIsCommandeerSideEffect()) { + $errors[] = $this->newInvalidError( + pht('The author of a revision can not be a reviewer.'), + $xaction); + continue; + } + } + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php new file mode 100644 index 0000000000..a4f1dcafa5 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php @@ -0,0 +1,57 @@ +getSummary(); + } + + public function applyInternalEffects($object, $value) { + $object->setSummary($value); + } + + public function getTitle() { + return pht( + '%s edited the summary of this revision.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the summary of %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO REVISION SUMMARY'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php new file mode 100644 index 0000000000..bf2beab3d8 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php @@ -0,0 +1,75 @@ +getTestPlan(); + } + + public function applyInternalEffects($object, $value) { + $object->setTestPlan($value); + } + + public function getTitle() { + return pht( + '%s edited the test plan for this revision.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the test plan for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO TEST PLAN'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $is_required = PhabricatorEnv::getEnvConfig( + 'differential.require-test-plan-field'); + + if ($is_required) { + if ($this->isEmptyTextTransaction($object->getTestPlan(), $xactions)) { + $errors[] = $this->newRequiredError( + pht( + 'You must provide a test plan. Describe the actions you '. + 'performed to verify the behavior of this change.')); + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php new file mode 100644 index 0000000000..9b763c53ca --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php @@ -0,0 +1,58 @@ +getTitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setTitle($value); + } + + public function getTitle() { + return pht( + '%s retitled this revision from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s retitled %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Revisions must have a title.')); + } + + $max_length = $object->getColumnMaximumByteLength('title'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht( + 'Revision title is too long: the maximum length of a '. + 'revision title is 255 bytes.'), + $xaction); + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionTransactionType.php b/src/applications/differential/xaction/DifferentialRevisionTransactionType.php new file mode 100644 index 0000000000..f740d97c74 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionTransactionType.php @@ -0,0 +1,4 @@ +loadDiffusionContext(); if ($response) { diff --git a/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php b/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php index 1c42fb027b..4c84d430cf 100644 --- a/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php +++ b/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php @@ -186,7 +186,7 @@ final class DiffusionSetPasswordSettingsPanel extends PhabricatorSettingsPanel { $form->appendRemarkupInstructions( pht( 'Having trouble coming up with a good password? Try this '. - 'artisinal password, hand made in small batches by our expert '. + 'artisanal password, hand made in small batches by our expert '. 'craftspeople: '. "\n\n". "`%s`", diff --git a/src/applications/diviner/controller/DivinerBookEditController.php b/src/applications/diviner/controller/DivinerBookEditController.php index 758cc190bb..b783e96746 100644 --- a/src/applications/diviner/controller/DivinerBookEditController.php +++ b/src/applications/diviner/controller/DivinerBookEditController.php @@ -92,15 +92,13 @@ final class DivinerBookEditController extends DivinerController { ->setName('viewPolicy') ->setPolicyObject($book) ->setCapability($view_capability) - ->setPolicies($policies) - ->setCaption($book->describeAutomaticCapability($view_capability))) + ->setPolicies($policies)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('editPolicy') ->setPolicyObject($book) ->setCapability($edit_capability) - ->setPolicies($policies) - ->setCaption($book->describeAutomaticCapability($edit_capability))) + ->setPolicies($policies)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Save')) diff --git a/src/applications/meta/query/PhabricatorAppSearchEngine.php b/src/applications/meta/query/PhabricatorAppSearchEngine.php index 62e1c1020e..b609a8b137 100644 --- a/src/applications/meta/query/PhabricatorAppSearchEngine.php +++ b/src/applications/meta/query/PhabricatorAppSearchEngine.php @@ -201,7 +201,7 @@ final class PhabricatorAppSearchEngine $results[] = phutil_tag( 'h1', array( - 'class' => 'phui-object-item-list-header', + 'class' => 'phui-oi-list-header', ), idx($group_names, $group, $group)); } diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index 44672edd3c..a4666c5a21 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -71,8 +71,8 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { ), '/p/(?P[\w._-]+)/' => array( '' => 'PhabricatorPeopleProfileViewController', - 'panel/' - => $this->getPanelRouting('PhabricatorPeopleProfilePanelController'), + 'item/' => $this->getProfileMenuRouting( + 'PhabricatorPeopleProfileMenuController'), ), ); } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index 74705f9809..1e0a9cbe18 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -36,7 +36,7 @@ abstract class PhabricatorPeopleProfileController if ($user) { $viewer = $this->getViewer(); - $engine = id(new PhabricatorPeopleProfilePanelEngine()) + $engine = id(new PhabricatorPeopleProfileMenuEngine()) ->setViewer($viewer) ->setProfileObject($user); diff --git a/src/applications/people/controller/PhabricatorPeopleProfileEditController.php b/src/applications/people/controller/PhabricatorPeopleProfileEditController.php index 9f132a18d8..3eda8a968b 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileEditController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileEditController.php @@ -85,7 +85,7 @@ final class PhabricatorPeopleProfileEditController $crumbs->setBorder(true); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $header = id(new PHUIHeaderView()) ->setHeader(pht('Edit Profile: %s', $user->getFullName())) diff --git a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php index d298660bd3..c5a3ceabd4 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php @@ -43,7 +43,7 @@ final class PhabricatorPeopleProfileManageController $name = $user->getUsername(); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $timeline = $this->buildTransactionTimeline( $user, diff --git a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php index 29b2290153..226646bc70 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php @@ -256,7 +256,7 @@ final class PhabricatorPeopleProfilePictureController $crumbs->setBorder(true); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $header = id(new PHUIHeaderView()) ->setHeader(pht('Edit Profile Picture')) diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php index 79134de017..17fc67e2f3 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php @@ -78,7 +78,7 @@ final class PhabricatorPeopleProfileViewController )); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_PROFILE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_PROFILE); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); diff --git a/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php new file mode 100644 index 0000000000..aab3896721 --- /dev/null +++ b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php @@ -0,0 +1,84 @@ +getProfileObject(); + $username = $user->getUsername(); + $username = phutil_escape_uri($username); + return "/p/{$username}/item/{$path}"; + } + + protected function getBuiltinProfileItems($object) { + $viewer = $this->getViewer(); + + $items = array(); + + $items[] = $this->newItem() + ->setBuiltinKey(self::ITEM_PROFILE) + ->setMenuItemKey(PhabricatorPeopleDetailsProfileMenuItem::MENUITEMKEY); + + $have_maniphest = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorManiphestApplication', + $viewer); + if ($have_maniphest) { + $uri = urisprintf( + '/maniphest/?statuses=open()&assigned=%s#R', + $object->getPHID()); + + $items[] = $this->newItem() + ->setBuiltinKey('tasks') + ->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY) + ->setMenuItemProperty('icon', 'maniphest') + ->setMenuItemProperty('name', pht('Open Tasks')) + ->setMenuItemProperty('uri', $uri); + } + + $have_differential = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorDifferentialApplication', + $viewer); + if ($have_differential) { + $uri = urisprintf( + '/differential/?authors=%s#R', + $object->getPHID()); + + $items[] = $this->newItem() + ->setBuiltinKey('revisions') + ->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY) + ->setMenuItemProperty('icon', 'differential') + ->setMenuItemProperty('name', pht('Revisions')) + ->setMenuItemProperty('uri', $uri); + } + + $have_diffusion = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorDiffusionApplication', + $viewer); + if ($have_diffusion) { + $uri = urisprintf( + '/audit/?authors=%s#R', + $object->getPHID()); + + $items[] = $this->newItem() + ->setBuiltinKey('commits') + ->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY) + ->setMenuItemProperty('icon', 'diffusion') + ->setMenuItemProperty('name', pht('Commits')) + ->setMenuItemProperty('uri', $uri); + } + + $items[] = $this->newItem() + ->setBuiltinKey(self::ITEM_MANAGE) + ->setMenuItemKey(PhabricatorPeopleManageProfileMenuItem::MENUITEMKEY); + + return $items; + } + +} diff --git a/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php b/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php deleted file mode 100644 index db362d2049..0000000000 --- a/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php +++ /dev/null @@ -1,84 +0,0 @@ -getProfileObject(); - $username = $user->getUsername(); - $username = phutil_escape_uri($username); - return "/p/{$username}/panel/{$path}"; - } - - protected function getBuiltinProfilePanels($object) { - $viewer = $this->getViewer(); - - $panels = array(); - - $panels[] = $this->newPanel() - ->setBuiltinKey(self::PANEL_PROFILE) - ->setPanelKey(PhabricatorPeopleDetailsProfilePanel::PANELKEY); - - $have_maniphest = PhabricatorApplication::isClassInstalledForViewer( - 'PhabricatorManiphestApplication', - $viewer); - if ($have_maniphest) { - $uri = urisprintf( - '/maniphest/?statuses=open()&assigned=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('tasks') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'maniphest') - ->setPanelProperty('name', pht('Open Tasks')) - ->setPanelProperty('uri', $uri); - } - - $have_differential = PhabricatorApplication::isClassInstalledForViewer( - 'PhabricatorDifferentialApplication', - $viewer); - if ($have_differential) { - $uri = urisprintf( - '/differential/?authors=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('revisions') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'differential') - ->setPanelProperty('name', pht('Revisions')) - ->setPanelProperty('uri', $uri); - } - - $have_diffusion = PhabricatorApplication::isClassInstalledForViewer( - 'PhabricatorDiffusionApplication', - $viewer); - if ($have_diffusion) { - $uri = urisprintf( - '/audit/?authors=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('commits') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'diffusion') - ->setPanelProperty('name', pht('Commits')) - ->setPanelProperty('uri', $uri); - } - - $panels[] = $this->newPanel() - ->setBuiltinKey(self::PANEL_MANAGE) - ->setPanelKey(PhabricatorPeopleManageProfilePanel::PANELKEY); - - return $panels; - } - -} diff --git a/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php b/src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php similarity index 66% rename from src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php rename to src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php index 83d45dfb9d..0f5cb6c1fa 100644 --- a/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php +++ b/src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -25,18 +25,18 @@ final class PhabricatorPeopleDetailsProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $user = $config->getProfileObject(); diff --git a/src/applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php b/src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php similarity index 59% rename from src/applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php rename to src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php index 29000b5a94..78d3dca49d 100644 --- a/src/applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php +++ b/src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -30,18 +30,18 @@ final class PhabricatorPeopleManageProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $user = $config->getProfileObject(); $id = $user->getID(); diff --git a/src/applications/policy/rule/PhabricatorPolicyRule.php b/src/applications/policy/rule/PhabricatorPolicyRule.php index bd5af9a1b8..2f9fac9cfb 100644 --- a/src/applications/policy/rule/PhabricatorPolicyRule.php +++ b/src/applications/policy/rule/PhabricatorPolicyRule.php @@ -144,9 +144,30 @@ abstract class PhabricatorPolicyRule extends Phobject { private static function getObjectPolicyCacheKey( PhabricatorPolicyInterface $object, PhabricatorPolicyRule $rule) { - $hash = spl_object_hash($object); - $rule = get_class($rule); - return 'policycache.'.$hash.'.'.$rule; + + // NOTE: This is quite a bit of a hack, but we don't currently have a + // better way to carry hints from the TransactionEditor into PolicyRules + // about pending policy changes. + + // Put some magic secret unique value on each object so we can pass + // information about it by proxy. This allows us to test if pending + // edits to an object will cause policy violations or not, before allowing + // those edits to go through. + + // Some better approaches might be: + // - Use traits to give `PhabricatorPolicyInterface` objects real + // storage (requires PHP 5.4.0). + // - Wrap policy objects in a container with extra storage which the + // policy filter knows how to unbox (lots of work). + + // When this eventually gets cleaned up, the corresponding hack in + // LiskDAO->__set() should also be cleaned up. + static $id = 0; + if (!isset($object->_hashKey)) { + @$object->_hashKey = 'object.id('.(++$id).')'; + } + + return $object->_hashKey; } diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index b8a6149e4f..8988f0f73a 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -61,8 +61,8 @@ final class PhabricatorProjectApplication extends PhabricatorApplication { => 'PhabricatorProjectEditPictureController', $this->getEditRoutePattern('edit/') => 'PhabricatorProjectEditController', - '(?P[1-9]\d*)/panel/' - => $this->getPanelRouting('PhabricatorProjectPanelController'), + '(?P[1-9]\d*)/item/' => $this->getProfileMenuRouting( + 'PhabricatorProjectMenuItemController'), 'subprojects/(?P[1-9]\d*)/' => 'PhabricatorProjectSubprojectsController', 'board/(?P[1-9]\d*)/'. diff --git a/src/applications/project/controller/PhabricatorProjectBoardController.php b/src/applications/project/controller/PhabricatorProjectBoardController.php index 04ab714eb0..d0c6abf882 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardController.php @@ -6,7 +6,7 @@ abstract class PhabricatorProjectBoardController protected function getProfileMenu() { $menu = parent::getProfileMenu(); - $menu->selectFilter(PhabricatorProject::PANEL_WORKBOARD); + $menu->selectFilter(PhabricatorProject::ITEM_WORKBOARD); $menu->addClass('project-board-nav'); return $menu; diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index da992d9b19..fa2a423b09 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -170,7 +170,7 @@ final class PhabricatorProjectBoardViewController } $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD); + $nav->selectFilter(PhabricatorProject::ITEM_WORKBOARD); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Workboard')); @@ -935,8 +935,8 @@ final class PhabricatorProjectBoardViewController $set_default = $request->getBool('default'); if ($set_default) { $this - ->getProfilePanelEngine() - ->adjustDefault(PhabricatorProject::PANEL_WORKBOARD); + ->getProfileMenuEngine() + ->adjustDefault(PhabricatorProject::ITEM_WORKBOARD); } if ($request->isFormPost()) { diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php index 8da16f923b..45e2f193af 100644 --- a/src/applications/project/controller/PhabricatorProjectController.php +++ b/src/applications/project/controller/PhabricatorProjectController.php @@ -4,7 +4,7 @@ abstract class PhabricatorProjectController extends PhabricatorController { private $project; private $profileMenu; - private $profilePanelEngine; + private $profileMenuEngine; protected function setProject(PhabricatorProject $project) { $this->project = $project; @@ -99,7 +99,7 @@ abstract class PhabricatorProjectController extends PhabricatorController { protected function getProfileMenu() { if (!$this->profileMenu) { - $engine = $this->getProfilePanelEngine(); + $engine = $this->getProfileMenuEngine(); if ($engine) { $this->profileMenu = $engine->buildNavigation(); } @@ -127,24 +127,25 @@ abstract class PhabricatorProjectController extends PhabricatorController { return $crumbs; } - protected function getProfilePanelEngine() { - if (!$this->profilePanelEngine) { + protected function getProfileMenuEngine() { + if (!$this->profileMenuEngine) { $viewer = $this->getViewer(); $project = $this->getProject(); if ($project) { - $engine = id(new PhabricatorProjectProfilePanelEngine()) + $engine = id(new PhabricatorProjectProfileMenuEngine()) ->setViewer($viewer) ->setController($this) ->setProfileObject($project); - $this->profilePanelEngine = $engine; + $this->profileMenuEngine = $engine; } } - return $this->profilePanelEngine; + + return $this->profileMenuEngine; } - protected function setProfilePanelEngine( - PhabricatorProjectProfilePanelEngine $engine) { - $this->profilePanelEngine = $engine; + protected function setProfileMenuEngine( + PhabricatorProjectProfileMenuEngine $engine) { + $this->profileMenuEngine = $engine; return $this; } diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php index 34a2c1b00e..4352ec6ad8 100644 --- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php +++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php @@ -255,7 +255,7 @@ final class PhabricatorProjectEditPictureController ->setForm($upload_form); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MANAGE); + $nav->selectFilter(PhabricatorProject::ITEM_MANAGE); return $this->newPage() ->setTitle($title) diff --git a/src/applications/project/controller/PhabricatorProjectManageController.php b/src/applications/project/controller/PhabricatorProjectManageController.php index c827f5abab..6ecdf6f62c 100644 --- a/src/applications/project/controller/PhabricatorProjectManageController.php +++ b/src/applications/project/controller/PhabricatorProjectManageController.php @@ -39,7 +39,7 @@ final class PhabricatorProjectManageController $timeline->setShouldTerminate(true); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MANAGE); + $nav->selectFilter(PhabricatorProject::ITEM_MANAGE); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Manage')); @@ -91,7 +91,7 @@ final class PhabricatorProjectManageController id(new PhabricatorActionView()) ->setName(pht('Edit Menu')) ->setIcon('fa-th-list') - ->setHref($this->getApplicationURI("{$id}/panel/configure/")) + ->setHref($this->getApplicationURI("{$id}/item/configure/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); diff --git a/src/applications/project/controller/PhabricatorProjectMembersViewController.php b/src/applications/project/controller/PhabricatorProjectMembersViewController.php index e98412ff31..959927c9f3 100644 --- a/src/applications/project/controller/PhabricatorProjectMembersViewController.php +++ b/src/applications/project/controller/PhabricatorProjectMembersViewController.php @@ -42,7 +42,7 @@ final class PhabricatorProjectMembersViewController ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MEMBERS); + $nav->selectFilter(PhabricatorProject::ITEM_MEMBERS); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Members')); diff --git a/src/applications/project/controller/PhabricatorProjectPanelController.php b/src/applications/project/controller/PhabricatorProjectMenuItemController.php similarity index 71% rename from src/applications/project/controller/PhabricatorProjectPanelController.php rename to src/applications/project/controller/PhabricatorProjectMenuItemController.php index d20b5b9828..bd615c3f8e 100644 --- a/src/applications/project/controller/PhabricatorProjectPanelController.php +++ b/src/applications/project/controller/PhabricatorProjectMenuItemController.php @@ -1,6 +1,6 @@ getViewer(); $project = $this->getProject(); - $engine = id(new PhabricatorProjectProfilePanelEngine()) + $engine = id(new PhabricatorProjectProfileMenuEngine()) ->setProfileObject($project) ->setController($this); - $this->setProfilePanelEngine($engine); + $this->setProfileMenuEngine($engine); return $engine->buildResponse(); } diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index c9f3c2b9d3..ca9732b6f1 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -70,7 +70,7 @@ final class PhabricatorProjectProfileController ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + $nav->selectFilter(PhabricatorProject::ITEM_PROFILE); $stories = id(new PhabricatorFeedQuery()) ->setViewer($viewer) diff --git a/src/applications/project/controller/PhabricatorProjectSubprojectsController.php b/src/applications/project/controller/PhabricatorProjectSubprojectsController.php index 1232d4010e..4a89bb4cde 100644 --- a/src/applications/project/controller/PhabricatorProjectSubprojectsController.php +++ b/src/applications/project/controller/PhabricatorProjectSubprojectsController.php @@ -92,7 +92,7 @@ final class PhabricatorProjectSubprojectsController ->addPropertyList($property_list); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_SUBPROJECTS); + $nav->selectFilter(PhabricatorProject::ITEM_SUBPROJECTS); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Subprojects')); diff --git a/src/applications/project/controller/PhabricatorProjectViewController.php b/src/applications/project/controller/PhabricatorProjectViewController.php index 412565c056..d2f8d4f58d 100644 --- a/src/applications/project/controller/PhabricatorProjectViewController.php +++ b/src/applications/project/controller/PhabricatorProjectViewController.php @@ -17,14 +17,14 @@ final class PhabricatorProjectViewController } $project = $this->getProject(); - $engine = $this->getProfilePanelEngine(); - $default = $engine->getDefaultPanel(); + $engine = $this->getProfileMenuEngine(); + $default = $engine->getDefaultItem(); switch ($default->getBuiltinKey()) { - case PhabricatorProject::PANEL_WORKBOARD: + case PhabricatorProject::ITEM_WORKBOARD: $controller_object = new PhabricatorProjectBoardViewController(); break; - case PhabricatorProject::PANEL_PROFILE: + case PhabricatorProject::ITEM_PROFILE: default: $controller_object = new PhabricatorProjectProfileController(); break; diff --git a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php new file mode 100644 index 0000000000..d3ea39e1e2 --- /dev/null +++ b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php @@ -0,0 +1,47 @@ +getProfileObject(); + $id = $project->getID(); + return "/project/{$id}/item/{$path}"; + } + + protected function getBuiltinProfileItems($object) { + $items = array(); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_PROFILE) + ->setMenuItemKey(PhabricatorProjectDetailsProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_POINTS) + ->setMenuItemKey(PhabricatorProjectPointsProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_WORKBOARD) + ->setMenuItemKey(PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_MEMBERS) + ->setMenuItemKey(PhabricatorProjectMembersProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_SUBPROJECTS) + ->setMenuItemKey( + PhabricatorProjectSubprojectsProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_MANAGE) + ->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY); + + return $items; + } + +} diff --git a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php deleted file mode 100644 index 3a34b6c80c..0000000000 --- a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php +++ /dev/null @@ -1,46 +0,0 @@ -getProfileObject(); - $id = $project->getID(); - return "/project/{$id}/panel/{$path}"; - } - - protected function getBuiltinProfilePanels($object) { - $panels = array(); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_PROFILE) - ->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_POINTS) - ->setPanelKey(PhabricatorProjectPointsProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD) - ->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) - ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_SUBPROJECTS) - ->setPanelKey(PhabricatorProjectSubprojectsProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_MANAGE) - ->setPanelKey(PhabricatorProjectManageProfilePanel::PANELKEY); - - return $panels; - } - -} diff --git a/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php b/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php index ce9fbf332c..5daacd315c 100644 --- a/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php +++ b/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php @@ -5,6 +5,10 @@ final class PhabricatorProjectsEditEngineExtension const EXTENSIONKEY = 'projects.projects'; + const EDITKEY_ADD = 'projects.add'; + const EDITKEY_SET = 'projects.set'; + const EDITKEY_REMOVE = 'projects.remove'; + public function getExtensionPriority() { return 500; } @@ -58,14 +62,14 @@ final class PhabricatorProjectsEditEngineExtension $projects_field->setViewer($engine->getViewer()); - $edit_add = $projects_field->getConduitEditType('projects.add') + $edit_add = $projects_field->getConduitEditType(self::EDITKEY_ADD) ->setConduitDescription(pht('Add project tags.')); - $edit_set = $projects_field->getConduitEditType('projects.set') + $edit_set = $projects_field->getConduitEditType(self::EDITKEY_SET) ->setConduitDescription( pht('Set project tags, overwriting current value.')); - $edit_rem = $projects_field->getConduitEditType('projects.remove') + $edit_rem = $projects_field->getConduitEditType(self::EDITKEY_REMOVE) ->setConduitDescription(pht('Remove project tags.')); return array( diff --git a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php similarity index 64% rename from src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php index 07e6ce4c10..becdd36c16 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -30,18 +30,18 @@ final class PhabricatorProjectDetailsProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); diff --git a/src/applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php similarity index 60% rename from src/applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php index ae66c4cc3e..1bd7e796dc 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -35,18 +35,18 @@ final class PhabricatorProjectManageProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); diff --git a/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php similarity index 65% rename from src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php index b5374416aa..580aacb635 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -25,18 +25,18 @@ final class PhabricatorProjectMembersProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); diff --git a/src/applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php similarity index 92% rename from src/applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php index 02a2f3984f..020e5626de 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php @@ -1,11 +1,11 @@ getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorInstructionsEditField()) ->setValue( @@ -53,7 +53,7 @@ final class PhabricatorProjectPointsProfilePanel } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $project = $config->getProfileObject(); diff --git a/src/applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php similarity index 71% rename from src/applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php index 342c8025aa..dfcb164f45 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -33,18 +33,18 @@ final class PhabricatorProjectSubprojectsProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); diff --git a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php similarity index 71% rename from src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php index 8bfeeb4cfe..6305bb4b13 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php @@ -1,11 +1,11 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; @@ -42,18 +42,18 @@ final class PhabricatorProjectWorkboardProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $has_workboard = $project->getHasWorkboard(); diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 6e4892b32a..47e251f3af 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -49,13 +49,13 @@ final class PhabricatorProject extends PhabricatorProjectDAO const TABLE_DATASOURCE_TOKEN = 'project_datasourcetoken'; - const PANEL_PROFILE = 'project.profile'; - const PANEL_POINTS = 'project.points'; - const PANEL_WORKBOARD = 'project.workboard'; - const PANEL_MEMBERS = 'project.members'; - const PANEL_MANAGE = 'project.manage'; - const PANEL_MILESTONES = 'project.milestones'; - const PANEL_SUBPROJECTS = 'project.subprojects'; + const ITEM_PROFILE = 'project.profile'; + const ITEM_POINTS = 'project.points'; + const ITEM_WORKBOARD = 'project.workboard'; + const ITEM_MEMBERS = 'project.members'; + const ITEM_MANAGE = 'project.manage'; + const ITEM_MILESTONES = 'project.milestones'; + const ITEM_SUBPROJECTS = 'project.subprojects'; public static function initializeNewProject(PhabricatorUser $actor) { $app = id(new PhabricatorApplicationQuery()) diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php index 9cbb8db8e9..fe19849163 100644 --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -272,6 +272,11 @@ final class PhabricatorRepositoryPullLocalDaemon $future->setTimeout($timeout); + // The default TERM inherited by this process is "unknown", which causes PHP + // to produce a warning upon startup. Override it to squash this output to + // STDERR. + $future->updateEnv('TERM', 'dumb'); + return $future; } diff --git a/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php b/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php similarity index 63% rename from src/applications/search/editor/PhabricatorProfilePanelEditEngine.php rename to src/applications/search/editor/PhabricatorProfileMenuEditEngine.php index e5689c8e68..f7b8f76ec7 100644 --- a/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php +++ b/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php @@ -1,26 +1,26 @@ panelEngine = $engine; + public function setMenuEngine(PhabricatorProfileMenuEngine $engine) { + $this->menuEngine = $engine; return $this; } - public function getPanelEngine() { - return $this->panelEngine; + public function getMenuEngine() { + return $this->menuEngine; } public function setProfileObject($profile_object) { @@ -32,14 +32,14 @@ final class PhabricatorProfilePanelEditEngine return $this->profileObject; } - public function setNewPanelConfiguration( - PhabricatorProfilePanelConfiguration $configuration) { - $this->newPanelConfiguration = $configuration; + public function setNewMenuItemConfiguration( + PhabricatorProfileMenuItemConfiguration $configuration) { + $this->newMenuItemConfiguration = $configuration; return $this; } - public function getNewPanelConfiguration() { - return $this->newPanelConfiguration; + public function getNewMenuItemConfiguration() { + return $this->newMenuItemConfiguration; } public function setIsBuiltin($is_builtin) { @@ -52,11 +52,11 @@ final class PhabricatorProfilePanelEditEngine } public function getEngineName() { - return pht('Profile Panels'); + return pht('Profile Menu Items'); } public function getSummaryHeader() { - return pht('Edit Profile Panel Configurations'); + return pht('Edit Profile Menu Item Configurations'); } public function getSummaryText() { @@ -68,16 +68,18 @@ final class PhabricatorProfilePanelEditEngine } protected function newEditableObject() { - if (!$this->newPanelConfiguration) { + if (!$this->newMenuItemConfiguration) { throw new Exception( - pht('Profile panels can not be generated without an object context.')); + pht( + 'Profile menu items can not be generated without an '. + 'object context.')); } - return clone $this->newPanelConfiguration; + return clone $this->newMenuItemConfiguration; } protected function newObjectQuery() { - return id(new PhabricatorProfilePanelConfigurationQuery()); + return id(new PhabricatorProfileMenuItemConfigurationQuery()); } protected function getObjectCreateTitleText($object) { @@ -113,19 +115,19 @@ final class PhabricatorProfilePanelEditEngine } protected function getObjectCreateCancelURI($object) { - return $this->getPanelEngine()->getConfigureURI(); + return $this->getMenuEngine()->getConfigureURI(); } protected function getObjectViewURI($object) { - return $this->getPanelEngine()->getConfigureURI(); + return $this->getMenuEngine()->getConfigureURI(); } protected function buildCustomEditFields($object) { - $panel = $object->getPanel(); - $fields = $panel->buildEditEngineFields($object); + $item = $object->getMenuItem(); + $fields = $item->buildEditEngineFields($object); $type_property = - PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY; foreach ($fields as $field) { $field diff --git a/src/applications/search/editor/PhabricatorProfilePanelEditor.php b/src/applications/search/editor/PhabricatorProfileMenuEditor.php similarity index 52% rename from src/applications/search/editor/PhabricatorProfilePanelEditor.php rename to src/applications/search/editor/PhabricatorProfileMenuEditor.php index ce4dbeb8f0..d91bba272b 100644 --- a/src/applications/search/editor/PhabricatorProfilePanelEditor.php +++ b/src/applications/search/editor/PhabricatorProfileMenuEditor.php @@ -1,6 +1,6 @@ getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: $key = $xaction->getMetadataValue('property.key'); - return $object->getPanelProperty($key, null); - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: - return $object->getPanelOrder(); - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + return $object->getMenuItemProperty($key, null); + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: + return $object->getMenuItemOrder(); + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: return $object->getVisibility(); } } @@ -41,10 +44,10 @@ final class PhabricatorProfilePanelEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: return $xaction->getNewValue(); - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: return (int)$xaction->getNewValue(); } } @@ -54,15 +57,15 @@ final class PhabricatorProfilePanelEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: $key = $xaction->getMetadataValue('property.key'); $value = $xaction->getNewValue(); - $object->setPanelProperty($key, $value); + $object->setMenuItemProperty($key, $value); return; - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: - $object->setPanelOrder($xaction->getNewValue()); + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: + $object->setMenuItemOrder($xaction->getNewValue()); return; - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: $object->setVisibility($xaction->getNewValue()); return; } @@ -75,9 +78,9 @@ final class PhabricatorProfilePanelEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: return; } diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfileMenuEngine.php similarity index 61% rename from src/applications/search/engine/PhabricatorProfilePanelEngine.php rename to src/applications/search/engine/PhabricatorProfileMenuEngine.php index d3c209ba68..d930b31314 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfileMenuEngine.php @@ -1,11 +1,11 @@ controller; } - private function setDefaultPanel( - PhabricatorProfilePanelConfiguration $default_panel) { - $this->defaultPanel = $default_panel; + private function setDefaultItem( + PhabricatorProfileMenuItemConfiguration $default_item) { + $this->defaultItem = $default_item; return $this; } - public function getDefaultPanel() { - $this->loadPanels(); - return $this->defaultPanel; + public function getDefaultItem() { + $this->loadItems(); + return $this->defaultItem; } - abstract protected function getPanelURI($path); + abstract protected function getItemURI($path); - abstract protected function isPanelEngineConfigurable(); + abstract protected function isMenuEngineConfigurable(); public function buildResponse() { $controller = $this->getController(); @@ -59,12 +59,12 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $request = $controller->getRequest(); - $panel_action = $request->getURIData('panelAction'); + $item_action = $request->getURIData('itemAction'); // If the engine is not configurable, don't respond to any of the editing // or configuration routes. - if (!$this->isPanelEngineConfigurable()) { - switch ($panel_action) { + if (!$this->isMenuEngineConfigurable()) { + switch ($item_action) { case 'view': break; default: @@ -72,80 +72,79 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } } - $panel_id = $request->getURIData('panelID'); + $item_id = $request->getURIData('itemID'); + $item_list = $this->getItems(); - $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_int) { - $selected_panel = $panel; + $selected_item = null; + if (strlen($item_id)) { + $item_id_int = (int)$item_id; + foreach ($item_list as $item) { + if ($item_id_int) { + if ((int)$item->getID() === $item_id_int) { + $selected_item = $item; break; } } - $builtin_key = $panel->getBuiltinKey(); - if ($builtin_key === (string)$panel_id) { - $selected_panel = $panel; + $builtin_key = $item->getBuiltinKey(); + if ($builtin_key === (string)$item_id) { + $selected_item = $item; break; } } } - switch ($panel_action) { + switch ($item_action) { case 'view': case 'info': case 'hide': case 'default': case 'builtin': - if (!$selected_panel) { + if (!$selected_item) { return new Aphront404Response(); } break; } $navigation = $this->buildNavigation(); - $navigation->selectFilter('panel.configure'); + $navigation->selectFilter('item.configure'); $crumbs = $controller->buildApplicationCrumbsForEditEngine(); - switch ($panel_action) { + switch ($item_action) { case 'view': - $content = $this->buildPanelViewContent($selected_panel); + $content = $this->buildItemViewContent($selected_item); break; case 'configure': - $content = $this->buildPanelConfigureContent($panel_list); + $content = $this->buildItemConfigureContent($item_list); $crumbs->addTextCrumb(pht('Configure Menu')); break; case 'reorder': - $content = $this->buildPanelReorderContent($panel_list); + $content = $this->buildItemReorderContent($item_list); break; case 'new': - $panel_key = $request->getURIData('panelKey'); - $content = $this->buildPanelNewContent($panel_key); + $item_key = $request->getURIData('itemKey'); + $content = $this->buildItemNewContent($item_key); break; case 'builtin': - $content = $this->buildPanelBuiltinContent($selected_panel); + $content = $this->buildItemBuiltinContent($selected_item); break; case 'hide': - $content = $this->buildPanelHideContent($selected_panel); + $content = $this->buildItemHideContent($selected_item); break; case 'default': - $content = $this->buildPanelDefaultContent( - $selected_panel, - $panel_list); + $content = $this->buildItemDefaultContent( + $selected_item, + $item_list); break; case 'edit': - $content = $this->buildPanelEditContent(); + $content = $this->buildItemEditContent(); break; default: throw new Exception( pht( - 'Unsupported panel action "%s".', - $panel_action)); + 'Unsupported item action "%s".', + $item_action)); } if ($content instanceof AphrontResponse) { @@ -156,8 +155,10 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { return $content; } + $crumbs->setBorder(true); + return $controller->newPage() - ->setTitle(pht('Profile Stuff')) + ->setTitle(pht('Configure Menu')) ->setNavigation($navigation) ->setCrumbs($crumbs) ->appendChild($content); @@ -170,33 +171,45 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $nav = id(new AphrontSideNavFilterView()) ->setIsProfileMenu(true) - ->setBaseURI(new PhutilURI($this->getPanelURI(''))); + ->setBaseURI(new PhutilURI($this->getItemURI(''))); - $panels = $this->getPanels(); + $menu_items = $this->getItems(); + $filtered_items = array(); + foreach ($menu_items as $menu_item) { + if ($menu_item->isDisabled()) { + continue; + } + $filtered_items[] = $menu_item; + } + $filtered_groups = mgroup($filtered_items, 'getMenuItemKey'); + foreach ($filtered_groups as $group) { + $first_item = head($group); + $first_item->willBuildNavigationItems($group); + } - foreach ($panels as $panel) { - if ($panel->isDisabled()) { + foreach ($menu_items as $menu_item) { + if ($menu_item->isDisabled()) { continue; } - $items = $panel->buildNavigationMenuItems(); + $items = $menu_item->buildNavigationMenuItems(); foreach ($items as $item) { $this->validateNavigationMenuItem($item); } - // If the panel produced only a single item which does not otherwise + // If the item produced only a single item which does not otherwise // have a key, try to automatically assign it a reasonable key. This // makes selecting the correct item simpler. if (count($items) == 1) { $item = head($items); if ($item->getKey() === null) { - $builtin_key = $panel->getBuiltinKey(); - $panel_phid = $panel->getPHID(); + $builtin_key = $menu_item->getBuiltinKey(); + $item_phid = $menu_item->getPHID(); if ($builtin_key !== null) { $item->setKey($builtin_key); - } else if ($panel_phid !== null) { - $item->setKey($panel_phid); + } else if ($item_phid !== null) { + $item->setKey($item_phid); } } } @@ -217,75 +230,75 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { return $this->navigation; } - private function getPanels() { - if ($this->panels === null) { - $this->panels = $this->loadPanels(); + private function getItems() { + if ($this->items === null) { + $this->items = $this->loadItems(); } - return $this->panels; + return $this->items; } - private function loadPanels() { + private function loadItems() { $viewer = $this->getViewer(); $object = $this->getProfileObject(); - $panels = $this->loadBuiltinProfilePanels(); + $items = $this->loadBuiltinProfileItems(); - $stored_panels = id(new PhabricatorProfilePanelConfigurationQuery()) + $stored_items = id(new PhabricatorProfileMenuItemConfigurationQuery()) ->setViewer($viewer) ->withProfilePHIDs(array($object->getPHID())) ->execute(); - foreach ($stored_panels as $stored_panel) { - $impl = $stored_panel->getPanel(); + foreach ($stored_items as $stored_item) { + $impl = $stored_item->getMenuItem(); $impl->setViewer($viewer); } - // Merge the stored panels into the builtin panels. If a builtin panel has + // Merge the stored items into the builtin items. If a builtin item has // a stored version, replace the defaults with the stored changes. - foreach ($stored_panels as $stored_panel) { - if (!$stored_panel->shouldEnableForObject($object)) { + foreach ($stored_items as $stored_item) { + if (!$stored_item->shouldEnableForObject($object)) { continue; } - $builtin_key = $stored_panel->getBuiltinKey(); + $builtin_key = $stored_item->getBuiltinKey(); if ($builtin_key !== null) { // If this builtin actually exists, replace the builtin with the // stored configuration. Otherwise, we're just going to drop the // stored config: it corresponds to an out-of-date or uninstalled - // panel. - if (isset($panels[$builtin_key])) { - $panels[$builtin_key] = $stored_panel; + // item. + if (isset($items[$builtin_key])) { + $items[$builtin_key] = $stored_item; } else { continue; } } else { - $panels[] = $stored_panel; + $items[] = $stored_item; } } - $panels = msort($panels, 'getSortKey'); + $items = msort($items, 'getSortKey'); // Normalize keys since callers shouldn't rely on this array being // partially keyed. - $panels = array_values($panels); + $items = array_values($items); - // Make sure exactly one valid panel is marked as default. + // Make sure exactly one valid item is marked as default. $default = null; $first = null; - foreach ($panels as $panel) { - if (!$panel->canMakeDefault()) { + foreach ($items as $item) { + if (!$item->canMakeDefault()) { continue; } - if ($panel->isDefault()) { - $default = $panel; + if ($item->isDefault()) { + $default = $item; break; } if ($first === null) { - $first = $panel; + $first = $item; } } @@ -294,17 +307,17 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } if ($default) { - $this->setDefaultPanel($default); + $this->setDefaultItem($default); } - return $panels; + return $items; } - private function loadBuiltinProfilePanels() { + private function loadBuiltinProfileItems() { $object = $this->getProfileObject(); - $builtins = $this->getBuiltinProfilePanels($object); + $builtins = $this->getBuiltinProfileItems($object); - $panels = PhabricatorProfilePanel::getAllPanels(); + $items = PhabricatorProfileMenuItem::getAllMenuItems(); $viewer = $this->getViewer(); $order = 1; @@ -315,38 +328,38 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { if (!$builtin_key) { throw new Exception( pht( - 'Object produced a builtin panel with no builtin panel key! '. - 'Builtin panels must have a unique key.')); + 'Object produced a builtin item with no builtin item key! '. + 'Builtin items must have a unique key.')); } if (isset($map[$builtin_key])) { throw new Exception( pht( - 'Object produced two panels with the same builtin key ("%s"). '. - 'Each panel must have a unique builtin key.', + 'Object produced two items with the same builtin key ("%s"). '. + 'Each item must have a unique builtin key.', $builtin_key)); } - $panel_key = $builtin->getPanelKey(); + $item_key = $builtin->getMenuItemKey(); - $panel = idx($panels, $panel_key); - if (!$panel) { + $item = idx($items, $item_key); + if (!$item) { throw new Exception( pht( - 'Builtin panel ("%s") specifies a bad panel key ("%s"); there '. - 'is no corresponding panel implementation available.', + 'Builtin item ("%s") specifies a bad item key ("%s"); there '. + 'is no corresponding item implementation available.', $builtin_key, - $panel_key)); + $item_key)); } - $panel = clone $panel; - $panel->setViewer($viewer); + $item = clone $item; + $item->setViewer($viewer); $builtin ->setProfilePHID($object->getPHID()) - ->attachPanel($panel) + ->attachMenuItem($item) ->attachProfileObject($object) - ->setPanelOrder($order); + ->setMenuItemOrder($order); if (!$builtin->shouldEnableForObject($object)) { continue; @@ -437,10 +450,10 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } public function getConfigureURI() { - return $this->getPanelURI('configure/'); + return $this->getItemURI('configure/'); } - private function buildPanelReorderContent(array $panels) { + private function buildItemReorderContent(array $items) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); @@ -459,14 +472,14 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $by_builtin = array(); $by_id = array(); - foreach ($panels as $key => $panel) { - $id = $panel->getID(); + foreach ($items as $key => $item) { + $id = $item->getID(); if ($id) { $by_id[$id] = $key; continue; } - $builtin_key = $panel->getBuiltinKey(); + $builtin_key = $item->getBuiltinKey(); if ($builtin_key) { $by_builtin[$builtin_key] = $key; continue; @@ -485,25 +498,25 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } } - $panels = array_select_keys($panels, $key_order) + $panels; + $items = array_select_keys($items, $key_order) + $items; $type_order = - PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER; $order = 1; - foreach ($panels as $panel) { + foreach ($items as $item) { $xactions = array(); - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) + $xactions[] = id(new PhabricatorProfileMenuItemConfigurationTransaction()) ->setTransactionType($type_order) ->setNewValue($order); - $editor = id(new PhabricatorProfilePanelEditor()) + $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) - ->applyTransactions($panel, $xactions); + ->applyTransactions($item, $xactions); $order++; } @@ -513,7 +526,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } - private function buildPanelConfigureContent(array $panels) { + private function buildItemConfigureContent(array $items) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); @@ -528,34 +541,34 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { 'reorder-profile-menu-items', array( 'listID' => $list_id, - 'orderURI' => $this->getPanelURI('reorder/'), + 'orderURI' => $this->getItemURI('reorder/'), )); $list = id(new PHUIObjectItemListView()) ->setID($list_id); - foreach ($panels as $panel) { - $id = $panel->getID(); - $builtin_key = $panel->getBuiltinKey(); + foreach ($items as $item) { + $id = $item->getID(); + $builtin_key = $item->getBuiltinKey(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, - $panel, + $item, PhabricatorPolicyCapability::CAN_EDIT); - $item = id(new PHUIObjectItemView()); + $view = id(new PHUIObjectItemView()); - $name = $panel->getDisplayName(); - $type = $panel->getPanelTypeName(); + $name = $item->getDisplayName(); + $type = $item->getMenuItemTypeName(); if (!strlen(trim($name))) { $name = pht('Untitled "%s" Item', $type); } - $item->setHeader($name); - $item->addAttribute($type); + $view->setHeader($name); + $view->addAttribute($type); if ($can_edit) { - $item + $view ->setGrippable(true) ->addSigil('profile-menu-item') ->setMetadata( @@ -564,15 +577,15 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { )); if ($id) { - $default_uri = $this->getPanelURI("default/{$id}/"); + $default_uri = $this->getItemURI("default/{$id}/"); } else { - $default_uri = $this->getPanelURI("default/{$builtin_key}/"); + $default_uri = $this->getItemURI("default/{$builtin_key}/"); } - if ($panel->isDefault()) { + if ($item->isDefault()) { $default_icon = 'fa-thumb-tack green'; $default_text = pht('Current Default'); - } else if ($panel->canMakeDefault()) { + } else if ($item->canMakeDefault()) { $default_icon = 'fa-thumb-tack'; $default_text = pht('Make Default'); } else { @@ -580,7 +593,7 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } if ($default_text !== null) { - $item->addAction( + $view->addAction( id(new PHUIListItemView()) ->setHref($default_uri) ->setWorkflow(true) @@ -589,17 +602,17 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { } if ($id) { - $item->setHref($this->getPanelURI("edit/{$id}/")); - $hide_uri = $this->getPanelURI("hide/{$id}/"); + $view->setHref($this->getItemURI("edit/{$id}/")); + $hide_uri = $this->getItemURI("hide/{$id}/"); } else { - $item->setHref($this->getPanelURI("builtin/{$builtin_key}/")); - $hide_uri = $this->getPanelURI("hide/{$builtin_key}/"); + $view->setHref($this->getItemURI("builtin/{$builtin_key}/")); + $hide_uri = $this->getItemURI("hide/{$builtin_key}/"); } - if ($panel->isDisabled()) { + if ($item->isDisabled()) { $hide_icon = 'fa-plus'; $hide_text = pht('Enable'); - } else if ($panel->getBuiltinKey() !== null) { + } else if ($item->getBuiltinKey() !== null) { $hide_icon = 'fa-times'; $hide_text = pht('Disable'); } else { @@ -607,9 +620,9 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $hide_text = pht('Delete'); } - $can_disable = $panel->canHidePanel(); + $can_disable = $item->canHideMenuItem(); - $item->addAction( + $view->addAction( id(new PHUIListItemView()) ->setHref($hide_uri) ->setWorkflow(true) @@ -618,38 +631,43 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ->setIcon($hide_icon)); } - if ($panel->isDisabled()) { - $item->setDisabled(true); + if ($item->isDisabled()) { + $view->setDisabled(true); } - $list->addItem($item); + $list->addItem($view); } $action_view = id(new PhabricatorActionListView()) ->setUser($viewer); - $panel_types = PhabricatorProfilePanel::getAllPanels(); + $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); + $object = $this->getProfileObject(); - $action_view->addAction( + $action_list = id(new PhabricatorActionListView()) + ->setViewer($viewer); + + $action_list->addAction( id(new PhabricatorActionView()) ->setLabel(true) ->setName(pht('Add New Menu Item...'))); - foreach ($panel_types as $panel_type) { - if (!$panel_type->canAddToObject($object)) { + foreach ($item_types as $item_type) { + if (!$item_type->canAddToObject($object)) { continue; } - $panel_key = $panel_type->getPanelKey(); + $item_key = $item_type->getMenuItemKey(); - $action_view->addAction( + $action_list->addAction( id(new PhabricatorActionView()) - ->setIcon($panel_type->getPanelTypeIcon()) - ->setName($panel_type->getPanelTypeName()) - ->setHref($this->getPanelURI("new/{$panel_key}/"))); + ->setIcon($item_type->getMenuItemTypeIcon()) + ->setName($item_type->getMenuItemTypeName()) + ->setHref($this->getItemURI("new/{$item_key}/")) + ->setWorkflow(true)); } - $action_view->addAction( + $action_list->addAction( id(new PhabricatorActionView()) ->setLabel(true) ->setName(pht('Documentation'))); @@ -657,47 +675,54 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $doc_link = PhabricatorEnv::getDoclink('Profile Menu User Guide'); $doc_name = pht('Profile Menu User Guide'); - $action_view->addAction( + $action_list->addAction( id(new PhabricatorActionView()) ->setIcon('fa-book') ->setHref($doc_link) ->setName($doc_name)); - $action_button = id(new PHUIButtonView()) - ->setTag('a') - ->setText(pht('Configure Menu')) - ->setHref('#') - ->setIcon('fa-gear') - ->setDropdownMenu($action_view); - $header = id(new PHUIHeaderView()) ->setHeader(pht('Profile Menu Items')) - ->setSubHeader(pht('Drag tabs to reorder menu')) - ->addActionLink($action_button); + ->setHeaderIcon('fa-list'); $box = id(new PHUIObjectBoxView()) - ->setHeader($header) + ->setHeaderText(pht('Navigation')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList($list); - return $box; + $panel = id(new PHUICurtainPanelView()) + ->appendChild($action_view); + + $curtain = id(new PHUICurtainView()) + ->setViewer($viewer) + ->setActionList($action_list); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setCurtain($curtain) + ->setMainColumn( + array( + $box, + )); + + return $view; } - private function buildPanelNewContent($panel_key) { - $panel_types = PhabricatorProfilePanel::getAllPanels(); - $panel_type = idx($panel_types, $panel_key); - if (!$panel_type) { + private function buildItemNewContent($item_key) { + $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); + $item_type = idx($item_types, $item_key); + if (!$item_type) { return new Aphront404Response(); } $object = $this->getProfileObject(); - if (!$panel_type->canAddToObject($object)) { + if (!$item_type->canAddToObject($object)) { return new Aphront404Response(); } - $configuration = - PhabricatorProfilePanelConfiguration::initializeNewPanelConfiguration( - $object, - $panel_type); + $configuration = PhabricatorProfileMenuItemConfiguration::initializeNewItem( + $object, + $item_type); $viewer = $this->getViewer(); @@ -708,38 +733,38 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $controller = $this->getController(); - return id(new PhabricatorProfilePanelEditEngine()) - ->setPanelEngine($this) + return id(new PhabricatorProfileMenuEditEngine()) + ->setMenuEngine($this) ->setProfileObject($object) - ->setNewPanelConfiguration($configuration) + ->setNewMenuItemConfiguration($configuration) ->setController($controller) ->buildResponse(); } - private function buildPanelEditContent() { + private function buildItemEditContent() { $viewer = $this->getViewer(); $object = $this->getProfileObject(); $controller = $this->getController(); - return id(new PhabricatorProfilePanelEditEngine()) - ->setPanelEngine($this) + return id(new PhabricatorProfileMenuEditEngine()) + ->setMenuEngine($this) ->setProfileObject($object) ->setController($controller) ->buildResponse(); } - private function buildPanelBuiltinContent( - PhabricatorProfilePanelConfiguration $configuration) { + private function buildItemBuiltinContent( + PhabricatorProfileMenuItemConfiguration $configuration) { - // If this builtin panel has already been persisted, redirect to the + // If this builtin item has already been persisted, redirect to the // edit page. $id = $configuration->getID(); if ($id) { return id(new AphrontRedirectResponse()) - ->setURI($this->getPanelURI("edit/{$id}/")); + ->setURI($this->getItemURI("edit/{$id}/")); } - // Otherwise, act like we're creating a new panel, we're just starting + // Otherwise, act like we're creating a new item, we're just starting // with the builtin template. $viewer = $this->getViewer(); @@ -751,17 +776,17 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $object = $this->getProfileObject(); $controller = $this->getController(); - return id(new PhabricatorProfilePanelEditEngine()) + return id(new PhabricatorProfileMenuEditEngine()) ->setIsBuiltin(true) - ->setPanelEngine($this) + ->setMenuEngine($this) ->setProfileObject($object) - ->setNewPanelConfiguration($configuration) + ->setNewMenuItemConfiguration($configuration) ->setController($controller) ->buildResponse(); } - private function buildPanelHideContent( - PhabricatorProfilePanelConfiguration $configuration) { + private function buildItemHideContent( + PhabricatorProfileMenuItemConfiguration $configuration) { $controller = $this->getController(); $request = $controller->getRequest(); @@ -772,11 +797,11 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $configuration, PhabricatorPolicyCapability::CAN_EDIT); - if (!$configuration->canHidePanel()) { + if (!$configuration->canHideMenuItem()) { return $controller->newDialog() - ->setTitle(pht('Mandatory Panel')) + ->setTitle(pht('Mandatory Item')) ->appendParagraph( - pht('This panel is very important, and can not be disabled.')) + pht('This menu item is very important, and can not be disabled.')) ->addCancelButton($this->getConfigureURI()); } @@ -787,14 +812,14 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $body = pht('Delete this menu item?'); $button = pht('Delete Menu Item'); } else if ($configuration->isDisabled()) { - $new_value = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; + $new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE; $title = pht('Enable Menu Item'); $body = pht( 'Enable this menu item? It will appear in the menu again.'); $button = pht('Enable Menu Item'); } else { - $new_value = PhabricatorProfilePanelConfiguration::VISIBILITY_DISABLED; + $new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DISABLED; $title = pht('Disable Menu Item'); $body = pht( @@ -809,15 +834,16 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $configuration->delete(); } else { $type_visibility = - PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY; $xactions = array(); - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) - ->setTransactionType($type_visibility) - ->setNewValue($new_value); + $xactions[] = + id(new PhabricatorProfileMenuItemConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($new_value); - $editor = id(new PhabricatorProfilePanelEditor()) + $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) @@ -836,9 +862,9 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ->addSubmitButton($button); } - private function buildPanelDefaultContent( - PhabricatorProfilePanelConfiguration $configuration, - array $panels) { + private function buildItemDefaultContent( + PhabricatorProfileMenuItemConfiguration $configuration, + array $items) { $controller = $this->getController(); $request = $controller->getRequest(); @@ -893,8 +919,8 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ->addSubmitButton(pht('Make Default')); } - protected function newPanel() { - return PhabricatorProfilePanelConfiguration::initializeNewBuiltin(); + protected function newItem() { + return PhabricatorProfileMenuItemConfiguration::initializeNewBuiltin(); } public function adjustDefault($key) { @@ -902,39 +928,39 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { $request = $controller->getRequest(); $viewer = $request->getViewer(); - $panels = $this->loadPanels(); + $items = $this->loadItems(); - // To adjust the default panel, we first change any existing panels that - // are marked as defaults to "visible", then make the new default panel + // To adjust the default item, we first change any existing items that + // are marked as defaults to "visible", then make the new default item // the default. $default = array(); $visible = array(); - foreach ($panels as $panel) { - $builtin_key = $panel->getBuiltinKey(); - $id = $panel->getID(); + foreach ($items as $item) { + $builtin_key = $item->getBuiltinKey(); + $id = $item->getID(); $is_target = (($builtin_key !== null) && ($builtin_key === $key)) || (($id !== null) && ((int)$id === (int)$key)); if ($is_target) { - if (!$panel->isDefault()) { - $default[] = $panel; + if (!$item->isDefault()) { + $default[] = $item; } } else { - if ($panel->isDefault()) { - $visible[] = $panel; + if ($item->isDefault()) { + $visible[] = $item; } } } $type_visibility = - PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY; - $v_visible = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; - $v_default = PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT; + $v_visible = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE; + $v_default = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DEFAULT; $apply = array( array($v_visible, $visible), @@ -942,20 +968,21 @@ abstract class PhabricatorProfilePanelEngine extends Phobject { ); foreach ($apply as $group) { - list($value, $panels) = $group; - foreach ($panels as $panel) { + list($value, $items) = $group; + foreach ($items as $item) { $xactions = array(); - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) - ->setTransactionType($type_visibility) - ->setNewValue($value); + $xactions[] = + id(new PhabricatorProfileMenuItemConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($value); - $editor = id(new PhabricatorProfilePanelEditor()) + $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) - ->applyTransactions($panel, $xactions); + ->applyTransactions($item, $xactions); } } diff --git a/src/applications/search/profilepanel/PhabricatorApplicationProfilePanel.php b/src/applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php similarity index 70% rename from src/applications/search/profilepanel/PhabricatorApplicationProfilePanel.php rename to src/applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php index f2d53f936d..214819100e 100644 --- a/src/applications/search/profilepanel/PhabricatorApplicationProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php @@ -1,15 +1,15 @@ getApplication($config); if ($app) { return $app->getName(); @@ -29,20 +29,20 @@ final class PhabricatorApplicationProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorDatasourceEditField()) ->setKey('application') ->setLabel(pht('Application')) ->setDatasource(new PhabricatorApplicationDatasource()) - ->setSingleValue($config->getPanelProperty('application')), + ->setSingleValue($config->getMenuItemProperty('application')), ); } private function getApplication( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); - $phid = $config->getPanelProperty('application'); + $phid = $config->getMenuItemProperty('application'); $app = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) ->withPHIDs(array($phid)) @@ -52,7 +52,7 @@ final class PhabricatorApplicationProfilePanel } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $app = $this->getApplication($config); if (!$app) { diff --git a/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php new file mode 100644 index 0000000000..9074b1b117 --- /dev/null +++ b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php @@ -0,0 +1,112 @@ +dashboard = $dashboard; + return $this; + } + + public function getDashboard() { + $dashboard = $this->dashboard; + if (!$dashboard) { + return null; + } else if ($dashboard->isArchived()) { + return null; + } + return $dashboard; + } + + public function willBuildNavigationItems(array $items) { + $viewer = $this->getViewer(); + $dashboard_phids = array(); + foreach ($items as $item) { + $dashboard_phids[] = $item->getMenuItemProperty('dashboardPHID'); + } + + $dashboards = id(new PhabricatorDashboardQuery()) + ->setViewer($viewer) + ->withPHIDs($dashboard_phids) + ->execute(); + + $dashboards = mpull($dashboards, null, 'getPHID'); + foreach ($items as $item) { + $dashboard_phid = $item->getMenuItemProperty('dashboardPHID'); + $dashboard = idx($dashboards, $dashboard_phid, null); + $item->getMenuItem()->attachDashboard($dashboard); + } + } + + public function getDisplayName( + PhabricatorProfileMenuItemConfiguration $config) { + $dashboard = $this->getDashboard(); + if (!$dashboard) { + return pht('(Restricted/Invalid Dashboard)'); + } + if (strlen($this->getName($config))) { + return $this->getName($config); + } else { + return $dashboard->getName(); + } + } + + public function buildEditEngineFields( + PhabricatorProfileMenuItemConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setValue($this->getName($config)), + id(new PhabricatorDatasourceEditField()) + ->setKey('dashboardPHID') + ->setLabel(pht('Dashboard')) + ->setDatasource(new PhabricatorDashboardDatasource()) + ->setSingleValue($config->getMenuItemProperty('dashboardPHID')), + ); + } + + private function getName( + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('name'); + } + + protected function newNavigationMenuItems( + PhabricatorProfileMenuItemConfiguration $config) { + + $dashboard = $this->getDashboard(); + if (!$dashboard) { + return array(); + } + + $icon = $dashboard->getIcon(); + $name = $this->getDisplayName($config); + $href = $dashboard->getViewURI(); + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setIcon($icon); + + return array( + $item, + ); + } + +} diff --git a/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php b/src/applications/search/menuitem/PhabricatorDividerProfileMenuItem.php similarity index 65% rename from src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php rename to src/applications/search/menuitem/PhabricatorDividerProfileMenuItem.php index 1458cac56c..255e0d4b72 100644 --- a/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorDividerProfileMenuItem.php @@ -1,15 +1,15 @@ setValue( @@ -35,7 +35,7 @@ final class PhabricatorDividerProfilePanel } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $item = $this->newItem() ->addClass('phui-divider'); diff --git a/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php b/src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php similarity index 65% rename from src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php rename to src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php index 18654dccd3..5571788cc1 100644 --- a/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php @@ -1,15 +1,15 @@ getLinkName($config); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') @@ -38,24 +38,24 @@ final class PhabricatorLinkProfilePanel id(new PhabricatorIconSetEditField()) ->setKey('icon') ->setLabel(pht('Icon')) - ->setIconSet(new PhabricatorProfilePanelIconSet()) + ->setIconSet(new PhabricatorProfileMenuItemIconSet()) ->setValue($this->getLinkIcon($config)), ); } private function getLinkName( - PhabricatorProfilePanelConfiguration $config) { - return $config->getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('name'); } private function getLinkIcon( - PhabricatorProfilePanelConfiguration $config) { - return $config->getPanelProperty('icon', 'link'); + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('icon', 'link'); } private function getLinkURI( - PhabricatorProfilePanelConfiguration $config) { - return $config->getPanelProperty('uri'); + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('uri'); } private function isValidLinkURI($uri) { @@ -63,7 +63,7 @@ final class PhabricatorLinkProfilePanel } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $icon = $this->getLinkIcon($config); $name = $this->getLinkName($config); @@ -73,7 +73,7 @@ final class PhabricatorLinkProfilePanel $href = '#'; } - $icon_object = id(new PhabricatorProfilePanelIconSet()) + $icon_object = id(new PhabricatorProfileMenuItemIconSet()) ->getIcon($icon); if ($icon_object) { $icon_class = $icon_object->getIcon(); diff --git a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php b/src/applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php similarity index 88% rename from src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php rename to src/applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php index 5a645039ec..f53bc2b0eb 100644 --- a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php @@ -1,15 +1,15 @@ getOptions(); - $name = idx($options, $config->getPanelProperty('source')); + $name = idx($options, $config->getMenuItemProperty('source')); if ($name !== null) { return pht('Motivator: %s', $name); } else { @@ -30,13 +30,13 @@ final class PhabricatorMotivatorProfilePanel } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorInstructionsEditField()) ->setValue( pht( 'Motivate your team with inspirational quotes from great minds. '. - 'This panel shows a new quote every day.')), + 'This menu item shows a new quote every day.')), id(new PhabricatorSelectEditField()) ->setKey('source') ->setLabel(pht('Source')) @@ -51,9 +51,9 @@ final class PhabricatorMotivatorProfilePanel } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { - $source = $config->getPanelProperty('source'); + $source = $config->getMenuItemProperty('source'); switch ($source) { case 'catfacts': diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanel.php b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php similarity index 53% rename from src/applications/search/profilepanel/PhabricatorProfilePanel.php rename to src/applications/search/menuitem/PhabricatorProfileMenuItem.php index 8fcbd3f96a..c47d9afe8e 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php @@ -1,28 +1,30 @@ newNavigationMenuItems($config); } abstract protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config); + PhabricatorProfileMenuItemConfiguration $config); - public function getPanelTypeIcon() { + public function willBuildNavigationItems(array $items) {} + + public function getMenuItemTypeIcon() { return null; } - abstract public function getPanelTypeName(); + abstract public function getMenuItemTypeName(); abstract public function getDisplayName( - PhabricatorProfilePanelConfiguration $config); + PhabricatorProfileMenuItemConfiguration $config); public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array(); } @@ -34,13 +36,13 @@ abstract class PhabricatorProfilePanel extends Phobject { return true; } - public function canHidePanel( - PhabricatorProfilePanelConfiguration $config) { + public function canHideMenuItem( + PhabricatorProfileMenuItemConfiguration $config) { return true; } public function canMakeDefault( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return false; } @@ -53,14 +55,14 @@ abstract class PhabricatorProfilePanel extends Phobject { return $this->viewer; } - final public function getPanelKey() { - return $this->getPhobjectClassConstant('PANELKEY'); + final public function getMenuItemKey() { + return $this->getPhobjectClassConstant('MENUITEMKEY'); } - final public static function getAllPanels() { + final public static function getAllMenuItems() { return id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) - ->setUniqueMethod('getPanelKey') + ->setUniqueMethod('getMenuItemKey') ->execute(); } diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php b/src/applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php similarity index 94% rename from src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php rename to src/applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php index bc3b15a7cf..74333cc087 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php +++ b/src/applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php @@ -1,9 +1,9 @@ project = $project; + return $this; + } + + public function getProject() { + $project = $this->project; + if (!$project) { + return null; + } else if ($project->isArchived()) { + return null; + } + return $project; + } + + public function willBuildNavigationItems(array $items) { + $viewer = $this->getViewer(); + $project_phids = array(); + foreach ($items as $item) { + $project_phids[] = $item->getMenuItemProperty('project'); + } + + $projects = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withPHIDs($project_phids) + ->needImages(true) + ->execute(); + + $projects = mpull($projects, null, 'getPHID'); + foreach ($items as $item) { + $project_phid = $item->getMenuItemProperty('project'); + $project = idx($projects, $project_phid, null); + $item->getMenuItem()->attachProject($project); + } + } + + public function getDisplayName( + PhabricatorProfileMenuItemConfiguration $config) { + $project = $this->getProject(); + if (!$project) { + return pht('(Restricted/Invalid Project)'); + } + if (strlen($this->getName($config))) { + return $this->getName($config); + } else { + return $project->getName(); + } + } + + public function buildEditEngineFields( + PhabricatorProfileMenuItemConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setValue($this->getName($config)), + id(new PhabricatorDatasourceEditField()) + ->setKey('project') + ->setLabel(pht('Project')) + ->setDatasource(new PhabricatorProjectDatasource()) + ->setSingleValue($config->getMenuItemProperty('project')), + ); + } + + private function getName( + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('name'); + } + + protected function newNavigationMenuItems( + PhabricatorProfileMenuItemConfiguration $config) { + + $project = $this->getProject(); + if (!$project) { + return array(); + } + + $picture = $project->getProfileImageURI(); + $name = $this->getDisplayName($config); + $href = $project->getURI(); + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setProfileImage($picture); + + return array( + $item, + ); + } + +} diff --git a/src/applications/search/phidtype/PhabricatorProfilePanelPHIDType.php b/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php similarity index 69% rename from src/applications/search/phidtype/PhabricatorProfilePanelPHIDType.php rename to src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php index e2285e2543..0fbdcaca48 100644 --- a/src/applications/search/phidtype/PhabricatorProfilePanelPHIDType.php +++ b/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php @@ -1,16 +1,16 @@ withPHIDs($phids); } @@ -32,7 +32,7 @@ final class PhabricatorProfilePanelPHIDType foreach ($handles as $phid => $handle) { $config = $objects[$phid]; - $handle->setName(pht('Profile Panel')); + $handle->setName(pht('Profile Menu Item')); } } diff --git a/src/applications/search/query/PhabricatorProfilePanelConfigurationQuery.php b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php similarity index 74% rename from src/applications/search/query/PhabricatorProfilePanelConfigurationQuery.php rename to src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php index 52e12581cf..f8172638c3 100644 --- a/src/applications/search/query/PhabricatorProfilePanelConfigurationQuery.php +++ b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php @@ -1,6 +1,6 @@ $panel) { - $panel_type = idx($panels, $panel->getPanelKey()); - if (!$panel_type) { - $this->didRejectResult($panel); + $items = PhabricatorProfileMenuItem::getAllMenuItems(); + foreach ($page as $key => $item) { + $item_type = idx($items, $item->getMenuItemKey()); + if (!$item_type) { + $this->didRejectResult($item); unset($page[$key]); continue; } - $panel->attachPanel($panel_type); + $item_type = clone $item_type; + $item->attachMenuItem($item_type); } if (!$page) { @@ -82,14 +83,14 @@ final class PhabricatorProfilePanelConfigurationQuery ->execute(); $profiles = mpull($profiles, null, 'getPHID'); - foreach ($page as $key => $panel) { - $profile = idx($profiles, $panel->getProfilePHID()); + foreach ($page as $key => $item) { + $profile = idx($profiles, $item->getProfilePHID()); if (!$profile) { - $this->didRejectResult($panel); + $this->didRejectResult($item); unset($page[$key]); continue; } - $panel->attachProfileObject($profile); + $item->attachProfileObject($profile); } return $page; diff --git a/src/applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php new file mode 100644 index 0000000000..0023660512 --- /dev/null +++ b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php @@ -0,0 +1,10 @@ +setVisibility(self::VISIBILITY_VISIBLE); } - public static function initializeNewPanelConfiguration( + public static function initializeNewItem( $profile_object, - PhabricatorProfilePanel $panel) { + PhabricatorProfileMenuItem $item) { return self::initializeNewBuiltin() ->setProfilePHID($profile_object->getPHID()) - ->setPanelKey($panel->getPanelKey()) - ->attachPanel($panel) + ->setMenuItemKey($item->getMenuItemKey()) + ->attachMenuItem($item) ->attachProfileObject($profile_object); } @@ -41,17 +46,17 @@ final class PhabricatorProfilePanelConfiguration return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( - 'panelProperties' => self::SERIALIZATION_JSON, + 'menuItemProperties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'panelKey' => 'text64', + 'menuItemKey' => 'text64', 'builtinKey' => 'text64?', - 'panelOrder' => 'uint32?', + 'menuItemOrder' => 'uint32?', 'visibility' => 'text32', ), self::CONFIG_KEY_SCHEMA => array( 'key_profile' => array( - 'columns' => array('profilePHID', 'panelOrder'), + 'columns' => array('profilePHID', 'menuItemOrder'), ), ), ) + parent::getConfiguration(); @@ -59,16 +64,16 @@ final class PhabricatorProfilePanelConfiguration public function generatePHID() { return PhabricatorPHID::generateNewPHID( - PhabricatorProfilePanelPHIDType::TYPECONST); + PhabricatorProfileMenuItemPHIDType::TYPECONST); } - public function attachPanel(PhabricatorProfilePanel $panel) { - $this->panel = $panel; + public function attachMenuItem(PhabricatorProfileMenuItem $item) { + $this->menuItem = $item; return $this; } - public function getPanel() { - return $this->assertAttached($this->panel); + public function getMenuItem() { + return $this->assertAttached($this->menuItem); } public function attachProfileObject($profile_object) { @@ -80,41 +85,45 @@ final class PhabricatorProfilePanelConfiguration return $this->assertAttached($this->profileObject); } - public function setPanelProperty($key, $value) { - $this->panelProperties[$key] = $value; + public function setMenuItemProperty($key, $value) { + $this->menuItemProperties[$key] = $value; return $this; } - public function getPanelProperty($key, $default = null) { - return idx($this->panelProperties, $key, $default); + public function getMenuItemProperty($key, $default = null) { + return idx($this->menuItemProperties, $key, $default); } public function buildNavigationMenuItems() { - return $this->getPanel()->buildNavigationMenuItems($this); + return $this->getMenuItem()->buildNavigationMenuItems($this); } - public function getPanelTypeName() { - return $this->getPanel()->getPanelTypeName(); + public function getMenuItemTypeName() { + return $this->getMenuItem()->getMenuItemTypeName(); } public function getDisplayName() { - return $this->getPanel()->getDisplayName($this); + return $this->getMenuItem()->getDisplayName($this); } public function canMakeDefault() { - return $this->getPanel()->canMakeDefault($this); + return $this->getMenuItem()->canMakeDefault($this); } - public function canHidePanel() { - return $this->getPanel()->canHidePanel($this); + public function canHideMenuItem() { + return $this->getMenuItem()->canHideMenuItem($this); } public function shouldEnableForObject($object) { - return $this->getPanel()->shouldEnableForObject($object); + return $this->getMenuItem()->shouldEnableForObject($object); + } + + public function willBuildNavigationItems(array $items) { + return $this->getMenuItem()->willBuildNavigationItems($items); } public function getSortKey() { - $order = $this->getPanelOrder(); + $order = $this->getMenuItemOrder(); if ($order === null) { $order = 'Z'; } else { @@ -128,7 +137,7 @@ final class PhabricatorProfilePanelConfiguration } public function isDisabled() { - if (!$this->canHidePanel()) { + if (!$this->canHideMenuItem()) { return false; } return ($this->getVisibility() === self::VISIBILITY_DISABLED); @@ -179,7 +188,7 @@ final class PhabricatorProfilePanelConfiguration public function getApplicationTransactionEditor() { - return new PhabricatorProfilePanelEditor(); + return new PhabricatorProfileMenuEditor(); } public function getApplicationTransactionObject() { @@ -187,7 +196,7 @@ final class PhabricatorProfilePanelConfiguration } public function getApplicationTransactionTemplate() { - return new PhabricatorProfilePanelConfigurationTransaction(); + return new PhabricatorProfileMenuItemConfigurationTransaction(); } public function willRenderTimeline( diff --git a/src/applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php b/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php similarity index 59% rename from src/applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php rename to src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php index 28181cb217..b1d30a5b9d 100644 --- a/src/applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php +++ b/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php @@ -1,6 +1,6 @@ buildEdgeSchemata(new PhabricatorProfilePanelConfiguration()); + $this->buildEdgeSchemata(new PhabricatorProfileMenuItemConfiguration()); $this->buildRawSchema( 'search', diff --git a/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php b/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php index d12db30f83..ac950eade1 100644 --- a/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php +++ b/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php @@ -148,7 +148,8 @@ final class PhabricatorHomePreferencesSettingsPanel $list = id(new PHUIObjectItemListView()) ->setViewer($viewer) - ->setID($list_id); + ->setID($list_id) + ->setDrag(true); Javelin::initBehavior( 'reorder-applications', @@ -170,7 +171,6 @@ final class PhabricatorHomePreferencesSettingsPanel $item = id(new PHUIObjectItemView()) ->setHeader($application->getName()) ->setImageIcon($icon) - ->addAttribute($application->getShortDescription()) ->setGrippable(true); $item->addAction( diff --git a/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php b/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php index a0a6cbf7be..ac0d3896cc 100644 --- a/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php +++ b/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php @@ -5,6 +5,10 @@ final class PhabricatorSubscriptionsEditEngineExtension const EXTENSIONKEY = 'subscriptions.subscribers'; + const EDITKEY_ADD = 'subscribers.add'; + const EDITKEY_SET = 'subscribers.set'; + const EDITKEY_REMOVE = 'subscribers.remove'; + public function getExtensionPriority() { return 750; } @@ -52,14 +56,14 @@ final class PhabricatorSubscriptionsEditEngineExtension $subscribers_field->setViewer($engine->getViewer()); - $edit_add = $subscribers_field->getConduitEditType('subscribers.add') + $edit_add = $subscribers_field->getConduitEditType(self::EDITKEY_ADD) ->setConduitDescription(pht('Add subscribers.')); - $edit_set = $subscribers_field->getConduitEditType('subscribers.set') + $edit_set = $subscribers_field->getConduitEditType(self::EDITKEY_SET) ->setConduitDescription( pht('Set subscribers, overwriting current value.')); - $edit_rem = $subscribers_field->getConduitEditType('subscribers.remove') + $edit_rem = $subscribers_field->getConduitEditType(self::EDITKEY_REMOVE) ->setConduitDescription(pht('Remove subscribers.')); return array( diff --git a/src/applications/transactions/editfield/PhabricatorCommentEditField.php b/src/applications/transactions/editfield/PhabricatorCommentEditField.php index 5d9c2b54da..f04002ed92 100644 --- a/src/applications/transactions/editfield/PhabricatorCommentEditField.php +++ b/src/applications/transactions/editfield/PhabricatorCommentEditField.php @@ -3,6 +3,17 @@ final class PhabricatorCommentEditField extends PhabricatorEditField { + private $isWebOnly; + + public function setIsWebOnly($is_web_only) { + $this->isWebOnly = $is_web_only; + return $this; + } + + public function getIsWebOnly() { + return $this->isWebOnly; + } + protected function newControl() { return new PhabricatorRemarkupControl(); } @@ -12,15 +23,23 @@ final class PhabricatorCommentEditField } protected function newConduitParameterType() { - return new ConduitStringParameterType(); + if ($this->getIsWebOnly()) { + return null; + } else { + return new ConduitStringParameterType(); + } } public function shouldGenerateTransactionsFromSubmit() { - return false; + return !$this->isPrimaryCommentField(); } public function shouldGenerateTransactionsFromComment() { - return true; + return $this->isPrimaryCommentField(); + } + + private function isPrimaryCommentField() { + return ($this->getKey() === 'comment'); } } diff --git a/src/applications/transactions/editfield/PhabricatorDividerEditField.php b/src/applications/transactions/editfield/PhabricatorDividerEditField.php new file mode 100644 index 0000000000..553c5256bc --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorDividerEditField.php @@ -0,0 +1,18 @@ +setValue($this->getValue()); + } + + protected function newHTTPParameterType() { + return null; + } + + protected function newConduitParameterType() { + return null; + } + +} diff --git a/src/applications/transactions/edittype/PhabricatorEditType.php b/src/applications/transactions/edittype/PhabricatorEditType.php index 298238aeb1..1451ec2c04 100644 --- a/src/applications/transactions/edittype/PhabricatorEditType.php +++ b/src/applications/transactions/edittype/PhabricatorEditType.php @@ -107,6 +107,13 @@ abstract class PhabricatorEditType extends Phobject { public function getConduitType() { $parameter_type = $this->getConduitParameterType(); + if (!$parameter_type) { + throw new Exception( + pht( + 'Edit type (with key "%s") is missing a Conduit parameter type.', + $this->getEditType())); + } + return $parameter_type->getTypeName(); } diff --git a/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php b/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php index a0a303bdc7..7eb2aee037 100644 --- a/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php +++ b/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php @@ -4,6 +4,7 @@ final class PhabricatorCommentEditEngineExtension extends PhabricatorEditEngineExtension { const EXTENSIONKEY = 'transactions.comment'; + const EDITKEY = 'comment'; public function getExtensionPriority() { return 9000; @@ -39,7 +40,7 @@ final class PhabricatorCommentEditEngineExtension $comment_type = PhabricatorTransactions::TYPE_COMMENT; $comment_field = id(new PhabricatorCommentEditField()) - ->setKey('comment') + ->setKey(self::EDITKEY) ->setLabel(pht('Comments')) ->setAliases(array('comments')) ->setIsHidden(true) diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index cc583d34c2..8157166bb4 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -960,9 +960,18 @@ abstract class PhabricatorApplicationTransaction if ($field) { return $field->getApplicationTransactionTitle($this); } else { - return pht( - '%s edited a custom field.', - $this->renderHandleLink($author_phid)); + $developer_mode = 'phabricator.developer-mode'; + $is_developer = PhabricatorEnv::getEnvConfig($developer_mode); + if ($is_developer) { + return pht( + '%s edited a custom field (with key "%s").', + $this->renderHandleLink($author_phid), + $this->getMetadata('customfield:key')); + } else { + return pht( + '%s edited a custom field.', + $this->renderHandleLink($author_phid)); + } } case PhabricatorTransactions::TYPE_TOKEN: diff --git a/src/applications/transactions/storage/PhabricatorModularTransaction.php b/src/applications/transactions/storage/PhabricatorModularTransaction.php index e62d550bb9..035a2585fd 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransaction.php +++ b/src/applications/transactions/storage/PhabricatorModularTransaction.php @@ -1,5 +1,9 @@ getTransactionType(); if (empty($types[$key])) { - $type = new PhabricatorCoreVoidTransaction(); + $type = $this->newFallbackModularTransactionType(); } else { $type = clone $types[$key]; } @@ -52,6 +56,10 @@ abstract class PhabricatorModularTransaction return $type; } + protected function newFallbackModularTransactionType() { + return new PhabricatorCoreVoidTransaction(); + } + final public function generateOldValue($object) { return $this->getTransactionImplementation()->generateOldValue($object); } @@ -76,7 +84,7 @@ abstract class PhabricatorModularTransaction ->applyExternalEffects($object); } - final public function shouldHide() { + /* final */ public function shouldHide() { if ($this->getTransactionImplementation()->shouldHide()) { return true; } @@ -84,7 +92,7 @@ abstract class PhabricatorModularTransaction return parent::shouldHide(); } - final public function getIcon() { + /* final */ public function getIcon() { $icon = $this->getTransactionImplementation()->getIcon(); if ($icon !== null) { return $icon; @@ -93,7 +101,7 @@ abstract class PhabricatorModularTransaction return parent::getIcon(); } - final public function getTitle() { + /* final */ public function getTitle() { $title = $this->getTransactionImplementation()->getTitle(); if ($title !== null) { return $title; @@ -111,7 +119,7 @@ abstract class PhabricatorModularTransaction return $title; } - final public function getTitleForFeed() { + /* final */ public function getTitleForFeed() { $title = $this->getTransactionImplementation()->getTitleForFeed(); if ($title !== null) { return $title; @@ -120,7 +128,7 @@ abstract class PhabricatorModularTransaction return parent::getTitleForFeed(); } - final public function getColor() { + /* final */ public function getColor() { $color = $this->getTransactionImplementation()->getColor(); if ($color !== null) { return $color; diff --git a/src/applications/transactions/storage/PhabricatorModularTransactionType.php b/src/applications/transactions/storage/PhabricatorModularTransactionType.php index 84bc4a07ec..2606264778 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php +++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php @@ -68,7 +68,7 @@ abstract class PhabricatorModularTransactionType } public function newChangeDetailView() { - throw new PhutilMethodNotImplementedException(); + return null; } public function getMailDiffSectionHeader() { @@ -227,7 +227,7 @@ abstract class PhabricatorModularTransactionType // server's settings, or the user may later refer back to it after // changing timezones. - if ($this->isTextMode()) { + if ($this->isRenderingTargetExternal()) { $offset = $viewer->getTimeZoneOffsetInHours(); if ($offset >= 0) { $display = pht('%s (UTC+%d)', $display, $offset); @@ -277,7 +277,17 @@ abstract class PhabricatorModularTransactionType return !strlen($value); } - private function isTextMode() { + /** + * When rendering to external targets (Email/Asana/etc), we need to include + * more information that users can't obtain later. + */ + final protected function isRenderingTargetExternal() { + // Right now, this is our best proxy for this: + return $this->isTextMode(); + // "TARGET_TEXT" means "EMail" and "TARGET_HTML" means "Web". + } + + final protected function isTextMode() { $target = $this->getStorage()->getRenderingTarget(); return ($target == PhabricatorApplicationTransaction::TARGET_TEXT); } diff --git a/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php b/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php new file mode 100644 index 0000000000..725716bdaf --- /dev/null +++ b/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php @@ -0,0 +1,39 @@ +executeQuery($query); + $results = array(); + foreach ($forms as $form) { + + $result = id(new PhabricatorTypeaheadResult()) + ->setName($form->getName()) + ->setPHID($form->getPHID()); + + if ($form->getIsDisabled()) { + $result->setClosed(pht('Archived')); + } + + $results[] = $result; + } + + return $this->filterResultsAgainstTokens($results); + } + +} diff --git a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php index 2c5556cb4a..6956561490 100644 --- a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php +++ b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php @@ -396,13 +396,16 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject { if (!self::isFunctionToken($token)) { $results[] = $token; } else { - $evaluate[] = $token; + // Put a placeholder in the result list so that we retain token order + // when possible. We'll overwrite this below. + $results[] = null; + $evaluate[last_key($results)] = $token; } } $results = $this->evaluateValues($results); - foreach ($evaluate as $function) { + foreach ($evaluate as $result_key => $function) { $function = self::parseFunction($function); if (!$function) { throw new PhabricatorTypeaheadInvalidTokenException(); @@ -411,11 +414,23 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject { $name = $function['name']; $argv = $function['argv']; - foreach ($this->evaluateFunction($name, array($argv)) as $phid) { - $results[] = $phid; + $evaluated_tokens = $this->evaluateFunction($name, array($argv)); + if (!$evaluated_tokens) { + unset($results[$result_key]); + } else { + $is_first = true; + foreach ($evaluated_tokens as $phid) { + if ($is_first) { + $results[$result_key] = $phid; + $is_first = false; + } else { + $results[] = $phid; + } + } } } + $results = array_values($results); $results = $this->didEvaluateTokens($results); return $results; diff --git a/src/docs/contributor/version.diviner b/src/docs/contributor/version.diviner index 81b1c845ef..a13c12d86f 100644 --- a/src/docs/contributor/version.diviner +++ b/src/docs/contributor/version.diviner @@ -49,6 +49,29 @@ hash from the output. This may be useful if you're encountering an issue which prevents you from reaching the version reporting screen. +Running a Fork? +=============== + +If you've forked Phabricator and have local commits, please make sure you are +reporting upstream commit hashes, not local commit hashes. The UI will attempt +to figure out where you branched from, but it may not be able to in all cases. + +If you report local commit hashes instead of upstream commit hashes we can not +go look up the commit hashes to figure out which changes they correspond to, so +we can not use that information to determine out how old your install is or +which patches you are missing. + +In most cases, you can find the upstream commit you've branched from like this: + +``` +$ git merge-base HEAD origin/master +```` + +Note that if you report a bug and have local commits, we will almost always ask +you to reproduce the issue against a clean copy of Phabricator before we +continue. You can get help faster by doing this //before// reporting an issue. + + Next Steps ========== diff --git a/src/docs/user/configuration/configuring_file_storage.diviner b/src/docs/user/configuration/configuring_file_storage.diviner index 64942b493e..d6abb22c13 100644 --- a/src/docs/user/configuration/configuring_file_storage.diviner +++ b/src/docs/user/configuration/configuring_file_storage.diviner @@ -133,15 +133,15 @@ Engine: MySQL MySQL storage is configured by default, for files up to (just under) 1MB. You can configure it with these keys: - - `storage.mysql-engine.max-size`: Change the filesize limit. Set to 0 - to disable. + - `storage.mysql-engine.max-size`: Change the filesize limit, in bytes. Set + to 0 to disable. For most installs, it is reasonable to leave this engine as-is and let small files (like thumbnails and profile images) be stored in MySQL, which is usually the lowest-latency filestore, even if you configure another storage engine. -To support large files, increase this limit to at least **8MB**. This will -activate chunk storage in MySQL. +To support large files, increase this limit to at least `8388608` (8MB). +This will activate chunk storage in MySQL. Engine: Local Disk ================== diff --git a/src/docs/user/userguide/drydock_blueprints.diviner b/src/docs/user/userguide/drydock_blueprints.diviner index 46c8a27f5e..21c4342fa6 100644 --- a/src/docs/user/userguide/drydock_blueprints.diviner +++ b/src/docs/user/userguide/drydock_blueprints.diviner @@ -14,7 +14,7 @@ Drydock builds and manages various hardware and software resources, like hosts and repository working copies. Other applications can use these resources to perform useful work (like running tests or builds). -For additional disussion of Drydock, see @{article:Drydock User Guide}. +For additional discussion of Drydock, see @{article:Drydock User Guide}. Drydock can't create any resources until you configure it. You'll configure Drydock by creating **Blueprints**. Each blueprint tells Drydock how to build diff --git a/src/docs/user/userguide/profile_menu.diviner b/src/docs/user/userguide/profile_menu.diviner index bd278b2702..2b4ffc4be8 100644 --- a/src/docs/user/userguide/profile_menu.diviner +++ b/src/docs/user/userguide/profile_menu.diviner @@ -146,4 +146,4 @@ Writing New Item Types IMPORTANT: This feature is not stable, and the API is subject to change. -To add new types of items, subclass @{class:PhabricatorProfilePanel}. +To add new types of items, subclass @{class:PhabricatorProfileMenuItem}. diff --git a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php index 8d448f624b..ffdb157d8e 100644 --- a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php +++ b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php @@ -37,6 +37,10 @@ final class PhabricatorCustomFieldEditField } protected function buildControl() { + if ($this->getIsConduitOnly()) { + return null; + } + $field = $this->getCustomField(); $clone = clone $field; @@ -47,14 +51,13 @@ final class PhabricatorCustomFieldEditField } protected function newEditType() { - $conduit_type = $this->newConduitParameterType(); - if (!$conduit_type) { - return null; - } - $type = id(new PhabricatorCustomFieldEditType()) - ->setCustomField($this->getCustomField()) - ->setConduitParameterType($conduit_type); + ->setCustomField($this->getCustomField()); + + $conduit_type = $this->newConduitParameterType(); + if ($conduit_type) { + $type->setConduitParameterType($conduit_type); + } return $type; } diff --git a/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php b/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php index b9427905b8..3edc898cb7 100644 --- a/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php +++ b/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php @@ -31,7 +31,7 @@ final class PhabricatorCustomFieldEditEngineExtension $field_list = PhabricatorCustomField::getObjectFields( $object, - PhabricatorCustomField::ROLE_EDIT); + PhabricatorCustomField::ROLE_EDITENGINE); $field_list->setViewer($viewer); diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php index 7791700a14..8f88c1469e 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -33,6 +33,7 @@ abstract class PhabricatorCustomField extends Phobject { const ROLE_GLOBALSEARCH = 'GlobalSearch'; const ROLE_CONDUIT = 'conduit'; const ROLE_HERALD = 'herald'; + const ROLE_EDITENGINE = 'EditEngine'; /* -( Building Applications with Custom Fields )--------------------------- */ @@ -292,6 +293,9 @@ abstract class PhabricatorCustomField extends Phobject { return $this->shouldAppearInTransactionMail(); case self::ROLE_HERALD: return $this->shouldAppearInHerald(); + case self::ROLE_EDITENGINE: + return $this->shouldAppearInEditView() || + $this->shouldAppearInEditEngine(); case self::ROLE_DEFAULT: return true; default: @@ -1120,12 +1124,19 @@ abstract class PhabricatorCustomField extends Phobject { return $this->proxy->newStandardEditField(); } + if (!$this->shouldAppearInEditView()) { + $conduit_only = true; + } else { + $conduit_only = false; + } + return $this->newEditField() ->setKey($this->getFieldKey()) ->setEditTypeKey($this->getModernFieldKey()) ->setLabel($this->getFieldName()) ->setDescription($this->getFieldDescription()) ->setTransactionType($this->getApplicationTransactionType()) + ->setIsConduitOnly($conduit_only) ->setValue($this->getNewValueForApplicationTransactions()); } @@ -1146,6 +1157,16 @@ abstract class PhabricatorCustomField extends Phobject { return false; } + /** + * @task edit + */ + public function shouldAppearInEditEngine() { + if ($this->proxy) { + return $this->proxy->shouldAppearInEditEngine(); + } + return false; + } + /** * @task edit diff --git a/src/infrastructure/storage/lisk/LiskDAO.php b/src/infrastructure/storage/lisk/LiskDAO.php index 71cfba3d54..0527c3cf1e 100644 --- a/src/infrastructure/storage/lisk/LiskDAO.php +++ b/src/infrastructure/storage/lisk/LiskDAO.php @@ -1780,10 +1780,13 @@ abstract class LiskDAO extends Phobject { * @task util */ public function __set($name, $value) { - phlog( - pht( - 'Wrote to undeclared property %s.', - get_class($this).'::$'.$name)); + // Hack for policy system hints, see PhabricatorPolicyRule for notes. + if ($name != '_hashKey') { + phlog( + pht( + 'Wrote to undeclared property %s.', + get_class($this).'::$'.$name)); + } $this->$name = $value; } diff --git a/src/view/layout/PhabricatorActionView.php b/src/view/layout/PhabricatorActionView.php index 493f8c3dbd..8788529945 100644 --- a/src/view/layout/PhabricatorActionView.php +++ b/src/view/layout/PhabricatorActionView.php @@ -271,6 +271,10 @@ final class PhabricatorActionView extends AphrontView { $classes[] = 'phabricator-action-view-submenu'; } + if ($this->getHref()) { + $classes[] = 'phabricator-action-view-href'; + } + $style = array(); if ($this->hidden) { diff --git a/src/view/phui/PHUIObjectItemListView.php b/src/view/phui/PHUIObjectItemListView.php index 6c81053f0a..53e86382c2 100644 --- a/src/view/phui/PHUIObjectItemListView.php +++ b/src/view/phui/PHUIObjectItemListView.php @@ -9,8 +9,9 @@ final class PHUIObjectItemListView extends AphrontTagView { private $flush; private $simple; private $big; + private $drag; private $allowEmptyList; - private $itemClass = 'phui-object-item-standard'; + private $itemClass = 'phui-oi-standard'; public function setAllowEmptyList($allow_empty_list) { $this->allowEmptyList = $allow_empty_list; @@ -46,6 +47,12 @@ final class PHUIObjectItemListView extends AphrontTagView { return $this; } + public function setDrag($drag) { + $this->drag = $drag; + $this->setItemClass('phui-oi-drag'); + return $this; + } + public function setNoDataString($no_data_string) { $this->noDataString = $no_data_string; return $this; @@ -67,16 +74,26 @@ final class PHUIObjectItemListView extends AphrontTagView { protected function getTagAttributes() { $classes = array(); + $classes[] = 'phui-oi-list-view'; - $classes[] = 'phui-object-item-list-view'; if ($this->flush) { - $classes[] = 'phui-object-list-flush'; + $classes[] = 'phui-oi-list-flush'; + require_celerity_resource('phui-oi-flush-ui-css'); } + if ($this->simple) { - $classes[] = 'phui-object-list-simple'; + $classes[] = 'phui-oi-list-simple'; + require_celerity_resource('phui-oi-simple-ui-css'); } + if ($this->big) { - $classes[] = 'phui-object-list-big'; + $classes[] = 'phui-oi-list-big'; + require_celerity_resource('phui-oi-big-ui-css'); + } + + if ($this->drag) { + $classes[] = 'phui-oi-list-drag'; + require_celerity_resource('phui-oi-drag-ui-css'); } return array( @@ -86,14 +103,15 @@ final class PHUIObjectItemListView extends AphrontTagView { protected function getTagContent() { $viewer = $this->getUser(); - require_celerity_resource('phui-object-item-list-view-css'); + require_celerity_resource('phui-oi-list-view-css'); + require_celerity_resource('phui-oi-color-css'); $header = null; if (strlen($this->header)) { $header = phutil_tag( 'h1', array( - 'class' => 'phui-object-item-list-header', + 'class' => 'phui-oi-list-header', ), $this->header); } @@ -120,7 +138,7 @@ final class PHUIObjectItemListView extends AphrontTagView { $items = phutil_tag( 'li', array( - 'class' => 'phui-object-item-empty', + 'class' => 'phui-oi-empty', ), $string); diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php index 80fe6fb4d0..6d193081d2 100644 --- a/src/view/phui/PHUIObjectItemView.php +++ b/src/view/phui/PHUIObjectItemView.php @@ -229,45 +229,45 @@ final class PHUIObjectItemView extends AphrontTagView { protected function getTagAttributes() { $item_classes = array(); - $item_classes[] = 'phui-object-item'; + $item_classes[] = 'phui-oi'; if ($this->icons) { - $item_classes[] = 'phui-object-item-with-icons'; + $item_classes[] = 'phui-oi-with-icons'; } if ($this->attributes) { - $item_classes[] = 'phui-object-item-with-attrs'; + $item_classes[] = 'phui-oi-with-attrs'; } if ($this->handleIcons) { - $item_classes[] = 'phui-object-item-with-handle-icons'; + $item_classes[] = 'phui-oi-with-handle-icons'; } if ($this->barColor) { - $item_classes[] = 'phui-object-item-bar-color-'.$this->barColor; + $item_classes[] = 'phui-oi-bar-color-'.$this->barColor; } else { - $item_classes[] = 'phui-object-item-no-bar'; + $item_classes[] = 'phui-oi-no-bar'; } if ($this->actions) { $n = count($this->actions); - $item_classes[] = 'phui-object-item-with-actions'; - $item_classes[] = 'phui-object-item-with-'.$n.'-actions'; + $item_classes[] = 'phui-oi-with-actions'; + $item_classes[] = 'phui-oi-with-'.$n.'-actions'; } if ($this->disabled) { - $item_classes[] = 'phui-object-item-disabled'; + $item_classes[] = 'phui-oi-disabled'; } switch ($this->effect) { case 'highlighted': - $item_classes[] = 'phui-object-item-highlighted'; + $item_classes[] = 'phui-oi-highlighted'; break; case 'selected': - $item_classes[] = 'phui-object-item-selected'; + $item_classes[] = 'phui-oi-selected'; break; case 'visited': - $item_classes[] = 'phui-object-item-visited'; + $item_classes[] = 'phui-oi-visited'; break; case null: break; @@ -276,15 +276,15 @@ final class PHUIObjectItemView extends AphrontTagView { } if ($this->getGrippable()) { - $item_classes[] = 'phui-object-item-grippable'; + $item_classes[] = 'phui-oi-grippable'; } if ($this->getImageURI()) { - $item_classes[] = 'phui-object-item-with-image'; + $item_classes[] = 'phui-oi-with-image'; } if ($this->getImageIcon()) { - $item_classes[] = 'phui-object-item-with-image-icon'; + $item_classes[] = 'phui-oi-with-image-icon'; } return array( @@ -296,7 +296,7 @@ final class PHUIObjectItemView extends AphrontTagView { $viewer = $this->getUser(); $content_classes = array(); - $content_classes[] = 'phui-object-item-content'; + $content_classes[] = 'phui-oi-content'; $header_name = array(); @@ -311,7 +311,7 @@ final class PHUIObjectItemView extends AphrontTagView { phutil_tag( 'span', array( - 'class' => 'phui-object-item-objname', + 'class' => 'phui-oi-objname', ), $this->objectName), ' ', @@ -329,7 +329,7 @@ final class PHUIObjectItemView extends AphrontTagView { $this->href ? 'a' : 'div', array( 'href' => $this->href, - 'class' => 'phui-object-item-link', + 'class' => 'phui-oi-link', 'title' => $title_text, ), $this->header); @@ -340,7 +340,7 @@ final class PHUIObjectItemView extends AphrontTagView { $header = phutil_tag( 'div', array( - 'class' => 'phui-object-item-name', + 'class' => 'phui-oi-name', ), javelin_tag( 'span', @@ -360,7 +360,7 @@ final class PHUIObjectItemView extends AphrontTagView { $icon = $spec['icon']; $icon = id(new PHUIIconView()) ->setIcon($icon) - ->addClass('phui-object-item-icon-image'); + ->addClass('phui-oi-icon-image'); if (isset($spec['attributes']['tip'])) { $sigil = 'has-tooltip'; @@ -375,7 +375,7 @@ final class PHUIObjectItemView extends AphrontTagView { $label = phutil_tag( 'span', array( - 'class' => 'phui-object-item-icon-label', + 'class' => 'phui-oi-icon-label', ), $spec['label']); @@ -389,7 +389,7 @@ final class PHUIObjectItemView extends AphrontTagView { } $classes = array(); - $classes[] = 'phui-object-item-icon'; + $classes[] = 'phui-oi-icon'; if (isset($spec['attributes']['class'])) { $classes[] = $spec['attributes']['class']; } @@ -405,7 +405,7 @@ final class PHUIObjectItemView extends AphrontTagView { $icons[] = phutil_tag( 'ul', array( - 'class' => 'phui-object-item-icons', + 'class' => 'phui-oi-icons', ), $icon_list); } @@ -420,7 +420,7 @@ final class PHUIObjectItemView extends AphrontTagView { $handle_bar = phutil_tag( 'li', array( - 'class' => 'phui-object-item-handle-icons', + 'class' => 'phui-oi-handle-icons', ), $handle_bar); } @@ -431,14 +431,14 @@ final class PHUIObjectItemView extends AphrontTagView { $bylines[] = phutil_tag( 'div', array( - 'class' => 'phui-object-item-byline', + 'class' => 'phui-oi-byline', ), $byline); } $bylines = phutil_tag( 'div', array( - 'class' => 'phui-object-item-bylines', + 'class' => 'phui-oi-bylines', ), $bylines); } @@ -448,7 +448,7 @@ final class PHUIObjectItemView extends AphrontTagView { $subhead = phutil_tag( 'div', array( - 'class' => 'phui-object-item-subhead', + 'class' => 'phui-oi-subhead', ), $this->subhead); } @@ -468,7 +468,7 @@ final class PHUIObjectItemView extends AphrontTagView { $spacer = phutil_tag( 'span', array( - 'class' => 'phui-object-item-attribute-spacer', + 'class' => 'phui-oi-attribute-spacer', ), "\xC2\xB7"); $first = true; @@ -476,7 +476,7 @@ final class PHUIObjectItemView extends AphrontTagView { $attrs[] = phutil_tag( 'li', array( - 'class' => 'phui-object-item-attribute', + 'class' => 'phui-oi-attribute', ), array( ($first ? null : $spacer), @@ -488,7 +488,7 @@ final class PHUIObjectItemView extends AphrontTagView { $attrs = phutil_tag( 'ul', array( - 'class' => 'phui-object-item-attributes', + 'class' => 'phui-oi-attributes', ), array( $handle_bar, @@ -507,7 +507,7 @@ final class PHUIObjectItemView extends AphrontTagView { $grippable = phutil_tag( 'div', array( - 'class' => 'phui-object-item-grip', + 'class' => 'phui-oi-grip', ), ''); } @@ -528,7 +528,7 @@ final class PHUIObjectItemView extends AphrontTagView { $image = phutil_tag( 'div', array( - 'class' => 'phui-object-item-image', + 'class' => 'phui-oi-image', 'style' => 'background-image: url('.$this->getImageURI().')', ), ''); @@ -536,7 +536,7 @@ final class PHUIObjectItemView extends AphrontTagView { $image = phutil_tag( 'div', array( - 'class' => 'phui-object-item-image-icon', + 'class' => 'phui-oi-image-icon', ), $this->getImageIcon()); } @@ -556,7 +556,7 @@ final class PHUIObjectItemView extends AphrontTagView { $column0 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col0', + 'class' => 'phui-oi-col0', ), $status); } @@ -565,7 +565,7 @@ final class PHUIObjectItemView extends AphrontTagView { $column0 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col0 phui-object-item-badge', + 'class' => 'phui-oi-col0 phui-oi-badge', ), $this->badge); } @@ -574,7 +574,7 @@ final class PHUIObjectItemView extends AphrontTagView { $countdown = phutil_tag( 'div', array( - 'class' => 'phui-object-item-countdown-number', + 'class' => 'phui-oi-countdown-number', ), array( phutil_tag_div('', $this->countdownNum), @@ -583,7 +583,7 @@ final class PHUIObjectItemView extends AphrontTagView { $column0 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col0 phui-object-item-countdown', + 'class' => 'phui-oi-col0 phui-oi-countdown', ), $countdown); } @@ -591,7 +591,7 @@ final class PHUIObjectItemView extends AphrontTagView { $column1 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col1', + 'class' => 'phui-oi-col1', ), array( $header, @@ -603,7 +603,7 @@ final class PHUIObjectItemView extends AphrontTagView { $column2 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col2', + 'class' => 'phui-oi-col2', ), array( $icons, @@ -615,7 +615,7 @@ final class PHUIObjectItemView extends AphrontTagView { $column2 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col2 phui-object-item-launch-button', + 'class' => 'phui-oi-col2 phui-oi-launch-button', ), array( $this->launchButton, @@ -625,10 +625,10 @@ final class PHUIObjectItemView extends AphrontTagView { $table = phutil_tag( 'div', array( - 'class' => 'phui-object-item-table', + 'class' => 'phui-oi-table', ), phutil_tag_div( - 'phui-object-item-table-row', + 'phui-oi-table-row', array( $column0, $column1, @@ -638,7 +638,7 @@ final class PHUIObjectItemView extends AphrontTagView { $box = phutil_tag( 'div', array( - 'class' => 'phui-object-item-content-box', + 'class' => 'phui-oi-content-box', ), array( $grippable, @@ -656,7 +656,7 @@ final class PHUIObjectItemView extends AphrontTagView { $actions = phutil_tag( 'ul', array( - 'class' => 'phui-object-item-actions', + 'class' => 'phui-oi-actions', ), $actions); } @@ -664,7 +664,7 @@ final class PHUIObjectItemView extends AphrontTagView { $frame_content = phutil_tag( 'div', array( - 'class' => 'phui-object-item-frame-content', + 'class' => 'phui-oi-frame-content', ), array( $actions, @@ -678,13 +678,13 @@ final class PHUIObjectItemView extends AphrontTagView { 'img', array( 'src' => $this->coverImage, - 'class' => 'phui-object-item-cover-image', + 'class' => 'phui-oi-cover-image', )); $frame_cover = phutil_tag( 'div', array( - 'class' => 'phui-object-item-frame-cover', + 'class' => 'phui-oi-frame-cover', ), $cover_image); } @@ -692,7 +692,7 @@ final class PHUIObjectItemView extends AphrontTagView { $frame = phutil_tag( 'div', array( - 'class' => 'phui-object-item-frame', + 'class' => 'phui-oi-frame', ), array( $frame_cover, @@ -709,7 +709,7 @@ final class PHUIObjectItemView extends AphrontTagView { ->setIcon($icon); $options = array( - 'class' => 'phui-object-item-status-icon', + 'class' => 'phui-oi-status-icon', ); if (strlen($label)) { @@ -725,7 +725,7 @@ final class PHUIObjectItemView extends AphrontTagView { Javelin::initBehavior('phabricator-tooltips'); $options = array( - 'class' => 'phui-object-item-handle-icon', + 'class' => 'phui-oi-handle-icon', 'style' => 'background-image: url('.$handle->getImageURI().')', ); diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php index 87fee5cfa6..a5834befd3 100644 --- a/src/view/phui/PHUITimelineEventView.php +++ b/src/view/phui/PHUITimelineEventView.php @@ -347,6 +347,17 @@ final class PHUITimelineEventView extends AphrontView { $group_children = array(); foreach ($events as $event) { if ($event->shouldRenderEventTitle()) { + + // Render the group anchor here, outside the title box. If we render + // it inside the title box it ends up completely hidden and Chrome 55 + // refuses to jump to it. See T11997 for discussion. + + if ($extra && $this->anchor) { + $group_titles[] = id(new PhabricatorAnchorView()) + ->setAnchorName($this->anchor) + ->render(); + } + $group_titles[] = $event->renderEventTitle( $force_icon, $has_menu, @@ -533,12 +544,7 @@ final class PHUITimelineEventView extends AphrontView { Javelin::initBehavior('phabricator-watch-anchor'); Javelin::initBehavior('phabricator-tooltips'); - $anchor = id(new PhabricatorAnchorView()) - ->setAnchorName($this->anchor) - ->render(); - $date = array( - $anchor, javelin_tag( 'a', array( @@ -546,7 +552,7 @@ final class PHUITimelineEventView extends AphrontView { 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $content_source, - ), + ), ), $date), ); diff --git a/webroot/rsrc/css/aphront/dialog-view.css b/webroot/rsrc/css/aphront/dialog-view.css index 9cf56394df..3b2de1cee6 100644 --- a/webroot/rsrc/css/aphront/dialog-view.css +++ b/webroot/rsrc/css/aphront/dialog-view.css @@ -158,18 +158,18 @@ margin-top: 16px; } -.device-desktop .aphront-dialog-flush .phui-object-item-list-view { +.device-desktop .aphront-dialog-flush .phui-oi-list-view { margin: 0; padding: 0; } -.aphront-dialog-flush .phui-object-item-list-view.phui-object-list-stackable - .phui-object-item { +.aphront-dialog-flush .phui-oi-list-view.phui-object-list-stackable + .phui-oi { border: 0; } -.aphront-dialog-flush .phui-object-item-list-view.phui-object-list-stackable - .phui-object-item-frame { +.aphront-dialog-flush .phui-oi-list-view.phui-object-list-stackable + .phui-oi-frame { border: 0; border-top: 1px solid {$thinblueborder}; } diff --git a/webroot/rsrc/css/application/config/config-page.css b/webroot/rsrc/css/application/config/config-page.css index 5fe15aadb8..82cb9642d2 100644 --- a/webroot/rsrc/css/application/config/config-page.css +++ b/webroot/rsrc/css/application/config/config-page.css @@ -39,7 +39,7 @@ margin: 0 4px; } -.device-desktop .config-page-content .phui-object-item-list-view { +.device-desktop .config-page-content .phui-oi-list-view { padding-left: 0; padding-right: 0; } diff --git a/webroot/rsrc/css/application/flag/flag.css b/webroot/rsrc/css/application/flag/flag.css index 8f6f7a45e8..7d5f0af5d2 100644 --- a/webroot/rsrc/css/application/flag/flag.css +++ b/webroot/rsrc/css/application/flag/flag.css @@ -7,7 +7,7 @@ background: transparent 0 0 no-repeat; } -.phui-object-item .phabricator-flag-icon { +.phui-oi .phabricator-flag-icon { float: left; margin: 2px; margin-right: 8px; diff --git a/webroot/rsrc/css/application/phame/phame.css b/webroot/rsrc/css/application/phame/phame.css index 6a9a5b5717..7b20009356 100644 --- a/webroot/rsrc/css/application/phame/phame.css +++ b/webroot/rsrc/css/application/phame/phame.css @@ -23,7 +23,6 @@ display: inline-block; background-repeat: no-repeat; background-size: 100%; - box-shadow: inset 0 0 0 1px rgba({$alphagrey},.15); width: 40px; height: 40px; border-radius: 3px; @@ -98,7 +97,6 @@ display: inline-block; background-repeat: no-repeat; background-size: 100%; - box-shadow: inset 0 0 0 1px rgba({$alphagrey},.15); width: 24px; height: 24px; border-radius: 3px; @@ -253,14 +251,16 @@ /* Blog Chrome */ .phame-live-view .phui-crumbs-view { - background: #fff; border: none; - padding-left: 8px; + width: 960px; + margin: 0 auto; + padding: 4px 0; } /* Hero Image */ .phame-header-hero { background-color: #fff; + margin-top: 16px; } .phame-header-image { diff --git a/webroot/rsrc/css/application/project/project-view.css b/webroot/rsrc/css/application/project/project-view.css index 7fc3001d80..5b72e1c9eb 100644 --- a/webroot/rsrc/css/application/project/project-view.css +++ b/webroot/rsrc/css/application/project/project-view.css @@ -72,7 +72,7 @@ margin-bottom: 0; } -.project-view-home .phui-box-grey .phui-object-item-list-view { +.project-view-home .phui-box-grey .phui-oi-list-view { padding: 4px 8px 0 8px; } @@ -80,7 +80,7 @@ background-color: #fff; } -.project-view-home .phui-box-grey .phui-object-item-attribute .phui-icon-view { +.project-view-home .phui-box-grey .phui-oi-attribute .phui-icon-view { color: {$lightgreytext}; } diff --git a/webroot/rsrc/css/application/search/search-results.css b/webroot/rsrc/css/application/search/search-results.css index f02efe1315..734d86c029 100644 --- a/webroot/rsrc/css/application/search/search-results.css +++ b/webroot/rsrc/css/application/search/search-results.css @@ -2,7 +2,7 @@ * @provides phabricator-search-results-css */ -.phui-object-item-link strong { +.phui-oi-link strong { color: {$fire}; text-decoration: underline; } diff --git a/webroot/rsrc/css/layout/phabricator-source-code-view.css b/webroot/rsrc/css/layout/phabricator-source-code-view.css index 4bd57fcfcb..7e956b580a 100644 --- a/webroot/rsrc/css/layout/phabricator-source-code-view.css +++ b/webroot/rsrc/css/layout/phabricator-source-code-view.css @@ -10,7 +10,7 @@ background-color: #FFFEF5; } -.phui-object-item .phabricator-source-code-container { +.phui-oi .phabricator-source-code-container { margin-left: 8px; } diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css new file mode 100644 index 0000000000..7fcc6d4ef7 --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css @@ -0,0 +1,48 @@ +/** + * @provides phui-oi-big-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-oi-list-big ul.phui-oi-list-view { + margin: 0; + padding: 20px; +} + +.phui-oi-list-big .phui-oi-no-bar .phui-oi-frame { + border: 0; +} + +.phui-oi-list-big .phui-oi-image-icon { + margin: 8px 2px 12px; +} + +.phui-oi-list-big a.phui-oi-link { + color: #000; + font-size: {$biggestfontsize}; +} + +.phui-oi-list-big .phui-oi-name { + padding-top: 6px; +} + +.phui-oi-list-big .phui-oi-launch-button a.button { + font-size: {$normalfontsize}; + padding: 3px 12px 4px; +} + +.device-desktop .phui-oi-list-big .phui-oi { + margin-bottom: 8px; +} + +.phui-oi-list-big .phui-oi-col0 { + vertical-align: top; + padding: 0; +} + +.phui-oi-list-big .phui-oi-status-icon { + padding: 5px; +} + +.phui-oi-list-big .phui-oi-visited a.phui-oi-link { + color: {$violet}; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-color.css b/webroot/rsrc/css/phui/object-item/phui-oi-color.css new file mode 100644 index 0000000000..e9ec630727 --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-color.css @@ -0,0 +1,68 @@ +/** + * @provides phui-oi-color-css + * @requires phui-oi-list-view-css + */ + + +/* - Bar Colors ---------------------------------------------------------------- + Colors for the left-hand border bars, used to indicate object status or other + attributes. +*/ + +.phui-oi-bar-color-red { + border-left-color: {$red}; +} + +.phui-oi-bar-color-orange { + border-left-color: {$orange}; +} + +.phui-oi-bar-color-yellow { + border-left-color: {$yellow}; +} + +.phui-oi-bar-color-green { + border-left-color: {$green}; +} + +.phui-oi-bar-color-sky { + border-left-color: {$sky}; +} + +.phui-oi-bar-color-blue { + border-left-color: {$blue}; +} + +.phui-oi-bar-color-indigo { + border-left-color: {$indigo}; +} + +.phui-oi-bar-color-violet { + border-left-color: {$violet}; +} + +.phui-oi-bar-color-pink { + border-left-color: {$pink}; +} + +.phui-oi-bar-color-fire { + border-left-color: {$fire}; +} + +.phui-oi-bar-color-bluegrey { + border-left-color: {$bluetext}; +} + +.phui-oi-bar-color-lightbluetext { + border-left-color: {$lightbluetext}; +} + +.phui-oi-bar-color-grey, +.phui-oi-bar-color-lightgreytext { + border-left-color: {$lightgreytext}; +} + +.phui-oi-bar-color-black, +.phui-oi-bar-color-dark { + border-left-color: {$darkgreytext}; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-drag-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-drag-ui.css new file mode 100644 index 0000000000..caf9ff8dd0 --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-drag-ui.css @@ -0,0 +1,59 @@ +/** + * @provides phui-oi-drag-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-object-box .phui-oi-list-view.phui-oi-list-drag { + margin-top: 8px; + margin-bottom: 4px; +} + +.phui-oi.phui-oi-drag { + background: {$bluebackground}; + border-radius: 3px; + border: none; +} + +.phui-oi.phui-oi-drag, +.phui-oi.phui-oi-drag .phui-oi-frame { + border: none; +} + +.phui-object-box .phui-oi-list-view .phui-oi.phui-oi-drag { + margin-top: 4px; +} + +.phui-oi-drag.phui-oi-with-image-icon .phui-oi-frame, +.phui-oi-drag.phui-oi-with-image .phui-oi-frame, +.phui-oi-drag .phui-oi-frame { + min-height: 36px; +} + +.phui-oi-drag .phui-oi-list-icon { + height: auto; + width: auto; +} + +.phui-oi-drag .phui-oi-image-icon .phui-icon-view { + height: 16px; + width: 16px; + font-size: 16px; + line-height: 20px; +} + +.phui-oi-drag.phui-oi-grippable .phui-oi-frame { + padding-left: 28px; +} + +.phui-oi-drag .phui-oi-grip { + left: 4px; +} + +.phui-oi-drag.phui-oi-with-image-icon .phui-oi-content-box, +.phui-oi-drag.phui-oi-with-image .phui-oi-content-box { + margin-left: 24px; +} + +.phui-oi-list-drag .drag-ghost { + margin-top: 4px; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-flush-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-flush-ui.css new file mode 100644 index 0000000000..2902cb22ce --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-flush-ui.css @@ -0,0 +1,13 @@ +/** + * @provides phui-oi-flush-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-oi-list-view.phui-oi-list-flush { + padding: 0; + margin: 0; +} + +.phui-object-box .phui-oi-list-flush .phui-oi { + margin: 0; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css new file mode 100644 index 0000000000..018245e21c --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css @@ -0,0 +1,625 @@ +/** + * @provides phui-oi-list-view-css + */ + +.phui-oi { + border-left-width: 0; +} + +ul.phui-oi-list-view { + padding: 8px; + list-style: none; +} + +.device-desktop .phui-oi-list-view { + padding: 16px; +} + +.phui-oi-list-view + .phui-oi-list-view { + padding-top: 0; +} + +.phui-object-box .phui-oi-list-view .phui-oi { + margin: 0; +} + +.phui-oi-list-view .phui-info-view { + margin: 0; +} + +.phui-object-box .phui-oi-list-view .phui-info-view { + color: {$greytext}; + border: none; +} + +.phui-oi { + border-style: solid; + border-color: {$lightgreyborder}; + margin: 5px 0; + overflow: hidden; + background: #fff; + margin-bottom: 4px; +} + +.phui-oi .phui-icon-view { + display: inline-block; +} + +.phui-oi-frame { + border-color: {$lightblueborder}; + border-width: 1px 1px 1px 0; + border-style: solid; + position: relative; + min-height: 33px; + overflow: hidden; +} + +.phui-oi-cover-image { + display: none; +} + +.phui-oi-no-bar .phui-oi-frame { + border-width: 1px; +} + +.device-desktop .phui-oi { + margin: 0 0 4px 0; +} + +.phui-object-box .phui-oi-list-view { + margin: 0; +} + +.phui-oi-status-icon { + font-weight: bold; + padding: 3px; + font-size: 16px; +} + +.phui-oi-list-view .phui-oi-col0 .phui-icon-view { + width: 17px; + text-align: center; + overflow: visible; + position: relative; + left: -1px; +} + +.phui-oi-name { + padding: 8px 8px 0; + white-space: nowrap; + word-wrap: break-word; + overflow: hidden; + text-overflow: ellipsis; + font-weight: bold; + -webkit-font-smoothing: antialiased; +} + +.device-phone .phui-oi-name { + overflow: normal; + white-space: normal; + font-weight: bold; +} + +.phui-oi-link { + display: inline; +} + +.phui-oi-objname { + color: #000; + cursor: text; + font-weight: bold; +} + +.phui-oi-content { + margin: 4px 8px 2px 0; + overflow: hidden; +} + +.phui-oi-grippable { + cursor: move; +} + +.device .phui-oi-grippable { + cursor: normal; +} + +.phui-oi-grip { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 20px; + background: url('/rsrc/image/texture/grip.png') center center no-repeat; +} + +.device .phui-oi-grip { + display: none; +} + +.phui-oi-grippable .phui-oi-frame { + padding-left: 16px; +} + +.device .phui-oi-grippable .phui-oi-frame { + padding-left: 0; +} + +.phui-oi-list-header { + padding: 0 0 8px 0; + color: {$darkgreytext}; +} + +.phui-oi-table { + display: table; + table-layout: fixed; + width: 100%; +} + +.phui-oi-table-row { + display: table-row; +} + +.phui-oi-col0 { + width: 20px; + display: table-cell; + vertical-align: middle; + padding-left: 4px; +} + +.device-phone .phui-oi-col0 { + vertical-align: top; + padding-top: 8px; +} + +.phui-oi-col1 { + display: table-cell; + vertical-align: top; +} + +.phui-oi-col2 { + width: 160px; + display: table-cell; + vertical-align: top; +} + +.device-phone .phui-oi-col1, +.device-phone .phui-oi-col2 { + display: block; + width: auto; +} + +/* - Item Actions -------------------------------------------------------------- + + Action buttons, like "Edit" and "Delete". + +*/ + +.phui-oi-actions { + position: absolute; + right: 4px; + top: 4px; + bottom: 4px; + vertical-align: middle; + text-align: right; +} + +.phui-oi-actions .phui-list-item-view { + float: right; + height: 100%; + width: 24px; + display: inline-block; + position: relative; +} + +.phui-oi-actions .phui-list-item-href { + display: inline-block; + position: relative; + width: 24px; + height: 100%; +} + +.device-desktop .phui-oi-actions .phui-list-item-href:hover { + background: {$hoverblue}; + border-radius: 3px; +} + +.phui-oi-actions .phui-list-item-icon { + width: 14px; + height: 14px; + position: absolute; + display: block; + top: 50%; + margin-top: -7px; + left: 3px; +} + +.phui-oi-actions .phui-list-item-name { + display: none; +} + +.phui-oi-with-1-actions .phui-oi-content-box { + margin-right: 28px; + overflow: hidden; +} + +.phui-oi-with-2-actions .phui-oi-content-box { + margin-right: 54px; + overflow: hidden; +} + +.phui-oi-with-3-actions .phui-oi-content-box { + margin-right: 76px; + overflow: hidden; +} + + +/* - Object Box List ----------------------------------------------------------- + + Tighter, stacking list when inside an Object Box + +*/ + +.phui-object-box .phui-oi-list-view { + padding: 0; + border: none; +} + +.phui-object-box .phui-oi-frame { + border-right: none; +} + +.phui-object-box .phui-oi:last-child + .phui-oi-frame { + border-bottom: none; +} + + +/* - Subhead ------------------------------------------------------------------- + + Descriptive Text or Links under the main header, before attributes. + +*/ + +.phui-oi-subhead { + color: {$greytext}; + padding: 0 8px 6px; +} + + +/* - Attribute List ------------------------------------------------------------ + + Object attributes, commonly used to render created date, etc. + +*/ + +.phui-oi-attributes { + padding: 0 8px 6px; + line-height: 18px; + min-height: 21px; +} + +.phui-oi-attribute { + display: inline-block; + color: {$greytext}; + vertical-align: top; +} + +.phui-oi-attribute-spacer { + padding: 0 4px; +} + + +/* - Icons --------------------------------------------------------------------- + + Icons, which show object state. On mobile, they are rendered without labels + to save space. + +*/ + +.phui-object-icon-pane { + margin: 8px 0 4px; +} + +.device-phone .phui-object-icon-pane { + margin: 0 0 4px; +} + +.phui-oi-icons { + padding: 0 4px 0 0; +} + +.device-phone .phui-oi-icons { + padding: 0 0 0 8px; +} + +ul.phui-oi-icons { + margin: 0; +} + +.phui-oi-icon { + vertical-align: middle; + font-size: {$smallerfontsize}; + color: {$greytext}; + text-align: right; + white-space: nowrap; + overflow: hidden; + min-height: 18px; + line-height: 18px; +} + +.device-phone .phui-oi-icon { + text-align: left; + font-size: 13px; +} + +/* + * Items with icon 'none' still have on mobile, thus creating a weird vertical + * margin for elements which follow + */ +.device-phone .phui-oi-icon .none { + display: none; +} + +.phui-oi-icon-image { + width: 14px; + height: 14px; + font-size: 13px; + margin-right: 4px; +} + + +/* - Disabled ------------------------------------------------------------------ + + Disabled/inactive objects. + +*/ + + +.phui-oi.phui-oi-disabled .phui-oi-link, +.phui-oi.phui-oi-disabled .phui-oi-link a { + color: {$lightgreytext}; +} + +.phui-oi.phui-oi-disabled .phui-oi-frame { + border-color: #d7d7d7; +} + +.phui-oi.phui-oi-disabled .phui-oi-objname { + color: {$greytext}; + text-decoration: line-through; +} + + +/* - Effects ------------------------------------------------------------------- + + Effects like highlighted items. + +*/ + +.phui-oi.phui-oi-highlighted { + background: {$sh-yellowbackground}; +} + +ul.phui-oi-list-view .phui-oi-highlighted + .phui-oi-frame { + border-color: {$sh-yellowborder}; +} + +.phui-oi-selected { + background: {$sh-bluebackground}; +} + +ul.phui-oi-list-view .phui-oi-selected + .phui-oi-frame { + border-color: {$sh-blueborder}; +} + + +/* - Handle Icons -------------------------------------------------------------- + + Shows owners, reviewers, etc., using profile picture icons. + +*/ + +.phui-oi-handle-icons { + bottom: 0; + right: 4px; + position: absolute; +} + +.phui-oi-handle-icon { + width: 24px; + height: 24px; + display: inline-block; + background-size: 100%; + border-radius: 3px; + background-repeat: no-repeat; +} + + +/* - Bylines ------------------------------------------------------------------- + + Shows owners, authors, reviewers, etc., in text. + +*/ + +.phui-oi-bylines { + padding: 0 4px 0 8px; + margin: 4px 0 8px; + font-size: {$smallerfontsize}; + color: {$greytext}; + text-align: right; +} + +.phui-oi-byline { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.device-phone .phui-oi-bylines { + float: none; + text-align: left; + padding: 0 8px; + font-size: {$normalfontsize}; +} + + +/* - Draggable List ------------------------------------------------------------ + + These classes are applied by and/or provided for use with JX.DraggableList. + +*/ + +.drag-ghost { + position: relative; + background: {$sh-indigobackground}; + border-radius: 3px; + margin-bottom: 4px; + border: 1px dashed {$sh-indigoborder}; +} + +.drag-dragging { + opacity: 0.25; +} + +.drag-sending { + opacity: 0.5; +} + +.drag-clone, +.drag-frame { + /* This allows mousewheel events to pass through the clone and frame while + they are being dragged. Without this, the mousewheel does not work during + a drag operation. */ + pointer-events: none; +} + +.drag-frame { + position: fixed; + overflow: hidden; + left: 0; + right: 0; + top: 0; + bottom: 0; +} + +.drag-clone { + position: absolute; + list-style: none; +} + +/* - Badges ---------------------------------------------------------------- */ + +.phui-oi-col0.phui-oi-badge { + width: 28px; +} + +.phui-oi-col0.phui-oi-badge .phui-icon-view { + left: 0; +} + +/* - Countdowns ------------------------------------------------------------ */ + +.phui-oi-col0.phui-oi-countdown { + width: 52px; + padding: 0; +} + +.phui-oi-countdown .phui-oi-countdown-number { + border-right: 1px solid {$thinblueborder}; + text-align: center; + color: {$bluetext}; +} + + +/* - Dashboards ------------------------------------------------------------ */ + +.phui-object-box .phui-oi-list-view .phui-oi-frame { + border: none; + border-bottom: 1px solid {$thinblueborder}; +} + +.drag-clone.phui-oi-standard .phui-oi-frame { + border: none; + opacity: 0.8; + background: {$sh-bluebackground}; +} + +.phui-object-box .phui-oi-list-header { + font-size: {$normalfontsize}; + color: {$darkbluetext}; + border-top: 1px solid {$thinblueborder}; + border-bottom: 1px solid {$thinblueborder}; + padding: 8px; + background-color: {$lightgreybackground}; +} + +.phui-object-box .phui-header-shell + .phui-oi-list-view .phui-oi-list-header, +.phui-object-box .phui-object-box-hidden-content + .phui-oi-list-view + .phui-oi-list-header, +.phui-object-box .phui-object-box-hidden-content + .phui-oi-list-header { + border-top: none; + } + +.dashboard-pane .phui-oi-empty .phui-info-view { + border: none; + margin: 0; +} + +.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up + .aphront-multi-column-column-outer.third .phui-oi-col2 { + display: none; + } + + +/* - Launcher List ---------------------------------------------------------- */ + +.phui-oi-image-icon { + background: none; + width: 40px; + height: 40px; + margin: 8px 6px; + position: absolute; +} + +.phui-oi-image-icon .phui-icon-view { + position: absolute; + width: 40px; + height: 40px; + font-size: 26px; + text-align: center; + line-height: 36px; +} + +.phui-oi-image { + width: 40px; + height: 40px; + border-radius: 3px; + background-size: 100%; + margin: 8px 6px; + position: absolute; +} + +.phui-oi-with-image-icon .phui-oi-frame, +.phui-oi-with-image .phui-oi-frame { + min-height: 52px; +} + +.phui-oi-with-image-icon .phui-oi-content-box, +.phui-oi-with-image .phui-oi-content-box { + margin-left: 46px; +} + +/* - Launcher Button -------------------------------------------------------- */ + +.phui-oi-col2.phui-oi-launch-button { + text-align: right; + vertical-align: middle; + padding-right: 4px; +} + +.device-phone .phui-oi-col2.phui-oi-launch-button { + padding: 0 8px 8px; + text-align: left; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css new file mode 100644 index 0000000000..e838f1ce3e --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css @@ -0,0 +1,43 @@ +/** + * @provides phui-oi-simple-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-oi-list-simple .phui-oi-with-image .phui-oi-frame { + min-height: 26px; +} + +.phui-oi-list-simple .phui-oi-image { + height: 26px; + width: 26px; + margin: 0; +} + +.phui-oi-list-simple .phui-oi-with-image + .phui-oi-content-box { + margin-left: 32px; +} + +.phui-oi-list-simple .phui-oi-name { + padding: 2px 0; +} + +.phui-oi-list-simple .phui-oi-name a { + color: {$darkbluetext}; +} + +.phui-oi-list-view.phui-oi-list-simple .phui-oi-frame { + border: none; + margin-bottom: 4px; +} + +.phui-oi-list-view.phui-oi-list-simple li:last-child + .phui-oi-frame { + margin: 0; +} + +.phui-oi-list-simple .phui-oi-actions { + top: 2px; + bottom: 2px; + right: 2px; +} diff --git a/webroot/rsrc/css/phui/phui-box.css b/webroot/rsrc/css/phui/phui-box.css index 8d2acd0069..ef0816f826 100644 --- a/webroot/rsrc/css/phui/phui-box.css +++ b/webroot/rsrc/css/phui/phui-box.css @@ -24,18 +24,18 @@ border-color: {$thinblueborder}; } -.phui-box-blue .phui-object-item, -.phui-box-grey .phui-object-item { +.phui-box-blue .phui-oi, +.phui-box-grey .phui-oi { background: transparent; } -.phui-box-blue .phui-object-item-link, -.phui-box-grey .phui-object-item-link { +.phui-box-blue .phui-oi-link, +.phui-box-grey .phui-oi-link { color: {$darkbluetext}; } -.phui-box-blue .phui-object-item-list-view, -.phui-box-grey .phui-object-item-list-view { +.phui-box-blue .phui-oi-list-view, +.phui-box-grey .phui-oi-list-view { background-color: #fff; } @@ -98,7 +98,7 @@ body.device .phui-box-blue-property.phui-object-box.phui-object-box-collapsed color: {$bluetext}; } -.phui-box-blue-property .phui-object-item-list-view { +.phui-box-blue-property .phui-oi-list-view { padding: 2px 8px; } diff --git a/webroot/rsrc/css/phui/phui-button.css b/webroot/rsrc/css/phui/phui-button.css index 51807fa48e..15142d3b1a 100644 --- a/webroot/rsrc/css/phui/phui-button.css +++ b/webroot/rsrc/css/phui/phui-button.css @@ -17,9 +17,16 @@ button.phabricator-action-view-item { -webkit-font-smoothing: auto; } -button::-moz-focus-inner { - padding: 0; +button::-moz-focus-inner, +input::-moz-focus-inner { border: 0; + padding: 0; +} + +button:focus, +a.button:focus { + outline: 0; + box-shadow: 0 0 2pt 2pt rgba(82, 168, 236, 0.7); } button, diff --git a/webroot/rsrc/css/phui/phui-crumbs-view.css b/webroot/rsrc/css/phui/phui-crumbs-view.css index 3cf8013723..d2d0744819 100644 --- a/webroot/rsrc/css/phui/phui-crumbs-view.css +++ b/webroot/rsrc/css/phui/phui-crumbs-view.css @@ -119,7 +119,7 @@ body .phui-crumbs-view + .phui-object-box { margin-top: 0; } -body .phui-crumbs-view + .phui-object-item-list-view { +body .phui-crumbs-view + .phui-oi-list-view { padding-top: 0; } diff --git a/webroot/rsrc/css/phui/phui-object-item-list-view.css b/webroot/rsrc/css/phui/phui-object-item-list-view.css deleted file mode 100644 index 2f77102f42..0000000000 --- a/webroot/rsrc/css/phui/phui-object-item-list-view.css +++ /dev/null @@ -1,790 +0,0 @@ -/** - * @provides phui-object-item-list-view-css - */ - -ul.phui-object-item-list-view { - padding: 8px; - list-style: none; -} - -.device-desktop .phui-object-item-list-view { - padding: 16px; -} - -.phui-object-item-list-view + .phui-object-item-list-view { - padding-top: 0; -} - -.phui-object-item-list-view.phui-object-list-flush { - padding: 0; - margin: 0; -} - -.phui-object-box .phui-object-item-list-view .phui-object-item { - margin: 0; -} - -.phui-object-item-list-view .phui-info-view { - margin: 0; -} - -.phui-object-box .phui-object-item-list-view .phui-info-view { - color: {$greytext}; - border: none; -} - -.phui-object-item { - border-style: solid; - border-color: {$lightgreyborder}; - margin: 5px 0; - overflow: hidden; - background: #fff; - margin-bottom: 4px; -} - -.phui-object-item .phui-icon-view { - display: inline-block; -} - -.phui-object-item-frame { - border-color: {$lightblueborder}; - border-width: 1px 1px 1px 0; - border-style: solid; - position: relative; - min-height: 33px; - overflow: hidden; -} - -.phui-object-item-cover-image { - display: none; -} - -.phui-object-item-no-bar .phui-object-item-frame { - border-width: 1px; -} - -.device-desktop .phui-object-item { - margin: 0 0 4px 0; -} - -.phui-object-box .phui-object-list-flush .phui-object-item { - margin: 0; -} - -.phui-object-box .phui-object-item-list-view { - margin: 0; -} - -.phui-object-item-status-icon { - font-weight: bold; - padding: 3px; - font-size: 16px; -} - -.phui-object-item-list-view .phui-object-item-col0 .phui-icon-view { - width: 17px; - text-align: center; - overflow: visible; - position: relative; - left: -1px; -} - -.phui-object-item-name { - padding: 8px 8px 0; - white-space: nowrap; - word-wrap: break-word; - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - -webkit-font-smoothing: antialiased; -} - -.device-phone .phui-object-item-name { - overflow: normal; - white-space: normal; - font-weight: bold; -} - -.phui-object-item-link { - display: inline; -} - -.phui-object-item-objname { - color: #000; - cursor: text; - font-weight: bold; -} - -.phui-object-item-content { - margin: 4px 8px 2px 0; - overflow: hidden; -} - -.phui-object-item-grippable { - cursor: move; -} - -.device .phui-object-item-grippable { - cursor: normal; -} - -.phui-object-item-grip { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 20px; - background: url('/rsrc/image/texture/grip.png') center center no-repeat; -} - -.device .phui-object-item-grip { - display: none; -} - -.phui-object-item-grippable .phui-object-item-frame { - padding-left: 16px; -} - -.device .phui-object-item-grippable .phui-object-item-frame { - padding-left: 0; -} - -.phui-object-item-list-header { - padding: 0 0 8px 0; - color: {$darkgreytext}; -} - -.phui-object-item-table { - display: table; - table-layout: fixed; - width: 100%; -} - -.phui-object-item-table-row { - display: table-row; -} - -.phui-object-item-col0 { - width: 20px; - display: table-cell; - vertical-align: middle; - padding-left: 4px; -} - -.device-phone .phui-object-item-col0 { - vertical-align: top; - padding-top: 8px; -} - -.phui-object-item-col1 { - display: table-cell; - vertical-align: top; -} - -.phui-object-item-col2 { - width: 160px; - display: table-cell; - vertical-align: top; -} - -.device-phone .phui-object-item-col1, -.device-phone .phui-object-item-col2 { - display: block; - width: auto; -} - -/* - Item Actions -------------------------------------------------------------- - - Action buttons, like "Edit" and "Delete". - -*/ - -.phui-object-item-actions { - position: absolute; - right: 4px; - top: 4px; - bottom: 4px; - vertical-align: middle; - text-align: right; -} - -.phui-object-item-actions .phui-list-item-view { - float: right; - height: 100%; - width: 24px; - display: inline-block; - position: relative; -} - -.phui-object-item-actions .phui-list-item-href { - display: inline-block; - position: relative; - width: 24px; - height: 100%; -} - -.device-desktop .phui-object-item-actions .phui-list-item-href:hover { - background: {$hoverblue}; - border-radius: 3px; -} - -.phui-object-item-actions .phui-list-item-icon { - width: 14px; - height: 14px; - position: absolute; - display: block; - top: 50%; - margin-top: -7px; - left: 3px; -} - -.phui-object-item-actions .phui-list-item-name { - display: none; -} - -.phui-object-item-with-1-actions .phui-object-item-content-box { - margin-right: 28px; - overflow: hidden; -} - -.phui-object-item-with-2-actions .phui-object-item-content-box { - margin-right: 54px; - overflow: hidden; -} - -.phui-object-item-with-3-actions .phui-object-item-content-box { - margin-right: 76px; - overflow: hidden; -} - - -/* - Object Box List ----------------------------------------------------------- - - Tighter, stacking list when inside an Object Box - -*/ - -.phui-object-box .phui-object-item-list-view { - padding: 0; - border: none; -} - -.phui-object-box .phui-object-item-frame { - border-right: none; -} - -.phui-object-box .phui-object-item:last-child - .phui-object-item-frame { - border-bottom: none; -} - - -/* - Subhead ------------------------------------------------------------------- - - Descriptive Text or Links under the main header, before attributes. - -*/ - -.phui-object-item-subhead { - color: {$greytext}; - padding: 0 8px 6px; -} - - -/* - Attribute List ------------------------------------------------------------ - - Object attributes, commonly used to render created date, etc. - -*/ - -.phui-object-item-attributes { - padding: 0 8px 6px; - line-height: 18px; - min-height: 21px; -} - -.phui-object-item-attribute { - display: inline-block; - color: {$greytext}; - vertical-align: top; -} - -.phui-object-item-attribute-spacer { - padding: 0 4px; -} - - -/* - Icons --------------------------------------------------------------------- - - Icons, which show object state. On mobile, they are rendered without labels - to save space. - -*/ - -.phui-object-icon-pane { - margin: 8px 0 4px; -} - -.device-phone .phui-object-icon-pane { - margin: 0 0 4px; -} - -.phui-object-item-icons { - padding: 0 4px 0 0; -} - -.device-phone .phui-object-item-icons { - padding: 0 0 0 8px; -} - -ul.phui-object-item-icons { - margin: 0; -} - -.phui-object-item-icon { - vertical-align: middle; - font-size: {$smallerfontsize}; - color: {$greytext}; - text-align: right; - white-space: nowrap; - overflow: hidden; - min-height: 18px; - line-height: 18px; -} - -.device-phone .phui-object-item-icon { - text-align: left; - font-size: 13px; -} - -/* - * Items with icon 'none' still have on mobile, thus creating a weird vertical - * margin for elements which follow - */ -.device-phone .phui-object-item-icon .none { - display: none; -} - -.phui-object-item-icon-image { - width: 14px; - height: 14px; - font-size: 13px; - margin-right: 4px; -} - -/* - Bar Colors ---------------------------------------------------------------- - Colors for the left-hand border bars, used to indicate object status or other - attributes. -*/ - -.phui-object-item { - border-left-width: 0; -} - -.phui-object-item-bar-color-red { - border-left-color: {$red}; -} - -.phui-object-item-bar-color-orange { - border-left-color: {$orange}; -} - -.phui-object-item-bar-color-yellow { - border-left-color: {$yellow}; -} - -.phui-object-item-bar-color-green { - border-left-color: {$green}; -} - -.phui-object-item-bar-color-sky { - border-left-color: {$sky}; -} - -.phui-object-item-bar-color-blue { - border-left-color: {$blue}; -} - -.phui-object-item-bar-color-indigo { - border-left-color: {$indigo}; -} - -.phui-object-item-bar-color-violet { - border-left-color: {$violet}; -} - -.phui-object-item-bar-color-pink { - border-left-color: {$pink}; -} - -.phui-object-item-bar-color-fire { - border-left-color: {$fire}; -} - -.phui-object-item-bar-color-bluegrey { - border-left-color: {$bluetext}; -} - -.phui-object-item-bar-color-lightbluetext { - border-left-color: {$lightbluetext}; -} - -.phui-object-item-bar-color-grey, -.phui-object-item-bar-color-lightgreytext { - border-left-color: {$lightgreytext}; -} - -.phui-object-item-bar-color-black, -.phui-object-item-bar-color-dark { - border-left-color: {$darkgreytext}; -} - - -/* - Disabled ------------------------------------------------------------------ - - Disabled/inactive objects. - -*/ - - -.phui-object-item.phui-object-item-disabled .phui-object-item-link, -.phui-object-item.phui-object-item-disabled .phui-object-item-link a { - color: {$lightgreytext}; -} - -.phui-object-item.phui-object-item-disabled .phui-object-item-frame { - border-color: #d7d7d7; -} - -.phui-object-item.phui-object-item-disabled .phui-object-item-objname { - color: {$greytext}; - text-decoration: line-through; -} - - -/* - Effects ------------------------------------------------------------------- - - Effects like highlighted items. - -*/ - -.phui-object-item.phui-object-item-highlighted { - background: {$sh-yellowbackground}; -} - -ul.phui-object-item-list-view .phui-object-item-highlighted - .phui-object-item-frame { - border-color: {$sh-yellowborder}; -} - -.phui-object-item-selected { - background: {$sh-bluebackground}; -} - -ul.phui-object-item-list-view .phui-object-item-selected - .phui-object-item-frame { - border-color: {$sh-blueborder}; -} - - -/* - Handle Icons -------------------------------------------------------------- - - Shows owners, reviewers, etc., using profile picture icons. - -*/ - -.phui-object-item-handle-icons { - bottom: 0; - right: 4px; - position: absolute; -} - -.phui-object-item-handle-icon { - width: 24px; - height: 24px; - display: inline-block; - background-size: 100%; - border-radius: 3px; - background-repeat: no-repeat; -} - - -/* - Bylines ------------------------------------------------------------------- - - Shows owners, authors, reviewers, etc., in text. - -*/ - -.phui-object-item-bylines { - padding: 0 4px 0 8px; - margin: 4px 0 8px; - font-size: {$smallerfontsize}; - color: {$greytext}; - text-align: right; -} - -.phui-object-item-byline { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.device-phone .phui-object-item-bylines { - float: none; - text-align: left; - padding: 0 8px; - font-size: {$normalfontsize}; -} - - -/* - Draggable List ------------------------------------------------------------ - - These classes are applied by and/or provided for use with JX.DraggableList. - -*/ - -.drag-ghost { - position: relative; - background: {$sh-indigobackground}; - border-radius: 3px; - margin-bottom: 4px; - border: 1px dashed {$sh-indigoborder}; -} - -.drag-dragging { - opacity: 0.25; -} - -.drag-sending { - opacity: 0.5; -} - -.drag-clone, -.drag-frame { - /* This allows mousewheel events to pass through the clone and frame while - they are being dragged. Without this, the mousewheel does not work during - a drag operation. */ - pointer-events: none; -} - -.drag-frame { - position: fixed; - overflow: hidden; - left: 0; - right: 0; - top: 0; - bottom: 0; -} - -.drag-clone { - position: absolute; - list-style: none; -} - -/* - Badges ---------------------------------------------------------------- */ - -.phui-object-item-col0.phui-object-item-badge { - width: 28px; -} - -.phui-object-item-col0.phui-object-item-badge .phui-icon-view { - left: 0; -} - -/* - Countdowns ------------------------------------------------------------ */ - -.phui-object-item-col0.phui-object-item-countdown { - width: 52px; - padding: 0; -} - -.phui-object-item-countdown .phui-object-item-countdown-number { - border-right: 1px solid {$thinblueborder}; - text-align: center; - color: {$bluetext}; -} - - -/* - Dashboards ------------------------------------------------------------ */ - -.phui-object-box .phui-object-item-list-view .phui-object-item-frame { - border: none; - border-bottom: 1px solid {$thinblueborder}; -} - -.drag-clone.phui-object-item-standard .phui-object-item-frame { - border: none; - opacity: 0.8; - background: {$sh-bluebackground}; -} - -.phui-object-box .phui-object-item-list-header { - font-size: {$normalfontsize}; - color: {$darkbluetext}; - border-top: 1px solid {$thinblueborder}; - border-bottom: 1px solid {$thinblueborder}; - padding: 8px; - background-color: {$lightgreybackground}; -} - -.phui-object-box .phui-header-shell + .phui-object-item-list-view - .phui-object-item-list-header, -.phui-object-box .phui-object-box-hidden-content + .phui-object-item-list-view - .phui-object-item-list-header, -.phui-object-box .phui-object-box-hidden-content + - .phui-object-item-list-header { - border-top: none; - } - -.dashboard-pane .phui-object-item-empty .phui-info-view { - border: none; - margin: 0; -} - -.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up - .aphront-multi-column-column-outer.third .phui-object-item-col2 { - display: none; - } - - -/* - Launcher List ---------------------------------------------------------- */ - -.phui-object-item-image-icon { - background: none; - width: 40px; - height: 40px; - margin: 8px 6px; - position: absolute; -} - -.phui-object-item-image-icon .phui-icon-view { - position: absolute; - width: 40px; - height: 40px; - font-size: 26px; - text-align: center; - line-height: 36px; -} - -.phui-object-item-image { - width: 40px; - height: 40px; - border-radius: 3px; - background-size: 100%; - margin: 8px 6px; - position: absolute; -} - -.phui-object-item-with-image-icon .phui-object-item-frame, -.phui-object-item-with-image .phui-object-item-frame { - min-height: 52px; -} - -.phui-object-item-with-image-icon .phui-object-item-content-box, -.phui-object-item-with-image .phui-object-item-content-box { - margin-left: 46px; -} - -/* - Launcher Button -------------------------------------------------------- */ - -.phui-object-item-col2.phui-object-item-launch-button { - text-align: right; - vertical-align: middle; - padding-right: 4px; -} - -.device-phone .phui-object-item-col2.phui-object-item-launch-button { - padding: 0 8px 8px; - text-align: left; -} - -/* - Simple List------------------------------------------------------------- */ - -.phui-object-list-simple .phui-object-item-with-image .phui-object-item-frame { - min-height: 26px; -} - -.phui-object-list-simple .phui-object-item-image { - height: 26px; - width: 26px; - margin: 0; -} - -.phui-object-list-simple .phui-object-item-with-image - .phui-object-item-content-box { - margin-left: 32px; -} - -.phui-object-list-simple .phui-object-item-name { - padding: 2px 0; -} - -.phui-object-list-simple .phui-object-item-name a { - color: {$darkbluetext}; -} - -.phui-object-item-list-view.phui-object-list-simple .phui-object-item-frame { - border: none; - margin-bottom: 4px; -} - -.phui-object-item-list-view.phui-object-list-simple li:last-child - .phui-object-item-frame { - margin: 0; -} - -.phui-object-list-simple .phui-object-item-actions { - top: 2px; - bottom: 2px; - right: 2px; -} - -/* - Big List---------------------------------------------------------------- */ - -.phui-object-list-big ul.phui-object-item-list-view { - margin: 0; - padding: 20px; -} - -.phui-object-list-big .phui-object-item-no-bar .phui-object-item-frame { - border: 0; -} - -.phui-object-list-big .phui-object-item-image-icon { - margin: 8px 2px 12px; -} - -.phui-object-list-big a.phui-object-item-link { - color: #000; - font-size: {$biggestfontsize}; -} - -.phui-object-list-big .phui-object-item-name { - padding-top: 6px; -} - -.phui-object-list-big .phui-object-item-launch-button a.button { - font-size: {$normalfontsize}; - padding: 3px 12px 4px; -} - -.device-desktop .phui-object-list-big .phui-object-item { - margin-bottom: 8px; -} - -.phui-object-list-big .phui-object-item-col0 { - vertical-align: top; - padding: 0; -} - -.phui-object-list-big .phui-object-item-status-icon { - padding: 5px; -} - -.phui-object-list-big .phui-object-item-visited a.phui-object-item-link { - color: {$violet}; -} - -.device-desktop .phui-object-list-big .phui-object-item-frame:hover { - -} diff --git a/webroot/rsrc/css/phui/phui-tag-view.css b/webroot/rsrc/css/phui/phui-tag-view.css index 729c4719e5..f14909bc06 100644 --- a/webroot/rsrc/css/phui/phui-tag-view.css +++ b/webroot/rsrc/css/phui/phui-tag-view.css @@ -145,11 +145,11 @@ a.phui-tag-view:hover margin-top: 4px; } -.phui-object-item .phabricator-handle-tag-list { +.phui-oi .phabricator-handle-tag-list { display: inline; } -.phui-object-item .phabricator-handle-tag-list-item { +.phui-oi .phabricator-handle-tag-list-item { display: inline-block; margin: 0 4px 2px 0; } diff --git a/webroot/rsrc/css/phui/phui-two-column-view.css b/webroot/rsrc/css/phui/phui-two-column-view.css index aea567d025..0020df8b84 100644 --- a/webroot/rsrc/css/phui/phui-two-column-view.css +++ b/webroot/rsrc/css/phui/phui-two-column-view.css @@ -164,7 +164,7 @@ padding: 5px 4px 5px 28px; } -.device-desktop .phui-two-column-properties .phabricator-action-view:hover +.device-desktop .phui-two-column-properties .phabricator-action-view-href:hover .phabricator-action-view-item { text-decoration: none; background-color: rgba({$alphablue}, .08); @@ -172,7 +172,7 @@ border-radius: 3px; } -.device-desktop .phui-two-column-properties .phabricator-action-view:hover +.device-desktop .phui-two-column-properties .phabricator-action-view-href:hover .phabricator-action-view-icon { color: {$sky}; } @@ -199,7 +199,7 @@ padding: 12px; } -.phui-two-column-view .phui-side-column .phui-object-item-empty +.phui-two-column-view .phui-side-column .phui-oi-empty .phui-info-view { margin-bottom: 0; } diff --git a/webroot/rsrc/css/phui/workboards/phui-workcard.css b/webroot/rsrc/css/phui/workboards/phui-workcard.css index 64792c6915..5af162b4bc 100644 --- a/webroot/rsrc/css/phui/workboards/phui-workcard.css +++ b/webroot/rsrc/css/phui/workboards/phui-workcard.css @@ -2,7 +2,7 @@ * @provides phui-workcard-view-css */ -.phui-workcard.phui-object-item { +.phui-workcard.phui-oi { background-color: #fff; border-radius: 3px; margin-bottom: 8px; @@ -10,22 +10,22 @@ box-sizing: border-box; } -.phui-workcard .phui-object-item-name { +.phui-workcard .phui-oi-name { padding-bottom: 4px; } -.phui-workcard .phui-object-item-content { +.phui-workcard .phui-oi-content { margin-top: 0; } -.phui-workcard .phui-object-item-frame { +.phui-workcard .phui-oi-frame { border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-color: {$thinblueborder}; border-bottom-color: {$lightblueborder}; } -.phui-workcard.phui-object-item .phui-object-item-objname { +.phui-workcard.phui-oi .phui-oi-objname { -webkit-touch-callout: text; -webkit-user-select: text; -khtml-user-select: text; @@ -34,36 +34,36 @@ user-select: text; } -.phui-workcard .phui-object-item-link { +.phui-workcard .phui-oi-link { white-space: normal; font-weight: normal; color: #000; margin-left: 2px; } -.phui-object-item-disabled.phui-workcard { +.phui-oi-disabled.phui-workcard { background-color: rgba({$alphawhite},.67); } -.phui-object-item-disabled.phui-workcard .phui-object-item-link { +.phui-oi-disabled.phui-workcard .phui-oi-link { color: {$greytext}; } -.device-desktop .phui-workcard .phui-object-item-with-1-actions - .phui-object-item-content-box { +.device-desktop .phui-workcard .phui-oi-with-1-actions + .phui-oi-content-box { margin-right: 0; overflow: hidden; } -.phui-workcard .phui-object-item-objname { +.phui-workcard .phui-oi-objname { vertical-align: top; } -.phui-workcard.phui-object-item-grippable .phui-object-item-frame { +.phui-workcard.phui-oi-grippable .phui-oi-frame { padding-left: 0; } -.phui-workcard .phui-object-item-grip { +.phui-workcard .phui-oi-grip { display: none; } @@ -71,28 +71,28 @@ display: none; } -.phui-workcard.phui-object-item .phui-list-item-href { +.phui-workcard.phui-oi .phui-list-item-href { height: 24px; width: 24px; } -.device-desktop .phui-workcard.phui-object-item:hover +.device-desktop .phui-workcard.phui-oi:hover .phui-list-item-href { background: #fff; opacity: .7; } -.device-desktop .phui-workcard.phui-object-item +.device-desktop .phui-workcard.phui-oi .phui-list-item-href:hover { background: {$sh-bluebackground}; opacity: 1; } -.phui-workcard.phui-object-item:hover .phui-list-item-icon { +.phui-workcard.phui-oi:hover .phui-list-item-icon { display: block; } -.phui-workcard .phui-object-item-attributes { +.phui-workcard .phui-oi-attributes { margin-right: 12px; } @@ -100,21 +100,21 @@ margin-bottom: 8px; } -.phui-workcard .phui-object-item-cover-image { +.phui-workcard .phui-oi-cover-image { display: block; padding: 8px 8px 0 8px; width: 263px; } -.phui-workcard.phui-object-item.phui-workcard-upload-target { +.phui-workcard.phui-oi.phui-workcard-upload-target { background-color: {$sh-greenbackground}; } -.phui-object-item-list-view .phui-workcard:last-child { +.phui-oi-list-view .phui-workcard:last-child { margin-bottom: 0; } -.phui-workcard .phui-object-item-attribute-spacer { +.phui-workcard .phui-oi-attribute-spacer { display: none; } @@ -123,54 +123,54 @@ display: inline-block; } -.phui-workcard .phui-object-item-attribute { +.phui-workcard .phui-oi-attribute { display: inline; } /* - Draggable Colors --------------------------------------------------------*/ -.phui-workcard.phui-object-item.drag-clone { +.phui-workcard.phui-oi.drag-clone { box-shadow: {$dropshadow}; background-color: {$sh-greybackground}; } -.phui-workcard.phui-object-item.drag-clone .phui-list-item-href { +.phui-workcard.phui-oi.drag-clone .phui-list-item-href { display: none; } -.phui-workcard.drag-clone.phui-object-item-bar-color-red { +.phui-workcard.drag-clone.phui-oi-bar-color-red { background-color: {$sh-redbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-orange { +.phui-workcard.drag-clone.phui-oi-bar-color-orange { background-color: {$sh-orangebackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-yellow { +.phui-workcard.drag-clone.phui-oi-bar-color-yellow { background-color: {$sh-yellowbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-green { +.phui-workcard.drag-clone.phui-oi-bar-color-green { background-color: {$sh-greenbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-blue { +.phui-workcard.drag-clone.phui-oi-bar-color-blue { background-color: {$sh-bluebackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-indigo { +.phui-workcard.drag-clone.phui-oi-bar-color-indigo { background-color: {$sh-indigobackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-violet { +.phui-workcard.drag-clone.phui-oi-bar-color-violet { background-color: {$sh-violetbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-pink { +.phui-workcard.drag-clone.phui-oi-bar-color-pink { background-color: {$sh-pinkbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-sky { +.phui-workcard.drag-clone.phui-oi-bar-color-sky { background-color: {$sh-bluebackground}; } diff --git a/webroot/rsrc/css/phui/workboards/phui-workpanel.css b/webroot/rsrc/css/phui/workboards/phui-workpanel.css index 899c6f74eb..617ff5aa6d 100644 --- a/webroot/rsrc/css/phui/workboards/phui-workpanel.css +++ b/webroot/rsrc/css/phui/workboards/phui-workpanel.css @@ -83,7 +83,7 @@ width: auto; } -.phui-workpanel-body .phui-object-item-list-view { +.phui-workpanel-body .phui-oi-list-view { min-height: 54px; background-color: transparent; } @@ -115,18 +115,18 @@ border-radius: 4px; } -.project-panel-empty .phui-object-item-list-view { +.project-panel-empty .phui-oi-list-view { background: rgba(234, 230, 247, 0.85); border-radius: 3px; margin-bottom: 4px; border: 1px dashed {$sh-indigoborder}; } -.project-panel-empty .phui-object-item-list-view .drag-ghost { +.project-panel-empty .phui-oi-list-view .drag-ghost { display: none; } -.project-panel-empty .phui-object-item-list-view.drag-target-list { +.project-panel-empty .phui-oi-list-view.drag-target-list { background: rgba({$alphawhite},.7); } diff --git a/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js b/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js index 30a557e268..b7728abb57 100644 --- a/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js +++ b/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js @@ -35,7 +35,7 @@ JX.behavior('maniphest-batch-selector', function(config) { JX.DOM.alterClass( task, - 'phui-object-item-selected', + 'phui-oi-selected', is_selected(task)); update();