diff --git a/resources/celerity/map.php b/resources/celerity/map.php index c9f7585f45..da014bccde 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'f79ebe46', + 'core.pkg.css' => '33799ec4', 'core.pkg.js' => 'a590b451', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '9451634c', @@ -28,7 +28,6 @@ return array( 'rsrc/css/aphront/table-view.css' => 'e3632cc9', 'rsrc/css/aphront/tokenizer.css' => '04875312', 'rsrc/css/aphront/tooltip.css' => '7672b60f', - 'rsrc/css/aphront/two-column.css' => '16ab3ad2', 'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c', 'rsrc/css/aphront/typeahead.css' => '0e403212', 'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af', @@ -48,13 +47,13 @@ return array( 'rsrc/css/application/config/unhandled-exception.css' => '4c96257a', 'rsrc/css/application/conpherence/durable-column.css' => '86396117', 'rsrc/css/application/conpherence/menu.css' => 'f99fee4c', - 'rsrc/css/application/conpherence/message-pane.css' => '2c16d204', + 'rsrc/css/application/conpherence/message-pane.css' => 'dd4f8a3b', 'rsrc/css/application/conpherence/notification.css' => '6cdcc253', 'rsrc/css/application/conpherence/transaction.css' => '85d0974c', 'rsrc/css/application/conpherence/update.css' => 'faf6be09', 'rsrc/css/application/conpherence/widget-pane.css' => '419fd50c', 'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', - 'rsrc/css/application/countdown/timer.css' => '4f02bd98', + 'rsrc/css/application/countdown/timer.css' => 'e7544472', 'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a', 'rsrc/css/application/dashboard/dashboard.css' => 'eb458607', 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', @@ -73,7 +72,7 @@ return array( 'rsrc/css/application/files/global-drag-and-drop.css' => '697324ad', 'rsrc/css/application/flag/flag.css' => '5337623f', 'rsrc/css/application/harbormaster/harbormaster.css' => '49d64eb4', - 'rsrc/css/application/herald/herald-test.css' => '778b008e', + 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 'rsrc/css/application/herald/herald.css' => '826075fa', 'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5', 'rsrc/css/application/maniphest/report.css' => 'f6931fdf', @@ -83,7 +82,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' => '25970776', - 'rsrc/css/application/phame/phame.css' => '3259b53d', + 'rsrc/css/application/phame/phame.css' => 'bb147387', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio.css' => '95174bdd', @@ -94,10 +93,7 @@ return array( 'rsrc/css/application/policy/policy-edit.css' => '815c66f7', 'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43', 'rsrc/css/application/policy/policy.css' => '957ea14c', - 'rsrc/css/application/ponder/comments.css' => '865a67e6', - 'rsrc/css/application/ponder/feed.css' => 'e62615b6', - 'rsrc/css/application/ponder/post.css' => '9d415218', - 'rsrc/css/application/ponder/vote.css' => 'aea452b0', + 'rsrc/css/application/ponder/ponder-view.css' => 'fcd6b398', 'rsrc/css/application/projects/project-icon.css' => '4e3eaa5a', 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', @@ -112,7 +108,7 @@ return array( 'rsrc/css/core/syntax.css' => '9fd11da8', 'rsrc/css/core/z-index.css' => '57ddcaa2', 'rsrc/css/diviner/diviner-shared.css' => '5a337049', - 'rsrc/css/font/font-awesome.css' => 'e2e712fe', + 'rsrc/css/font/font-awesome.css' => 'd2fc4e8d', 'rsrc/css/font/font-lato.css' => '5ab1a46a', 'rsrc/css/font/font-roboto-slab.css' => 'f24a53cb', 'rsrc/css/font/phui-font-icon-base.css' => '3dad2ae3', @@ -126,12 +122,12 @@ return array( 'rsrc/css/phui/calendar/phui-calendar.css' => 'ccabe893', 'rsrc/css/phui/phui-action-list.css' => 'c5eba19d', 'rsrc/css/phui/phui-action-panel.css' => '3ee9afd5', - 'rsrc/css/phui/phui-badge.css' => 'b6218fa8', + 'rsrc/css/phui/phui-badge.css' => 'f25c3476', 'rsrc/css/phui/phui-box.css' => 'a5bb366d', 'rsrc/css/phui/phui-button.css' => '16020a60', 'rsrc/css/phui/phui-crumbs-view.css' => 'd842f867', 'rsrc/css/phui/phui-document.css' => '0267054b', - 'rsrc/css/phui/phui-feed-story.css' => 'c7d8113a', + 'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23', 'rsrc/css/phui/phui-fontkit.css' => 'cb8ae7ad', 'rsrc/css/phui/phui-form-view.css' => '621b21c5', 'rsrc/css/phui/phui-form.css' => 'afdb2c6e', @@ -142,27 +138,27 @@ return array( 'rsrc/css/phui/phui-info-view.css' => '5b16bac6', 'rsrc/css/phui/phui-list.css' => '125599df', 'rsrc/css/phui/phui-object-box.css' => '407eaf5a', - 'rsrc/css/phui/phui-object-item-list-view.css' => 'a1b990b7', + 'rsrc/css/phui/phui-object-item-list-view.css' => '36ce366c', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', - 'rsrc/css/phui/phui-property-list-view.css' => 'aeb09581', + 'rsrc/css/phui/phui-property-list-view.css' => '15bbe0b0', 'rsrc/css/phui/phui-remarkup-preview.css' => '867f85b3', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '888cedb8', 'rsrc/css/phui/phui-tag-view.css' => '402691cc', 'rsrc/css/phui/phui-text.css' => 'cf019f54', - 'rsrc/css/phui/phui-timeline-view.css' => 'fc23e7b7', - 'rsrc/css/phui/phui-workboard-view.css' => '6a20991a', - 'rsrc/css/phui/phui-workpanel-view.css' => '8cebb2b1', + 'rsrc/css/phui/phui-timeline-view.css' => 'f1bccf73', + 'rsrc/css/phui/phui-workboard-view.css' => '6704d68d', + 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '1ebb9bf9', 'rsrc/css/sprite-main-header.css' => 'f07bbb87', 'rsrc/css/sprite-menu.css' => '9dd65b92', 'rsrc/css/sprite-projects.css' => 'e5ad842a', 'rsrc/css/sprite-tokens.css' => '4f399012', - 'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '5fb6fb0e', - 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => 'a653cb11', - 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => '80526fc8', - 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '4924d54d', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '7d5a4653', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '531835e8', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => '427fe363', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => 'a9897054', 'rsrc/externals/font/lato/lato-bold.eot' => '99fbcf8c', 'rsrc/externals/font/lato/lato-bold.ttf' => '0a7141f7', 'rsrc/externals/font/lato/lato-bold.woff' => 'f5db2061', @@ -382,7 +378,7 @@ return array( 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781', 'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', - 'rsrc/js/application/herald/HeraldRuleEditor.js' => '52684226', + 'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b', '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', @@ -503,7 +499,6 @@ return array( 'aphront-table-view-css' => 'e3632cc9', 'aphront-tokenizer-control-css' => '04875312', 'aphront-tooltip-css' => '7672b60f', - 'aphront-two-column-view-css' => '16ab3ad2', 'aphront-typeahead-control-css' => '0e403212', 'auth-css' => '0877ed6e', 'bulk-job-css' => 'df9c1d4a', @@ -514,7 +509,7 @@ return array( 'config-welcome-css' => '6abd79be', 'conpherence-durable-column-view' => '86396117', 'conpherence-menu-css' => 'f99fee4c', - 'conpherence-message-pane-css' => '2c16d204', + 'conpherence-message-pane-css' => 'dd4f8a3b', 'conpherence-notification-css' => '6cdcc253', 'conpherence-thread-manager' => '01774ab2', 'conpherence-transaction-css' => '85d0974c', @@ -532,14 +527,14 @@ return array( 'diffusion-readme-css' => '2106ea08', 'diffusion-source-css' => '66fdf661', 'diviner-shared-css' => '5a337049', - 'font-fontawesome' => 'e2e712fe', + 'font-fontawesome' => 'd2fc4e8d', 'font-lato' => '5ab1a46a', 'font-roboto-slab' => 'f24a53cb', 'global-drag-and-drop-css' => '697324ad', 'harbormaster-css' => '49d64eb4', 'herald-css' => '826075fa', - 'herald-rule-editor' => '52684226', - 'herald-test-css' => '778b008e', + 'herald-rule-editor' => '91a6031b', + 'herald-test-css' => 'a52e323e', 'inline-comment-summary-css' => '51efda3a', 'javelin-aphlict' => '5359e785', 'javelin-behavior' => '61cbc29a', @@ -722,7 +717,7 @@ return array( 'phabricator-chatlog-css' => 'd295b020', 'phabricator-content-source-view-css' => '4b8b05d4', 'phabricator-core-css' => 'a76cefc9', - 'phabricator-countdown-css' => '4f02bd98', + 'phabricator-countdown-css' => 'e7544472', 'phabricator-dashboard-css' => 'eb458607', 'phabricator-drag-and-drop-file-upload' => '07de8873', 'phabricator-draggable-list' => 'a16ec1c6', @@ -765,7 +760,7 @@ return array( 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 'phabricator-zindex-css' => '57ddcaa2', - 'phame-css' => '3259b53d', + 'phame-css' => 'bb147387', 'pholio-css' => '95174bdd', 'pholio-edit-css' => '3ad9d1ee', 'pholio-inline-comments-css' => '8e545e49', @@ -775,7 +770,7 @@ return array( 'phrequent-css' => 'ffc185ad', 'phriction-document-css' => 'd1861e06', 'phui-action-panel-css' => '3ee9afd5', - 'phui-badge-view-css' => 'b6218fa8', + 'phui-badge-view-css' => 'f25c3476', 'phui-box-css' => 'a5bb366d', 'phui-button-css' => '16020a60', 'phui-calendar-css' => 'ccabe893', @@ -784,7 +779,7 @@ return array( 'phui-calendar-month-css' => '476be7e0', 'phui-crumbs-view-css' => 'd842f867', 'phui-document-view-css' => '0267054b', - 'phui-feed-story-css' => 'c7d8113a', + 'phui-feed-story-css' => 'b7b26d23', 'phui-font-icon-base-css' => '3dad2ae3', 'phui-fontkit-css' => 'cb8ae7ad', 'phui-form-css' => 'afdb2c6e', @@ -797,29 +792,26 @@ return array( 'phui-inline-comment-view-css' => '9fadd6b8', 'phui-list-view-css' => '125599df', 'phui-object-box-css' => '407eaf5a', - 'phui-object-item-list-view-css' => 'a1b990b7', + 'phui-object-item-list-view-css' => '36ce366c', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', - 'phui-property-list-view-css' => 'aeb09581', + 'phui-property-list-view-css' => '15bbe0b0', 'phui-remarkup-preview-css' => '867f85b3', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '888cedb8', 'phui-tag-view-css' => '402691cc', 'phui-text-css' => 'cf019f54', 'phui-theme-css' => '6b451f24', - 'phui-timeline-view-css' => 'fc23e7b7', - 'phui-workboard-view-css' => '6a20991a', - 'phui-workpanel-view-css' => '8cebb2b1', + 'phui-timeline-view-css' => 'f1bccf73', + 'phui-workboard-view-css' => '6704d68d', + 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', 'phuix-dropdown-menu' => 'bd4c8dca', 'policy-css' => '957ea14c', 'policy-edit-css' => '815c66f7', 'policy-transaction-detail-css' => '82100a43', - 'ponder-comment-table-css' => '865a67e6', - 'ponder-feed-view-css' => 'e62615b6', - 'ponder-post-css' => '9d415218', - 'ponder-vote-css' => 'aea452b0', + 'ponder-view-css' => 'fcd6b398', 'project-icon-css' => '4e3eaa5a', 'raphael-core' => '51ee6b43', 'raphael-g' => '40dde778', @@ -1172,15 +1164,6 @@ return array( 'javelin-dom', 'javelin-reactor-dom', ), - 52684226 => array( - 'multirow-row-manager', - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-json', - 'phabricator-prefab', - ), '5359e785' => array( 'javelin-install', 'javelin-util', @@ -1539,6 +1522,15 @@ return array( 'javelin-dom', 'javelin-stratcom', ), + '91a6031b' => array( + 'multirow-row-manager', + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-json', + 'phabricator-prefab', + ), '93d0c9e3' => array( 'javelin-behavior', 'javelin-stratcom', diff --git a/resources/sql/autopatches/20150725.badges.mailkey.1.sql b/resources/sql/autopatches/20150725.badges.mailkey.1.sql new file mode 100644 index 0000000000..5219a759b3 --- /dev/null +++ b/resources/sql/autopatches/20150725.badges.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_badges.badges_badge + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20150725.badges.mailkey.2.php b/resources/sql/autopatches/20150725.badges.mailkey.2.php new file mode 100644 index 0000000000..8231492478 --- /dev/null +++ b/resources/sql/autopatches/20150725.badges.mailkey.2.php @@ -0,0 +1,18 @@ +establishConnection('w'); +$iterator = new LiskMigrationIterator($table); +foreach ($iterator as $badge) { + $id = $badge->getID(); + + echo pht('Adding mail key for badge %d...', $id); + echo "\n"; + + queryfx( + $conn_w, + 'UPDATE %T SET mailKey = %s WHERE id = %d', + $table->getTableName(), + Filesystem::readRandomCharacters(20), + $id); +} diff --git a/resources/sql/autopatches/20150725.badges.viewpolicy.3.sql b/resources/sql/autopatches/20150725.badges.viewpolicy.3.sql new file mode 100644 index 0000000000..a5933f4ade --- /dev/null +++ b/resources/sql/autopatches/20150725.badges.viewpolicy.3.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_badges.badges_badge + DROP COLUMN viewPolicy; diff --git a/resources/sql/autopatches/20150725.countdown.mailkey.1.sql b/resources/sql/autopatches/20150725.countdown.mailkey.1.sql new file mode 100644 index 0000000000..c53441e1cb --- /dev/null +++ b/resources/sql/autopatches/20150725.countdown.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_countdown.countdown + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20150725.countdown.mailkey.2.php b/resources/sql/autopatches/20150725.countdown.mailkey.2.php new file mode 100644 index 0000000000..c07a763942 --- /dev/null +++ b/resources/sql/autopatches/20150725.countdown.mailkey.2.php @@ -0,0 +1,18 @@ +establishConnection('w'); +$iterator = new LiskMigrationIterator($table); +foreach ($iterator as $countdown) { + $id = $countdown->getID(); + + echo pht('Adding mail key for countdown %d...', $id); + echo "\n"; + + queryfx( + $conn_w, + 'UPDATE %T SET mailKey = %s WHERE id = %d', + $table->getTableName(), + Filesystem::readRandomCharacters(20), + $id); +} diff --git a/resources/sql/autopatches/20150725.slowvote.mailkey.1.sql b/resources/sql/autopatches/20150725.slowvote.mailkey.1.sql new file mode 100644 index 0000000000..00591afa56 --- /dev/null +++ b/resources/sql/autopatches/20150725.slowvote.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_slowvote.slowvote_poll + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20150725.slowvote.mailkey.2.php b/resources/sql/autopatches/20150725.slowvote.mailkey.2.php new file mode 100644 index 0000000000..fa6b2035df --- /dev/null +++ b/resources/sql/autopatches/20150725.slowvote.mailkey.2.php @@ -0,0 +1,18 @@ +establishConnection('w'); +$iterator = new LiskMigrationIterator($table); +foreach ($iterator as $slowvote) { + $id = $slowvote->getID(); + + echo pht('Adding mail key for Slowvote %d...', $id); + echo "\n"; + + queryfx( + $conn_w, + 'UPDATE %T SET mailKey = %s WHERE id = %d', + $table->getTableName(), + Filesystem::readRandomCharacters(20), + $id); +} diff --git a/resources/sql/autopatches/20150730.herald.1.sql b/resources/sql/autopatches/20150730.herald.1.sql new file mode 100644 index 0000000000..e6e097f82c --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.1.sql @@ -0,0 +1,27 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'subscribers.add' + WHERE r.ruleType != 'personal' + AND a.action = 'addcc'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'subscribers.self.add' + WHERE r.ruleType = 'personal' + AND a.action = 'addcc'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'subscribers.remove' + WHERE r.ruleType != 'personal' + AND a.action = 'remcc'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'subscribers.self.remove' + WHERE r.ruleType = 'personal' + AND a.action = 'remcc'; diff --git a/resources/sql/autopatches/20150730.herald.2.sql b/resources/sql/autopatches/20150730.herald.2.sql new file mode 100644 index 0000000000..3d0b5a0a05 --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.2.sql @@ -0,0 +1,13 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'email.other' + WHERE r.ruleType != 'personal' + AND a.action = 'email'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'email.self' + WHERE r.ruleType = 'personal' + AND a.action = 'email'; diff --git a/resources/sql/autopatches/20150730.herald.3.sql b/resources/sql/autopatches/20150730.herald.3.sql new file mode 100644 index 0000000000..e9fcbff59b --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.3.sql @@ -0,0 +1,11 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'projects.add' + WHERE a.action = 'addprojects'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'projects.remove' + WHERE a.action = 'removeprojects'; diff --git a/resources/sql/autopatches/20150730.herald.4.sql b/resources/sql/autopatches/20150730.herald.4.sql new file mode 100644 index 0000000000..1f5c35a851 --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.4.sql @@ -0,0 +1,13 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'maniphest.assign.other' + WHERE r.ruleType != 'personal' + AND a.action = 'assigntask'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'maniphest.assign.self' + WHERE r.ruleType = 'personal' + AND a.action = 'assigntask'; diff --git a/resources/sql/autopatches/20150730.herald.5.sql b/resources/sql/autopatches/20150730.herald.5.sql new file mode 100644 index 0000000000..84c9eea3c5 --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.5.sql @@ -0,0 +1,27 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'differential.reviewers.blocking' + WHERE r.ruleType != 'personal' + AND a.action = 'addreviewers'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'differential.reviewers.self.blocking' + WHERE r.ruleType = 'personal' + AND a.action = 'addreviewers'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'differential.reviewers.add' + WHERE r.ruleType != 'personal' + AND a.action = 'addblockingreviewers'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'differential.reviewers.self.add' + WHERE r.ruleType = 'personal' + AND a.action = 'addblockingreviewers'; diff --git a/resources/sql/autopatches/20150730.herald.6.sql b/resources/sql/autopatches/20150730.herald.6.sql new file mode 100644 index 0000000000..08188c6d4f --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.6.sql @@ -0,0 +1,6 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'legalpad.require' + WHERE r.ruleType != 'personal' + AND a.action = 'signature'; diff --git a/resources/sql/autopatches/20150730.herald.7.sql b/resources/sql/autopatches/20150730.herald.7.sql new file mode 100644 index 0000000000..403a90ac26 --- /dev/null +++ b/resources/sql/autopatches/20150730.herald.7.sql @@ -0,0 +1,6 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'harbormaster.build' + WHERE r.ruleType != 'personal' + AND a.action = 'applybuildplans'; diff --git a/resources/sql/autopatches/20150803.herald.1.sql b/resources/sql/autopatches/20150803.herald.1.sql new file mode 100644 index 0000000000..21f462b8c8 --- /dev/null +++ b/resources/sql/autopatches/20150803.herald.1.sql @@ -0,0 +1,13 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'diffusion.auditors.add' + WHERE r.ruleType != 'personal' + AND a.action = 'audit'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'diffusion.auditors.self.add' + WHERE r.ruleType = 'personal' + AND a.action = 'audit'; diff --git a/resources/sql/autopatches/20150803.herald.2.sql b/resources/sql/autopatches/20150803.herald.2.sql new file mode 100644 index 0000000000..4d48bc03b6 --- /dev/null +++ b/resources/sql/autopatches/20150803.herald.2.sql @@ -0,0 +1,13 @@ +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'diffusion.block' + WHERE r.contentType != 'differential.diff' + AND a.action = 'block'; + +UPDATE {$NAMESPACE}_herald.herald_action a + JOIN {$NAMESPACE}_herald.herald_rule r + ON a.ruleID = r.id + SET a.action = 'differential.block' + WHERE r.contentType = 'differential.diff' + AND a.action = 'block'; diff --git a/resources/sql/autopatches/20150804.ponder.answer.mailkey.1.sql b/resources/sql/autopatches/20150804.ponder.answer.mailkey.1.sql new file mode 100644 index 0000000000..63ba3494f9 --- /dev/null +++ b/resources/sql/autopatches/20150804.ponder.answer.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_ponder.ponder_answer + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20150804.ponder.answer.mailkey.2.php b/resources/sql/autopatches/20150804.ponder.answer.mailkey.2.php new file mode 100644 index 0000000000..e643a5dab5 --- /dev/null +++ b/resources/sql/autopatches/20150804.ponder.answer.mailkey.2.php @@ -0,0 +1,18 @@ +establishConnection('w'); +$iterator = new LiskMigrationIterator($table); +foreach ($iterator as $answer) { + $id = $answer->getID(); + + echo pht('Adding mail key for Answer %d...', $id); + echo "\n"; + + queryfx( + $conn_w, + 'UPDATE %T SET mailKey = %s WHERE id = %d', + $table->getTableName(), + Filesystem::readRandomCharacters(20), + $id); +} diff --git a/resources/sql/autopatches/20150804.ponder.question.1.sql b/resources/sql/autopatches/20150804.ponder.question.1.sql new file mode 100644 index 0000000000..8ea3b2c34c --- /dev/null +++ b/resources/sql/autopatches/20150804.ponder.question.1.sql @@ -0,0 +1,5 @@ +ALTER TABLE {$NAMESPACE}_ponder.ponder_question + ADD editPolicy VARBINARY(64) NOT NULL; + +ALTER TABLE {$NAMESPACE}_ponder.ponder_question + ADD viewPolicy VARBINARY(64) NOT NULL; diff --git a/resources/sql/autopatches/20150804.ponder.question.2.sql b/resources/sql/autopatches/20150804.ponder.question.2.sql new file mode 100644 index 0000000000..ddca10f753 --- /dev/null +++ b/resources/sql/autopatches/20150804.ponder.question.2.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_ponder.ponder_question + SET editPolicy = authorPHID WHERE editPolicy = ''; diff --git a/resources/sql/autopatches/20150804.ponder.question.3.sql b/resources/sql/autopatches/20150804.ponder.question.3.sql new file mode 100644 index 0000000000..0a359453ea --- /dev/null +++ b/resources/sql/autopatches/20150804.ponder.question.3.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_ponder.ponder_question + SET viewPolicy = 'users' WHERE viewPolicy = ''; diff --git a/resources/sql/autopatches/20150804.ponder.spaces.4.sql b/resources/sql/autopatches/20150804.ponder.spaces.4.sql new file mode 100644 index 0000000000..4282b8a509 --- /dev/null +++ b/resources/sql/autopatches/20150804.ponder.spaces.4.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_ponder.ponder_question + ADD spacePHID VARBINARY(64); diff --git a/resources/sql/autopatches/20150805.paste.status.1.sql b/resources/sql/autopatches/20150805.paste.status.1.sql new file mode 100644 index 0000000000..c9b98bf58c --- /dev/null +++ b/resources/sql/autopatches/20150805.paste.status.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_pastebin.pastebin_paste + ADD status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20150805.paste.status.2.sql b/resources/sql/autopatches/20150805.paste.status.2.sql new file mode 100644 index 0000000000..be2fe2c485 --- /dev/null +++ b/resources/sql/autopatches/20150805.paste.status.2.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_pastebin.pastebin_paste + SET status = 'active' WHERE status = ''; diff --git a/scripts/symbols/import_repository_symbols.php b/scripts/symbols/import_repository_symbols.php index 94cf601a34..2ac2b3c8a9 100755 --- a/scripts/symbols/import_repository_symbols.php +++ b/scripts/symbols/import_repository_symbols.php @@ -203,7 +203,7 @@ foreach ($input as $key => $line) { } } - if (count ($symbols) >= $args->getArg('max-transaction')) { + if (count($symbols) >= $args->getArg('max-transaction')) { try { echo pht( "Committing %s symbols...\n", diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 64bad75915..0f00bd7430 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -165,7 +165,6 @@ phutil_register_library_map(array( 'AphrontTableView' => 'view/control/AphrontTableView.php', 'AphrontTagView' => 'view/AphrontTagView.php', 'AphrontTokenizerTemplateView' => 'view/control/AphrontTokenizerTemplateView.php', - 'AphrontTwoColumnView' => 'view/layout/AphrontTwoColumnView.php', 'AphrontTypeaheadTemplateView' => 'view/control/AphrontTypeaheadTemplateView.php', 'AphrontURIMapper' => 'aphront/AphrontURIMapper.php', 'AphrontUnhandledExceptionResponse' => 'aphront/response/AphrontUnhandledExceptionResponse.php', @@ -303,6 +302,7 @@ phutil_register_library_map(array( 'DifferentialAuditorsField' => 'applications/differential/customfield/DifferentialAuditorsField.php', 'DifferentialAuthorField' => 'applications/differential/customfield/DifferentialAuthorField.php', 'DifferentialBlameRevisionField' => 'applications/differential/customfield/DifferentialBlameRevisionField.php', + 'DifferentialBlockHeraldAction' => 'applications/differential/herald/DifferentialBlockHeraldAction.php', 'DifferentialBranchField' => 'applications/differential/customfield/DifferentialBranchField.php', 'DifferentialChangeHeraldFieldGroup' => 'applications/differential/herald/DifferentialChangeHeraldFieldGroup.php', 'DifferentialChangeType' => 'applications/differential/constants/DifferentialChangeType.php', @@ -435,7 +435,12 @@ phutil_register_library_map(array( 'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php', 'DifferentialReviewerForRevisionEdgeType' => 'applications/differential/edge/DifferentialReviewerForRevisionEdgeType.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', 'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php', + 'DifferentialReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersHeraldAction.php', 'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php', 'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php', 'DifferentialRevisionAffectedFilesHeraldField' => 'applications/differential/herald/DifferentialRevisionAffectedFilesHeraldField.php', @@ -493,6 +498,10 @@ phutil_register_library_map(array( 'DifferentialUpdateUnitResultsConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateUnitResultsConduitAPIMethod.php', 'DifferentialViewPolicyField' => 'applications/differential/customfield/DifferentialViewPolicyField.php', 'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php', + 'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php', + 'DiffusionAuditorsAddSelfHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php', + 'DiffusionAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsHeraldAction.php', + 'DiffusionBlockHeraldAction' => 'applications/diffusion/herald/DiffusionBlockHeraldAction.php', 'DiffusionBranchQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBranchQueryConduitAPIMethod.php', 'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php', 'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php', @@ -941,6 +950,7 @@ phutil_register_library_map(array( 'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php', 'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php', 'HarbormasterBuildStepEditor' => 'applications/harbormaster/editor/HarbormasterBuildStepEditor.php', + 'HarbormasterBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php', 'HarbormasterBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterBuildStepImplementation.php', 'HarbormasterBuildStepImplementationTestCase' => 'applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php', 'HarbormasterBuildStepPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php', @@ -958,6 +968,7 @@ phutil_register_library_map(array( 'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php', 'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php', 'HarbormasterBuildableActionController' => 'applications/harbormaster/controller/HarbormasterBuildableActionController.php', + 'HarbormasterBuildableAdapterInterface' => 'applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php', 'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php', 'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php', 'HarbormasterBuildablePHIDType' => 'applications/harbormaster/phid/HarbormasterBuildablePHIDType.php', @@ -967,10 +978,12 @@ phutil_register_library_map(array( 'HarbormasterBuildableTransactionEditor' => 'applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php', 'HarbormasterBuildableTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildableTransactionQuery.php', 'HarbormasterBuildableViewController' => 'applications/harbormaster/controller/HarbormasterBuildableViewController.php', + 'HarbormasterBuiltinBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php', 'HarbormasterCommandBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterCommandBuildStepImplementation.php', 'HarbormasterConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterConduitAPIMethod.php', 'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php', 'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php', + 'HarbormasterExternalBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterExternalBuildStepGroup.php', 'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php', 'HarbormasterLeaseHostBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php', 'HarbormasterLintMessagesController' => 'applications/harbormaster/controller/HarbormasterLintMessagesController.php', @@ -979,18 +992,22 @@ phutil_register_library_map(array( 'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php', 'HarbormasterManagementUpdateWorkflow' => 'applications/harbormaster/management/HarbormasterManagementUpdateWorkflow.php', 'HarbormasterManagementWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWorkflow.php', + 'HarbormasterMessageType' => 'applications/harbormaster/engine/HarbormasterMessageType.php', 'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php', + 'HarbormasterOtherBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterOtherBuildStepGroup.php', 'HarbormasterPlanController' => 'applications/harbormaster/controller/HarbormasterPlanController.php', 'HarbormasterPlanDisableController' => 'applications/harbormaster/controller/HarbormasterPlanDisableController.php', 'HarbormasterPlanEditController' => 'applications/harbormaster/controller/HarbormasterPlanEditController.php', 'HarbormasterPlanListController' => 'applications/harbormaster/controller/HarbormasterPlanListController.php', 'HarbormasterPlanRunController' => 'applications/harbormaster/controller/HarbormasterPlanRunController.php', 'HarbormasterPlanViewController' => 'applications/harbormaster/controller/HarbormasterPlanViewController.php', + 'HarbormasterPrototypeBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterPrototypeBuildStepGroup.php', 'HarbormasterPublishFragmentBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php', 'HarbormasterQueryAutotargetsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryAutotargetsConduitAPIMethod.php', 'HarbormasterQueryBuildablesConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildablesConduitAPIMethod.php', 'HarbormasterQueryBuildsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php', 'HarbormasterRemarkupRule' => 'applications/harbormaster/remarkup/HarbormasterRemarkupRule.php', + 'HarbormasterRunBuildPlansHeraldAction' => 'applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php', 'HarbormasterSchemaSpec' => 'applications/harbormaster/storage/HarbormasterSchemaSpec.php', 'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php', 'HarbormasterSendMessageConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php', @@ -1000,6 +1017,7 @@ phutil_register_library_map(array( 'HarbormasterStepEditController' => 'applications/harbormaster/controller/HarbormasterStepEditController.php', 'HarbormasterTargetEngine' => 'applications/harbormaster/engine/HarbormasterTargetEngine.php', 'HarbormasterTargetWorker' => 'applications/harbormaster/worker/HarbormasterTargetWorker.php', + 'HarbormasterTestBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterTestBuildStepGroup.php', 'HarbormasterThrowExceptionBuildStep' => 'applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php', 'HarbormasterUIEventListener' => 'applications/harbormaster/event/HarbormasterUIEventListener.php', 'HarbormasterUnitMessagesController' => 'applications/harbormaster/controller/HarbormasterUnitMessagesController.php', @@ -1007,10 +1025,13 @@ phutil_register_library_map(array( 'HarbormasterUploadArtifactBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php', 'HarbormasterWaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php', 'HarbormasterWorker' => 'applications/harbormaster/worker/HarbormasterWorker.php', + 'HeraldAction' => 'applications/herald/action/HeraldAction.php', + 'HeraldActionGroup' => 'applications/herald/action/HeraldActionGroup.php', 'HeraldActionRecord' => 'applications/herald/storage/HeraldActionRecord.php', 'HeraldAdapter' => 'applications/herald/adapter/HeraldAdapter.php', 'HeraldAlwaysField' => 'applications/herald/field/HeraldAlwaysField.php', 'HeraldAnotherRuleField' => 'applications/herald/field/HeraldAnotherRuleField.php', + 'HeraldApplicationActionGroup' => 'applications/herald/action/HeraldApplicationActionGroup.php', 'HeraldApplyTranscript' => 'applications/herald/storage/transcript/HeraldApplyTranscript.php', 'HeraldBasicFieldGroup' => 'applications/herald/field/HeraldBasicFieldGroup.php', 'HeraldCommitAdapter' => 'applications/diffusion/herald/HeraldCommitAdapter.php', @@ -1018,12 +1039,12 @@ phutil_register_library_map(array( 'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php', 'HeraldContentSourceField' => 'applications/herald/field/HeraldContentSourceField.php', 'HeraldController' => 'applications/herald/controller/HeraldController.php', - 'HeraldCustomAction' => 'applications/herald/extension/HeraldCustomAction.php', 'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php', 'HeraldDifferentialAdapter' => 'applications/differential/herald/HeraldDifferentialAdapter.php', 'HeraldDifferentialDiffAdapter' => 'applications/differential/herald/HeraldDifferentialDiffAdapter.php', 'HeraldDifferentialRevisionAdapter' => 'applications/differential/herald/HeraldDifferentialRevisionAdapter.php', 'HeraldDisableController' => 'applications/herald/controller/HeraldDisableController.php', + 'HeraldDoNothingAction' => 'applications/herald/action/HeraldDoNothingAction.php', 'HeraldEditFieldGroup' => 'applications/herald/field/HeraldEditFieldGroup.php', 'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php', 'HeraldEmptyFieldValue' => 'applications/herald/value/HeraldEmptyFieldValue.php', @@ -1032,17 +1053,20 @@ phutil_register_library_map(array( 'HeraldFieldGroup' => 'applications/herald/field/HeraldFieldGroup.php', 'HeraldFieldTestCase' => 'applications/herald/field/__tests__/HeraldFieldTestCase.php', 'HeraldFieldValue' => 'applications/herald/value/HeraldFieldValue.php', + 'HeraldGroup' => 'applications/herald/group/HeraldGroup.php', 'HeraldInvalidActionException' => 'applications/herald/engine/exception/HeraldInvalidActionException.php', 'HeraldInvalidConditionException' => 'applications/herald/engine/exception/HeraldInvalidConditionException.php', 'HeraldManageGlobalRulesCapability' => 'applications/herald/capability/HeraldManageGlobalRulesCapability.php', 'HeraldManiphestTaskAdapter' => 'applications/maniphest/herald/HeraldManiphestTaskAdapter.php', 'HeraldNewController' => 'applications/herald/controller/HeraldNewController.php', 'HeraldNewObjectField' => 'applications/herald/field/HeraldNewObjectField.php', + 'HeraldNotifyActionGroup' => 'applications/herald/action/HeraldNotifyActionGroup.php', 'HeraldObjectTranscript' => 'applications/herald/storage/transcript/HeraldObjectTranscript.php', 'HeraldPholioMockAdapter' => 'applications/pholio/herald/HeraldPholioMockAdapter.php', 'HeraldPreCommitAdapter' => 'applications/diffusion/herald/HeraldPreCommitAdapter.php', 'HeraldPreCommitContentAdapter' => 'applications/diffusion/herald/HeraldPreCommitContentAdapter.php', 'HeraldPreCommitRefAdapter' => 'applications/diffusion/herald/HeraldPreCommitRefAdapter.php', + 'HeraldPreventActionGroup' => 'applications/herald/action/HeraldPreventActionGroup.php', 'HeraldProjectsField' => 'applications/project/herald/HeraldProjectsField.php', 'HeraldRecursiveConditionsException' => 'applications/herald/engine/exception/HeraldRecursiveConditionsException.php', 'HeraldRelatedFieldGroup' => 'applications/herald/field/HeraldRelatedFieldGroup.php', @@ -1065,6 +1089,7 @@ phutil_register_library_map(array( 'HeraldSelectFieldValue' => 'applications/herald/value/HeraldSelectFieldValue.php', 'HeraldSpaceField' => 'applications/spaces/herald/HeraldSpaceField.php', 'HeraldSubscribersField' => 'applications/subscriptions/herald/HeraldSubscribersField.php', + 'HeraldSupportActionGroup' => 'applications/herald/action/HeraldSupportActionGroup.php', 'HeraldSupportFieldGroup' => 'applications/herald/field/HeraldSupportFieldGroup.php', 'HeraldTestConsoleController' => 'applications/herald/controller/HeraldTestConsoleController.php', 'HeraldTextFieldValue' => 'applications/herald/value/HeraldTextFieldValue.php', @@ -1077,6 +1102,7 @@ phutil_register_library_map(array( 'HeraldTranscriptQuery' => 'applications/herald/query/HeraldTranscriptQuery.php', 'HeraldTranscriptSearchEngine' => 'applications/herald/query/HeraldTranscriptSearchEngine.php', 'HeraldTranscriptTestCase' => 'applications/herald/storage/__tests__/HeraldTranscriptTestCase.php', + 'HeraldUtilityActionGroup' => 'applications/herald/action/HeraldUtilityActionGroup.php', 'Javelin' => 'infrastructure/javelin/Javelin.php', 'JavelinReactorUIExample' => 'applications/uiexample/examples/JavelinReactorUIExample.php', 'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php', @@ -1110,6 +1136,7 @@ phutil_register_library_map(array( 'LegalpadMailReceiver' => 'applications/legalpad/mail/LegalpadMailReceiver.php', 'LegalpadObjectNeedsSignatureEdgeType' => 'applications/legalpad/edge/LegalpadObjectNeedsSignatureEdgeType.php', 'LegalpadReplyHandler' => 'applications/legalpad/mail/LegalpadReplyHandler.php', + 'LegalpadRequireSignatureHeraldAction' => 'applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php', 'LegalpadSchemaSpec' => 'applications/legalpad/storage/LegalpadSchemaSpec.php', 'LegalpadSignatureNeededByObjectEdgeType' => 'applications/legalpad/edge/LegalpadSignatureNeededByObjectEdgeType.php', 'LegalpadTransaction' => 'applications/legalpad/storage/LegalpadTransaction.php', @@ -1178,6 +1205,9 @@ phutil_register_library_map(array( 'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php', 'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php', 'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php', + 'ManiphestTaskAssignHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php', + 'ManiphestTaskAssignOtherHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php', + 'ManiphestTaskAssignSelfHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignSelfHeraldAction.php', 'ManiphestTaskAssigneeHeraldField' => 'applications/maniphest/herald/ManiphestTaskAssigneeHeraldField.php', 'ManiphestTaskAuthorHeraldField' => 'applications/maniphest/herald/ManiphestTaskAuthorHeraldField.php', 'ManiphestTaskAuthorPolicyRule' => 'applications/maniphest/policyrule/ManiphestTaskAuthorPolicyRule.php', @@ -1631,10 +1661,12 @@ phutil_register_library_map(array( 'PhabricatorBadgesEditor' => 'applications/badges/editor/PhabricatorBadgesEditor.php', 'PhabricatorBadgesIcon' => 'applications/badges/icon/PhabricatorBadgesIcon.php', 'PhabricatorBadgesListController' => 'applications/badges/controller/PhabricatorBadgesListController.php', + 'PhabricatorBadgesMailReceiver' => 'applications/badges/mail/PhabricatorBadgesMailReceiver.php', 'PhabricatorBadgesPHIDType' => 'applications/badges/phid/PhabricatorBadgesPHIDType.php', 'PhabricatorBadgesQuery' => 'applications/badges/query/PhabricatorBadgesQuery.php', 'PhabricatorBadgesRecipientsListView' => 'applications/badges/view/PhabricatorBadgesRecipientsListView.php', 'PhabricatorBadgesRemoveRecipientsController' => 'applications/badges/controller/PhabricatorBadgesRemoveRecipientsController.php', + 'PhabricatorBadgesReplyHandler' => 'applications/badges/mail/PhabricatorBadgesReplyHandler.php', 'PhabricatorBadgesSchemaSpec' => 'applications/badges/storage/PhabricatorBadgesSchemaSpec.php', 'PhabricatorBadgesSearchEngine' => 'applications/badges/query/PhabricatorBadgesSearchEngine.php', 'PhabricatorBadgesTransaction' => 'applications/badges/storage/PhabricatorBadgesTransaction.php', @@ -1830,6 +1862,7 @@ phutil_register_library_map(array( 'PhabricatorCountdownEditController' => 'applications/countdown/controller/PhabricatorCountdownEditController.php', 'PhabricatorCountdownEditor' => 'applications/countdown/editor/PhabricatorCountdownEditor.php', 'PhabricatorCountdownListController' => 'applications/countdown/controller/PhabricatorCountdownListController.php', + 'PhabricatorCountdownMailReceiver' => 'applications/countdown/mail/PhabricatorCountdownMailReceiver.php', 'PhabricatorCountdownQuery' => 'applications/countdown/query/PhabricatorCountdownQuery.php', 'PhabricatorCountdownRemarkupRule' => 'applications/countdown/remarkup/PhabricatorCountdownRemarkupRule.php', 'PhabricatorCountdownReplyHandler' => 'applications/countdown/mail/PhabricatorCountdownReplyHandler.php', @@ -2099,6 +2132,7 @@ phutil_register_library_map(array( 'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php', 'PhabricatorFilesOutboundRequestAction' => 'applications/files/action/PhabricatorFilesOutboundRequestAction.php', 'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php', + 'PhabricatorFlagAddFlagHeraldAction' => 'applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php', 'PhabricatorFlagColor' => 'applications/flag/constants/PhabricatorFlagColor.php', 'PhabricatorFlagConstants' => 'applications/flag/constants/PhabricatorFlagConstants.php', 'PhabricatorFlagController' => 'applications/flag/controller/PhabricatorFlagController.php', @@ -2222,6 +2256,7 @@ phutil_register_library_map(array( 'PhabricatorMailManagementSendTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php', 'PhabricatorMailManagementShowInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowInboundWorkflow.php', 'PhabricatorMailManagementShowOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php', + 'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php', 'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php', 'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php', 'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php', @@ -2262,6 +2297,9 @@ phutil_register_library_map(array( 'PhabricatorMetaMTADAO' => 'applications/metamta/storage/PhabricatorMetaMTADAO.php', 'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser/PhabricatorMetaMTAEmailBodyParser.php', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__/PhabricatorMetaMTAEmailBodyParserTestCase.php', + 'PhabricatorMetaMTAEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php', + 'PhabricatorMetaMTAEmailOthersHeraldAction' => 'applications/metamta/herald/PhabricatorMetaMTAEmailOthersHeraldAction.php', + 'PhabricatorMetaMTAEmailSelfHeraldAction' => 'applications/metamta/herald/PhabricatorMetaMTAEmailSelfHeraldAction.php', 'PhabricatorMetaMTAErrorMailAction' => 'applications/metamta/action/PhabricatorMetaMTAErrorMailAction.php', 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php', 'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php', @@ -2525,6 +2563,7 @@ phutil_register_library_map(array( 'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php', 'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php', 'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php', + 'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php', 'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php', 'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php', 'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php', @@ -2557,6 +2596,7 @@ phutil_register_library_map(array( 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php', 'PhabricatorProjectFeedController' => 'applications/project/controller/PhabricatorProjectFeedController.php', + 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', 'PhabricatorProjectIcon' => 'applications/project/icon/PhabricatorProjectIcon.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', @@ -2578,6 +2618,7 @@ phutil_register_library_map(array( 'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php', 'PhabricatorProjectProjectPHIDType' => 'applications/project/phid/PhabricatorProjectProjectPHIDType.php', 'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php', + 'PhabricatorProjectRemoveHeraldAction' => 'applications/project/herald/PhabricatorProjectRemoveHeraldAction.php', 'PhabricatorProjectSchemaSpec' => 'applications/project/storage/PhabricatorProjectSchemaSpec.php', 'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php', 'PhabricatorProjectSearchField' => 'applications/project/searchfield/PhabricatorProjectSearchField.php', @@ -2789,11 +2830,13 @@ phutil_register_library_map(array( 'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php', 'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php', 'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php', + 'PhabricatorSlowvoteMailReceiver' => 'applications/slowvote/mail/PhabricatorSlowvoteMailReceiver.php', 'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php', 'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php', 'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php', 'PhabricatorSlowvotePollPHIDType' => 'applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php', 'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php', + 'PhabricatorSlowvoteReplyHandler' => 'applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php', 'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php', 'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php', 'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php', @@ -2866,10 +2909,15 @@ phutil_register_library_map(array( 'PhabricatorSubscribedToObjectEdgeType' => 'applications/transactions/edges/PhabricatorSubscribedToObjectEdgeType.php', 'PhabricatorSubscribersQuery' => 'applications/subscriptions/query/PhabricatorSubscribersQuery.php', 'PhabricatorSubscriptionTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorSubscriptionTriggerClock.php', + 'PhabricatorSubscriptionsAddSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsAddSelfHeraldAction.php', + 'PhabricatorSubscriptionsAddSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsAddSubscribersHeraldAction.php', 'PhabricatorSubscriptionsApplication' => 'applications/subscriptions/application/PhabricatorSubscriptionsApplication.php', 'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php', 'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php', + 'PhabricatorSubscriptionsHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php', 'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.php', + 'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php', + 'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php', 'PhabricatorSubscriptionsSubscribeEmailCommand' => 'applications/subscriptions/command/PhabricatorSubscriptionsSubscribeEmailCommand.php', 'PhabricatorSubscriptionsSubscribersPolicyRule' => 'applications/subscriptions/policyrule/PhabricatorSubscriptionsSubscribersPolicyRule.php', 'PhabricatorSubscriptionsTransactionController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php', @@ -2937,7 +2985,6 @@ phutil_register_library_map(array( 'PhabricatorTrivialTestCase' => 'infrastructure/testing/__tests__/PhabricatorTrivialTestCase.php', 'PhabricatorTwitchAuthProvider' => 'applications/auth/provider/PhabricatorTwitchAuthProvider.php', 'PhabricatorTwitterAuthProvider' => 'applications/auth/provider/PhabricatorTwitterAuthProvider.php', - 'PhabricatorTwoColumnUIExample' => 'applications/uiexample/examples/PhabricatorTwoColumnUIExample.php', 'PhabricatorTypeaheadApplication' => 'applications/typeahead/application/PhabricatorTypeaheadApplication.php', 'PhabricatorTypeaheadCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php', 'PhabricatorTypeaheadDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php', @@ -3357,6 +3404,8 @@ phutil_register_library_map(array( 'PonderEditor' => 'applications/ponder/editor/PonderEditor.php', 'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php', 'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php', + 'PonderQuestionDefaultEditCapability' => 'applications/ponder/capability/PonderQuestionDefaultEditCapability.php', + 'PonderQuestionDefaultViewCapability' => 'applications/ponder/capability/PonderQuestionDefaultViewCapability.php', 'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php', 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 'PonderQuestionHasVotingUserEdgeType' => 'applications/ponder/edge/PonderQuestionHasVotingUserEdgeType.php', @@ -3716,7 +3765,6 @@ phutil_register_library_map(array( 'AphrontTableView' => 'AphrontView', 'AphrontTagView' => 'AphrontView', 'AphrontTokenizerTemplateView' => 'AphrontView', - 'AphrontTwoColumnView' => 'AphrontView', 'AphrontTypeaheadTemplateView' => 'AphrontView', 'AphrontURIMapper' => 'Phobject', 'AphrontUnhandledExceptionResponse' => 'AphrontStandaloneHTMLResponse', @@ -3868,6 +3916,7 @@ phutil_register_library_map(array( 'DifferentialAuditorsField' => 'DifferentialStoredCustomField', 'DifferentialAuthorField' => 'DifferentialCustomField', 'DifferentialBlameRevisionField' => 'DifferentialStoredCustomField', + 'DifferentialBlockHeraldAction' => 'HeraldAction', 'DifferentialBranchField' => 'DifferentialCustomField', 'DifferentialChangeHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialChangeType' => 'Phobject', @@ -4015,7 +4064,12 @@ phutil_register_library_map(array( 'DifferentialReviewer' => 'Phobject', 'DifferentialReviewerForRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialReviewerStatus' => 'Phobject', + 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', + 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'DifferentialReviewersHeraldAction', + 'DifferentialReviewersAddReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', + 'DifferentialReviewersAddSelfHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersField' => 'DifferentialCoreCustomField', + 'DifferentialReviewersHeraldAction' => 'HeraldAction', 'DifferentialReviewersView' => 'AphrontView', 'DifferentialRevision' => array( 'DifferentialDAO', @@ -4087,6 +4141,10 @@ phutil_register_library_map(array( 'DifferentialUpdateUnitResultsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialViewPolicyField' => 'DifferentialCoreCustomField', 'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', + 'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction', + 'DiffusionAuditorsAddSelfHeraldAction' => 'DiffusionAuditorsHeraldAction', + 'DiffusionAuditorsHeraldAction' => 'HeraldAction', + 'DiffusionBlockHeraldAction' => 'HeraldAction', 'DiffusionBranchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBranchTableController' => 'DiffusionController', 'DiffusionBranchTableView' => 'DiffusionView', @@ -4606,6 +4664,7 @@ phutil_register_library_map(array( ), 'HarbormasterBuildStepCustomField' => 'PhabricatorCustomField', 'HarbormasterBuildStepEditor' => 'PhabricatorApplicationTransactionEditor', + 'HarbormasterBuildStepGroup' => 'Phobject', 'HarbormasterBuildStepImplementation' => 'Phobject', 'HarbormasterBuildStepImplementationTestCase' => 'PhabricatorTestCase', 'HarbormasterBuildStepPHIDType' => 'PhabricatorPHIDType', @@ -4639,10 +4698,12 @@ phutil_register_library_map(array( 'HarbormasterBuildableTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildableTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildableViewController' => 'HarbormasterController', + 'HarbormasterBuiltinBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterCommandBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod', 'HarbormasterController' => 'PhabricatorController', 'HarbormasterDAO' => 'PhabricatorLiskDAO', + 'HarbormasterExternalBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterHTTPRequestBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterLeaseHostBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterLintMessagesController' => 'HarbormasterController', @@ -4651,18 +4712,22 @@ phutil_register_library_map(array( 'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementUpdateWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementWorkflow' => 'PhabricatorManagementWorkflow', + 'HarbormasterMessageType' => 'Phobject', 'HarbormasterObject' => 'HarbormasterDAO', + 'HarbormasterOtherBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterPlanController' => 'HarbormasterController', 'HarbormasterPlanDisableController' => 'HarbormasterPlanController', 'HarbormasterPlanEditController' => 'HarbormasterPlanController', 'HarbormasterPlanListController' => 'HarbormasterPlanController', 'HarbormasterPlanRunController' => 'HarbormasterController', 'HarbormasterPlanViewController' => 'HarbormasterPlanController', + 'HarbormasterPrototypeBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterPublishFragmentBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterQueryAutotargetsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterQueryBuildablesConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterQueryBuildsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterRemarkupRule' => 'PhabricatorObjectRemarkupRule', + 'HarbormasterRunBuildPlansHeraldAction' => 'HeraldAction', 'HarbormasterSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HarbormasterScratchTable' => 'HarbormasterDAO', 'HarbormasterSendMessageConduitAPIMethod' => 'HarbormasterConduitAPIMethod', @@ -4672,6 +4737,7 @@ phutil_register_library_map(array( 'HarbormasterStepEditController' => 'HarbormasterController', 'HarbormasterTargetEngine' => 'Phobject', 'HarbormasterTargetWorker' => 'HarbormasterWorker', + 'HarbormasterTestBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterThrowExceptionBuildStep' => 'HarbormasterBuildStepImplementation', 'HarbormasterUIEventListener' => 'PhabricatorEventListener', 'HarbormasterUnitMessagesController' => 'HarbormasterController', @@ -4679,42 +4745,54 @@ phutil_register_library_map(array( 'HarbormasterUploadArtifactBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterWaitForPreviousBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterWorker' => 'PhabricatorWorker', + 'HeraldAction' => 'Phobject', + 'HeraldActionGroup' => 'HeraldGroup', 'HeraldActionRecord' => 'HeraldDAO', 'HeraldAdapter' => 'Phobject', 'HeraldAlwaysField' => 'HeraldField', 'HeraldAnotherRuleField' => 'HeraldField', + 'HeraldApplicationActionGroup' => 'HeraldActionGroup', 'HeraldApplyTranscript' => 'Phobject', 'HeraldBasicFieldGroup' => 'HeraldFieldGroup', - 'HeraldCommitAdapter' => 'HeraldAdapter', + 'HeraldCommitAdapter' => array( + 'HeraldAdapter', + 'HarbormasterBuildableAdapterInterface', + ), 'HeraldCondition' => 'HeraldDAO', 'HeraldConditionTranscript' => 'Phobject', 'HeraldContentSourceField' => 'HeraldField', 'HeraldController' => 'PhabricatorController', - 'HeraldCustomAction' => 'Phobject', 'HeraldDAO' => 'PhabricatorLiskDAO', 'HeraldDifferentialAdapter' => 'HeraldAdapter', 'HeraldDifferentialDiffAdapter' => 'HeraldDifferentialAdapter', - 'HeraldDifferentialRevisionAdapter' => 'HeraldDifferentialAdapter', + 'HeraldDifferentialRevisionAdapter' => array( + 'HeraldDifferentialAdapter', + 'HarbormasterBuildableAdapterInterface', + ), 'HeraldDisableController' => 'HeraldController', + 'HeraldDoNothingAction' => 'HeraldAction', 'HeraldEditFieldGroup' => 'HeraldFieldGroup', 'HeraldEffect' => 'Phobject', 'HeraldEmptyFieldValue' => 'HeraldFieldValue', 'HeraldEngine' => 'Phobject', 'HeraldField' => 'Phobject', - 'HeraldFieldGroup' => 'Phobject', + 'HeraldFieldGroup' => 'HeraldGroup', 'HeraldFieldTestCase' => 'PhutilTestCase', 'HeraldFieldValue' => 'Phobject', + 'HeraldGroup' => 'Phobject', 'HeraldInvalidActionException' => 'Exception', 'HeraldInvalidConditionException' => 'Exception', 'HeraldManageGlobalRulesCapability' => 'PhabricatorPolicyCapability', 'HeraldManiphestTaskAdapter' => 'HeraldAdapter', 'HeraldNewController' => 'HeraldController', 'HeraldNewObjectField' => 'HeraldField', + 'HeraldNotifyActionGroup' => 'HeraldActionGroup', 'HeraldObjectTranscript' => 'Phobject', 'HeraldPholioMockAdapter' => 'HeraldAdapter', 'HeraldPreCommitAdapter' => 'HeraldAdapter', 'HeraldPreCommitContentAdapter' => 'HeraldPreCommitAdapter', 'HeraldPreCommitRefAdapter' => 'HeraldPreCommitAdapter', + 'HeraldPreventActionGroup' => 'HeraldActionGroup', 'HeraldProjectsField' => 'HeraldField', 'HeraldRecursiveConditionsException' => 'Exception', 'HeraldRelatedFieldGroup' => 'HeraldFieldGroup', @@ -4743,6 +4821,7 @@ phutil_register_library_map(array( 'HeraldSelectFieldValue' => 'HeraldFieldValue', 'HeraldSpaceField' => 'HeraldField', 'HeraldSubscribersField' => 'HeraldField', + 'HeraldSupportActionGroup' => 'HeraldActionGroup', 'HeraldSupportFieldGroup' => 'HeraldFieldGroup', 'HeraldTestConsoleController' => 'HeraldController', 'HeraldTextFieldValue' => 'HeraldFieldValue', @@ -4759,6 +4838,7 @@ phutil_register_library_map(array( 'HeraldTranscriptQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HeraldTranscriptSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HeraldTranscriptTestCase' => 'PhabricatorTestCase', + 'HeraldUtilityActionGroup' => 'HeraldActionGroup', 'Javelin' => 'Phobject', 'JavelinReactorUIExample' => 'PhabricatorUIExample', 'JavelinUIExample' => 'PhabricatorUIExample', @@ -4804,6 +4884,7 @@ phutil_register_library_map(array( 'LegalpadMailReceiver' => 'PhabricatorObjectMailReceiver', 'LegalpadObjectNeedsSignatureEdgeType' => 'PhabricatorEdgeType', 'LegalpadReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', + 'LegalpadRequireSignatureHeraldAction' => 'HeraldAction', 'LegalpadSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'LegalpadSignatureNeededByObjectEdgeType' => 'PhabricatorEdgeType', 'LegalpadTransaction' => 'PhabricatorApplicationTransaction', @@ -4889,6 +4970,9 @@ phutil_register_library_map(array( 'PhabricatorProjectInterface', 'PhabricatorSpacesInterface', ), + 'ManiphestTaskAssignHeraldAction' => 'HeraldAction', + 'ManiphestTaskAssignOtherHeraldAction' => 'ManiphestTaskAssignHeraldAction', + 'ManiphestTaskAssignSelfHeraldAction' => 'ManiphestTaskAssignHeraldAction', 'ManiphestTaskAssigneeHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskAuthorHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskAuthorPolicyRule' => 'PhabricatorPolicyRule', @@ -5115,6 +5199,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', + 'PhabricatorSubscribableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', ), @@ -5388,6 +5473,7 @@ phutil_register_library_map(array( 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', + 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', ), @@ -5402,10 +5488,12 @@ phutil_register_library_map(array( 'PhabricatorBadgesEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorBadgesIcon' => 'Phobject', 'PhabricatorBadgesListController' => 'PhabricatorBadgesController', + 'PhabricatorBadgesMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorBadgesPHIDType' => 'PhabricatorPHIDType', 'PhabricatorBadgesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorBadgesRecipientsListView' => 'AphrontTagView', 'PhabricatorBadgesRemoveRecipientsController' => 'PhabricatorBadgesController', + 'PhabricatorBadgesReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorBadgesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorBadgesSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorBadgesTransaction' => 'PhabricatorApplicationTransaction', @@ -5644,6 +5732,7 @@ phutil_register_library_map(array( 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCountdownListController' => 'PhabricatorCountdownController', + 'PhabricatorCountdownMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorCountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCountdownRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorCountdownReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', @@ -5918,6 +6007,7 @@ phutil_register_library_map(array( 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', + 'PhabricatorTokenReceiverInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorFileImageTransform' => 'PhabricatorFileTransform', @@ -5962,6 +6052,7 @@ phutil_register_library_map(array( 'PhabricatorFlagDAO', 'PhabricatorPolicyInterface', ), + 'PhabricatorFlagAddFlagHeraldAction' => 'HeraldAction', 'PhabricatorFlagColor' => 'PhabricatorFlagConstants', 'PhabricatorFlagConstants' => 'Phobject', 'PhabricatorFlagController' => 'PhabricatorController', @@ -6090,6 +6181,7 @@ phutil_register_library_map(array( 'PhabricatorMailManagementSendTestWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', + 'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorMailReceiver' => 'Phobject', 'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase', @@ -6137,6 +6229,9 @@ phutil_register_library_map(array( 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', 'PhabricatorMetaMTAEmailBodyParser' => 'Phobject', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase', + 'PhabricatorMetaMTAEmailHeraldAction' => 'HeraldAction', + 'PhabricatorMetaMTAEmailOthersHeraldAction' => 'PhabricatorMetaMTAEmailHeraldAction', + 'PhabricatorMetaMTAEmailSelfHeraldAction' => 'PhabricatorMetaMTAEmailHeraldAction', 'PhabricatorMetaMTAErrorMailAction' => 'PhabricatorSystemAction', 'PhabricatorMetaMTAMail' => array( 'PhabricatorMetaMTADAO', @@ -6457,6 +6552,7 @@ phutil_register_library_map(array( 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', ), + 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectApplication' => 'PhabricatorApplication', 'PhabricatorProjectArchiveController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardController' => 'PhabricatorProjectController', @@ -6500,6 +6596,7 @@ phutil_register_library_map(array( 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorProjectFeedController' => 'PhabricatorProjectController', + 'PhabricatorProjectHeraldAction' => 'HeraldAction', 'PhabricatorProjectIcon' => 'Phobject', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectLogicalAndDatasource' => 'PhabricatorTypeaheadCompositeDatasource', @@ -6520,6 +6617,7 @@ phutil_register_library_map(array( 'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorProjectRemoveHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorProjectSearchField' => 'PhabricatorSearchTokenizerField', @@ -6774,6 +6872,7 @@ phutil_register_library_map(array( 'PhabricatorSlowvoteEditController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController', + 'PhabricatorSlowvoteMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvotePoll' => array( 'PhabricatorSlowvoteDAO', @@ -6789,6 +6888,7 @@ phutil_register_library_map(array( 'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvotePollPHIDType' => 'PhabricatorPHIDType', 'PhabricatorSlowvoteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorSlowvoteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorSlowvoteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSlowvoteTransaction' => 'PhabricatorApplicationTransaction', @@ -6864,10 +6964,15 @@ phutil_register_library_map(array( 'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', 'PhabricatorSubscriptionTriggerClock' => 'PhabricatorTriggerClock', + 'PhabricatorSubscriptionsAddSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', + 'PhabricatorSubscriptionsAddSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsApplication' => 'PhabricatorApplication', 'PhabricatorSubscriptionsEditController' => 'PhabricatorController', 'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor', + 'PhabricatorSubscriptionsHeraldAction' => 'HeraldAction', 'PhabricatorSubscriptionsListController' => 'PhabricatorController', + 'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', + 'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsSubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorSubscriptionsSubscribersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorSubscriptionsTransactionController' => 'PhabricatorController', @@ -6940,7 +7045,6 @@ phutil_register_library_map(array( 'PhabricatorTrivialTestCase' => 'PhabricatorTestCase', 'PhabricatorTwitchAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorTwitterAuthProvider' => 'PhabricatorOAuth1AuthProvider', - 'PhabricatorTwoColumnUIExample' => 'PhabricatorUIExample', 'PhabricatorTypeaheadApplication' => 'PhabricatorApplication', 'PhabricatorTypeaheadCompositeDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorTypeaheadDatasource' => 'Phobject', @@ -7497,8 +7601,11 @@ phutil_register_library_map(array( 'PhabricatorTokenReceiverInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', + 'PhabricatorSpacesInterface', ), 'PonderQuestionCommentController' => 'PonderController', + 'PonderQuestionDefaultEditCapability' => 'PhabricatorPolicyCapability', + 'PonderQuestionDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PonderQuestionEditController' => 'PonderController', 'PonderQuestionEditor' => 'PonderEditor', 'PonderQuestionHasVotingUserEdgeType' => 'PhabricatorEdgeType', diff --git a/src/applications/audit/controller/PhabricatorAuditAddCommentController.php b/src/applications/audit/controller/PhabricatorAuditAddCommentController.php index 92c9beb933..b4bb950806 100644 --- a/src/applications/audit/controller/PhabricatorAuditAddCommentController.php +++ b/src/applications/audit/controller/PhabricatorAuditAddCommentController.php @@ -3,9 +3,8 @@ final class PhabricatorAuditAddCommentController extends PhabricatorAuditController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); if (!$request->isFormPost()) { return new Aphront403Response(); @@ -13,7 +12,7 @@ final class PhabricatorAuditAddCommentController $commit_phid = $request->getStr('commit'); $commit = id(new DiffusionCommitQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($commit_phid)) ->needAuditRequests(true) ->executeOne(); @@ -61,7 +60,7 @@ final class PhabricatorAuditAddCommentController } $inlines = PhabricatorAuditInlineComment::loadDraftComments( - $user, + $viewer, $commit->getPHID()); foreach ($inlines as $inline) { $xactions[] = id(new PhabricatorAuditTransaction()) @@ -70,14 +69,14 @@ final class PhabricatorAuditAddCommentController } id(new PhabricatorAuditEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->applyTransactions($commit, $xactions); $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', - $user->getPHID(), + $viewer->getPHID(), 'diffusion-audit-'.$commit->getID()); if ($draft) { $draft->delete(); diff --git a/src/applications/audit/controller/PhabricatorAuditPreviewController.php b/src/applications/audit/controller/PhabricatorAuditPreviewController.php index f27b55ae34..2b0212370c 100644 --- a/src/applications/audit/controller/PhabricatorAuditPreviewController.php +++ b/src/applications/audit/controller/PhabricatorAuditPreviewController.php @@ -3,17 +3,11 @@ final class PhabricatorAuditPreviewController extends PhabricatorAuditController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $commit = id(new PhabricatorRepositoryCommit())->load($this->id); + $commit = id(new PhabricatorRepositoryCommit())->load($id); if (!$commit) { return new Aphront404Response(); } @@ -23,7 +17,7 @@ final class PhabricatorAuditPreviewController $action = $request->getStr('action'); if ($action != PhabricatorAuditActionConstants::COMMENT) { $action_xaction = id(new PhabricatorAuditTransaction()) - ->setAuthorPHID($user->getPHID()) + ->setAuthorPHID($viewer->getPHID()) ->setObjectPHID($commit->getPHID()) ->setTransactionType(PhabricatorAuditActionConstants::ACTION) ->setNewValue($action); @@ -52,7 +46,7 @@ final class PhabricatorAuditPreviewController $content = $request->getStr('content'); if (strlen($content)) { $xactions[] = id(new PhabricatorAuditTransaction()) - ->setAuthorPHID($user->getPHID()) + ->setAuthorPHID($viewer->getPHID()) ->setObjectPHID($commit->getPHID()) ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) ->attachComment( @@ -72,13 +66,13 @@ final class PhabricatorAuditPreviewController $view = id(new PhabricatorAuditTransactionView()) ->setIsPreview(true) - ->setUser($user) + ->setUser($viewer) ->setObjectPHID($commit->getPHID()) ->setTransactions($xactions); id(new PhabricatorDraft()) - ->setAuthorPHID($user->getPHID()) - ->setDraftKey('diffusion-audit-'.$this->id) + ->setAuthorPHID($viewer->getPHID()) + ->setDraftKey('diffusion-audit-'.$id) ->setDraft($content) ->replaceOrDelete(); diff --git a/src/applications/audit/editor/PhabricatorAuditEditor.php b/src/applications/audit/editor/PhabricatorAuditEditor.php index 95f8ee8311..7c0f3d2e34 100644 --- a/src/applications/audit/editor/PhabricatorAuditEditor.php +++ b/src/applications/audit/editor/PhabricatorAuditEditor.php @@ -170,7 +170,7 @@ final class PhabricatorAuditEditor $audit_requested = PhabricatorAuditStatusConstants::AUDIT_REQUESTED; $audit_reason = $this->getAuditReasons($phid); } - $requests[] = id (new PhabricatorRepositoryAuditRequest()) + $requests[] = id(new PhabricatorRepositoryAuditRequest()) ->setCommitPHID($object->getPHID()) ->setAuditorPHID($phid) ->setAuditStatus($audit_requested) @@ -877,35 +877,6 @@ final class PhabricatorAuditEditor HeraldAdapter $adapter, HeraldTranscript $transcript) { - $xactions = array(); - - $audit_phids = $adapter->getAuditMap(); - foreach ($audit_phids as $phid => $rule_ids) { - foreach ($rule_ids as $rule_id) { - $this->addAuditReason( - $phid, - pht( - '%s Triggered Audit', - "H{$rule_id}")); - } - } - - if ($audit_phids) { - $xactions[] = id(new PhabricatorAuditTransaction()) - ->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS) - ->setNewValue(array_fuse(array_keys($audit_phids))) - ->setMetadataValue( - 'auditStatus', - PhabricatorAuditStatusConstants::AUDIT_REQUIRED) - ->setMetadataValue( - 'auditReasonMap', $this->auditReasonMap); - } - - HarbormasterBuildable::applyBuildPlans( - $object->getPHID(), - $object->getRepository()->getPHID(), - $adapter->getBuildPlans()); - $limit = self::MAX_FILES_SHOWN_IN_EMAIL; $files = $adapter->loadAffectedPaths(); sort($files); @@ -919,7 +890,7 @@ final class PhabricatorAuditEditor } $this->affectedFiles = implode("\n", $files); - return $xactions; + return array(); } private function isCommitMostlyImported(PhabricatorLiskDAO $object) { diff --git a/src/applications/auth/controller/PhabricatorAuthConfirmLinkController.php b/src/applications/auth/controller/PhabricatorAuthConfirmLinkController.php index 32c0101b8a..799a8e691e 100644 --- a/src/applications/auth/controller/PhabricatorAuthConfirmLinkController.php +++ b/src/applications/auth/controller/PhabricatorAuthConfirmLinkController.php @@ -3,17 +3,11 @@ final class PhabricatorAuthConfirmLinkController extends PhabricatorAuthController { - private $accountKey; + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $accountkey = $request->getURIData('akey'); - public function willProcessRequest(array $data) { - $this->accountKey = idx($data, 'akey'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $result = $this->loadAccountForRegistrationOrLinking($this->accountKey); + $result = $this->loadAccountForRegistrationOrLinking($accountkey); list($account, $provider, $response) = $result; if ($response) { diff --git a/src/applications/auth/controller/PhabricatorAuthDowngradeSessionController.php b/src/applications/auth/controller/PhabricatorAuthDowngradeSessionController.php index c4b6b2ad43..4981845876 100644 --- a/src/applications/auth/controller/PhabricatorAuthDowngradeSessionController.php +++ b/src/applications/auth/controller/PhabricatorAuthDowngradeSessionController.php @@ -3,9 +3,8 @@ final class PhabricatorAuthDowngradeSessionController extends PhabricatorAuthController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); $panel_uri = '/settings/panel/sessions/'; diff --git a/src/applications/auth/controller/PhabricatorAuthFinishController.php b/src/applications/auth/controller/PhabricatorAuthFinishController.php index 82f4d72b26..387679b44e 100644 --- a/src/applications/auth/controller/PhabricatorAuthFinishController.php +++ b/src/applications/auth/controller/PhabricatorAuthFinishController.php @@ -15,9 +15,8 @@ final class PhabricatorAuthFinishController return true; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); // If the user already has a full session, just kick them out of here. $has_partial_session = $viewer->hasSession() && diff --git a/src/applications/auth/controller/PhabricatorAuthLinkController.php b/src/applications/auth/controller/PhabricatorAuthLinkController.php index 75d63004b4..d50bcf1d8a 100644 --- a/src/applications/auth/controller/PhabricatorAuthLinkController.php +++ b/src/applications/auth/controller/PhabricatorAuthLinkController.php @@ -3,25 +3,18 @@ final class PhabricatorAuthLinkController extends PhabricatorAuthController { - private $action; - private $providerKey; - - public function willProcessRequest(array $data) { - $this->providerKey = $data['pkey']; - $this->action = $data['action']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $action = $request->getURIData('action'); + $provider_key = $request->getURIData('pkey'); $provider = PhabricatorAuthProvider::getEnabledProviderByKey( - $this->providerKey); + $provider_key); if (!$provider) { return new Aphront404Response(); } - switch ($this->action) { + switch ($action) { case 'link': if (!$provider->shouldAllowAccountLink()) { return $this->renderErrorPage( @@ -50,7 +43,7 @@ final class PhabricatorAuthLinkController $provider->getProviderDomain(), $viewer->getPHID()); - switch ($this->action) { + switch ($action) { case 'link': if ($account) { return $this->renderErrorPage( @@ -81,7 +74,7 @@ final class PhabricatorAuthLinkController PhabricatorCookies::setClientIDCookie($request); - switch ($this->action) { + switch ($action) { case 'link': id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession( $viewer, @@ -107,7 +100,7 @@ final class PhabricatorAuthLinkController $form); } - switch ($this->action) { + switch ($action) { case 'link': $name = pht('Link Account'); $title = pht('Link %s Account', $provider->getProviderName()); diff --git a/src/applications/auth/controller/PhabricatorAuthLoginController.php b/src/applications/auth/controller/PhabricatorAuthLoginController.php index e3cbeaa2c6..65d462cb8e 100644 --- a/src/applications/auth/controller/PhabricatorAuthLoginController.php +++ b/src/applications/auth/controller/PhabricatorAuthLoginController.php @@ -20,18 +20,14 @@ final class PhabricatorAuthLoginController return parent::shouldAllowRestrictedParameter($parameter_name); } - public function willProcessRequest(array $data) { - $this->providerKey = $data['pkey']; - $this->extraURIData = idx($data, 'extra'); - } - public function getExtraURIData() { return $this->extraURIData; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $this->providerKey = $request->getURIData('pkey'); + $this->extraURIData = $request->getURIData('extra'); $response = $this->loadProvider(); if ($response) { diff --git a/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php b/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php index 8e0bf99551..0d07470560 100644 --- a/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php +++ b/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php @@ -15,16 +15,15 @@ final class PhabricatorAuthNeedsApprovalController return false; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); $wait_for_approval = pht( "Your account has been created, but needs to be approved by an ". "administrator. You'll receive an email once your account is approved."); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Wait for Approval')) ->appendChild($wait_for_approval) ->addCancelButton('/', pht('Wait Patiently')); diff --git a/src/applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php b/src/applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php index 975355ec97..aaf3864156 100644 --- a/src/applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php +++ b/src/applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php @@ -9,9 +9,8 @@ final class PhabricatorAuthNeedsMultiFactorController return false; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); $panel = id(new PhabricatorMultiFactorSettingsPanel()) ->setUser($viewer) diff --git a/src/applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php b/src/applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php index cc7f362583..6b75b929ab 100644 --- a/src/applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php +++ b/src/applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php @@ -3,8 +3,6 @@ final class PhabricatorAuthOldOAuthRedirectController extends PhabricatorAuthController { - private $provider; - public function shouldRequireLogin() { return false; } @@ -16,11 +14,9 @@ final class PhabricatorAuthOldOAuthRedirectController return parent::shouldAllowRestrictedParameter($parameter_name); } - public function willProcessRequest(array $data) { - $this->provider = $data['provider']; - } - - public function processRequest() { + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $provider = $request->getURIData('provider'); // TODO: Most OAuth providers are OK with changing the redirect URI, but // Google and GitHub are strict. We need to respect the old OAuth URI until // we can get installs to migrate. This just keeps the old OAuth URI working @@ -31,11 +27,11 @@ final class PhabricatorAuthOldOAuthRedirectController 'github' => 'github:github.com', ); - if (!isset($provider_map[$this->provider])) { + if (!isset($provider_map[$provider])) { return new Aphront404Response(); } - $provider_key = $provider_map[$this->provider]; + $provider_key = $provider_map[$provider]; $uri = $this->getRequest()->getRequestURI(); $uri->setPath($this->getApplicationURI('login/'.$provider_key.'/')); diff --git a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php index 312367d03a..6dfa49d860 100644 --- a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php +++ b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php @@ -3,24 +3,16 @@ final class PhabricatorAuthOneTimeLoginController extends PhabricatorAuthController { - private $id; - private $key; - private $emailID; - private $linkType; - public function shouldRequireLogin() { return false; } - public function willProcessRequest(array $data) { - $this->linkType = $data['type']; - $this->id = $data['id']; - $this->key = $data['key']; - $this->emailID = idx($data, 'emailID'); - } - - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); + $link_type = $request->getURIData('type'); + $key = $request->getURIData('key'); + $email_id = $request->getURIData('emailID'); if ($request->getUser()->isLoggedIn()) { return $this->renderError( @@ -29,7 +21,7 @@ final class PhabricatorAuthOneTimeLoginController $target_user = id(new PhabricatorPeopleQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$target_user) { return new Aphront404Response(); @@ -58,11 +50,11 @@ final class PhabricatorAuthOneTimeLoginController // - get a "verified" address you don't control. $target_email = null; - if ($this->emailID) { + if ($email_id) { $target_email = id(new PhabricatorUserEmail())->loadOneWhere( 'userPHID = %s AND id = %d', $target_user->getPHID(), - $this->emailID); + $email_id); if (!$target_email) { return new Aphront404Response(); } @@ -72,7 +64,7 @@ final class PhabricatorAuthOneTimeLoginController $token = $engine->loadOneTimeLoginKey( $target_user, $target_email, - $this->key); + $key); if (!$token) { return $this->newDialog() @@ -154,7 +146,7 @@ final class PhabricatorAuthOneTimeLoginController // then log a user in to an account they control via sneaky invisible // form submissions. - switch ($this->linkType) { + switch ($link_type) { case PhabricatorAuthSessionEngine::ONETIME_WELCOME: $title = pht('Welcome to Phabricator'); break; diff --git a/src/applications/auth/controller/PhabricatorAuthRegisterController.php b/src/applications/auth/controller/PhabricatorAuthRegisterController.php index 9341345143..655f63acb9 100644 --- a/src/applications/auth/controller/PhabricatorAuthRegisterController.php +++ b/src/applications/auth/controller/PhabricatorAuthRegisterController.php @@ -3,26 +3,21 @@ final class PhabricatorAuthRegisterController extends PhabricatorAuthController { - private $accountKey; - public function shouldRequireLogin() { return false; } - public function willProcessRequest(array $data) { - $this->accountKey = idx($data, 'akey'); - } - - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $account_key = $request->getURIData('akey'); if ($request->getUser()->isLoggedIn()) { return $this->renderError(pht('You are already logged in.')); } $is_setup = false; - if (strlen($this->accountKey)) { - $result = $this->loadAccountForRegistrationOrLinking($this->accountKey); + if (strlen($account_key)) { + $result = $this->loadAccountForRegistrationOrLinking($account_key); list($account, $provider, $response) = $result; $is_default = false; } else if ($this->isFirstTimeSetup()) { diff --git a/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php b/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php index 27981eee27..c1f0c21cb1 100644 --- a/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php +++ b/src/applications/auth/controller/PhabricatorAuthRevokeTokenController.php @@ -3,23 +3,17 @@ final class PhabricatorAuthRevokeTokenController extends PhabricatorAuthController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $is_all = ($this->id === 'all'); + $is_all = ($id === 'all'); $query = id(new PhabricatorAuthTemporaryTokenQuery()) ->setViewer($viewer) ->withObjectPHIDs(array($viewer->getPHID())); if (!$is_all) { - $query->withIDs(array($this->id)); + $query->withIDs(array($id)); } $tokens = $query->execute(); diff --git a/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php b/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php index bb4acd0b4d..d09d52cc14 100644 --- a/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php +++ b/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php @@ -5,8 +5,8 @@ final class PhabricatorAuthSSHKeyEditController public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); - $id = $request->getURIData('id'); + if ($id) { $key = id(new PhabricatorAuthSSHKeyQuery()) ->setViewer($viewer) diff --git a/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php b/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php index d2534c4a45..ae8179a798 100644 --- a/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php +++ b/src/applications/auth/controller/PhabricatorAuthTerminateSessionController.php @@ -3,23 +3,17 @@ final class PhabricatorAuthTerminateSessionController extends PhabricatorAuthController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - $is_all = ($this->id === 'all'); + $is_all = ($id === 'all'); $query = id(new PhabricatorAuthSessionQuery()) ->setViewer($viewer) ->withIdentityPHIDs(array($viewer->getPHID())); if (!$is_all) { - $query->withIDs(array($this->id)); + $query->withIDs(array($id)); } $current_key = PhabricatorHash::digest( diff --git a/src/applications/auth/controller/PhabricatorAuthUnlinkController.php b/src/applications/auth/controller/PhabricatorAuthUnlinkController.php index a5bdf90b70..3f694207b9 100644 --- a/src/applications/auth/controller/PhabricatorAuthUnlinkController.php +++ b/src/applications/auth/controller/PhabricatorAuthUnlinkController.php @@ -5,13 +5,9 @@ final class PhabricatorAuthUnlinkController private $providerKey; - public function willProcessRequest(array $data) { - $this->providerKey = $data['pkey']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $this->providerKey = $request->getURIData('pkey'); list($type, $domain) = explode(':', $this->providerKey, 2); diff --git a/src/applications/auth/controller/PhabricatorAuthValidateController.php b/src/applications/auth/controller/PhabricatorAuthValidateController.php index c91f3c4504..bb45a68acf 100644 --- a/src/applications/auth/controller/PhabricatorAuthValidateController.php +++ b/src/applications/auth/controller/PhabricatorAuthValidateController.php @@ -15,9 +15,8 @@ final class PhabricatorAuthValidateController return true; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); $failures = array(); diff --git a/src/applications/auth/controller/PhabricatorDisabledUserController.php b/src/applications/auth/controller/PhabricatorDisabledUserController.php index 842f2daad6..39e390d44a 100644 --- a/src/applications/auth/controller/PhabricatorDisabledUserController.php +++ b/src/applications/auth/controller/PhabricatorDisabledUserController.php @@ -7,15 +7,16 @@ final class PhabricatorDisabledUserController return false; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - if (!$user->getIsDisabled()) { + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); + + if (!$viewer->getIsDisabled()) { return new Aphront404Response(); } return id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Account Disabled')) ->addCancelButton('/logout/', pht('Okay')) ->appendParagraph(pht('Your account has been disabled.')); diff --git a/src/applications/auth/controller/PhabricatorEmailLoginController.php b/src/applications/auth/controller/PhabricatorEmailLoginController.php index 9db360d51d..26609133ea 100644 --- a/src/applications/auth/controller/PhabricatorEmailLoginController.php +++ b/src/applications/auth/controller/PhabricatorEmailLoginController.php @@ -7,8 +7,7 @@ final class PhabricatorEmailLoginController return false; } - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { if (!PhabricatorPasswordAuthProvider::getPasswordProvider()) { return new Aphront400Response(); diff --git a/src/applications/auth/controller/PhabricatorEmailVerificationController.php b/src/applications/auth/controller/PhabricatorEmailVerificationController.php index ea5f273d79..83a370139c 100644 --- a/src/applications/auth/controller/PhabricatorEmailVerificationController.php +++ b/src/applications/auth/controller/PhabricatorEmailVerificationController.php @@ -3,12 +3,6 @@ final class PhabricatorEmailVerificationController extends PhabricatorAuthController { - private $code; - - public function willProcessRequest(array $data) { - $this->code = $data['code']; - } - public function shouldRequireEmailVerification() { // Since users need to be able to hit this endpoint in order to verify // email, we can't ever require email verification here. @@ -21,11 +15,11 @@ final class PhabricatorEmailVerificationController return false; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $code = $request->getURIData('code'); - if ($user->getIsDisabled()) { + if ($viewer->getIsDisabled()) { // We allowed unapproved and disabled users to hit this controller, but // want to kick out disabled users now. return new Aphront400Response(); @@ -33,8 +27,8 @@ final class PhabricatorEmailVerificationController $email = id(new PhabricatorUserEmail())->loadOneWhere( 'userPHID = %s AND verificationCode = %s', - $user->getPHID(), - $this->code); + $viewer->getPHID(), + $code); $submit = null; @@ -46,7 +40,7 @@ final class PhabricatorEmailVerificationController 'user. Make sure you followed the link in the email correctly and are '. 'logged in with the user account associated with the email address.'); $continue = pht('Rats!'); - } else if ($email->getIsVerified() && $user->getIsEmailVerified()) { + } else if ($email->getIsVerified() && $viewer->getIsEmailVerified()) { $title = pht('Address Already Verified'); $content = pht( 'This email address has already been verified.'); @@ -54,8 +48,8 @@ final class PhabricatorEmailVerificationController } else if ($request->isFormPost()) { id(new PhabricatorUserEditor()) - ->setActor($user) - ->verifyEmail($user, $email); + ->setActor($viewer) + ->verifyEmail($viewer, $email); $title = pht('Address Verified'); $content = pht( @@ -72,7 +66,7 @@ final class PhabricatorEmailVerificationController } $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle($title) ->addCancelButton('/', $continue) ->appendChild($content); diff --git a/src/applications/auth/controller/PhabricatorLogoutController.php b/src/applications/auth/controller/PhabricatorLogoutController.php index 127e5b5e1f..de3ac50e5d 100644 --- a/src/applications/auth/controller/PhabricatorLogoutController.php +++ b/src/applications/auth/controller/PhabricatorLogoutController.php @@ -26,14 +26,13 @@ final class PhabricatorLogoutController } public function handleRequest(AphrontRequest $request) { - $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $this->getViewer(); if ($request->isFormPost()) { $log = PhabricatorUserLog::initializeNewLog( - $user, - $user->getPHID(), + $viewer, + $viewer->getPHID(), PhabricatorUserLog::ACTION_LOGOUT); $log->save(); @@ -43,7 +42,7 @@ final class PhabricatorLogoutController $phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION); if (strlen($phsid)) { $session = id(new PhabricatorAuthSessionQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withSessionKeys(array($phsid)) ->executeOne(); if ($session) { @@ -56,9 +55,9 @@ final class PhabricatorLogoutController ->setURI('/auth/loggedout/'); } - if ($user->getPHID()) { + if ($viewer->getPHID()) { $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Log out of Phabricator?')) ->appendChild(pht('Are you sure you want to log out?')) ->addSubmitButton(pht('Logout')) diff --git a/src/applications/auth/controller/PhabricatorMustVerifyEmailController.php b/src/applications/auth/controller/PhabricatorMustVerifyEmailController.php index e64096e4be..779196382d 100644 --- a/src/applications/auth/controller/PhabricatorMustVerifyEmailController.php +++ b/src/applications/auth/controller/PhabricatorMustVerifyEmailController.php @@ -13,13 +13,12 @@ final class PhabricatorMustVerifyEmailController return false; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); - $email = $user->loadPrimaryEmail(); + $email = $viewer->loadPrimaryEmail(); - if ($user->getIsEmailVerified()) { + if ($viewer->getIsEmailVerified()) { return id(new AphrontRedirectResponse())->setURI('/'); } @@ -27,7 +26,7 @@ final class PhabricatorMustVerifyEmailController $sent = null; if ($request->isFormPost()) { - $email->sendVerificationEmail($user); + $email->sendVerificationEmail($viewer); $sent = new PHUIInfoView(); $sent->setSeverity(PHUIInfoView::SEVERITY_NOTICE); $sent->setTitle(pht('Email Sent')); @@ -48,7 +47,7 @@ final class PhabricatorMustVerifyEmailController 'to try sending another one.'); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Check Your Email')) ->appendParagraph($must_verify) ->appendParagraph($send_again) diff --git a/src/applications/auth/controller/PhabricatorRefreshCSRFController.php b/src/applications/auth/controller/PhabricatorRefreshCSRFController.php index 19d7aa7eb1..fc1d5cc02d 100644 --- a/src/applications/auth/controller/PhabricatorRefreshCSRFController.php +++ b/src/applications/auth/controller/PhabricatorRefreshCSRFController.php @@ -2,14 +2,13 @@ final class PhabricatorRefreshCSRFController extends PhabricatorAuthController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); return id(new AphrontAjaxResponse()) ->setContent( array( - 'token' => $user->getCSRFToken(), + 'token' => $viewer->getCSRFToken(), )); } diff --git a/src/applications/badges/editor/PhabricatorBadgesEditor.php b/src/applications/badges/editor/PhabricatorBadgesEditor.php index d060c6df7a..a6cd90bb92 100644 --- a/src/applications/badges/editor/PhabricatorBadgesEditor.php +++ b/src/applications/badges/editor/PhabricatorBadgesEditor.php @@ -142,6 +142,23 @@ final class PhabricatorBadgesEditor return $errors; } + protected function shouldSendMail( + PhabricatorLiskDAO $object, + array $xactions) { + return true; + } + + public function getMailTagsMap() { + return array( + PhabricatorBadgesTransaction::MAILTAG_DETAILS => + pht('Someone changes the badge\'s details.'), + PhabricatorBadgesTransaction::MAILTAG_COMMENT => + pht('Someone comments on a badge.'), + PhabricatorBadgesTransaction::MAILTAG_OTHER => + pht('Other badge activity not listed above occurs.'), + ); + } + protected function shouldPublishFeedStory( PhabricatorLiskDAO $object, array $xactions) { @@ -149,7 +166,7 @@ final class PhabricatorBadgesEditor } protected function buildReplyHandler(PhabricatorLiskDAO $object) { - return id(new PhabricatorMacroReplyHandler()) + return id(new PhabricatorBadgesReplyHandler()) ->setMailReceiver($object); } @@ -164,6 +181,7 @@ final class PhabricatorBadgesEditor protected function getMailTo(PhabricatorLiskDAO $object) { return array( + $object->getCreatorPHID(), $this->requireActor()->getPHID(), ); } diff --git a/src/applications/badges/mail/PhabricatorBadgesMailReceiver.php b/src/applications/badges/mail/PhabricatorBadgesMailReceiver.php new file mode 100644 index 0000000000..4e72c8422d --- /dev/null +++ b/src/applications/badges/mail/PhabricatorBadgesMailReceiver.php @@ -0,0 +1,28 @@ +setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + } + + protected function getTransactionReplyHandler() { + return new PhabricatorBadgesReplyHandler(); + } + +} diff --git a/src/applications/badges/mail/PhabricatorBadgesReplyHandler.php b/src/applications/badges/mail/PhabricatorBadgesReplyHandler.php new file mode 100644 index 0000000000..af03dd7e2a --- /dev/null +++ b/src/applications/badges/mail/PhabricatorBadgesReplyHandler.php @@ -0,0 +1,16 @@ +setIcon(self::DEFAULT_ICON) ->setQuality(self::DEFAULT_QUALITY) ->setCreatorPHID($actor->getPHID()) - ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->setStatus(self::STATUS_OPEN); } @@ -87,6 +87,7 @@ final class PhabricatorBadgesBadge extends PhabricatorBadgesDAO 'icon' => 'text255', 'quality' => 'text255', 'status' => 'text32', + 'mailKey' => 'bytes20', ), self::CONFIG_KEY_SCHEMA => array( 'key_creator' => array( @@ -114,6 +115,13 @@ final class PhabricatorBadgesBadge extends PhabricatorBadgesDAO return $this->assertAttached($this->recipientPHIDs); } + public function save() { + if (!$this->getMailKey()) { + $this->setMailKey(Filesystem::readRandomCharacters(20)); + } + return parent::save(); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ @@ -182,6 +190,15 @@ final class PhabricatorBadgesBadge extends PhabricatorBadgesDAO } +/* -( PhabricatorTokenReceiverInterface )---------------------------------- */ + + + public function getUsersToNotifyOfTokenGiven() { + return array($this->getCreatorPHID()); + } + + + /* -( PhabricatorDestructibleInterface )----------------------------------- */ diff --git a/src/applications/badges/storage/PhabricatorBadgesTransaction.php b/src/applications/badges/storage/PhabricatorBadgesTransaction.php index e7ab4eab6a..c50297f768 100644 --- a/src/applications/badges/storage/PhabricatorBadgesTransaction.php +++ b/src/applications/badges/storage/PhabricatorBadgesTransaction.php @@ -10,6 +10,11 @@ final class PhabricatorBadgesTransaction const TYPE_STATUS = 'badges:status'; const TYPE_FLAVOR = 'badges:flavor'; + const MAILTAG_NAME = 'badges:name'; + const MAILTAG_DETAILS = 'badges:details'; + const MAILTAG_COMMENT = 'badges:comment'; + const MAILTAG_OTHER = 'badges:other'; + public function getApplicationName() { return 'badges'; } @@ -168,6 +173,28 @@ final class PhabricatorBadgesTransaction return parent::getTitleForFeed(); } + public function getMailTags() { + $tags = parent::getMailTags(); + + switch ($this->getTransactionType()) { + case PhabricatorTransactions::TYPE_COMMENT: + $tags[] = self::MAILTAG_COMMENT; + break; + case self::TYPE_NAME: + case self::TYPE_DESCRIPTION: + case self::TYPE_FLAVOR: + case self::TYPE_ICON: + case self::TYPE_STATUS: + case self::TYPE_QUALITY: + $tags[] = self::MAILTAG_DETAILS; + break; + default: + $tags[] = self::MAILTAG_OTHER; + break; + } + return $tags; + } + public function shouldHide() { $old = $this->getOldValue(); diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php b/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php index 8cbd594bea..4be5a77d11 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventCancelController.php @@ -3,20 +3,14 @@ final class PhabricatorCalendarEventCancelController extends PhabricatorCalendarController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $sequence = $request->getURIData('sequence'); $event = id(new PhabricatorCalendarEventQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -26,7 +20,7 @@ final class PhabricatorCalendarEventCancelController if ($sequence) { $parent_event = $event; - $event = $parent_event->generateNthGhost($sequence, $user); + $event = $parent_event->generateNthGhost($sequence, $viewer); $event->attachParentEvent($parent_event); } @@ -51,10 +45,10 @@ final class PhabricatorCalendarEventCancelController return id(new AphrontRedirectResponse())->setURI($cancel_uri); } else if ($sequence) { $event = $this->createEventFromGhost( - $user, + $viewer, $event, $sequence); - $event->applyViewerTimezone($user); + $event->applyViewerTimezone($viewer); } $xactions = array(); @@ -65,7 +59,7 @@ final class PhabricatorCalendarEventCancelController ->setNewValue(!$is_cancelled); $editor = id(new PhabricatorCalendarEventEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true); diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventCommentController.php b/src/applications/calendar/controller/PhabricatorCalendarEventCommentController.php index 9094de5401..876712a455 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventCommentController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventCommentController.php @@ -3,24 +3,20 @@ final class PhabricatorCalendarEventCommentController extends PhabricatorCalendarController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - public function handleRequest(AphrontRequest $request) { if (!$request->isFormPost()) { return new Aphront400Response(); } - $user = $request->getUser(); + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $is_preview = $request->isPreviewRequest(); $draft = PhabricatorDraft::buildFromRequest($request); $event = id(new PhabricatorCalendarEventQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$event) { return new Aphront404Response(); @@ -29,7 +25,7 @@ final class PhabricatorCalendarEventCommentController $index = $request->getURIData('sequence'); if ($index && !$is_preview) { $result = $this->getEventAtIndexForGhostPHID( - $user, + $viewer, $event->getPHID(), $index); @@ -37,10 +33,10 @@ final class PhabricatorCalendarEventCommentController $event = $result; } else { $event = $this->createEventFromGhost( - $user, + $viewer, $event, $index); - $event->applyViewerTimezone($user); + $event->applyViewerTimezone($viewer); } } @@ -54,7 +50,7 @@ final class PhabricatorCalendarEventCommentController ->setContent($request->getStr('comment'))); $editor = id(new PhabricatorCalendarEventEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect($request->isContinueRequest()) ->setContentSourceFromRequest($request) ->setIsPreview($is_preview); @@ -73,7 +69,7 @@ final class PhabricatorCalendarEventCommentController if ($request->isAjax() && $is_preview) { return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setIsPreview($is_preview); } else { diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php index 07da53fa67..e55b0debaa 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditController.php @@ -5,10 +5,6 @@ final class PhabricatorCalendarEventEditController private $id; - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - public function isCreate() { return !$this->id; } @@ -16,6 +12,8 @@ final class PhabricatorCalendarEventEditController public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $user_phid = $viewer->getPHID(); + $this->id = $request->getURIData('id'); + $error_name = true; $error_recurrence_end_date = null; $error_start_date = true; diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php b/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php index a8c9af97fb..e93baa52bd 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventEditIconController.php @@ -3,19 +3,14 @@ final class PhabricatorCalendarEventEditIconController extends PhabricatorCalendarController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - public function handleRequest(AphrontRequest $request) { $viewer = $request->getUser(); + $id = $request->getURIData('id'); - if ($this->id) { + if ($id) { $event = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php b/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php index 60cde4f561..a7f41c4a0c 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventJoinController.php @@ -3,14 +3,12 @@ final class PhabricatorCalendarEventJoinController extends PhabricatorCalendarController { - private $id; - const ACTION_ACCEPT = 'accept'; const ACTION_DECLINE = 'decline'; const ACTION_JOIN = 'join'; public function handleRequest(AphrontRequest $request) { - $this->id = $request->getURIData('id'); + $id = $request->getURIData('id'); $action = $request->getURIData('action'); $request = $this->getRequest(); @@ -20,7 +18,7 @@ final class PhabricatorCalendarEventJoinController $event = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$event) { diff --git a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php index 580e5ea5ee..a0d5be4e4d 100644 --- a/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php +++ b/src/applications/calendar/controller/PhabricatorCalendarEventViewController.php @@ -3,26 +3,20 @@ final class PhabricatorCalendarEventViewController extends PhabricatorCalendarController { - private $id; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $sequence = $request->getURIData('sequence'); $timeline = null; $event = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$event) { return new Aphront404Response(); diff --git a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php index 4d2193f2bb..8614e68f56 100644 --- a/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php +++ b/src/applications/calendar/query/PhabricatorCalendarEventSearchEngine.php @@ -287,10 +287,21 @@ final class PhabricatorCalendarEventSearchEngine $event->getDuration()); } + if ($event->getIsGhostEvent()) { + $title_text = $event->getMonogram() + .' (' + .$event->getSequenceIndex() + .'): ' + .$event->getName(); + } else { + $title_text = $event->getMonogram().': '.$event->getName(); + } + $item = id(new PHUIObjectItemView()) ->setUser($viewer) ->setObject($event) - ->setHeader($viewer->renderHandle($event->getPHID())->render()) + ->setHeader($title_text) + ->setHref($event->getURI()) ->addAttribute($event_date_info) ->addAttribute($attendees) ->addIcon('none', $duration); diff --git a/src/applications/chatlog/controller/PhabricatorChatLogChannelListController.php b/src/applications/chatlog/controller/PhabricatorChatLogChannelListController.php index a7c5c68153..cdff189633 100644 --- a/src/applications/chatlog/controller/PhabricatorChatLogChannelListController.php +++ b/src/applications/chatlog/controller/PhabricatorChatLogChannelListController.php @@ -7,12 +7,11 @@ final class PhabricatorChatLogChannelListController return true; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $channels = id(new PhabricatorChatLogChannelQuery()) - ->setViewer($user) + ->setViewer($viewer) ->execute(); $list = new PHUIObjectItemListView(); diff --git a/src/applications/chatlog/controller/PhabricatorChatLogChannelLogController.php b/src/applications/chatlog/controller/PhabricatorChatLogChannelLogController.php index 4281adf421..8084356ced 100644 --- a/src/applications/chatlog/controller/PhabricatorChatLogChannelLogController.php +++ b/src/applications/chatlog/controller/PhabricatorChatLogChannelLogController.php @@ -3,19 +3,13 @@ final class PhabricatorChatLogChannelLogController extends PhabricatorChatLogController { - private $channelID; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->channelID = $data['channelID']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('channelID'); $uri = clone $request->getRequestURI(); $uri->setQueryParams(array()); @@ -25,12 +19,12 @@ final class PhabricatorChatLogChannelLogController $pager->setPageSize(250); $query = id(new PhabricatorChatLogQuery()) - ->setViewer($user) - ->withChannelIDs(array($this->channelID)); + ->setViewer($viewer) + ->withChannelIDs(array($id)); $channel = id(new PhabricatorChatLogChannelQuery()) - ->setViewer($user) - ->withIDs(array($this->channelID)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$channel) { @@ -115,7 +109,7 @@ final class PhabricatorChatLogChannelLogController $href = $uri->alter('at', $block['id']); $timestamp = $block['epoch']; - $timestamp = phabricator_datetime($timestamp, $user); + $timestamp = phabricator_datetime($timestamp, $viewer); $timestamp = phutil_tag( 'a', array( @@ -189,7 +183,7 @@ final class PhabricatorChatLogChannelLogController ->addTextCrumb($channel->getChannelName(), $uri); $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->setMethod('GET') ->setAction($uri) ->appendChild( @@ -273,7 +267,7 @@ final class PhabricatorChatLogChannelLogController AphrontRequest $request, PhabricatorChatLogQuery $query) { - $user = $request->getUser(); + $viewer = $request->getViewer(); $at_id = $request->getInt('at'); $at_date = $request->getStr('date'); @@ -298,7 +292,7 @@ final class PhabricatorChatLogChannelLogController ); } else if ($at_date) { - $timestamp = PhabricatorTime::parseLocalTime($at_date, $user); + $timestamp = PhabricatorTime::parseLocalTime($at_date, $viewer); if ($timestamp) { $context_logs = $query diff --git a/src/applications/conduit/method/ConduitAPIMethod.php b/src/applications/conduit/method/ConduitAPIMethod.php index 4472f80864..39fa9b66f4 100644 --- a/src/applications/conduit/method/ConduitAPIMethod.php +++ b/src/applications/conduit/method/ConduitAPIMethod.php @@ -1,18 +1,41 @@ getMethodDescription(); + } + + + /** + * Get a detailed description of the method. + * + * This method should return remarkup. + * + * @return string Detailed description of the method. + * @task info + */ abstract public function getMethodDescription(); + abstract protected function defineParamTypes(); abstract protected function defineReturnType(); diff --git a/src/applications/conduit/query/PhabricatorConduitSearchEngine.php b/src/applications/conduit/query/PhabricatorConduitSearchEngine.php index 5e12cf7f99..6c067a8ff4 100644 --- a/src/applications/conduit/query/PhabricatorConduitSearchEngine.php +++ b/src/applications/conduit/query/PhabricatorConduitSearchEngine.php @@ -174,7 +174,7 @@ final class PhabricatorConduitSearchEngine $item = id(new PHUIObjectItemView()) ->setHeader($method_name) ->setHref($this->getApplicationURI('method/'.$method_name.'/')) - ->addAttribute($method->getMethodDescription()); + ->addAttribute($method->getMethodSummary()); switch ($method->getMethodStatus()) { case ConduitAPIMethod::METHOD_STATUS_STABLE: diff --git a/src/applications/config/controller/PhabricatorConfigAllController.php b/src/applications/config/controller/PhabricatorConfigAllController.php index 309304ed21..17bf65fd7b 100644 --- a/src/applications/config/controller/PhabricatorConfigAllController.php +++ b/src/applications/config/controller/PhabricatorConfigAllController.php @@ -3,9 +3,8 @@ final class PhabricatorConfigAllController extends PhabricatorConfigController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $db_values = id(new PhabricatorConfigEntry()) ->loadAllWhere('namespace = %s', 'default'); diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php b/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php index 252d8a73de..22df5104e4 100644 --- a/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php +++ b/src/applications/config/controller/PhabricatorConfigDatabaseIssueController.php @@ -3,9 +3,8 @@ final class PhabricatorConfigDatabaseIssueController extends PhabricatorConfigDatabaseController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $query = $this->buildSchemaQuery(); diff --git a/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php b/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php index f69e794fb8..d886e98d74 100644 --- a/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php +++ b/src/applications/config/controller/PhabricatorConfigDatabaseStatusController.php @@ -8,16 +8,12 @@ final class PhabricatorConfigDatabaseStatusController private $column; private $key; - public function willProcessRequest(array $data) { - $this->database = idx($data, 'database'); - $this->table = idx($data, 'table'); - $this->column = idx($data, 'column'); - $this->key = idx($data, 'key'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $this->database = $request->getURIData('database'); + $this->table = $request->getURIData('table'); + $this->column = $request->getURIData('column'); + $this->key = $request->getURIData('key'); $query = $this->buildSchemaQuery(); diff --git a/src/applications/config/controller/PhabricatorConfigEditController.php b/src/applications/config/controller/PhabricatorConfigEditController.php index f3360b3496..90547f41f7 100644 --- a/src/applications/config/controller/PhabricatorConfigEditController.php +++ b/src/applications/config/controller/PhabricatorConfigEditController.php @@ -3,25 +3,19 @@ final class PhabricatorConfigEditController extends PhabricatorConfigController { - private $key; - - public function willProcessRequest(array $data) { - $this->key = $data['key']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $key = $request->getURIData('key'); $options = PhabricatorApplicationConfigOptions::loadAllOptions(); - if (empty($options[$this->key])) { + if (empty($options[$key])) { $ancient = PhabricatorExtraConfigSetupCheck::getAncientConfig(); - if (isset($ancient[$this->key])) { + if (isset($ancient[$key])) { $desc = pht( "This configuration has been removed. You can safely delete ". "it.\n\n%s", - $ancient[$this->key]); + $ancient[$key]); } else { $desc = pht( 'This configuration option is unknown. It may be misspelled, '. @@ -32,14 +26,14 @@ final class PhabricatorConfigEditController // longer exists. Allow it to be edited so it can be reviewed and // deleted. $option = id(new PhabricatorConfigOption()) - ->setKey($this->key) + ->setKey($key) ->setType('wild') ->setDefault(null) ->setDescription($desc); $group = null; $group_uri = $this->getApplicationURI(); } else { - $option = $options[$this->key]; + $option = $options[$key]; $group = $option->getGroup(); $group_uri = $this->getApplicationURI('group/'.$group->getKey().'/'); } @@ -57,11 +51,11 @@ final class PhabricatorConfigEditController $config_entry = id(new PhabricatorConfigEntry()) ->loadOneWhere( 'configKey = %s AND namespace = %s', - $this->key, + $key, 'default'); if (!$config_entry) { $config_entry = id(new PhabricatorConfigEntry()) - ->setConfigKey($this->key) + ->setConfigKey($key) ->setNamespace('default') ->setIsDeleted(true); $config_entry->setPHID($config_entry->generatePHID()); @@ -81,7 +75,7 @@ final class PhabricatorConfigEditController if (!$errors) { $editor = id(new PhabricatorConfigEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request); @@ -138,7 +132,7 @@ final class PhabricatorConfigEditController } $engine = new PhabricatorMarkupEngine(); - $engine->setViewer($user); + $engine->setViewer($viewer); $engine->addObject($option, 'description'); $engine->process(); $description = phutil_tag( @@ -149,7 +143,7 @@ final class PhabricatorConfigEditController $engine->getOutput($option, 'description')); $form - ->setUser($user) + ->setUser($viewer) ->addHiddenInput('issue', $request->getStr('issue')) ->appendChild( id(new AphrontFormMarkupControl()) @@ -194,7 +188,7 @@ final class PhabricatorConfigEditController ->setValue($this->renderDefaults($option, $config_entry))); } - $title = pht('Edit %s', $this->key); + $title = pht('Edit %s', $key); $short = pht('Edit'); $form_box = id(new PHUIObjectBoxView()) @@ -212,7 +206,7 @@ final class PhabricatorConfigEditController $crumbs->addTextCrumb($group->getName(), $group_uri); } - $crumbs->addTextCrumb($this->key, '/config/edit/'.$this->key); + $crumbs->addTextCrumb($key, '/config/edit/'.$key); $timeline = $this->buildTransactionTimeline( $config_entry, diff --git a/src/applications/config/controller/PhabricatorConfigGroupController.php b/src/applications/config/controller/PhabricatorConfigGroupController.php index b9dffd9a08..4569491427 100644 --- a/src/applications/config/controller/PhabricatorConfigGroupController.php +++ b/src/applications/config/controller/PhabricatorConfigGroupController.php @@ -3,18 +3,12 @@ final class PhabricatorConfigGroupController extends PhabricatorConfigController { - private $groupKey; - - public function willProcessRequest(array $data) { - $this->groupKey = $data['key']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $group_key = $request->getURIData('key'); $groups = PhabricatorApplicationConfigOptions::loadAll(); - $options = idx($groups, $this->groupKey); + $options = idx($groups, $group_key); if (!$options) { return new Aphront404Response(); } diff --git a/src/applications/config/controller/PhabricatorConfigHistoryController.php b/src/applications/config/controller/PhabricatorConfigHistoryController.php index acb1d3c297..d86fb79878 100644 --- a/src/applications/config/controller/PhabricatorConfigHistoryController.php +++ b/src/applications/config/controller/PhabricatorConfigHistoryController.php @@ -3,12 +3,12 @@ final class PhabricatorConfigHistoryController extends PhabricatorConfigController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $xactions = id(new PhabricatorConfigTransactionQuery()) - ->setViewer($user) + ->setViewer($viewer) ->needComments(true) ->execute(); @@ -19,7 +19,7 @@ final class PhabricatorConfigHistoryController $view = $xaction->getApplicationTransactionViewObject(); $timeline = $view - ->setUser($user) + ->setUser($viewer) ->setTransactions($xactions) ->setRenderAsFeed(true) ->setObjectPHID(PhabricatorPHIDConstants::PHID_VOID); diff --git a/src/applications/config/controller/PhabricatorConfigIgnoreController.php b/src/applications/config/controller/PhabricatorConfigIgnoreController.php index ba634dec1a..80a859c147 100644 --- a/src/applications/config/controller/PhabricatorConfigIgnoreController.php +++ b/src/applications/config/controller/PhabricatorConfigIgnoreController.php @@ -3,38 +3,33 @@ final class PhabricatorConfigIgnoreController extends PhabricatorConfigController { - private $verb; - private $issue; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $issue = $request->getURIData('key'); + $verb = $request->getURIData('verb'); - public function willProcessRequest(array $data) { - $this->verb = $data['verb']; - $this->issue = $data['key']; - } - - public function processRequest() { - $request = $this->getRequest(); - $issue_uri = $this->getApplicationURI('issue/'.$this->issue.'/'); + $issue_uri = $this->getApplicationURI('issue/'.$issue.'/'); if ($request->isDialogFormPost()) { - $this->manageApplication(); + $this->manageApplication($issue); return id(new AphrontRedirectResponse())->setURI($issue_uri); } - if ($this->verb == 'ignore') { + if ($verb == 'ignore') { $title = pht('Really ignore this setup issue?'); $submit_title = pht('Ignore'); $body = pht( "You can ignore an issue if you don't want to fix it, or plan to ". "fix it later. Ignored issues won't appear on every page but will ". "still be shown in the list of open issues."); - } else if ($this->verb == 'unignore') { + } else if ($verb == 'unignore') { $title = pht('Unignore this setup issue?'); $submit_title = pht('Unignore'); $body = pht( 'This issue will no longer be suppressed, and will return to its '. 'rightful place as a global setup warning.'); } else { - throw new Exception(pht('Unrecognized verb: %s', $this->verb)); + throw new Exception(pht('Unrecognized verb: %s', $verb)); } $dialog = id(new AphrontDialogView()) @@ -47,15 +42,15 @@ final class PhabricatorConfigIgnoreController return id(new AphrontDialogResponse())->setDialog($dialog); } - public function manageApplication() { + public function manageApplication($issue) { $key = 'config.ignore-issues'; $config_entry = PhabricatorConfigEntry::loadConfigEntry($key); $list = $config_entry->getValue(); - if (isset($list[$this->issue])) { - unset($list[$this->issue]); + if (isset($list[$issue])) { + unset($list[$issue]); } else { - $list[$this->issue] = true; + $list[$issue] = true; } PhabricatorConfigEditor::storeNewValue( diff --git a/src/applications/config/controller/PhabricatorConfigIssueListController.php b/src/applications/config/controller/PhabricatorConfigIssueListController.php index d1d19860b9..89b8ea7cd6 100644 --- a/src/applications/config/controller/PhabricatorConfigIssueListController.php +++ b/src/applications/config/controller/PhabricatorConfigIssueListController.php @@ -3,9 +3,8 @@ final class PhabricatorConfigIssueListController extends PhabricatorConfigController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $nav = $this->buildSideNavView(); $nav->selectFilter('issue/'); diff --git a/src/applications/config/controller/PhabricatorConfigIssueViewController.php b/src/applications/config/controller/PhabricatorConfigIssueViewController.php index a2beb8ae76..e8d6e188a4 100644 --- a/src/applications/config/controller/PhabricatorConfigIssueViewController.php +++ b/src/applications/config/controller/PhabricatorConfigIssueViewController.php @@ -3,21 +3,15 @@ final class PhabricatorConfigIssueViewController extends PhabricatorConfigController { - private $issueKey; - - public function willProcessRequest(array $data) { - $this->issueKey = $data['key']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $issue_key = $request->getURIData('key'); $issues = PhabricatorSetupCheck::runAllChecks(); PhabricatorSetupCheck::setOpenSetupIssueKeys( PhabricatorSetupCheck::getUnignoredIssueKeys($issues)); - if (empty($issues[$this->issueKey])) { + if (empty($issues[$issue_key])) { $content = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setTitle(pht('Issue Resolved')) @@ -31,7 +25,7 @@ final class PhabricatorConfigIssueViewController pht('Return to Open Issue List'))); $title = pht('Resolved Issue'); } else { - $issue = $issues[$this->issueKey]; + $issue = $issues[$issue_key]; $content = $this->renderIssue($issue); $title = $issue->getShortName(); } diff --git a/src/applications/config/controller/PhabricatorConfigListController.php b/src/applications/config/controller/PhabricatorConfigListController.php index 4da4f2ac01..6a1823ecda 100644 --- a/src/applications/config/controller/PhabricatorConfigListController.php +++ b/src/applications/config/controller/PhabricatorConfigListController.php @@ -3,9 +3,8 @@ final class PhabricatorConfigListController extends PhabricatorConfigController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $nav = $this->buildSideNavView(); $nav->selectFilter('/'); diff --git a/src/applications/config/controller/PhabricatorConfigWelcomeController.php b/src/applications/config/controller/PhabricatorConfigWelcomeController.php index 11132af08b..37442c2375 100644 --- a/src/applications/config/controller/PhabricatorConfigWelcomeController.php +++ b/src/applications/config/controller/PhabricatorConfigWelcomeController.php @@ -3,9 +3,8 @@ final class PhabricatorConfigWelcomeController extends PhabricatorConfigController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $nav = $this->buildSideNavView(); $nav->selectFilter('welcome/'); diff --git a/src/applications/conpherence/controller/ConpherenceNewRoomController.php b/src/applications/conpherence/controller/ConpherenceNewRoomController.php index 5578741e89..40dd6b2572 100644 --- a/src/applications/conpherence/controller/ConpherenceNewRoomController.php +++ b/src/applications/conpherence/controller/ConpherenceNewRoomController.php @@ -7,6 +7,7 @@ final class ConpherenceNewRoomController extends ConpherenceController { $title = pht('New Room'); $e_title = true; + $v_message = null; $validation_exception = null; $conpherence = ConpherenceThread::initializeNewRoom($user); @@ -35,12 +36,12 @@ final class ConpherenceNewRoomController extends ConpherenceController { ->setTransactionType(PhabricatorTransactions::TYPE_JOIN_POLICY) ->setNewValue($request->getStr('joinPolicy')); - $message = $request->getStr('message'); - if ($message) { + $v_message = $request->getStr('message'); + if (strlen($v_message)) { $message_xactions = $editor->generateTransactionsFromText( $user, $conpherence, - $message); + $v_message); $xactions = array_merge($xactions, $message_xactions); } @@ -121,7 +122,8 @@ final class ConpherenceNewRoomController extends ConpherenceController { id(new PhabricatorRemarkupControl()) ->setUser($user) ->setName('message') - ->setLabel(pht('First Message'))); + ->setLabel(pht('First Message')) + ->setValue($v_message)); $dialog->appendChild($form); diff --git a/src/applications/countdown/controller/PhabricatorCountdownDeleteController.php b/src/applications/countdown/controller/PhabricatorCountdownDeleteController.php index 5dfbd18146..81129f3beb 100644 --- a/src/applications/countdown/controller/PhabricatorCountdownDeleteController.php +++ b/src/applications/countdown/controller/PhabricatorCountdownDeleteController.php @@ -3,19 +3,13 @@ final class PhabricatorCountdownDeleteController extends PhabricatorCountdownController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $countdown = id(new PhabricatorCountdownQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/countdown/controller/PhabricatorCountdownListController.php b/src/applications/countdown/controller/PhabricatorCountdownListController.php index f3c34d23aa..031e5430fe 100644 --- a/src/applications/countdown/controller/PhabricatorCountdownListController.php +++ b/src/applications/countdown/controller/PhabricatorCountdownListController.php @@ -3,19 +3,15 @@ final class PhabricatorCountdownListController extends PhabricatorCountdownController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhabricatorCountdownSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/countdown/editor/PhabricatorCountdownEditor.php b/src/applications/countdown/editor/PhabricatorCountdownEditor.php index 7438e4ac02..97f8e5b947 100644 --- a/src/applications/countdown/editor/PhabricatorCountdownEditor.php +++ b/src/applications/countdown/editor/PhabricatorCountdownEditor.php @@ -160,7 +160,7 @@ final class PhabricatorCountdownEditor protected function buildMailTemplate(PhabricatorLiskDAO $object) { $monogram = $object->getMonogram(); - $name = $object->getName(); + $name = $object->getTitle(); return id(new PhabricatorMetaMTAMail()) ->setSubject("{$monogram}: {$name}") @@ -172,6 +172,13 @@ final class PhabricatorCountdownEditor array $xactions) { $body = parent::buildMailBody($object, $xactions); + $description = $object->getDescription(); + + if (strlen($description)) { + $body->addTextSection( + pht('COUNTDOWN DESCRIPTION'), + $object->getDescription()); + } $body->addLinkSection( pht('COUNTDOWN DETAIL'), @@ -181,11 +188,13 @@ final class PhabricatorCountdownEditor } protected function getMailTo(PhabricatorLiskDAO $object) { - return array($object->getAuthorPHID()); + return array( + $object->getAuthorPHID(), + $this->requireActor()->getPHID(), + ); } - protected function getMailSubjectPrefix() { - return 'Countdown'; + return '[Countdown]'; } protected function buildReplyHandler(PhabricatorLiskDAO $object) { diff --git a/src/applications/countdown/mail/PhabricatorCountdownMailReceiver.php b/src/applications/countdown/mail/PhabricatorCountdownMailReceiver.php new file mode 100644 index 0000000000..d0218de59b --- /dev/null +++ b/src/applications/countdown/mail/PhabricatorCountdownMailReceiver.php @@ -0,0 +1,28 @@ +setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + } + + protected function getTransactionReplyHandler() { + return new PhabricatorCountdownReplyHandler(); + } + +} diff --git a/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php b/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php index 74ee2b9518..b9f438ece8 100644 --- a/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php +++ b/src/applications/countdown/query/PhabricatorCountdownSearchEngine.php @@ -102,13 +102,9 @@ final class PhabricatorCountdownSearchEngine foreach ($countdowns as $countdown) { $id = $countdown->getID(); $ended = false; - $icon = 'fa-clock-o'; - $color = 'green'; $epoch = $countdown->getEpoch(); if ($epoch <= PhabricatorTime::getNow()) { $ended = true; - $icon = 'fa-check-square-o'; - $color = 'grey'; } $item = id(new PHUIObjectItemView()) @@ -116,7 +112,6 @@ final class PhabricatorCountdownSearchEngine ->setObject($countdown) ->setObjectName("C{$id}") ->setHeader($countdown->getTitle()) - ->setStatusIcon($icon.' '.$color) ->setHref($this->getApplicationURI("{$id}/")) ->addByline( pht( @@ -128,6 +123,14 @@ final class PhabricatorCountdownSearchEngine pht('Launched on %s', phabricator_datetime($epoch, $viewer))); $item->setDisabled(true); } else { + $time_left = ($epoch - PhabricatorTime::getNow()); + $num = round($time_left / (60 * 60 * 24)); + $noun = pht('Days'); + if ($num < 1) { + $num = round($time_left / (60 * 60), 1); + $noun = pht('Hours'); + } + $item->setCountdown($num, $noun); $item->addAttribute( phabricator_datetime($epoch, $viewer)); } diff --git a/src/applications/countdown/storage/PhabricatorCountdown.php b/src/applications/countdown/storage/PhabricatorCountdown.php index 01fd5d2509..8753c66223 100644 --- a/src/applications/countdown/storage/PhabricatorCountdown.php +++ b/src/applications/countdown/storage/PhabricatorCountdown.php @@ -16,7 +16,7 @@ final class PhabricatorCountdown extends PhabricatorCountdownDAO protected $description; protected $viewPolicy; protected $editPolicy; - + protected $mailKey; protected $spacePHID; public static function initializeNewCountdown(PhabricatorUser $actor) { @@ -41,6 +41,7 @@ final class PhabricatorCountdown extends PhabricatorCountdownDAO self::CONFIG_COLUMN_SCHEMA => array( 'title' => 'text255', 'description' => 'text', + 'mailKey' => 'bytes20', ), ) + parent::getConfiguration(); } @@ -54,6 +55,13 @@ final class PhabricatorCountdown extends PhabricatorCountdownDAO return 'C'.$this->getID(); } + public function save() { + if (!$this->getMailKey()) { + $this->setMailKey(Filesystem::readRandomCharacters(20)); + } + return parent::save(); + } + /* -( PhabricatorSubscribableInterface )----------------------------------- */ diff --git a/src/applications/countdown/storage/PhabricatorCountdownTransaction.php b/src/applications/countdown/storage/PhabricatorCountdownTransaction.php index e3241acd63..eace665a89 100644 --- a/src/applications/countdown/storage/PhabricatorCountdownTransaction.php +++ b/src/applications/countdown/storage/PhabricatorCountdownTransaction.php @@ -152,4 +152,29 @@ final class PhabricatorCountdownTransaction return $tags; } + public function shouldHide() { + $old = $this->getOldValue(); + switch ($this->getTransactionType()) { + case self::TYPE_DESCRIPTION: + return ($old === null); + } + return parent::shouldHide(); + } + + public function hasChangeDetails() { + switch ($this->getTransactionType()) { + case self::TYPE_DESCRIPTION: + return ($this->getOldValue() !== null); + } + + return parent::hasChangeDetails(); + } + + public function renderChangeDetails(PhabricatorUser $viewer) { + return $this->renderTextCorpusChangeDetails( + $viewer, + $this->getOldValue(), + $this->getNewValue()); + } + } diff --git a/src/applications/countdown/view/PhabricatorCountdownView.php b/src/applications/countdown/view/PhabricatorCountdownView.php index 7ede4ef887..2e8f1dedb3 100644 --- a/src/applications/countdown/view/PhabricatorCountdownView.php +++ b/src/applications/countdown/view/PhabricatorCountdownView.php @@ -56,6 +56,16 @@ final class PhabricatorCountdownView extends AphrontTagView { javelin_tag('td', array('sigil' => 'phabricator-timer-seconds'), '-'), ); + $epoch = $countdown->getEpoch(); + $launch_date = phabricator_datetime($epoch, $this->getUser()); + $foot = phutil_tag( + 'td', + array( + 'colspan' => '4', + 'class' => 'phabricator-timer-foot', + ), + $launch_date); + $container = celerity_generate_unique_node_id(); $content = phutil_tag( 'div', @@ -65,6 +75,7 @@ final class PhabricatorCountdownView extends AphrontTagView { phutil_tag('table', array('class' => 'phabricator-timer-table'), array( phutil_tag('tr', array(), $ths), phutil_tag('tr', array(), $dashes), + phutil_tag('tr', array(), $foot), )), )); diff --git a/src/applications/daemon/controller/PhabricatorDaemonConsoleController.php b/src/applications/daemon/controller/PhabricatorDaemonConsoleController.php index beaabae074..9f54726bc9 100644 --- a/src/applications/daemon/controller/PhabricatorDaemonConsoleController.php +++ b/src/applications/daemon/controller/PhabricatorDaemonConsoleController.php @@ -222,7 +222,6 @@ final class PhabricatorDaemonConsoleController $nav, array( 'title' => pht('Console'), - 'device' => false, )); } diff --git a/src/applications/differential/customfield/DifferentialUnitField.php b/src/applications/differential/customfield/DifferentialUnitField.php index daff8cf0d5..b5de9fce53 100644 --- a/src/applications/differential/customfield/DifferentialUnitField.php +++ b/src/applications/differential/customfield/DifferentialUnitField.php @@ -56,8 +56,14 @@ final class DifferentialUnitField protected function newHarbormasterMessageView(array $messages) { foreach ($messages as $key => $message) { - if ($message->getResult() == ArcanistUnitTestResult::RESULT_PASS) { - unset($messages[$key]); + switch ($message->getResult()) { + case ArcanistUnitTestResult::RESULT_PASS: + case ArcanistUnitTestResult::RESULT_SKIP: + // Don't show "Pass" or "Skip" in the UI since they aren't very + // interesting. The user can click through to the full results if + // they want details. + unset($messages[$key]); + break; } } diff --git a/src/applications/differential/editor/DifferentialDiffEditor.php b/src/applications/differential/editor/DifferentialDiffEditor.php index 235ab84c21..0058485e63 100644 --- a/src/applications/differential/editor/DifferentialDiffEditor.php +++ b/src/applications/differential/editor/DifferentialDiffEditor.php @@ -131,10 +131,11 @@ final class DifferentialDiffEditor $rules = mpull($rules, null, 'getID'); $effects = $engine->applyRules($rules, $adapter); + $action_block = DifferentialBlockHeraldAction::ACTIONCONST; $blocking_effect = null; foreach ($effects as $effect) { - if ($effect->getAction() == HeraldAdapter::ACTION_BLOCK) { + if ($effect->getAction() == $action_block) { $blocking_effect = $effect; break; } diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php index c73bb53956..2a8e907145 100644 --- a/src/applications/differential/editor/DifferentialTransactionEditor.php +++ b/src/applications/differential/editor/DifferentialTransactionEditor.php @@ -1588,112 +1588,9 @@ final class DifferentialTransactionEditor $revision, $revision->getActiveDiff()); - $reviewers = $revision->getReviewerStatus(); - $reviewer_phids = mpull($reviewers, 'getReviewerPHID'); - - $adapter->setExplicitReviewers($reviewer_phids); - return $adapter; } - protected function didApplyHeraldRules( - PhabricatorLiskDAO $object, - HeraldAdapter $adapter, - HeraldTranscript $transcript) { - - $xactions = array(); - - // Build a transaction to adjust reviewers. - $reviewers = array( - DifferentialReviewerStatus::STATUS_ADDED => - array_keys($adapter->getReviewersAddedByHerald()), - DifferentialReviewerStatus::STATUS_BLOCKING => - array_keys($adapter->getBlockingReviewersAddedByHerald()), - ); - - $old_reviewers = $object->getReviewerStatus(); - $old_reviewers = mpull($old_reviewers, null, 'getReviewerPHID'); - - $value = array(); - foreach ($reviewers as $status => $phids) { - foreach ($phids as $phid) { - if ($phid == $object->getAuthorPHID()) { - // Don't try to add the revision's author as a reviewer, since this - // isn't valid and doesn't make sense. - continue; - } - - // If the target is already a reviewer, don't try to change anything - // if their current status is at least as strong as the new status. - // For example, don't downgrade an "Accepted" to a "Blocking Reviewer". - $old_reviewer = idx($old_reviewers, $phid); - if ($old_reviewer) { - $old_status = $old_reviewer->getStatus(); - - $old_strength = DifferentialReviewerStatus::getStatusStrength( - $old_status); - $new_strength = DifferentialReviewerStatus::getStatusStrength( - $status); - - if ($new_strength <= $old_strength) { - continue; - } - } - - $value['+'][$phid] = array( - 'data' => array( - 'status' => $status, - ), - ); - } - } - - if ($value) { - $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; - - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $edge_reviewer) - ->setNewValue($value); - } - - // Require legalpad document signatures. - $legal_phids = $adapter->getRequiredSignatureDocumentPHIDs(); - if ($legal_phids) { - // We only require signatures of documents which have not already - // been signed. In general, this reduces the amount of churn that - // signature rules cause. - - $signatures = id(new LegalpadDocumentSignatureQuery()) - ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withDocumentPHIDs($legal_phids) - ->withSignerPHIDs(array($object->getAuthorPHID())) - ->execute(); - $signed_phids = mpull($signatures, 'getDocumentPHID'); - $legal_phids = array_diff($legal_phids, $signed_phids); - - // If we still have something to trigger, add the edges. - if ($legal_phids) { - $edge_legal = LegalpadObjectNeedsSignatureEdgeType::EDGECONST; - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $edge_legal) - ->setNewValue( - array( - '+' => array_fuse($legal_phids), - )); - } - } - - // Apply build plans. - HarbormasterBuildable::applyBuildPlans( - $adapter->getDiff()->getPHID(), - $adapter->getPHID(), - $adapter->getBuildPlans()); - - return $xactions; - } - /** * Update the table which links Differential revisions to paths they affect, * so Diffusion can efficiently find pending revisions for a given file. diff --git a/src/applications/differential/herald/DifferentialBlockHeraldAction.php b/src/applications/differential/herald/DifferentialBlockHeraldAction.php new file mode 100644 index 0000000000..33ad4a3480 --- /dev/null +++ b/src/applications/differential/herald/DifferentialBlockHeraldAction.php @@ -0,0 +1,56 @@ +logEffect(self::DO_BLOCK); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_TEXT; + } + + public function renderActionDescription($value) { + return pht('Block diff with message: %s', $value); + } + + protected function getActionEffectMap() { + return array( + self::DO_BLOCK => array( + 'icon' => 'fa-stop', + 'color' => 'red', + 'name' => pht('Blocked Diff'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_BLOCK: + return pht('Blocked diff.'); + } + } +} diff --git a/src/applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php b/src/applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php new file mode 100644 index 0000000000..79a00bc940 --- /dev/null +++ b/src/applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php @@ -0,0 +1,32 @@ +applyReviewers($effect->getTarget(), $is_blocking = true); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorMetaMTAMailableDatasource(); + } + + public function renderActionDescription($value) { + return pht('Add blocking reviewers: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php b/src/applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php new file mode 100644 index 0000000000..938f298955 --- /dev/null +++ b/src/applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php @@ -0,0 +1,29 @@ +getRule()->getAuthorPHID(); + return $this->applyReviewers(array($phid), $is_blocking = true); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Add rule author as blocking reviewer.'); + } + +} diff --git a/src/applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php b/src/applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php new file mode 100644 index 0000000000..45f209385e --- /dev/null +++ b/src/applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php @@ -0,0 +1,32 @@ +applyReviewers($effect->getTarget(), $is_blocking = false); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorMetaMTAMailableDatasource(); + } + + public function renderActionDescription($value) { + return pht('Add reviewers: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php b/src/applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php new file mode 100644 index 0000000000..a7e9991901 --- /dev/null +++ b/src/applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php @@ -0,0 +1,29 @@ +getRule()->getAuthorPHID(); + return $this->applyReviewers(array($phid), $is_blocking = false); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Add rule author as reviewer.'); + } + +} diff --git a/src/applications/differential/herald/DifferentialReviewersHeraldAction.php b/src/applications/differential/herald/DifferentialReviewersHeraldAction.php new file mode 100644 index 0000000000..c568537f7c --- /dev/null +++ b/src/applications/differential/herald/DifferentialReviewersHeraldAction.php @@ -0,0 +1,149 @@ +getAdapter(); + $object = $adapter->getObject(); + + $phids = array_fuse($phids); + + // Don't try to add revision authors as reviewers. + $authors = array(); + foreach ($phids as $phid) { + if ($phid == $object->getAuthorPHID()) { + $authors[] = $phid; + unset($phids[$phid]); + } + } + + if ($authors) { + $this->logEffect(self::DO_AUTHORS, $authors); + if (!$phids) { + return; + } + } + + $reviewers = $object->getReviewerStatus(); + $reviewers = mpull($reviewers, null, 'getReviewerPHID'); + + if ($is_blocking) { + $new_status = DifferentialReviewerStatus::STATUS_BLOCKING; + } else { + $new_status = DifferentialReviewerStatus::STATUS_ADDED; + } + + $new_strength = DifferentialReviewerStatus::getStatusStrength( + $new_status); + + $current = array(); + foreach ($phids as $phid) { + if (!isset($reviewers[$phid])) { + continue; + } + + // If we're applying a stronger status (usually, upgrading a reviewer + // into a blocking reviewer), skip this check so we apply the change. + $old_strength = DifferentialReviewerStatus::getStatusStrength( + $reviewers[$phid]->getStatus()); + if ($old_strength <= $new_strength) { + continue; + } + + $current[] = $phid; + } + + $allowed_types = array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + ); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + $value = array(); + foreach ($phids as $phid) { + $value[$phid] = array( + 'data' => array( + 'status' => $new_status, + ), + ); + } + + $edgetype_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; + + $xaction = $adapter->newTransaction() + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $edgetype_reviewer) + ->setNewValue( + array( + '+' => $value, + )); + + $adapter->queueTransaction($xaction); + + if ($is_blocking) { + $this->logEffect(self::DO_ADD_BLOCKING_REVIEWERS, $phids); + } else { + $this->logEffect(self::DO_ADD_REVIEWERS, $phids); + } + } + + protected function getActionEffectMap() { + return array( + self::DO_AUTHORS => array( + 'icon' => 'fa-user', + 'color' => 'grey', + 'name' => pht('Revision Author'), + ), + self::DO_ADD_REVIEWERS => array( + 'icon' => 'fa-user', + 'color' => 'green', + 'name' => pht('Added Reviewers'), + ), + self::DO_ADD_BLOCKING_REVIEWERS => array( + 'icon' => 'fa-user', + 'color' => 'green', + 'name' => pht('Added Blocking Reviewers'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_AUTHORS: + return pht( + 'Declined to add revision author as reviewer: %s.', + $this->renderHandleList($data)); + case self::DO_ADD_REVIEWERS: + return pht( + 'Added %s reviewer(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_ADD_BLOCKING_REVIEWERS: + return pht( + 'Added %s blocking reviewer(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + + +} diff --git a/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php b/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php index 225ba5b73d..9528978050 100644 --- a/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php +++ b/src/applications/differential/herald/HeraldDifferentialDiffAdapter.php @@ -63,44 +63,4 @@ final class HeraldDifferentialDiffAdapter extends HeraldDifferentialAdapter { return pht('New Diff'); } - public function getActionNameMap($rule_type) { - return array( - self::ACTION_BLOCK => pht('Block diff with message'), - ) + parent::getActionNameMap($rule_type); - } - - public function getActions($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - return array_merge( - array( - self::ACTION_BLOCK, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - } - } - - public function applyHeraldEffects(array $effects) { - assert_instances_of($effects, 'HeraldEffect'); - - $result = array(); - foreach ($effects as $effect) { - $action = $effect->getAction(); - switch ($action) { - case self::ACTION_BLOCK: - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Blocked diff.')); - break; - default: - $result[] = $this->applyStandardEffect($effect); - break; - } - } - - return $result; - } - } diff --git a/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php b/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php index d3264860d6..a47d433357 100644 --- a/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php +++ b/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php @@ -1,20 +1,17 @@ explicitReviewers = $explicit_reviewers; - return $this; - } - - public function getReviewersAddedByHerald() { - return $this->addReviewerPHIDs; - } - - public function getBlockingReviewersAddedByHerald() { - return $this->blockingReviewerPHIDs; - } - - public function getRequiredSignatureDocumentPHIDs() { - return $this->requiredSignatureDocumentPHIDs; - } - - public function getBuildPlans() { - return $this->buildPlans; - } - public function getHeraldName() { return $this->revision->getTitle(); } @@ -147,98 +123,28 @@ final class HeraldDifferentialRevisionAdapter } public function loadReviewers() { - // TODO: This can probably go away as I believe it's just a performance - // optimization, just retaining it while modularizing fields to limit the - // scope of that change. - if (isset($this->explicitReviewers)) { - return array_keys($this->explicitReviewers); - } else { - return $this->revision->getReviewers(); - } + $reviewers = $this->getObject()->getReviewerStatus(); + return mpull($reviewers, 'getReviewerPHID'); } - public function getActions($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_EMAIL, - self::ACTION_ADD_REVIEWERS, - self::ACTION_ADD_BLOCKING_REVIEWERS, - self::ACTION_APPLY_BUILD_PLANS, - self::ACTION_REQUIRE_SIGNATURE, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_EMAIL, - self::ACTION_FLAG, - self::ACTION_ADD_REVIEWERS, - self::ACTION_ADD_BLOCKING_REVIEWERS, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - } + +/* -( HarbormasterBuildableAdapterInterface )------------------------------ */ + + + public function getHarbormasterBuildablePHID() { + return $this->getDiff()->getPHID(); } - public function applyHeraldEffects(array $effects) { - assert_instances_of($effects, 'HeraldEffect'); + public function getHarbormasterContainerPHID() { + return $this->getObject()->getPHID(); + } - $result = array(); + public function getQueuedHarbormasterBuildPlanPHIDs() { + return $this->buildPlanPHIDs; + } - foreach ($effects as $effect) { - $action = $effect->getAction(); - switch ($action) { - case self::ACTION_ADD_REVIEWERS: - foreach ($effect->getTarget() as $phid) { - $this->addReviewerPHIDs[$phid] = true; - } - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Added reviewers.')); - break; - case self::ACTION_ADD_BLOCKING_REVIEWERS: - // This adds reviewers normally, it just also marks them blocking. - foreach ($effect->getTarget() as $phid) { - $this->addReviewerPHIDs[$phid] = true; - $this->blockingReviewerPHIDs[$phid] = true; - } - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Added blocking reviewers.')); - break; - case self::ACTION_APPLY_BUILD_PLANS: - foreach ($effect->getTarget() as $phid) { - $this->buildPlans[] = $phid; - } - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Applied build plans.')); - break; - case self::ACTION_REQUIRE_SIGNATURE: - foreach ($effect->getTarget() as $phid) { - $this->requiredSignatureDocumentPHIDs[] = $phid; - } - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Required signatures.')); - break; - default: - $result[] = $this->applyStandardEffect($effect); - break; - } - } - return $result; + public function queueHarbormasterBuildPlanPHID($phid) { + $this->buildPlanPHIDs[] = $phid; } } diff --git a/src/applications/diffusion/engine/DiffusionCommitHookEngine.php b/src/applications/diffusion/engine/DiffusionCommitHookEngine.php index f84eb13bdf..ee257ebee0 100644 --- a/src/applications/diffusion/engine/DiffusionCommitHookEngine.php +++ b/src/applications/diffusion/engine/DiffusionCommitHookEngine.php @@ -325,9 +325,11 @@ final class DiffusionCommitHookEngine extends Phobject { $this->emailPHIDs[$email_phid] = $email_phid; } + $block_action = DiffusionBlockHeraldAction::ACTIONCONST; + if ($blocking_effect === null) { foreach ($effects as $effect) { - if ($effect->getAction() == HeraldAdapter::ACTION_BLOCK) { + if ($effect->getAction() == $block_action) { $blocking_effect = $effect; $blocked_update = $update; break; diff --git a/src/applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php b/src/applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php new file mode 100644 index 0000000000..36b01b96f8 --- /dev/null +++ b/src/applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php @@ -0,0 +1,33 @@ +getRule(); + return $this->applyAuditors($effect->getTarget(), $rule); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new DiffusionAuditorDatasource(); + } + + public function renderActionDescription($value) { + return pht('Add auditors: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php b/src/applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php new file mode 100644 index 0000000000..d27876d40e --- /dev/null +++ b/src/applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php @@ -0,0 +1,30 @@ +getRule(); + $phid = $rule->getAuthorPHID(); + return $this->applyAuditors(array($phid), $rule); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Add rule author as auditor.'); + } + +} diff --git a/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php b/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php new file mode 100644 index 0000000000..32830cb673 --- /dev/null +++ b/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php @@ -0,0 +1,76 @@ +getAdapter(); + $object = $adapter->getObject(); + + $auditors = $object->getAudits(); + $auditors = mpull($auditors, null, 'getAuditorPHID'); + $current = array_keys($auditors); + + $allowed_types = array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + PhabricatorOwnersPackagePHIDType::TYPECONST, + ); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + // TODO: Convert this to be translatable, structured data eventually. + $reason_map = array(); + foreach ($phids as $phid) { + $reason_map[$phid][] = pht('%s Triggered Audit', $rule->getMonogram()); + } + + $xaction = $adapter->newTransaction() + ->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS) + ->setNewValue($phids) + ->setMetadataValue( + 'auditStatus', + PhabricatorAuditStatusConstants::AUDIT_REQUIRED) + ->setMetadataValue('auditReasonMap', $reason_map); + + $adapter->queueTransaction($xaction); + + $this->logEffect(self::DO_ADD_AUDITORS, $phids); + } + + protected function getActionEffectMap() { + return array( + self::DO_ADD_AUDITORS => array( + 'icon' => 'fa-user', + 'color' => 'green', + 'name' => pht('Added Auditors'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_ADD_AUDITORS: + return pht( + 'Added %s auditor(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + +} diff --git a/src/applications/diffusion/herald/DiffusionBlockHeraldAction.php b/src/applications/diffusion/herald/DiffusionBlockHeraldAction.php new file mode 100644 index 0000000000..32656d78fe --- /dev/null +++ b/src/applications/diffusion/herald/DiffusionBlockHeraldAction.php @@ -0,0 +1,56 @@ +logEffect(self::DO_BLOCK); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_TEXT; + } + + public function renderActionDescription($value) { + return pht('Block push with message: %s', $value); + } + + protected function getActionEffectMap() { + return array( + self::DO_BLOCK => array( + 'icon' => 'fa-stop', + 'color' => 'red', + 'name' => pht('Blocked Push'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_BLOCK: + return pht('Blocked push.'); + } + } +} diff --git a/src/applications/diffusion/herald/HeraldCommitAdapter.php b/src/applications/diffusion/herald/HeraldCommitAdapter.php index 0210185ed9..ab3e850475 100644 --- a/src/applications/diffusion/herald/HeraldCommitAdapter.php +++ b/src/applications/diffusion/herald/HeraldCommitAdapter.php @@ -1,6 +1,8 @@ auditMap; - } - - public function getBuildPlans() { - return $this->buildPlans; - } - public function getHeraldName() { return 'r'. @@ -333,40 +298,24 @@ final class HeraldCommitAdapter extends HeraldAdapter { return $result; } - public function applyHeraldEffects(array $effects) { - assert_instances_of($effects, 'HeraldEffect'); - $result = array(); - foreach ($effects as $effect) { - $action = $effect->getAction(); - switch ($action) { - case self::ACTION_AUDIT: - foreach ($effect->getTarget() as $phid) { - if (empty($this->auditMap[$phid])) { - $this->auditMap[$phid] = array(); - } - $this->auditMap[$phid][] = $effect->getRule()->getID(); - } - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Triggered an audit.')); - break; - case self::ACTION_APPLY_BUILD_PLANS: - foreach ($effect->getTarget() as $phid) { - $this->buildPlans[] = $phid; - } - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Applied build plans.')); - break; - default: - $result[] = $this->applyStandardEffect($effect); - break; - } - } - return $result; +/* -( HarbormasterBuildableAdapterInterface )------------------------------ */ + + + public function getHarbormasterBuildablePHID() { + return $this->getObject()->getPHID(); + } + + public function getHarbormasterContainerPHID() { + return $this->getObject()->getRepository()->getPHID(); + } + + public function getQueuedHarbormasterBuildPlanPHIDs() { + return $this->buildPlanPHIDs; + } + + public function queueHarbormasterBuildPlanPHID($phid) { + $this->buildPlanPHIDs[] = $phid; } } diff --git a/src/applications/diffusion/herald/HeraldPreCommitAdapter.php b/src/applications/diffusion/herald/HeraldPreCommitAdapter.php index 07f1f0d2c7..6b5b94b578 100644 --- a/src/applications/diffusion/herald/HeraldPreCommitAdapter.php +++ b/src/applications/diffusion/herald/HeraldPreCommitAdapter.php @@ -73,47 +73,4 @@ abstract class HeraldPreCommitAdapter extends HeraldAdapter { $this->hookEngine->getRepository()->getProjectPHIDs()); } - public function getActions($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: - return array_merge( - array( - self::ACTION_BLOCK, - self::ACTION_EMAIL, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: - return array_merge( - array( - self::ACTION_EMAIL, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - } - } - - public function applyHeraldEffects(array $effects) { - assert_instances_of($effects, 'HeraldEffect'); - - $result = array(); - foreach ($effects as $effect) { - $action = $effect->getAction(); - switch ($action) { - case self::ACTION_BLOCK: - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Blocked push.')); - break; - default: - $result[] = $this->applyStandardEffect($effect); - break; - } - } - - return $result; - } - } diff --git a/src/applications/diffusion/query/DiffusionCommitQuery.php b/src/applications/diffusion/query/DiffusionCommitQuery.php index 7098e7416f..45f8b063af 100644 --- a/src/applications/diffusion/query/DiffusionCommitQuery.php +++ b/src/applications/diffusion/query/DiffusionCommitQuery.php @@ -300,7 +300,7 @@ final class DiffusionCommitQuery $where = array(); if ($this->repositoryPHIDs !== null) { - $map_repositories = id (new PhabricatorRepositoryQuery()) + $map_repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()) ->withPHIDs($this->repositoryPHIDs) ->execute(); diff --git a/src/applications/drydock/controller/DrydockBlueprintCreateController.php b/src/applications/drydock/controller/DrydockBlueprintCreateController.php index 56e0228077..5398a2327d 100644 --- a/src/applications/drydock/controller/DrydockBlueprintCreateController.php +++ b/src/applications/drydock/controller/DrydockBlueprintCreateController.php @@ -3,9 +3,8 @@ final class DrydockBlueprintCreateController extends DrydockBlueprintController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $this->requireApplicationCapability( DrydockCreateBlueprintsCapability::CAPABILITY); diff --git a/src/applications/drydock/controller/DrydockBlueprintEditController.php b/src/applications/drydock/controller/DrydockBlueprintEditController.php index 4211c80b4c..1c75bf708d 100644 --- a/src/applications/drydock/controller/DrydockBlueprintEditController.php +++ b/src/applications/drydock/controller/DrydockBlueprintEditController.php @@ -2,20 +2,14 @@ final class DrydockBlueprintEditController extends DrydockBlueprintController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $blueprint = id(new DrydockBlueprintQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -27,7 +21,7 @@ final class DrydockBlueprintEditController extends DrydockBlueprintController { } $impl = $blueprint->getImplementation(); - $cancel_uri = $this->getApplicationURI('blueprint/'.$this->id.'/'); + $cancel_uri = $this->getApplicationURI('blueprint/'.$id.'/'); } else { $this->requireApplicationCapability( DrydockCreateBlueprintsCapability::CAPABILITY); diff --git a/src/applications/drydock/controller/DrydockBlueprintListController.php b/src/applications/drydock/controller/DrydockBlueprintListController.php index 31e716691d..ff09f19ff8 100644 --- a/src/applications/drydock/controller/DrydockBlueprintListController.php +++ b/src/applications/drydock/controller/DrydockBlueprintListController.php @@ -2,20 +2,16 @@ final class DrydockBlueprintListController extends DrydockBlueprintController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $request = $this->getRequest(); $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new DrydockBlueprintSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/drydock/controller/DrydockBlueprintViewController.php b/src/applications/drydock/controller/DrydockBlueprintViewController.php index be5229972e..33a27264b8 100644 --- a/src/applications/drydock/controller/DrydockBlueprintViewController.php +++ b/src/applications/drydock/controller/DrydockBlueprintViewController.php @@ -2,19 +2,13 @@ final class DrydockBlueprintViewController extends DrydockBlueprintController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $blueprint = id(new DrydockBlueprintQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$blueprint) { return new Aphront404Response(); diff --git a/src/applications/drydock/controller/DrydockConsoleController.php b/src/applications/drydock/controller/DrydockConsoleController.php index fd2dff8ba5..118d49ea59 100644 --- a/src/applications/drydock/controller/DrydockConsoleController.php +++ b/src/applications/drydock/controller/DrydockConsoleController.php @@ -22,9 +22,8 @@ final class DrydockConsoleController extends DrydockController { return $nav; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $menu = id(new PHUIObjectItemListView()) ->setUser($viewer); diff --git a/src/applications/drydock/controller/DrydockLeaseListController.php b/src/applications/drydock/controller/DrydockLeaseListController.php index f5c0897717..e370467a5f 100644 --- a/src/applications/drydock/controller/DrydockLeaseListController.php +++ b/src/applications/drydock/controller/DrydockLeaseListController.php @@ -2,19 +2,16 @@ final class DrydockLeaseListController extends DrydockLeaseController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new DrydockLeaseSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/drydock/controller/DrydockLeaseReleaseController.php b/src/applications/drydock/controller/DrydockLeaseReleaseController.php index 1779edf1b2..4bac0330ba 100644 --- a/src/applications/drydock/controller/DrydockLeaseReleaseController.php +++ b/src/applications/drydock/controller/DrydockLeaseReleaseController.php @@ -2,19 +2,13 @@ final class DrydockLeaseReleaseController extends DrydockLeaseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $lease = id(new DrydockLeaseQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$lease) { return new Aphront404Response(); @@ -25,7 +19,7 @@ final class DrydockLeaseReleaseController extends DrydockLeaseController { if ($lease->getStatus() != DrydockLeaseStatus::STATUS_ACTIVE) { $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Lease Not Active')) ->appendChild( phutil_tag( @@ -39,7 +33,7 @@ final class DrydockLeaseReleaseController extends DrydockLeaseController { if (!$request->isDialogFormPost()) { $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Really release lease?')) ->appendChild( phutil_tag( diff --git a/src/applications/drydock/controller/DrydockLeaseViewController.php b/src/applications/drydock/controller/DrydockLeaseViewController.php index d597209b5a..92d215bcbb 100644 --- a/src/applications/drydock/controller/DrydockLeaseViewController.php +++ b/src/applications/drydock/controller/DrydockLeaseViewController.php @@ -2,19 +2,13 @@ final class DrydockLeaseViewController extends DrydockLeaseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $lease = id(new DrydockLeaseQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$lease) { return new Aphront404Response(); diff --git a/src/applications/drydock/controller/DrydockLogListController.php b/src/applications/drydock/controller/DrydockLogListController.php index eaeb411d28..aecf77dc77 100644 --- a/src/applications/drydock/controller/DrydockLogListController.php +++ b/src/applications/drydock/controller/DrydockLogListController.php @@ -2,19 +2,16 @@ final class DrydockLogListController extends DrydockLogController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new DrydockLogSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/drydock/controller/DrydockResourceCloseController.php b/src/applications/drydock/controller/DrydockResourceCloseController.php index 7963612ee4..915bf89452 100644 --- a/src/applications/drydock/controller/DrydockResourceCloseController.php +++ b/src/applications/drydock/controller/DrydockResourceCloseController.php @@ -2,19 +2,13 @@ final class DrydockResourceCloseController extends DrydockResourceController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $resource = id(new DrydockResourceQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$resource) { return new Aphront404Response(); diff --git a/src/applications/drydock/controller/DrydockResourceListController.php b/src/applications/drydock/controller/DrydockResourceListController.php index 53ed62a743..d2f34ec25b 100644 --- a/src/applications/drydock/controller/DrydockResourceListController.php +++ b/src/applications/drydock/controller/DrydockResourceListController.php @@ -2,19 +2,16 @@ final class DrydockResourceListController extends DrydockResourceController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new DrydockResourceSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/drydock/controller/DrydockResourceViewController.php b/src/applications/drydock/controller/DrydockResourceViewController.php index 9be8188191..4cc7349dac 100644 --- a/src/applications/drydock/controller/DrydockResourceViewController.php +++ b/src/applications/drydock/controller/DrydockResourceViewController.php @@ -2,19 +2,13 @@ final class DrydockResourceViewController extends DrydockResourceController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $resource = id(new DrydockResourceQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$resource) { return new Aphront404Response(); diff --git a/src/applications/fact/controller/PhabricatorFactChartController.php b/src/applications/fact/controller/PhabricatorFactChartController.php index 92718f47f8..d6f3bc0c43 100644 --- a/src/applications/fact/controller/PhabricatorFactChartController.php +++ b/src/applications/fact/controller/PhabricatorFactChartController.php @@ -2,9 +2,8 @@ final class PhabricatorFactChartController extends PhabricatorFactController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $table = new PhabricatorFactRaw(); $conn_r = $table->establishConnection('r'); diff --git a/src/applications/fact/controller/PhabricatorFactHomeController.php b/src/applications/fact/controller/PhabricatorFactHomeController.php index b0e24cb79f..8e5c9511eb 100644 --- a/src/applications/fact/controller/PhabricatorFactHomeController.php +++ b/src/applications/fact/controller/PhabricatorFactHomeController.php @@ -6,9 +6,8 @@ final class PhabricatorFactHomeController extends PhabricatorFactController { return true; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); if ($request->isFormPost()) { $uri = new PhutilURI('/fact/chart/'); @@ -34,7 +33,7 @@ final class PhabricatorFactHomeController extends PhabricatorFactController { $spec = $specs[$fact->getFactType()]; $name = $spec->getName(); - $value = $spec->formatValueForDisplay($user, $fact->getValueX()); + $value = $spec->formatValueForDisplay($viewer, $fact->getValueX()); $rows[] = array($name, $value); } @@ -73,7 +72,7 @@ final class PhabricatorFactHomeController extends PhabricatorFactController { private function buildChartForm() { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $table = new PhabricatorFactRaw(); $conn_r = $table->establishConnection('r'); @@ -106,7 +105,7 @@ final class PhabricatorFactHomeController extends PhabricatorFactController { } $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Y-Axis')) diff --git a/src/applications/feed/controller/PhabricatorFeedDetailController.php b/src/applications/feed/controller/PhabricatorFeedDetailController.php index 459011af80..4fac10d1a8 100644 --- a/src/applications/feed/controller/PhabricatorFeedDetailController.php +++ b/src/applications/feed/controller/PhabricatorFeedDetailController.php @@ -2,19 +2,13 @@ final class PhabricatorFeedDetailController extends PhabricatorFeedController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $story = id(new PhabricatorFeedQuery()) - ->setViewer($user) - ->withChronologicalKeys(array($this->id)) + ->setViewer($viewer) + ->withChronologicalKeys(array($id)) ->executeOne(); if (!$story) { return new Aphront404Response(); @@ -27,7 +21,7 @@ final class PhabricatorFeedDetailController extends PhabricatorFeedController { $feed = array($story); $builder = new PhabricatorFeedBuilder($feed); - $builder->setUser($user); + $builder->setUser($viewer); $feed_view = $builder->buildView(); $title = pht('Story'); diff --git a/src/applications/feed/controller/PhabricatorFeedListController.php b/src/applications/feed/controller/PhabricatorFeedListController.php index f317b477be..8451592362 100644 --- a/src/applications/feed/controller/PhabricatorFeedListController.php +++ b/src/applications/feed/controller/PhabricatorFeedListController.php @@ -2,19 +2,15 @@ final class PhabricatorFeedListController extends PhabricatorFeedController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhabricatorFeedSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/files/controller/PhabricatorFileCommentController.php b/src/applications/files/controller/PhabricatorFileCommentController.php index c527e6fc12..11833ea8d8 100644 --- a/src/applications/files/controller/PhabricatorFileCommentController.php +++ b/src/applications/files/controller/PhabricatorFileCommentController.php @@ -2,23 +2,17 @@ final class PhabricatorFileCommentController extends PhabricatorFileController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $file = id(new PhabricatorFileQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$file) { return new Aphront404Response(); @@ -37,7 +31,7 @@ final class PhabricatorFileCommentController extends PhabricatorFileController { ->setContent($request->getStr('comment'))); $editor = id(new PhabricatorFileEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect($request->isContinueRequest()) ->setContentSourceFromRequest($request) ->setIsPreview($is_preview); @@ -56,7 +50,7 @@ final class PhabricatorFileCommentController extends PhabricatorFileController { if ($request->isAjax() && $is_preview) { return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setIsPreview($is_preview); } else { diff --git a/src/applications/files/controller/PhabricatorFileComposeController.php b/src/applications/files/controller/PhabricatorFileComposeController.php index f3e450add5..de5a6757a4 100644 --- a/src/applications/files/controller/PhabricatorFileComposeController.php +++ b/src/applications/files/controller/PhabricatorFileComposeController.php @@ -3,9 +3,8 @@ final class PhabricatorFileComposeController extends PhabricatorFileController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $colors = array( 'red' => pht('Verbillion'), diff --git a/src/applications/files/controller/PhabricatorFileDataController.php b/src/applications/files/controller/PhabricatorFileDataController.php index e528eb15f2..848560f099 100644 --- a/src/applications/files/controller/PhabricatorFileDataController.php +++ b/src/applications/files/controller/PhabricatorFileDataController.php @@ -7,19 +7,15 @@ final class PhabricatorFileDataController extends PhabricatorFileController { private $token; private $file; - public function willProcessRequest(array $data) { - $this->phid = $data['phid']; - $this->key = $data['key']; - $this->token = idx($data, 'token'); - } - public function shouldRequireLogin() { return false; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $this->getViewer(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $this->phid = $request->getURIData('phid'); + $this->key = $request->getURIData('key'); + $this->token = $request->getURIData('token'); $alt = PhabricatorEnv::getEnvConfig('security.alternate-file-domain'); $base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri'); diff --git a/src/applications/files/controller/PhabricatorFileDeleteController.php b/src/applications/files/controller/PhabricatorFileDeleteController.php index ed245c5cba..a07fe2e91a 100644 --- a/src/applications/files/controller/PhabricatorFileDeleteController.php +++ b/src/applications/files/controller/PhabricatorFileDeleteController.php @@ -2,19 +2,13 @@ final class PhabricatorFileDeleteController extends PhabricatorFileController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $file = id(new PhabricatorFileQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -25,8 +19,8 @@ final class PhabricatorFileDeleteController extends PhabricatorFileController { return new Aphront404Response(); } - if (($user->getPHID() != $file->getAuthorPHID()) && - (!$user->getIsAdmin())) { + if (($viewer->getPHID() != $file->getAuthorPHID()) && + (!$viewer->getIsAdmin())) { return new Aphront403Response(); } @@ -36,7 +30,7 @@ final class PhabricatorFileDeleteController extends PhabricatorFileController { } $dialog = new AphrontDialogView(); - $dialog->setUser($user); + $dialog->setUser($viewer); $dialog->setTitle(pht('Really delete file?')); $dialog->appendChild(hsprintf( '

%s

', diff --git a/src/applications/files/controller/PhabricatorFileDropUploadController.php b/src/applications/files/controller/PhabricatorFileDropUploadController.php index 34f6bc81e8..222fc799c7 100644 --- a/src/applications/files/controller/PhabricatorFileDropUploadController.php +++ b/src/applications/files/controller/PhabricatorFileDropUploadController.php @@ -3,12 +3,17 @@ final class PhabricatorFileDropUploadController extends PhabricatorFileController { + public function shouldAllowRestrictedParameter($parameter_name) { + // Prevent false positives from file content when it is submitted via + // drag-and-drop upload. + return true; + } + /** * @phutil-external-symbol class PhabricatorStartup */ - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); // NOTE: Throws if valid CSRF token is not present in the request. $request->validateCSRF(); diff --git a/src/applications/files/controller/PhabricatorFileEditController.php b/src/applications/files/controller/PhabricatorFileEditController.php index a496202093..9c416b588c 100644 --- a/src/applications/files/controller/PhabricatorFileEditController.php +++ b/src/applications/files/controller/PhabricatorFileEditController.php @@ -2,19 +2,13 @@ final class PhabricatorFileEditController extends PhabricatorFileController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/files/controller/PhabricatorFileInfoController.php b/src/applications/files/controller/PhabricatorFileInfoController.php index 0e3d041eac..d9b5de14ee 100644 --- a/src/applications/files/controller/PhabricatorFileInfoController.php +++ b/src/applications/files/controller/PhabricatorFileInfoController.php @@ -2,26 +2,19 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { - private $phid; - private $id; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->phid = idx($data, 'phid'); - $this->id = idx($data, 'id'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $phid = $request->getURIData('phid'); - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - if ($this->phid) { + if ($phid) { $file = id(new PhabricatorFileQuery()) - ->setViewer($user) - ->withPHIDs(array($this->phid)) + ->setViewer($viewer) + ->withPHIDs(array($phid)) ->executeOne(); if (!$file) { @@ -30,8 +23,8 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { return id(new AphrontRedirectResponse())->setURI($file->getInfoURI()); } $file = id(new PhabricatorFileQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$file) { return new Aphront404Response(); @@ -40,7 +33,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { $phid = $file->getPHID(); $header = id(new PHUIHeaderView()) - ->setUser($user) + ->setUser($viewer) ->setPolicyObject($file) ->setHeader($file->getName()); @@ -87,7 +80,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { } private function buildTransactionView(PhabricatorFile $file) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $timeline = $this->buildTransactionTimeline( $file, @@ -99,10 +92,10 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { ? pht('Add Comment') : pht('Question File Integrity'); - $draft = PhabricatorDraft::newFromUserAndKey($user, $file->getPHID()); + $draft = PhabricatorDraft::newFromUserAndKey($viewer, $file->getPHID()); $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($user) + ->setUser($viewer) ->setObjectPHID($file->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) @@ -116,8 +109,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { } private function buildActionView(PhabricatorFile $file) { - $request = $this->getRequest(); - $viewer = $request->getUser(); + $viewer = $this->getViewer(); $id = $file->getID(); @@ -184,7 +176,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { PhabricatorFile $file, PhabricatorActionListView $actions) { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $properties = id(new PHUIPropertyListView()); $properties->setActionList($actions); @@ -193,12 +185,12 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { if ($file->getAuthorPHID()) { $properties->addProperty( pht('Author'), - $user->renderHandle($file->getAuthorPHID())); + $viewer->renderHandle($file->getAuthorPHID())); } $properties->addProperty( pht('Created'), - phabricator_datetime($file->getDateCreated(), $user)); + phabricator_datetime($file->getDateCreated(), $viewer)); $finfo = id(new PHUIPropertyListView()); @@ -276,7 +268,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { $attached->addProperty( pht('Attached To'), - $user->renderHandleList($phids)); + $viewer->renderHandleList($phids)); } if ($file->isViewableImage()) { @@ -330,7 +322,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController { $box->addPropertyList($chunkinfo, pht('Chunks')); $chunks = id(new PhabricatorFileChunkQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withChunkHandles(array($file->getStorageHandle())) ->execute(); $chunks = msort($chunks, 'getByteStart'); diff --git a/src/applications/files/controller/PhabricatorFileUploadDialogController.php b/src/applications/files/controller/PhabricatorFileUploadDialogController.php index e99910c430..dd22caa74a 100644 --- a/src/applications/files/controller/PhabricatorFileUploadDialogController.php +++ b/src/applications/files/controller/PhabricatorFileUploadDialogController.php @@ -3,12 +3,11 @@ final class PhabricatorFileUploadDialogController extends PhabricatorFileController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Upload File')) ->appendChild(pht( 'To add files, drag and drop them into the comment text area.')) diff --git a/src/applications/flag/controller/PhabricatorFlagDeleteController.php b/src/applications/flag/controller/PhabricatorFlagDeleteController.php index cf1202c251..4dcb2cc371 100644 --- a/src/applications/flag/controller/PhabricatorFlagDeleteController.php +++ b/src/applications/flag/controller/PhabricatorFlagDeleteController.php @@ -2,22 +2,17 @@ final class PhabricatorFlagDeleteController extends PhabricatorFlagController { - private $id; - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $flag = id(new PhabricatorFlag())->load($this->id); + $flag = id(new PhabricatorFlag())->load($id); if (!$flag) { return new Aphront404Response(); } - if ($flag->getOwnerPHID() != $user->getPHID()) { + if ($flag->getOwnerPHID() != $viewer->getPHID()) { return new Aphront400Response(); } diff --git a/src/applications/flag/controller/PhabricatorFlagEditController.php b/src/applications/flag/controller/PhabricatorFlagEditController.php index b6e2327cd4..5844a3801a 100644 --- a/src/applications/flag/controller/PhabricatorFlagEditController.php +++ b/src/applications/flag/controller/PhabricatorFlagEditController.php @@ -2,19 +2,12 @@ final class PhabricatorFlagEditController extends PhabricatorFlagController { - private $phid; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $phid = $request->getURIData('phid'); - public function willProcessRequest(array $data) { - $this->phid = $data['phid']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $phid = $this->phid; $handle = id(new PhabricatorHandleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); @@ -22,14 +15,14 @@ final class PhabricatorFlagEditController extends PhabricatorFlagController { return new Aphront404Response(); } - $flag = PhabricatorFlagQuery::loadUserFlag($user, $phid); + $flag = PhabricatorFlagQuery::loadUserFlag($viewer, $phid); if (!$flag) { $flag = new PhabricatorFlag(); - $flag->setOwnerPHID($user->getPHID()); + $flag->setOwnerPHID($viewer->getPHID()); $flag->setType($handle->getType()); $flag->setObjectPHID($handle->getPHID()); - $flag->setReasonPHID($user->getPHID()); + $flag->setReasonPHID($viewer->getPHID()); } if ($request->isDialogFormPost()) { @@ -43,7 +36,7 @@ final class PhabricatorFlagEditController extends PhabricatorFlagController { $type_name = $handle->getTypeName(); $dialog = new AphrontDialogView(); - $dialog->setUser($user); + $dialog->setUser($viewer); $dialog->setTitle(pht('Flag %s', $type_name)); diff --git a/src/applications/flag/controller/PhabricatorFlagListController.php b/src/applications/flag/controller/PhabricatorFlagListController.php index 9029a35a7e..88a6bcf7e0 100644 --- a/src/applications/flag/controller/PhabricatorFlagListController.php +++ b/src/applications/flag/controller/PhabricatorFlagListController.php @@ -2,19 +2,16 @@ final class PhabricatorFlagListController extends PhabricatorFlagController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhabricatorFlagSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php b/src/applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php new file mode 100644 index 0000000000..e4ae03915f --- /dev/null +++ b/src/applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php @@ -0,0 +1,88 @@ +getAdapter()->getPHID(); + $rule = $effect->getRule(); + $author = $rule->getAuthor(); + + $flag = PhabricatorFlagQuery::loadUserFlag($author, $phid); + if ($flag) { + $this->logEffect(self::DO_IGNORE, $flag->getColor()); + return; + } + + $flag = id(new PhabricatorFlag()) + ->setOwnerPHID($author->getPHID()) + ->setType(phid_get_type($phid)) + ->setObjectPHID($phid) + ->setReasonPHID($rule->getPHID()) + ->setColor($effect->getTarget()) + ->setNote('') + ->save(); + + $this->logEffect(self::DO_FLAG, $flag->getColor()); + } + + public function getHeraldActionValueType() { + return id(new HeraldSelectFieldValue()) + ->setKey('flag.color') + ->setOptions(PhabricatorFlagColor::getColorNameMap()) + ->setDefault(PhabricatorFlagColor::COLOR_BLUE); + } + + protected function getActionEffectMap() { + return array( + self::DO_IGNORE => array( + 'icon' => 'fa-times', + 'color' => 'grey', + 'name' => pht('Already Marked'), + ), + self::DO_FLAG => array( + 'icon' => 'fa-flag', + 'name' => pht('Flagged'), + ), + ); + } + + public function renderActionDescription($value) { + $color = PhabricatorFlagColor::getColorName($value); + return pht('Mark with %s flag.', $color); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_IGNORE: + return pht( + 'Already marked with %s flag.', + PhabricatorFlagColor::getColorName($data)); + case self::DO_FLAG: + return pht( + 'Marked with "%s" flag.', + PhabricatorFlagColor::getColorName($data)); + } + } + +} diff --git a/src/applications/fund/controller/FundBackerListController.php b/src/applications/fund/controller/FundBackerListController.php index 0cc0f5a0f5..ab75b123dd 100644 --- a/src/applications/fund/controller/FundBackerListController.php +++ b/src/applications/fund/controller/FundBackerListController.php @@ -3,26 +3,21 @@ final class FundBackerListController extends FundController { - private $id; - private $queryKey; private $initiative; public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { - $request = $this->getRequest(); - - if ($this->id) { + if ($id) { $this->initiative = id(new FundInitiativeQuery()) - ->setViewer($request->getUser()) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$this->initiative) { return new Aphront404Response(); @@ -30,7 +25,7 @@ final class FundBackerListController } $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine($this->getEngine()) ->setNavigation($this->buildSideNavView()); @@ -66,8 +61,7 @@ final class FundBackerListController } private function getEngine() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + $viewer = $this->getViewer(); $engine = id(new FundBackerSearchEngine()) ->setViewer($viewer); diff --git a/src/applications/fund/controller/FundInitiativeBackController.php b/src/applications/fund/controller/FundInitiativeBackController.php index cb4c12ea40..414a5ebd64 100644 --- a/src/applications/fund/controller/FundInitiativeBackController.php +++ b/src/applications/fund/controller/FundInitiativeBackController.php @@ -3,19 +3,13 @@ final class FundInitiativeBackController extends FundController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $initiative = id(new FundInitiativeQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$initiative) { return new Aphront404Response(); diff --git a/src/applications/fund/controller/FundInitiativeCloseController.php b/src/applications/fund/controller/FundInitiativeCloseController.php index 803b6242cf..6adddb0d80 100644 --- a/src/applications/fund/controller/FundInitiativeCloseController.php +++ b/src/applications/fund/controller/FundInitiativeCloseController.php @@ -3,19 +3,13 @@ final class FundInitiativeCloseController extends FundController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $initiative = id(new FundInitiativeQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/fund/controller/FundInitiativeEditController.php b/src/applications/fund/controller/FundInitiativeEditController.php index b63b4d6d6b..75f7d338c9 100644 --- a/src/applications/fund/controller/FundInitiativeEditController.php +++ b/src/applications/fund/controller/FundInitiativeEditController.php @@ -3,20 +3,14 @@ final class FundInitiativeEditController extends FundController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $initiative = id(new FundInitiativeQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/fund/controller/FundInitiativeListController.php b/src/applications/fund/controller/FundInitiativeListController.php index c737de4828..6ba398fb2b 100644 --- a/src/applications/fund/controller/FundInitiativeListController.php +++ b/src/applications/fund/controller/FundInitiativeListController.php @@ -3,19 +3,15 @@ final class FundInitiativeListController extends FundController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new FundInitiativeSearchEngine()) ->setNavigation($this->buildSideNavView()); @@ -23,13 +19,13 @@ final class FundInitiativeListController } public function buildSideNavView() { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); id(new FundInitiativeSearchEngine()) - ->setViewer($user) + ->setViewer($viewer) ->addNavigationItems($nav->getMenu()); $nav->addLabel(pht('Backers')); diff --git a/src/applications/fund/controller/FundInitiativeViewController.php b/src/applications/fund/controller/FundInitiativeViewController.php index 37618b22d2..3d12f1549c 100644 --- a/src/applications/fund/controller/FundInitiativeViewController.php +++ b/src/applications/fund/controller/FundInitiativeViewController.php @@ -3,23 +3,18 @@ final class FundInitiativeViewController extends FundController { - private $id; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $initiative = id(new FundInitiativeQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$initiative) { return new Aphront404Response(); diff --git a/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php b/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php index 016e2a5cbc..266ac4fafc 100644 --- a/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php +++ b/src/applications/harbormaster/application/PhabricatorHarbormasterApplication.php @@ -36,16 +36,21 @@ final class PhabricatorHarbormasterApplication extends PhabricatorApplication { ); } - public function isPrototype() { - return true; - } - public function getRemarkupRules() { return array( new HarbormasterRemarkupRule(), ); } + public function getHelpDocumentationArticles(PhabricatorUser $viewer) { + return array( + array( + 'name' => pht('Harbormaster User Guide'), + 'href' => PhabricatorEnv::getDoclink('Harbormaster User Guide'), + ), + ); + } + public function getRoutes() { return array( '/B(?P[1-9]\d*)' => 'HarbormasterBuildableViewController', diff --git a/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php b/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php index 9590f90cec..3a2d808239 100644 --- a/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php +++ b/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php @@ -7,20 +7,206 @@ final class HarbormasterSendMessageConduitAPIMethod return 'harbormaster.sendmessage'; } - public function getMethodDescription() { + public function getMethodSummary() { return pht( - 'Send a message to a build target, notifying it of results in an '. - 'external system.'); + 'Send a message about the status of a build target to Harbormaster, '. + 'notifying the application of build results in an external system.'); + } + + public function getMethodDescription() { + $messages = HarbormasterMessageType::getAllMessages(); + + $head_type = pht('Constant'); + $head_desc = pht('Description'); + $head_key = pht('Key'); + $head_type = pht('Type'); + $head_name = pht('Name'); + + $rows = array(); + $rows[] = "| {$head_type} | {$head_desc} |"; + $rows[] = '|--------------|--------------|'; + foreach ($messages as $message) { + $description = HarbormasterMessageType::getMessageDescription($message); + $rows[] = "| `{$message}` | {$description} |"; + } + $message_table = implode("\n", $rows); + + $rows = array(); + $rows[] = "| {$head_key} | {$head_type} | {$head_desc} |"; + $rows[] = '|-------------|--------------|--------------|'; + $unit_spec = HarbormasterBuildUnitMessage::getParameterSpec(); + foreach ($unit_spec as $key => $parameter) { + $type = idx($parameter, 'type'); + $type = str_replace('|', pht(' or '), $type); + $description = idx($parameter, 'description'); + $rows[] = "| `{$key}` | //{$type}// | {$description} |"; + } + $unit_table = implode("\n", $rows); + + $rows = array(); + $rows[] = "| {$head_key} | {$head_name} | {$head_desc} |"; + $rows[] = '|-------------|--------------|--------------|'; + $results = ArcanistUnitTestResult::getAllResultCodes(); + foreach ($results as $result_code) { + $name = ArcanistUnitTestResult::getResultCodeName($result_code); + $description = ArcanistUnitTestResult::getResultCodeDescription( + $result_code); + $rows[] = "| `{$result_code}` | **{$name}** | {$description} |"; + } + $result_table = implode("\n", $rows); + + $rows = array(); + $rows[] = "| {$head_key} | {$head_type} | {$head_desc} |"; + $rows[] = '|-------------|--------------|--------------|'; + $lint_spec = HarbormasterBuildLintMessage::getParameterSpec(); + foreach ($lint_spec as $key => $parameter) { + $type = idx($parameter, 'type'); + $type = str_replace('|', pht(' or '), $type); + $description = idx($parameter, 'description'); + $rows[] = "| `{$key}` | //{$type}// | {$description} |"; + } + $lint_table = implode("\n", $rows); + + $rows = array(); + $rows[] = "| {$head_key} | {$head_name} |"; + $rows[] = '|-------------|--------------|'; + $severities = ArcanistLintSeverity::getLintSeverities(); + foreach ($severities as $key => $name) { + $rows[] = "| `{$key}` | **{$name}** |"; + } + $severity_table = implode("\n", $rows); + + $valid_unit = array( + array( + 'name' => 'PassingTest', + 'result' => ArcanistUnitTestResult::RESULT_PASS, + ), + array( + 'name' => 'FailingTest', + 'result' => ArcanistUnitTestResult::RESULT_FAIL, + ), + ); + + $valid_lint = array( + array( + 'name' => pht('Syntax Error'), + 'code' => 'EXAMPLE1', + 'severity' => ArcanistLintSeverity::SEVERITY_ERROR, + 'path' => 'path/to/example.c', + 'line' => 17, + 'char' => 3, + ), + array( + 'name' => pht('Not A Haiku'), + 'code' => 'EXAMPLE2', + 'severity' => ArcanistLintSeverity::SEVERITY_ERROR, + 'path' => 'path/to/source.cpp', + 'line' => 23, + 'char' => 1, + 'description' => pht( + 'This function definition is not a haiku.'), + ), + ); + + $json = new PhutilJSON(); + $valid_unit = $json->encodeAsList($valid_unit); + $valid_lint = $json->encodeAsList($valid_lint); + + return pht( + "Send a message about the status of a build target to Harbormaster, ". + "notifying the application of build results in an external system.". + "\n\n". + "Sending Messages\n". + "================\n". + "If you run external builds, you can use this method to publish build ". + "results back into Harbormaster after the external system finishes work ". + "or as it makes progress.". + "\n\n". + "The simplest way to use this method is to call it once after the ". + "build finishes with a `pass` or `fail` message. This will record the ". + "build result, and continue the next step in the build if the build was ". + "waiting for a result.". + "\n\n". + "When you send a status message about a build target, you can ". + "optionally include detailed `lint` or `unit` results alongside the ". + "message. See below for details.". + "\n\n". + "If you want to report intermediate results but a build hasn't ". + "completed yet, you can use the `work` message. This message doesn't ". + "have any direct effects, but allows you to send additional data to ". + "update the progress of the build target. The target will continue ". + "waiting for a completion message, but the UI will update to show the ". + "progress which has been made.". + "\n\n". + "Message Types\n". + "=============\n". + "When you send Harbormaster a message, you must include a `type`, ". + "which describes the overall state of the build. For example, use ". + "`pass` to tell Harbomaster that a build completed successfully.". + "\n\n". + "Supported message types are:". + "\n\n". + "%s". + "\n\n". + "Unit Results\n". + "============\n". + "You can report test results alongside a message. The simplest way to ". + "do this is to report all the results alongside a `pass` or `fail` ". + "message, but you can also send a `work` message to report intermediate ". + "results.\n\n". + "To provide unit test results, pass a list of results in the `unit` ". + "parameter. Each result shoud be a dictionary with these keys:". + "\n\n". + "%s". + "\n\n". + "The `result` parameter recognizes these test results:". + "\n\n". + "%s". + "\n\n". + "This is a simple, valid value for the `unit` parameter. It reports ". + "one passing test and one failing test:\n\n". + "\n\n". + "```lang=json\n". + "%s". + "```". + "\n\n". + "Lint Results\n". + "============\n". + "Like unit test results, you can report lint results alongside a ". + "message. The `lint` parameter should contain results as a list of ". + "dictionaries with these keys:". + "\n\n". + "%s". + "\n\n". + "The `severity` parameter recognizes these severity levels:". + "\n\n". + "%s". + "\n\n". + "This is a simple, valid value for the `lint` parameter. It reports one ". + "error and one warning:". + "\n\n". + "```lang=json\n". + "%s". + "```". + "\n\n", + $message_table, + $unit_table, + $result_table, + $valid_unit, + $lint_table, + $severity_table, + $valid_lint); } protected function defineParamTypes() { - $type_const = $this->formatStringConstants(array('pass', 'fail')); + $messages = HarbormasterMessageType::getAllMessages(); + $type_const = $this->formatStringConstants($messages); return array( 'buildTargetPHID' => 'required phid', - 'lint' => 'optional list', - 'unit' => 'optional list', 'type' => 'required '.$type_const, + 'unit' => 'optional list', + 'lint' => 'optional list', ); } diff --git a/src/applications/harbormaster/controller/HarbormasterPlanViewController.php b/src/applications/harbormaster/controller/HarbormasterPlanViewController.php index 417b9a700e..da35e389a0 100644 --- a/src/applications/harbormaster/controller/HarbormasterPlanViewController.php +++ b/src/applications/harbormaster/controller/HarbormasterPlanViewController.php @@ -235,7 +235,7 @@ final class HarbormasterPlanViewController extends HarbormasterPlanController { id(new PHUIIconView()) ->setIconFont('fa-plus')) ->setDisabled(!$can_edit) - ->setWorkflow(true)); + ->setWorkflow(!$can_edit)); $step_box = id(new PHUIObjectBoxView()) ->setHeader($header) diff --git a/src/applications/harbormaster/controller/HarbormasterStepAddController.php b/src/applications/harbormaster/controller/HarbormasterStepAddController.php index 371a1d1db2..21cdc3f12c 100644 --- a/src/applications/harbormaster/controller/HarbormasterStepAddController.php +++ b/src/applications/harbormaster/controller/HarbormasterStepAddController.php @@ -23,48 +23,83 @@ final class HarbormasterStepAddController extends HarbormasterController { $plan_id = $plan->getID(); $cancel_uri = $this->getApplicationURI("plan/{$plan_id}/"); + $plan_title = pht('Plan %d', $plan_id); $all = HarbormasterBuildStepImplementation::getImplementations(); - foreach ($all as $key => $impl) { - if ($impl->shouldRequireAutotargeting()) { - unset($all[$key]); + $all = msort($all, 'getName'); + + $all_groups = HarbormasterBuildStepGroup::getAllGroups(); + foreach ($all as $impl) { + $group_key = $impl->getBuildStepGroupKey(); + if (empty($all_groups[$group_key])) { + throw new Exception( + pht( + 'Build step "%s" has step group key "%s", but no step group '. + 'with that key exists.', + get_class($impl), + $group_key)); } } - $errors = array(); - if ($request->isFormPost()) { - $class = $request->getStr('class'); - if (empty($all[$class])) { - $errors[] = pht('Choose the type of build step you want to add.'); + $groups = mgroup($all, 'getBuildStepGroupKey'); + $lists = array(); + + $enabled_groups = HarbormasterBuildStepGroup::getAllEnabledGroups(); + foreach ($enabled_groups as $group) { + $list = id(new PHUIObjectItemListView()) + ->setHeader($group->getGroupName()) + ->setNoDataString( + pht( + 'This group has no available build steps.')); + + $steps = idx($groups, $group->getGroupKey(), array()); + + foreach ($steps as $key => $impl) { + if ($impl->shouldRequireAutotargeting()) { + unset($steps[$key]); + continue; + } } - if (!$errors) { + + if (!$steps && !$group->shouldShowIfEmpty()) { + continue; + } + + foreach ($steps as $key => $impl) { + $class = get_class($impl); + $new_uri = $this->getApplicationURI("step/new/{$plan_id}/{$class}/"); - return id(new AphrontRedirectResponse())->setURI($new_uri); + + $item = id(new PHUIObjectItemView()) + ->setHeader($impl->getName()) + ->setHref($new_uri) + ->addAttribute($impl->getGenericDescription()); + + $list->addItem($item); } + + $lists[] = $list; } - $control = id(new AphrontFormRadioButtonControl()) - ->setName('class'); + $crumbs = $this->buildApplicationCrumbs() + ->addTextCrumb($plan_title, $cancel_uri) + ->addTextCrumb(pht('Add Build Step')); - foreach ($all as $class => $implementation) { - $control->addButton( - $class, - $implementation->getName(), - $implementation->getGenericDescription()); - } + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Add Build Step')) + ->appendChild($lists); - if ($errors) { - $errors = id(new PHUIInfoView()) - ->setErrors($errors); - } - - return $this->newDialog() - ->setTitle(pht('Add New Step')) - ->addSubmitButton(pht('Add Build Step')) - ->addCancelButton($cancel_uri) - ->appendChild($errors) - ->appendParagraph(pht('Choose a type of build step to add:')) - ->appendChild($control); + return $this->buildApplicationPage( + array( + $crumbs, + $box, + ), + array( + 'title' => array( + $plan_title, + pht('Add Build Step'), + ), + )); } } diff --git a/src/applications/harbormaster/engine/HarbormasterBuildEngine.php b/src/applications/harbormaster/engine/HarbormasterBuildEngine.php index 8d8c26818e..fd895979cd 100644 --- a/src/applications/harbormaster/engine/HarbormasterBuildEngine.php +++ b/src/applications/harbormaster/engine/HarbormasterBuildEngine.php @@ -317,14 +317,17 @@ final class HarbormasterBuildEngine extends Phobject { foreach ($messages as $message) { $target = $waiting_targets[$message->getBuildTargetPHID()]; - $new_status = null; switch ($message->getType()) { - case 'pass': + case HarbormasterMessageType::MESSAGE_PASS: $new_status = HarbormasterBuildTarget::STATUS_PASSED; break; - case 'fail': + case HarbormasterMessageType::MESSAGE_FAIL: $new_status = HarbormasterBuildTarget::STATUS_FAILED; break; + case HarbormasterMessageType::MESSAGE_WORK: + default: + $new_status = null; + break; } if ($new_status !== null) { diff --git a/src/applications/harbormaster/engine/HarbormasterMessageType.php b/src/applications/harbormaster/engine/HarbormasterMessageType.php new file mode 100644 index 0000000000..5900817c69 --- /dev/null +++ b/src/applications/harbormaster/engine/HarbormasterMessageType.php @@ -0,0 +1,44 @@ + array( + 'description' => pht( + 'Report that the target is complete, and the target has passed.'), + ), + self::MESSAGE_FAIL => array( + 'description' => pht( + 'Report that the target is complete, and the target has failed.'), + ), + self::MESSAGE_WORK => array( + 'description' => pht( + 'Report that work on the target is ongoing. This message can be '. + 'used to report partial results during a build.'), + ), + ); + } + +} diff --git a/src/applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php b/src/applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php new file mode 100644 index 0000000000..cf6cda8f95 --- /dev/null +++ b/src/applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php @@ -0,0 +1,34 @@ +getObject()->getPHID(); + } + + public function getHarbormasterContainerPHID() { + return null; + } + + public function getQueuedHarbormasterBuildPlanPHIDs() { + return $this->buildPlanPHIDs; + } + + public function queueHarbormasterBuildPlanPHID($phid) { + $this->buildPlanPHIDs[] = $phid; + } + +*/ diff --git a/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php b/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php new file mode 100644 index 0000000000..830598e812 --- /dev/null +++ b/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php @@ -0,0 +1,85 @@ +getAdapter(); + return ($adapter instanceof HarbormasterBuildableAdapterInterface); + } + + protected function applyBuilds(array $phids) { + $adapter = $this->getAdapter(); + + $allowed_types = array( + HarbormasterBuildPlanPHIDType::TYPECONST, + ); + + $targets = $this->loadStandardTargets($phids, $allowed_types, array()); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + foreach ($phids as $phid) { + $adapter->queueHarbormasterBuildPlanPHID($phid); + } + + $this->logEffect(self::DO_BUILD, $phids); + } + + protected function getActionEffectMap() { + return array( + self::DO_BUILD => array( + 'icon' => 'fa-play', + 'color' => 'green', + 'name' => pht('Building'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_BUILD: + return pht( + 'Started %s build(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + + public function getHeraldActionName() { + return pht('Run build plans'); + } + + public function supportsRuleType($rule_type) { + return ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL); + } + + public function applyEffect($object, HeraldEffect $effect) { + return $this->applyBuilds($effect->getTarget()); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new HarbormasterBuildPlanDatasource(); + } + + public function renderActionDescription($value) { + return pht( + 'Run build plans: %s.', + $this->renderHandleList($value)); + } +} diff --git a/src/applications/harbormaster/step/HarbormasterArcLintBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterArcLintBuildStepImplementation.php index 93b6e498c7..ed69ab807d 100644 --- a/src/applications/harbormaster/step/HarbormasterArcLintBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterArcLintBuildStepImplementation.php @@ -25,6 +25,10 @@ final class HarbormasterArcLintBuildStepImplementation return pht('Automatic `arc lint` step.'); } + public function getBuildStepGroupKey() { + return HarbormasterBuiltinBuildStepGroup::GROUPKEY; + } + public function execute( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { diff --git a/src/applications/harbormaster/step/HarbormasterArcUnitBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterArcUnitBuildStepImplementation.php index 4f3805949f..d2b41a06a6 100644 --- a/src/applications/harbormaster/step/HarbormasterArcUnitBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterArcUnitBuildStepImplementation.php @@ -25,6 +25,10 @@ final class HarbormasterArcUnitBuildStepImplementation return pht('Automatic `arc unit` step.'); } + public function getBuildStepGroupKey() { + return HarbormasterBuiltinBuildStepGroup::GROUPKEY; + } + public function execute( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { diff --git a/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php index c831b711dd..15f2dd9943 100644 --- a/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterBuildStepImplementation.php @@ -41,6 +41,10 @@ abstract class HarbormasterBuildStepImplementation extends Phobject { */ abstract public function getName(); + public function getBuildStepGroupKey() { + return HarbormasterOtherBuildStepGroup::GROUPKEY; + } + /** * The generic description of the implementation. */ diff --git a/src/applications/harbormaster/step/HarbormasterCommandBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterCommandBuildStepImplementation.php index 5dbfd80262..931ade75a7 100644 --- a/src/applications/harbormaster/step/HarbormasterCommandBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterCommandBuildStepImplementation.php @@ -13,6 +13,10 @@ final class HarbormasterCommandBuildStepImplementation return pht('Run a command on Drydock host.'); } + public function getBuildStepGroupKey() { + return HarbormasterPrototypeBuildStepGroup::GROUPKEY; + } + public function getDescription() { return pht( 'Run command %s on host %s.', diff --git a/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php index 5d361b3de3..3910ac0b24 100644 --- a/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php @@ -11,6 +11,10 @@ final class HarbormasterHTTPRequestBuildStepImplementation return pht('Make an HTTP request.'); } + public function getBuildStepGroupKey() { + return HarbormasterExternalBuildStepGroup::GROUPKEY; + } + public function getDescription() { $domain = null; $uri = $this->getSetting('uri'); diff --git a/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php index 28e14c964e..d5f461506a 100644 --- a/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php @@ -11,6 +11,10 @@ final class HarbormasterLeaseHostBuildStepImplementation return pht('Obtain a lease on a Drydock host for performing builds.'); } + public function getBuildStepGroupKey() { + return HarbormasterPrototypeBuildStepGroup::GROUPKEY; + } + public function execute( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { diff --git a/src/applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php index e008d5d50b..dc59717a23 100644 --- a/src/applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php @@ -11,6 +11,11 @@ final class HarbormasterPublishFragmentBuildStepImplementation return pht('Publish a fragment based on a file artifact.'); } + + public function getBuildStepGroupKey() { + return HarbormasterPrototypeBuildStepGroup::GROUPKEY; + } + public function getDescription() { return pht( 'Publish file artifact %s as fragment %s.', diff --git a/src/applications/harbormaster/step/HarbormasterSleepBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterSleepBuildStepImplementation.php index 968c5b99cb..60221b782c 100644 --- a/src/applications/harbormaster/step/HarbormasterSleepBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterSleepBuildStepImplementation.php @@ -11,6 +11,11 @@ final class HarbormasterSleepBuildStepImplementation return pht('Sleep for a specified number of seconds.'); } + + public function getBuildStepGroupKey() { + return HarbormasterTestBuildStepGroup::GROUPKEY; + } + public function getDescription() { return pht( 'Sleep for %s seconds.', diff --git a/src/applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php b/src/applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php index 402a03ba20..06947317ef 100644 --- a/src/applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php +++ b/src/applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php @@ -11,6 +11,10 @@ final class HarbormasterThrowExceptionBuildStep return pht('Throw an exception.'); } + public function getBuildStepGroupKey() { + return HarbormasterTestBuildStepGroup::GROUPKEY; + } + public function execute( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { diff --git a/src/applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php index 4172da8917..75b48eb3c6 100644 --- a/src/applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php @@ -11,6 +11,10 @@ final class HarbormasterUploadArtifactBuildStepImplementation return pht('Upload a file from a host to Phabricator.'); } + public function getBuildStepGroupKey() { + return HarbormasterPrototypeBuildStepGroup::GROUPKEY; + } + public function getDescription() { return pht( 'Upload %s from %s.', diff --git a/src/applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php index 288cb1b1fa..f4e965b6c2 100644 --- a/src/applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php +++ b/src/applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php @@ -13,6 +13,10 @@ final class HarbormasterWaitForPreviousBuildStepImplementation 'before continuing.'); } + public function getBuildStepGroupKey() { + return HarbormasterPrototypeBuildStepGroup::GROUPKEY; + } + public function execute( HarbormasterBuild $build, HarbormasterBuildTarget $build_target) { diff --git a/src/applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php b/src/applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php new file mode 100644 index 0000000000..bb439b75b4 --- /dev/null +++ b/src/applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php @@ -0,0 +1,52 @@ +getConstant('GROUPKEY'); + if ($const === false) { + throw new Exception( + pht( + '"%s" class "%s" must define a "%s" property.', + __CLASS__, + get_class($this), + 'GROUPKEY')); + } + + return $const; + } + + final public static function getAllGroups() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getGroupKey') + ->setSortMethod('getGroupOrder') + ->execute(); + } + + final public static function getAllEnabledGroups() { + $groups = self::getAllGroups(); + + foreach ($groups as $key => $group) { + if (!$group->isEnabled()) { + unset($groups[$key]); + } + } + + return $groups; + } + +} diff --git a/src/applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php b/src/applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php new file mode 100644 index 0000000000..c730048e78 --- /dev/null +++ b/src/applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php @@ -0,0 +1,20 @@ +getBuildStatus() === self::STATUS_BUILDING; } + public function isAutobuild() { + return ($this->getPlanAutoKey() !== null); + } + public function createLog( HarbormasterBuildTarget $build_target, $log_source, @@ -336,16 +340,28 @@ final class HarbormasterBuild extends HarbormasterDAO } public function canRestartBuild() { + if ($this->isAutobuild()) { + return false; + } + return !$this->isRestarting(); } public function canStopBuild() { + if ($this->isAutobuild()) { + return false; + } + return !$this->isComplete() && !$this->isStopped() && !$this->isStopping(); } public function canResumeBuild() { + if ($this->isAutobuild()) { + return false; + } + return $this->isStopped() && !$this->isResuming(); } diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php b/src/applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php index c9957b0149..2bd37b2f79 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php @@ -20,21 +20,60 @@ final class HarbormasterBuildLintMessage ->setBuildTargetPHID($build_target->getPHID()); } + public static function getParameterSpec() { + return array( + 'name' => array( + 'type' => 'string', + 'description' => pht( + 'Short message name, like "Syntax Error".'), + ), + 'code' => array( + 'type' => 'string', + 'description' => pht( + 'Lint message code identifying the type of message, like "ERR123".'), + ), + 'severity' => array( + 'type' => 'string', + 'description' => pht( + 'Severity of the message.'), + ), + 'path' => array( + 'type' => 'string', + 'description' => pht( + 'Path to the file containing the lint message, from the project '. + 'root.'), + ), + 'line' => array( + 'type' => 'optional int', + 'description' => pht( + 'Line number in the file where the text which triggered the '. + 'message first appears. The first line of the file is line 1, '. + 'not line 0.'), + ), + 'char' => array( + 'type' => 'optional int', + 'description' => pht( + 'Byte position on the line where the text which triggered the '. + 'message starts. The first byte on the line is byte 1, not byte '. + '0. This position is byte-based (not character-based) because '. + 'not all lintable files have a valid character encoding.'), + ), + 'description' => array( + 'type' => 'optional string', + 'description' => pht( + 'Long explanation of the lint message.'), + ), + ); + } + public static function newFromDictionary( HarbormasterBuildTarget $build_target, array $dict) { $obj = self::initializeNewLintMessage($build_target); - $spec = array( - 'path' => 'string', - 'line' => 'optional int', - 'char' => 'optional int', - 'code' => 'string', - 'severity' => 'string', - 'name' => 'string', - 'description' => 'optional string', - ); + $spec = self::getParameterSpec(); + $spec = ipull($spec, 'type'); // We're just going to ignore extra keys for now, to make it easier to // add stuff here later on. diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php b/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php index 2b9108b035..1062b64a3a 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php @@ -19,21 +19,59 @@ final class HarbormasterBuildUnitMessage ->setBuildTargetPHID($build_target->getPHID()); } + public static function getParameterSpec() { + return array( + 'name' => array( + 'type' => 'string', + 'description' => pht( + 'Short test name, like "ExampleTest".'), + ), + 'result' => array( + 'type' => 'string', + 'description' => pht( + 'Result of the test.'), + ), + 'namespace' => array( + 'type' => 'optional string', + 'description' => pht( + 'Optional namespace for this test. This is organizational and '. + 'is often a class or module name, like "ExampleTestCase".'), + ), + 'engine' => array( + 'type' => 'optional string', + 'description' => pht( + 'Test engine running the test, like "JavascriptTestEngine". This '. + 'primarily prevents collisions between tests with the same name '. + 'in different test suites (for example, a Javascript test and a '. + 'Python test).'), + ), + 'duration' => array( + 'type' => 'optional float|int', + 'description' => pht( + 'Runtime duration of the test, in seconds.'), + ), + 'path' => array( + 'type' => 'optional string', + 'description' => pht( + 'Path to the file where the test is declared, relative to the '. + 'project root.'), + ), + 'coverage' => array( + 'type' => 'optional map', + 'description' => pht( + 'Coverage information for this test.'), + ), + ); + } + public static function newFromDictionary( HarbormasterBuildTarget $build_target, array $dict) { $obj = self::initializeNewUnitMessage($build_target); - $spec = array( - 'engine' => 'optional string', - 'namespace' => 'optional string', - 'name' => 'string', - 'result' => 'string', - 'duration' => 'optional float|int', - 'path' => 'optional string', - 'coverage' => 'optional map', - ); + $spec = self::getParameterSpec(); + $spec = ipull($spec, 'type'); // We're just going to ignore extra keys for now, to make it easier to // add stuff here later on. diff --git a/src/applications/help/controller/PhabricatorHelpEditorProtocolController.php b/src/applications/help/controller/PhabricatorHelpEditorProtocolController.php index 51dd4cfa0f..010e41ffcd 100644 --- a/src/applications/help/controller/PhabricatorHelpEditorProtocolController.php +++ b/src/applications/help/controller/PhabricatorHelpEditorProtocolController.php @@ -7,9 +7,8 @@ final class PhabricatorHelpEditorProtocolController return true; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $dialog = id(new AphrontDialogView()) ->setUser($viewer) diff --git a/src/applications/help/controller/PhabricatorHelpKeyboardShortcutController.php b/src/applications/help/controller/PhabricatorHelpKeyboardShortcutController.php index f91182859a..b136265d7f 100644 --- a/src/applications/help/controller/PhabricatorHelpKeyboardShortcutController.php +++ b/src/applications/help/controller/PhabricatorHelpKeyboardShortcutController.php @@ -7,9 +7,8 @@ final class PhabricatorHelpKeyboardShortcutController return true; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $keys = $request->getStr('keys'); try { @@ -59,7 +58,7 @@ final class PhabricatorHelpKeyboardShortcutController $rows); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Keyboard Shortcuts')) ->appendChild($table) ->addCancelButton('#', pht('Close')); diff --git a/src/applications/herald/action/HeraldAction.php b/src/applications/herald/action/HeraldAction.php new file mode 100644 index 0000000000..02a9dfa60a --- /dev/null +++ b/src/applications/herald/action/HeraldAction.php @@ -0,0 +1,407 @@ +getActionConstant() => $this); + } + + protected function getDatasource() { + throw new PhutilMethodNotImplementedException(); + } + + protected function getDatasourceValueMap() { + return null; + } + + public function getHeraldActionStandardType() { + throw new PhutilMethodNotImplementedException(); + } + + public function getHeraldActionValueType() { + switch ($this->getHeraldActionStandardType()) { + case self::STANDARD_NONE: + return new HeraldEmptyFieldValue(); + case self::STANDARD_TEXT: + return new HeraldTextFieldValue(); + case self::STANDARD_PHID_LIST: + $tokenizer = id(new HeraldTokenizerFieldValue()) + ->setKey($this->getHeraldActionName()) + ->setDatasource($this->getDatasource()); + + $value_map = $this->getDatasourceValueMap(); + if ($value_map !== null) { + $tokenizer->setValueMap($value_map); + } + + return $tokenizer; + } + + throw new PhutilMethodNotImplementedException(); + } + + public function willSaveActionValue($value) { + try { + $type = $this->getHeraldActionStandardType(); + } catch (PhutilMethodNotImplementedException $ex) { + return $value; + } + + switch ($type) { + case self::STANDARD_PHID_LIST: + return array_keys($value); + } + + return $value; + } + + public function getEditorValue(PhabricatorUser $viewer, $target) { + try { + $type = $this->getHeraldActionStandardType(); + } catch (PhutilMethodNotImplementedException $ex) { + return $target; + } + + switch ($type) { + case self::STANDARD_PHID_LIST: + $handles = $viewer->loadHandles($target); + $handles = iterator_to_array($handles); + return mpull($handles, 'getName', 'getPHID'); + } + + return $target; + } + + final public function setAdapter(HeraldAdapter $adapter) { + $this->adapter = $adapter; + return $this; + } + + final public function getAdapter() { + return $this->adapter; + } + + final public function setViewer(PhabricatorUser $viewer) { + $this->viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + final public function getActionConstant() { + $class = new ReflectionClass($this); + + $const = $class->getConstant('ACTIONCONST'); + if ($const === false) { + throw new Exception( + pht( + '"%s" class "%s" must define a "%s" property.', + __CLASS__, + get_class($this), + 'ACTIONCONST')); + } + + $limit = self::getActionConstantByteLimit(); + if (!is_string($const) || (strlen($const) > $limit)) { + throw new Exception( + pht( + '"%s" class "%s" has an invalid "%s" property. Action constants '. + 'must be strings and no more than %s bytes in length.', + __CLASS__, + get_class($this), + 'ACTIONCONST', + new PhutilNumber($limit))); + } + + return $const; + } + + final public static function getActionConstantByteLimit() { + return 64; + } + + final public static function getAllActions() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getActionConstant') + ->execute(); + } + + protected function logEffect($type, $data = null) { + if (!is_string($type)) { + throw new Exception( + pht( + 'Effect type passed to "%s" must be a scalar string.', + 'logEffect()')); + } + + $this->applyLog[] = array( + 'type' => $type, + 'data' => $data, + ); + + return $this; + } + + final public function getApplyTranscript(HeraldEffect $effect) { + $context = $this->applyLog; + $this->applyLog = array(); + return new HeraldApplyTranscript($effect, true, $context); + } + + protected function getActionEffectMap() { + throw new PhutilMethodNotImplementedException(); + } + + private function getActionEffectSpec($type) { + $map = $this->getActionEffectMap() + $this->getStandardEffectMap(); + return idx($map, $type, array()); + } + + final public function renderActionEffectIcon($type, $data) { + $map = $this->getActionEffectSpec($type); + return idx($map, 'icon'); + } + + final public function renderActionEffectColor($type, $data) { + $map = $this->getActionEffectSpec($type); + return idx($map, 'color'); + } + + final public function renderActionEffectName($type, $data) { + $map = $this->getActionEffectSpec($type); + return idx($map, 'name'); + } + + protected function renderHandleList($phids) { + if (!is_array($phids)) { + return pht('(Invalid List)'); + } + + return $this->getViewer() + ->renderHandleList($phids) + ->setAsInline(true) + ->render(); + } + + protected function loadStandardTargets( + array $phids, + array $allowed_types, + array $current_value) { + + $phids = array_fuse($phids); + if (!$phids) { + $this->logEffect(self::DO_STANDARD_EMPTY); + } + + $current_value = array_fuse($current_value); + $no_effect = array(); + foreach ($phids as $phid) { + if (isset($current_value[$phid])) { + $no_effect[] = $phid; + unset($phids[$phid]); + } + } + + if ($no_effect) { + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $no_effect); + } + + if (!$phids) { + return; + } + + $allowed_types = array_fuse($allowed_types); + $invalid = array(); + foreach ($phids as $phid) { + $type = phid_get_type($phid); + if ($type == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { + $invalid[] = $phid; + unset($phids[$phid]); + continue; + } + + if ($allowed_types && empty($allowed_types[$type])) { + $invalid[] = $phid; + unset($phids[$phid]); + continue; + } + } + + if ($invalid) { + $this->logEffect(self::DO_STANDARD_INVALID, $invalid); + } + + if (!$phids) { + return; + } + + $targets = id(new PhabricatorObjectQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withPHIDs($phids) + ->execute(); + $targets = mpull($targets, null, 'getPHID'); + + $unloadable = array(); + foreach ($phids as $phid) { + if (empty($targets[$phid])) { + $unloadable[] = $phid; + unset($phids[$phid]); + } + } + + if ($unloadable) { + $this->logEffect(self::DO_STANDARD_UNLOADABLE, $unloadable); + } + + if (!$phids) { + return; + } + + $adapter = $this->getAdapter(); + $object = $adapter->getObject(); + + if ($object instanceof PhabricatorPolicyInterface) { + $no_permission = array(); + foreach ($targets as $phid => $target) { + if (!($target instanceof PhabricatorUser)) { + continue; + } + + $can_view = PhabricatorPolicyFilter::hasCapability( + $target, + $object, + PhabricatorPolicyCapability::CAN_VIEW); + if ($can_view) { + continue; + } + + $no_permission[] = $phid; + unset($targets[$phid]); + } + } + + if ($no_permission) { + $this->logEffect(self::DO_STANDARD_PERMISSION, $no_permission); + } + + return $targets; + } + + protected function getStandardEffectMap() { + return array( + self::DO_STANDARD_EMPTY => array( + 'icon' => 'fa-ban', + 'color' => 'grey', + 'name' => pht('No Targets'), + ), + self::DO_STANDARD_NO_EFFECT => array( + 'icon' => 'fa-circle-o', + 'color' => 'grey', + 'name' => pht('No Effect'), + ), + self::DO_STANDARD_INVALID => array( + 'icon' => 'fa-ban', + 'color' => 'red', + 'name' => pht('Invalid Targets'), + ), + self::DO_STANDARD_UNLOADABLE => array( + 'icon' => 'fa-ban', + 'color' => 'red', + 'name' => pht('Unloadable Targets'), + ), + self::DO_STANDARD_PERMISSION => array( + 'icon' => 'fa-lock', + 'color' => 'red', + 'name' => pht('No Permission'), + ), + self::DO_STANDARD_INVALID_ACTION => array( + 'icon' => 'fa-ban', + 'color' => 'red', + 'name' => pht('Invalid Action'), + ), + self::DO_STANDARD_WRONG_RULE_TYPE => array( + 'icon' => 'fa-ban', + 'color' => 'red', + 'name' => pht('Wrong Rule Type'), + ), + ); + } + + final public function renderEffectDescription($type, $data) { + $result = $this->renderActionEffectDescription($type, $data); + if ($result !== null) { + return $result; + } + + switch ($type) { + case self::DO_STANDARD_EMPTY: + return pht( + 'This action specifies no targets.'); + case self::DO_STANDARD_NO_EFFECT: + return pht( + 'This action has no effect on %s target(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_STANDARD_INVALID: + return pht( + '%s target(s) are invalid or of the wrong type: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_STANDARD_UNLOADABLE: + return pht( + '%s target(s) could not be loaded: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_STANDARD_PERMISSION: + return pht( + '%s target(s) do not have permission to see this object: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_STANDARD_INVALID_ACTION: + return pht( + 'No implementation is available for rule "%s".', + $data); + case self::DO_STANDARD_WRONG_RULE_TYPE: + return pht( + 'This action does not support rules of type "%s".', + $data); + } + + return null; + } + +} diff --git a/src/applications/herald/action/HeraldActionGroup.php b/src/applications/herald/action/HeraldActionGroup.php new file mode 100644 index 0000000000..a087909609 --- /dev/null +++ b/src/applications/herald/action/HeraldActionGroup.php @@ -0,0 +1,28 @@ +getConstant('ACTIONGROUPKEY'); + if ($const === false) { + throw new Exception( + pht( + '"%s" class "%s" must define a "%s" property.', + __CLASS__, + get_class($this), + 'ACTIONGROUPKEY')); + } + + return $const; + } + + final public static function getAllActionGroups() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getGroupKey') + ->setSortMethod('getSortKey') + ->execute(); + } +} diff --git a/src/applications/herald/action/HeraldApplicationActionGroup.php b/src/applications/herald/action/HeraldApplicationActionGroup.php new file mode 100644 index 0000000000..b2b6e8d2c6 --- /dev/null +++ b/src/applications/herald/action/HeraldApplicationActionGroup.php @@ -0,0 +1,15 @@ +logEffect(self::DO_NOTHING); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + protected function getActionEffectMap() { + return array( + self::DO_NOTHING => array( + 'icon' => 'fa-check', + 'color' => 'grey', + 'name' => pht('Did Nothing'), + ), + ); + } + + public function renderActionDescription($value) { + return pht('Do nothing.'); + } + + protected function renderActionEffectDescription($type, $data) { + return pht('Did nothing.'); + } + +} diff --git a/src/applications/herald/action/HeraldNotifyActionGroup.php b/src/applications/herald/action/HeraldNotifyActionGroup.php new file mode 100644 index 0000000000..df8c395341 --- /dev/null +++ b/src/applications/herald/action/HeraldNotifyActionGroup.php @@ -0,0 +1,15 @@ +emailPHIDs); @@ -59,35 +44,12 @@ abstract class HeraldAdapter extends Phobject { return array_values($this->forcedEmailPHIDs); } - public function getCustomActions() { - if ($this->customActions === null) { - $custom_actions = id(new PhutilSymbolLoader()) - ->setAncestorClass('HeraldCustomAction') - ->loadObjects(); - - foreach ($custom_actions as $key => $object) { - if (!$object->appliesToAdapter($this)) { - unset($custom_actions[$key]); - } - } - - $this->customActions = array(); - foreach ($custom_actions as $action) { - $key = $action->getActionKey(); - - if (array_key_exists($key, $this->customActions)) { - throw new Exception( - pht( - "More than one Herald custom action implementation ". - "handles the action key: '%s'.", - $key)); - } - - $this->customActions[$key] = $action; - } + public function addEmailPHID($phid, $force) { + $this->emailPHIDs[$phid] = $phid; + if ($force) { + $this->forcedEmailPHIDs[$phid] = $phid; } - - return $this->customActions; + return $this; } public function setContentSource(PhabricatorContentSource $content_source) { @@ -149,19 +111,6 @@ abstract class HeraldAdapter extends Phobject { return $result; } - protected function handleCustomHeraldEffect(HeraldEffect $effect) { - $custom_action = idx($this->getCustomActions(), $effect->getAction()); - - if ($custom_action !== null) { - return $custom_action->applyEffect( - $this, - $this->getObject(), - $effect); - } - - return null; - } - public function isAvailableToUser(PhabricatorUser $viewer) { $applications = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) @@ -180,7 +129,7 @@ abstract class HeraldAdapter extends Phobject { return $this->queuedTransactions; } - protected function newTransaction() { + public function newTransaction() { $object = $this->newObject(); if (!($object instanceof PhabricatorApplicationTransactionInterface)) { @@ -615,120 +564,117 @@ abstract class HeraldAdapter extends Phobject { /* -( Actions )------------------------------------------------------------ */ - public function getCustomActionsForRuleType($rule_type) { - $results = array(); - foreach ($this->getCustomActions() as $custom_action) { - if ($custom_action->appliesToRuleType($rule_type)) { - $results[] = $custom_action; + private function getActionImplementationMap() { + if ($this->actionMap === null) { + // We can't use PhutilClassMapQuery here because action expansion + // depends on the adapter and object. + + $object = $this->getObject(); + + $map = array(); + $all = HeraldAction::getAllActions(); + foreach ($all as $key => $action) { + $action = id(clone $action)->setAdapter($this); + + if (!$action->supportsObject($object)) { + continue; + } + + $subactions = $action->getActionsForObject($object); + foreach ($subactions as $subkey => $subaction) { + if (isset($map[$subkey])) { + throw new Exception( + pht( + 'Two HeraldActions (of classes "%s" and "%s") have the same '. + 'action key ("%s") after expansion for an object of class '. + '"%s" inside adapter "%s". Each action must have a unique '. + 'action key.', + get_class($subaction), + get_class($map[$subkey]), + $subkey, + get_class($object), + get_class($this))); + } + + $subaction = id(clone $subaction)->setAdapter($this); + + $map[$subkey] = $subaction; + } } + $this->actionMap = $map; } - return $results; + + return $this->actionMap; } - public function getActions($rule_type) { - $custom_actions = $this->getCustomActionsForRuleType($rule_type); - $custom_actions = mpull($custom_actions, 'getActionKey'); + private function requireActionImplementation($action_key) { + $action = $this->getActionImplementation($action_key); - $actions = $custom_actions; + if (!$action) { + throw new Exception( + pht( + 'No action with key "%s" is available to Herald adapter "%s".', + $action_key, + get_class($this))); + } - $object = $this->newObject(); + return $action; + } - if (($object instanceof PhabricatorProjectInterface)) { - if ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) { - $actions[] = self::ACTION_ADD_PROJECTS; - $actions[] = self::ACTION_REMOVE_PROJECTS; + private function getActionsForRuleType($rule_type) { + $actions = $this->getActionImplementationMap(); + + foreach ($actions as $key => $action) { + if (!$action->supportsRuleType($rule_type)) { + unset($actions[$key]); } } return $actions; } - public function getActionNameMap($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - case HeraldRuleTypeConfig::RULE_TYPE_OBJECT: - $standard = array( - self::ACTION_NOTHING => pht('Do nothing'), - self::ACTION_ADD_CC => pht('Add Subscribers'), - self::ACTION_REMOVE_CC => pht('Remove Subscribers'), - self::ACTION_EMAIL => pht('Send an email to'), - self::ACTION_AUDIT => pht('Trigger an Audit by'), - self::ACTION_FLAG => pht('Mark with flag'), - self::ACTION_ASSIGN_TASK => pht('Assign task to'), - self::ACTION_ADD_PROJECTS => pht('Add projects'), - self::ACTION_REMOVE_PROJECTS => pht('Remove projects'), - self::ACTION_ADD_REVIEWERS => pht('Add reviewers'), - self::ACTION_ADD_BLOCKING_REVIEWERS => pht('Add blocking reviewers'), - self::ACTION_APPLY_BUILD_PLANS => pht('Run build plans'), - self::ACTION_REQUIRE_SIGNATURE => pht('Require legal signatures'), - self::ACTION_BLOCK => pht('Block change with message'), - ); - break; - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: - $standard = array( - self::ACTION_NOTHING => pht('Do nothing'), - self::ACTION_ADD_CC => pht('Add me as a subscriber'), - self::ACTION_REMOVE_CC => pht('Remove me as a subscriber'), - self::ACTION_EMAIL => pht('Send me an email'), - self::ACTION_AUDIT => pht('Trigger an Audit by me'), - self::ACTION_FLAG => pht('Mark with flag'), - self::ACTION_ASSIGN_TASK => pht('Assign task to me'), - self::ACTION_ADD_REVIEWERS => pht('Add me as a reviewer'), - self::ACTION_ADD_BLOCKING_REVIEWERS => - pht('Add me as a blocking reviewer'), - ); - break; - default: - throw new Exception(pht("Unknown rule type '%s'!", $rule_type)); + public function getActionImplementation($key) { + return idx($this->getActionImplementationMap(), $key); + } + + public function getActionKeys() { + return array_keys($this->getActionImplementationMap()); + } + + public function getActionGroupKey($action_key) { + $action = $this->getActionImplementation($action_key); + if (!$action) { + return null; } - $custom_actions = $this->getCustomActionsForRuleType($rule_type); - $standard += mpull($custom_actions, 'getActionName', 'getActionKey'); + return $action->getActionGroupKey(); + } - return $standard; + public function getActions($rule_type) { + $actions = array(); + foreach ($this->getActionsForRuleType($rule_type) as $key => $action) { + $actions[] = $key; + } + + return $actions; + } + + public function getActionNameMap($rule_type) { + $map = array(); + foreach ($this->getActionsForRuleType($rule_type) as $key => $action) { + $map[$key] = $action->getHeraldActionName(); + } + + return $map; } public function willSaveAction( HeraldRule $rule, HeraldActionRecord $action) { + $impl = $this->requireActionImplementation($action->getAction()); $target = $action->getTarget(); - if (is_array($target)) { - $target = array_keys($target); - } - - $author_phid = $rule->getAuthorPHID(); - - $rule_type = $rule->getRuleType(); - if ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL) { - switch ($action->getAction()) { - case self::ACTION_EMAIL: - case self::ACTION_ADD_CC: - case self::ACTION_REMOVE_CC: - case self::ACTION_AUDIT: - case self::ACTION_ASSIGN_TASK: - case self::ACTION_ADD_REVIEWERS: - case self::ACTION_ADD_BLOCKING_REVIEWERS: - // For personal rules, force these actions to target the rule owner. - $target = array($author_phid); - break; - case self::ACTION_FLAG: - // Make sure flag color is valid; set to blue if not. - $color_map = PhabricatorFlagColor::getColorNameMap(); - if (empty($color_map[$target])) { - $target = PhabricatorFlagColor::COLOR_BLUE; - } - break; - case self::ACTION_BLOCK: - case self::ACTION_NOTHING: - break; - default: - throw new HeraldInvalidActionException( - pht( - 'Unrecognized action type "%s"!', - $action->getAction())); - } - } + $target = $impl->willSaveActionValue($target); $action->setTarget($target); } @@ -744,73 +690,8 @@ abstract class HeraldAdapter extends Phobject { } public function getValueTypeForAction($action, $rule_type) { - $is_personal = ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_PERSONAL); - - if ($is_personal) { - switch ($action) { - case self::ACTION_ADD_CC: - case self::ACTION_REMOVE_CC: - case self::ACTION_EMAIL: - case self::ACTION_NOTHING: - case self::ACTION_AUDIT: - case self::ACTION_ASSIGN_TASK: - case self::ACTION_ADD_REVIEWERS: - case self::ACTION_ADD_BLOCKING_REVIEWERS: - return new HeraldEmptyFieldValue(); - case self::ACTION_FLAG: - return $this->buildFlagColorFieldValue(); - case self::ACTION_ADD_PROJECTS: - case self::ACTION_REMOVE_PROJECTS: - return $this->buildTokenizerFieldValue( - new PhabricatorProjectDatasource()); - } - } else { - switch ($action) { - case self::ACTION_ADD_CC: - case self::ACTION_REMOVE_CC: - case self::ACTION_EMAIL: - return $this->buildTokenizerFieldValue( - new PhabricatorMetaMTAMailableDatasource()); - case self::ACTION_NOTHING: - return new HeraldEmptyFieldValue(); - case self::ACTION_ADD_PROJECTS: - case self::ACTION_REMOVE_PROJECTS: - return $this->buildTokenizerFieldValue( - new PhabricatorProjectDatasource()); - case self::ACTION_FLAG: - return $this->buildFlagColorFieldValue(); - case self::ACTION_ASSIGN_TASK: - return $this->buildTokenizerFieldValue( - new PhabricatorPeopleDatasource()); - case self::ACTION_AUDIT: - case self::ACTION_ADD_REVIEWERS: - case self::ACTION_ADD_BLOCKING_REVIEWERS: - return $this->buildTokenizerFieldValue( - new PhabricatorProjectOrUserDatasource()); - case self::ACTION_APPLY_BUILD_PLANS: - return $this->buildTokenizerFieldValue( - new HarbormasterBuildPlanDatasource()); - case self::ACTION_REQUIRE_SIGNATURE: - return $this->buildTokenizerFieldValue( - new LegalpadDocumentDatasource()); - case self::ACTION_BLOCK: - return new HeraldTextFieldValue(); - } - } - - $custom_action = idx($this->getCustomActions(), $action); - if ($custom_action !== null) { - return $custom_action->getActionType(); - } - - throw new Exception(pht("Unknown or invalid action '%s'.", $action)); - } - - private function buildFlagColorFieldValue() { - return id(new HeraldSelectFieldValue()) - ->setKey('flag.color') - ->setOptions(PhabricatorFlagColor::getColorNameMap()) - ->setDefault(PhabricatorFlagColor::COLOR_BLUE); + $impl = $this->requireActionImplementation($action); + return $impl->getHeraldActionValueType(); } private function buildTokenizerFieldValue( @@ -889,8 +770,7 @@ abstract class HeraldAdapter extends Phobject { public function getEditorValueForCondition( PhabricatorUser $viewer, - HeraldCondition $condition, - array $handles) { + HeraldCondition $condition) { $field = $this->requireFieldImplementation($condition->getFieldName()); @@ -900,6 +780,17 @@ abstract class HeraldAdapter extends Phobject { $condition->getValue()); } + public function getEditorValueForAction( + PhabricatorUser $viewer, + HeraldActionRecord $action_record) { + + $action = $this->requireActionImplementation($action_record->getAction()); + + return $action->getEditorValue( + $viewer, + $action_record->getTarget()); + } + public function renderRuleAsText( HeraldRule $rule, PhabricatorHandleList $handles, @@ -964,7 +855,7 @@ abstract class HeraldAdapter extends Phobject { ), array( $icon, - $this->renderActionAsText($action, $handles), + $this->renderActionAsText($viewer, $action, $handles), )); } @@ -982,22 +873,41 @@ abstract class HeraldAdapter extends Phobject { PhabricatorUser $viewer) { $field_type = $condition->getFieldName(); + $field = $this->getFieldImplementation($field_type); - $default = pht('(Unknown Field "%s")', $field_type); + if (!$field) { + return pht('Unknown Field: "%s"', $field_type); + } - $field_name = idx($this->getFieldNameMap(), $field_type, $default); + $field_name = $field->getHeraldFieldName(); $condition_type = $condition->getFieldCondition(); $condition_name = idx($this->getConditionNameMap(), $condition_type); $value = $this->renderConditionValueAsText($condition, $handles, $viewer); - return hsprintf(' %s %s %s', $field_name, $condition_name, $value); + return array( + $field_name, + ' ', + $condition_name, + ' ', + $value, + ); } private function renderActionAsText( + PhabricatorUser $viewer, HeraldActionRecord $action, PhabricatorHandleList $handles) { + + $impl = $this->getActionImplementation($action->getAction()); + if ($impl) { + $impl->setViewer($viewer); + + $value = $action->getTarget(); + return $impl->renderActionDescription($value); + } + $rule_global = HeraldRuleTypeConfig::RULE_TYPE_GLOBAL; $action_type = $action->getAction(); @@ -1031,15 +941,14 @@ abstract class HeraldAdapter extends Phobject { HeraldActionRecord $action, PhabricatorHandleList $handles) { + // TODO: This should be driven through HeraldAction. + $target = $action->getTarget(); if (!is_array($target)) { $target = array($target); } foreach ($target as $index => $val) { switch ($action->getAction()) { - case self::ACTION_FLAG: - $target[$index] = PhabricatorFlagColor::getColorName($val); - break; default: $handle = $handles->getHandleIfExists($val); if ($handle) { @@ -1107,244 +1016,46 @@ abstract class HeraldAdapter extends Phobject { */ protected function applyStandardEffect(HeraldEffect $effect) { $action = $effect->getAction(); - $rule_type = $effect->getRule()->getRuleType(); - $supported = $this->getActions($rule_type); - $supported = array_fuse($supported); - if (empty($supported[$action])) { + + $impl = $this->getActionImplementation($action); + if (!$impl) { return new HeraldApplyTranscript( $effect, false, - pht( - 'Adapter "%s" does not support action "%s" for rule type "%s".', - get_class($this), - $action, - $rule_type)); - } - - switch ($action) { - case self::ACTION_ADD_PROJECTS: - case self::ACTION_REMOVE_PROJECTS: - return $this->applyProjectsEffect($effect); - case self::ACTION_ADD_CC: - case self::ACTION_REMOVE_CC: - return $this->applySubscribersEffect($effect); - case self::ACTION_FLAG: - return $this->applyFlagEffect($effect); - case self::ACTION_EMAIL: - return $this->applyEmailEffect($effect); - case self::ACTION_NOTHING: - return $this->applyNothingEffect($effect); - default: - break; - } - - $result = $this->handleCustomHeraldEffect($effect); - - if (!$result) { - return new HeraldApplyTranscript( - $effect, - false, - pht( - 'No custom action exists to handle rule action "%s".', - $action)); - } - - return $result; - } - - private function applyNothingEffect(HeraldEffect $effect) { - return new HeraldApplyTranscript( - $effect, - true, - pht('Did nothing.')); - } - - /** - * @task apply - */ - private function applyProjectsEffect(HeraldEffect $effect) { - - if ($effect->getAction() == self::ACTION_ADD_PROJECTS) { - $kind = '+'; - } else { - $kind = '-'; - } - - $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $project_phids = $effect->getTarget(); - $xaction = $this->newTransaction() - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $project_type) - ->setNewValue( array( - $kind => array_fuse($project_phids), + array( + HeraldAction::DO_STANDARD_INVALID_ACTION, + $action, + ), )); - - $this->queueTransaction($xaction); - - return new HeraldApplyTranscript( - $effect, - true, - pht('Added projects.')); - } - - /** - * @task apply - */ - private function applySubscribersEffect(HeraldEffect $effect) { - if ($effect->getAction() == self::ACTION_ADD_CC) { - $kind = '+'; - $is_add = true; - } else { - $kind = '-'; - $is_add = false; } - $subscriber_phids = array_fuse($effect->getTarget()); - if (!$subscriber_phids) { + if (!$impl->supportsRuleType($rule_type)) { return new HeraldApplyTranscript( $effect, false, - pht('This action lists no users or objects to affect.')); - } - - // The "Add Subscribers" rule only adds subscribers who haven't previously - // unsubscribed from the object explicitly. Filter these subscribers out - // before continuing. - $unsubscribed = array(); - if ($is_add) { - if ($this->unsubscribedPHIDs === null) { - $this->unsubscribedPHIDs = PhabricatorEdgeQuery::loadDestinationPHIDs( - $this->getObject()->getPHID(), - PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST); - } - - foreach ($this->unsubscribedPHIDs as $phid) { - if (isset($subscriber_phids[$phid])) { - $unsubscribed[$phid] = $phid; - unset($subscriber_phids[$phid]); - } - } - } - - if (!$subscriber_phids) { - return new HeraldApplyTranscript( - $effect, - false, - pht('All targets have previously unsubscribed explicitly.')); - } - - // Filter out PHIDs which aren't valid subscribers. Lower levels of the - // stack will fail loudly if we try to add subscribers with invalid PHIDs - // or unknown PHID types, so drop them here. - $invalid = array(); - foreach ($subscriber_phids as $phid) { - $type = phid_get_type($phid); - switch ($type) { - case PhabricatorPeopleUserPHIDType::TYPECONST: - case PhabricatorProjectProjectPHIDType::TYPECONST: - break; - default: - $invalid[$phid] = $phid; - unset($subscriber_phids[$phid]); - break; - } - } - - if (!$subscriber_phids) { - return new HeraldApplyTranscript( - $effect, - false, - pht('All targets are invalid as subscribers.')); - } - - $xaction = $this->newTransaction() - ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) - ->setNewValue( array( - $kind => $subscriber_phids, + array( + HeraldAction::DO_STANDARD_WRONG_RULE_TYPE, + $rule_type, + ), )); - - $this->queueTransaction($xaction); - - // TODO: We could be more detailed about this, but doing it meaningfully - // probably requires substantial changes to how transactions are rendered - // first. - if ($is_add) { - $message = pht('Subscribed targets.'); - } else { - $message = pht('Unsubscribed targets.'); } - return new HeraldApplyTranscript($effect, true, $message); + $impl->applyEffect($this->getObject(), $effect); + return $impl->getApplyTranscript($effect); } + public function loadEdgePHIDs($type) { + if (!isset($this->edgeCache[$type])) { + $phids = PhabricatorEdgeQuery::loadDestinationPHIDs( + $this->getObject()->getPHID(), + $type); - /** - * @task apply - */ - private function applyFlagEffect(HeraldEffect $effect) { - $phid = $this->getPHID(); - $color = $effect->getTarget(); - - $rule = $effect->getRule(); - $user = $rule->getAuthor(); - - $flag = PhabricatorFlagQuery::loadUserFlag($user, $phid); - if ($flag) { - return new HeraldApplyTranscript( - $effect, - false, - pht('Object already flagged.')); + $this->edgeCache[$type] = array_fuse($phids); } - - $handle = id(new PhabricatorHandleQuery()) - ->setViewer($user) - ->withPHIDs(array($phid)) - ->executeOne(); - - $flag = new PhabricatorFlag(); - $flag->setOwnerPHID($user->getPHID()); - $flag->setType($handle->getType()); - $flag->setObjectPHID($handle->getPHID()); - - // TOOD: Should really be transcript PHID, but it doesn't exist yet. - $flag->setReasonPHID($user->getPHID()); - - $flag->setColor($color); - $flag->setNote( - pht('Flagged by Herald Rule "%s".', $rule->getName())); - $flag->save(); - - return new HeraldApplyTranscript( - $effect, - true, - pht('Added flag.')); + return $this->edgeCache[$type]; } - - /** - * @task apply - */ - private function applyEmailEffect(HeraldEffect $effect) { - foreach ($effect->getTarget() as $phid) { - $this->emailPHIDs[$phid] = $phid; - - // If this is a personal rule, we'll force delivery of a real email. This - // effect is stronger than notification preferences, so you get an actual - // email even if your preferences are set to "Notify" or "Ignore". - $rule = $effect->getRule(); - if ($rule->isPersonalRule()) { - $this->forcedEmailPHIDs[$phid] = $phid; - } - } - - return new HeraldApplyTranscript( - $effect, - true, - pht('Added mailable to mail targets.')); - } - - } diff --git a/src/applications/herald/application/PhabricatorHeraldApplication.php b/src/applications/herald/application/PhabricatorHeraldApplication.php index b74a27d9f2..e3537d9722 100644 --- a/src/applications/herald/application/PhabricatorHeraldApplication.php +++ b/src/applications/herald/application/PhabricatorHeraldApplication.php @@ -58,7 +58,7 @@ final class PhabricatorHeraldApplication extends PhabricatorApplication { 'transcript/' => array( '' => 'HeraldTranscriptListController', '(?:query/(?P[^/]+)/)?' => 'HeraldTranscriptListController', - '(?P[1-9]\d*)/(?:(?P\w+)/)?' + '(?P[1-9]\d*)/' => 'HeraldTranscriptController', ), ), diff --git a/src/applications/herald/controller/HeraldDisableController.php b/src/applications/herald/controller/HeraldDisableController.php index edf15f80f6..054f30e7d3 100644 --- a/src/applications/herald/controller/HeraldDisableController.php +++ b/src/applications/herald/controller/HeraldDisableController.php @@ -2,18 +2,10 @@ final class HeraldDisableController extends HeraldController { - private $id; - private $action; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - $this->action = $data['action']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - $id = $this->id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $action = $request->getURIData('action'); $rule = id(new HeraldRuleQuery()) ->setViewer($viewer) @@ -35,7 +27,7 @@ final class HeraldDisableController extends HeraldController { $view_uri = $this->getApplicationURI("rule/{$id}/"); - $is_disable = ($this->action === 'disable'); + $is_disable = ($action === 'disable'); if ($request->isFormPost()) { $xaction = id(new HeraldRuleTransaction()) diff --git a/src/applications/herald/controller/HeraldNewController.php b/src/applications/herald/controller/HeraldNewController.php index 2bbc00456f..53e1faf7d6 100644 --- a/src/applications/herald/controller/HeraldNewController.php +++ b/src/applications/herald/controller/HeraldNewController.php @@ -2,9 +2,8 @@ final class HeraldNewController extends HeraldController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer); $rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap(); diff --git a/src/applications/herald/controller/HeraldRuleController.php b/src/applications/herald/controller/HeraldRuleController.php index 5f447abffd..ce7a46cd00 100644 --- a/src/applications/herald/controller/HeraldRuleController.php +++ b/src/applications/herald/controller/HeraldRuleController.php @@ -2,24 +2,16 @@ final class HeraldRuleController extends HeraldController { - private $id; - private $filter; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = (int)idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $content_type_map = HeraldAdapter::getEnabledAdapterMap($user); + $content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer); $rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap(); - if ($this->id) { - $id = $this->id; + if ($id) { $rule = id(new HeraldRuleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -33,7 +25,7 @@ final class HeraldRuleController extends HeraldController { $cancel_uri = $this->getApplicationURI("rule/{$id}/"); } else { $rule = new HeraldRule(); - $rule->setAuthorPHID($user->getPHID()); + $rule->setAuthorPHID($viewer->getPHID()); $rule->setMustMatchAll(1); $content_type = $request->getStr('content_type'); @@ -58,7 +50,7 @@ final class HeraldRuleController extends HeraldController { if ($rule->isObjectRule()) { $rule->setTriggerObjectPHID($request->getStr('targetPHID')); $object = id(new PhabricatorObjectQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($rule->getTriggerObjectPHID())) ->requireCapabilities( array( @@ -128,7 +120,7 @@ final class HeraldRuleController extends HeraldController { $rule_type_name = $rule_type_map[$rule->getRuleType()]; $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->setID('herald-rule-edit-form') ->addHiddenInput('content_type', $rule->getContentType()) ->addHiddenInput('rule_type', $rule->getRuleType()) @@ -356,8 +348,7 @@ final class HeraldRuleController extends HeraldController { foreach ($rule->getConditions() as $condition) { $value = $adapter->getEditorValueForCondition( $this->getViewer(), - $condition, - $handles); + $condition); $serial_conditions[] = array( $condition->getFieldName(), @@ -374,27 +365,13 @@ final class HeraldRuleController extends HeraldController { if ($rule->getActions()) { $serial_actions = array(); foreach ($rule->getActions() as $action) { - switch ($action->getAction()) { - case HeraldAdapter::ACTION_FLAG: - case HeraldAdapter::ACTION_BLOCK: - $current_value = $action->getTarget(); - break; - default: - if (is_array($action->getTarget())) { - $target_map = array(); - foreach ((array)$action->getTarget() as $fbid) { - $target_map[$fbid] = $handles[$fbid]->getName(); - } - $current_value = $target_map; - } else { - $current_value = $action->getTarget(); - } - break; - } + $value = $adapter->getEditorValueForAction( + $this->getViewer(), + $action); $serial_actions[] = array( $action->getAction(), - $current_value, + $value, ); } } @@ -435,40 +412,10 @@ final class HeraldRuleController extends HeraldController { } } - $group_map = array(); - foreach ($field_map as $field_key => $field_name) { - $group_key = $adapter->getFieldGroupKey($field_key); - $group_map[$group_key][$field_key] = $field_name; - } - - $field_groups = HeraldFieldGroup::getAllFieldGroups(); - - $groups = array(); - foreach ($group_map as $group_key => $options) { - asort($options); - - $field_group = idx($field_groups, $group_key); - if ($field_group) { - $group_label = $field_group->getGroupLabel(); - $group_order = $field_group->getSortKey(); - } else { - $group_label = nonempty($group_key, pht('Other')); - $group_order = 'Z'; - } - - $groups[] = array( - 'label' => $group_label, - 'options' => $options, - 'order' => $group_order, - ); - } - - $groups = array_values(isort($groups, 'order')); - $config_info = array(); - $config_info['fields'] = $groups; + $config_info['fields'] = $this->getFieldGroups($adapter, $field_map); $config_info['conditions'] = $all_conditions; - $config_info['actions'] = $action_map; + $config_info['actions'] = $this->getActionGroups($adapter, $action_map); $config_info['valueMap'] = array(); foreach ($field_map as $field => $name) { @@ -500,7 +447,7 @@ final class HeraldRuleController extends HeraldController { $config_info['rule_type'] = $rule->getRuleType(); - foreach ($config_info['actions'] as $action => $name) { + foreach ($action_map as $action => $name) { try { $value_key = $adapter->getValueTypeForAction( $action, @@ -667,4 +614,55 @@ final class HeraldRuleController extends HeraldController { return $all_rules; } + private function getFieldGroups(HeraldAdapter $adapter, array $field_map) { + $group_map = array(); + foreach ($field_map as $field_key => $field_name) { + $group_key = $adapter->getFieldGroupKey($field_key); + $group_map[$group_key][$field_key] = $field_name; + } + + return $this->getGroups( + $group_map, + HeraldFieldGroup::getAllFieldGroups()); + } + + private function getActionGroups(HeraldAdapter $adapter, array $action_map) { + $group_map = array(); + foreach ($action_map as $action_key => $action_name) { + $group_key = $adapter->getActionGroupKey($action_key); + $group_map[$group_key][$action_key] = $action_name; + } + + return $this->getGroups( + $group_map, + HeraldActionGroup::getAllActionGroups()); + } + + private function getGroups(array $item_map, array $group_list) { + assert_instances_of($group_list, 'HeraldGroup'); + + $groups = array(); + foreach ($item_map as $group_key => $options) { + asort($options); + + $group_object = idx($group_list, $group_key); + if ($group_object) { + $group_label = $group_object->getGroupLabel(); + $group_order = $group_object->getSortKey(); + } else { + $group_label = nonempty($group_key, pht('Other')); + $group_order = 'Z'; + } + + $groups[] = array( + 'label' => $group_label, + 'options' => $options, + 'order' => $group_order, + ); + } + + return array_values(isort($groups, 'order')); + } + + } diff --git a/src/applications/herald/controller/HeraldRuleListController.php b/src/applications/herald/controller/HeraldRuleListController.php index 8847b5d06b..490d84212d 100644 --- a/src/applications/herald/controller/HeraldRuleListController.php +++ b/src/applications/herald/controller/HeraldRuleListController.php @@ -2,19 +2,15 @@ final class HeraldRuleListController extends HeraldController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new HeraldRuleSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/herald/controller/HeraldRuleViewController.php b/src/applications/herald/controller/HeraldRuleViewController.php index f1ba8e44d7..f6ec235a9e 100644 --- a/src/applications/herald/controller/HeraldRuleViewController.php +++ b/src/applications/herald/controller/HeraldRuleViewController.php @@ -2,19 +2,13 @@ final class HeraldRuleViewController extends HeraldController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $rule = id(new HeraldRuleQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needConditionsAndActions(true) ->executeOne(); if (!$rule) { diff --git a/src/applications/herald/controller/HeraldTestConsoleController.php b/src/applications/herald/controller/HeraldTestConsoleController.php index 7cd610f35a..a7741ba3ce 100644 --- a/src/applications/herald/controller/HeraldTestConsoleController.php +++ b/src/applications/herald/controller/HeraldTestConsoleController.php @@ -2,13 +2,8 @@ final class HeraldTestConsoleController extends HeraldController { - public function processRequest() { - - $request = $this->getRequest(); - $user = $request->getUser(); - - $request = $this->getRequest(); - + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $object_name = trim($request->getStr('object_name')); $e_name = true; @@ -21,7 +16,7 @@ final class HeraldTestConsoleController extends HeraldController { if (!$errors) { $object = id(new PhabricatorObjectQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withNames(array($object_name)) ->executeOne(); @@ -57,7 +52,7 @@ final class HeraldTestConsoleController extends HeraldController { $adapter->setIsNewObject(false); $rules = id(new HeraldRuleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withContentTypes(array($adapter->getAdapterContentType())) ->withDisabled(false) ->needConditionsAndActions(true) @@ -80,7 +75,7 @@ final class HeraldTestConsoleController extends HeraldController { } $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendRemarkupInstructions( pht( 'Enter an object to test rules for, like a Diffusion commit (e.g., '. diff --git a/src/applications/herald/controller/HeraldTranscriptController.php b/src/applications/herald/controller/HeraldTranscriptController.php index eac808b54e..64563b7ef8 100644 --- a/src/applications/herald/controller/HeraldTranscriptController.php +++ b/src/applications/herald/controller/HeraldTranscriptController.php @@ -2,43 +2,26 @@ final class HeraldTranscriptController extends HeraldController { - const FILTER_AFFECTED = 'affected'; - const FILTER_OWNED = 'owned'; - const FILTER_ALL = 'all'; - - private $id; - private $filter; private $handles; private $adapter; - public function willProcessRequest(array $data) { - $this->id = $data['id']; - $map = $this->getFilterMap(); - $this->filter = idx($data, 'filter'); - if (empty($map[$this->filter])) { - $this->filter = self::FILTER_ALL; - } - } - private function getAdapter() { return $this->adapter; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); $xscript = id(new HeraldTranscriptQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($request->getURIData('id'))) ->executeOne(); if (!$xscript) { return new Aphront404Response(); } require_celerity_resource('herald-test-css'); - - $nav = $this->buildSideNav(); + $content = array(); $object_xscript = $xscript->getObjectTranscript(); if (!$object_xscript) { @@ -49,7 +32,7 @@ final class HeraldTranscriptController extends HeraldController { 'p', array(), pht('Details of this transcript have been garbage collected.'))); - $nav->appendChild($notice); + $content[] = $notice; } else { $map = HeraldAdapter::getEnabledAdapterMap($viewer); $object_type = $object_xscript->getType(); @@ -65,9 +48,7 @@ final class HeraldTranscriptController extends HeraldController { $this->adapter = HeraldAdapter::getAdapterForContentType($object_type); - $filter = $this->getFilterPHIDs(); - $this->filterTranscript($xscript, $filter); - $phids = array_merge($filter, $this->getTranscriptPHIDs($xscript)); + $phids = $this->getTranscriptPHIDs($xscript); $phids = array_unique($phids); $phids = array_filter($phids); @@ -82,23 +63,16 @@ final class HeraldTranscriptController extends HeraldController { pht( 'This was a dry run to test Herald rules, '. 'no actions were executed.')); - $nav->appendChild($notice); + $content[] = $notice; } $warning_panel = $this->buildWarningPanel($xscript); - $nav->appendChild($warning_panel); + $content[] = $warning_panel; - $apply_xscript_panel = $this->buildApplyTranscriptPanel( - $xscript); - $nav->appendChild($apply_xscript_panel); - - $action_xscript_panel = $this->buildActionTranscriptPanel( - $xscript); - $nav->appendChild($action_xscript_panel); - - $object_xscript_panel = $this->buildObjectTranscriptPanel( - $xscript); - $nav->appendChild($object_xscript_panel); + $content[] = array( + $this->buildActionTranscriptPanel($xscript), + $this->buildObjectTranscriptPanel($xscript), + ); } $crumbs = id($this->buildApplicationCrumbs()) @@ -106,10 +80,12 @@ final class HeraldTranscriptController extends HeraldController { pht('Transcripts'), $this->getApplicationURI('/transcript/')) ->addTextCrumb($xscript->getID()); - $nav->setCrumbs($crumbs); return $this->buildApplicationPage( - $nav, + array( + $crumbs, + $content, + ), array( 'title' => pht('Transcript'), )); @@ -146,33 +122,6 @@ final class HeraldTranscriptController extends HeraldController { return phutil_tag('span', array('class' => 'condition-test-value'), $value); } - private function buildSideNav() { - $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI('/herald/transcript/'.$this->id.'/')); - - $items = array(); - $filters = $this->getFilterMap(); - foreach ($filters as $key => $name) { - $nav->addFilter($key, $name); - } - $nav->selectFilter($this->filter, null); - - return $nav; - } - - protected function getFilterMap() { - return array( - self::FILTER_ALL => pht('All Rules'), - self::FILTER_OWNED => pht('Rules I Own'), - self::FILTER_AFFECTED => pht('Rules that Affected Me'), - ); - } - - - protected function getFilterPHIDs() { - return array($this->getRequest()->getUser()->getPHID()); - } - protected function getTranscriptPHIDs($xscript) { $phids = array(); @@ -228,71 +177,6 @@ final class HeraldTranscriptController extends HeraldController { return $phids; } - protected function filterTranscript($xscript, $filter_phids) { - $filter_owned = ($this->filter == self::FILTER_OWNED); - $filter_affected = ($this->filter == self::FILTER_AFFECTED); - - if (!$filter_owned && !$filter_affected) { - // No filtering to be done. - return; - } - - if (!$xscript->getObjectTranscript()) { - return; - } - - $user_phid = $this->getRequest()->getUser()->getPHID(); - - $keep_apply_xscripts = array(); - $keep_rule_xscripts = array(); - - $filter_phids = array_fill_keys($filter_phids, true); - - $rule_xscripts = $xscript->getRuleTranscripts(); - foreach ($xscript->getApplyTranscripts() as $id => $apply_xscript) { - $rule_id = $apply_xscript->getRuleID(); - if ($filter_owned) { - if (empty($rule_xscripts[$rule_id])) { - // No associated rule so you can't own this effect. - continue; - } - if ($rule_xscripts[$rule_id]->getRuleOwner() != $user_phid) { - continue; - } - } else if ($filter_affected) { - $targets = (array)$apply_xscript->getTarget(); - if (!array_select_keys($filter_phids, $targets)) { - continue; - } - } - $keep_apply_xscripts[$id] = true; - if ($rule_id) { - $keep_rule_xscripts[$rule_id] = true; - } - } - - foreach ($rule_xscripts as $rule_id => $rule_xscript) { - if ($filter_owned && $rule_xscript->getRuleOwner() == $user_phid) { - $keep_rule_xscripts[$rule_id] = true; - } - } - - $xscript->setRuleTranscripts( - array_intersect_key( - $xscript->getRuleTranscripts(), - $keep_rule_xscripts)); - - $xscript->setApplyTranscripts( - array_intersect_key( - $xscript->getApplyTranscripts(), - $keep_apply_xscripts)); - - $xscript->setConditionTranscripts( - array_intersect_key( - $xscript->getConditionTranscripts(), - $keep_rule_xscripts)); - } - private function buildWarningPanel(HeraldTranscript $xscript) { $request = $this->getRequest(); $panel = null; @@ -333,163 +217,187 @@ final class HeraldTranscriptController extends HeraldController { return $panel; } - private function buildApplyTranscriptPanel(HeraldTranscript $xscript) { - $handles = $this->handles; - $adapter = $this->getAdapter(); - - $rule_type_global = HeraldRuleTypeConfig::RULE_TYPE_GLOBAL; - $action_names = $adapter->getActionNameMap($rule_type_global); - - $list = new PHUIObjectItemListView(); - $list->setStates(true); - $list->setNoDataString(pht('No actions were taken.')); - foreach ($xscript->getApplyTranscripts() as $apply_xscript) { - - $target = $apply_xscript->getTarget(); - switch ($apply_xscript->getAction()) { - case HeraldAdapter::ACTION_NOTHING: - $target = null; - break; - case HeraldAdapter::ACTION_FLAG: - $target = PhabricatorFlagColor::getColorName($target); - break; - case HeraldAdapter::ACTION_BLOCK: - // Target is a text string. - $target = $target; - break; - default: - if (is_array($target) && $target) { - foreach ($target as $k => $phid) { - if (isset($handles[$phid])) { - $target[$k] = $handles[$phid]->getName(); - } - } - $target = implode(', ', $target); - } else if (is_string($target)) { - $target = $target; - } else { - $target = ''; - } - break; - } - - $item = new PHUIObjectItemView(); - - if ($apply_xscript->getApplied()) { - $item->setState(PHUIObjectItemView::STATE_SUCCESS); - } else { - $item->setState(PHUIObjectItemView::STATE_FAIL); - } - - $rule = idx( - $action_names, - $apply_xscript->getAction(), - pht('Unknown Action "%s"', $apply_xscript->getAction())); - - $item->setHeader(pht('%s: %s', $rule, $target)); - $item->addAttribute($apply_xscript->getReason()); - $item->addAttribute( - pht('Outcome: %s', $apply_xscript->getAppliedReason())); - - $list->addItem($item); - } - - $box = new PHUIObjectBoxView(); - $box->setHeaderText(pht('Actions Taken')); - $box->appendChild($list); - - return $box; - } - private function buildActionTranscriptPanel(HeraldTranscript $xscript) { $action_xscript = mgroup($xscript->getApplyTranscripts(), 'getRuleID'); $adapter = $this->getAdapter(); - $field_names = $adapter->getFieldNameMap(); $condition_names = $adapter->getConditionNameMap(); $handles = $this->handles; - $rule_markup = array(); - foreach ($xscript->getRuleTranscripts() as $rule_id => $rule) { - $cond_markup = array(); - foreach ($xscript->getConditionTranscriptsForRule($rule_id) as $cond) { - if ($cond->getNote()) { - $note = phutil_tag_div('herald-condition-note', $cond->getNote()); + $action_map = $xscript->getApplyTranscripts(); + $action_map = mgroup($action_map, 'getRuleID'); + + $rule_list = id(new PHUIObjectItemListView()) + ->setNoDataString(pht('No Herald rules applied to this object.')); + + $rule_xscripts = $xscript->getRuleTranscripts(); + $rule_xscripts = msort($rule_xscripts, 'getRuleID'); + foreach ($rule_xscripts as $rule_xscript) { + $rule_id = $rule_xscript->getRuleID(); + + $rule_item = id(new PHUIObjectItemView()) + ->setObjectName(pht('H%d', $rule_id)) + ->setHeader($rule_xscript->getRuleName()); + + if (!$rule_xscript->getResult()) { + $rule_item->setDisabled(true); + } + + $rule_list->addItem($rule_item); + + // Build the field/condition transcript. + + $cond_xscripts = $xscript->getConditionTranscriptsForRule($rule_id); + + $cond_list = id(new PHUIStatusListView()); + $cond_list->addItem( + id(new PHUIStatusItemView()) + ->setTarget(phutil_tag('strong', array(), pht('Conditions')))); + + foreach ($cond_xscripts as $cond_xscript) { + if ($cond_xscript->getResult()) { + $icon = 'fa-check'; + $color = 'green'; + $result = pht('Passed'); + } else { + $icon = 'fa-times'; + $color = 'red'; + $result = pht('Failed'); + } + + if ($cond_xscript->getNote()) { + $note = phutil_tag( + 'div', + array( + 'class' => 'herald-condition-note', + ), + $cond_xscript->getNote()); } else { $note = null; } - if ($cond->getResult()) { - $result = phutil_tag( - 'span', - array('class' => 'herald-outcome condition-pass'), - "\xE2\x9C\x93"); + // TODO: This is not really translatable and should be driven through + // HeraldField. + $explanation = pht( + '%s %s %s', + idx($field_names, $cond_xscript->getFieldName(), pht('Unknown')), + idx($condition_names, $cond_xscript->getCondition(), pht('Unknown')), + $this->renderConditionTestValue($cond_xscript, $handles)); + + $cond_item = id(new PHUIStatusItemView()) + ->setIcon($icon, $color) + ->setTarget($result) + ->setNote(array($explanation, $note)); + + $cond_list->addItem($cond_item); + } + + if ($rule_xscript->getResult()) { + $last_icon = 'fa-check-circle'; + $last_color = 'green'; + $last_result = pht('Passed'); + $last_note = pht('Rule passed.'); + } else { + $last_icon = 'fa-times-circle'; + $last_color = 'red'; + $last_result = pht('Failed'); + $last_note = pht('Rule failed.'); + } + + $cond_last = id(new PHUIStatusItemView()) + ->setIcon($last_icon, $last_color) + ->setTarget(phutil_tag('strong', array(), $last_result)) + ->setNote($last_note); + $cond_list->addItem($cond_last); + + $cond_box = id(new PHUIBoxView()) + ->appendChild($cond_list) + ->addMargin(PHUI::MARGIN_LARGE_LEFT); + + $rule_item->appendChild($cond_box); + + if (!$rule_xscript->getResult()) { + // If the rule didn't pass, don't generate an action transcript since + // actions didn't apply. + continue; + } + + $cond_box->addMargin(PHUI::MARGIN_MEDIUM_BOTTOM); + + $action_xscripts = idx($action_map, $rule_id, array()); + foreach ($action_xscripts as $action_xscript) { + $action_key = $action_xscript->getAction(); + $action = $adapter->getActionImplementation($action_key); + + if ($action) { + $name = $action->getHeraldActionName(); + $action->setViewer($this->getViewer()); } else { - $result = phutil_tag( - 'span', - array('class' => 'herald-outcome condition-fail'), - "\xE2\x9C\x98"); + $name = pht('Unknown Action ("%s")', $action_key); } - $cond_markup[] = phutil_tag( - 'li', - array(), - pht( - '%s Condition: %s %s %s%s', - $result, - idx($field_names, $cond->getFieldName(), pht('Unknown')), - idx($condition_names, $cond->getCondition(), pht('Unknown')), - $this->renderConditionTestValue($cond, $handles), - $note)); + $name = pht('Action: %s', $name); + + $action_list = id(new PHUIStatusListView()); + $action_list->addItem( + id(new PHUIStatusItemView()) + ->setTarget(phutil_tag('strong', array(), $name))); + + $action_box = id(new PHUIBoxView()) + ->appendChild($action_list) + ->addMargin(PHUI::MARGIN_LARGE_LEFT); + + $rule_item->appendChild($action_box); + + $log = $action_xscript->getAppliedReason(); + + // Handle older transcripts which used a static string to record + // action results. + if (!is_array($log)) { + $action_list->addItem( + id(new PHUIStatusItemView()) + ->setIcon('fa-clock-o', 'grey') + ->setTarget(pht('Old Transcript')) + ->setNote( + pht( + 'This is an old transcript which uses an obsolete log '. + 'format. Detailed action information is not available.'))); + continue; + } + + foreach ($log as $entry) { + $type = idx($entry, 'type'); + $data = idx($entry, 'data'); + + if ($action) { + $icon = $action->renderActionEffectIcon($type, $data); + $color = $action->renderActionEffectColor($type, $data); + $name = $action->renderActionEffectName($type, $data); + $note = $action->renderEffectDescription($type, $data); + } else { + $icon = 'fa-question-circle'; + $color = 'indigo'; + $name = pht('Unknown Effect ("%s")', $type); + $note = null; + } + + $action_item = id(new PHUIStatusItemView()) + ->setIcon($icon, $color) + ->setTarget($name) + ->setNote($note); + + $action_list->addItem($action_item); + } } - - if ($rule->getResult()) { - $result = phutil_tag( - 'span', - array('class' => 'herald-outcome rule-pass'), - pht('PASS')); - $class = 'herald-rule-pass'; - } else { - $result = phutil_tag( - 'span', - array('class' => 'herald-outcome rule-fail'), - pht('FAIL')); - $class = 'herald-rule-fail'; - } - - $cond_markup[] = phutil_tag( - 'li', - array(), - array($result, $rule->getReason())); - $user_phid = $this->getRequest()->getUser()->getPHID(); - - $name = $rule->getRuleName(); - - $rule_markup[] = - phutil_tag( - 'li', - array( - 'class' => $class, - ), - phutil_tag_div('rule-name', array( - phutil_tag('strong', array(), $name), - ' ', - phutil_tag('ul', array(), $cond_markup), - ))); } - $box = null; - if ($rule_markup) { - $box = new PHUIObjectBoxView(); - $box->setHeaderText(pht('Rule Details')); - $box->appendChild(phutil_tag( - 'ul', - array('class' => 'herald-explain-list'), - $rule_markup)); - } + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Rule Transcript')) + ->appendChild($rule_list); + return $box; } diff --git a/src/applications/herald/controller/HeraldTranscriptListController.php b/src/applications/herald/controller/HeraldTranscriptListController.php index d53130d476..81865eee4a 100644 --- a/src/applications/herald/controller/HeraldTranscriptListController.php +++ b/src/applications/herald/controller/HeraldTranscriptListController.php @@ -2,8 +2,6 @@ final class HeraldTranscriptListController extends HeraldController { - private $queryKey; - public function buildSideNavView($for_app = false) { $user = $this->getRequest()->getUser(); @@ -32,13 +30,11 @@ final class HeraldTranscriptListController extends HeraldController { return $crumbs; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new HeraldTranscriptSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/herald/extension/HeraldCustomAction.php b/src/applications/herald/extension/HeraldCustomAction.php deleted file mode 100644 index 2701a8ae66..0000000000 --- a/src/applications/herald/extension/HeraldCustomAction.php +++ /dev/null @@ -1,20 +0,0 @@ -getGroupOrder(), $this->getGroupLabel()); - } - final public static function getAllFieldGroups() { return id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) diff --git a/src/applications/herald/group/HeraldGroup.php b/src/applications/herald/group/HeraldGroup.php new file mode 100644 index 0000000000..348ea1d24a --- /dev/null +++ b/src/applications/herald/group/HeraldGroup.php @@ -0,0 +1,15 @@ +getGroupOrder(), $this->getGroupLabel()); + } + +} diff --git a/src/applications/herald/query/HeraldRuleSearchEngine.php b/src/applications/herald/query/HeraldRuleSearchEngine.php index 63e6efc818..04b7a5d852 100644 --- a/src/applications/herald/query/HeraldRuleSearchEngine.php +++ b/src/applications/herald/query/HeraldRuleSearchEngine.php @@ -197,12 +197,6 @@ final class HeraldRuleSearchEngine extends PhabricatorApplicationSearchEngine { $item->addIcon('fa-lock grey', pht('Disabled')); } - $item->addAction( - id(new PHUIListItemView()) - ->setHref($this->getApplicationURI("history/{$id}/")) - ->setIcon('fa-file-text-o') - ->setName(pht('Edit Log'))); - $content_type_name = idx($content_type_map, $rule->getContentType()); $item->addAttribute(pht('Affects: %s', $content_type_name)); diff --git a/src/applications/legalpad/controller/LegalpadDocumentCommentController.php b/src/applications/legalpad/controller/LegalpadDocumentCommentController.php index f0f557d67f..530696437b 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentCommentController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentCommentController.php @@ -2,23 +2,17 @@ final class LegalpadDocumentCommentController extends LegalpadController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $document = id(new LegalpadDocumentQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needDocumentBodies(true) ->executeOne(); @@ -48,7 +42,7 @@ final class LegalpadDocumentCommentController extends LegalpadController { } $editor = id(new LegalpadDocumentEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect($request->isContinueRequest()) ->setIsPreview($is_preview); @@ -67,7 +61,7 @@ final class LegalpadDocumentCommentController extends LegalpadController { if ($request->isAjax() && $is_preview) { return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setIsPreview($is_preview); } else { diff --git a/src/applications/legalpad/controller/LegalpadDocumentDoneController.php b/src/applications/legalpad/controller/LegalpadDocumentDoneController.php index e6601ba072..b12e3f65ad 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentDoneController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentDoneController.php @@ -6,9 +6,8 @@ final class LegalpadDocumentDoneController extends LegalpadController { return true; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); return $this->newDialog() ->setTitle(pht('Verify Signature')) diff --git a/src/applications/legalpad/controller/LegalpadDocumentEditController.php b/src/applications/legalpad/controller/LegalpadDocumentEditController.php index 140a26a670..edbaaf99e2 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentEditController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentEditController.php @@ -3,25 +3,25 @@ final class LegalpadDocumentEditController extends LegalpadController { public function handleRequest(AphrontRequest $request) { - $user = $request->getUser(); - + $viewer = $request->getViewer(); $id = $request->getURIData('id'); + if (!$id) { $is_create = true; $this->requireApplicationCapability( LegalpadCreateDocumentsCapability::CAPABILITY); - $document = LegalpadDocument::initializeNewDocument($user); + $document = LegalpadDocument::initializeNewDocument($viewer); $body = id(new LegalpadDocumentBody()) - ->setCreatorPHID($user->getPHID()); + ->setCreatorPHID($viewer->getPHID()); $document->attachDocumentBody($body); $document->setDocumentBodyPHID(PhabricatorPHIDConstants::PHID_VOID); } else { $is_create = false; $document = id(new LegalpadDocumentQuery()) - ->setViewer($user) + ->setViewer($viewer) ->needDocumentBodies(true) ->requireCapabilities( array( @@ -94,7 +94,7 @@ final class LegalpadDocumentEditController extends LegalpadController { $v_require_signature = $request->getBool('requireSignature', 0); if ($v_require_signature) { - if (!$user->getIsAdmin()) { + if (!$viewer->getIsAdmin()) { $errors[] = pht('Only admins may require signature.'); } $individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL; @@ -104,7 +104,7 @@ final class LegalpadDocumentEditController extends LegalpadController { 'signing to use Phabricator.'); } } - if ($user->getIsAdmin()) { + if ($viewer->getIsAdmin()) { $xactions[] = id(new LegalpadTransaction()) ->setTransactionType(LegalpadTransaction::TYPE_REQUIRE_SIGNATURE) ->setNewValue($v_require_signature); @@ -114,7 +114,7 @@ final class LegalpadDocumentEditController extends LegalpadController { $editor = id(new LegalpadDocumentEditor()) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) - ->setActor($user); + ->setActor($viewer); $xactions = $editor->applyTransactions($document, $xactions); @@ -130,7 +130,7 @@ final class LegalpadDocumentEditController extends LegalpadController { } $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormTextControl()) ->setID('document-title') @@ -162,7 +162,7 @@ final class LegalpadDocumentEditController extends LegalpadController { $form ->appendChild( id(new AphrontFormCheckboxControl()) - ->setDisabled(!$user->getIsAdmin()) + ->setDisabled(!$viewer->getIsAdmin()) ->setLabel(pht('Require Signature')) ->addCheckbox( 'requireSignature', @@ -175,7 +175,7 @@ final class LegalpadDocumentEditController extends LegalpadController { $form ->appendChild( id(new PhabricatorRemarkupControl()) - ->setUser($user) + ->setUser($viewer) ->setID('preamble') ->setLabel(pht('Preamble')) ->setValue($v_preamble) @@ -184,7 +184,7 @@ final class LegalpadDocumentEditController extends LegalpadController { pht('Optional help text for users signing this document.'))) ->appendChild( id(new PhabricatorRemarkupControl()) - ->setUser($user) + ->setUser($viewer) ->setID('document-text') ->setLabel(pht('Document Body')) ->setError($e_text) @@ -193,21 +193,21 @@ final class LegalpadDocumentEditController extends LegalpadController { ->setName('text')); $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) + ->setViewer($viewer) ->setObject($document) ->execute(); $form ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicyObject($document) ->setPolicies($policies) ->setName('can_view')) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicyObject($document) ->setPolicies($policies) diff --git a/src/applications/legalpad/controller/LegalpadDocumentListController.php b/src/applications/legalpad/controller/LegalpadDocumentListController.php index 3229107658..cbd92f87a9 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentListController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentListController.php @@ -2,19 +2,15 @@ final class LegalpadDocumentListController extends LegalpadController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new LegalpadDocumentSearchEngine()) ->setNavigation($this->buildSideNav()); diff --git a/src/applications/legalpad/controller/LegalpadDocumentManageController.php b/src/applications/legalpad/controller/LegalpadDocumentManageController.php index f24c0d03ce..9fc773258f 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentManageController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentManageController.php @@ -2,21 +2,15 @@ final class LegalpadDocumentManageController extends LegalpadController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); // NOTE: We require CAN_EDIT to view this page. $document = id(new LegalpadDocumentQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needDocumentBodies(true) ->needContributors(true) ->requireCapabilities( @@ -35,7 +29,7 @@ final class LegalpadDocumentManageController extends LegalpadController { $document_body = $document->getDocumentBody(); $engine = id(new PhabricatorMarkupEngine()) - ->setViewer($user); + ->setViewer($viewer); $engine->addObject( $document_body, LegalpadDocumentBody::MARKUP_FIELD_TEXT); @@ -48,7 +42,7 @@ final class LegalpadDocumentManageController extends LegalpadController { $header = id(new PHUIHeaderView()) ->setHeader($title) - ->setUser($user) + ->setUser($viewer) ->setPolicyObject($document); $actions = $this->buildActionView($document); @@ -99,15 +93,15 @@ final class LegalpadDocumentManageController extends LegalpadController { } private function buildActionView(LegalpadDocument $document) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $actions = id(new PhabricatorActionListView()) - ->setUser($user) + ->setUser($viewer) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($document); $can_edit = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, $document, PhabricatorPolicyCapability::CAN_EDIT); @@ -141,10 +135,10 @@ final class LegalpadDocumentManageController extends LegalpadController { PhabricatorMarkupEngine $engine, PhabricatorActionListView $actions) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) - ->setUser($user) + ->setUser($viewer) ->setObject($document) ->setActionList($actions); @@ -154,11 +148,11 @@ final class LegalpadDocumentManageController extends LegalpadController { $properties->addProperty( pht('Last Updated'), - phabricator_datetime($document->getDateModified(), $user)); + phabricator_datetime($document->getDateModified(), $viewer)); $properties->addProperty( pht('Updated By'), - $user->renderHandle($document->getDocumentBody()->getCreatorPHID())); + $viewer->renderHandle($document->getDocumentBody()->getCreatorPHID())); $properties->addProperty( pht('Versions'), @@ -167,7 +161,7 @@ final class LegalpadDocumentManageController extends LegalpadController { if ($document->getContributors()) { $properties->addProperty( pht('Contributors'), - $user + $viewer ->renderHandleList($document->getContributors()) ->setAsInline(true)); } @@ -180,9 +174,9 @@ final class LegalpadDocumentManageController extends LegalpadController { private function buildAddCommentView( LegalpadDocument $document, $comment_form_id) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); - $draft = PhabricatorDraft::newFromUserAndKey($user, $document->getPHID()); + $draft = PhabricatorDraft::newFromUserAndKey($viewer, $document->getPHID()); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); @@ -191,7 +185,7 @@ final class LegalpadDocumentManageController extends LegalpadController { : pht('Debate Legislation'); $form = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($user) + ->setUser($viewer) ->setObjectPHID($document->getPHID()) ->setFormID($comment_form_id) ->setHeaderText($title) diff --git a/src/applications/legalpad/controller/LegalpadDocumentSignatureListController.php b/src/applications/legalpad/controller/LegalpadDocumentSignatureListController.php index 945ad2dc39..5330049aae 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentSignatureListController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentSignatureListController.php @@ -2,23 +2,17 @@ final class LegalpadDocumentSignatureListController extends LegalpadController { - private $documentID; - private $queryKey; private $document; - public function willProcessRequest(array $data) { - $this->documentID = idx($data, 'id'); - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - if ($this->documentID) { + if ($id) { $document = id(new LegalpadDocumentQuery()) - ->setViewer($user) - ->withIDs(array($this->documentID)) + ->setViewer($viewer) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -39,7 +33,7 @@ final class LegalpadDocumentSignatureListController extends LegalpadController { } $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine($engine) ->setNavigation($this->buildSideNav()); @@ -47,13 +41,13 @@ final class LegalpadDocumentSignatureListController extends LegalpadController { } public function buildSideNav($for_app = false) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); $engine = id(new LegalpadDocumentSignatureSearchEngine()) - ->setViewer($user); + ->setViewer($viewer); if ($this->document) { $engine->setDocument($this->document); diff --git a/src/applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php b/src/applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php index a940eb646f..b50b91e896 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php @@ -3,25 +3,19 @@ final class LegalpadDocumentSignatureVerificationController extends LegalpadController { - private $code; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->code = $data['code']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $code = $request->getURIData('code'); // NOTE: We're using the omnipotent user to handle logged-out signatures // and corporate signatures. $signature = id(new LegalpadDocumentSignatureQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withSecretKeys(array($this->code)) + ->withSecretKeys(array($code)) ->executeOne(); if (!$signature) { diff --git a/src/applications/legalpad/controller/LegalpadDocumentSignatureViewController.php b/src/applications/legalpad/controller/LegalpadDocumentSignatureViewController.php index 6d58d1b693..6f2c447b71 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentSignatureViewController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentSignatureViewController.php @@ -2,19 +2,13 @@ final class LegalpadDocumentSignatureViewController extends LegalpadController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $signature = id(new LegalpadDocumentSignatureQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$signature) { return new Aphront404Response(); diff --git a/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php b/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php new file mode 100644 index 0000000000..22d41449ad --- /dev/null +++ b/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php @@ -0,0 +1,133 @@ +getAdapter(); + + $edgetype_legal = LegalpadObjectNeedsSignatureEdgeType::EDGECONST; + $current = $adapter->loadEdgePHIDs($edgetype_legal); + + $allowed_types = array( + PhabricatorLegalpadDocumentPHIDType::TYPECONST, + ); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + $object = $adapter->getObject(); + $author_phid = $object->getAuthorPHID(); + + $signatures = id(new LegalpadDocumentSignatureQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withDocumentPHIDs($phids) + ->withSignerPHIDs(array($author_phid)) + ->execute(); + $signatures = mpull($signatures, null, 'getDocumentPHID'); + + $signed = array(); + foreach ($phids as $phid) { + if (isset($signatures[$phid])) { + $signed[] = $phid; + unset($phids[$phid]); + } + } + + if ($signed) { + $this->logEffect(self::DO_SIGNED, $phids); + } + + if (!$phids) { + return; + } + + $xaction = $adapter->newTransaction() + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $edgetype_legal) + ->setNewValue( + array( + '+' => $phids, + )); + + $adapter->queueTransaction($xaction); + + $this->logEffect(self::DO_REQUIRED, $phids); + } + + protected function getActionEffectMap() { + return array( + self::DO_SIGNED => array( + 'icon' => 'fa-terminal', + 'color' => 'green', + 'name' => pht('Already Signed'), + ), + self::DO_REQUIRED => array( + 'icon' => 'fa-terminal', + 'color' => 'green', + 'name' => pht('Required Signature'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_SIGNED: + return pht( + '%s document(s) are already signed: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_REQUIRED: + return pht( + 'Required %s signature(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + + public function getHeraldActionName() { + return pht('Require signatures'); + } + + public function supportsRuleType($rule_type) { + return ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL); + } + + public function applyEffect($object, HeraldEffect $effect) { + return $this->applyRequire($effect->getTarget()); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new LegalpadDocumentDatasource(); + } + + public function renderActionDescription($value) { + return pht( + 'Require document signatures: %s.', + $this->renderHandleList($value)); + } +} diff --git a/src/applications/macro/controller/PhabricatorMacroAudioController.php b/src/applications/macro/controller/PhabricatorMacroAudioController.php index e46b7c78e8..92b98e5564 100644 --- a/src/applications/macro/controller/PhabricatorMacroAudioController.php +++ b/src/applications/macro/controller/PhabricatorMacroAudioController.php @@ -2,26 +2,20 @@ final class PhabricatorMacroAudioController extends PhabricatorMacroController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { $this->requireApplicationCapability( PhabricatorMacroManageCapability::CAPABILITY); - $request = $this->getRequest(); - $viewer = $request->getUser(); - $macro = id(new PhabricatorMacroQuery()) ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, )) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$macro) { diff --git a/src/applications/macro/controller/PhabricatorMacroCommentController.php b/src/applications/macro/controller/PhabricatorMacroCommentController.php index f438e9b31a..f038140be1 100644 --- a/src/applications/macro/controller/PhabricatorMacroCommentController.php +++ b/src/applications/macro/controller/PhabricatorMacroCommentController.php @@ -3,23 +3,17 @@ final class PhabricatorMacroCommentController extends PhabricatorMacroController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $macro = id(new PhabricatorMacroQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$macro) { return new Aphront404Response(); @@ -38,7 +32,7 @@ final class PhabricatorMacroCommentController ->setContent($request->getStr('comment'))); $editor = id(new PhabricatorMacroEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect($request->isContinueRequest()) ->setContentSourceFromRequest($request) ->setIsPreview($is_preview); @@ -57,7 +51,7 @@ final class PhabricatorMacroCommentController if ($request->isAjax() && $is_preview) { return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setIsPreview($is_preview); } else { diff --git a/src/applications/macro/controller/PhabricatorMacroDisableController.php b/src/applications/macro/controller/PhabricatorMacroDisableController.php index 0804e119e5..a9868647f0 100644 --- a/src/applications/macro/controller/PhabricatorMacroDisableController.php +++ b/src/applications/macro/controller/PhabricatorMacroDisableController.php @@ -3,28 +3,22 @@ final class PhabricatorMacroDisableController extends PhabricatorMacroController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { $this->requireApplicationCapability( PhabricatorMacroManageCapability::CAPABILITY); - $request = $this->getRequest(); - $user = $request->getUser(); - $macro = id(new PhabricatorMacroQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$macro) { return new Aphront404Response(); } - $view_uri = $this->getApplicationURI('/view/'.$this->id.'/'); + $view_uri = $this->getApplicationURI('/view/'.$id.'/'); if ($request->isDialogFormPost() || $macro->getIsDisabled()) { $xaction = id(new PhabricatorMacroTransaction()) @@ -32,7 +26,7 @@ final class PhabricatorMacroDisableController ->setNewValue($macro->getIsDisabled() ? 0 : 1); $editor = id(new PhabricatorMacroEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request); $xactions = $editor->applyTransactions($macro, array($xaction)); @@ -52,7 +46,7 @@ final class PhabricatorMacroDisableController 'Really disable the much-beloved image macro %s? '. 'It will be sorely missed.', $macro->getName()))) - ->setSubmitURI($this->getApplicationURI('/disable/'.$this->id.'/')) + ->setSubmitURI($this->getApplicationURI('/disable/'.$id.'/')) ->addSubmitButton(pht('Disable')) ->addCancelButton($view_uri); diff --git a/src/applications/macro/controller/PhabricatorMacroEditController.php b/src/applications/macro/controller/PhabricatorMacroEditController.php index f15e5364c2..9e988ef637 100644 --- a/src/applications/macro/controller/PhabricatorMacroEditController.php +++ b/src/applications/macro/controller/PhabricatorMacroEditController.php @@ -2,23 +2,17 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { $this->requireApplicationCapability( PhabricatorMacroManageCapability::CAPABILITY); - $request = $this->getRequest(); - $user = $request->getUser(); - - if ($this->id) { + if ($id) { $macro = id(new PhabricatorMacroQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needFiles(true) ->executeOne(); if (!$macro) { @@ -26,7 +20,7 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { } } else { $macro = new PhabricatorFileImageMacro(); - $macro->setAuthorPHID($user->getPHID()); + $macro->setAuthorPHID($viewer->getPHID()); } $errors = array(); @@ -66,7 +60,7 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { $_FILES['file'], array( 'name' => $request->getStr('name'), - 'authorPHID' => $user->getPHID(), + 'authorPHID' => $viewer->getPHID(), 'isExplicitUpload' => true, 'canCDN' => true, )); @@ -75,7 +69,7 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { // Rate limit outbound fetches to make this mechanism less useful for // scanning networks and ports. PhabricatorSystemActionEngine::willTakeAction( - array($user->getPHID()), + array($viewer->getPHID()), new PhabricatorFilesOutboundRequestAction(), 1); @@ -101,7 +95,7 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { $mime_type)); } else { $file - ->setAuthorPHID($user->getPHID()) + ->setAuthorPHID($viewer->getPHID()) ->save(); } } catch (HTTPFutureHTTPResponseStatus $status) { @@ -114,7 +108,7 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { } } else if ($request->getStr('phid')) { $file = id(new PhabricatorFileQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($request->getStr('phid'))) ->executeOne(); } @@ -152,7 +146,7 @@ final class PhabricatorMacroEditController extends PhabricatorMacroController { } $editor = id(new PhabricatorMacroEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request); diff --git a/src/applications/macro/controller/PhabricatorMacroListController.php b/src/applications/macro/controller/PhabricatorMacroListController.php index 730f8de3b1..3847117275 100644 --- a/src/applications/macro/controller/PhabricatorMacroListController.php +++ b/src/applications/macro/controller/PhabricatorMacroListController.php @@ -2,19 +2,15 @@ final class PhabricatorMacroListController extends PhabricatorMacroController { - private $key; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->key = idx($data, 'key'); - } + public function handleRequest(AphrontRequest $request) { + $key = $request->getURIData('key'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->key) + ->setQueryKey($key) ->setSearchEngine(new PhabricatorMacroSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/macro/controller/PhabricatorMacroMemeController.php b/src/applications/macro/controller/PhabricatorMacroMemeController.php index ff25a8a8a4..03b13f6205 100644 --- a/src/applications/macro/controller/PhabricatorMacroMemeController.php +++ b/src/applications/macro/controller/PhabricatorMacroMemeController.php @@ -7,14 +7,13 @@ final class PhabricatorMacroMemeController return true; } - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { $macro_name = $request->getStr('macro'); $upper_text = $request->getStr('uppertext'); $lower_text = $request->getStr('lowertext'); - $user = $request->getUser(); + $viewer = $request->getViewer(); - $uri = self::generateMacro($user, $macro_name, + $uri = self::generateMacro($viewer, $macro_name, $upper_text, $lower_text); if ($uri === false) { return new Aphront404Response(); @@ -24,10 +23,10 @@ final class PhabricatorMacroMemeController ->setURI($uri); } - public static function generateMacro($user, $macro_name, $upper_text, + public static function generateMacro($viewer, $macro_name, $upper_text, $lower_text) { $macro = id(new PhabricatorMacroQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withNames(array($macro_name)) ->needFiles(true) ->executeOne(); @@ -46,7 +45,7 @@ final class PhabricatorMacroMemeController if ($xform) { $memefile = id(new PhabricatorFileQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($xform->getTransformedPHID())) ->executeOne(); if ($memefile) { diff --git a/src/applications/macro/controller/PhabricatorMacroMemeDialogController.php b/src/applications/macro/controller/PhabricatorMacroMemeDialogController.php index 25a223f5ac..5851cc5ad8 100644 --- a/src/applications/macro/controller/PhabricatorMacroMemeDialogController.php +++ b/src/applications/macro/controller/PhabricatorMacroMemeDialogController.php @@ -3,9 +3,8 @@ final class PhabricatorMacroMemeDialogController extends PhabricatorMacroController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $phid = head($request->getArr('macro')); $above = $request->getStr('above'); @@ -19,7 +18,7 @@ final class PhabricatorMacroMemeDialogController $errors[] = pht('Macro name is required.'); } else { $macro = id(new PhabricatorMacroQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); if (!$macro) { @@ -45,7 +44,7 @@ final class PhabricatorMacroMemeDialogController } $view = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendControl( id(new AphrontFormTokenizerControl()) ->setLabel(pht('Macro')) @@ -65,7 +64,7 @@ final class PhabricatorMacroMemeDialogController ->setValue($below)); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Create Meme')) ->appendForm($view) ->addCancelButton('/') diff --git a/src/applications/macro/controller/PhabricatorMacroViewController.php b/src/applications/macro/controller/PhabricatorMacroViewController.php index a031c7f92b..8915954fc4 100644 --- a/src/applications/macro/controller/PhabricatorMacroViewController.php +++ b/src/applications/macro/controller/PhabricatorMacroViewController.php @@ -3,23 +3,17 @@ final class PhabricatorMacroViewController extends PhabricatorMacroController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - public function shouldAllowPublic() { return true; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $macro = id(new PhabricatorMacroQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needFiles(true) ->executeOne(); if (!$macro) { @@ -55,7 +49,7 @@ final class PhabricatorMacroViewController new PhabricatorMacroTransactionQuery()); $header = id(new PHUIHeaderView()) - ->setUser($user) + ->setUser($viewer) ->setPolicyObject($macro) ->setHeader($title_long); @@ -71,10 +65,10 @@ final class PhabricatorMacroViewController ? pht('Add Comment') : pht('Grovel in Awe'); - $draft = PhabricatorDraft::newFromUserAndKey($user, $macro->getPHID()); + $draft = PhabricatorDraft::newFromUserAndKey($viewer, $macro->getPHID()); $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($user) + ->setUser($viewer) ->setObjectPHID($macro->getPHID()) ->setDraft($draft) ->setHeaderText($comment_header) diff --git a/src/applications/macro/storage/PhabricatorFileImageMacro.php b/src/applications/macro/storage/PhabricatorFileImageMacro.php index 0d68bf0c1b..72a6577924 100644 --- a/src/applications/macro/storage/PhabricatorFileImageMacro.php +++ b/src/applications/macro/storage/PhabricatorFileImageMacro.php @@ -5,6 +5,7 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO PhabricatorSubscribableInterface, PhabricatorApplicationTransactionInterface, PhabricatorFlaggableInterface, + PhabricatorTokenReceiverInterface, PhabricatorPolicyInterface { protected $authorPHID; @@ -119,6 +120,16 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO } +/* -( PhabricatorTokenRecevierInterface )---------------------------------- */ + + + public function getUsersToNotifyOfTokenGiven() { + return array( + $this->getAuthorPHID(), + ); + } + + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php b/src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php index ad659af259..d4adee9570 100644 --- a/src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php +++ b/src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php @@ -38,7 +38,7 @@ final class ManiphestUpdateConduitAPIMethod extends ManiphestConduitAPIMethod { 'phid')); } - $query = id (new ManiphestTaskQuery()) + $query = id(new ManiphestTaskQuery()) ->setViewer($request->getUser()) ->needSubscriberPHIDs(true) ->needProjectPHIDs(true); diff --git a/src/applications/maniphest/controller/ManiphestExportController.php b/src/applications/maniphest/controller/ManiphestExportController.php index 6db04a6e32..88e6849afb 100644 --- a/src/applications/maniphest/controller/ManiphestExportController.php +++ b/src/applications/maniphest/controller/ManiphestExportController.php @@ -2,27 +2,19 @@ final class ManiphestExportController extends ManiphestController { - private $key; - - public function willProcessRequest(array $data) { - $this->key = $data['key']; - return $this; - } - /** * @phutil-external-symbol class PHPExcel * @phutil-external-symbol class PHPExcel_IOFactory * @phutil-external-symbol class PHPExcel_Style_NumberFormat * @phutil-external-symbol class PHPExcel_Cell_DataType */ - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $key = $request->getURIData('key'); $ok = @include_once 'PHPExcel.php'; if (!$ok) { - $dialog = new AphrontDialogView(); - $dialog->setUser($user); + $dialog = $this->newDialog(); $inst1 = pht( 'This system does not have PHPExcel installed. This software '. @@ -54,14 +46,14 @@ final class ManiphestExportController extends ManiphestController { // for that here, since it fatals if we don't have the ZipArchive class. $saved = id(new PhabricatorSavedQueryQuery()) - ->setViewer($user) - ->withQueryKeys(array($this->key)) + ->setViewer($viewer) + ->withQueryKeys(array($key)) ->executeOne(); if (!$saved) { $engine = id(new ManiphestTaskSearchEngine()) - ->setViewer($user); - if ($engine->isBuiltinQuery($this->key)) { - $saved = $engine->buildSavedQueryFromBuiltin($this->key); + ->setViewer($viewer); + if ($engine->isBuiltinQuery($key)) { + $saved = $engine->buildSavedQueryFromBuiltin($key); } if (!$saved) { return new Aphront404Response(); @@ -76,7 +68,7 @@ final class ManiphestExportController extends ManiphestController { if (!$request->isDialogFormPost()) { $dialog = new AphrontDialogView(); - $dialog->setUser($user); + $dialog->setUser($viewer); $dialog->setTitle(pht('Export Tasks to Excel')); $dialog->appendChild( @@ -108,22 +100,22 @@ final class ManiphestExportController extends ManiphestController { $saved->setParameter('limit', PHP_INT_MAX); $engine = id(new ManiphestTaskSearchEngine()) - ->setViewer($user); + ->setViewer($viewer); $query = $engine->buildQueryFromSavedQuery($saved); - $query->setViewer($user); + $query->setViewer($viewer); $tasks = $query->execute(); $all_projects = array_mergev(mpull($tasks, 'getProjectPHIDs')); $all_assigned = mpull($tasks, 'getOwnerPHID'); $handles = id(new PhabricatorHandleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array_merge($all_projects, $all_assigned)) ->execute(); $workbook = new PHPExcel(); - $format->buildWorkbook($workbook, $tasks, $handles, $user); + $format->buildWorkbook($workbook, $tasks, $handles, $viewer); $writer = PHPExcel_IOFactory::createWriter($workbook, 'Excel2007'); ob_start(); diff --git a/src/applications/maniphest/controller/ManiphestReportController.php b/src/applications/maniphest/controller/ManiphestReportController.php index bdf446150e..6c2ce9fec3 100644 --- a/src/applications/maniphest/controller/ManiphestReportController.php +++ b/src/applications/maniphest/controller/ManiphestReportController.php @@ -4,13 +4,9 @@ final class ManiphestReportController extends ManiphestController { private $view; - public function willProcessRequest(array $data) { - $this->view = idx($data, 'view'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $this->view = $request->getURIData('view'); if ($request->isFormPost()) { $uri = $request->getRequestURI(); @@ -64,7 +60,7 @@ final class ManiphestReportController extends ManiphestController { public function renderBurn() { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $handle = null; @@ -132,7 +128,7 @@ final class ManiphestReportController extends ManiphestController { $day_bucket = phabricator_format_local_time( $row['dateCreated'], - $user, + $viewer, 'Yz'); $day_buckets[$day_bucket] = $row['dateCreated']; if (empty($stats[$day_bucket])) { @@ -166,12 +162,12 @@ final class ManiphestReportController extends ManiphestController { $week_bucket = phabricator_format_local_time( $epoch, - $user, + $viewer, 'YW'); if ($week_bucket != $last_week) { if ($week) { $rows[] = $this->formatBurnRow( - pht('Week of %s', phabricator_date($last_week_epoch, $user)), + pht('Week of %s', phabricator_date($last_week_epoch, $viewer)), $week); $rowc[] = 'week'; } @@ -182,12 +178,12 @@ final class ManiphestReportController extends ManiphestController { $month_bucket = phabricator_format_local_time( $epoch, - $user, + $viewer, 'Ym'); if ($month_bucket != $last_month) { if ($month) { $rows[] = $this->formatBurnRow( - phabricator_format_local_time($last_month_epoch, $user, 'F, Y'), + phabricator_format_local_time($last_month_epoch, $viewer, 'F, Y'), $month); $rowc[] = 'month'; } @@ -196,7 +192,7 @@ final class ManiphestReportController extends ManiphestController { $last_month_epoch = $epoch; } - $rows[] = $this->formatBurnRow(phabricator_date($epoch, $user), $info); + $rows[] = $this->formatBurnRow(phabricator_date($epoch, $viewer), $info); $rowc[] = null; $week['open'] += $info['open']; $week['close'] += $info['close']; @@ -315,10 +311,10 @@ final class ManiphestReportController extends ManiphestController { private function renderReportFilters(array $tokens, $has_window) { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorProjectDatasource()) @@ -390,11 +386,11 @@ final class ManiphestReportController extends ManiphestController { public function renderOpenTasks() { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $query = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withStatuses(ManiphestTaskStatus::getOpenStatusConstants()); switch ($this->view) { @@ -420,7 +416,7 @@ final class ManiphestReportController extends ManiphestController { $recently_closed = $this->loadRecentlyClosedTasks(); - $date = phabricator_date(time(), $user); + $date = phabricator_date(time(), $viewer); switch ($this->view) { case 'user': @@ -615,7 +611,7 @@ final class ManiphestReportController extends ManiphestController { $cclass[] = 'n'; list($ignored, $window_epoch) = $this->getWindow(); - $edate = phabricator_datetime($window_epoch, $user); + $edate = phabricator_datetime($window_epoch, $viewer); $cname[] = javelin_tag( 'span', array( @@ -726,7 +722,7 @@ final class ManiphestReportController extends ManiphestController { */ private function getWindow() { $request = $this->getRequest(); - $user = $request->getUser(); + $viewer = $request->getUser(); $window_str = $this->getRequest()->getStr('window', '12 AM 7 days ago'); @@ -736,7 +732,7 @@ final class ManiphestReportController extends ManiphestController { // Do locale-aware parsing so that the user's timezone is assumed for // time windows like "3 PM", rather than assuming the server timezone. - $window_epoch = PhabricatorTime::parseLocalTime($window_str, $user); + $window_epoch = PhabricatorTime::parseLocalTime($window_str, $viewer); if (!$window_epoch) { $error = 'Invalid'; $window_epoch = time() - (60 * 60 * 24 * 7); diff --git a/src/applications/maniphest/controller/ManiphestSubpriorityController.php b/src/applications/maniphest/controller/ManiphestSubpriorityController.php index 44b13955fb..25920212c8 100644 --- a/src/applications/maniphest/controller/ManiphestSubpriorityController.php +++ b/src/applications/maniphest/controller/ManiphestSubpriorityController.php @@ -2,16 +2,15 @@ final class ManiphestSubpriorityController extends ManiphestController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); if (!$request->validateCSRF()) { return new Aphront403Response(); } $task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getInt('task'))) ->needProjectPHIDs(true) ->requireCapabilities( @@ -26,7 +25,7 @@ final class ManiphestSubpriorityController extends ManiphestController { if ($request->getInt('after')) { $after_task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getInt('after'))) ->executeOne(); if (!$after_task) { @@ -52,7 +51,7 @@ final class ManiphestSubpriorityController extends ManiphestController { ->setNewValue($sub); $editor = id(new ManiphestTransactionEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request); diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php index 0d4fa74398..8619987201 100644 --- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php +++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php @@ -2,27 +2,21 @@ final class ManiphestTaskDetailController extends ManiphestController { - private $id; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); $e_title = null; $priority_map = ManiphestTaskPriority::getTaskPriorityMap(); $task = id(new ManiphestTaskQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needSubscriberPHIDs(true) ->executeOne(); if (!$task) { @@ -33,7 +27,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $parent_task = null; if ($workflow && is_numeric($workflow)) { $parent_task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($workflow)) ->executeOne(); } @@ -42,7 +36,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $task, PhabricatorCustomField::ROLE_VIEW); $field_list - ->setViewer($user) + ->setViewer($viewer) ->readFieldsFromStorage($task); $e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST; @@ -83,7 +77,7 @@ final class ManiphestTaskDetailController extends ManiphestController { } $phids = array_keys($phids); - $handles = $user->loadHandles($phids); + $handles = $viewer->loadHandles($phids); $info_view = null; if ($parent_task) { @@ -115,7 +109,7 @@ final class ManiphestTaskDetailController extends ManiphestController { } $engine = new PhabricatorMarkupEngine(); - $engine->setViewer($user); + $engine->setViewer($viewer); $engine->setContextObject($task); $engine->addObject($task, ManiphestTask::MARKUP_FIELD_DESCRIPTION); @@ -169,12 +163,13 @@ final class ManiphestTaskDetailController extends ManiphestController { } $default_claim = array( - $user->getPHID() => $user->getUsername().' ('.$user->getRealName().')', + $viewer->getPHID() => $viewer->getUsername(). + ' ('.$viewer->getRealName().')', ); $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', - $user->getPHID(), + $viewer->getPHID(), $task->getPHID()); if ($draft) { $draft_text = $draft->getDraft(); @@ -188,7 +183,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $comment_form = new AphrontFormView(); $comment_form - ->setUser($user) + ->setUser($viewer) ->setWorkflow(true) ->setAction('/maniphest/transaction/save/') ->setEncType('multipart/form-data') @@ -249,12 +244,12 @@ final class ManiphestTaskDetailController extends ManiphestController { ->setControlStyle('display: none')) ->appendChild( id(new PhabricatorRemarkupControl()) - ->setUser($user) + ->setUser($viewer) ->setLabel(pht('Comments')) ->setName('comments') ->setValue($draft_text) ->setID('transaction-comments') - ->setUser($user)) + ->setUser($viewer)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Submit'))); @@ -288,7 +283,7 @@ final class ManiphestTaskDetailController extends ManiphestController { ); // TODO: Initializing these behaviors for logged out users fatals things. - if ($user->isLoggedIn()) { + if ($viewer->isLoggedIn()) { Javelin::initBehavior('maniphest-transaction-controls', array( 'select' => 'transaction-action', 'controlMap' => $control_map, @@ -330,11 +325,11 @@ final class ManiphestTaskDetailController extends ManiphestController { $task, $field_list, $edges, $actions, $handles); $description = $this->buildDescriptionView($task, $engine); - if (!$user->isLoggedIn()) { + if (!$viewer->isLoggedIn()) { // TODO: Eventually, everything should run through this. For now, we're // only using it to get a consistent "Login to Comment" button. $comment_box = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($user) + ->setUser($viewer) ->setRequestURI($request->getRequestURI()); $preview_panel = null; } else { diff --git a/src/applications/maniphest/controller/ManiphestTaskEditController.php b/src/applications/maniphest/controller/ManiphestTaskEditController.php index 72b75c876f..703bb61768 100644 --- a/src/applications/maniphest/controller/ManiphestTaskEditController.php +++ b/src/applications/maniphest/controller/ManiphestTaskEditController.php @@ -2,15 +2,9 @@ final class ManiphestTaskEditController extends ManiphestController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); $response_type = $request->getStr('responseType', 'task'); $order = $request->getStr('order', PhabricatorProjectColumn::DEFAULT_ORDER); @@ -26,22 +20,22 @@ final class ManiphestTaskEditController extends ManiphestController { $can_edit_status = $this->hasApplicationCapability( ManiphestEditStatusCapability::CAPABILITY); $can_create_projects = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, PhabricatorApplication::getByClass('PhabricatorProjectApplication'), ProjectCreateProjectsCapability::CAPABILITY); $parent_task = null; $template_id = null; - if ($this->id) { + if ($id) { $task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needSubscriberPHIDs(true) ->needProjectPHIDs(true) ->executeOne(); @@ -49,7 +43,7 @@ final class ManiphestTaskEditController extends ManiphestController { return new Aphront404Response(); } } else { - $task = ManiphestTask::initializeNewTask($user); + $task = ManiphestTask::initializeNewTask($viewer); // We currently do not allow you to set the task status when creating // a new task, although now that statuses are custom it might make @@ -82,7 +76,7 @@ final class ManiphestTaskEditController extends ManiphestController { } $default_projects = id(new PhabricatorObjectQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withNames($tokens) ->execute(); $default_projects = mpull($default_projects, 'getPHID'); @@ -109,12 +103,12 @@ final class ManiphestTaskEditController extends ManiphestController { $assign = $request->getStr('assign'); if (strlen($assign)) { $assign_user = id(new PhabricatorPeopleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withUsernames(array($assign)) ->executeOne(); if (!$assign_user) { $assign_user = id(new PhabricatorPeopleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($assign)) ->executeOne(); } @@ -132,7 +126,7 @@ final class ManiphestTaskEditController extends ManiphestController { $parent_id = $request->getInt('parent'); if (strlen($parent_id)) { $parent_task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($parent_id)) ->executeOne(); if (!$parent_task) { @@ -150,7 +144,7 @@ final class ManiphestTaskEditController extends ManiphestController { $field_list = PhabricatorCustomField::getObjectFields( $task, PhabricatorCustomField::ROLE_EDIT); - $field_list->setViewer($user); + $field_list->setViewer($viewer); $field_list->readFieldsFromStorage($task); $aux_fields = $field_list->getFields(); @@ -250,7 +244,7 @@ final class ManiphestTaskEditController extends ManiphestController { // allow for putting a task in a project column at creation -only- if (!$task->getID() && $column_phid && $projects) { $column = id(new PhabricatorProjectColumnQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withProjectPHIDs($projects) ->withPHIDs(array($column_phid)) ->executeOne(); @@ -329,7 +323,7 @@ final class ManiphestTaskEditController extends ManiphestController { 'new' => $is_new, 'transactions' => $transactions, )); - $event->setUser($user); + $event->setUser($viewer); $event->setAphrontRequest($request); PhutilEventEngine::dispatchEvent($event); @@ -337,7 +331,7 @@ final class ManiphestTaskEditController extends ManiphestController { $transactions = $event->getValue('transactions'); $editor = id(new ManiphestTransactionEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->applyTransactions($task, $transactions); @@ -349,7 +343,7 @@ final class ManiphestTaskEditController extends ManiphestController { 'new' => $is_new, 'transactions' => $transactions, )); - $event->setUser($user); + $event->setUser($viewer); $event->setAphrontRequest($request); PhutilEventEngine::dispatchEvent($event); } @@ -372,19 +366,19 @@ final class ManiphestTaskEditController extends ManiphestController { $owner = null; if ($task->getOwnerPHID()) { $owner = id(new PhabricatorHandleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($task->getOwnerPHID())) ->executeOne(); } $tasks = id(new ProjectBoardTaskCard()) - ->setViewer($user) + ->setViewer($viewer) ->setTask($task) ->setOwner($owner) ->setCanEdit(true) ->getItem(); $column = id(new PhabricatorProjectColumnQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($request->getStr('columnPHID'))) ->executeOne(); if (!$column) { @@ -403,13 +397,13 @@ final class ManiphestTaskEditController extends ManiphestController { } $positions = id(new PhabricatorProjectColumnPositionQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withColumns(array($column)) ->execute(); $task_phids = mpull($positions, 'getObjectPHID'); $column_tasks = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs($task_phids) ->execute(); @@ -461,11 +455,11 @@ final class ManiphestTaskEditController extends ManiphestController { } else { if (!$task->getID()) { $task->attachSubscriberPHIDs(array( - $user->getPHID(), + $viewer->getPHID(), )); if ($template_id) { $template_task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($template_id)) ->needSubscriberPHIDs(true) ->needProjectPHIDs(true) @@ -473,7 +467,7 @@ final class ManiphestTaskEditController extends ManiphestController { if ($template_task) { $cc_phids = array_unique(array_merge( $template_task->getSubscriberPHIDs(), - array($user->getPHID()))); + array($viewer->getPHID()))); $task->attachSubscriberPHIDs($cc_phids); $task->attachProjectPHIDs($template_task->getProjectPHIDs()); $task->setOwnerPHID($template_task->getOwnerPHID()); @@ -499,7 +493,7 @@ final class ManiphestTaskEditController extends ManiphestController { if ($fields) { id(new PhabricatorCustomFieldList($fields)) - ->setViewer($user) + ->setViewer($viewer) ->readFieldsFromStorage($template_task); foreach ($fields as $key => $field) { @@ -563,7 +557,7 @@ final class ManiphestTaskEditController extends ManiphestController { $form = new AphrontFormView(); $form - ->setUser($user) + ->setUser($viewer) ->addHiddenInput('template', $template_id) ->addHiddenInput('responseType', $response_type) ->addHiddenInput('order', $order) @@ -575,7 +569,7 @@ final class ManiphestTaskEditController extends ManiphestController { ->appendChild( id(new AphrontFormStaticControl()) ->setLabel(pht('Parent Task')) - ->setValue($user->renderHandle($parent_task->getPHID()))) + ->setValue($viewer->renderHandle($parent_task->getPHID()))) ->addHiddenInput('parent', $parent_task->getID()); } @@ -607,7 +601,7 @@ final class ManiphestTaskEditController extends ManiphestController { } $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) + ->setViewer($viewer) ->setObject($task) ->execute(); @@ -617,7 +611,7 @@ final class ManiphestTaskEditController extends ManiphestController { ->setLabel(pht('Assigned To')) ->setName('assigned_to') ->setValue($assigned_value) - ->setUser($user) + ->setUser($viewer) ->setDatasource(new PhabricatorPeopleDatasource()) ->setLimit(1)); } @@ -628,7 +622,7 @@ final class ManiphestTaskEditController extends ManiphestController { ->setLabel(pht('CC')) ->setName('cc') ->setValue($cc_value) - ->setUser($user) + ->setUser($viewer) ->setDatasource(new PhabricatorMetaMTAMailableDatasource())); if ($can_edit_priority) { @@ -645,7 +639,7 @@ final class ManiphestTaskEditController extends ManiphestController { $form ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicyObject($task) ->setPolicies($policies) @@ -653,7 +647,7 @@ final class ManiphestTaskEditController extends ManiphestController { ->setName('viewPolicy')) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicyObject($task) ->setPolicies($policies) @@ -696,14 +690,14 @@ final class ManiphestTaskEditController extends ManiphestController { ->setName('description') ->setID('description-textarea') ->setValue($task->getDescription()) - ->setUser($user); + ->setUser($viewer); $form ->appendChild($description_control); if ($request->isAjax()) { $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setWidth(AphrontDialogView::WIDTH_FULL) ->setTitle($header_name) ->appendChild( diff --git a/src/applications/maniphest/controller/ManiphestTaskListController.php b/src/applications/maniphest/controller/ManiphestTaskListController.php index 9d2fa33716..ddb2827e83 100644 --- a/src/applications/maniphest/controller/ManiphestTaskListController.php +++ b/src/applications/maniphest/controller/ManiphestTaskListController.php @@ -3,19 +3,15 @@ final class ManiphestTaskListController extends ManiphestController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine( id(new ManiphestTaskSearchEngine()) ->setShowBatchControls(true)) diff --git a/src/applications/maniphest/controller/ManiphestTransactionPreviewController.php b/src/applications/maniphest/controller/ManiphestTransactionPreviewController.php index 0d7988cd64..65756ca8e4 100644 --- a/src/applications/maniphest/controller/ManiphestTransactionPreviewController.php +++ b/src/applications/maniphest/controller/ManiphestTransactionPreviewController.php @@ -2,29 +2,22 @@ final class ManiphestTransactionPreviewController extends ManiphestController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); $comments = $request->getStr('comments'); $task = id(new ManiphestTaskQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$task) { return new Aphront404Response(); } id(new PhabricatorDraft()) - ->setAuthorPHID($user->getPHID()) + ->setAuthorPHID($viewer->getPHID()) ->setDraftKey($task->getPHID()) ->setDraft($comments) ->replaceOrDelete(); @@ -32,7 +25,7 @@ final class ManiphestTransactionPreviewController extends ManiphestController { $action = $request->getStr('action'); $transaction = new ManiphestTransaction(); - $transaction->setAuthorPHID($user->getPHID()); + $transaction->setAuthorPHID($viewer->getPHID()); $transaction->setTransactionType($action); // This should really be split into a separate transaction, but it should @@ -104,7 +97,7 @@ final class ManiphestTransactionPreviewController extends ManiphestController { $transaction->setNewValue($value); break; } - $phids[] = $user->getPHID(); + $phids[] = $viewer->getPHID(); $handles = $this->loadViewerHandles($phids); @@ -112,7 +105,7 @@ final class ManiphestTransactionPreviewController extends ManiphestController { $transactions[] = $transaction; $engine = new PhabricatorMarkupEngine(); - $engine->setViewer($user); + $engine->setViewer($viewer); $engine->setContextObject($task); if ($transaction->hasComment()) { $engine->addObject( @@ -124,7 +117,7 @@ final class ManiphestTransactionPreviewController extends ManiphestController { $transaction->setHandles($handles); $view = id(new PhabricatorApplicationTransactionView()) - ->setUser($user) + ->setUser($viewer) ->setTransactions($transactions) ->setIsPreview(true); diff --git a/src/applications/maniphest/controller/ManiphestTransactionSaveController.php b/src/applications/maniphest/controller/ManiphestTransactionSaveController.php index f7693d9416..b060b18cab 100644 --- a/src/applications/maniphest/controller/ManiphestTransactionSaveController.php +++ b/src/applications/maniphest/controller/ManiphestTransactionSaveController.php @@ -2,12 +2,11 @@ final class ManiphestTransactionSaveController extends ManiphestController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); $task = id(new ManiphestTaskQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getStr('taskID'))) ->needSubscriberPHIDs(true) ->needProjectPHIDs(true) @@ -102,7 +101,7 @@ final class ManiphestTransactionSaveController extends ManiphestController { // this task. $assign = new ManiphestTransaction(); $assign->setTransactionType(ManiphestTransaction::TYPE_OWNER); - $assign->setNewValue($user->getPHID()); + $assign->setNewValue($viewer->getPHID()); $transactions[] = $assign; $implicitly_claimed = true; @@ -114,10 +113,10 @@ final class ManiphestTransactionSaveController extends ManiphestController { $user_owns_task = true; } else { if ($action == ManiphestTransaction::TYPE_OWNER) { - if ($transaction->getNewValue() == $user->getPHID()) { + if ($transaction->getNewValue() == $viewer->getPHID()) { $user_owns_task = true; } - } else if ($task->getOwnerPHID() == $user->getPHID()) { + } else if ($task->getOwnerPHID() == $viewer->getPHID()) { $user_owns_task = true; } } @@ -125,8 +124,8 @@ final class ManiphestTransactionSaveController extends ManiphestController { if (!$user_owns_task) { // If we aren't making the user the new task owner and they aren't the // existing task owner, add them to CC unless they're aleady CC'd. - if (!in_array($user->getPHID(), $task->getSubscriberPHIDs())) { - $implicit_ccs[] = $user->getPHID(); + if (!in_array($viewer->getPHID(), $task->getSubscriberPHIDs())) { + $implicit_ccs[] = $viewer->getPHID(); } } @@ -164,7 +163,7 @@ final class ManiphestTransactionSaveController extends ManiphestController { 'new' => false, 'transactions' => $transactions, )); - $event->setUser($user); + $event->setUser($viewer); $event->setAphrontRequest($request); PhutilEventEngine::dispatchEvent($event); @@ -172,7 +171,7 @@ final class ManiphestTransactionSaveController extends ManiphestController { $transactions = $event->getValue('transactions'); $editor = id(new ManiphestTransactionEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect($request->isContinueRequest()); @@ -187,7 +186,7 @@ final class ManiphestTransactionSaveController extends ManiphestController { $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', - $user->getPHID(), + $viewer->getPHID(), $task->getPHID()); if ($draft) { $draft->delete(); @@ -200,7 +199,7 @@ final class ManiphestTransactionSaveController extends ManiphestController { 'new' => false, 'transactions' => $transactions, )); - $event->setUser($user); + $event->setUser($viewer); $event->setAphrontRequest($request); PhutilEventEngine::dispatchEvent($event); diff --git a/src/applications/maniphest/editor/ManiphestTransactionEditor.php b/src/applications/maniphest/editor/ManiphestTransactionEditor.php index 39111644cb..dcc518e06b 100644 --- a/src/applications/maniphest/editor/ManiphestTransactionEditor.php +++ b/src/applications/maniphest/editor/ManiphestTransactionEditor.php @@ -506,23 +506,6 @@ final class ManiphestTransactionEditor ->setTask($object); } - protected function didApplyHeraldRules( - PhabricatorLiskDAO $object, - HeraldAdapter $adapter, - HeraldTranscript $transcript) { - - $xactions = array(); - - $assign_phid = $adapter->getAssignPHID(); - if ($assign_phid) { - $xactions[] = id(new ManiphestTransaction()) - ->setTransactionType(ManiphestTransaction::TYPE_OWNER) - ->setNewValue($assign_phid); - } - - return $xactions; - } - protected function requireCapabilities( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { diff --git a/src/applications/maniphest/event/ManiphestHovercardEventListener.php b/src/applications/maniphest/event/ManiphestHovercardEventListener.php index a33a854bc6..5615b78d04 100644 --- a/src/applications/maniphest/event/ManiphestHovercardEventListener.php +++ b/src/applications/maniphest/event/ManiphestHovercardEventListener.php @@ -53,12 +53,15 @@ final class ManiphestHovercardEventListener extends PhabricatorEventListener { $owner = phutil_tag('em', array(), pht('None')); } $hovercard->addField(pht('Assigned To'), $owner); + $hovercard->addField( + pht('Priority'), + ManiphestTaskPriority::getTaskPriorityName($task->getPriority())); if ($edge_phids) { $edge_types = array( $e_project => pht('Projects'), - $e_dep_by => pht('Dependent Tasks'), - $e_dep_on => pht('Depends On'), + $e_dep_by => pht('Blocks'), + $e_dep_on => pht('Blocked By'), ); $max_count = 6; diff --git a/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php b/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php index eade548740..d504a71214 100644 --- a/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php +++ b/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php @@ -3,7 +3,6 @@ final class HeraldManiphestTaskAdapter extends HeraldAdapter { private $task; - private $assignPHID; protected function newObject() { return new ManiphestTask(); @@ -55,70 +54,12 @@ final class HeraldManiphestTaskAdapter extends HeraldAdapter { return $this->task; } - public function setAssignPHID($assign_phid) { - $this->assignPHID = $assign_phid; - return $this; - } - public function getAssignPHID() { - return $this->assignPHID; - } - public function getAdapterContentName() { return pht('Maniphest Tasks'); } - public function getActions($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_EMAIL, - self::ACTION_ASSIGN_TASK, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_EMAIL, - self::ACTION_FLAG, - self::ACTION_ASSIGN_TASK, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - } - } - public function getHeraldName() { return 'T'.$this->getTask()->getID(); } - public function applyHeraldEffects(array $effects) { - assert_instances_of($effects, 'HeraldEffect'); - - $result = array(); - foreach ($effects as $effect) { - $action = $effect->getAction(); - switch ($action) { - case self::ACTION_ASSIGN_TASK: - $target_array = $effect->getTarget(); - $assign_phid = reset($target_array); - $this->setAssignPHID($assign_phid); - $result[] = new HeraldApplyTranscript( - $effect, - true, - pht('Assigned task.')); - break; - default: - $result[] = $this->applyStandardEffect($effect); - break; - } - } - return $result; - } - } diff --git a/src/applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php b/src/applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php new file mode 100644 index 0000000000..79e74e7466 --- /dev/null +++ b/src/applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php @@ -0,0 +1,61 @@ +getAdapter(); + $object = $adapter->getObject(); + + $current = array($object->getOwnerPHID()); + + $allowed_types = array( + PhabricatorPeopleUserPHIDType::TYPECONST, + ); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phid = head_key($targets); + + $xaction = $adapter->newTransaction() + ->setTransactionType(ManiphestTransaction::TYPE_OWNER) + ->setNewValue($phid); + + $adapter->queueTransaction($xaction); + + $this->logEffect(self::DO_ASSIGN, array($phid)); + } + + protected function getActionEffectMap() { + return array( + self::DO_ASSIGN => array( + 'icon' => 'fa-user', + 'color' => 'green', + 'name' => pht('Assigned Task'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_ASSIGN: + return pht( + 'Assigned task to: %s.', + $this->renderHandleList($data)); + } + } + +} diff --git a/src/applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php b/src/applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php new file mode 100644 index 0000000000..6df37056e3 --- /dev/null +++ b/src/applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php @@ -0,0 +1,34 @@ +applyAssign($effect->getTarget()); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + // TODO: Eventually, it would be nice to get "limit = 1" exported from here + // up to the UI. + return new PhabricatorPeopleDatasource(); + } + + public function renderActionDescription($value) { + return pht('Assign task to: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/maniphest/herald/ManiphestTaskAssignSelfHeraldAction.php b/src/applications/maniphest/herald/ManiphestTaskAssignSelfHeraldAction.php new file mode 100644 index 0000000000..a48bafb53e --- /dev/null +++ b/src/applications/maniphest/herald/ManiphestTaskAssignSelfHeraldAction.php @@ -0,0 +1,29 @@ +getRule()->getAuthorPHID(); + return $this->applyAssign(array($phid)); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Assign task to rule author.'); + } + +} diff --git a/src/applications/meta/controller/PhabricatorApplicationUninstallController.php b/src/applications/meta/controller/PhabricatorApplicationUninstallController.php index b43c728257..ae1c5f8748 100644 --- a/src/applications/meta/controller/PhabricatorApplicationUninstallController.php +++ b/src/applications/meta/controller/PhabricatorApplicationUninstallController.php @@ -6,10 +6,6 @@ final class PhabricatorApplicationUninstallController private $application; private $action; - public function shouldRequireAdmin() { - return true; - } - public function willProcessRequest(array $data) { $this->application = $data['application']; $this->action = $data['action']; @@ -19,7 +15,15 @@ final class PhabricatorApplicationUninstallController $request = $this->getRequest(); $user = $request->getUser(); - $selected = PhabricatorApplication::getByClass($this->application); + $selected = id(new PhabricatorApplicationQuery()) + ->setViewer($user) + ->withClasses(array($this->application)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); if (!$selected) { return new Aphront404Response(); diff --git a/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php b/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php new file mode 100644 index 0000000000..835bde8d4d --- /dev/null +++ b/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php @@ -0,0 +1,85 @@ +getAdapter(); + + $allowed_types = array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + ); + + // There's no stateful behavior for this action: we always just send an + // email. + $current = array(); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + foreach ($phids as $phid) { + $adapter->addEmailPHID($phid, $force); + } + + if ($force) { + $this->logEffect(self::DO_FORCE, $phids); + } else { + $this->logEffect(self::DO_SEND, $phids); + } + } + + protected function getActionEffectMap() { + return array( + self::DO_SEND => array( + 'icon' => 'fa-envelope', + 'color' => 'green', + 'name' => pht('Sent Mail'), + ), + self::DO_FORCE => array( + 'icon' => 'fa-envelope', + 'color' => 'blue', + 'name' => pht('Forced Mail'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_SEND: + return pht( + 'Queued email to be delivered to %s target(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_FORCE: + return pht( + 'Queued email to be delivered to %s target(s), ignoring their '. + 'notification preferences: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + +} diff --git a/src/applications/metamta/herald/PhabricatorMetaMTAEmailOthersHeraldAction.php b/src/applications/metamta/herald/PhabricatorMetaMTAEmailOthersHeraldAction.php new file mode 100644 index 0000000000..d569848e01 --- /dev/null +++ b/src/applications/metamta/herald/PhabricatorMetaMTAEmailOthersHeraldAction.php @@ -0,0 +1,32 @@ +applyEmail($effect->getTarget(), $force = false); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorMetaMTAMailableDatasource(); + } + + public function renderActionDescription($value) { + return pht('Send an email to: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/metamta/herald/PhabricatorMetaMTAEmailSelfHeraldAction.php b/src/applications/metamta/herald/PhabricatorMetaMTAEmailSelfHeraldAction.php new file mode 100644 index 0000000000..67563da521 --- /dev/null +++ b/src/applications/metamta/herald/PhabricatorMetaMTAEmailSelfHeraldAction.php @@ -0,0 +1,34 @@ +getRule()->getAuthorPHID(); + + // For personal rules, we'll force delivery of a real email. This effect + // is stronger than notification preferences, so you get an actual email + // even if your preferences are set to "Notify" or "Ignore". + + return $this->applyEmail(array($phid), $force = true); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Send an email to rule author.'); + } + +} diff --git a/src/applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php new file mode 100644 index 0000000000..c907bf1050 --- /dev/null +++ b/src/applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php @@ -0,0 +1,79 @@ +setName('volume') + ->setSynopsis( + pht('Show how much mail users have received in the last 30 days.')) + ->setExamples( + '**volume**') + ->setArguments( + array( + )); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + $viewer = $this->getViewer(); + + $since = (PhabricatorTime::getNow() - phutil_units('30 days in seconds')); + $until = PhabricatorTime::getNow(); + + $mails = id(new PhabricatorMetaMTAMailQuery()) + ->setViewer($viewer) + ->withDateCreatedBetween($since, $until) + ->execute(); + + $unfiltered = array(); + + foreach ($mails as $mail) { + $unfiltered_actors = mpull($mail->loadAllActors(), 'getPHID'); + foreach ($unfiltered_actors as $phid) { + if (empty($unfiltered[$phid])) { + $unfiltered[$phid] = 0; + } + $unfiltered[$phid]++; + } + } + + arsort($unfiltered); + + $table = id(new PhutilConsoleTable()) + ->setBorders(true) + ->addColumn( + 'user', + array( + 'title' => pht('User'), + )) + ->addColumn( + 'unfiltered', + array( + 'title' => pht('Unfiltered'), + )); + + $handles = $viewer->loadHandles(array_keys($unfiltered)); + $names = mpull(iterator_to_array($handles), 'getName', 'getPHID'); + + foreach ($unfiltered as $phid => $count) { + $table->addRow( + array( + 'user' => idx($names, $phid), + 'unfiltered' => $count, + )); + } + + $table->draw(); + + echo "\n"; + echo pht('Mail sent in the last 30 days.')."\n"; + echo pht( + '"Unfiltered" is raw volume before preferences were applied.')."\n"; + echo "\n"; + + return 0; + } + +} diff --git a/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php index a0965b7133..e0dadb5f13 100644 --- a/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php +++ b/src/applications/metamta/query/PhabricatorMetaMTAMailQuery.php @@ -7,6 +7,8 @@ final class PhabricatorMetaMTAMailQuery private $phids; private $actorPHIDs; private $recipientPHIDs; + private $createdMin; + private $createdMax; public function withIDs(array $ids) { $this->ids = $ids; @@ -28,53 +30,73 @@ final class PhabricatorMetaMTAMailQuery return $this; } + public function withDateCreatedBetween($min, $max) { + $this->createdMin = $min; + $this->createdMax = $max; + return $this; + } + protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { - $where = array(); + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { + $where = parent::buildWhereClauseParts($conn); if ($this->ids !== null) { $where[] = qsprintf( - $conn_r, + $conn, 'mail.id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( - $conn_r, + $conn, 'mail.phid IN (%Ls)', $this->phids); } if ($this->actorPHIDs !== null) { $where[] = qsprintf( - $conn_r, + $conn, 'mail.actorPHID IN (%Ls)', $this->actorPHIDs); } if ($this->recipientPHIDs !== null) { $where[] = qsprintf( - $conn_r, + $conn, 'recipient.dst IN (%Ls)', $this->recipientPHIDs); } if ($this->actorPHIDs === null && $this->recipientPHIDs === null) { $viewer = $this->getViewer(); - $where[] = qsprintf( - $conn_r, - 'edge.dst = %s OR actorPHID = %s', - $viewer->getPHID(), - $viewer->getPHID()); + if (!$viewer->isOmnipotent()) { + $where[] = qsprintf( + $conn, + 'edge.dst = %s OR actorPHID = %s', + $viewer->getPHID(), + $viewer->getPHID()); + } } - $where[] = $this->buildPagingClause($conn_r); + if ($this->createdMin !== null) { + $where[] = qsprintf( + $conn, + 'mail.dateCreated >= %d', + $this->createdMin); + } - return $this->formatWhereClause($where); + if ($this->createdMax !== null) { + $where[] = qsprintf( + $conn, + 'mail.dateCreated <= %d', + $this->createdMax); + } + + return $where; } protected function buildJoinClause(AphrontDatabaseConnection $conn) { diff --git a/src/applications/notification/controller/PhabricatorNotificationClearController.php b/src/applications/notification/controller/PhabricatorNotificationClearController.php index ba781234e7..0b6027d379 100644 --- a/src/applications/notification/controller/PhabricatorNotificationClearController.php +++ b/src/applications/notification/controller/PhabricatorNotificationClearController.php @@ -3,10 +3,9 @@ final class PhabricatorNotificationClearController extends PhabricatorNotificationController { - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $chrono_key = $request->getStr('chronoKey'); - $user = $request->getUser(); if ($request->isDialogFormPost()) { $table = new PhabricatorFeedStoryNotification(); @@ -16,7 +15,7 @@ final class PhabricatorNotificationClearController 'UPDATE %T SET hasViewed = 1 '. 'WHERE userPHID = %s AND hasViewed = 0 and chronologicalKey <= %s', $table->getTableName(), - $user->getPHID(), + $viewer->getPHID(), $chrono_key); return id(new AphrontReloadResponse()) @@ -24,7 +23,7 @@ final class PhabricatorNotificationClearController } $dialog = new AphrontDialogView(); - $dialog->setUser($user); + $dialog->setUser($viewer); $dialog->addCancelButton('/notification/'); if ($chrono_key) { $dialog->setTitle(pht('Really mark all notifications as read?')); diff --git a/src/applications/notification/controller/PhabricatorNotificationIndividualController.php b/src/applications/notification/controller/PhabricatorNotificationIndividualController.php index 6e6f7361df..68214d1965 100644 --- a/src/applications/notification/controller/PhabricatorNotificationIndividualController.php +++ b/src/applications/notification/controller/PhabricatorNotificationIndividualController.php @@ -3,9 +3,8 @@ final class PhabricatorNotificationIndividualController extends PhabricatorNotificationController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $stories = id(new PhabricatorNotificationQuery()) ->setViewer($viewer) diff --git a/src/applications/notification/controller/PhabricatorNotificationListController.php b/src/applications/notification/controller/PhabricatorNotificationListController.php index b7ab15df90..718c2431a1 100644 --- a/src/applications/notification/controller/PhabricatorNotificationListController.php +++ b/src/applications/notification/controller/PhabricatorNotificationListController.php @@ -3,15 +3,11 @@ final class PhabricatorNotificationListController extends PhabricatorNotificationController { - private $queryKey; + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } - - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhabricatorNotificationSearchEngine()) ->setNavigation($this->buildSideNavView()); @@ -19,13 +15,13 @@ final class PhabricatorNotificationListController } public function buildSideNavView() { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); id(new PhabricatorNotificationSearchEngine()) - ->setViewer($user) + ->setViewer($viewer) ->addNavigationItems($nav->getMenu()); $nav->selectFilter(null); diff --git a/src/applications/notification/controller/PhabricatorNotificationPanelController.php b/src/applications/notification/controller/PhabricatorNotificationPanelController.php index 3e8f16b07a..c16069a0e6 100644 --- a/src/applications/notification/controller/PhabricatorNotificationPanelController.php +++ b/src/applications/notification/controller/PhabricatorNotificationPanelController.php @@ -3,14 +3,12 @@ final class PhabricatorNotificationPanelController extends PhabricatorNotificationController { - public function processRequest() { - - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $query = id(new PhabricatorNotificationQuery()) - ->setViewer($user) - ->withUserPHIDs(array($user->getPHID())) + ->setViewer($viewer) + ->withUserPHIDs(array($viewer->getPHID())) ->setLimit(15); $stories = $query->execute(); @@ -81,7 +79,7 @@ final class PhabricatorNotificationPanelController $connection_ui); $unread_count = id(new PhabricatorFeedStoryNotification()) - ->countUnread($user); + ->countUnread($viewer); $json = array( 'content' => $content, diff --git a/src/applications/notification/controller/PhabricatorNotificationStatusController.php b/src/applications/notification/controller/PhabricatorNotificationStatusController.php index 2c9e308985..e889c7af5e 100644 --- a/src/applications/notification/controller/PhabricatorNotificationStatusController.php +++ b/src/applications/notification/controller/PhabricatorNotificationStatusController.php @@ -3,7 +3,8 @@ final class PhabricatorNotificationStatusController extends PhabricatorNotificationController { - public function processRequest() { + public function handleRequest(AphrontRequest $request) { + try { $status = PhabricatorNotificationClient::getServerStatus(); $status = $this->renderServerStatus($status); diff --git a/src/applications/notification/controller/PhabricatorNotificationTestController.php b/src/applications/notification/controller/PhabricatorNotificationTestController.php index 706242818c..5c76e53357 100644 --- a/src/applications/notification/controller/PhabricatorNotificationTestController.php +++ b/src/applications/notification/controller/PhabricatorNotificationTestController.php @@ -3,9 +3,8 @@ final class PhabricatorNotificationTestController extends PhabricatorNotificationController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $story_type = 'PhabricatorNotificationTestFeedStory'; $story_data = array( diff --git a/src/applications/nuance/controller/NuanceItemEditController.php b/src/applications/nuance/controller/NuanceItemEditController.php index b5e02cbda6..89bfbda5c9 100644 --- a/src/applications/nuance/controller/NuanceItemEditController.php +++ b/src/applications/nuance/controller/NuanceItemEditController.php @@ -2,33 +2,16 @@ final class NuanceItemEditController extends NuanceController { - private $itemID; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function setItemID($item_id) { - $this->itemID = $item_id; - return $this; - } - public function getItemID() { - return $this->itemID; - } - - public function willProcessRequest(array $data) { - $this->setItemID(idx($data, 'id')); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $item_id = $this->getItemID(); - $is_new = !$item_id; - - if ($is_new) { + if (!$id) { $item = new NuanceItem(); } else { $item = id(new NuanceItemQuery()) - ->setViewer($user) - ->withIDs(array($item_id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); } diff --git a/src/applications/nuance/controller/NuanceItemViewController.php b/src/applications/nuance/controller/NuanceItemViewController.php index e0ba457e89..9c7401cafe 100644 --- a/src/applications/nuance/controller/NuanceItemViewController.php +++ b/src/applications/nuance/controller/NuanceItemViewController.php @@ -2,28 +2,13 @@ final class NuanceItemViewController extends NuanceController { - private $itemID; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function setItemID($item_id) { - $this->itemID = $item_id; - return $this; - } - public function getItemID() { - return $this->itemID; - } - - public function willProcessRequest(array $data) { - $this->setItemID($data['id']); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $item_id = $this->getItemID(); $item = id(new NuanceItemQuery()) - ->setViewer($user) - ->withIDs(array($item_id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$item) { diff --git a/src/applications/nuance/controller/NuanceRequestorEditController.php b/src/applications/nuance/controller/NuanceRequestorEditController.php index 42405a227f..2efc49f711 100644 --- a/src/applications/nuance/controller/NuanceRequestorEditController.php +++ b/src/applications/nuance/controller/NuanceRequestorEditController.php @@ -2,34 +2,17 @@ final class NuanceRequestorEditController extends NuanceController { - private $requestorID; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function setRequestorID($requestor_id) { - $this->requestorID = $requestor_id; - return $this; - } - public function getRequestorID() { - return $this->requestorID; - } - - public function willProcessRequest(array $data) { - $this->setRequestorID(idx($data, 'id')); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $requestor_id = $this->getRequestorID(); - $is_new = !$requestor_id; - - if ($is_new) { + if (!$id) { $requestor = new NuanceRequestor(); } else { $requestor = id(new NuanceRequestorQuery()) - ->setViewer($user) - ->withIDs(array($requestor_id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); } diff --git a/src/applications/nuance/controller/NuanceRequestorViewController.php b/src/applications/nuance/controller/NuanceRequestorViewController.php index 08dcedb62a..8f6912c4d7 100644 --- a/src/applications/nuance/controller/NuanceRequestorViewController.php +++ b/src/applications/nuance/controller/NuanceRequestorViewController.php @@ -2,28 +2,13 @@ final class NuanceRequestorViewController extends NuanceController { - private $requestorID; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function setRequestorID($requestor_id) { - $this->requestorID = $requestor_id; - return $this; - } - public function getRequestorID() { - return $this->requestorID; - } - - public function willProcessRequest(array $data) { - $this->setRequestorID($data['id']); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - $requestor_id = $this->getRequestorID(); $requestor = id(new NuanceRequestorQuery()) - ->setViewer($user) - ->withIDs(array($requestor_id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$requestor) { diff --git a/src/applications/passphrase/controller/PassphraseCredentialConduitController.php b/src/applications/passphrase/controller/PassphraseCredentialConduitController.php index 4c65b5d07d..b86d18c227 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialConduitController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialConduitController.php @@ -3,19 +3,13 @@ final class PassphraseCredentialConduitController extends PassphraseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/passphrase/controller/PassphraseCredentialCreateController.php b/src/applications/passphrase/controller/PassphraseCredentialCreateController.php index a6462b8da8..cfddcbcc4a 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialCreateController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialCreateController.php @@ -2,9 +2,8 @@ final class PassphraseCredentialCreateController extends PassphraseController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $types = PassphraseCredentialType::getAllCreateableTypes(); $types = mpull($types, null, 'getCredentialType'); diff --git a/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php b/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php index 53f9e0650f..8858d0ef6b 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php @@ -3,19 +3,13 @@ final class PassphraseCredentialDestroyController extends PassphraseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/passphrase/controller/PassphraseCredentialEditController.php b/src/applications/passphrase/controller/PassphraseCredentialEditController.php index 36033c7c01..8a2a8da70f 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialEditController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialEditController.php @@ -2,20 +2,14 @@ final class PassphraseCredentialEditController extends PassphraseController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/passphrase/controller/PassphraseCredentialListController.php b/src/applications/passphrase/controller/PassphraseCredentialListController.php index db36a4a6ba..c4da29a984 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialListController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialListController.php @@ -2,19 +2,15 @@ final class PassphraseCredentialListController extends PassphraseController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PassphraseCredentialSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/passphrase/controller/PassphraseCredentialLockController.php b/src/applications/passphrase/controller/PassphraseCredentialLockController.php index 3abe4c8820..4a872d8667 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialLockController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialLockController.php @@ -3,19 +3,13 @@ final class PassphraseCredentialLockController extends PassphraseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/passphrase/controller/PassphraseCredentialPublicController.php b/src/applications/passphrase/controller/PassphraseCredentialPublicController.php index dc129a327d..56fc6ac4ae 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialPublicController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialPublicController.php @@ -3,19 +3,13 @@ final class PassphraseCredentialPublicController extends PassphraseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php index e82dea7408..c61086b0e7 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php @@ -3,19 +3,13 @@ final class PassphraseCredentialRevealController extends PassphraseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/passphrase/controller/PassphraseCredentialViewController.php b/src/applications/passphrase/controller/PassphraseCredentialViewController.php index ede3bab78f..46fd0c4c7a 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialViewController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialViewController.php @@ -2,19 +2,13 @@ final class PassphraseCredentialViewController extends PassphraseController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$credential) { return new Aphront404Response(); @@ -199,6 +193,8 @@ final class PassphraseCredentialViewController extends PassphraseController { $viewer->renderHandleList($used_by_phids)); } + $properties->invokeWillRenderEvent(); + $description = $credential->getDescription(); if (strlen($description)) { $properties->addSectionHeader( diff --git a/src/applications/passphrase/storage/PassphraseCredential.php b/src/applications/passphrase/storage/PassphraseCredential.php index 3ad1351061..1c58ced82d 100644 --- a/src/applications/passphrase/storage/PassphraseCredential.php +++ b/src/applications/passphrase/storage/PassphraseCredential.php @@ -5,6 +5,7 @@ final class PassphraseCredential extends PassphraseDAO PhabricatorApplicationTransactionInterface, PhabricatorPolicyInterface, PhabricatorFlaggableInterface, + PhabricatorSubscribableInterface, PhabricatorDestructibleInterface, PhabricatorSpacesInterface { @@ -147,6 +148,23 @@ final class PassphraseCredential extends PassphraseDAO return null; } + +/* -( PhabricatorSubscribableInterface )----------------------------------- */ + + + public function isAutomaticallySubscribed($phid) { + return false; + } + + public function shouldShowSubscribersProperty() { + return true; + } + + public function shouldAllowSubscription($phid) { + return true; + } + + /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( diff --git a/src/applications/paste/controller/PhabricatorPasteCommentController.php b/src/applications/paste/controller/PhabricatorPasteCommentController.php index cd35c4a36e..06596e5be7 100644 --- a/src/applications/paste/controller/PhabricatorPasteCommentController.php +++ b/src/applications/paste/controller/PhabricatorPasteCommentController.php @@ -3,23 +3,17 @@ final class PhabricatorPasteCommentController extends PhabricatorPasteController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $paste = id(new PhabricatorPasteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$paste) { return new Aphront404Response(); @@ -38,7 +32,7 @@ final class PhabricatorPasteCommentController ->setContent($request->getStr('comment'))); $editor = id(new PhabricatorPasteEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect($request->isContinueRequest()) ->setContentSourceFromRequest($request) ->setIsPreview($is_preview); @@ -57,7 +51,7 @@ final class PhabricatorPasteCommentController if ($request->isAjax() && $is_preview) { return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setIsPreview($is_preview); } else { diff --git a/src/applications/paste/controller/PhabricatorPasteEditController.php b/src/applications/paste/controller/PhabricatorPasteEditController.php index dcc4900951..19b394c18a 100644 --- a/src/applications/paste/controller/PhabricatorPasteEditController.php +++ b/src/applications/paste/controller/PhabricatorPasteEditController.php @@ -2,29 +2,23 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $parent = null; $parent_id = null; - if (!$this->id) { + if (!$id) { $is_create = true; - $paste = PhabricatorPaste::initializeNewPaste($user); + $paste = PhabricatorPaste::initializeNewPaste($viewer); $parent_id = $request->getStr('parent'); if ($parent_id) { // NOTE: If the Paste is forked from a paste which the user no longer // has permission to see, we still let them edit it. $parent = id(new PhabricatorPasteQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($parent_id)) ->needContent(true) ->needRawContent(true) @@ -37,19 +31,19 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { } } - $paste->setAuthorPHID($user->getPHID()); + $paste->setAuthorPHID($viewer->getPHID()); $paste->attachRawContent(''); } else { $is_create = false; $paste = id(new PhabricatorPasteQuery()) - ->setViewer($user) + ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needRawContent(true) ->executeOne(); if (!$paste) { @@ -70,6 +64,7 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { } $v_view_policy = $paste->getViewPolicy(); $v_edit_policy = $paste->getEditPolicy(); + $v_status = $paste->getStatus(); if ($is_create) { $v_projects = array(); @@ -91,13 +86,14 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { $v_edit_policy = $request->getStr('can_edit'); $v_projects = $request->getArr('projects'); $v_space = $request->getStr('spacePHID'); + $v_status = $request->getStr('status'); // NOTE: The author is the only editor and can always view the paste, // so it's impossible for them to choose an invalid policy. if ($is_create || ($v_text !== $paste->getRawContent())) { $file = PhabricatorPasteEditor::initializeFileForPaste( - $user, + $viewer, $v_title, $v_text); @@ -121,6 +117,9 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { $xactions[] = id(new PhabricatorPasteTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) ->setNewValue($v_space); + $xactions[] = id(new PhabricatorPasteTransaction()) + ->setTransactionType(PhabricatorPasteTransaction::TYPE_STATUS) + ->setNewValue($v_status); $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $xactions[] = id(new PhabricatorPasteTransaction()) @@ -129,7 +128,7 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { ->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PhabricatorPasteEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true); @@ -148,7 +147,7 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { ) + PhabricatorEnv::getEnvConfig('pygments.dropdown-choices'); $form - ->setUser($user) + ->setUser($viewer) ->addHiddenInput('parent', $parent_id) ->appendChild( id(new AphrontFormTextControl()) @@ -163,13 +162,13 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { ->setOptions($langs)); $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) + ->setViewer($viewer) ->setObject($paste) ->execute(); $form->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicyObject($paste) ->setPolicies($policies) @@ -179,13 +178,20 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { $form->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicyObject($paste) ->setPolicies($policies) ->setValue($v_edit_policy) ->setName('can_edit')); + $form->appendChild( + id(new AphrontFormSelectControl()) + ->setLabel(pht('Status')) + ->setName('status') + ->setValue($v_status) + ->setOptions($paste->getStatusNameMap())); + $form->appendControl( id(new AphrontFormTokenizerControl()) ->setLabel(pht('Projects')) diff --git a/src/applications/paste/controller/PhabricatorPasteListController.php b/src/applications/paste/controller/PhabricatorPasteListController.php index 3d8cf7fc11..2092443ffc 100644 --- a/src/applications/paste/controller/PhabricatorPasteListController.php +++ b/src/applications/paste/controller/PhabricatorPasteListController.php @@ -2,19 +2,15 @@ final class PhabricatorPasteListController extends PhabricatorPasteController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhabricatorPasteSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/paste/controller/PhabricatorPasteViewController.php b/src/applications/paste/controller/PhabricatorPasteViewController.php index 75f2532358..0273636d00 100644 --- a/src/applications/paste/controller/PhabricatorPasteViewController.php +++ b/src/applications/paste/controller/PhabricatorPasteViewController.php @@ -5,7 +5,6 @@ */ final class PhabricatorPasteViewController extends PhabricatorPasteController { - private $id; private $highlightMap; public function shouldAllowPublic() { @@ -13,7 +12,6 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { } public function willProcessRequest(array $data) { - $this->id = $data['id']; $raw_lines = idx($data, 'lines'); $map = array(); if ($raw_lines) { @@ -31,13 +29,13 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { $this->highlightMap = $map; } - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $paste = id(new PhabricatorPasteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needContent(true) ->executeOne(); if (!$paste) { @@ -45,7 +43,7 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { } $file = id(new PhabricatorFileQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($paste->getFilePHID())) ->executeOne(); if (!$file) { @@ -53,13 +51,13 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { } $forks = id(new PhabricatorPasteQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withParentPHIDs(array($paste->getPHID())) ->execute(); $fork_phids = mpull($forks, 'getPHID'); $header = $this->buildHeaderView($paste); - $actions = $this->buildActionView($user, $paste, $file); + $actions = $this->buildActionView($viewer, $paste, $file); $properties = $this->buildPropertyView($paste, $fork_phids, $actions); $object_box = id(new PHUIObjectBoxView()) @@ -90,10 +88,10 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { ? pht('Add Comment') : pht('Eat Paste'); - $draft = PhabricatorDraft::newFromUserAndKey($user, $paste->getPHID()); + $draft = PhabricatorDraft::newFromUserAndKey($viewer, $paste->getPHID()); $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($user) + ->setUser($viewer) ->setObjectPHID($paste->getPHID()) ->setDraft($draft) ->setHeaderText($add_comment_header) @@ -117,29 +115,41 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { private function buildHeaderView(PhabricatorPaste $paste) { $title = (nonempty($paste->getTitle())) ? $paste->getTitle() : pht('(An Untitled Masterwork)'); + + if ($paste->isArchived()) { + $header_icon = 'fa-ban'; + $header_name = pht('Archived'); + $header_color = 'dark'; + } else { + $header_icon = 'fa-check'; + $header_name = pht('Active'); + $header_color = 'bluegrey'; + } + $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($this->getRequest()->getUser()) + ->setStatus($header_icon, $header_color, $header_name) ->setPolicyObject($paste); return $header; } private function buildActionView( - PhabricatorUser $user, + PhabricatorUser $viewer, PhabricatorPaste $paste, PhabricatorFile $file) { $can_edit = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, $paste, PhabricatorPolicyCapability::CAN_EDIT); - $can_fork = $user->isLoggedIn(); + $can_fork = $viewer->isLoggedIn(); $fork_uri = $this->getApplicationURI('/create/?parent='.$paste->getID()); return id(new PhabricatorActionListView()) - ->setUser($user) + ->setUser($viewer) ->setObject($paste) ->setObjectURI($this->getRequest()->getRequestURI()) ->addAction( diff --git a/src/applications/paste/editor/PhabricatorPasteEditor.php b/src/applications/paste/editor/PhabricatorPasteEditor.php index 732db28bd7..bae2003afe 100644 --- a/src/applications/paste/editor/PhabricatorPasteEditor.php +++ b/src/applications/paste/editor/PhabricatorPasteEditor.php @@ -33,6 +33,7 @@ final class PhabricatorPasteEditor $types[] = PhabricatorPasteTransaction::TYPE_CONTENT; $types[] = PhabricatorPasteTransaction::TYPE_TITLE; $types[] = PhabricatorPasteTransaction::TYPE_LANGUAGE; + $types[] = PhabricatorPasteTransaction::TYPE_STATUS; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_COMMENT; @@ -51,6 +52,8 @@ final class PhabricatorPasteEditor return $object->getTitle(); case PhabricatorPasteTransaction::TYPE_LANGUAGE: return $object->getLanguage(); + case PhabricatorPasteTransaction::TYPE_STATUS: + return $object->getStatus(); } } @@ -62,6 +65,7 @@ final class PhabricatorPasteEditor case PhabricatorPasteTransaction::TYPE_CONTENT: case PhabricatorPasteTransaction::TYPE_TITLE: case PhabricatorPasteTransaction::TYPE_LANGUAGE: + case PhabricatorPasteTransaction::TYPE_STATUS: return $xaction->getNewValue(); } } @@ -80,6 +84,9 @@ final class PhabricatorPasteEditor case PhabricatorPasteTransaction::TYPE_LANGUAGE: $object->setLanguage($xaction->getNewValue()); return; + case PhabricatorPasteTransaction::TYPE_STATUS: + $object->setStatus($xaction->getNewValue()); + return; } return parent::applyCustomInternalTransaction($object, $xaction); @@ -93,6 +100,7 @@ final class PhabricatorPasteEditor case PhabricatorPasteTransaction::TYPE_CONTENT: case PhabricatorPasteTransaction::TYPE_TITLE: case PhabricatorPasteTransaction::TYPE_LANGUAGE: + case PhabricatorPasteTransaction::TYPE_STATUS: return; } diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php index 661701ba09..0fab56b724 100644 --- a/src/applications/paste/storage/PhabricatorPaste.php +++ b/src/applications/paste/storage/PhabricatorPaste.php @@ -20,8 +20,12 @@ final class PhabricatorPaste extends PhabricatorPasteDAO protected $viewPolicy; protected $editPolicy; protected $mailKey; + protected $status; protected $spacePHID; + const STATUS_ACTIVE = 'active'; + const STATUS_ARCHIVED = 'archived'; + private $content = self::ATTACHABLE; private $rawContent = self::ATTACHABLE; @@ -36,12 +40,20 @@ final class PhabricatorPaste extends PhabricatorPasteDAO return id(new PhabricatorPaste()) ->setTitle('') + ->setStatus(self::STATUS_ACTIVE) ->setAuthorPHID($actor->getPHID()) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->setSpacePHID($actor->getDefaultSpacePHID()); } + public static function getStatusNameMap() { + return array( + self::STATUS_ACTIVE => pht('Active'), + self::STATUS_ARCHIVED => pht('Archived'), + ); + } + public function getURI() { return '/'.$this->getMonogram(); } @@ -54,6 +66,7 @@ final class PhabricatorPaste extends PhabricatorPasteDAO return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( + 'status' => 'text32', 'title' => 'text255', 'language' => 'text64', 'mailKey' => 'bytes20', @@ -85,6 +98,10 @@ final class PhabricatorPaste extends PhabricatorPasteDAO PhabricatorPastePastePHIDType::TYPECONST); } + public function isArchived() { + return ($this->getStatus() == self::STATUS_ARCHIVED); + } + public function save() { if (!$this->getMailKey()) { $this->setMailKey(Filesystem::readRandomCharacters(20)); diff --git a/src/applications/paste/storage/PhabricatorPasteTransaction.php b/src/applications/paste/storage/PhabricatorPasteTransaction.php index 34cc6bd92d..d6b962298b 100644 --- a/src/applications/paste/storage/PhabricatorPasteTransaction.php +++ b/src/applications/paste/storage/PhabricatorPasteTransaction.php @@ -6,6 +6,7 @@ final class PhabricatorPasteTransaction const TYPE_CONTENT = 'paste.create'; const TYPE_TITLE = 'paste.title'; const TYPE_LANGUAGE = 'paste.language'; + const TYPE_STATUS = 'paste.status'; const MAILTAG_CONTENT = 'paste-content'; const MAILTAG_OTHER = 'paste-other'; @@ -54,6 +55,15 @@ final class PhabricatorPasteTransaction case self::TYPE_LANGUAGE: return 'fa-pencil'; break; + case self::TYPE_STATUS: + $new = $this->getNewValue(); + switch ($new) { + case PhabricatorPaste::STATUS_ACTIVE: + return 'fa-check'; + case PhabricatorPaste::STATUS_ARCHIVED: + return 'fa-ban'; + } + break; } return parent::getIcon(); } @@ -89,6 +99,19 @@ final class PhabricatorPasteTransaction "%s updated the paste's language.", $this->renderHandleLink($author_phid)); break; + case self::TYPE_STATUS: + switch ($new) { + case PhabricatorPaste::STATUS_ACTIVE: + return pht( + '%s activated this paste.', + $this->renderHandleLink($author_phid)); + case PhabricatorPaste::STATUS_ARCHIVED: + return pht( + '%s archived this paste.', + $this->renderHandleLink($author_phid)); + } + break; + } return parent::getTitle(); @@ -128,6 +151,20 @@ final class PhabricatorPasteTransaction $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; + case self::TYPE_STATUS: + switch ($new) { + case PhabricatorPaste::STATUS_ACTIVE: + return pht( + '%s activated %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + case PhabricatorPaste::STATUS_ARCHIVED: + return pht( + '%s archived %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + break; } return parent::getTitleForFeed(); @@ -140,6 +177,14 @@ final class PhabricatorPasteTransaction switch ($this->getTransactionType()) { case self::TYPE_CONTENT: return PhabricatorTransactions::COLOR_GREEN; + case self::TYPE_STATUS: + switch ($new) { + case PhabricatorPaste::STATUS_ACTIVE: + return 'green'; + case PhabricatorPaste::STATUS_ARCHIVED: + return 'indigo'; + } + break; } return parent::getColor(); diff --git a/src/applications/phame/controller/PhameController.php b/src/applications/phame/controller/PhameController.php index adf72c0e7d..fba717e8d9 100644 --- a/src/applications/phame/controller/PhameController.php +++ b/src/applications/phame/controller/PhameController.php @@ -9,14 +9,10 @@ abstract class PhameController extends PhabricatorController { $nav = new AphrontSideNavFilterView(); $nav->setBaseURI($base_uri); - $nav->addLabel(pht('Create')); - $nav->addFilter('post/new', pht('New Post')); - $nav->addFilter('blog/new', pht('New Blog')); - $nav->addLabel(pht('Posts')); + $nav->addFilter('post/all', pht('Latest Posts')); $nav->addFilter('post/draft', pht('My Drafts')); $nav->addFilter('post', pht('My Posts')); - $nav->addFilter('post/all', pht('All Posts')); $nav->addLabel(pht('Blogs')); $nav->addFilter('blog/user', pht('Joinable Blogs')); diff --git a/src/applications/phame/controller/blog/PhameBlogEditController.php b/src/applications/phame/controller/blog/PhameBlogEditController.php index 3b3d6bd92f..19862fbfbe 100644 --- a/src/applications/phame/controller/blog/PhameBlogEditController.php +++ b/src/applications/phame/controller/blog/PhameBlogEditController.php @@ -192,18 +192,14 @@ final class PhameBlogEditController ->setForm($form); $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/')); $crumbs->addTextCrumb($page_title, $this->getApplicationURI('blog/new')); - $nav = $this->renderSideNavFilterView(); - $nav->selectFilter($id ? null : 'blog/new'); - $nav->appendChild( + return $this->buildApplicationPage( array( $crumbs, $form_box, - )); - - return $this->buildApplicationPage( - $nav, + ), array( 'title' => $page_title, )); diff --git a/src/applications/phame/controller/blog/PhameBlogListController.php b/src/applications/phame/controller/blog/PhameBlogListController.php index 16486b95da..9d0253d89c 100644 --- a/src/applications/phame/controller/blog/PhameBlogListController.php +++ b/src/applications/phame/controller/blog/PhameBlogListController.php @@ -38,7 +38,7 @@ final class PhameBlogListController extends PhameController { $blog_list = $this->renderBlogList($blogs, $user, $nodata); $blog_list->setPager($pager); - $box = id (new PHUIObjectBoxView()) + $box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setObjectList($blog_list); @@ -60,18 +60,23 @@ final class PhameBlogListController extends PhameController { private function renderBlogList( array $blogs, - PhabricatorUser $user, + PhabricatorUser $viewer, $nodata) { $view = new PHUIObjectItemListView(); $view->setNoDataString($nodata); - $view->setUser($user); + $view->setUser($viewer); foreach ($blogs as $blog) { + $id = $blog->getID(); $item = id(new PHUIObjectItemView()) + ->setUser($viewer) + ->setObject($blog) ->setHeader($blog->getName()) - ->setHref($this->getApplicationURI('blog/view/'.$blog->getID().'/')) - ->setObject($blog); + ->setStatusIcon('fa-star') + ->setHref($this->getApplicationURI("/blog/view/{$id}/")) + ->addAttribute($blog->getSkin()) + ->addAttribute($blog->getDomain()); $view->addItem($item); } diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index 2196281c7d..c8eddfbad3 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -22,8 +22,6 @@ final class PhameBlogViewController extends PhameController { ->withBlogPHIDs(array($blog->getPHID())) ->executeWithCursorPager($pager); - $nav = $this->renderSideNavFilterView(null); - $header = id(new PHUIHeaderView()) ->setHeader($blog->getName()) ->setUser($user) @@ -36,29 +34,24 @@ final class PhameBlogViewController extends PhameController { $user, pht('This blog has no visible posts.')); - require_celerity_resource('phame-css'); - $post_list = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_LARGE) - ->addClass('phame-post-list') + $post_list = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Latest Posts')) ->appendChild($post_list); - $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/')); $crumbs->addTextCrumb($blog->getName(), $this->getApplicationURI()); $object_box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addPropertyList($properties); - $nav->appendChild( + return $this->buildApplicationPage( array( $crumbs, $object_box, $post_list, - )); - - return $this->buildApplicationPage( - $nav, + ), array( 'title' => $blog->getName(), )); diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php index 2b3324f805..e79d435deb 100644 --- a/src/applications/phame/controller/post/PhamePostEditController.php +++ b/src/applications/phame/controller/post/PhamePostEditController.php @@ -169,7 +169,6 @@ final class PhamePostEditController extends PhameController { phutil_tag('div', array('id' => 'post-preview'), $loading), )); - require_celerity_resource('phame-css'); Javelin::initBehavior( 'phame-post-preview', array( @@ -190,16 +189,12 @@ final class PhamePostEditController extends PhameController { $page_title, $this->getApplicationURI('/post/view/'.$id.'/')); - $nav = $this->renderSideNavFilterView(null); - $nav->appendChild( + return $this->buildApplicationPage( array( $crumbs, $form_box, $preview_panel, - )); - - return $this->buildApplicationPage( - $nav, + ), array( 'title' => $page_title, )); diff --git a/src/applications/phame/controller/post/PhamePostListController.php b/src/applications/phame/controller/post/PhamePostListController.php index 6a02129bd8..b2b28bd4eb 100644 --- a/src/applications/phame/controller/post/PhamePostListController.php +++ b/src/applications/phame/controller/post/PhamePostListController.php @@ -21,12 +21,6 @@ final class PhamePostListController extends PhameController { $title = pht('Unpublished Drafts'); $nav->selectFilter('post/draft'); break; - case 'all': - $nodata = pht('There are no visible posts.'); - $title = pht('Posts'); - $nav->selectFilter('post/all'); - break; - default: case 'blogger': if ($bloggername) { $blogger = id(new PhabricatorUser())->loadOneWhere( @@ -48,6 +42,12 @@ final class PhamePostListController extends PhameController { } $title = pht('Posts by %s', $blogger); break; + default: + case 'all': + $nodata = pht('There are no visible posts.'); + $title = pht('Posts'); + $nav->selectFilter('post/all'); + break; } $pager = id(new AphrontCursorPagerView()) @@ -55,7 +55,6 @@ final class PhamePostListController extends PhameController { $posts = $query->executeWithCursorPager($pager); - require_celerity_resource('phame-css'); $post_list = $this->renderPostList($posts, $viewer, $nodata); $post_list = id(new PHUIObjectBoxView()) ->setHeaderText($title) diff --git a/src/applications/phame/controller/post/PhamePostNewController.php b/src/applications/phame/controller/post/PhamePostNewController.php index 94d8651f27..33330ef271 100644 --- a/src/applications/phame/controller/post/PhamePostNewController.php +++ b/src/applications/phame/controller/post/PhamePostNewController.php @@ -56,12 +56,10 @@ final class PhamePostNewController extends PhameController { )) ->execute(); - $nav = $this->renderSideNavFilterView(); - $nav->selectFilter('post/new'); - $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title, $view_uri); - $nav->appendChild($crumbs); + $display = array(); + $display[] = $crumbs; if (!$blogs) { $notification = id(new PHUIInfoView()) @@ -70,7 +68,7 @@ final class PhamePostNewController extends PhameController { pht('You do not have permission to join any blogs. Create a blog '. 'first, then you can post to it.')); - $nav->appendChild($notification); + $display[] = $notification; } else { $options = mpull($blogs, 'getName', 'getID'); asort($options); @@ -109,11 +107,11 @@ final class PhamePostNewController extends PhameController { ->setHeaderText($title) ->setForm($form); - $nav->appendChild($form_box); + $display[] = $form_box; } return $this->buildApplicationPage( - $nav, + $display, array( 'title' => $title, )); diff --git a/src/applications/phame/query/PhamePostSearchEngine.php b/src/applications/phame/query/PhamePostSearchEngine.php index 600d633627..a5feb3d634 100644 --- a/src/applications/phame/query/PhamePostSearchEngine.php +++ b/src/applications/phame/query/PhamePostSearchEngine.php @@ -102,7 +102,7 @@ final class PhamePostSearchEngine $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); - $result->setNoDataString(pht('No blogs found.')); + $result->setNoDataString(pht('No blogs posts found.')); return $result; } diff --git a/src/applications/phame/view/PhamePostView.php b/src/applications/phame/view/PhamePostView.php index 236ecc2b39..f35125f255 100644 --- a/src/applications/phame/view/PhamePostView.php +++ b/src/applications/phame/view/PhamePostView.php @@ -173,6 +173,7 @@ final class PhamePostView extends AphrontView { $uri = $this->getSkin()->getURI('post/'.$this->getPost()->getPhameTitle()); + require_celerity_resource('phame-css'); $fb_comments = phutil_tag('div', array( 'class' => 'fb-comments', diff --git a/src/applications/pholio/controller/PholioImageUploadController.php b/src/applications/pholio/controller/PholioImageUploadController.php index 530563dc8f..0329d3eb1d 100644 --- a/src/applications/pholio/controller/PholioImageUploadController.php +++ b/src/applications/pholio/controller/PholioImageUploadController.php @@ -2,9 +2,8 @@ final class PholioImageUploadController extends PholioController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $phid = $request->getStr('filePHID'); $replaces_phid = $request->getStr('replacesPHID'); diff --git a/src/applications/pholio/controller/PholioInlineController.php b/src/applications/pholio/controller/PholioInlineController.php index 4cc5510b99..101ef9e758 100644 --- a/src/applications/pholio/controller/PholioInlineController.php +++ b/src/applications/pholio/controller/PholioInlineController.php @@ -2,18 +2,12 @@ final class PholioInlineController extends PholioController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { - $inline = id(new PholioTransactionComment())->load($this->id); + if ($id) { + $inline = id(new PholioTransactionComment())->load($id); if (!$inline) { return new Aphront404Response(); diff --git a/src/applications/pholio/controller/PholioInlineListController.php b/src/applications/pholio/controller/PholioInlineListController.php index 0befd5dbd2..673a55bbaa 100644 --- a/src/applications/pholio/controller/PholioInlineListController.php +++ b/src/applications/pholio/controller/PholioInlineListController.php @@ -2,19 +2,13 @@ final class PholioInlineListController extends PholioController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $image = id(new PholioImageQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$image) { return new Aphront404Response(); @@ -23,8 +17,8 @@ final class PholioInlineListController extends PholioController { $inline_comments = id(new PholioTransactionComment())->loadAllWhere( 'imageid = %d AND (transactionphid IS NOT NULL OR (authorphid = %s AND transactionphid IS NULL))', - $this->id, - $user->getPHID()); + $id, + $viewer->getPHID()); $author_phids = mpull($inline_comments, 'getAuthorPHID'); $authors = $this->loadViewerHandles($author_phids); diff --git a/src/applications/pholio/controller/PholioMockCommentController.php b/src/applications/pholio/controller/PholioMockCommentController.php index 719d2db6ef..b127d0b1da 100644 --- a/src/applications/pholio/controller/PholioMockCommentController.php +++ b/src/applications/pholio/controller/PholioMockCommentController.php @@ -2,23 +2,17 @@ final class PholioMockCommentController extends PholioController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $mock = id(new PholioMockQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needImages(true) ->executeOne(); @@ -38,7 +32,7 @@ final class PholioMockCommentController extends PholioController { $inline_comments = id(new PholioTransactionComment())->loadAllWhere( 'authorphid = %s AND transactionphid IS NULL AND imageid IN (%Ld)', - $user->getPHID(), + $viewer->getPHID(), mpull($mock->getImages(), 'getID')); if (!$inline_comments || strlen($comment)) { @@ -56,7 +50,7 @@ final class PholioMockCommentController extends PholioController { } $editor = id(new PholioMockEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect($request->isContinueRequest()) ->setIsPreview($is_preview); @@ -78,7 +72,7 @@ final class PholioMockCommentController extends PholioController { ->setMock($mock); return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setTransactionView($xaction_view) ->setIsPreview($is_preview); diff --git a/src/applications/pholio/controller/PholioMockEditController.php b/src/applications/pholio/controller/PholioMockEditController.php index 728c7b29d6..18423e0050 100644 --- a/src/applications/pholio/controller/PholioMockEditController.php +++ b/src/applications/pholio/controller/PholioMockEditController.php @@ -2,26 +2,20 @@ final class PholioMockEditController extends PholioController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); - - if ($this->id) { + if ($id) { $mock = id(new PholioMockQuery()) - ->setViewer($user) + ->setViewer($viewer) ->needImages(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$mock) { @@ -35,7 +29,7 @@ final class PholioMockEditController extends PholioController { $files = mpull($mock_images, 'getFile'); $mock_images = mpull($mock_images, null, 'getFilePHID'); } else { - $mock = PholioMock::initializeNewMock($user); + $mock = PholioMock::initializeNewMock($viewer); $title = pht('Create Mock'); @@ -104,7 +98,7 @@ final class PholioMockEditController extends PholioController { $file_phids = $request->getArr('file_phids'); if ($file_phids) { $files = id(new PhabricatorFileQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs($file_phids) ->execute(); $files = mpull($files, null, 'getPHID'); @@ -219,7 +213,7 @@ final class PholioMockEditController extends PholioController { $editor = id(new PholioMockEditor()) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) - ->setActor($user); + ->setActor($viewer); $xactions = $editor->applyTransactions($mock, $xactions); @@ -230,9 +224,9 @@ final class PholioMockEditController extends PholioController { } } - if ($this->id) { + if ($id) { $submit = id(new AphrontFormSubmitControl()) - ->addCancelButton('/M'.$this->id) + ->addCancelButton('/M'.$id) ->setValue(pht('Save')); } else { $submit = id(new AphrontFormSubmitControl()) @@ -241,7 +235,7 @@ final class PholioMockEditController extends PholioController { } $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) + ->setViewer($viewer) ->setObject($mock) ->execute(); @@ -257,7 +251,7 @@ final class PholioMockEditController extends PholioController { } foreach ($display_mock_images as $mock_image) { $image_elements[] = id(new PholioUploadedImageView()) - ->setUser($user) + ->setUser($viewer) ->setImage($mock_image) ->setReplacesPHID($mock_image->getFilePHID()); } @@ -308,7 +302,7 @@ final class PholioMockEditController extends PholioController { require_celerity_resource('pholio-edit-css'); $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild($order_control) ->appendChild( id(new AphrontFormTextControl()) @@ -321,9 +315,9 @@ final class PholioMockEditController extends PholioController { ->setName('description') ->setValue($v_desc) ->setLabel(pht('Description')) - ->setUser($user)); + ->setUser($viewer)); - if ($this->id) { + if ($id) { $form->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Status')) @@ -346,11 +340,11 @@ final class PholioMockEditController extends PholioController { ->setLabel(pht('Subscribers')) ->setName('cc') ->setValue($v_cc) - ->setUser($user) + ->setUser($viewer) ->setDatasource(new PhabricatorMetaMTAMailableDatasource())) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicyObject($mock) ->setPolicies($policies) @@ -358,7 +352,7 @@ final class PholioMockEditController extends PholioController { ->setName('can_view')) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicyObject($mock) ->setPolicies($policies) diff --git a/src/applications/pholio/controller/PholioMockListController.php b/src/applications/pholio/controller/PholioMockListController.php index c4d7fb4117..b4fa17fc8a 100644 --- a/src/applications/pholio/controller/PholioMockListController.php +++ b/src/applications/pholio/controller/PholioMockListController.php @@ -2,19 +2,15 @@ final class PholioMockListController extends PholioController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PholioMockSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/pholio/controller/PholioMockViewController.php b/src/applications/pholio/controller/PholioMockViewController.php index b9084474d2..c5c6fed16c 100644 --- a/src/applications/pholio/controller/PholioMockViewController.php +++ b/src/applications/pholio/controller/PholioMockViewController.php @@ -2,8 +2,6 @@ final class PholioMockViewController extends PholioController { - private $id; - private $imageID; private $maniphestTaskPHIDs = array(); private function setManiphestTaskPHIDs($maniphest_task_phids) { @@ -18,18 +16,14 @@ final class PholioMockViewController extends PholioController { return true; } - public function willProcessRequest(array $data) { - $this->id = $data['id']; - $this->imageID = idx($data, 'imageID'); - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $image_id = $request->getURIData('imageID'); $mock = id(new PholioMockQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needImages(true) ->needInlineComments(true) ->executeOne(); @@ -44,7 +38,7 @@ final class PholioMockViewController extends PholioController { $this->setManiphestTaskPHIDs($phids); $engine = id(new PhabricatorMarkupEngine()) - ->setViewer($user); + ->setViewer($viewer); $engine->addObject($mock, PholioMock::MARKUP_FIELD_DESCRIPTION); $title = $mock->getName(); @@ -61,7 +55,7 @@ final class PholioMockViewController extends PholioController { $header = id(new PHUIHeaderView()) ->setHeader($title) - ->setUser($user) + ->setUser($viewer) ->setStatus($header_icon, $header_color, $header_name) ->setPolicyObject($mock); @@ -81,9 +75,9 @@ final class PholioMockViewController extends PholioController { $mock_view = id(new PholioMockImagesView()) ->setRequestURI($request->getRequestURI()) ->setCommentFormID($comment_form_id) - ->setUser($user) + ->setUser($viewer) ->setMock($mock) - ->setImageID($this->imageID); + ->setImageID($image_id); $this->addExtraQuicksandConfig( array('mockViewConfig' => $mock_view->getBehaviorConfig())); @@ -101,7 +95,7 @@ final class PholioMockViewController extends PholioController { ->addPropertyList($properties); $thumb_grid = id(new PholioMockThumbGridView()) - ->setUser($user) + ->setUser($viewer) ->setMock($mock); $content = array( @@ -122,15 +116,15 @@ final class PholioMockViewController extends PholioController { } private function buildActionView(PholioMock $mock) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $actions = id(new PhabricatorActionListView()) - ->setUser($user) + ->setUser($viewer) ->setObjectURI($this->getRequest()->getRequestURI()) ->setObject($mock); $can_edit = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, $mock, PhabricatorPolicyCapability::CAN_EDIT); @@ -147,7 +141,7 @@ final class PholioMockViewController extends PholioController { ->setIcon('fa-anchor') ->setName(pht('Edit Maniphest Tasks')) ->setHref("/search/attach/{$mock->getPHID()}/TASK/edge/") - ->setDisabled(!$user->isLoggedIn()) + ->setDisabled(!$viewer->isLoggedIn()) ->setWorkflow(true)); return $actions; @@ -158,25 +152,25 @@ final class PholioMockViewController extends PholioController { PhabricatorMarkupEngine $engine, PhabricatorActionListView $actions) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) - ->setUser($user) + ->setUser($viewer) ->setObject($mock) ->setActionList($actions); $properties->addProperty( pht('Author'), - $user->renderHandle($mock->getAuthorPHID())); + $viewer->renderHandle($mock->getAuthorPHID())); $properties->addProperty( pht('Created'), - phabricator_datetime($mock->getDateCreated(), $user)); + phabricator_datetime($mock->getDateCreated(), $viewer)); if ($this->getManiphestTaskPHIDs()) { $properties->addProperty( pht('Maniphest Tasks'), - $user->renderHandleList($this->getManiphestTaskPHIDs())); + $viewer->renderHandleList($this->getManiphestTaskPHIDs())); } $properties->invokeWillRenderEvent(); @@ -192,9 +186,9 @@ final class PholioMockViewController extends PholioController { } private function buildAddCommentView(PholioMock $mock, $comment_form_id) { - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); - $draft = PhabricatorDraft::newFromUserAndKey($user, $mock->getPHID()); + $draft = PhabricatorDraft::newFromUserAndKey($viewer, $mock->getPHID()); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $title = $is_serious @@ -202,7 +196,7 @@ final class PholioMockViewController extends PholioController { : pht('History Beckons'); $form = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($user) + ->setUser($viewer) ->setObjectPHID($mock->getPHID()) ->setFormID($comment_form_id) ->setDraft($draft) diff --git a/src/applications/pholio/herald/HeraldPholioMockAdapter.php b/src/applications/pholio/herald/HeraldPholioMockAdapter.php index 2c87c394e9..57fa74c3a1 100644 --- a/src/applications/pholio/herald/HeraldPholioMockAdapter.php +++ b/src/applications/pholio/herald/HeraldPholioMockAdapter.php @@ -47,28 +47,6 @@ final class HeraldPholioMockAdapter extends HeraldAdapter { } } - public function getActions($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_FLAG, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - } - } - public function getHeraldName() { return 'M'.$this->getMock()->getID(); } diff --git a/src/applications/pholio/view/PholioMockThumbGridView.php b/src/applications/pholio/view/PholioMockThumbGridView.php index 8e9d3007c5..d7d174d928 100644 --- a/src/applications/pholio/view/PholioMockThumbGridView.php +++ b/src/applications/pholio/view/PholioMockThumbGridView.php @@ -116,6 +116,7 @@ final class PholioMockThumbGridView extends AphrontView { $preview_key = PhabricatorFileThumbnailTransform::TRANSFORM_THUMBGRID; $xform = PhabricatorFileTransform::getTransformByKey($preview_key); + Javelin::initBehavior('phabricator-tooltips'); $attributes = array( 'class' => 'pholio-mock-thumb-grid-image', @@ -161,11 +162,13 @@ final class PholioMockThumbGridView extends AphrontView { return javelin_tag( 'a', array( - 'sigil' => 'mock-thumbnail', + 'sigil' => 'mock-thumbnail has-tooltip', 'class' => implode(' ', $classes), 'href' => '#', 'meta' => array( 'imageID' => $image->getID(), + 'tip' => $image->getName(), + 'align' => 'N', ), ), array( diff --git a/src/applications/phortune/controller/PhortuneAccountEditController.php b/src/applications/phortune/controller/PhortuneAccountEditController.php index 7847420549..f51f1293d9 100644 --- a/src/applications/phortune/controller/PhortuneAccountEditController.php +++ b/src/applications/phortune/controller/PhortuneAccountEditController.php @@ -2,20 +2,14 @@ final class PhortuneAccountEditController extends PhortuneController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $account = id(new PhortuneAccountQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/phortune/controller/PhortuneAccountListController.php b/src/applications/phortune/controller/PhortuneAccountListController.php index 8613cbda4d..0de082fa01 100644 --- a/src/applications/phortune/controller/PhortuneAccountListController.php +++ b/src/applications/phortune/controller/PhortuneAccountListController.php @@ -2,9 +2,8 @@ final class PhortuneAccountListController extends PhortuneController { - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $accounts = id(new PhortuneAccountQuery()) ->setViewer($viewer) diff --git a/src/applications/phortune/controller/PhortuneCartAcceptController.php b/src/applications/phortune/controller/PhortuneCartAcceptController.php index 3db7467290..cb53e66f50 100644 --- a/src/applications/phortune/controller/PhortuneCartAcceptController.php +++ b/src/applications/phortune/controller/PhortuneCartAcceptController.php @@ -3,15 +3,9 @@ final class PhortuneCartAcceptController extends PhortuneCartController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); // You must control the merchant to accept orders. $authority = $this->loadMerchantAuthority(); @@ -21,7 +15,7 @@ final class PhortuneCartAcceptController $cart = id(new PhortuneCartQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->withMerchantPHIDs(array($authority->getPHID())) ->needPurchases(true) ->executeOne(); diff --git a/src/applications/phortune/controller/PhortuneCartCancelController.php b/src/applications/phortune/controller/PhortuneCartCancelController.php index 3aedceb6b0..c4a26c0d00 100644 --- a/src/applications/phortune/controller/PhortuneCartCancelController.php +++ b/src/applications/phortune/controller/PhortuneCartCancelController.php @@ -3,23 +3,16 @@ final class PhortuneCartCancelController extends PhortuneCartController { - private $id; - private $action; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - $this->action = $data['action']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $action = $request->getURIData('action'); $authority = $this->loadMerchantAuthority(); $cart_query = id(new PhortuneCartQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needPurchases(true); if ($authority) { @@ -31,7 +24,7 @@ final class PhortuneCartCancelController return new Aphront404Response(); } - switch ($this->action) { + switch ($action) { case 'cancel': // You must be able to edit the account to cancel an order. PhabricatorPolicyFilter::requireCapability( diff --git a/src/applications/phortune/controller/PhortuneCartCheckoutController.php b/src/applications/phortune/controller/PhortuneCartCheckoutController.php index 0d8e55f5c3..e22a9521fd 100644 --- a/src/applications/phortune/controller/PhortuneCartCheckoutController.php +++ b/src/applications/phortune/controller/PhortuneCartCheckoutController.php @@ -3,19 +3,13 @@ final class PhortuneCartCheckoutController extends PhortuneCartController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $cart = id(new PhortuneCartQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needPurchases(true) ->executeOne(); if (!$cart) { diff --git a/src/applications/phortune/controller/PhortuneCartUpdateController.php b/src/applications/phortune/controller/PhortuneCartUpdateController.php index ea571ccf8a..3d49611d2d 100644 --- a/src/applications/phortune/controller/PhortuneCartUpdateController.php +++ b/src/applications/phortune/controller/PhortuneCartUpdateController.php @@ -3,21 +3,15 @@ final class PhortuneCartUpdateController extends PhortuneCartController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $authority = $this->loadMerchantAuthority(); $cart_query = id(new PhortuneCartQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needPurchases(true); if ($authority) { diff --git a/src/applications/phortune/controller/PhortuneCartViewController.php b/src/applications/phortune/controller/PhortuneCartViewController.php index 9e133002f5..f4eb0d9612 100644 --- a/src/applications/phortune/controller/PhortuneCartViewController.php +++ b/src/applications/phortune/controller/PhortuneCartViewController.php @@ -3,21 +3,15 @@ final class PhortuneCartViewController extends PhortuneCartController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $authority = $this->loadMerchantAuthority(); $query = id(new PhortuneCartQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->needPurchases(true); if ($authority) { diff --git a/src/applications/phortune/controller/PhortuneChargeListController.php b/src/applications/phortune/controller/PhortuneChargeListController.php index 85a5a0cfb2..b8edb92507 100644 --- a/src/applications/phortune/controller/PhortuneChargeListController.php +++ b/src/applications/phortune/controller/PhortuneChargeListController.php @@ -3,26 +3,19 @@ final class PhortuneChargeListController extends PhortuneController { - private $accountID; - private $queryKey; - private $account; - public function willProcessRequest(array $data) { - $this->accountID = idx($data, 'accountID'); - $this->queryKey = idx($data, 'queryKey'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); + $account_id = $request->getURIData('accountID'); $engine = new PhortuneChargeSearchEngine(); - if ($this->accountID) { + if ($account_id) { $account = id(new PhortuneAccountQuery()) ->setViewer($viewer) - ->withIDs(array($this->accountID)) + ->withIDs(array($account_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -39,7 +32,7 @@ final class PhortuneChargeListController } $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine($engine) ->setNavigation($this->buildSideNavView()); @@ -47,7 +40,7 @@ final class PhortuneChargeListController } public function buildSideNavView() { - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); diff --git a/src/applications/phortune/controller/PhortuneLandingController.php b/src/applications/phortune/controller/PhortuneLandingController.php index ddff75f9ec..2a019c5df9 100644 --- a/src/applications/phortune/controller/PhortuneLandingController.php +++ b/src/applications/phortune/controller/PhortuneLandingController.php @@ -2,18 +2,17 @@ final class PhortuneLandingController extends PhortuneController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $accounts = id(new PhortuneAccountQuery()) - ->setViewer($user) - ->withMemberPHIDs(array($user->getPHID())) + ->setViewer($viewer) + ->withMemberPHIDs(array($viewer->getPHID())) ->execute(); if (!$accounts) { $account = PhortuneAccount::createNewAccount( - $user, + $viewer, PhabricatorContentSource::newFromRequest($request)); $accounts = array($account); } diff --git a/src/applications/phortune/controller/PhortuneMerchantEditController.php b/src/applications/phortune/controller/PhortuneMerchantEditController.php index adb6e39c44..d3b396ddb0 100644 --- a/src/applications/phortune/controller/PhortuneMerchantEditController.php +++ b/src/applications/phortune/controller/PhortuneMerchantEditController.php @@ -3,20 +3,14 @@ final class PhortuneMerchantEditController extends PhortuneMerchantController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $merchant = id(new PhortuneMerchantQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/phortune/controller/PhortuneMerchantListController.php b/src/applications/phortune/controller/PhortuneMerchantListController.php index 6849393de7..48fb02195b 100644 --- a/src/applications/phortune/controller/PhortuneMerchantListController.php +++ b/src/applications/phortune/controller/PhortuneMerchantListController.php @@ -3,19 +3,16 @@ final class PhortuneMerchantListController extends PhortuneMerchantController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhortuneMerchantSearchEngine()) ->setNavigation($this->buildSideNavView()); @@ -23,7 +20,7 @@ final class PhortuneMerchantListController } public function buildSideNavView() { - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); diff --git a/src/applications/phortune/controller/PhortuneMerchantViewController.php b/src/applications/phortune/controller/PhortuneMerchantViewController.php index 2ca9f70c80..4b515c44c5 100644 --- a/src/applications/phortune/controller/PhortuneMerchantViewController.php +++ b/src/applications/phortune/controller/PhortuneMerchantViewController.php @@ -3,19 +3,13 @@ final class PhortuneMerchantViewController extends PhortuneMerchantController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $merchant = id(new PhortuneMerchantQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$merchant) { return new Aphront404Response(); diff --git a/src/applications/phortune/controller/PhortunePaymentMethodCreateController.php b/src/applications/phortune/controller/PhortunePaymentMethodCreateController.php index 6b7e55bb54..dd783d4c51 100644 --- a/src/applications/phortune/controller/PhortunePaymentMethodCreateController.php +++ b/src/applications/phortune/controller/PhortunePaymentMethodCreateController.php @@ -3,19 +3,13 @@ final class PhortunePaymentMethodCreateController extends PhortuneController { - private $accountID; - - public function willProcessRequest(array $data) { - $this->accountID = $data['accountID']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $account_id = $request->getURIData('accountID'); $account = id(new PhortuneAccountQuery()) ->setViewer($viewer) - ->withIDs(array($this->accountID)) + ->withIDs(array($account_id)) ->executeOne(); if (!$account) { return new Aphront404Response(); diff --git a/src/applications/phortune/controller/PhortunePaymentMethodDisableController.php b/src/applications/phortune/controller/PhortunePaymentMethodDisableController.php index 8f5124bdb4..4b8fb76010 100644 --- a/src/applications/phortune/controller/PhortunePaymentMethodDisableController.php +++ b/src/applications/phortune/controller/PhortunePaymentMethodDisableController.php @@ -3,19 +3,13 @@ final class PhortunePaymentMethodDisableController extends PhortuneController { - private $methodID; - - public function willProcessRequest(array $data) { - $this->methodID = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $method_id = $request->getURIData('methodID'); $method = id(new PhortunePaymentMethodQuery()) ->setViewer($viewer) - ->withIDs(array($this->methodID)) + ->withIDs(array($method_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/phortune/controller/PhortunePaymentMethodEditController.php b/src/applications/phortune/controller/PhortunePaymentMethodEditController.php index 2db514a1cf..27edd72a59 100644 --- a/src/applications/phortune/controller/PhortunePaymentMethodEditController.php +++ b/src/applications/phortune/controller/PhortunePaymentMethodEditController.php @@ -3,19 +3,13 @@ final class PhortunePaymentMethodEditController extends PhortuneController { - private $methodID; - - public function willProcessRequest(array $data) { - $this->methodID = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $method_id = $request->getURIData('id'); $method = id(new PhortunePaymentMethodQuery()) ->setViewer($viewer) - ->withIDs(array($this->methodID)) + ->withIDs(array($method_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/phortune/controller/PhortuneProductListController.php b/src/applications/phortune/controller/PhortuneProductListController.php index 8a1181b33e..a82effa6d4 100644 --- a/src/applications/phortune/controller/PhortuneProductListController.php +++ b/src/applications/phortune/controller/PhortuneProductListController.php @@ -2,15 +2,14 @@ final class PhortuneProductListController extends PhabricatorController { - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); $pager = new AphrontCursorPagerView(); $pager->readFromRequest($request); $query = id(new PhortuneProductQuery()) - ->setViewer($user); + ->setViewer($viewer); $products = $query->executeWithCursorPager($pager); @@ -27,7 +26,7 @@ final class PhortuneProductListController extends PhabricatorController { ->setIcon('fa-plus-square')); $product_list = id(new PHUIObjectItemListView()) - ->setUser($user) + ->setUser($viewer) ->setNoDataString(pht('No products.')); foreach ($products as $product) { diff --git a/src/applications/phortune/controller/PhortuneProductViewController.php b/src/applications/phortune/controller/PhortuneProductViewController.php index 02426f07ca..73d120bfd9 100644 --- a/src/applications/phortune/controller/PhortuneProductViewController.php +++ b/src/applications/phortune/controller/PhortuneProductViewController.php @@ -2,19 +2,13 @@ final class PhortuneProductViewController extends PhortuneController { - private $productID; - - public function willProcessRequest(array $data) { - $this->productID = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $product = id(new PhortuneProductQuery()) - ->setViewer($user) - ->withIDs(array($this->productID)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$product) { return new Aphront404Response(); @@ -28,7 +22,7 @@ final class PhortuneProductViewController extends PhortuneController { $edit_uri = $this->getApplicationURI('product/edit/'.$product->getID().'/'); $actions = id(new PhabricatorActionListView()) - ->setUser($user) + ->setUser($viewer) ->setObjectURI($request->getRequestURI()); $crumbs = $this->buildApplicationCrumbs(); @@ -40,7 +34,7 @@ final class PhortuneProductViewController extends PhortuneController { $request->getRequestURI()); $properties = id(new PHUIPropertyListView()) - ->setUser($user) + ->setUser($viewer) ->setActionList($actions) ->addProperty( pht('Price'), diff --git a/src/applications/phortune/controller/PhortuneProviderActionController.php b/src/applications/phortune/controller/PhortuneProviderActionController.php index b856b67d97..52d5453f42 100644 --- a/src/applications/phortune/controller/PhortuneProviderActionController.php +++ b/src/applications/phortune/controller/PhortuneProviderActionController.php @@ -3,14 +3,8 @@ final class PhortuneProviderActionController extends PhortuneController { - private $id; private $action; - public function willProcessRequest(array $data) { - $this->id = $data['id']; - $this->setAction($data['action']); - } - public function setAction($action) { $this->action = $action; return $this; @@ -20,13 +14,14 @@ final class PhortuneProviderActionController return $this->action; } - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); + $this->setAction($request->getURIData('action')); $provider_config = id(new PhortunePaymentProviderConfigQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->executeOne(); if (!$provider_config) { return new Aphront404Response(); diff --git a/src/applications/phortune/controller/PhortuneProviderDisableController.php b/src/applications/phortune/controller/PhortuneProviderDisableController.php index e398cbc886..03236b54bc 100644 --- a/src/applications/phortune/controller/PhortuneProviderDisableController.php +++ b/src/applications/phortune/controller/PhortuneProviderDisableController.php @@ -3,19 +3,13 @@ final class PhortuneProviderDisableController extends PhortuneMerchantController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $provider_config = id(new PhortunePaymentProviderConfigQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/phortune/controller/PhortuneProviderEditController.php b/src/applications/phortune/controller/PhortuneProviderEditController.php index 3ed97b5a4b..f956c41d68 100644 --- a/src/applications/phortune/controller/PhortuneProviderEditController.php +++ b/src/applications/phortune/controller/PhortuneProviderEditController.php @@ -3,20 +3,14 @@ final class PhortuneProviderEditController extends PhortuneMerchantController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $provider_config = id(new PhortunePaymentProviderConfigQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/phortune/controller/PhortuneSubscriptionListController.php b/src/applications/phortune/controller/PhortuneSubscriptionListController.php index 4fbdb804c3..469960f4bc 100644 --- a/src/applications/phortune/controller/PhortuneSubscriptionListController.php +++ b/src/applications/phortune/controller/PhortuneSubscriptionListController.php @@ -3,29 +3,21 @@ final class PhortuneSubscriptionListController extends PhortuneController { - private $accountID; - private $merchantID; - private $queryKey; - private $merchant; private $account; - public function willProcessRequest(array $data) { - $this->merchantID = idx($data, 'merchantID'); - $this->accountID = idx($data, 'accountID'); - $this->queryKey = idx($data, 'queryKey'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $querykey = $request->getURIData('queryKey'); + $merchant_id = $request->getURIData('merchantID'); + $account_id = $request->getURIData('accountID'); $engine = new PhortuneSubscriptionSearchEngine(); - if ($this->merchantID) { + if ($merchant_id) { $merchant = id(new PhortuneMerchantQuery()) ->setViewer($viewer) - ->withIDs(array($this->merchantID)) + ->withIDs(array($merchant_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -38,10 +30,10 @@ final class PhortuneSubscriptionListController $this->merchant = $merchant; $viewer->grantAuthority($merchant); $engine->setMerchant($merchant); - } else if ($this->accountID) { + } else if ($account_id) { $account = id(new PhortuneAccountQuery()) ->setViewer($viewer) - ->withIDs(array($this->accountID)) + ->withIDs(array($account_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -58,7 +50,7 @@ final class PhortuneSubscriptionListController } $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine($engine) ->setNavigation($this->buildSideNavView()); @@ -66,7 +58,7 @@ final class PhortuneSubscriptionListController } public function buildSideNavView() { - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); diff --git a/src/applications/phortune/query/PhortuneChargeSearchEngine.php b/src/applications/phortune/query/PhortuneChargeSearchEngine.php index 598614d885..0d6c2cfd59 100644 --- a/src/applications/phortune/query/PhortuneChargeSearchEngine.php +++ b/src/applications/phortune/query/PhortuneChargeSearchEngine.php @@ -130,6 +130,6 @@ final class PhortuneChargeSearchEngine $result = new PhabricatorApplicationSearchResultView(); $result->setTable($table); - return $table; + return $result; } } diff --git a/src/applications/phpast/controller/PhabricatorXHPASTViewFrameController.php b/src/applications/phpast/controller/PhabricatorXHPASTViewFrameController.php index 560d4203a0..2c5a43687c 100644 --- a/src/applications/phpast/controller/PhabricatorXHPASTViewFrameController.php +++ b/src/applications/phpast/controller/PhabricatorXHPASTViewFrameController.php @@ -3,18 +3,12 @@ final class PhabricatorXHPASTViewFrameController extends PhabricatorXHPASTViewController { - private $id; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $id = $this->id; + public function handleRequest(AphrontRequest $request) { + $id = $request->getURIData('id'); return $this->buildStandardPageResponse( phutil_tag( diff --git a/src/applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php b/src/applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php index a21bb30b68..de446b5e44 100644 --- a/src/applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php +++ b/src/applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php @@ -3,18 +3,12 @@ final class PhabricatorXHPASTViewFramesetController extends PhabricatorXHPASTViewController { - private $id; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $id = $this->id; + public function handleRequest(AphrontRequest $request) { + $id = $request->getURIData('id'); $response = new AphrontWebpageResponse(); $response->setFrameable(true); diff --git a/src/applications/phpast/controller/PhabricatorXHPASTViewInputController.php b/src/applications/phpast/controller/PhabricatorXHPASTViewInputController.php index 48ba6afc33..6e1fd87db7 100644 --- a/src/applications/phpast/controller/PhabricatorXHPASTViewInputController.php +++ b/src/applications/phpast/controller/PhabricatorXHPASTViewInputController.php @@ -3,7 +3,7 @@ final class PhabricatorXHPASTViewInputController extends PhabricatorXHPASTViewPanelController { - public function processRequest() { + public function handleRequest(AphrontRequest $request) { $input = $this->getStorageTree()->getInput(); return $this->buildXHPASTViewPanelResponse($input); } diff --git a/src/applications/phpast/controller/PhabricatorXHPASTViewRunController.php b/src/applications/phpast/controller/PhabricatorXHPASTViewRunController.php index f5a79a4b28..dd9cf85433 100644 --- a/src/applications/phpast/controller/PhabricatorXHPASTViewRunController.php +++ b/src/applications/phpast/controller/PhabricatorXHPASTViewRunController.php @@ -3,10 +3,8 @@ final class PhabricatorXHPASTViewRunController extends PhabricatorXHPASTViewController { - public function processRequest() { - - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); if ($request->isFormPost()) { $source = $request->getStr('source'); @@ -24,7 +22,7 @@ final class PhabricatorXHPASTViewRunController $storage_tree = new PhabricatorXHPASTViewParseTree(); $storage_tree->setInput($source); $storage_tree->setStdout($stdout); - $storage_tree->setAuthorPHID($user->getPHID()); + $storage_tree->setAuthorPHID($viewer->getPHID()); $storage_tree->save(); return id(new AphrontRedirectResponse()) @@ -32,7 +30,7 @@ final class PhabricatorXHPASTViewRunController } $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel(pht('Source')) diff --git a/src/applications/phpast/controller/PhabricatorXHPASTViewStreamController.php b/src/applications/phpast/controller/PhabricatorXHPASTViewStreamController.php index 4a098f1591..3fe1046f10 100644 --- a/src/applications/phpast/controller/PhabricatorXHPASTViewStreamController.php +++ b/src/applications/phpast/controller/PhabricatorXHPASTViewStreamController.php @@ -3,7 +3,7 @@ final class PhabricatorXHPASTViewStreamController extends PhabricatorXHPASTViewPanelController { - public function processRequest() { + public function handleRequest(AphrontRequest $request) { $storage = $this->getStorageTree(); $input = $storage->getInput(); $stdout = $storage->getStdout(); diff --git a/src/applications/phpast/controller/PhabricatorXHPASTViewTreeController.php b/src/applications/phpast/controller/PhabricatorXHPASTViewTreeController.php index 7da285f121..1b4eec6441 100644 --- a/src/applications/phpast/controller/PhabricatorXHPASTViewTreeController.php +++ b/src/applications/phpast/controller/PhabricatorXHPASTViewTreeController.php @@ -7,7 +7,7 @@ final class PhabricatorXHPASTViewTreeController return true; } - public function processRequest() { + public function handleRequest(AphrontRequest $request) { $storage = $this->getStorageTree(); $input = $storage->getInput(); $stdout = $storage->getStdout(); diff --git a/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php b/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php index 48f72d57db..575d4b3dd8 100644 --- a/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php +++ b/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php @@ -48,31 +48,6 @@ final class PhrictionDocumentHeraldAdapter extends HeraldAdapter { } } - public function getActions($rule_type) { - switch ($rule_type) { - case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_EMAIL, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL: - return array_merge( - array( - self::ACTION_ADD_CC, - self::ACTION_REMOVE_CC, - self::ACTION_EMAIL, - self::ACTION_FLAG, - self::ACTION_NOTHING, - ), - parent::getActions($rule_type)); - } - } - - public function getHeraldName() { return pht('Wiki Document %d', $this->getDocument()->getID()); } diff --git a/src/applications/ponder/application/PhabricatorPonderApplication.php b/src/applications/ponder/application/PhabricatorPonderApplication.php index 999580e90b..11e90dc274 100644 --- a/src/applications/ponder/application/PhabricatorPonderApplication.php +++ b/src/applications/ponder/application/PhabricatorPonderApplication.php @@ -48,17 +48,29 @@ final class PhabricatorPonderApplication extends PhabricatorApplication { public function getRoutes() { return array( - '/Q(?P[1-9]\d*)' => 'PonderQuestionViewController', + '/Q(?P[1-9]\d*)' + => 'PonderQuestionViewController', '/ponder/' => array( - '(?:query/(?P[^/]+)/)?' => 'PonderQuestionListController', - 'answer/add/' => 'PonderAnswerSaveController', - 'answer/edit/(?P\d+)/' => 'PonderAnswerEditController', - 'answer/comment/(?P\d+)/' => 'PonderAnswerCommentController', - 'answer/history/(?P\d+)/' => 'PonderAnswerHistoryController', - 'question/edit/(?:(?P\d+)/)?' => 'PonderQuestionEditController', - 'question/comment/(?P\d+)/' => 'PonderQuestionCommentController', - 'question/history/(?P\d+)/' => 'PonderQuestionHistoryController', - 'preview/' => 'PhabricatorMarkupPreviewController', + '(?:query/(?P[^/]+)/)?' + => 'PonderQuestionListController', + 'answer/add/' + => 'PonderAnswerSaveController', + 'answer/edit/(?P\d+)/' + => 'PonderAnswerEditController', + 'answer/comment/(?P\d+)/' + => 'PonderAnswerCommentController', + 'answer/history/(?P\d+)/' + => 'PonderAnswerHistoryController', + 'question/edit/(?:(?P\d+)/)?' + => 'PonderQuestionEditController', + 'question/create/' + => 'PonderQuestionEditController', + 'question/comment/(?P\d+)/' + => 'PonderQuestionCommentController', + 'question/history/(?P\d+)/' + => 'PonderQuestionHistoryController', + 'preview/' + => 'PhabricatorMarkupPreviewController', 'question/(?Popen|close)/(?P[1-9]\d*)/' => 'PonderQuestionStatusController', 'vote/' => 'PonderVoteSaveController', @@ -79,6 +91,19 @@ final class PhabricatorPonderApplication extends PhabricatorApplication { ); } + protected function getCustomCapabilities() { + return array( + PonderQuestionDefaultViewCapability::CAPABILITY => array( + 'template' => PonderQuestionPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, + ), + PonderQuestionDefaultEditCapability::CAPABILITY => array( + 'template' => PonderQuestionPHIDType::TYPECONST, + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, + ), + ); + } + public function getApplicationSearchDocumentTypes() { return array( PonderQuestionPHIDType::TYPECONST, diff --git a/src/applications/ponder/capability/PonderQuestionDefaultEditCapability.php b/src/applications/ponder/capability/PonderQuestionDefaultEditCapability.php new file mode 100644 index 0000000000..2f9ca73b0f --- /dev/null +++ b/src/applications/ponder/capability/PonderQuestionDefaultEditCapability.php @@ -0,0 +1,12 @@ +getID(); $crumbs = $this->buildApplicationCrumbs(); + $crumbs->setBorder(true); $crumbs->addTextCrumb("Q{$qid}", "/Q{$qid}"); $crumbs->addTextCrumb("A{$aid}", "/Q{$qid}#{$aid}"); $crumbs->addTextCrumb(pht('History')); diff --git a/src/applications/ponder/controller/PonderController.php b/src/applications/ponder/controller/PonderController.php index 30bd412504..a14d70c773 100644 --- a/src/applications/ponder/controller/PonderController.php +++ b/src/applications/ponder/controller/PonderController.php @@ -2,12 +2,16 @@ abstract class PonderController extends PhabricatorController { - protected function buildSideNavView() { + protected function buildSideNavView($for_app = false) { $user = $this->getRequest()->getUser(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); + if ($for_app) { + $nav->addFilter('question/create/', pht('Ask Question')); + } + id(new PonderQuestionSearchEngine()) ->setViewer($user) ->addNavigationItems($nav->getMenu()); @@ -17,13 +21,18 @@ abstract class PonderController extends PhabricatorController { return $nav; } + public function buildApplicationMenu() { + return $this->buildSideNavView($for_app = true)->getMenu(); + } + protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); + $href = $this->getApplicationURI('question/create/'); $crumbs ->addAction( id(new PHUIListItemView()) - ->setName(pht('Create Question')) - ->setHref('/ponder/question/edit/') + ->setName(pht('Ask Question')) + ->setHref($href) ->setIcon('fa-plus-square')); return $crumbs; diff --git a/src/applications/ponder/controller/PonderQuestionEditController.php b/src/applications/ponder/controller/PonderQuestionEditController.php index 36c723445d..cf8b5f9de1 100644 --- a/src/applications/ponder/controller/PonderQuestionEditController.php +++ b/src/applications/ponder/controller/PonderQuestionEditController.php @@ -3,12 +3,12 @@ final class PonderQuestionEditController extends PonderController { public function handleRequest(AphrontRequest $request) { - $user = $request->getViewer(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); if ($id) { $question = id(new PonderQuestionQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -24,17 +24,15 @@ final class PonderQuestionEditController extends PonderController { PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $v_projects = array_reverse($v_projects); } else { - $question = id(new PonderQuestion()) - ->setStatus(PonderQuestionStatus::STATUS_OPEN) - ->setAuthorPHID($user->getPHID()) - ->setVoteCount(0) - ->setAnswerCount(0) - ->setHeat(0.0); + $question = PonderQuestion::initializeNewQuestion($viewer); $v_projects = array(); } $v_title = $question->getTitle(); $v_content = $question->getContent(); + $v_view = $question->getViewPolicy(); + $v_edit = $question->getEditPolicy(); + $v_space = $question->getSpacePHID(); $errors = array(); $e_title = true; @@ -42,6 +40,9 @@ final class PonderQuestionEditController extends PonderController { $v_title = $request->getStr('title'); $v_content = $request->getStr('content'); $v_projects = $request->getArr('projects'); + $v_view = $request->getStr('viewPolicy'); + $v_edit = $request->getStr('editPolicy'); + $v_space = $request->getStr('spacePHID'); $len = phutil_utf8_strlen($v_title); if ($len < 1) { @@ -64,6 +65,18 @@ final class PonderQuestionEditController extends PonderController { ->setTransactionType(PonderQuestionTransaction::TYPE_CONTENT) ->setNewValue($v_content); + $xactions[] = id(clone $template) + ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) + ->setNewValue($v_view); + + $xactions[] = id(clone $template) + ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) + ->setNewValue($v_edit); + + $xactions[] = id(clone $template) + ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) + ->setNewValue($v_space); + $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $xactions[] = id(new PonderQuestionTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) @@ -71,7 +84,7 @@ final class PonderQuestionEditController extends PonderController { ->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PonderQuestionEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true); @@ -82,8 +95,13 @@ final class PonderQuestionEditController extends PonderController { } } + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($viewer) + ->setObject($question) + ->execute(); + $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Question')) @@ -92,12 +110,27 @@ final class PonderQuestionEditController extends PonderController { ->setError($e_title)) ->appendChild( id(new PhabricatorRemarkupControl()) - ->setUser($user) + ->setUser($viewer) ->setName('content') ->setID('content') ->setValue($v_content) ->setLabel(pht('Description')) - ->setUser($user)); + ->setUser($viewer)) + ->appendControl( + id(new AphrontFormPolicyControl()) + ->setName('viewPolicy') + ->setPolicyObject($question) + ->setSpacePHID($v_space) + ->setPolicies($policies) + ->setValue($v_view) + ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)) + ->appendControl( + id(new AphrontFormPolicyControl()) + ->setName('editPolicy') + ->setPolicyObject($question) + ->setPolicies($policies) + ->setValue($v_edit) + ->setCapability(PhabricatorPolicyCapability::CAN_EDIT)); $form->appendControl( id(new AphrontFormTokenizerControl()) @@ -106,7 +139,7 @@ final class PonderQuestionEditController extends PonderController { ->setValue($v_projects) ->setDatasource(new PhabricatorProjectDatasource())); - $form ->appendChild( + $form->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($this->getApplicationURI()) ->setValue(pht('Ask Away!'))); diff --git a/src/applications/ponder/controller/PonderQuestionHistoryController.php b/src/applications/ponder/controller/PonderQuestionHistoryController.php index 3d62a7fcb6..91ded8c094 100644 --- a/src/applications/ponder/controller/PonderQuestionHistoryController.php +++ b/src/applications/ponder/controller/PonderQuestionHistoryController.php @@ -22,6 +22,7 @@ final class PonderQuestionHistoryController extends PonderController { $qid = $question->getID(); $crumbs = $this->buildApplicationCrumbs(); + $crumbs->setBorder(true); $crumbs->addTextCrumb("Q{$qid}", "/Q{$qid}"); $crumbs->addTextCrumb(pht('History')); diff --git a/src/applications/ponder/controller/PonderQuestionViewController.php b/src/applications/ponder/controller/PonderQuestionViewController.php index d2b5a53826..51f165b408 100644 --- a/src/applications/ponder/controller/PonderQuestionViewController.php +++ b/src/applications/ponder/controller/PonderQuestionViewController.php @@ -3,11 +3,11 @@ final class PonderQuestionViewController extends PonderController { public function handleRequest(AphrontRequest $request) { - $user = $request->getViewer(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $question = id(new PonderQuestionQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->needAnswers(true) ->needViewerVotes(true) @@ -16,15 +16,15 @@ final class PonderQuestionViewController extends PonderController { return new Aphront404Response(); } - $question->attachVotes($user->getPHID()); + $question->attachVotes($viewer->getPHID()); $question_xactions = $this->buildQuestionTransactions($question); $answers = $this->buildAnswers($question->getAnswers()); $authors = mpull($question->getAnswers(), null, 'getAuthorPHID'); - if (isset($authors[$user->getPHID()])) { + if (isset($authors[$viewer->getPHID()])) { $answer_add_panel = id(new PHUIInfoView()) - ->setSeverity(PHUIInfoView::SEVERITY_NODATA) + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->appendChild( pht( 'You have already answered this question. You can not answer '. @@ -33,12 +33,14 @@ final class PonderQuestionViewController extends PonderController { $answer_add_panel = new PonderAddAnswerView(); $answer_add_panel ->setQuestion($question) - ->setUser($user) + ->setUser($viewer) ->setActionURI('/ponder/answer/add/'); } - $header = id(new PHUIHeaderView()) - ->setHeader($question->getTitle()); + $header = new PHUIHeaderView(); + $header->setHeader($question->getTitle()); + $header->setUser($viewer); + $header->setPolicyObject($question); if ($question->getStatus() == PonderQuestionStatus::STATUS_OPEN) { $header->setStatus('fa-square-o', 'bluegrey', pht('Open')); @@ -56,13 +58,22 @@ final class PonderQuestionViewController extends PonderController { $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); $crumbs->addTextCrumb('Q'.$id, '/Q'.$id); - return $this->buildApplicationPage( + $ponder_view = phutil_tag( + 'div', + array( + 'class' => 'ponder-question-view', + ), array( $crumbs, $object_box, $question_xactions, $answers, $answer_add_panel, + )); + + return $this->buildApplicationPage( + array( + $ponder_view, ), array( 'title' => 'Q'.$question->getID().' '.$question->getTitle(), @@ -73,9 +84,8 @@ final class PonderQuestionViewController extends PonderController { } private function buildActionListView(PonderQuestion $question) { + $viewer = $this->getViewer(); $request = $this->getRequest(); - $viewer = $request->getUser(); - $id = $question->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( @@ -84,7 +94,7 @@ final class PonderQuestionViewController extends PonderController { PhabricatorPolicyCapability::CAN_EDIT); $view = id(new PhabricatorActionListView()) - ->setUser($request->getUser()) + ->setUser($viewer) ->setObject($question) ->setObjectURI($request->getRequestURI()); @@ -128,16 +138,12 @@ final class PonderQuestionViewController extends PonderController { PonderQuestion $question, PhabricatorActionListView $actions) { - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($question) ->setActionList($actions); - $view->addProperty( - pht('Status'), - PonderQuestionStatus::getQuestionStatusFullName($question->getStatus())); - $view->addProperty( pht('Author'), $viewer->renderHandle($question->getAuthorPHID())); @@ -207,8 +213,7 @@ final class PonderQuestionViewController extends PonderController { * standard fashion. This is necessary to scale this application. */ private function buildAnswers(array $answers) { - $request = $this->getRequest(); - $viewer = $request->getUser(); + $viewer = $this->getViewer(); $out = array(); @@ -281,9 +286,8 @@ final class PonderQuestionViewController extends PonderController { } private function buildAnswerActions(PonderAnswer $answer) { + $viewer = $this->getViewer(); $request = $this->getRequest(); - $viewer = $request->getUser(); - $id = $answer->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( @@ -292,7 +296,7 @@ final class PonderQuestionViewController extends PonderController { PhabricatorPolicyCapability::CAN_EDIT); $view = id(new PhabricatorActionListView()) - ->setUser($request->getUser()) + ->setUser($viewer) ->setObject($answer) ->setObjectURI($request->getRequestURI()); @@ -317,7 +321,7 @@ final class PonderQuestionViewController extends PonderController { PonderAnswer $answer, PhabricatorActionListView $actions) { - $viewer = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($answer) @@ -364,7 +368,7 @@ final class PonderQuestionViewController extends PonderController { $hide_id = celerity_generate_unique_node_id(); Javelin::initBehavior('phabricator-reveal-content'); - require_celerity_resource('ponder-comment-table-css'); + require_celerity_resource('ponder-view-css'); $show = phutil_tag( 'div', @@ -387,6 +391,7 @@ final class PonderQuestionViewController extends PonderController { $hide = phutil_tag( 'div', array( + 'class' => 'ponder-comments-view', 'id' => $hide_id, 'style' => 'display: none', ), diff --git a/src/applications/ponder/editor/PonderQuestionEditor.php b/src/applications/ponder/editor/PonderQuestionEditor.php index 9dbe58cb0e..af984f4b4d 100644 --- a/src/applications/ponder/editor/PonderQuestionEditor.php +++ b/src/applications/ponder/editor/PonderQuestionEditor.php @@ -66,6 +66,10 @@ final class PonderQuestionEditor $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; + $types[] = PhabricatorTransactions::TYPE_SPACE; + $types[] = PonderQuestionTransaction::TYPE_TITLE; $types[] = PonderQuestionTransaction::TYPE_CONTENT; $types[] = PonderQuestionTransaction::TYPE_ANSWERS; diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php index 78bc42a7d3..74d8230327 100644 --- a/src/applications/ponder/query/PonderQuestionQuery.php +++ b/src/applications/ponder/query/PonderQuestionQuery.php @@ -8,6 +8,8 @@ final class PonderQuestionQuery private $authorPHIDs; private $answererPHIDs; + private $needProjectPHIDs; + private $status = 'status-any'; const STATUS_ANY = 'status-any'; @@ -52,6 +54,11 @@ final class PonderQuestionQuery return $this; } + public function needProjectPHIDs($need_projects) { + $this->needProjectPHIDs = $need_projects; + return $this; + } + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); @@ -109,6 +116,9 @@ final class PonderQuestionQuery } protected function willFilterPage(array $questions) { + + $phids = mpull($questions, 'getPHID'); + if ($this->needAnswers) { $aquery = id(new PonderAnswerQuery()) ->setViewer($this->getViewer()) @@ -133,7 +143,7 @@ final class PonderQuestionQuery $etype = PonderQuestionHasVotingUserEdgeType::EDGECONST; $edges = id(new PhabricatorEdgeQuery()) - ->withSourcePHIDs(mpull($questions, 'getPHID')) + ->withSourcePHIDs($phids) ->withDestinationPHIDs(array($viewer_phid)) ->withEdgeTypes(array($etype)) ->needEdgeData(true) @@ -148,6 +158,22 @@ final class PonderQuestionQuery } } + if ($this->needProjectPHIDs) { + $edge_query = id(new PhabricatorEdgeQuery()) + ->withSourcePHIDs($phids) + ->withEdgeTypes( + array( + PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, + )); + $edge_query->execute(); + + foreach ($questions as $question) { + $project_phids = $edge_query->getDestinationPHIDs( + array($question->getPHID())); + $question->attachProjectPHIDs($project_phids); + } + } + return $questions; } diff --git a/src/applications/ponder/query/PonderQuestionSearchEngine.php b/src/applications/ponder/query/PonderQuestionSearchEngine.php index 885e39bbf9..1b475c7b58 100644 --- a/src/applications/ponder/query/PonderQuestionSearchEngine.php +++ b/src/applications/ponder/query/PonderQuestionSearchEngine.php @@ -12,7 +12,8 @@ final class PonderQuestionSearchEngine } public function newQuery() { - return new PonderQuestionQuery(); + return id(new PonderQuestionQuery()) + ->needProjectPHIDs(true); } protected function buildQueryFromParameters(array $map) { @@ -112,6 +113,18 @@ final class PonderQuestionSearchEngine $viewer = $this->requireViewer(); + $proj_phids = array(); + foreach ($questions as $question) { + foreach ($question->getProjectPHIDs() as $project_phid) { + $proj_phids[] = $project_phid; + } + } + + $proj_handles = id(new PhabricatorHandleQuery()) + ->setViewer($viewer) + ->withPHIDs($proj_phids) + ->execute(); + $view = id(new PHUIObjectItemListView()) ->setUser($viewer); @@ -129,6 +142,10 @@ final class PonderQuestionSearchEngine $item->setObject($question); $item->setStatusIcon($icon.' '.$color, $full_status); + $project_handles = array_select_keys( + $proj_handles, + $question->getProjectPHIDs()); + $created_date = phabricator_date($question->getDateCreated(), $viewer); $item->addIcon('none', $created_date); $item->addByline( @@ -139,6 +156,14 @@ final class PonderQuestionSearchEngine $item->addAttribute( pht('%d Answer(s)', $question->getAnswerCount())); + if ($project_handles) { + $item->addAttribute( + id(new PHUIHandleTagListView()) + ->setLimit(4) + ->setSlim(true) + ->setHandles($project_handles)); + } + $view->addItem($item); } diff --git a/src/applications/ponder/storage/PonderAnswer.php b/src/applications/ponder/storage/PonderAnswer.php index 57e0e2ea21..10ada70c5e 100644 --- a/src/applications/ponder/storage/PonderAnswer.php +++ b/src/applications/ponder/storage/PonderAnswer.php @@ -18,6 +18,7 @@ final class PonderAnswer extends PonderDAO protected $content; protected $contentSource; + protected $mailKey; protected $voteCount; private $vote; @@ -71,6 +72,7 @@ final class PonderAnswer extends PonderDAO self::CONFIG_COLUMN_SCHEMA => array( 'voteCount' => 'sint32', 'content' => 'text', + 'mailKey' => 'bytes20', // T6203/NULLABILITY // This should always exist. @@ -113,6 +115,13 @@ final class PonderAnswer extends PonderDAO return self::MARKUP_FIELD_CONTENT; } + public function save() { + if (!$this->getMailKey()) { + $this->setMailKey(Filesystem::readRandomCharacters(20)); + } + return parent::save(); + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/ponder/storage/PonderQuestion.php b/src/applications/ponder/storage/PonderQuestion.php index 1568c59245..f2d81c4838 100644 --- a/src/applications/ponder/storage/PonderQuestion.php +++ b/src/applications/ponder/storage/PonderQuestion.php @@ -10,7 +10,8 @@ final class PonderQuestion extends PonderDAO PhabricatorPolicyInterface, PhabricatorTokenReceiverInterface, PhabricatorProjectInterface, - PhabricatorDestructibleInterface { + PhabricatorDestructibleInterface, + PhabricatorSpacesInterface { const MARKUP_FIELD_CONTENT = 'markup:content'; @@ -21,6 +22,9 @@ final class PonderQuestion extends PonderDAO protected $status; protected $content; protected $contentSource; + protected $viewPolicy; + protected $editPolicy; + protected $spacePHID; protected $voteCount; protected $answerCount; @@ -31,6 +35,30 @@ final class PonderQuestion extends PonderDAO private $vote; private $comments; + private $projectPHIDs = self::ATTACHABLE; + + public static function initializeNewQuestion(PhabricatorUser $actor) { + $app = id(new PhabricatorApplicationQuery()) + ->setViewer($actor) + ->withClasses(array('PhabricatorPonderApplication')) + ->executeOne(); + + $view_policy = $app->getPolicy( + PonderQuestionDefaultViewCapability::CAPABILITY); + $edit_policy = $app->getPolicy( + PonderQuestionDefaultEditCapability::CAPABILITY); + + return id(new PonderQuestion()) + ->setAuthorPHID($actor->getPHID()) + ->setViewPolicy($view_policy) + ->setEditPolicy($edit_policy) + ->setStatus(PonderQuestionStatus::STATUS_OPEN) + ->setVoteCount(0) + ->setAnswerCount(0) + ->setHeat(0.0) + ->setSpacePHID($actor->getDefaultSpacePHID()); + } + protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, @@ -141,6 +169,15 @@ final class PonderQuestion extends PonderDAO return $this->answers; } + public function getProjectPHIDs() { + return $this->assertAttached($this->projectPHIDs); + } + + public function attachProjectPHIDs(array $phids) { + $this->projectPHIDs = $phids; + return $this; + } + public function getMarkupField() { return self::MARKUP_FIELD_CONTENT; } @@ -234,15 +271,12 @@ final class PonderQuestion extends PonderDAO } public function getPolicy($capability) { - $policy = PhabricatorPolicies::POLICY_NOONE; - switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: - $policy = PhabricatorPolicies::POLICY_USER; - break; + return $this->getViewPolicy(); + case PhabricatorPolicyCapability::CAN_EDIT: + return $this->getEditPolicy(); } - - return $policy; } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { @@ -298,4 +332,12 @@ final class PonderQuestion extends PonderDAO $this->saveTransaction(); } + +/* -( PhabricatorSpacesInterface )----------------------------------------- */ + + + public function getSpacePHID() { + return $this->spacePHID; + } + } diff --git a/src/applications/ponder/view/PonderVotableView.php b/src/applications/ponder/view/PonderVotableView.php index 11cbe6cde0..dbd6ba32a8 100644 --- a/src/applications/ponder/view/PonderVotableView.php +++ b/src/applications/ponder/view/PonderVotableView.php @@ -28,7 +28,7 @@ final class PonderVotableView extends AphrontView { } public function render() { - require_celerity_resource('ponder-vote-css'); + require_celerity_resource('ponder-view-css'); require_celerity_resource('javelin-behavior-ponder-votebox'); Javelin::initBehavior('ponder-votebox', array()); diff --git a/src/applications/project/herald/PhabricatorProjectAddHeraldAction.php b/src/applications/project/herald/PhabricatorProjectAddHeraldAction.php new file mode 100644 index 0000000000..5d2a348eca --- /dev/null +++ b/src/applications/project/herald/PhabricatorProjectAddHeraldAction.php @@ -0,0 +1,28 @@ +applyProjects($effect->getTarget(), $is_add = true); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorProjectDatasource(); + } + + public function renderActionDescription($value) { + return pht('Add projects: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/project/herald/PhabricatorProjectHeraldAction.php b/src/applications/project/herald/PhabricatorProjectHeraldAction.php new file mode 100644 index 0000000000..a720ebe5b0 --- /dev/null +++ b/src/applications/project/herald/PhabricatorProjectHeraldAction.php @@ -0,0 +1,125 @@ +getAdapter(); + + $allowed_types = array( + PhabricatorProjectProjectPHIDType::TYPECONST, + ); + + // Detection of "No Effect" is a bit tricky for this action, so just do it + // manually a little later on. + $current = array(); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; + $current = $adapter->loadEdgePHIDs($project_type); + + if ($is_add) { + $already = array(); + foreach ($phids as $phid) { + if (isset($current[$phid])) { + $already[$phid] = $phid; + unset($phids[$phid]); + } + } + + if ($already) { + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); + } + } else { + $already = array(); + foreach ($phids as $phid) { + if (empty($current[$phid])) { + $already[$phid] = $phid; + unset($phids[$phid]); + } + } + + if ($already) { + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); + } + } + + if (!$phids) { + return; + } + + if ($is_add) { + $kind = '+'; + } else { + $kind = '-'; + } + + $xaction = $adapter->newTransaction() + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue('edge:type', $project_type) + ->setNewValue( + array( + $kind => $phids, + )); + + $adapter->queueTransaction($xaction); + + if ($is_add) { + $this->logEffect(self::DO_ADD_PROJECTS, $phids); + } else { + $this->logEffect(self::DO_REMOVE_PROJECTS, $phids); + } + } + + protected function getActionEffectMap() { + return array( + self::DO_ADD_PROJECTS => array( + 'icon' => 'fa-briefcase', + 'color' => 'green', + 'name' => pht('Added Projects'), + ), + self::DO_REMOVE_PROJECTS => array( + 'icon' => 'fa-minus-circle', + 'color' => 'green', + 'name' => pht('Removed Projects'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_ADD_PROJECTS: + return pht( + 'Added %s project(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_REMOVE_PROJECTS: + return pht( + 'Removed %s project(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + +} diff --git a/src/applications/project/herald/PhabricatorProjectRemoveHeraldAction.php b/src/applications/project/herald/PhabricatorProjectRemoveHeraldAction.php new file mode 100644 index 0000000000..77e7071b13 --- /dev/null +++ b/src/applications/project/herald/PhabricatorProjectRemoveHeraldAction.php @@ -0,0 +1,28 @@ +applyProjects($effect->getTarget(), $is_add = false); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorProjectDatasource(); + } + + public function renderActionDescription($value) { + return pht('Remove projects: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/releeph/controller/branch/ReleephBranchAccessController.php b/src/applications/releeph/controller/branch/ReleephBranchAccessController.php index 177fb82c8f..8b675ed2da 100644 --- a/src/applications/releeph/controller/branch/ReleephBranchAccessController.php +++ b/src/applications/releeph/controller/branch/ReleephBranchAccessController.php @@ -2,21 +2,14 @@ final class ReleephBranchAccessController extends ReleephBranchController { - private $action; - private $branchID; - - public function willProcessRequest(array $data) { - $this->action = $data['action']; - $this->branchID = $data['branchID']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $action = $request->getURIData('action'); + $id = $request->getURIData('branchID'); $branch = id(new ReleephBranchQuery()) ->setViewer($viewer) - ->withIDs(array($this->branchID)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -28,7 +21,6 @@ final class ReleephBranchAccessController extends ReleephBranchController { } $this->setBranch($branch); - $action = $this->action; switch ($action) { case 'close': case 're-open': diff --git a/src/applications/releeph/controller/branch/ReleephBranchCreateController.php b/src/applications/releeph/controller/branch/ReleephBranchCreateController.php index 851724c6d9..d13383cc3b 100644 --- a/src/applications/releeph/controller/branch/ReleephBranchCreateController.php +++ b/src/applications/releeph/controller/branch/ReleephBranchCreateController.php @@ -2,19 +2,13 @@ final class ReleephBranchCreateController extends ReleephProductController { - private $productID; - - public function willProcessRequest(array $data) { - $this->productID = $data['projectID']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('projectID'); $product = id(new ReleephProductQuery()) ->setViewer($viewer) - ->withIDs(array($this->productID)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, diff --git a/src/applications/releeph/controller/branch/ReleephBranchEditController.php b/src/applications/releeph/controller/branch/ReleephBranchEditController.php index 000e9535bf..6d66f5d9d5 100644 --- a/src/applications/releeph/controller/branch/ReleephBranchEditController.php +++ b/src/applications/releeph/controller/branch/ReleephBranchEditController.php @@ -2,15 +2,9 @@ final class ReleephBranchEditController extends ReleephBranchController { - private $branchID; - - public function willProcessRequest(array $data) { - $this->branchID = $data['branchID']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('branchID'); $branch = id(new ReleephBranchQuery()) ->setViewer($viewer) @@ -19,7 +13,7 @@ final class ReleephBranchEditController extends ReleephBranchController { PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) - ->withIDs(array($this->branchID)) + ->withIDs(array($id)) ->executeOne(); if (!$branch) { return new Aphront404Response(); @@ -40,8 +34,7 @@ final class ReleephBranchEditController extends ReleephBranchController { $symbolic_name); $branch->openTransaction(); - $branch - ->setSymbolicName($symbolic_name); + $branch->setSymbolicName($symbolic_name); if ($existing_with_same_symbolic_name) { $existing_with_same_symbolic_name diff --git a/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php b/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php index 46c0b47f6c..a77cdf8fb3 100644 --- a/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php +++ b/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php @@ -2,23 +2,17 @@ final class ReleephBranchHistoryController extends ReleephBranchController { - private $branchID; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->branchID = $data['branchID']; - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('branchID'); $branch = id(new ReleephBranchQuery()) ->setViewer($viewer) - ->withIDs(array($this->branchID)) + ->withIDs(array($id)) ->executeOne(); if (!$branch) { return new Aphront404Response(); diff --git a/src/applications/releeph/controller/branch/ReleephBranchNamePreviewController.php b/src/applications/releeph/controller/branch/ReleephBranchNamePreviewController.php index bf429f9034..f2dbd23d8d 100644 --- a/src/applications/releeph/controller/branch/ReleephBranchNamePreviewController.php +++ b/src/applications/releeph/controller/branch/ReleephBranchNamePreviewController.php @@ -3,8 +3,7 @@ final class ReleephBranchNamePreviewController extends ReleephController { - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { $is_symbolic = $request->getBool('isSymbolic'); $template = $request->getStr('template'); diff --git a/src/applications/releeph/controller/branch/ReleephBranchViewController.php b/src/applications/releeph/controller/branch/ReleephBranchViewController.php index 29e0f6d658..11615fe3ed 100644 --- a/src/applications/releeph/controller/branch/ReleephBranchViewController.php +++ b/src/applications/releeph/controller/branch/ReleephBranchViewController.php @@ -2,25 +2,18 @@ final class ReleephBranchViewController extends ReleephBranchController { - private $queryKey; - private $branchID; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->branchID = $data['branchID']; - $this->queryKey = idx($data, 'queryKey'); - } - - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('branchID'); + $querykey = $request->getURIData('queryKey'); $branch = id(new ReleephBranchQuery()) ->setViewer($viewer) - ->withIDs(array($this->branchID)) + ->withIDs(array($id)) ->executeOne(); if (!$branch) { return new Aphront404Response(); @@ -29,7 +22,7 @@ final class ReleephBranchViewController extends ReleephBranchController { $controller = id(new PhabricatorApplicationSearchController()) ->setPreface($this->renderPreface()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine($this->getSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/settings/controller/PhabricatorSettingsAdjustController.php b/src/applications/settings/controller/PhabricatorSettingsAdjustController.php index 2f6b2bcab1..7211431f16 100644 --- a/src/applications/settings/controller/PhabricatorSettingsAdjustController.php +++ b/src/applications/settings/controller/PhabricatorSettingsAdjustController.php @@ -3,8 +3,7 @@ final class PhabricatorSettingsAdjustController extends PhabricatorController { - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { $user = $request->getUser(); $prefs = $user->loadPreferences(); diff --git a/src/applications/settings/controller/PhabricatorSettingsMainController.php b/src/applications/settings/controller/PhabricatorSettingsMainController.php index 80753b17ca..7a2799935c 100644 --- a/src/applications/settings/controller/PhabricatorSettingsMainController.php +++ b/src/applications/settings/controller/PhabricatorSettingsMainController.php @@ -3,8 +3,6 @@ final class PhabricatorSettingsMainController extends PhabricatorController { - private $id; - private $key; private $user; private function getUser() { @@ -12,24 +10,20 @@ final class PhabricatorSettingsMainController } private function isSelf() { - $viewer_phid = $this->getRequest()->getUser()->getPHID(); + $viewer_phid = $this->getViewer()->getPHID(); $user_phid = $this->getUser()->getPHID(); return ($viewer_phid == $user_phid); } - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - $this->key = idx($data, 'key'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); + $key = $request->getURIData('key'); - public function processRequest() { - $request = $this->getRequest(); - $viewer = $request->getUser(); - - if ($this->id) { + if ($id) { $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) - ->withIDs(array($this->id)) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -49,7 +43,7 @@ final class PhabricatorSettingsMainController $panels = $this->buildPanels(); $nav = $this->renderSideNav($panels); - $key = $nav->selectFilter($this->key, head($panels)->getPanelKey()); + $key = $nav->selectFilter($key, head($panels)->getPanelKey()); $panel = $panels[$key]; $panel->setUser($this->getUser()); diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php index c4e4fed588..05c12aec27 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php @@ -3,19 +3,13 @@ final class PhabricatorSlowvoteCloseController extends PhabricatorSlowvoteController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $poll = id(new PhabricatorSlowvoteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -42,7 +36,7 @@ final class PhabricatorSlowvoteCloseController ->setNewValue($new_status); id(new PhabricatorSlowvoteEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true) diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteCommentController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteCommentController.php index 588f06b649..035eb577d8 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteCommentController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteCommentController.php @@ -3,23 +3,17 @@ final class PhabricatorSlowvoteCommentController extends PhabricatorSlowvoteController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $poll = id(new PhabricatorSlowvoteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->executeOne(); if (!$poll) { return new Aphront404Response(); @@ -38,7 +32,7 @@ final class PhabricatorSlowvoteCommentController ->setContent($request->getStr('comment'))); $editor = id(new PhabricatorSlowvoteEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect($request->isContinueRequest()) ->setContentSourceFromRequest($request) ->setIsPreview($is_preview); @@ -57,7 +51,7 @@ final class PhabricatorSlowvoteCommentController if ($request->isAjax() && $is_preview) { return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($user) + ->setViewer($viewer) ->setTransactions($xactions) ->setIsPreview($is_preview); } else { diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php index 44d9cec792..e497a50fbc 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php @@ -3,21 +3,14 @@ final class PhabricatorSlowvoteEditController extends PhabricatorSlowvoteController { - private $id; + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); - public function willProcessRequest(array $data) { - $this->id = idx($data, 'id'); - } - - public function processRequest() { - - $request = $this->getRequest(); - $user = $request->getUser(); - - if ($this->id) { + if ($id) { $poll = id(new PhabricatorSlowvoteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -29,7 +22,7 @@ final class PhabricatorSlowvoteEditController } $is_new = false; } else { - $poll = PhabricatorSlowvotePoll::initializeNewPoll($user); + $poll = PhabricatorSlowvotePoll::initializeNewPoll($viewer); $is_new = true; } @@ -119,7 +112,7 @@ final class PhabricatorSlowvoteEditController ->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PhabricatorSlowvoteEditor()) - ->setActor($user) + ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request); @@ -153,7 +146,7 @@ final class PhabricatorSlowvoteEditController 'protracted deliberation.')); $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild($instructions) ->appendChild( id(new AphrontFormTextAreaControl()) @@ -164,7 +157,7 @@ final class PhabricatorSlowvoteEditController ->setError($e_question)) ->appendChild( id(new PhabricatorRemarkupControl()) - ->setUser($user) + ->setUser($viewer) ->setLabel(pht('Description')) ->setName('description') ->setValue($v_description)) @@ -232,7 +225,7 @@ final class PhabricatorSlowvoteEditController } $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) + ->setViewer($viewer) ->setObject($poll) ->execute(); @@ -253,7 +246,7 @@ final class PhabricatorSlowvoteEditController $v_shuffle)) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setName('viewPolicy') ->setPolicyObject($poll) ->setPolicies($policies) diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php index 8062fc4098..bbb96d4dc4 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteListController.php @@ -3,19 +3,15 @@ final class PhabricatorSlowvoteListController extends PhabricatorSlowvoteController { - private $queryKey; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->queryKey = idx($data, 'queryKey'); - } + public function handleRequest(AphrontRequest $request) { + $querykey = $request->getURIData('queryKey'); - public function processRequest() { $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($this->queryKey) + ->setQueryKey($querykey) ->setSearchEngine(new PhabricatorSlowvoteSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php index 9bac0a6088..40980e5f41 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvotePollController.php @@ -3,19 +3,13 @@ final class PhabricatorSlowvotePollController extends PhabricatorSlowvoteController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $poll = id(new PhabricatorSlowvoteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needOptions(true) ->needChoices(true) ->needViewerChoices(true) @@ -26,7 +20,7 @@ final class PhabricatorSlowvotePollController $poll_view = id(new SlowvoteEmbedView()) ->setHeadless(true) - ->setUser($user) + ->setUser($viewer) ->setPoll($poll); if ($request->isAjax()) { @@ -44,7 +38,7 @@ final class PhabricatorSlowvotePollController $header = id(new PHUIHeaderView()) ->setHeader($poll->getQuestion()) - ->setUser($user) + ->setUser($viewer) ->setStatus($header_icon, $header_color, $header_name) ->setPolicyObject($poll); diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteVoteController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteVoteController.php index 6cfeae0ac0..2d630bffc1 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteVoteController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteVoteController.php @@ -3,19 +3,13 @@ final class PhabricatorSlowvoteVoteController extends PhabricatorSlowvoteController { - private $id; - - public function willProcessRequest(array $data) { - $this->id = $data['id']; - } - - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $id = $request->getURIData('id'); $poll = id(new PhabricatorSlowvoteQuery()) - ->setViewer($user) - ->withIDs(array($this->id)) + ->setViewer($viewer) + ->withIDs(array($id)) ->needOptions(true) ->needViewerChoices(true) ->executeOne(); @@ -27,9 +21,9 @@ final class PhabricatorSlowvoteVoteController } $options = $poll->getOptions(); - $user_choices = $poll->getViewerChoices($user); + $viewer_choices = $poll->getViewerChoices($viewer); - $old_votes = mpull($user_choices, null, 'getOptionID'); + $old_votes = mpull($viewer_choices, null, 'getOptionID'); if ($request->isAjax()) { $vote = $request->getInt('vote'); @@ -50,12 +44,12 @@ final class PhabricatorSlowvoteVoteController } } - $this->updateVotes($user, $poll, $old_votes, $votes); + $this->updateVotes($viewer, $poll, $old_votes, $votes); $updated_choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere( 'pollID = %d AND authorPHID = %s', $poll->getID(), - $user->getPHID()); + $viewer->getPHID()); $embed = id(new SlowvoteEmbedView()) ->setPoll($poll) @@ -76,12 +70,12 @@ final class PhabricatorSlowvoteVoteController $votes = $request->getArr('vote'); $votes = array_fuse($votes, $votes); - $this->updateVotes($user, $poll, $old_votes, $votes); + $this->updateVotes($viewer, $poll, $old_votes, $votes); return id(new AphrontRedirectResponse())->setURI('/V'.$poll->getID()); } - private function updateVotes($user, $poll, $old_votes, $votes) { + private function updateVotes($viewer, $poll, $old_votes, $votes) { if (!empty($votes) && count($votes) > 1 && $poll->getMethod() == PhabricatorSlowvotePoll::METHOD_PLURALITY) { return id(new Aphront400Response()); @@ -99,7 +93,7 @@ final class PhabricatorSlowvoteVoteController } id(new PhabricatorSlowvoteChoice()) - ->setAuthorPHID($user->getPHID()) + ->setAuthorPHID($viewer->getPHID()) ->setPollID($poll->getID()) ->setOptionID($vote) ->save(); diff --git a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php index d1bd6c18f0..047a5c99a8 100644 --- a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php +++ b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php @@ -8,7 +8,7 @@ final class PhabricatorSlowvoteEditor } public function getEditorObjectsDescription() { - return pht('Slowvotes'); + return pht('Slowvote'); } public function getTransactionTypes() { @@ -111,4 +111,71 @@ final class PhabricatorSlowvoteEditor return; } + protected function shouldSendMail( + PhabricatorLiskDAO $object, + array $xactions) { + return true; + } + + public function getMailTagsMap() { + return array( + PhabricatorSlowvoteTransaction::MAILTAG_DETAILS => + pht('Someone changes the poll details.'), + PhabricatorSlowvoteTransaction::MAILTAG_RESPONSES => + pht('Someone votes on a poll.'), + PhabricatorSlowvoteTransaction::MAILTAG_OTHER => + pht('Other poll activity not listed above occurs.'), + ); + } + + protected function buildMailTemplate(PhabricatorLiskDAO $object) { + $monogram = $object->getMonogram(); + $name = $object->getQuestion(); + + return id(new PhabricatorMetaMTAMail()) + ->setSubject("{$monogram}: {$name}") + ->addHeader('Thread-Topic', $monogram); + } + + protected function buildMailBody( + PhabricatorLiskDAO $object, + array $xactions) { + + $body = parent::buildMailBody($object, $xactions); + $description = $object->getDescription(); + + if (strlen($description)) { + $body->addTextSection( + pht('SLOWVOTE DESCRIPTION'), + $object->getDescription()); + } + + $body->addLinkSection( + pht('SLOWVOTE DETAIL'), + PhabricatorEnv::getProductionURI('/'.$object->getMonogram())); + + return $body; + } + + protected function getMailTo(PhabricatorLiskDAO $object) { + return array( + $object->getAuthorPHID(), + $this->requireActor()->getPHID(), + ); + } + protected function getMailSubjectPrefix() { + return '[Slowvote]'; + } + + protected function buildReplyHandler(PhabricatorLiskDAO $object) { + return id(new PhabricatorSlowvoteReplyHandler()) + ->setMailReceiver($object); + } + + protected function shouldPublishFeedStory( + PhabricatorLiskDAO $object, + array $xactions) { + return true; + } + } diff --git a/src/applications/slowvote/mail/PhabricatorSlowvoteMailReceiver.php b/src/applications/slowvote/mail/PhabricatorSlowvoteMailReceiver.php new file mode 100644 index 0000000000..78e608231f --- /dev/null +++ b/src/applications/slowvote/mail/PhabricatorSlowvoteMailReceiver.php @@ -0,0 +1,28 @@ +setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + } + + protected function getTransactionReplyHandler() { + return new PhabricatorSlowvoteReplyHandler(); + } + +} diff --git a/src/applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php b/src/applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php new file mode 100644 index 0000000000..b67327e506 --- /dev/null +++ b/src/applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php @@ -0,0 +1,16 @@ + 'uint32', 'description' => 'text', 'isClosed' => 'bool', + 'mailKey' => 'bytes20', ), self::CONFIG_KEY_SCHEMA => array( 'key_phid' => null, @@ -106,6 +108,17 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO return $this; } + public function getMonogram() { + return 'V'.$this->getID(); + } + + public function save() { + if (!$this->getMailKey()) { + $this->setMailKey(Filesystem::readRandomCharacters(20)); + } + return parent::save(); + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php b/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php index 9abf1f5801..e45fdb013f 100644 --- a/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php +++ b/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php @@ -9,6 +9,10 @@ final class PhabricatorSlowvoteTransaction const TYPE_SHUFFLE = 'vote:shuffle'; const TYPE_CLOSE = 'vote:close'; + const MAILTAG_DETAILS = 'vote:details'; + const MAILTAG_RESPONSES = 'vote:responses'; + const MAILTAG_OTHER = 'vote:vote'; + public function getApplicationName() { return 'slowvote'; } @@ -93,6 +97,82 @@ final class PhabricatorSlowvoteTransaction return parent::getTitle(); } + public function getTitleForFeed() { + $author_phid = $this->getAuthorPHID(); + $object_phid = $this->getObjectPHID(); + + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + $type = $this->getTransactionType(); + switch ($type) { + case self::TYPE_QUESTION: + if ($old === null) { + return pht( + '%s created %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + + } else { + return pht( + '%s renamed %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + break; + case self::TYPE_DESCRIPTION: + if ($old === null) { + return pht( + '%s set the description of %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + + } else { + return pht( + '%s edited the description of %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + break; + case self::TYPE_RESPONSES: + // TODO: This could be more detailed + return pht( + '%s changed who can see the responses of %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + + case self::TYPE_SHUFFLE: + if ($new) { + return pht( + '%s made %s responses appear in a random order.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + + } else { + return pht( + '%s made %s responses appear in a fixed order.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + case self::TYPE_CLOSE: + if ($new) { + return pht( + '%s closed %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + + } else { + return pht( + '%s reopened %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + break; + } + + return parent::getTitleForFeed(); + } + public function getIcon() { $old = $this->getOldValue(); $new = $this->getNewValue(); @@ -152,5 +232,26 @@ final class PhabricatorSlowvoteTransaction $this->getNewValue()); } + public function getMailTags() { + $tags = parent::getMailTags(); + + switch ($this->getTransactionType()) { + case self::TYPE_QUESTION: + case self::TYPE_DESCRIPTION: + case self::TYPE_SHUFFLE: + case self::TYPE_CLOSE: + $tags[] = self::MAILTAG_DETAILS; + break; + case self::TYPE_RESPONSES: + $tags[] = self::MAILTAG_RESPONSES; + break; + default: + $tags[] = self::MAILTAG_OTHER; + break; + } + + return $tags; + } + } diff --git a/src/applications/subscriptions/herald/PhabricatorSubscriptionsAddSelfHeraldAction.php b/src/applications/subscriptions/herald/PhabricatorSubscriptionsAddSelfHeraldAction.php new file mode 100644 index 0000000000..20df5e06c4 --- /dev/null +++ b/src/applications/subscriptions/herald/PhabricatorSubscriptionsAddSelfHeraldAction.php @@ -0,0 +1,29 @@ +getRule()->getAuthorPHID(); + return $this->applySubscribe(array($phid), $is_add = true); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Add rule author as subscriber.'); + } + +} diff --git a/src/applications/subscriptions/herald/PhabricatorSubscriptionsAddSubscribersHeraldAction.php b/src/applications/subscriptions/herald/PhabricatorSubscriptionsAddSubscribersHeraldAction.php new file mode 100644 index 0000000000..14f72d313a --- /dev/null +++ b/src/applications/subscriptions/herald/PhabricatorSubscriptionsAddSubscribersHeraldAction.php @@ -0,0 +1,32 @@ +applySubscribe($effect->getTarget(), $is_add = true); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorMetaMTAMailableDatasource(); + } + + public function renderActionDescription($value) { + return pht('Add subscribers: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php b/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php new file mode 100644 index 0000000000..6ec7b6f776 --- /dev/null +++ b/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php @@ -0,0 +1,187 @@ +getAdapter(); + + $allowed_types = array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + ); + + // Evaluating "No Effect" is a bit tricky for this rule type, so just + // do it manually below. + $current = array(); + + $targets = $this->loadStandardTargets($phids, $allowed_types, $current); + if (!$targets) { + return; + } + + $phids = array_fuse(array_keys($targets)); + + // The "Add Subscribers" rule only adds subscribers who haven't previously + // unsubscribed from the object explicitly. Filter these subscribers out + // before continuing. + if ($is_add) { + $unsubscribed = $adapter->loadEdgePHIDs( + PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST); + + foreach ($unsubscribed as $phid) { + if (isset($phids[$phid])) { + $unsubscribed[$phid] = $phid; + unset($phids[$phid]); + } + } + + if ($unsubscribed) { + $this->logEffect( + self::DO_PREVIOUSLY_UNSUBSCRIBED, + array_values($unsubscribed)); + } + } + + if (!$phids) { + return; + } + + $auto = array(); + $object = $adapter->getObject(); + foreach ($phids as $phid) { + if ($object->isAutomaticallySubscribed($phid)) { + $auto[$phid] = $phid; + unset($phids[$phid]); + } + } + + if ($auto) { + $this->logEffect(self::DO_AUTOSUBSCRIBED, array_values($auto)); + } + + if (!$phids) { + return; + } + + $current = $adapter->loadEdgePHIDs( + PhabricatorObjectHasSubscriberEdgeType::EDGECONST); + + if ($is_add) { + $already = array(); + foreach ($phids as $phid) { + if (isset($current[$phid])) { + $already[$phid] = $phid; + unset($phids[$phid]); + } + } + + if ($already) { + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); + } + } else { + $already = array(); + foreach ($phids as $phid) { + if (empty($current[$phid])) { + $already[$phid] = $phid; + unset($phids[$phid]); + } + } + + if ($already) { + $this->logEffect(self::DO_STANDARD_NO_EFFECT, $already); + } + } + + if (!$phids) { + return; + } + + if ($is_add) { + $kind = '+'; + } else { + $kind = '-'; + } + + $xaction = $adapter->newTransaction() + ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) + ->setNewValue( + array( + $kind => $phids, + )); + + $adapter->queueTransaction($xaction); + + if ($is_add) { + $this->logEffect(self::DO_SUBSCRIBED, $phids); + } else { + $this->logEffect(self::DO_UNSUBSCRIBED, $phids); + } + } + + protected function getActionEffectMap() { + return array( + self::DO_PREVIOUSLY_UNSUBSCRIBED => array( + 'icon' => 'fa-minus-circle', + 'color' => 'grey', + 'name' => pht('Previously Unsubscribed'), + ), + self::DO_AUTOSUBSCRIBED => array( + 'icon' => 'fa-envelope', + 'color' => 'grey', + 'name' => pht('Automatically Subscribed'), + ), + self::DO_SUBSCRIBED => array( + 'icon' => 'fa-envelope', + 'color' => 'green', + 'name' => pht('Added Subscribers'), + ), + self::DO_UNSUBSCRIBED => array( + 'icon' => 'fa-minus-circle', + 'color' => 'green', + 'name' => pht('Removed Subscribers'), + ), + ); + } + + protected function renderActionEffectDescription($type, $data) { + switch ($type) { + case self::DO_PREVIOUSLY_UNSUBSCRIBED: + return pht( + 'Declined to resubscribe %s target(s) because they previously '. + 'unsubscribed: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_AUTOSUBSCRIBED: + return pht( + '%s automatically subscribed target(s) were not affected: %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_SUBSCRIBED: + return pht( + 'Added %s subscriber(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + case self::DO_UNSUBSCRIBED: + return pht( + 'Removed %s subscriber(s): %s.', + new PhutilNumber(count($data)), + $this->renderHandleList($data)); + } + } + + +} diff --git a/src/applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php b/src/applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php new file mode 100644 index 0000000000..5d751cb54a --- /dev/null +++ b/src/applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php @@ -0,0 +1,29 @@ +getRule()->getAuthorPHID(); + return $this->applySubscribe(array($phid), $is_add = false); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_NONE; + } + + public function renderActionDescription($value) { + return pht('Remove rule author as subscriber.'); + } + +} diff --git a/src/applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php b/src/applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php new file mode 100644 index 0000000000..67ece2cb72 --- /dev/null +++ b/src/applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php @@ -0,0 +1,32 @@ +applySubscribe($effect->getTarget(), $is_add = false); + } + + public function getHeraldActionStandardType() { + return self::STANDARD_PHID_LIST; + } + + protected function getDatasource() { + return new PhabricatorMetaMTAMailableDatasource(); + } + + public function renderActionDescription($value) { + return pht('Remove subscribers: %s.', $this->renderHandleList($value)); + } + +} diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php index 0b6dd2de91..45782758f8 100644 --- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php +++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php @@ -1706,7 +1706,7 @@ abstract class PhabricatorApplicationTransactionEditor $lists = array($new_set, $new_add, $new_rem); foreach ($lists as $list) { - $this->checkEdgeList($list); + $this->checkEdgeList($list, $xaction->getMetadataValue('edge:type')); } $result = array(); @@ -1743,7 +1743,7 @@ abstract class PhabricatorApplicationTransactionEditor return $result; } - private function checkEdgeList($list) { + private function checkEdgeList($list, $edge_type) { if (!$list) { return; } @@ -1751,16 +1751,18 @@ abstract class PhabricatorApplicationTransactionEditor if (phid_get_type($key) === PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { throw new Exception( pht( - "Edge transactions must have destination PHIDs as in edge ". - "lists (found key '%s').", - $key)); + 'Edge transactions must have destination PHIDs as in edge '. + 'lists (found key "%s" on transaction of type "%s").', + $key, + $edge_type)); } if (!is_array($item) && $item !== $key) { throw new Exception( pht( - "Edge transactions must have PHIDs or edge specs as values ". - "(found value '%s').", - $item)); + 'Edge transactions must have PHIDs or edge specs as values '. + '(found value "%s" on transaction of type "%s").', + $item, + $edge_type)); } } } @@ -2811,6 +2813,13 @@ abstract class PhabricatorApplicationTransactionEditor $this->setHeraldAdapter($adapter); $this->setHeraldTranscript($xscript); + if ($adapter instanceof HarbormasterBuildableAdapterInterface) { + HarbormasterBuildable::applyBuildPlans( + $adapter->getHarbormasterBuildablePHID(), + $adapter->getHarbormasterContainerPHID(), + $adapter->getQueuedHarbormasterBuildPlanPHIDs()); + } + return array_merge( $this->didApplyHeraldRules($object, $adapter, $xscript), $adapter->getQueuedTransactions()); diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index e8811da760..c7be284ecd 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -362,11 +362,23 @@ abstract class PhabricatorApplicationTransaction case PhabricatorTransactions::TYPE_COMMENT: $comment = $this->getComment(); if ($comment && $comment->getIsRemoved()) { - return 'fa-eraser'; + return 'fa-trash'; } return 'fa-comment'; case PhabricatorTransactions::TYPE_SUBSCRIBERS: - return 'fa-envelope'; + $old = $this->getOldValue(); + $new = $this->getNewValue(); + $add = array_diff($new, $old); + $rem = array_diff($old, $new); + if ($add && $rem) { + return 'fa-user'; + } else if ($add) { + return 'fa-user-plus'; + } else if ($rem) { + return 'fa-user-times'; + } else { + return 'fa-user'; + } case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: diff --git a/src/applications/uiexample/application/PhabricatorUIExamplesApplication.php b/src/applications/uiexample/application/PhabricatorUIExamplesApplication.php index c347a101e9..3b3d38ef14 100644 --- a/src/applications/uiexample/application/PhabricatorUIExamplesApplication.php +++ b/src/applications/uiexample/application/PhabricatorUIExamplesApplication.php @@ -30,6 +30,10 @@ final class PhabricatorUIExamplesApplication extends PhabricatorApplication { return self::GROUP_DEVELOPER; } + public function isPrototype() { + return true; + } + public function getApplicationOrder() { return 0.110; } diff --git a/src/applications/uiexample/controller/PhabricatorUIExampleRenderController.php b/src/applications/uiexample/controller/PhabricatorUIExampleRenderController.php index 00dd4daf41..32c60de1c5 100644 --- a/src/applications/uiexample/controller/PhabricatorUIExampleRenderController.php +++ b/src/applications/uiexample/controller/PhabricatorUIExampleRenderController.php @@ -2,17 +2,12 @@ final class PhabricatorUIExampleRenderController extends PhabricatorController { - private $class; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->class = idx($data, 'class'); - } - - public function processRequest() { + public function handleRequest(AphrontRequest $request) { + $id = $request->getURIData('class'); $classes = id(new PhutilSymbolLoader()) ->setAncestorClass('PhabricatorUIExample') @@ -27,7 +22,7 @@ final class PhabricatorUIExampleRenderController extends PhabricatorController { $nav->addFilter($class, $name); } - $selected = $nav->selectFilter($this->class, head_key($classes)); + $selected = $nav->selectFilter($id, head_key($classes)); $example = $classes[$selected]; $example->setRequest($this->getRequest()); diff --git a/src/applications/uiexample/examples/PHUITimelineExample.php b/src/applications/uiexample/examples/PHUITimelineExample.php index d3df3ded71..661d2e6899 100644 --- a/src/applications/uiexample/examples/PHUITimelineExample.php +++ b/src/applications/uiexample/examples/PHUITimelineExample.php @@ -196,6 +196,7 @@ final class PHUITimelineExample extends PhabricatorUIExample { } $timeline = id(new PHUITimelineView()); + $timeline->setUser($user); foreach ($events as $event) { $timeline->addEvent($event); } diff --git a/src/applications/uiexample/examples/PhabricatorTwoColumnUIExample.php b/src/applications/uiexample/examples/PhabricatorTwoColumnUIExample.php deleted file mode 100644 index fd9b422a26..0000000000 --- a/src/applications/uiexample/examples/PhabricatorTwoColumnUIExample.php +++ /dev/null @@ -1,36 +0,0 @@ - 'border: 1px solid blue; padding: 20px;', - ), - 'Mary, mary quite contrary.'); - - $side = phutil_tag( - 'div', - array( - 'style' => 'border: 1px solid red; padding: 20px;', - ), - 'How does your garden grow?'); - - - $content = id(new AphrontTwoColumnView()) - ->setMainColumn($main) - ->setSideColumn($side); - - return $content; - } -} diff --git a/src/applications/xhprof/controller/PhabricatorXHProfProfileController.php b/src/applications/xhprof/controller/PhabricatorXHProfProfileController.php index 7f3b155cdd..85815d8589 100644 --- a/src/applications/xhprof/controller/PhabricatorXHProfProfileController.php +++ b/src/applications/xhprof/controller/PhabricatorXHProfProfileController.php @@ -3,22 +3,16 @@ final class PhabricatorXHProfProfileController extends PhabricatorXHProfController { - private $phid; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->phid = $data['phid']; - } - - public function processRequest() { - $request = $this->getRequest(); + public function handleRequest(AphrontRequest $request) { + $phid = $request->getURIData('phid'); $file = id(new PhabricatorFileQuery()) ->setViewer($request->getUser()) - ->withPHIDs(array($this->phid)) + ->withPHIDs(array($phid)) ->executeOne(); if (!$file) { return new Aphront404Response(); diff --git a/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php b/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php index 98f20436e4..65ca5593f3 100644 --- a/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php +++ b/src/applications/xhprof/controller/PhabricatorXHProfSampleListController.php @@ -3,24 +3,22 @@ final class PhabricatorXHProfSampleListController extends PhabricatorXHProfController { - private $view; - public function shouldAllowPublic() { return true; } - public function willProcessRequest(array $data) { - $this->view = idx($data, 'view', 'all'); - } + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $view = $request->getURIData('view'); - public function processRequest() { - $request = $this->getRequest(); - $user = $request->getUser(); + if (!$view) { + $view = 'all'; + } $pager = new PHUIPagerView(); $pager->setOffset($request->getInt('page')); - switch ($this->view) { + switch ($view) { case 'sampled': $clause = 'sampleRate > 0'; $show_type = false; @@ -78,7 +76,7 @@ final class PhabricatorXHProfSampleListController $item->addIcon( 'none', - phabricator_datetime($sample->getDateCreated(), $user)); + phabricator_datetime($sample->getDateCreated(), $viewer)); $list->addItem($item); } diff --git a/src/docs/user/userguide/harbormaster.diviner b/src/docs/user/userguide/harbormaster.diviner new file mode 100644 index 0000000000..23ed15d5e4 --- /dev/null +++ b/src/docs/user/userguide/harbormaster.diviner @@ -0,0 +1,230 @@ +@title Harbormaster User Guide +@group userguide + +Guide to Harbormaster, a build and continuous integration application. + +Overview +======== + +WARNING: Harbormaster is still very rough. Read this document carefully to +understand what it can and can not do and what to expect in the future. + +The Harbormaster application provides build and continuous integration support +for Phabricator. + +Harbormaster is not a mature application. You should expect it to have major +missing capabilities and to change substantially over time. The current version +of Harbormaster can perform some basic build tasks, but has many limitations +and is not a complete build platform. + +In particular, you should be aware of these common limitations: + + - **Creating Build Plans**: Harbormaster ships with only very basic, crude + tools for writing build plans. There are no default integrations with + `arc unit` or systems like Jenkins. Build plans are likely to change + substantially over time. + - **Triggering Builds**: Harbormaster can only trigger builds through Herald + rules. It can not currently run periodic builds. + - **Executing Builds**: Harbormaster can only execute builds in a remote + system, like Jenkins. It can not currently host builds. + - **Change Handoff**: Change handoff is covered in rough edges and tradeoffs. + + +Harbormaster Basics +=================== + +Use Harbormaster to run builds or tests on code reviews and commits. In general, +the Harbormaster workflow looks like this today: + + - You create a new "Build Plan" which describes how to build a project (which + tests to run, which commands to execute, etc). + - You configure Harbormaster to trigger the plan when relevant code reviews + are created or relevant commits are pushed or discovered. + - Harbormaster executes the plan and reports the results, allowing you to see + if a change or commit breaks tests. + +The remainder of this document walks through these steps in more detail. + + +Concepts and Terminology +======================== + +Harbormaster uses these concepts to describe builds: + + - **Build Step**: Describes a single step in a build process, like running a + command. + - **Build Plan**: A collection of build steps which describe a build process. + You'll create build plans to tell Harbormaster which commands it needs to + run to perform a build. + - **Buildable**: A reference to an object from another application which can + have builds run against it. In the upstream, code reviews (from + Differential) and commits (from Diffusion) are buildable. + - **Build**: Created by running a build plan against a buildable. Collects + results from running build commands and shows build progress, status and + results. A build describes what happened when an entire build plan was + run. + - **Build Target**: Builds are made up of build targets, which are created + automatically when Harbormaster runs the individual steps in a build. A + build target describes what happened when a specific build step was run. + + +Creating a Build Plan +===================== + +NOTE: Build plans are currently crude and subject to change in future versions +of Harbormaster. + +A build plan tells Harbormaster how to run a build: which commands to run, +services to call, and so on. Builds start with a build plan. + +To create a build plan, navigate to {nav Harbormaster > Manage Build Plans > +New Build Plan}. + +Build plans are composed of "Build Steps". Each step describes an individual +action (like running a command) and the sequence of steps as a whole comprise +the plan. For example, you might want to run one command to build a binary, +then a second command to execute unit tests. Add steps to your build plan +with {nav Add Build Step}. + +Currently, the only useful type of build step is "Make HTTP Request", which you +can use to make a call to an external build system like Jenkins. Today, most +plans should therefor look something like this: + + - Use a "Make HTTP Request" step to tell Jenkins or some other similar + external build system about the code. + - Have the build step "Wait for Message" after the external system is + notified. + - Write custom code on the build server to respond to the request, run a + build, then report the results back to Phabricator by calling the + `harbormaster.sendmessage` Conduit API. + +You'll need to write a nontrivial amount of code to get this working today. +In the future, Harbormaster will become more powerful and have more builtin +support for interacting with build systems. + + +Triggering Builds +================= + +NOTE: Harbormaster can not currently watch a branch (like "build 'master' every +time it changes") or run periodic builds (like "build every hour"). These +capabilities may be added in the future. + +You can run builds manually by using {nav Run Plan Manually} from the detail +screen of a build plan. This will execute a manual build immediately, and can +be used to test that plans work properly. + +To trigger a build automatically, write a Herald rule which executes the "Run +build plans" action. The simplest rule would just use the "Always" condition +and run a single build plan, but you can use more complex conditions to control +which plans run on which code. + +This action is available for commits and revisions, as either can be built +with Harbormaster. This action is only available for "Project" or "Global" +rules. + +Change Handoff +============== + +NOTE: Change handoff is currently very rough. It may improve in the future. + +If you want to build code reviews in an external system, it will need to be +able to construct a working copy with the changes before it can build them. + +There are three ways to do this: + + - **Automatic Staging Areas**: Recommended. This is the simplest and + cleanest way to hand changes to an external build system. + - **Manual Staging Areas**: Recommended if you can not use automatic + staging areas. This is a simple way to hand changes to an external build + system, but not as clean as automatic staging areas. + - **`arc patch`**: Not recommended. This mechanism is the most difficult to + configure and debug, and is not nearly as reliable as handoff via staging + areas. + +With staging areas, `arc` pushes a copy of the local changes somewhere as a +side effect of running `arc diff`. In Git, it pushes changes to a tag like +`phabricator/diff/123` in a designated remote. + +The build system can then interact with this copy using normal VCS commands. +This is simpler to configure, use, troubleshoot and work with than `arc patch`. + +With `arc patch`, the build system downloads patches from Phabricator and +applies them to a local working copy. This is more complex and more error-prone +than staging areas. + +**Automatic Staging Areas**: This is the recommended mechanism for change +handoff. This mechanism has not been built yet, so you can not use it. + +**Manual Staging Areas**: If you can not use automatic staging areas, manual +staging areas are the next best approach. Manual staging areas are only +supported under Git, but work with both hosted and imported repositories. + +Manual staging areas work like this: + + - You configure a staging area for the repository you want to be able to + run builds for. A staging area is just a remote repository that you're + designating for temporary storage. + - Once a staging area is configured, `arc diff` will automatically push a + copy of the changes to the staging area as a side effect when creating + and updating reviews. + - Your build system can pull changes directly from the configured staging + area. + +Configure a staging area by navigating to {nav Diffusion > +(Choose a Repository) > Edit Repository > Edit Staging}. You'll enter the +remote URI of a repository to use as a staging area, and `arc diff` will push +changes to tags like `phabricator/diff/123`. + +There are several ways to select a staging area: + + - You can use the repository itself as its own staging area, but this will + clog it up with a lot of tags that users probably don't care about. This is + simplest to configure but will be disruptive and potentially confusing to + users. + - You can create a single staging repository and have all other + repositories use it as a staging area. This is simple to configure and + won't disrupt or confuse users, but you won't be able to set granular + permissions on the staging repository: all the staged changes in a + repository are visible to anyone who has access to the repository, even if + they came from a repository that the viewer does not have access to. + - You can create a staging repository for each standard repository. This will + give you the most control, but is also the most time consuming to configure. + - You can use a hybrid approach and have several staging repositories, each + of which is used for one or more standard repositories. This will let you + strike a balance between setup costs and granularity. + - Using automatic staging areas avoids all this complexity by using the + repository as its own staging area but hiding the tags from users. + +Once you've configured a staging area, have your build system clone the staging +area repository and do a checkout of the relevant tag in order to perform a +build. + +**`arc patch`**: You can also have the build system pull changes out of +Phabricator as patches and apply them with `arc patch`. This mechanism is the +most complex to configure and debug, and is much less reliable than using +staging areas. It is not recommended. + +To use `arc patch`-based handoff, install PHP on your build server and set up +`arc`. Create a "bot" user for your build system and generate a Conduit token +in {nav Settings > Conduit API Tokens}. Then have your build system clone the +repository and run `arc patch` to apply the changes: + + $ arc patch --conduit-token --diff + +This will usually work, but is more complex and less reliable than using a +staging area. + + +Troubleshooting +=============== + +You can troubleshoot Harbormaster by using `bin/harbormaster` from the command +line. Run it as `bin/harbormaster help` for details. + +In particular, you can run manual builds in the foreground from the CLI to see +more details about what they're doing: + + phabricator/ $ ./bin/harbormaster build D123 --plan 456 --trace + +This may help you understand or debug issues with a build plan. diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php index d0466fbb7d..98d062766b 100644 --- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php +++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php @@ -32,6 +32,8 @@ final class PhabricatorUSEnglishTranslation '%d path(s)' => array('%d path', '%d paths'), '%d diff(s)' => array('%d diff', '%d diffs'), + '%d Answer(s)' => array('%d Answer', '%d Answers'), + '%s DIFF LINK(S)' => array('DIFF LINK', 'DIFF LINKS'), 'You successfully created %d diff(s).' => array( 'You successfully created %d diff.', @@ -1182,6 +1184,7 @@ final class PhabricatorUSEnglishTranslation '%s Task', '%s Tasks', ), + '%s added %s badge(s) for %s: %s.' => array( array( '%s added a badge for %s: %3$s.', @@ -1256,6 +1259,107 @@ final class PhabricatorUSEnglishTranslation ), ), + '%s automatically subscribed target(s) were not affected: %s.' => array( + 'An automatically subscribed target was not affected: %2$s.', + 'Automatically subscribed targets were not affected: %2$s.', + ), + + 'Declined to resubscribe %s target(s) because they previously '. + 'unsubscribed: %s.' => array( + 'Delined to resubscribe a target because they previously '. + 'unsubscribed: %2$s.', + 'Declined to resubscribe targets because they previously '. + 'unsubscribed: %2$s.', + ), + + '%s target(s) are not subscribed: %s.' => array( + 'A target is not subscribed: %2$s.', + 'Targets are not subscribed: %2$s.', + ), + + '%s target(s) are already subscribed: %s.' => array( + 'A target is already subscribed: %2$s.', + 'Targets are already subscribed: %2$s.', + ), + + 'Added %s subscriber(s): %s.' => array( + 'Added a subscriber: %2$s.', + 'Added subscribers: %2$s.', + ), + + 'Removed %s subscriber(s): %s.' => array( + 'Removed a subscriber: %2$s.', + 'Removed subscribers: %2$s.', + ), + + 'Queued email to be delivered to %s target(s): %s.' => array( + 'Queued email to be delivered to target: %2$s.', + 'Queued email to be delivered to targets: %2$s.', + ), + + 'Queued email to be delivered to %s target(s), ignoring their '. + 'notification preferences: %s.' => array( + 'Queued email to be delivered to target, ignoring notification '. + 'preferences: %2$s.', + 'Queued email to be delivered to targets, ignoring notification '. + 'preferences: %2$s.', + ), + + '%s project(s) are not associated: %s.' => array( + 'A project is not associated: %2$s.', + 'Projects are not associated: %2$s.', + ), + + '%s project(s) are already associated: %s.' => array( + 'A project is already associated: %2$s.', + 'Projects are already associated: %2$s.', + ), + + 'Added %s project(s): %s.' => array( + 'Added a project: %2$s.', + 'Added projects: %2$s.', + ), + + 'Removed %s project(s): %s.' => array( + 'Removed a project: %2$s.', + 'Removed projects: %2$s.', + ), + + 'Added %s reviewer(s): %s.' => array( + 'Added a reviewer: %2$s.', + 'Added reviewers: %2$s.', + ), + + 'Added %s blocking reviewer(s): %s.' => array( + 'Added a blocking reviewer: %2$s.', + 'Added blocking reviewers: %2$s.', + ), + + 'Required %s signature(s): %s.' => array( + 'Required a signature: %2$s.', + 'Required signatures: %2$s.', + ), + + 'Started %s build(s): %s.' => array( + 'Started a build: %2$s.', + 'Started builds: %2$s.', + ), + + 'Added %s auditor(s): %s.' => array( + 'Added an auditor: %2$s.', + 'Added auditors: %2$s.', + ), + + '%s target(s) do not have permission to see this object: %s.' => array( + 'A target does not have permission to see this object: %2$s.', + 'Targets do not have permission to see this object: %2$s.', + ), + + 'This action has no effect on %s target(s): %s.' => array( + 'This action has no effect on a target: %2$s.', + 'This action has no effect on targets: %2$s.', + ), + ); } diff --git a/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php b/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php index f5c936539e..896c52276f 100644 --- a/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php +++ b/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php @@ -53,7 +53,7 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule { return $uri; } - protected function renderObjectRefForAnyMedia ( + protected function renderObjectRefForAnyMedia( $object, PhabricatorObjectHandle $handle, $anchor, diff --git a/src/view/layout/AphrontTwoColumnView.php b/src/view/layout/AphrontTwoColumnView.php deleted file mode 100644 index c29a658ff5..0000000000 --- a/src/view/layout/AphrontTwoColumnView.php +++ /dev/null @@ -1,66 +0,0 @@ -mainColumn = $main; - return $this; - } - - public function setSideColumn($side) { - $this->sideColumn = $side; - return $this; - } - - public function setCentered($centered) { - $this->centered = $centered; - return $this; - } - - public function setNoPadding($padding) { - $this->padding = $padding; - return $this; - } - - public function render() { - require_celerity_resource('aphront-two-column-view-css'); - - $main = phutil_tag( - 'div', - array( - 'class' => 'aphront-main-column', - ), - $this->mainColumn); - - $side = phutil_tag( - 'div', - array( - 'class' => 'aphront-side-column', - ), - $this->sideColumn); - - $classes = array('aphront-two-column'); - if ($this->centered) { - $classes = array('aphront-two-column-centered'); - } - - if ($this->padding) { - $classes[] = 'aphront-two-column-padded'; - } - - return phutil_tag( - 'div', - array( - 'class' => implode(' ', $classes), - ), - array( - $main, - $side, - )); - } -} diff --git a/src/view/phui/PHUIBadgeMiniView.php b/src/view/phui/PHUIBadgeMiniView.php index 5807336ca2..92d6fd8b8b 100644 --- a/src/view/phui/PHUIBadgeMiniView.php +++ b/src/view/phui/PHUIBadgeMiniView.php @@ -6,6 +6,7 @@ final class PHUIBadgeMiniView extends AphrontTagView { private $icon; private $quality; private $header; + private $tipDirection; public function setIcon($icon) { $this->icon = $icon; @@ -27,6 +28,11 @@ final class PHUIBadgeMiniView extends AphrontTagView { return $this; } + public function setTipDirection($direction) { + $this->tipDirection = $direction; + return $this; + } + protected function getTagName() { if ($this->href) { return 'a'; @@ -51,6 +57,8 @@ final class PHUIBadgeMiniView extends AphrontTagView { 'href' => $this->href, 'meta' => array( 'tip' => $this->header, + 'align' => $this->tipDirection, + 'size' => 300, ), ); } diff --git a/src/view/phui/PHUIIconView.php b/src/view/phui/PHUIIconView.php index 0cb7be8db5..08e27b0753 100644 --- a/src/view/phui/PHUIIconView.php +++ b/src/view/phui/PHUIIconView.php @@ -65,11 +65,9 @@ final class PHUIIconView extends AphrontTagView { protected function getTagAttributes() { require_celerity_resource('phui-icon-view-css'); - $style = null; $classes = array(); $classes[] = 'phui-icon-view'; - if ($this->spriteIcon) { require_celerity_resource('sprite-'.$this->spriteSheet.'-css'); $classes[] = 'sprite-'.$this->spriteSheet; @@ -88,7 +86,6 @@ final class PHUIIconView extends AphrontTagView { } $style = 'background-image: url('.$this->image.');'; } - if ($this->text) { $classes[] = 'phui-icon-has-text'; $this->appendChild($this->text); @@ -647,6 +644,88 @@ final class PHUIIconView extends AphrontTagView { 'fa-train', 'fa-subway', 'fa-medium', + 'fa-git', + 'fa-y-combinator-square', + 'fa-yc-square', + 'fa-hacker-news', + 'fa-yc', + 'fa-y-combinator', + 'fa-optin-monster', + 'fa-opencart', + 'fa-expeditedssl', + 'fa-battery-4', + 'fa-battery-full', + 'fa-battery-3', + 'fa-battery-three-quarters', + 'fa-battery-2', + 'fa-battery-half', + 'fa-battery-1', + 'fa-battery-quarter', + 'fa-battery-0', + 'fa-battery-empty', + 'fa-mouse-pointer', + 'fa-i-cursor', + 'fa-object-group', + 'fa-object-ungroup', + 'fa-sticky-note', + 'fa-sticky-note-o', + 'fa-cc-jcb', + 'fa-cc-diners-club', + 'fa-clone', + 'fa-balance-scale', + 'fa-hourglass-o', + 'fa-hourglass-1', + 'fa-hourglass-start', + 'fa-hourglass-2', + 'fa-hourglass-half', + 'fa-hourglass-3', + 'fa-hourglass-end', + 'fa-hourglass', + 'fa-hand-grab-o', + 'fa-hand-rock-o', + 'fa-hand-stop-o', + 'fa-hand-paper-o', + 'fa-hand-scissors-o', + 'fa-hand-lizard-o', + 'fa-hand-spock-o', + 'fa-hand-pointer-o', + 'fa-hand-peace-o', + 'fa-trademark', + 'fa-registered', + 'fa-creative-commons', + 'fa-gg', + 'fa-gg-circle', + 'fa-tripadvisor', + 'fa-odnoklassniki', + 'fa-odnoklassniki-square', + 'fa-get-pocket', + 'fa-wikipedia-w', + 'fa-safari', + 'fa-chrome', + 'fa-firefox', + 'fa-opera', + 'fa-internet-explorer', + 'fa-tv', + 'fa-television', + 'fa-contao', + 'fa-500px', + 'fa-amazon', + 'fa-calendar-plus-o', + 'fa-calendar-minus-o', + 'fa-calendar-times-o', + 'fa-calendar-check-o', + 'fa-industry', + 'fa-map-pin', + 'fa-map-signs', + 'fa-map-o', + 'fa-map', + 'fa-commenting', + 'fa-commenting-o', + 'fa-houzz', + 'fa-vimeo', + 'fa-black-tie', + 'fa-fonticons', + ); } diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php index 626dcd2781..973592a94c 100644 --- a/src/view/phui/PHUIObjectItemView.php +++ b/src/view/phui/PHUIObjectItemView.php @@ -24,6 +24,8 @@ final class PHUIObjectItemView extends AphrontTagView { private $imageIcon; private $titleText; private $badge; + private $countdownNum; + private $countdownNoun; const AGE_FRESH = 'fresh'; const AGE_STALE = 'stale'; @@ -105,6 +107,12 @@ final class PHUIObjectItemView extends AphrontTagView { return $this; } + public function setCountdown($num, $noun) { + $this->countdownNum = $num; + $this->countdownNoun = $noun; + return $this; + } + public function setTitleText($title_text) { $this->titleText = $title_text; return $this; @@ -603,6 +611,24 @@ final class PHUIObjectItemView extends AphrontTagView { $this->badge); } + if ($this->countdownNum) { + $countdown = phutil_tag( + 'div', + array( + 'class' => 'phui-object-item-countdown-number', + ), + array( + phutil_tag_div('', $this->countdownNum), + phutil_tag_div('', $this->countdownNoun), + )); + $column0 = phutil_tag( + 'div', + array( + 'class' => 'phui-object-item-col0 phui-object-item-countdown', + ), + $countdown); + } + $column1 = phutil_tag( 'div', array( diff --git a/src/view/phui/PHUITimelineView.php b/src/view/phui/PHUITimelineView.php index 17178b8135..d8ba96c140 100644 --- a/src/view/phui/PHUITimelineView.php +++ b/src/view/phui/PHUITimelineView.php @@ -255,6 +255,7 @@ final class PHUITimelineView extends AphrontView { ->setIcon($badge->getIcon()) ->setQuality($badge->getQuality()) ->setHeader($badge->getName()) + ->setTipDirection('E') ->setHref('/badges/view/'.$badge->getID()); $event->addBadge($badge_view); diff --git a/src/view/phui/calendar/PHUICalendarMonthView.php b/src/view/phui/calendar/PHUICalendarMonthView.php index 06d15bbcc9..0308f542e5 100644 --- a/src/view/phui/calendar/PHUICalendarMonthView.php +++ b/src/view/phui/calendar/PHUICalendarMonthView.php @@ -253,7 +253,7 @@ final class PHUICalendarMonthView extends AphrontView { $today_class .= ' last-weekday'; } - $today_slot = phutil_tag ( + $today_slot = phutil_tag( 'div', array( 'class' => $today_class, diff --git a/webroot/rsrc/css/aphront/two-column.css b/webroot/rsrc/css/aphront/two-column.css deleted file mode 100644 index e9a0217e8c..0000000000 --- a/webroot/rsrc/css/aphront/two-column.css +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @provides aphront-two-column-view-css - */ - -.aphront-two-column { - position: relative; -} - -.device-desktop .aphront-two-column.aphront-two-column-padded { - margin: 20px; -} - -.device-desktop .aphront-two-column .aphront-main-column { - margin-right: 300px; -} - -.device-desktop .aphront-two-column .aphront-side-column { - width: 300px; - position: absolute; - top: 0; - right: 0; -} - -.device-desktop .aphront-two-column-centered { - width: 980px; - margin: 0 auto; -} - -.device-desktop .aphront-two-column-centered .aphront-main-column { - float: left; - width: 820px; -} - -.device-desktop .aphront-two-column-centered .aphront-side-column { - width: 160px; - float: right; -} - -.device-phone .aphront-two-column.aphront-two-column-padded { - margin: 10px; -} diff --git a/webroot/rsrc/css/application/conpherence/message-pane.css b/webroot/rsrc/css/application/conpherence/message-pane.css index 9da3de6d7f..886700ccf5 100644 --- a/webroot/rsrc/css/application/conpherence/message-pane.css +++ b/webroot/rsrc/css/application/conpherence/message-pane.css @@ -344,3 +344,7 @@ height: 24px; width: 100%; } + +.conpherence-message .phabricator-remarkup .remarkup-code-block pre { + max-height: 200px; +} diff --git a/webroot/rsrc/css/application/countdown/timer.css b/webroot/rsrc/css/application/countdown/timer.css index 34a732128c..8b87aa6ed2 100644 --- a/webroot/rsrc/css/application/countdown/timer.css +++ b/webroot/rsrc/css/application/countdown/timer.css @@ -3,34 +3,47 @@ */ .phabricator-timer { - margin: 16px; + margin: 16px 16px 0 16px; border: 1px solid {$lightblueborder}; - border-radius: 4px; + border-radius: 3px; background: #ffffff; } +.device .phabricator-timer { + margin-left: 8px; + margin-right: 8px; +} + .phabricator-remarkup .phabricator-timer { - width: 360px; + max-width: 360px; margin: 0 0 12px 0; } +.device-phone .phabricator-remarkup .phabricator-timer { + width: auto; +} + .phabricator-timer-header { - font-size: {$biggerfontsize}; font-weight: bold; - padding: 4px 8px; + padding: 8px; background: {$bluebackground}; border-radius: 3px 3px 0 0; - border-bottom: 1px solid {$lightblueborder}; +} + +.phabricator-timer-header a { + color: {$darkbluetext}; + font-weight: normal; } .phabricator-timer-table { width: 100%; - margin: 8px 0; + margin: 8px 0 0 0; } .phabricator-timer-table th { text-align: center; - color: {$greytext}; + font-size: {$biggerfontsize}; + color: {$bluetext}; width: 10%; padding: 4px; } @@ -39,10 +52,23 @@ padding: 4px; text-align: center; font-size: 36px; + font-weight: bold; overflow: hidden; line-height: auto; height: auto; - line-height: 36px; + line-height: 44px; +} + +.phabricator-timer-table td.phabricator-timer-foot { + font-size: {$normalfontsize}; + line-height: 16px; + border-top: 1px solid {$thinblueborder}; + color: {$bluetext}; + font-weight: normal; + padding: 8px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + text-align: center; } .phabricator-timer-table small { diff --git a/webroot/rsrc/css/application/herald/herald-test.css b/webroot/rsrc/css/application/herald/herald-test.css index 178d54653d..67b49145d5 100644 --- a/webroot/rsrc/css/application/herald/herald-test.css +++ b/webroot/rsrc/css/application/herald/herald-test.css @@ -2,79 +2,10 @@ * @provides herald-test-css */ -ul.herald-explain-list { - margin: 12px; -} - -div.herald-condition-note { - clear: both; - margin: .5em 0em .53em 86px; - padding: .5em 1em; - background: #FFFF00; - font-weight: bold; -} - -ul.herald-explain-list .herald-outcome { - margin-right: 6px; - width: 50px; - text-align: center; - position: relative; - float: left; - font-weight: bold; - padding: 1px 2px; -} - -ul.herald-explain-list .condition-fail, -ul.herald-explain-list .rule-fail { +.herald-condition-note { color: {$red}; } -ul.herald-explain-list .condition-pass, -ul.herald-explain-list .rule-pass { - color: {$green}; -} - -ul.herald-explain-list li.herald-rule-pass, -ul.herald-explain-list li.herald-rule-fail { - margin: 0 0 8px; -} - -ul.herald-explain-list div.rule-name { - padding: 4px 0 8px 0; -} - -ul.herald-explain-list li.herald-rule-fail, -ul.herald-explain-list li.herald-rule-pass { - background: #ffffff; -} - -ul.herald-explain-list ul { - margin: 4px; -} - -ul.herald-explain-list ul li { - padding: 2px 0; -} - -.outcome-failure, -.outcome-success { - font-weight: bold; -} - -.outcome-failure { - color: {$red}; -} - -.outcome-success { - color: {$green}; -} - -.action-header { - font-weight: bold; - padding-top: 12px; - border-bottom: 1px solid {$thinblueborder}; -} - textarea.herald-field-value-transcript { width: 100%; height: 10em; diff --git a/webroot/rsrc/css/application/phame/phame.css b/webroot/rsrc/css/application/phame/phame.css index 2569711095..095602b22b 100644 --- a/webroot/rsrc/css/application/phame/phame.css +++ b/webroot/rsrc/css/application/phame/phame.css @@ -2,120 +2,6 @@ * @provides phame-css */ -.notice { - background: #F3F3FF; - border: 1px solid #008; - margin: 16px 16px 4px 26px; -} -.notice h3 { - background: #E3E3FF; - padding: 8px; -} - -.notice h4 { - font-weight: normal; - padding: 8px; -} - -.phame-post-preview-header { - margin: 0px 0px 16px 0px; -} - -.device-desktop .phame-post-list { - max-width: 600px; -} - -.phame-post-list .phui-info-view { - margin: 0; -} - -.phame-post-list .phui-icon-view:hover { - text-decoration: none; -} - -.blog-post-list { - clear: left; - float: left; - width: 70%; - margin: 16px 0px 16px 16px; - padding: 0px 8px 12px 8px; -} - -.device .blog-post-list { - float: none; - width: 90%; - margin: 16px auto; -} - -.blog-post-list-full { - clear: left; - float: left; - margin: 16px 0px 0px 0px; - padding: 0px 16px 0px 16px; -} - -.device .blog-post-list-full { - float: none; - margin: 16px auto; -} - -.blog-detail { - float: right; - clear: right; - width: 20%; - margin: 16px 16px 16px 0px; -} - -.device .blog-detail { - float: none; - margin: 16px auto; - width: 90%; -} - -.blog-detail .description { - margin: 16px 0px 16px 0px; -} - -.blog-detail .bloggers { - font-size: {$smallerfontsize}; -} - -.blog-post, -.blog-detail { - border: 1px solid #DBDBDB; - background: #F9F9F9; - padding: 20px; -} - -.blog-post { - margin: 0px 0px 20px 0px; -} - -.blog-post .header { - padding: 0px 0px 16px 0px; -} - -.blog-post .header h1 { - clear: none; -} - -.blog-post .header .last-updated { - color: {$greytext}; - clear: none; - font-size: {$smallerfontsize}; -} - -.blog-post .header .buttons { - float: right; -} -.blog-post .header .buttons a { - margin: 0px 0px 0px 12px; -} - -.more-and-comments { - padding: 12px 0px 12px 0px; -} - .fb-comments, .fb-comments span, .fb-comments iframe[style] { diff --git a/webroot/rsrc/css/application/ponder/comments.css b/webroot/rsrc/css/application/ponder/comments.css deleted file mode 100644 index ca712b1d74..0000000000 --- a/webroot/rsrc/css/application/ponder/comments.css +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @provides ponder-comment-table-css - */ - -.ponder-show-comments { - text-align: center; - padding: 8px; - margin: 0 16px; - float: right; - font-weight: bold; - background: #fff; - border-bottom: 1px solid {$blueborder}; - border-left: 1px solid {$lightblueborder}; - border-right: 1px solid {$lightblueborder}; -} - -.ponder-comments { - width: 480px; - margin: 5px 0 0 60px; -} - -.device .ponder-comments { - width: 100%; - margin: 5px 0 0 0; -} - -.ponder-comments th { - width: 0px; - height: 0px; -} - -.ponder-comments td { - vertical-align: top; - padding: 6px; - border-bottom: 1px solid {$thinblueborder}; - background: #fff; -} - -.ponder-datestamp { - font-size: {$smallestfontsize}; - color: {$greytext}; -} - -.ponder-label { - display: block; - width: 100%; - font-weight: bold; - color: #333; - text-align: left; - margin: 0px 0px 6px; - padding: 6px 4px; - background: #ccc; - border-bottom: 1px solid #aaa; - cursor: pointer; -} - -td .aphront-form-control { - padding: 0; -} - -td .aphront-form-control-submit { - display: block; -} - -td .aphront-form-input { - margin: 0; - width: 100%; -} - -td .aphront-form-control textarea { - height: 50px; -} - -.ponder-comment-markup p { - margin: 0 0 5px 0; -} - -.ponder-comment-markup h2, -.ponder-comment-markup h3, -.ponder-comment-markup h4, -.ponder-comment-markup h5 { - margin: 0; - font-size: inherit; - font-weight: normal; -} diff --git a/webroot/rsrc/css/application/ponder/feed.css b/webroot/rsrc/css/application/ponder/feed.css deleted file mode 100644 index e2c0eefb21..0000000000 --- a/webroot/rsrc/css/application/ponder/feed.css +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @provides ponder-feed-view-css - */ - -.ponder-question-summary { - width: 100%; - background: #DFDFE3; - float: left; - clear: both; - margin-top: 1px; - padding: 1px; -} - -.ponder-answer-summary { - width : 100%; - background : #DFDFE3; - float : left; - clear : both; - margin-top : 1px; - padding : 1px; -} - -.ponder-summary-votes { - width : 50px; - height : 36pt; - font-size : 18pt; - text-align : center; - background : #EEE; - border : 1px solid #BBB; - float : left; - margin : 2px; - padding-top : 2px; -} - -.ponder-summary-answers { - width : 50px; - height : 36pt; - font-size : 18pt; - text-align : center; - background : #EEE; - border : 1px solid #BBB; - float : left; - margin : 2px; - padding-top : 2px; -} - -.ponder-question-label { - font-size : 6pt; -} - -h2.ponder-question-title { - font-size : 12pt; - margin : 2px; - padding : 0; -} - -h2.ponder-answer-title { - font-size : 12pt; - margin : 2px; - padding : 0; -} - -.ponder-metadata { - padding-left : 5px; - width : 650px; - float : left; -} - -.ponder-small-metadata { - font-size : 7.5pt; - color : #555; - margin : 0; - text-align : right; -} diff --git a/webroot/rsrc/css/application/ponder/vote.css b/webroot/rsrc/css/application/ponder/ponder-view.css similarity index 61% rename from webroot/rsrc/css/application/ponder/vote.css rename to webroot/rsrc/css/application/ponder/ponder-view.css index 3436df9882..237c3e7676 100644 --- a/webroot/rsrc/css/application/ponder/vote.css +++ b/webroot/rsrc/css/application/ponder/ponder-view.css @@ -1,5 +1,5 @@ /** - * @provides ponder-vote-css + * @provides ponder-view-css */ .ponder-votable { @@ -40,3 +40,20 @@ line-height: 20px; font-weight: bold; } + +.ponder-show-comments { + text-align: center; + padding: 8px; + margin: 0 16px; + float: right; + font-weight: bold; + background: #fff; + border-bottom: 1px solid {$blueborder}; + border-left: 1px solid {$lightblueborder}; + border-right: 1px solid {$lightblueborder}; +} + +.device-desktop .ponder-comments-view { + width: 90%; + margin: 0 auto; +} diff --git a/webroot/rsrc/css/application/ponder/post.css b/webroot/rsrc/css/application/ponder/post.css deleted file mode 100644 index c1f3c67c55..0000000000 --- a/webroot/rsrc/css/application/ponder/post.css +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @provides ponder-post-css - */ - -.ponder-post-list { - max-width: 1162px; -} - -.ponder-add-answer-panel { - max-width: 1162px; -} - -.ponder-post-list .anchor-target { - background-color: #ffffdd; - border-color: #ffff00; -} - -.ponder-post-core .phabricator-remarkup .remarkup-code-block { - width: 88ex; - width: 81ch; -} - -.ponder-question { - background: white; -} diff --git a/webroot/rsrc/css/font/font-awesome.css b/webroot/rsrc/css/font/font-awesome.css index 7766362550..1658708f4e 100644 --- a/webroot/rsrc/css/font/font-awesome.css +++ b/webroot/rsrc/css/font/font-awesome.css @@ -3,15 +3,15 @@ */ /*! - * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */ /* FONT PATH * -------------------------- */ @font-face { font-family: 'FontAwesome'; - src: url('/rsrc/externals/font/fontawesome/fontawesome-webfont.eot?v=4.3.0'); - src: url('/rsrc/externals/font/fontawesome/fontawesome-webfont.eot?#iefix&v=4.3.0') format('embedded-opentype'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2?v=4.3.0') format('woff2'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.woff?v=4.3.0') format('woff'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf?v=4.3.0') format('truetype'); + src: url('/rsrc/externals/font/fontawesome/fontawesome-webfont.eot?v=4.4.0'); + src: url('/rsrc/externals/font/fontawesome/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2?v=4.4.0') format('woff2'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.woff?v=4.4.0') format('woff'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf?v=4.4.0') format('truetype'); font-weight: normal; font-style: normal; } @@ -40,6 +40,7 @@ width: 1.28571429em; text-align: center; } + /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen readers do not read off random characters that represent icons */ .fa-glass:before { @@ -502,6 +503,7 @@ .fa-credit-card:before { content: "\f09d"; } +.fa-feed:before, .fa-rss:before { content: "\f09e"; } @@ -1383,6 +1385,8 @@ .fa-git:before { content: "\f1d3"; } +.fa-y-combinator-square:before, +.fa-yc-square:before, .fa-hacker-news:before { content: "\f1d4"; } @@ -1407,7 +1411,6 @@ .fa-history:before { content: "\f1da"; } -.fa-genderless:before, .fa-circle-thin:before { content: "\f1db"; } @@ -1612,6 +1615,7 @@ .fa-mercury:before { content: "\f223"; } +.fa-intersex:before, .fa-transgender:before { content: "\f224"; } @@ -1639,6 +1643,9 @@ .fa-neuter:before { content: "\f22c"; } +.fa-genderless:before { + content: "\f22d"; +} .fa-facebook-official:before { content: "\f230"; } @@ -1673,3 +1680,210 @@ .fa-medium:before { content: "\f23a"; } +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} diff --git a/webroot/rsrc/css/phui/phui-badge.css b/webroot/rsrc/css/phui/phui-badge.css index e5f04e2707..f45a88f258 100644 --- a/webroot/rsrc/css/phui/phui-badge.css +++ b/webroot/rsrc/css/phui/phui-badge.css @@ -60,7 +60,8 @@ display: block; position: absolute; width: 128px; - height: 100%; + height: 180px; + overflow: hidden; backface-visibility: hidden; -webkit-backface-visibility: hidden; @@ -113,6 +114,7 @@ font-weight: bold; padding-top: 12px; display: block; + word-break: break-word; } .phui-badge-quality { @@ -124,6 +126,7 @@ .phui-badge-view-subhead { color: {$lightgreytext}; font-size: {$smallerfontsize}; + word-break: break-word; } .phui-badge-card-back { diff --git a/webroot/rsrc/css/phui/phui-feed-story.css b/webroot/rsrc/css/phui/phui-feed-story.css index 4bc505d0c1..9162d68328 100644 --- a/webroot/rsrc/css/phui/phui-feed-story.css +++ b/webroot/rsrc/css/phui/phui-feed-story.css @@ -61,8 +61,7 @@ } .phui-feed-story-bigtext-post h3 { - font-size: 18px; - font-weight: 200; + font-size: {$biggestfontsize}; line-height: 18px; color: {$darkgreytext}; margin: 0 0 5px 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 index 2be3de770d..fe965b1b00 100644 --- a/webroot/rsrc/css/phui/phui-object-item-list-view.css +++ b/webroot/rsrc/css/phui/phui-object-item-list-view.css @@ -627,6 +627,19 @@ ul.phui-object-item-list-view .phui-object-item-selected 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 ------------------------------------------------------------ */ diff --git a/webroot/rsrc/css/phui/phui-property-list-view.css b/webroot/rsrc/css/phui/phui-property-list-view.css index b4acc54994..71a096e69e 100644 --- a/webroot/rsrc/css/phui/phui-property-list-view.css +++ b/webroot/rsrc/css/phui/phui-property-list-view.css @@ -68,7 +68,6 @@ .phui-property-list-value { color: {$darkgreytext}; - line-height: 17px; } .device-desktop .phui-property-list-value { diff --git a/webroot/rsrc/css/phui/phui-timeline-view.css b/webroot/rsrc/css/phui/phui-timeline-view.css index fdef1d07a3..de6658f7dc 100644 --- a/webroot/rsrc/css/phui/phui-timeline-view.css +++ b/webroot/rsrc/css/phui/phui-timeline-view.css @@ -395,3 +395,13 @@ a.phui-timeline-menu .phui-icon-view { top: 52px; width: 54px; } + +.phui-timeline-badges .phui-badge-mini { + height: 18px; + width: 18px; + line-height: 16px; +} + +.phui-timeline-badges .phui-badge-mini .phui-icon-view { + font-size: 10px; +} diff --git a/webroot/rsrc/css/phui/phui-workboard-view.css b/webroot/rsrc/css/phui/phui-workboard-view.css index 7299059496..2befbd7823 100644 --- a/webroot/rsrc/css/phui/phui-workboard-view.css +++ b/webroot/rsrc/css/phui/phui-workboard-view.css @@ -129,6 +129,12 @@ padding: 0 8px; } +.device-phone .project-board-header .phui-header-subheader { + display: block; + margin: 8px 0 2px 0; + padding: 0; +} + .device-desktop .phabricator-icon-nav.project-board-nav .phabricator-nav-local { margin-top: 64px; diff --git a/webroot/rsrc/css/phui/phui-workpanel-view.css b/webroot/rsrc/css/phui/phui-workpanel-view.css index b042bda0e2..9b8943ceeb 100644 --- a/webroot/rsrc/css/phui/phui-workpanel-view.css +++ b/webroot/rsrc/css/phui/phui-workpanel-view.css @@ -90,6 +90,11 @@ width: 300px; } +.device-phone .aphront-multi-column-fixed .phui-workpanel-view, +.device-phone .phui-workpanel-view .phui-header-shell { + width: auto; +} + .phui-workpanel-body .phui-object-item-list-view { min-height: 54px; } diff --git a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.eot b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.eot index 33b2bb8005..a30335d748 100644 Binary files a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.eot and b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.eot differ diff --git a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf index ed9372f8ea..d7994e1308 100644 Binary files a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf and b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf differ diff --git a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff index 8b280b98fa..6fd4ede0f3 100644 Binary files a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff and b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff differ diff --git a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2 b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2 index 3311d58514..5560193ccc 100644 Binary files a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2 and b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2 differ diff --git a/webroot/rsrc/js/application/herald/HeraldRuleEditor.js b/webroot/rsrc/js/application/herald/HeraldRuleEditor.js index bf1db41dfc..82100062ed 100644 --- a/webroot/rsrc/js/application/herald/HeraldRuleEditor.js +++ b/webroot/rsrc/js/application/herald/HeraldRuleEditor.js @@ -322,21 +322,11 @@ JX.install('HeraldRuleEditor', { _renderCondition : function(row_id) { var groups = this._config.info.fields; - var optgroups = []; - for (var ii = 0; ii < groups.length; ii++) { - var group = groups[ii]; - var options = []; - for (var k in group.options) { - options.push(JX.$N('option', {value: k}, group.options[k])); - } - optgroups.push(JX.$N('optgroup', {label: group.label}, options)); - } - var attrs = { sigil: 'field-select' }; - var field_select = JX.$N('select', attrs, optgroups); + var field_select = this._renderGroupSelect(groups, attrs); field_select.value = this._config.conditions[row_id][0]; var field_cell = JX.$N('td', {sigil: 'field-cell'}, field_select); @@ -352,6 +342,21 @@ JX.install('HeraldRuleEditor', { delete actions[k]; } }, + + _renderGroupSelect: function(groups, attrs) { + var optgroups = []; + for (var ii = 0; ii < groups.length; ii++) { + var group = groups[ii]; + var options = []; + for (var k in group.options) { + options.push(JX.$N('option', {value: k}, group.options[k])); + } + optgroups.push(JX.$N('optgroup', {label: group.label}, options)); + } + + return JX.$N('select', attrs, optgroups); + }, + _newAction : function(data) { data = data || []; var temprow = this._actionsRowManager.addRow([]); @@ -361,11 +366,16 @@ JX.install('HeraldRuleEditor', { this._renderAction(data)); this._onactionchange(r); }, + _renderAction : function(action) { - var action_select = this._renderSelect( - this._config.info.actions, - action[0], - 'action-select'); + var groups = this._config.info.actions; + var attrs = { + sigil: 'action-select' + }; + + var action_select = this._renderGroupSelect(groups, attrs); + action_select.value = action[0]; + var action_cell = JX.$N('td', {sigil: 'action-cell'}, action_select); var target_cell = JX.$N(