diff --git a/resources/celerity/map.php b/resources/celerity/map.php index c67682e8f7..44ba4be6cd 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'e4f1ea81', + 'core.pkg.css' => '91bbffc2', 'core.pkg.js' => '47dc9ebb', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -104,13 +104,13 @@ return array( 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/core/core.css' => '78e8d7ea', - 'rsrc/css/core/remarkup.css' => '2193fc05', + 'rsrc/css/core/remarkup.css' => '88e1ebb6', 'rsrc/css/core/syntax.css' => '9fd11da8', 'rsrc/css/core/z-index.css' => '57ddcaa2', 'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa', - 'rsrc/css/font/font-aleo.css' => 'b61d3062', - 'rsrc/css/font/font-awesome.css' => 'd2fc4e8d', - 'rsrc/css/font/font-lato.css' => '5ab1a46a', + 'rsrc/css/font/font-aleo.css' => '8bdb2835', + 'rsrc/css/font/font-awesome.css' => 'c43323c5', + 'rsrc/css/font/font-lato.css' => 'c7ccd872', 'rsrc/css/font/phui-font-icon-base.css' => 'ecbbb4c2', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', 'rsrc/css/layout/phabricator-hovercard-view.css' => '1239cd52', @@ -126,11 +126,11 @@ return array( 'rsrc/css/phui/phui-box.css' => 'a5bb366d', 'rsrc/css/phui/phui-button.css' => '16020a60', 'rsrc/css/phui/phui-crumbs-view.css' => '414406b5', - 'rsrc/css/phui/phui-document-pro.css' => '7f3009ce', - 'rsrc/css/phui/phui-document.css' => 'f841ad0a', + 'rsrc/css/phui/phui-document-pro.css' => '5f75ed99', + 'rsrc/css/phui/phui-document.css' => 'a4a1c3b9', 'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23', - 'rsrc/css/phui/phui-fontkit.css' => 'c9d63950', - 'rsrc/css/phui/phui-form-view.css' => '621b21c5', + 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', + 'rsrc/css/phui/phui-form-view.css' => 'c1d2ef29', 'rsrc/css/phui/phui-form.css' => 'afdb2c6e', 'rsrc/css/phui/phui-header-view.css' => '55bb32dd', 'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6', @@ -143,7 +143,7 @@ return array( 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', - 'rsrc/css/phui/phui-remarkup-preview.css' => '867f85b3', + 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '888cedb8', 'rsrc/css/phui/phui-tag-view.css' => 'e60e227b', @@ -158,30 +158,36 @@ return array( 'rsrc/css/sprite-projects.css' => 'e5ad842a', 'rsrc/css/sprite-tokens.css' => '4f399012', 'rsrc/externals/font/aleo/aleo-bold.eot' => 'd3d3bed7', + 'rsrc/externals/font/aleo/aleo-bold.svg' => '45899c8e', 'rsrc/externals/font/aleo/aleo-bold.ttf' => '4b08bef0', 'rsrc/externals/font/aleo/aleo-bold.woff' => '93b513a1', 'rsrc/externals/font/aleo/aleo-bold.woff2' => '75fbf322', 'rsrc/externals/font/aleo/aleo-regular.eot' => 'a4e29e2f', + 'rsrc/externals/font/aleo/aleo-regular.svg' => '42a86f7a', 'rsrc/externals/font/aleo/aleo-regular.ttf' => '751e7479', 'rsrc/externals/font/aleo/aleo-regular.woff' => 'c3744be9', 'rsrc/externals/font/aleo/aleo-regular.woff2' => '851aa0ee', - '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/fontawesome/fontawesome-webfont.eot' => '346fbcc5', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '510fccb2', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => '0334f580', + 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '45dca585', 'rsrc/externals/font/lato/lato-bold.eot' => '99fbcf8c', + 'rsrc/externals/font/lato/lato-bold.svg' => '2aa83045', 'rsrc/externals/font/lato/lato-bold.ttf' => '0a7141f7', 'rsrc/externals/font/lato/lato-bold.woff' => 'f5db2061', 'rsrc/externals/font/lato/lato-bold.woff2' => '37a94ecd', 'rsrc/externals/font/lato/lato-bolditalic.eot' => 'b93389d0', + 'rsrc/externals/font/lato/lato-bolditalic.svg' => '5442e1ef', 'rsrc/externals/font/lato/lato-bolditalic.ttf' => 'dad31252', 'rsrc/externals/font/lato/lato-bolditalic.woff' => 'e53bcf47', 'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'd035007f', 'rsrc/externals/font/lato/lato-italic.eot' => '6a903f5d', + 'rsrc/externals/font/lato/lato-italic.svg' => '0dc7cf2f', 'rsrc/externals/font/lato/lato-italic.ttf' => '629f64f0', 'rsrc/externals/font/lato/lato-italic.woff' => '678dc4bb', 'rsrc/externals/font/lato/lato-italic.woff2' => '7c8dd650', 'rsrc/externals/font/lato/lato-regular.eot' => '848dfb1e', + 'rsrc/externals/font/lato/lato-regular.svg' => 'cbd5fd6b', 'rsrc/externals/font/lato/lato-regular.ttf' => 'e270165b', 'rsrc/externals/font/lato/lato-regular.woff' => '13d39fe2', 'rsrc/externals/font/lato/lato-regular.woff2' => '57a9f742', @@ -255,6 +261,7 @@ return array( 'rsrc/favicons/favicon-16x16.png' => 'ee2523ac', 'rsrc/favicons/favicon-32x32.png' => 'b6a8150e', 'rsrc/favicons/favicon-96x96.png' => '8f7ea177', + 'rsrc/favicons/mask-icon.svg' => '0460cb1f', 'rsrc/image/BFCFDA.png' => 'd5ec91f4', 'rsrc/image/actions/edit.png' => '2fc41442', 'rsrc/image/avatar.png' => '3eb28cd9', @@ -395,7 +402,7 @@ return array( 'rsrc/js/application/owners/OwnersPathEditor.js' => 'aa1733d0', 'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc', - 'rsrc/js/application/phame/phame-post-preview.js' => 'be807912', + 'rsrc/js/application/phame/phame-post-preview.js' => 'd6bba572', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '246dc085', 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => 'fbe497e7', 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '3f5d6dbf', @@ -412,6 +419,7 @@ return array( 'rsrc/js/application/repository/repository-crossreference.js' => 'e5339c43', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08', 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f', + 'rsrc/js/application/transactions/behavior-reorder-fields.js' => 'b59e1e96', 'rsrc/js/application/transactions/behavior-show-older-transactions.js' => 'dbbf48b6', 'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => 'b23b49e6', 'rsrc/js/application/transactions/behavior-transaction-list.js' => '13c739ea', @@ -529,9 +537,9 @@ return array( 'diffusion-readme-css' => '2106ea08', 'diffusion-source-css' => '075ba788', 'diviner-shared-css' => 'aa3656aa', - 'font-aleo' => 'b61d3062', - 'font-fontawesome' => 'd2fc4e8d', - 'font-lato' => '5ab1a46a', + 'font-aleo' => '8bdb2835', + 'font-fontawesome' => 'c43323c5', + 'font-lato' => 'c7ccd872', 'global-drag-and-drop-css' => '697324ad', 'harbormaster-css' => 'b0758ca5', 'herald-css' => '826075fa', @@ -584,6 +592,7 @@ return array( 'javelin-behavior-doorkeeper-tag' => 'e5822781', 'javelin-behavior-drydock-live-operation-status' => '901935ef', 'javelin-behavior-durable-column' => 'c72aa091', + 'javelin-behavior-editengine-reorder-fields' => 'b59e1e96', 'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-event-all-day' => '38dcf3c8', 'javelin-behavior-fancy-datepicker' => '8ae55229', @@ -628,7 +637,7 @@ return array( 'javelin-behavior-phabricator-transaction-comment-form' => 'b23b49e6', 'javelin-behavior-phabricator-transaction-list' => '13c739ea', 'javelin-behavior-phabricator-watch-anchor' => '9f36c42d', - 'javelin-behavior-phame-post-preview' => 'be807912', + 'javelin-behavior-phame-post-preview' => 'd6bba572', 'javelin-behavior-pholio-mock-edit' => '246dc085', 'javelin-behavior-pholio-mock-view' => 'fbe497e7', 'javelin-behavior-phui-dropdown-menu' => '54733475', @@ -740,7 +749,7 @@ return array( 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => '6920d200', - 'phabricator-remarkup-css' => '2193fc05', + 'phabricator-remarkup-css' => '88e1ebb6', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-side-menu-view-css' => 'bec2458e', @@ -780,13 +789,13 @@ return array( 'phui-calendar-list-css' => 'c1c7f338', 'phui-calendar-month-css' => '476be7e0', 'phui-crumbs-view-css' => '414406b5', - 'phui-document-view-css' => 'f841ad0a', - 'phui-document-view-pro-css' => '7f3009ce', + 'phui-document-view-css' => 'a4a1c3b9', + 'phui-document-view-pro-css' => '5f75ed99', 'phui-feed-story-css' => 'b7b26d23', 'phui-font-icon-base-css' => 'ecbbb4c2', - 'phui-fontkit-css' => 'c9d63950', + 'phui-fontkit-css' => '9cda225e', 'phui-form-css' => 'afdb2c6e', - 'phui-form-view-css' => '621b21c5', + 'phui-form-view-css' => 'c1d2ef29', 'phui-header-view-css' => '55bb32dd', 'phui-icon-view-css' => 'b0a6b1b6', 'phui-image-mask-css' => '5a8b09c8', @@ -799,7 +808,7 @@ return array( 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', 'phui-property-list-view-css' => '27b2849e', - 'phui-remarkup-preview-css' => '867f85b3', + 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '888cedb8', 'phui-tag-view-css' => 'e60e227b', @@ -1206,9 +1215,6 @@ return array( 'javelin-vector', 'javelin-dom', ), - '5ab1a46a' => array( - 'phui-fontkit-css', - ), '5b2e3e2b' => array( 'javelin-stratcom', 'javelin-request', @@ -1506,6 +1512,9 @@ return array( 'javelin-request', 'javelin-typeahead-source', ), + '8bdb2835' => array( + 'phui-fontkit-css', + ), '8ce821c5' => array( 'phabricator-notification', 'javelin-stratcom', @@ -1707,6 +1716,13 @@ return array( 'javelin-typeahead-preloaded-source', 'javelin-util', ), + 'b59e1e96' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-workflow', + 'javelin-dom', + 'phabricator-draggable-list', + ), 'b5c256b8' => array( 'javelin-install', 'javelin-dom', @@ -1717,9 +1733,6 @@ return array( 'javelin-dom', 'javelin-util', ), - 'b61d3062' => array( - 'phui-fontkit-css', - ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1752,12 +1765,6 @@ return array( 'javelin-util', 'javelin-request', ), - 'be807912' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-util', - 'phabricator-shaped-request', - ), 'c1700f6f' => array( 'javelin-install', 'javelin-util', @@ -1775,6 +1782,9 @@ return array( 'phabricator-keyboard-shortcut', 'conpherence-thread-manager', ), + 'c7ccd872' => array( + 'phui-fontkit-css', + ), 'c8e57404' => array( 'javelin-behavior', 'javelin-dom', @@ -1835,6 +1845,12 @@ return array( 'javelin-dom', 'javelin-stratcom', ), + 'd6bba572' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-util', + 'phabricator-shaped-request', + ), 'd75709e6' => array( 'javelin-behavior', 'javelin-workflow', diff --git a/resources/sql/autopatches/20151111.phame.blog.archive.1.sql b/resources/sql/autopatches/20151111.phame.blog.archive.1.sql new file mode 100644 index 0000000000..c7e5898e66 --- /dev/null +++ b/resources/sql/autopatches/20151111.phame.blog.archive.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_phame.phame_blog + ADD status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20151111.phame.blog.archive.2.sql b/resources/sql/autopatches/20151111.phame.blog.archive.2.sql new file mode 100644 index 0000000000..ee9ad1e4c7 --- /dev/null +++ b/resources/sql/autopatches/20151111.phame.blog.archive.2.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_phame.phame_blog + SET status = 'active' WHERE status = ''; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 73a0fd7393..4adf9deccd 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1843,6 +1843,8 @@ phutil_register_library_map(array( 'PhabricatorChatLogQuery' => 'applications/chatlog/query/PhabricatorChatLogQuery.php', 'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php', 'PhabricatorClusterConfigOptions' => 'applications/config/option/PhabricatorClusterConfigOptions.php', + 'PhabricatorCommentEditField' => 'applications/transactions/editfield/PhabricatorCommentEditField.php', + 'PhabricatorCommentEditType' => 'applications/transactions/edittype/PhabricatorCommentEditType.php', 'PhabricatorCommitBranchesField' => 'applications/repository/customfield/PhabricatorCommitBranchesField.php', 'PhabricatorCommitCustomField' => 'applications/repository/customfield/PhabricatorCommitCustomField.php', 'PhabricatorCommitMergedCommitsField' => 'applications/repository/customfield/PhabricatorCommitMergedCommitsField.php', @@ -2112,12 +2114,15 @@ phutil_register_library_map(array( 'PhabricatorEditEngine' => 'applications/transactions/editengine/PhabricatorEditEngine.php', 'PhabricatorEditEngineAPIMethod' => 'applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php', 'PhabricatorEditEngineConfiguration' => 'applications/transactions/storage/PhabricatorEditEngineConfiguration.php', + 'PhabricatorEditEngineConfigurationDefaultsController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php', 'PhabricatorEditEngineConfigurationEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php', 'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php', 'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php', 'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php', + 'PhabricatorEditEngineConfigurationLockController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php', 'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php', 'PhabricatorEditEngineConfigurationQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php', + 'PhabricatorEditEngineConfigurationReorderController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php', 'PhabricatorEditEngineConfigurationSaveController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php', 'PhabricatorEditEngineConfigurationSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php', 'PhabricatorEditEngineConfigurationTransaction' => 'applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php', @@ -2810,6 +2815,7 @@ phutil_register_library_map(array( 'PhabricatorRemarkupCowsayBlockInterpreter' => 'infrastructure/markup/interpreter/PhabricatorRemarkupCowsayBlockInterpreter.php', 'PhabricatorRemarkupCustomBlockRule' => 'infrastructure/markup/rule/PhabricatorRemarkupCustomBlockRule.php', 'PhabricatorRemarkupCustomInlineRule' => 'infrastructure/markup/rule/PhabricatorRemarkupCustomInlineRule.php', + 'PhabricatorRemarkupEditField' => 'applications/transactions/editfield/PhabricatorRemarkupEditField.php', 'PhabricatorRemarkupFigletBlockInterpreter' => 'infrastructure/markup/interpreter/PhabricatorRemarkupFigletBlockInterpreter.php', 'PhabricatorRemarkupUIExample' => 'applications/uiexample/examples/PhabricatorRemarkupUIExample.php', 'PhabricatorRepositoriesSetupCheck' => 'applications/config/check/PhabricatorRepositoriesSetupCheck.php', @@ -3271,9 +3277,9 @@ phutil_register_library_map(array( 'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php', 'PhameBasicTemplateBlogSkin' => 'applications/phame/skins/PhameBasicTemplateBlogSkin.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', + 'PhameBlogArchiveController' => 'applications/phame/controller/blog/PhameBlogArchiveController.php', 'PhameBlogController' => 'applications/phame/controller/blog/PhameBlogController.php', 'PhameBlogCreateCapability' => 'applications/phame/capability/PhameBlogCreateCapability.php', - 'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php', 'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php', @@ -3296,7 +3302,6 @@ phutil_register_library_map(array( 'PhamePost' => 'applications/phame/storage/PhamePost.php', 'PhamePostCommentController' => 'applications/phame/controller/post/PhamePostCommentController.php', 'PhamePostController' => 'applications/phame/controller/post/PhamePostController.php', - 'PhamePostDeleteController' => 'applications/phame/controller/post/PhamePostDeleteController.php', 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 'PhamePostEditor' => 'applications/phame/editor/PhamePostEditor.php', 'PhamePostFramedController' => 'applications/phame/controller/post/PhamePostFramedController.php', @@ -3304,7 +3309,6 @@ phutil_register_library_map(array( 'PhamePostMailReceiver' => 'applications/phame/mail/PhamePostMailReceiver.php', 'PhamePostNewController' => 'applications/phame/controller/post/PhamePostNewController.php', 'PhamePostNotLiveController' => 'applications/phame/controller/post/PhamePostNotLiveController.php', - 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php', @@ -5886,6 +5890,8 @@ phutil_register_library_map(array( 'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorClusterConfigOptions' => 'PhabricatorApplicationConfigOptions', + 'PhabricatorCommentEditField' => 'PhabricatorEditField', + 'PhabricatorCommentEditType' => 'PhabricatorEditType', 'PhabricatorCommitBranchesField' => 'PhabricatorCommitCustomField', 'PhabricatorCommitCustomField' => 'PhabricatorCustomField', 'PhabricatorCommitMergedCommitsField' => 'PhabricatorCommitCustomField', @@ -6203,12 +6209,15 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), + 'PhabricatorEditEngineConfigurationDefaultsController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController', + 'PhabricatorEditEngineConfigurationLockController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType', 'PhabricatorEditEngineConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorEditEngineConfigurationReorderController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationSaveController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorEditEngineConfigurationTransaction' => 'PhabricatorApplicationTransaction', @@ -7021,6 +7030,7 @@ phutil_register_library_map(array( 'PhabricatorRemarkupCowsayBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 'PhabricatorRemarkupCustomBlockRule' => 'PhutilRemarkupBlockRule', 'PhabricatorRemarkupCustomInlineRule' => 'PhutilRemarkupRule', + 'PhabricatorRemarkupEditField' => 'PhabricatorEditField', 'PhabricatorRemarkupFigletBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 'PhabricatorRemarkupUIExample' => 'PhabricatorUIExample', 'PhabricatorRepositoriesSetupCheck' => 'PhabricatorSetupCheck', @@ -7573,9 +7583,9 @@ phutil_register_library_map(array( 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', ), + 'PhameBlogArchiveController' => 'PhameBlogController', 'PhameBlogController' => 'PhameController', 'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability', - 'PhameBlogDeleteController' => 'PhameBlogController', 'PhameBlogEditController' => 'PhameBlogController', 'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor', 'PhameBlogFeedController' => 'PhameBlogController', @@ -7607,7 +7617,6 @@ phutil_register_library_map(array( ), 'PhamePostCommentController' => 'PhamePostController', 'PhamePostController' => 'PhameController', - 'PhamePostDeleteController' => 'PhamePostController', 'PhamePostEditController' => 'PhamePostController', 'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor', 'PhamePostFramedController' => 'PhamePostController', @@ -7615,7 +7624,6 @@ phutil_register_library_map(array( 'PhamePostMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhamePostNewController' => 'PhamePostController', 'PhamePostNotLiveController' => 'PhamePostController', - 'PhamePostPreviewController' => 'PhamePostController', 'PhamePostPublishController' => 'PhamePostController', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', diff --git a/src/applications/audit/editor/PhabricatorAuditEditor.php b/src/applications/audit/editor/PhabricatorAuditEditor.php index 51efdf175b..47fa055388 100644 --- a/src/applications/audit/editor/PhabricatorAuditEditor.php +++ b/src/applications/audit/editor/PhabricatorAuditEditor.php @@ -660,7 +660,7 @@ final class PhabricatorAuditEditor } if ($inlines) { - $body->addTextSection( + $body->addRemarkupSection( pht('INLINE COMMENTS'), $this->renderInlineCommentsForMail($object, $inlines)); } diff --git a/src/applications/badges/editor/PhabricatorBadgesEditor.php b/src/applications/badges/editor/PhabricatorBadgesEditor.php index d7403601ec..ad4ccca3d2 100644 --- a/src/applications/badges/editor/PhabricatorBadgesEditor.php +++ b/src/applications/badges/editor/PhabricatorBadgesEditor.php @@ -194,7 +194,7 @@ final class PhabricatorBadgesEditor $body = parent::buildMailBody($object, $xactions); if (strlen($description)) { - $body->addTextSection( + $body->addRemarkupSeciton( pht('BADGE DESCRIPTION'), $object->getDescription()); } diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 8dce30290d..f4b43a0ed1 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -636,7 +636,15 @@ abstract class PhabricatorApplication } protected function getEditRoutePattern($base = null) { - return $base.'(?:(?P[0-9]\d*)/)?(?:(?Pparameters)/)?'; + return $base.'(?:'. + '(?P[0-9]\d*)/)?'. + '(?:'. + '(?:'. + '(?Pparameters)'. + '|'. + '(?:form/(?P[^/]+))'. + ')'. + '/)?'; } protected function getQueryRoutePattern($base = null) { diff --git a/src/applications/celerity/controller/CelerityResourceController.php b/src/applications/celerity/controller/CelerityResourceController.php index eb2ec2b67c..01f6424382 100644 --- a/src/applications/celerity/controller/CelerityResourceController.php +++ b/src/applications/celerity/controller/CelerityResourceController.php @@ -125,6 +125,7 @@ abstract class CelerityResourceController extends PhabricatorController { 'css' => 'text/css; charset=utf-8', 'js' => 'text/javascript; charset=utf-8', 'png' => 'image/png', + 'svg' => 'image/svg+xml', 'gif' => 'image/gif', 'jpg' => 'image/jpeg', 'swf' => 'application/x-shockwave-flash', diff --git a/src/applications/celerity/resources/CelerityResourcesOnDisk.php b/src/applications/celerity/resources/CelerityResourcesOnDisk.php index 9b79a49285..3187c5b9ad 100644 --- a/src/applications/celerity/resources/CelerityResourcesOnDisk.php +++ b/src/applications/celerity/resources/CelerityResourcesOnDisk.php @@ -33,6 +33,7 @@ abstract class CelerityResourcesOnDisk extends CelerityPhysicalResources { 'jpg', 'gif', 'swf', + 'svg', 'woff', 'woff2', 'ttf', diff --git a/src/applications/countdown/editor/PhabricatorCountdownEditor.php b/src/applications/countdown/editor/PhabricatorCountdownEditor.php index f0962beae2..e1eddf2270 100644 --- a/src/applications/countdown/editor/PhabricatorCountdownEditor.php +++ b/src/applications/countdown/editor/PhabricatorCountdownEditor.php @@ -173,7 +173,7 @@ final class PhabricatorCountdownEditor $description = $object->getDescription(); if (strlen($description)) { - $body->addTextSection( + $body->addRemarkupSection( pht('COUNTDOWN DESCRIPTION'), $object->getDescription()); } diff --git a/src/applications/differential/customfield/DifferentialSummaryField.php b/src/applications/differential/customfield/DifferentialSummaryField.php index 91c78537cd..16a3f701c1 100644 --- a/src/applications/differential/customfield/DifferentialSummaryField.php +++ b/src/applications/differential/customfield/DifferentialSummaryField.php @@ -165,7 +165,7 @@ final class DifferentialSummaryField return; } - $body->addTextSection(pht('REVISION SUMMARY'), $summary); + $body->addRemarkupSection(pht('REVISION SUMMARY'), $summary); } } diff --git a/src/applications/differential/customfield/DifferentialTestPlanField.php b/src/applications/differential/customfield/DifferentialTestPlanField.php index 4b0869a7d8..32d3c15c31 100644 --- a/src/applications/differential/customfield/DifferentialTestPlanField.php +++ b/src/applications/differential/customfield/DifferentialTestPlanField.php @@ -195,7 +195,7 @@ final class DifferentialTestPlanField return; } - $body->addTextSection(pht('TEST PLAN'), $test_plan); + $body->addRemarkupSection(pht('TEST PLAN'), $test_plan); } diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php index fabd2511ba..b2e946cf7f 100644 --- a/src/applications/differential/editor/DifferentialTransactionEditor.php +++ b/src/applications/differential/editor/DifferentialTransactionEditor.php @@ -1212,7 +1212,7 @@ final class DifferentialTransactionEditor } if ($inlines) { - $body->addTextSection( + $body->addRemarkupSection( pht('INLINE COMMENTS'), $this->renderInlineCommentsForMail($object, $inlines)); } diff --git a/src/applications/files/transform/PhabricatorFileImageTransform.php b/src/applications/files/transform/PhabricatorFileImageTransform.php index ff8bd14683..468eae0e03 100644 --- a/src/applications/files/transform/PhabricatorFileImageTransform.php +++ b/src/applications/files/transform/PhabricatorFileImageTransform.php @@ -119,9 +119,9 @@ abstract class PhabricatorFileImageTransform extends PhabricatorFileTransform { $out = new TempFile(); $future = new ExecFuture('convert %s %Ls %s', $tmp, $argv, $out); - // Don't spend more than 10 seconds resizing; just fail if it takes longer + // Don't spend more than 60 seconds resizing; just fail if it takes longer // than that. - $future->setTimeout(10)->resolvex(); + $future->setTimeout(60)->resolvex(); $data = Filesystem::readFile($out); @@ -259,7 +259,7 @@ abstract class PhabricatorFileImageTransform extends PhabricatorFileTransform { $file = $this->file; - $max_size = (1024 * 1024 * 4); + $max_size = (1024 * 1024 * 16); $img_size = $file->getByteSize(); if ($img_size > $max_size) { throw new Exception( diff --git a/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php b/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php index 6d68b0a8b6..9c3f88d631 100644 --- a/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php +++ b/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php @@ -256,10 +256,15 @@ final class HarbormasterSendMessageConduitAPIMethod // If the build has completely paused because all steps are blocked on // waiting targets, this will resume it. + $build = $build_target->getBuild(); + PhabricatorWorker::scheduleTask( 'HarbormasterBuildWorker', array( - 'buildID' => $build_target->getBuild()->getID(), + 'buildID' => $build->getID(), + ), + array( + 'objectPHID' => $build->getPHID(), )); return null; diff --git a/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php b/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php index b8c39146cb..0727a473ec 100644 --- a/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php +++ b/src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php @@ -98,6 +98,9 @@ final class HarbormasterBuildTransactionEditor 'HarbormasterBuildWorker', array( 'buildID' => $build->getID(), + ), + array( + 'objectPHID' => $build->getPHID(), )); } diff --git a/src/applications/harbormaster/engine/HarbormasterBuildEngine.php b/src/applications/harbormaster/engine/HarbormasterBuildEngine.php index 36ca48b060..5eabd85034 100644 --- a/src/applications/harbormaster/engine/HarbormasterBuildEngine.php +++ b/src/applications/harbormaster/engine/HarbormasterBuildEngine.php @@ -81,6 +81,9 @@ final class HarbormasterBuildEngine extends Phobject { 'HarbormasterTargetWorker', array( 'targetID' => $target->getID(), + ), + array( + 'objectPHID' => $target->getPHID(), )); } diff --git a/src/applications/harbormaster/storage/HarbormasterBuildable.php b/src/applications/harbormaster/storage/HarbormasterBuildable.php index 3a7df73f52..6286072b42 100644 --- a/src/applications/harbormaster/storage/HarbormasterBuildable.php +++ b/src/applications/harbormaster/storage/HarbormasterBuildable.php @@ -184,6 +184,9 @@ final class HarbormasterBuildable extends HarbormasterDAO 'HarbormasterBuildWorker', array( 'buildID' => $build->getID(), + ), + array( + 'objectPHID' => $build->getPHID(), )); return $build; diff --git a/src/applications/herald/adapter/HeraldAdapter.php b/src/applications/herald/adapter/HeraldAdapter.php index bec6677230..c7239438c6 100644 --- a/src/applications/herald/adapter/HeraldAdapter.php +++ b/src/applications/herald/adapter/HeraldAdapter.php @@ -29,6 +29,7 @@ abstract class HeraldAdapter extends Phobject { private $contentSource; private $isNewObject; private $applicationEmail; + private $appliedTransactions = array(); private $queuedTransactions = array(); private $emailPHIDs = array(); private $forcedEmailPHIDs = array(); @@ -121,6 +122,36 @@ abstract class HeraldAdapter extends Phobject { return !empty($applications); } + + /** + * Set the list of transactions which just took effect. + * + * These transactions are set by @{class:PhabricatorApplicationEditor} + * automatically, before it invokes Herald. + * + * @param list List of transactions. + * @return this + */ + final public function setAppliedTransactions(array $xactions) { + assert_instances_of($xactions, 'PhabricatorApplicationTransaction'); + $this->appliedTransactions = $xactions; + return $this; + } + + + /** + * Get a list of transactions which just took effect. + * + * When an object is edited normally, transactions are applied and then + * Herald executes. You can call this method to examine the transactions + * if you want to react to them. + * + * @return list List of transactions. + */ + final public function getAppliedTransactions() { + return $this->appliedTransactions; + } + public function queueTransaction($transaction) { $this->queuedTransactions[] = $transaction; } diff --git a/src/applications/legalpad/controller/LegalpadDocumentEditController.php b/src/applications/legalpad/controller/LegalpadDocumentEditController.php index edbaaf99e2..84a879a7a2 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentEditController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentEditController.php @@ -243,10 +243,10 @@ final class LegalpadDocumentEditController extends LegalpadController { $crumbs->addTextCrumb($short); $preview = id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Document Preview')) + ->setHeader($document->getTitle()) ->setPreviewURI($this->getApplicationURI('document/preview/')) ->setControlID('document-text') - ->addClass('phui-document-view'); + ->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT); return $this->buildApplicationPage( array( diff --git a/src/applications/maniphest/editor/ManiphestTransactionEditor.php b/src/applications/maniphest/editor/ManiphestTransactionEditor.php index dcc518e06b..565f3cc627 100644 --- a/src/applications/maniphest/editor/ManiphestTransactionEditor.php +++ b/src/applications/maniphest/editor/ManiphestTransactionEditor.php @@ -442,7 +442,7 @@ final class ManiphestTransactionEditor $body = parent::buildMailBody($object, $xactions); if ($this->getIsNewObject()) { - $body->addTextSection( + $body->addRemarkupSection( pht('TASK DESCRIPTION'), $object->getDescription()); } diff --git a/src/applications/phame/application/PhabricatorPhameApplication.php b/src/applications/phame/application/PhabricatorPhameApplication.php index 1a3d3f90f4..8c6516dd96 100644 --- a/src/applications/phame/application/PhabricatorPhameApplication.php +++ b/src/applications/phame/application/PhabricatorPhameApplication.php @@ -44,13 +44,12 @@ final class PhabricatorPhameApplication extends PhabricatorApplication { '(?:(?Pdraft|all)/)?' => 'PhamePostListController', '(?:query/(?P[^/]+)/)?' => 'PhamePostListController', 'blogger/(?P[\w\.-_]+)/' => 'PhamePostListController', - 'delete/(?P[^/]+)/' => 'PhamePostDeleteController', 'edit/(?:(?P[^/]+)/)?' => 'PhamePostEditController', 'view/(?P\d+)/' => 'PhamePostViewController', 'publish/(?P\d+)/' => 'PhamePostPublishController', 'unpublish/(?P\d+)/' => 'PhamePostUnpublishController', 'notlive/(?P\d+)/' => 'PhamePostNotLiveController', - 'preview/' => 'PhamePostPreviewController', + 'preview/' => 'PhabricatorMarkupPreviewController', 'framed/(?P\d+)/' => 'PhamePostFramedController', 'new/' => 'PhamePostNewController', 'move/(?P\d+)/' => 'PhamePostNewController', @@ -59,7 +58,7 @@ final class PhabricatorPhameApplication extends PhabricatorApplication { 'blog/' => array( '(?:(?Puser|all)/)?' => 'PhameBlogListController', '(?:query/(?P[^/]+)/)?' => 'PhameBlogListController', - 'delete/(?P[^/]+)/' => 'PhameBlogDeleteController', + 'archive/(?P[^/]+)/' => 'PhameBlogArchiveController', 'edit/(?P[^/]+)/' => 'PhameBlogEditController', 'view/(?P[^/]+)/' => 'PhameBlogViewController', 'feed/(?P[^/]+)/' => 'PhameBlogFeedController', diff --git a/src/applications/phame/controller/blog/PhameBlogArchiveController.php b/src/applications/phame/controller/blog/PhameBlogArchiveController.php new file mode 100644 index 0000000000..dd69f3154a --- /dev/null +++ b/src/applications/phame/controller/blog/PhameBlogArchiveController.php @@ -0,0 +1,68 @@ +getViewer(); + $id = $request->getURIData('id'); + + $blog = id(new PhameBlogQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$blog) { + return new Aphront404Response(); + } + + $view_uri = $this->getApplicationURI('blog/view/'.$blog->getID().'/'); + + if ($request->isFormPost()) { + if ($blog->isArchived()) { + $new_status = PhameBlog::STATUS_ACTIVE; + } else { + $new_status = PhameBlog::STATUS_ARCHIVED; + } + + $xactions = array(); + + $xactions[] = id(new PhameBlogTransaction()) + ->setTransactionType(PhameBlogTransaction::TYPE_STATUS) + ->setNewValue($new_status); + + id(new PhameBlogEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->applyTransactions($blog, $xactions); + + return id(new AphrontRedirectResponse())->setURI($view_uri); + } + + if ($blog->isArchived()) { + $title = pht('Activate Blog'); + $body = pht('This blog will become active again.'); + $button = pht('Activate Blog'); + } else { + $title = pht('Archive Blog'); + $body = pht('This blog will be marked as archived.'); + $button = pht('Archive Blog'); + } + + $dialog = id(new AphrontDialogView()) + ->setUser($viewer) + ->setTitle($title) + ->appendChild($body) + ->addCancelButton($view_uri) + ->addSubmitButton($button); + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + +} diff --git a/src/applications/phame/controller/blog/PhameBlogDeleteController.php b/src/applications/phame/controller/blog/PhameBlogDeleteController.php deleted file mode 100644 index c60e27b2d7..0000000000 --- a/src/applications/phame/controller/blog/PhameBlogDeleteController.php +++ /dev/null @@ -1,42 +0,0 @@ -getViewer(); - $id = $request->getURIData('id'); - - $blog = id(new PhameBlogQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$blog) { - return new Aphront404Response(); - } - - if ($request->isFormPost()) { - $blog->delete(); - return id(new AphrontRedirectResponse()) - ->setURI($this->getApplicationURI()); - } - - $cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/'); - - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle(pht('Delete Blog?')) - ->appendChild( - pht( - 'Really delete the blog "%s"? It will be gone forever.', - $blog->getName())) - ->addSubmitButton(pht('Delete')) - ->addCancelButton($cancel_uri); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } - -} diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index 2f20702f6e..f74b838881 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -22,10 +22,21 @@ final class PhameBlogViewController extends PhameBlogController { ->withBlogPHIDs(array($blog->getPHID())) ->executeWithCursorPager($pager); + if ($blog->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($blog->getName()) ->setUser($viewer) - ->setPolicyObject($blog); + ->setPolicyObject($blog) + ->setStatus($header_icon, $header_color, $header_name); $actions = $this->renderActions($blog, $viewer); $properties = $this->renderProperties($blog, $viewer, $actions); @@ -158,13 +169,25 @@ final class PhameBlogViewController extends PhameBlogController { ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-times') - ->setHref($this->getApplicationURI('blog/delete/'.$blog->getID().'/')) - ->setName(pht('Delete Blog')) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); + if ($blog->isArchived()) { + $actions->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Activate Blog')) + ->setIcon('fa-check') + ->setHref( + $this->getApplicationURI('blog/archive/'.$blog->getID().'/')) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } else { + $actions->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Archive Blog')) + ->setIcon('fa-ban') + ->setHref( + $this->getApplicationURI('blog/archive/'.$blog->getID().'/')) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + } return $actions; } diff --git a/src/applications/phame/controller/post/PhamePostDeleteController.php b/src/applications/phame/controller/post/PhamePostDeleteController.php deleted file mode 100644 index 292fa6c18c..0000000000 --- a/src/applications/phame/controller/post/PhamePostDeleteController.php +++ /dev/null @@ -1,41 +0,0 @@ -getViewer(); - - $post = id(new PhamePostQuery()) - ->setViewer($viewer) - ->withIDs(array($request->getURIData('id'))) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$post) { - return new Aphront404Response(); - } - - if ($request->isFormPost()) { - $post->delete(); - return id(new AphrontRedirectResponse()) - ->setURI('/phame/post/'); - } - - $cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/'); - - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) - ->setTitle(pht('Delete Post?')) - ->appendChild( - pht( - 'Really delete the post "%s"? It will be gone forever.', - $post->getTitle())) - ->addSubmitButton(pht('Delete')) - ->addCancelButton($cancel_uri); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } - -} diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php index c768e3c3a0..145c291efb 100644 --- a/src/applications/phame/controller/post/PhamePostEditController.php +++ b/src/applications/phame/controller/post/PhamePostEditController.php @@ -175,27 +175,17 @@ final class PhamePostEditController extends PhamePostController { ->addCancelButton($cancel_uri) ->setValue($submit_button)); - $header = id(new PHUIHeaderView()) - ->setHeader(pht('%s (Post Preview)', $title)); - - $container = id(new PHUIBoxView()) - ->setID('post-preview'); - - $document = id(new PHUIDocumentViewPro()) - ->setHeader($header) - ->appendChild($container); - - $preview_panel = id(new PHUIObjectBoxView()) - ->appendChild($document); + $preview = id(new PHUIRemarkupPreviewPanel()) + ->setHeader($post->getTitle()) + ->setPreviewURI($this->getApplicationURI('post/preview/')) + ->setControlID('post-body') + ->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT); Javelin::initBehavior( 'phame-post-preview', array( - 'preview' => 'post-preview', - 'body' => 'post-body', 'title' => 'post-title', 'phame_title' => 'post-phame-title', - 'uri' => '/phame/post/preview/', )); $form_box = id(new PHUIObjectBoxView()) @@ -214,7 +204,7 @@ final class PhamePostEditController extends PhamePostController { ->appendChild( array( $form_box, - $preview_panel, + $preview, )); } diff --git a/src/applications/phame/controller/post/PhamePostPreviewController.php b/src/applications/phame/controller/post/PhamePostPreviewController.php deleted file mode 100644 index 3f81481576..0000000000 --- a/src/applications/phame/controller/post/PhamePostPreviewController.php +++ /dev/null @@ -1,26 +0,0 @@ -getViewer(); - $body = $request->getStr('body'); - - $post = id(new PhamePost()) - ->setBody($body); - - $content = PhabricatorMarkupEngine::renderOneObject( - $post, - PhamePost::MARKUP_FIELD_BODY, - $viewer); - - $content = phutil_tag_div('phabricator-remarkup', $content); - - return id(new AphrontAjaxResponse())->setContent($content); - } - -} diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php index 6b414a9fe7..bff1113efe 100644 --- a/src/applications/phame/controller/post/PhamePostViewController.php +++ b/src/applications/phame/controller/post/PhamePostViewController.php @@ -157,14 +157,6 @@ final class PhamePostViewController extends PhamePostController { ->setWorkflow(true)); } - $actions->addAction( - id(new PhabricatorActionView()) - ->setIcon('fa-times') - ->setHref($this->getApplicationURI('post/delete/'.$id.'/')) - ->setName(pht('Delete Post')) - ->setDisabled(!$can_edit) - ->setWorkflow(true)); - $blog = $post->getBlog(); $can_view_live = $blog && !$post->isDraft(); diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php index 712c4ddd5b..3f23854125 100644 --- a/src/applications/phame/editor/PhameBlogEditor.php +++ b/src/applications/phame/editor/PhameBlogEditor.php @@ -18,6 +18,7 @@ final class PhameBlogEditor $types[] = PhameBlogTransaction::TYPE_DESCRIPTION; $types[] = PhameBlogTransaction::TYPE_DOMAIN; $types[] = PhameBlogTransaction::TYPE_SKIN; + $types[] = PhameBlogTransaction::TYPE_STATUS; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; @@ -37,6 +38,8 @@ final class PhameBlogEditor return $object->getDomain(); case PhameBlogTransaction::TYPE_SKIN: return $object->getSkin(); + case PhameBlogTransaction::TYPE_STATUS: + return $object->getStatus(); } } @@ -49,6 +52,7 @@ final class PhameBlogEditor case PhameBlogTransaction::TYPE_DESCRIPTION: case PhameBlogTransaction::TYPE_DOMAIN: case PhameBlogTransaction::TYPE_SKIN: + case PhameBlogTransaction::TYPE_STATUS: return $xaction->getNewValue(); } } @@ -66,6 +70,8 @@ final class PhameBlogEditor return $object->setDomain($xaction->getNewValue()); case PhameBlogTransaction::TYPE_SKIN: return $object->setSkin($xaction->getNewValue()); + case PhameBlogTransaction::TYPE_STATUS: + return $object->setStatus($xaction->getNewValue()); } return parent::applyCustomInternalTransaction($object, $xaction); @@ -80,6 +86,7 @@ final class PhameBlogEditor case PhameBlogTransaction::TYPE_DESCRIPTION: case PhameBlogTransaction::TYPE_DOMAIN: case PhameBlogTransaction::TYPE_SKIN: + case PhameBlogTransaction::TYPE_STATUS: return; } diff --git a/src/applications/phame/query/PhameBlogQuery.php b/src/applications/phame/query/PhameBlogQuery.php index ef441636b3..279ff91724 100644 --- a/src/applications/phame/query/PhameBlogQuery.php +++ b/src/applications/phame/query/PhameBlogQuery.php @@ -5,6 +5,7 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { private $ids; private $phids; private $domain; + private $statuses; private $needBloggers; public function withIDs(array $ids) { @@ -22,6 +23,11 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { return $this; } + public function withStatuses(array $status) { + $this->statuses = $status; + return $this; + } + public function newResultObject() { return new PhameBlog(); } @@ -33,6 +39,13 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery { protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); + if ($this->statuses !== null) { + $where[] = qsprintf( + $conn, + 'status IN (%Ls)', + $this->statuses); + } + if ($this->ids !== null) { $where[] = qsprintf( $conn, diff --git a/src/applications/phame/query/PhameBlogSearchEngine.php b/src/applications/phame/query/PhameBlogSearchEngine.php index 25a0ab515d..58dba3b810 100644 --- a/src/applications/phame/query/PhameBlogSearchEngine.php +++ b/src/applications/phame/query/PhameBlogSearchEngine.php @@ -17,11 +17,23 @@ final class PhameBlogSearchEngine protected function buildQueryFromParameters(array $map) { $query = $this->newQuery(); + if ($map['statuses']) { + $query->withStatuses(array($map['statuses'])); + } return $query; } protected function buildCustomSearchFields() { - return array(); + return array( + id(new PhabricatorSearchSelectField()) + ->setKey('statuses') + ->setLabel(pht('Status')) + ->setOptions(array( + '' => pht('All'), + PhameBlog::STATUS_ACTIVE => pht('Active'), + PhameBlog::STATUS_ARCHIVED => pht('Archived'), + )), + ); } protected function getURI($path) { @@ -30,6 +42,8 @@ final class PhameBlogSearchEngine protected function getBuiltinQueryNames() { $names = array( + 'active' => pht('Active Blogs'), + 'archived' => pht('Archived Blogs'), 'all' => pht('All Blogs'), ); return $names; @@ -42,6 +56,12 @@ final class PhameBlogSearchEngine switch ($query_key) { case 'all': return $query; + case 'active': + return $query->setParameter( + 'statuses', PhameBlog::STATUS_ACTIVE); + case 'archived': + return $query->setParameter( + 'statuses', PhameBlog::STATUS_ARCHIVED); } return parent::buildSavedQueryFromBuiltin($query_key); @@ -58,12 +78,19 @@ final class PhameBlogSearchEngine $list->setUser($viewer); foreach ($blogs as $blog) { + $archived = false; + $icon = 'fa-star'; + if ($blog->isArchived()) { + $archived = true; + $icon = 'fa-ban'; + } $id = $blog->getID(); $item = id(new PHUIObjectItemView()) ->setUser($viewer) ->setObject($blog) ->setHeader($blog->getName()) - ->setStatusIcon('fa-star') + ->setStatusIcon($icon) + ->setDisabled($archived) ->setHref($this->getApplicationURI("/blog/view/{$id}/")) ->addAttribute($blog->getSkin()) ->addAttribute($blog->getDomain()); diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php index 3082592a93..3fc708f72a 100644 --- a/src/applications/phame/storage/PhameBlog.php +++ b/src/applications/phame/storage/PhameBlog.php @@ -20,10 +20,14 @@ final class PhameBlog extends PhameDAO protected $creatorPHID; protected $viewPolicy; protected $editPolicy; + protected $status; protected $mailKey; private static $requestBlog; + const STATUS_ACTIVE = 'active'; + const STATUS_ARCHIVED = 'archived'; + protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, @@ -34,6 +38,7 @@ final class PhameBlog extends PhameDAO 'name' => 'text64', 'description' => 'text', 'domain' => 'text128?', + 'status' => 'text32', 'mailKey' => 'bytes20', // T6203/NULLABILITY @@ -70,6 +75,7 @@ final class PhameBlog extends PhameDAO public static function initializeNewBlog(PhabricatorUser $actor) { $blog = id(new PhameBlog()) ->setCreatorPHID($actor->getPHID()) + ->setStatus(self::STATUS_ACTIVE) ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy()) ->setEditPolicy(PhabricatorPolicies::POLICY_USER); return $blog; @@ -98,6 +104,17 @@ final class PhameBlog extends PhameDAO return $skin; } + public function isArchived() { + return ($this->getStatus() == self::STATUS_ARCHIVED); + } + + public static function getStatusNameMap() { + return array( + self::STATUS_ACTIVE => pht('Active'), + self::STATUS_ARCHIVED => pht('Archived'), + ); + } + /** * Makes sure a given custom blog uri is properly configured in DNS * to point at this Phabricator instance. If there is an error in diff --git a/src/applications/phame/storage/PhameBlogTransaction.php b/src/applications/phame/storage/PhameBlogTransaction.php index 0954e72a37..791dc930c4 100644 --- a/src/applications/phame/storage/PhameBlogTransaction.php +++ b/src/applications/phame/storage/PhameBlogTransaction.php @@ -7,6 +7,7 @@ final class PhameBlogTransaction const TYPE_DESCRIPTION = 'phame.blog.description'; const TYPE_DOMAIN = 'phame.blog.domain'; const TYPE_SKIN = 'phame.blog.skin'; + const TYPE_STATUS = 'phame.blog.status'; const MAILTAG_DETAILS = 'phame-blog-details'; const MAILTAG_SUBSCRIBERS = 'phame-blog-subscribers'; @@ -106,6 +107,18 @@ final class PhameBlogTransaction $this->renderHandleLink($author_phid), $new); break; + case self::TYPE_STATUS: + switch ($new) { + case PhameBlog::STATUS_ACTIVE: + return pht( + '%s published this blog.', + $this->renderHandleLink($author_phid)); + case PhameBlog::STATUS_ARCHIVED: + return pht( + '%s archived this blog.', + $this->renderHandleLink($author_phid)); + } + } return parent::getTitle(); @@ -151,6 +164,21 @@ final class PhameBlogTransaction $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; + case self::TYPE_STATUS: + switch ($new) { + case PhameBlog::STATUS_ACTIVE: + return pht( + '%s published the blog %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + case PhameBlog::STATUS_ARCHIVED: + return pht( + '%s archived the blog %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); + } + break; + } return parent::getTitleForFeed(); diff --git a/src/applications/phriction/controller/PhrictionDocumentController.php b/src/applications/phriction/controller/PhrictionDocumentController.php index 452e45289b..14a929573a 100644 --- a/src/applications/phriction/controller/PhrictionDocumentController.php +++ b/src/applications/phriction/controller/PhrictionDocumentController.php @@ -32,6 +32,7 @@ final class PhrictionDocumentController $move_notice = ''; $properties = null; $content = null; + $toc = null; if (!$document) { @@ -53,6 +54,7 @@ final class PhrictionDocumentController $page_title = pht('Page Not Found'); } else { $version = $request->getInt('v'); + if ($version) { $content = id(new PhrictionContent())->loadOneWhere( 'documentID = %d AND version = %d', @@ -74,7 +76,6 @@ final class PhrictionDocumentController $content = id(new PhrictionContent())->load($document->getContentID()); } $page_title = $content->getTitle(); - $properties = $this ->buildPropertyListView($document, $content, $slug); @@ -84,6 +85,8 @@ final class PhrictionDocumentController $current_status == PhrictionChangeType::CHANGE_MOVE_HERE) { $core_content = $content->renderContent($viewer); + $toc = $this->getToc($content); + } else if ($current_status == PhrictionChangeType::CHANGE_DELETE) { $notice = new PHUIInfoView(); $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE); @@ -102,7 +105,6 @@ final class PhrictionDocumentController $core_content = $notice->render(); } else if ($current_status == PhrictionChangeType::CHANGE_MOVE_AWAY) { $new_doc_id = $content->getChangeRef(); - $slug_uri = null; // If the new document exists and the viewer can see it, provide a link @@ -212,11 +214,12 @@ final class PhrictionDocumentController $prop_list->addPropertyList($properties); } - $page_content = id(new PHUIDocumentView()) + $page_content = id(new PHUIDocumentViewPro()) ->setHeader($header) + ->setPropertyList($prop_list) + ->setToc($toc) ->appendChild( array( - $prop_list, $version_note, $move_notice, $core_content, @@ -230,7 +233,8 @@ final class PhrictionDocumentController ), array( 'pageObjects' => array($document->getPHID()), - 'title' => $page_title, + 'title' => $page_title, + 'class' => 'pro-white-background', )); } @@ -278,6 +282,7 @@ final class PhrictionDocumentController $action_view->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Document')) + ->setDisabled(!$can_edit) ->setIcon('fa-pencil') ->setHref('/phriction/edit/'.$document->getID().'/')); @@ -285,6 +290,7 @@ final class PhrictionDocumentController $action_view->addAction( id(new PhabricatorActionView()) ->setName(pht('Move Document')) + ->setDisabled(!$can_edit) ->setIcon('fa-arrows') ->setHref('/phriction/move/'.$document->getID().'/') ->setWorkflow(true)); @@ -292,6 +298,7 @@ final class PhrictionDocumentController $action_view->addAction( id(new PhabricatorActionView()) ->setName(pht('Delete Document')) + ->setDisabled(!$can_edit) ->setIcon('fa-times') ->setHref('/phriction/delete/'.$document->getID().'/') ->setWorkflow(true)); @@ -431,7 +438,7 @@ final class PhrictionDocumentController ), $list))); - return phutil_tag_div('phui-document-box', $box); + return phutil_tag_div('phui-document-view-pro-box', $box); } private function renderChildDocumentLink(array $info) { @@ -454,4 +461,17 @@ final class PhrictionDocumentController return $this->slug; } + protected function getToc(PhrictionContent $content) { + $toc = $content->getRenderedTableOfContents(); + if ($toc) { + $toc = phutil_tag_div('phui-document-toc-content', array( + phutil_tag_div( + 'phui-document-toc-header', + pht('Contents')), + $toc, + )); + } + return $toc; + } + } diff --git a/src/applications/phriction/controller/PhrictionEditController.php b/src/applications/phriction/controller/PhrictionEditController.php index 65c4fcf062..466d721a03 100644 --- a/src/applications/phriction/controller/PhrictionEditController.php +++ b/src/applications/phriction/controller/PhrictionEditController.php @@ -268,10 +268,10 @@ final class PhrictionEditController ->setForm($form); $preview = id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Document Preview')) + ->setHeader($content->getTitle()) ->setPreviewURI('/phriction/preview/') ->setControlID('document-textarea') - ->addClass('phui-document-view'); + ->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT); $crumbs = $this->buildApplicationCrumbs(); if ($document->getID()) { diff --git a/src/applications/phriction/editor/PhrictionTransactionEditor.php b/src/applications/phriction/editor/PhrictionTransactionEditor.php index 5d1534df19..4cec1ccdbf 100644 --- a/src/applications/phriction/editor/PhrictionTransactionEditor.php +++ b/src/applications/phriction/editor/PhrictionTransactionEditor.php @@ -419,7 +419,7 @@ final class PhrictionTransactionEditor $body = parent::buildMailBody($object, $xactions); if ($this->getIsNewObject()) { - $body->addTextSection( + $body->addRemarkupSection( pht('DOCUMENT CONTENT'), $object->getContent()->getContent()); } else if ($this->contentDiffURI) { diff --git a/src/applications/phriction/storage/PhrictionContent.php b/src/applications/phriction/storage/PhrictionContent.php index d58020e5ab..99aaf0c7ec 100644 --- a/src/applications/phriction/storage/PhrictionContent.php +++ b/src/applications/phriction/storage/PhrictionContent.php @@ -21,6 +21,8 @@ final class PhrictionContent extends PhrictionDAO protected $changeType; protected $changeRef; + private $renderedTableOfContents; + public function renderContent(PhabricatorUser $viewer) { return PhabricatorMarkupEngine::renderOneObject( $this, @@ -98,27 +100,22 @@ final class PhrictionContent extends PhrictionDAO $output, PhutilMarkupEngine $engine) { - $classes = array(); - $classes[] = 'phabricator-remarkup'; - $toc = PhutilRemarkupHeaderBlockRule::renderTableOfContents( - $engine); - - if ($toc) { - $classes[] = 'remarkup-has-toc'; - $toc = phutil_tag_div('phabricator-remarkup-toc', array( - phutil_tag_div( - 'phabricator-remarkup-toc-header', - pht('Table of Contents')), - $toc, - )); - } + $this->renderedTableOfContents = + PhutilRemarkupHeaderBlockRule::renderTableOfContents($engine); return phutil_tag( 'div', array( - 'class' => implode(' ', $classes), + 'class' => 'phabricator-remarkup', ), - array($toc, $output)); + $output); + } + + /** + * @task markup + */ + public function getRenderedTableOfContents() { + return $this->renderedTableOfContents; } diff --git a/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php b/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php index ef7f547621..712478c839 100644 --- a/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php +++ b/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php @@ -236,7 +236,7 @@ final class PhabricatorPhurlURLEditor $body = parent::buildMailBody($object, $xactions); if (strlen($description)) { - $body->addTextSection( + $body->addRemarkupSection( pht('URL DESCRIPTION'), $object->getDescription()); } diff --git a/src/applications/ponder/editor/PonderAnswerEditor.php b/src/applications/ponder/editor/PonderAnswerEditor.php index 521c1948ed..10a90a1945 100644 --- a/src/applications/ponder/editor/PonderAnswerEditor.php +++ b/src/applications/ponder/editor/PonderAnswerEditor.php @@ -10,6 +10,7 @@ final class PonderAnswerEditor extends PonderEditor { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; + $types[] = PhabricatorTransactions::TYPE_EDGE; $types[] = PonderAnswerTransaction::TYPE_CONTENT; $types[] = PonderAnswerTransaction::TYPE_STATUS; diff --git a/src/applications/project/remarkup/ProjectRemarkupRule.php b/src/applications/project/remarkup/ProjectRemarkupRule.php index 41ea2e026f..5eeddeabfe 100644 --- a/src/applications/project/remarkup/ProjectRemarkupRule.php +++ b/src/applications/project/remarkup/ProjectRemarkupRule.php @@ -20,17 +20,13 @@ final class ProjectRemarkupRule extends PhabricatorObjectRemarkupRule { } protected function getObjectIDPattern() { - // NOTE: This explicitly does not match strings which contain only - // digits, because digit strings like "#123" are used to reference tasks at - // Facebook and are somewhat conventional in general. - - // The latter half of this rule matches monograms with internal periods, - // like `#domain.com`, but does not match monograms with terminal periods, - // because they're probably just puncutation. + // NOTE: The latter half of this rule matches monograms with internal + // periods, like `#domain.com`, but does not match monograms with terminal + // periods, because they're probably just puncutation. // Broadly, this will not match every possible project monogram, and we - // accept some false negatives -- like `#1` or `#dot.` -- in order to avoid - // a bunch of false positives on general use of the `#` character. + // accept some false negatives -- like `#dot.` -- in order to avoid a bunch + // of false positives on general use of the `#` character. // In other contexts, the PhabricatorProjectProjectPHIDType pattern is // controlling and these names should parse correctly. @@ -38,17 +34,14 @@ final class ProjectRemarkupRule extends PhabricatorObjectRemarkupRule { // These characters may never appear anywhere in a hashtag. $never = '\s?!,:;{}#\\(\\)"\''; - // These characters may not appear at the beginning. - $never_first = '.\d'; - - // These characters may not appear at the end. - $never_last = '.'; + // These characters may not appear at the edge of the string. + $never_edge = '.'; return - '[^'.$never_first.$never.']+'. + '[^'.$never_edge.$never.']+'. '(?:'. '[^'.$never.']*'. - '[^'.$never_last.$never.']+'. + '[^'.$never_edge.$never.']+'. ')*'; } diff --git a/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php b/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php index 80e809aba9..3789a424dd 100644 --- a/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php +++ b/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php @@ -33,7 +33,21 @@ final class ProjectRemarkupRuleTestCase extends PhabricatorTestCase { ), '#123' => array( 'embed' => array(), - 'ref' => array(), + 'ref' => array( + array( + 'offset' => 1, + 'id' => '123', + ), + ), + ), + '#2x4' => array( + 'embed' => array(), + 'ref' => array( + array( + 'offset' => 1, + 'id' => '2x4', + ), + ), ), '#security#123' => array( 'embed' => array(), diff --git a/src/applications/releeph/editor/ReleephRequestTransactionalEditor.php b/src/applications/releeph/editor/ReleephRequestTransactionalEditor.php index ecfa4c5b6b..4710557043 100644 --- a/src/applications/releeph/editor/ReleephRequestTransactionalEditor.php +++ b/src/applications/releeph/editor/ReleephRequestTransactionalEditor.php @@ -249,7 +249,7 @@ final class ReleephRequestTransactionalEditor if ($has_pick_failure) { $instructions = $releeph_project->getDetail('pick_failure_instructions'); if ($instructions) { - $body->addTextSection( + $body->addRemarkupSection( pht('PICK FAILURE INSTRUCTIONS'), $instructions); } diff --git a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php index 047a5c99a8..94e31e8b92 100644 --- a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php +++ b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php @@ -145,7 +145,7 @@ final class PhabricatorSlowvoteEditor $description = $object->getDescription(); if (strlen($description)) { - $body->addTextSection( + $body->addRemarkupSection( pht('SLOWVOTE DESCRIPTION'), $object->getDescription()); } diff --git a/src/applications/transactions/application/PhabricatorTransactionsApplication.php b/src/applications/transactions/application/PhabricatorTransactionsApplication.php index 260fa889b4..c0a300e327 100644 --- a/src/applications/transactions/application/PhabricatorTransactionsApplication.php +++ b/src/applications/transactions/application/PhabricatorTransactionsApplication.php @@ -45,6 +45,12 @@ final class PhabricatorTransactionsApplication extends PhabricatorApplication { 'PhabricatorEditEngineConfigurationViewController', 'save/(?P[^/]+)/' => 'PhabricatorEditEngineConfigurationSaveController', + 'reorder/(?P[^/]+)/' => + 'PhabricatorEditEngineConfigurationReorderController', + 'defaults/(?P[^/]+)/' => + 'PhabricatorEditEngineConfigurationDefaultsController', + 'lock/(?P[^/]+)/' => + 'PhabricatorEditEngineConfigurationLockController', ), ), ), diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php new file mode 100644 index 0000000000..fa7f30c858 --- /dev/null +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php @@ -0,0 +1,111 @@ +getURIData('engineKey'); + $this->setEngineKey($engine_key); + + $key = $request->getURIData('key'); + $viewer = $this->getViewer(); + + $config = id(new PhabricatorEditEngineConfigurationQuery()) + ->setViewer($viewer) + ->withEngineKeys(array($engine_key)) + ->withIdentifiers(array($key)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$config) { + return id(new Aphront404Response()); + } + + $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/"; + + $engine = $config->getEngine(); + $fields = $engine->getFieldsForConfig($config); + + foreach ($fields as $key => $field) { + if (!$field->getIsDefaultable()) { + unset($fields[$key]); + continue; + } + } + + foreach ($fields as $field) { + $field->setIsEditDefaults(true); + } + + if ($request->isFormPost()) { + $xactions = array(); + + foreach ($fields as $field) { + $field->readValueFromSubmit($request); + } + + $type = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT; + + $xactions = array(); + foreach ($fields as $field) { + $new_value = $field->getValueForDefaults(); + $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction()) + ->setTransactionType($type) + ->setMetadataValue('field.key', $field->getKey()) + ->setNewValue($new_value); + } + + $editor = id(new PhabricatorEditEngineConfigurationEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($config, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($cancel_uri); + } + + $title = pht('Edit Form Defaults'); + + $form = id(new AphrontFormView()) + ->setUser($viewer); + + foreach ($fields as $field) { + $field->appendToForm($form); + } + + $form + ->appendControl( + id(new AphrontFormSubmitControl()) + ->setValue(pht('Save Defaults')) + ->addCancelButton($cancel_uri)); + + $info = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) + ->setErrors( + array( + pht('You are editing the default values for this form.'), + )); + + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText($title) + ->setInfoView($info) + ->setForm($form); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb(pht('Form %d', $config->getID()), $cancel_uri); + $crumbs->addTextCrumb(pht('Edit Defaults')); + + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild($box); + } + +} diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php new file mode 100644 index 0000000000..790eaccb47 --- /dev/null +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php @@ -0,0 +1,117 @@ +getURIData('engineKey'); + $this->setEngineKey($engine_key); + + $key = $request->getURIData('key'); + $viewer = $this->getViewer(); + + $config = id(new PhabricatorEditEngineConfigurationQuery()) + ->setViewer($viewer) + ->withEngineKeys(array($engine_key)) + ->withIdentifiers(array($key)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$config) { + return id(new Aphront404Response()); + } + + $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/"; + + if ($request->isFormPost()) { + $xactions = array(); + + $locks = $request->getArr('locks'); + $type_locks = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS; + + $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction()) + ->setTransactionType($type_locks) + ->setNewValue($locks); + + $editor = id(new PhabricatorEditEngineConfigurationEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($config, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($cancel_uri); + } + + $engine = $config->getEngine(); + $fields = $engine->getFieldsForConfig($config); + + $help = pht(<<setUser($viewer) + ->appendRemarkupInstructions($help); + + $locks = $config->getFieldLocks(); + + $lock_visible = PhabricatorEditEngineConfiguration::LOCK_VISIBLE; + $lock_locked = PhabricatorEditEngineConfiguration::LOCK_LOCKED; + $lock_hidden = PhabricatorEditEngineConfiguration::LOCK_HIDDEN; + + $map = array( + $lock_visible => pht('Visible'), + $lock_locked => pht("\xF0\x9F\x94\x92 Locked"), + $lock_hidden => pht("\xE2\x9C\x98 Hidden"), + ); + + foreach ($fields as $field) { + if (!$field->getIsLockable()) { + continue; + } + + $key = $field->getKey(); + + $label = $field->getLabel(); + if (!strlen($label)) { + $label = $key; + } + + if ($field->getIsHidden()) { + $value = $lock_hidden; + } else if ($field->getIsLocked()) { + $value = $lock_locked; + } else { + $value = $lock_visible; + } + + $form->appendControl( + id(new AphrontFormSelectControl()) + ->setName('locks['.$key.']') + ->setLabel($label) + ->setValue($value) + ->setOptions($map)); + } + + return $this->newDialog() + ->setTitle(pht('Lock / Hide Fields')) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->appendForm($form) + ->addSubmitButton(pht('Save Changes')) + ->addCancelButton($cancel_uri); + } + +} diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php new file mode 100644 index 0000000000..15eb9530fd --- /dev/null +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php @@ -0,0 +1,123 @@ +getURIData('engineKey'); + $this->setEngineKey($engine_key); + + $key = $request->getURIData('key'); + $viewer = $this->getViewer(); + + $config = id(new PhabricatorEditEngineConfigurationQuery()) + ->setViewer($viewer) + ->withEngineKeys(array($engine_key)) + ->withIdentifiers(array($key)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$config) { + return id(new Aphront404Response()); + } + + $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/"; + $reorder_uri = "/transactions/editengine/{$engine_key}/reorder/{$key}/"; + + if ($request->isFormPost()) { + $xactions = array(); + $key_order = $request->getStrList('keyOrder'); + + $type_order = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; + + $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction()) + ->setTransactionType($type_order) + ->setNewValue($key_order); + + $editor = id(new PhabricatorEditEngineConfigurationEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($config, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($cancel_uri); + } + + $engine = $config->getEngine(); + $fields = $engine->getFieldsForConfig($config); + + $list_id = celerity_generate_unique_node_id(); + $input_id = celerity_generate_unique_node_id(); + + $list = id(new PHUIObjectItemListView()) + ->setUser($viewer) + ->setID($list_id) + ->setFlush(true); + + $key_order = array(); + foreach ($fields as $field) { + if (!$field->getIsReorderable()) { + continue; + } + + $label = $field->getLabel(); + $key = $field->getKey(); + + if ($label !== null) { + $header = $label; + } else { + $header = $key; + } + + $item = id(new PHUIObjectItemView()) + ->setHeader($header) + ->setGrippable(true) + ->addSigil('editengine-form-field') + ->setMetadata( + array( + 'fieldKey' => $key, + )); + + $list->addItem($item); + + $key_order[] = $key; + } + + Javelin::initBehavior( + 'editengine-reorder-fields', + array( + 'listID' => $list_id, + 'inputID' => $input_id, + 'reorderURI' => $reorder_uri, + )); + + $note = id(new PHUIInfoView()) + ->appendChild(pht('Drag and drop fields to reorder them.')) + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE); + + $input = phutil_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => 'keyOrder', + 'value' => implode(', ', $key_order), + 'id' => $input_id, + )); + + return $this->newDialog() + ->setTitle(pht('Reorder Fields')) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->appendChild($note) + ->appendChild($list) + ->appendChild($input) + ->addSubmitButton(pht('Save Changes')) + ->addCancelButton($cancel_uri); + } + +} diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php index f65eed1746..5a60b16f0d 100644 --- a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php @@ -39,6 +39,8 @@ final class PhabricatorEditEngineConfigurationViewController ->setHeader($header) ->addPropertyList($properties); + $field_list = $this->buildFieldList($config); + $crumbs = $this->buildApplicationCrumbs(); if ($is_concrete) { @@ -62,6 +64,7 @@ final class PhabricatorEditEngineConfigurationViewController ->appendChild( array( $box, + $field_list, $timeline, )); } @@ -69,7 +72,8 @@ final class PhabricatorEditEngineConfigurationViewController private function buildActionView( PhabricatorEditEngineConfiguration $config) { $viewer = $this->getViewer(); - $engine_key = $this->getEngineKey(); + $engine = $config->getEngine(); + $engine_key = $engine->getEngineKey(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, @@ -79,13 +83,13 @@ final class PhabricatorEditEngineConfigurationViewController $view = id(new PhabricatorActionListView()) ->setUser($viewer); - $key = $config->getIdentifier(); + $form_key = $config->getIdentifier(); $base_uri = "/transactions/editengine/{$engine_key}"; $is_concrete = (bool)$config->getID(); if (!$is_concrete) { - $save_uri = "{$base_uri}/save/{$key}/"; + $save_uri = "{$base_uri}/save/{$form_key}/"; $view->addAction( id(new PhabricatorActionView()) @@ -97,7 +101,7 @@ final class PhabricatorEditEngineConfigurationViewController $can_edit = false; } else { - $edit_uri = "{$base_uri}/edit/{$key}/"; + $edit_uri = "{$base_uri}/edit/{$form_key}/"; $view->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Form Configuration')) @@ -107,6 +111,44 @@ final class PhabricatorEditEngineConfigurationViewController ->setHref($edit_uri)); } + $use_uri = $engine->getEditURI(null, "form/{$form_key}/"); + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Use Form')) + ->setIcon('fa-th-list') + ->setHref($use_uri)); + + $defaults_uri = "{$base_uri}/defaults/{$form_key}/"; + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Change Default Values')) + ->setIcon('fa-paint-brush') + ->setHref($defaults_uri) + ->setWorkflow(!$can_edit) + ->setDisabled(!$can_edit)); + + $reorder_uri = "{$base_uri}/reorder/{$form_key}/"; + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Change Field Order')) + ->setIcon('fa-sort-alpha-asc') + ->setHref($reorder_uri) + ->setWorkflow(true) + ->setDisabled(!$can_edit)); + + $lock_uri = "{$base_uri}/lock/{$form_key}/"; + + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Lock / Hide Fields')) + ->setIcon('fa-lock') + ->setHref($lock_uri) + ->setWorkflow(true) + ->setDisabled(!$can_edit)); + return $view; } @@ -121,5 +163,35 @@ final class PhabricatorEditEngineConfigurationViewController return $properties; } + private function buildFieldList(PhabricatorEditEngineConfiguration $config) { + $viewer = $this->getViewer(); + $engine = $config->getEngine(); + + $fields = $engine->getFieldsForConfig($config); + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->setAction(null); + + foreach ($fields as $field) { + $field->setIsPreview(true); + + $field->appendToForm($form); + } + + $info = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) + ->setErrors( + array( + pht('This is a preview of the current form configuration.'), + )); + + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Form Preview')) + ->setInfoView($info) + ->setForm($form); + + return $box; + } } diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php index 13c2b3e017..b398f226eb 100644 --- a/src/applications/transactions/editengine/PhabricatorEditEngine.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php @@ -46,6 +46,11 @@ abstract class PhabricatorEditEngine return $this->getPhobjectClassConstant('ENGINECONST', 64); } + final public function getApplication() { + $app_class = $this->getEngineApplicationClass(); + return PhabricatorApplication::getByClass($app_class); + } + /* -( Managing Fields )---------------------------------------------------- */ @@ -53,6 +58,19 @@ abstract class PhabricatorEditEngine abstract public function getEngineApplicationClass(); abstract protected function buildCustomEditFields($object); + public function getFieldsForConfig( + PhabricatorEditEngineConfiguration $config) { + + $object = $this->newEditableObject(); + + $this->editEngineConfiguration = $config; + + // This is mostly making sure that we fill in default values. + $this->setIsCreate(true); + + return $this->buildEditFields($object); + } + final protected function buildEditFields($object) { $viewer = $this->getViewer(); $editor = $object->getApplicationTransactionEditor(); @@ -129,6 +147,7 @@ abstract class PhabricatorEditEngine ->setEditTypeKey('space') ->setDescription( pht('Shifts the object in the Spaces application.')) + ->setIsReorderable(false) ->setAliases(array('space', 'policy.space')) ->setTransactionType($type_space) ->setValue($object->getSpacePHID()); @@ -195,6 +214,22 @@ abstract class PhabricatorEditEngine } } + $xaction = $object->getApplicationTransactionTemplate(); + $comment = $xaction->getApplicationTransactionCommentObject(); + if ($comment) { + $comment_type = PhabricatorTransactions::TYPE_COMMENT; + + $comment_field = id(new PhabricatorCommentEditField()) + ->setKey('comment') + ->setLabel(pht('Comments')) + ->setDescription(pht('Add comments.')) + ->setAliases(array('comments')) + ->setIsHidden(true) + ->setTransactionType($comment_type) + ->setValue(null); + $fields[] = $comment_field; + } + $config = $this->getEditEngineConfiguration(); $fields = $config->applyConfigurationToFields($this, $fields); @@ -222,6 +257,13 @@ abstract class PhabricatorEditEngine */ abstract protected function getObjectCreateTitleText($object); + /** + * @task text + */ + protected function getFormHeaderText($object) { + $config = $this->getEditEngineConfiguration(); + return $config->getName(); + } /** * @task text @@ -384,16 +426,16 @@ abstract class PhabricatorEditEngine /** * @task uri */ - protected function getObjectEditURI($object) { - return $this->getController()->getApplicationURI('edit/'); + protected function getObjectCreateCancelURI($object) { + return $this->getApplication()->getApplicationURI(); } /** * @task uri */ - protected function getObjectCreateCancelURI($object) { - return $this->getController()->getApplicationURI(); + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('edit/'); } @@ -408,12 +450,12 @@ abstract class PhabricatorEditEngine /** * @task uri */ - protected function getEditURI($object, $path = null) { - $parts = array( - $this->getObjectEditURI($object), - ); + public function getEditURI($object = null, $path = null) { + $parts = array(); - if (!$this->getIsCreate()) { + $parts[] = $this->getEditorURI(); + + if ($object && $object->getID()) { $parts[] = $object->getID().'/'; } @@ -563,7 +605,8 @@ abstract class PhabricatorEditEngine $controller = $this->getController(); $request = $controller->getRequest(); - $config = $this->loadEditEngineConfiguration($request->getURIData('form')); + $form_key = $request->getURIData('formKey'); + $config = $this->loadEditEngineConfiguration($form_key); if (!$config) { return new Aphront404Response(); } @@ -631,12 +674,22 @@ abstract class PhabricatorEditEngine $validation_exception = null; if ($request->isFormPost()) { foreach ($fields as $field) { + if ($field->getIsLocked() || $field->getIsHidden()) { + continue; + } + $field->readValueFromSubmit($request); } $xactions = array(); foreach ($fields as $field) { - $xactions[] = $field->generateTransaction(clone $template); + $xaction = $field->generateTransaction(clone $template); + + if (!$xaction) { + continue; + } + + $xactions[] = $xaction; } $editor = $object->getApplicationTransactionEditor() @@ -656,6 +709,10 @@ abstract class PhabricatorEditEngine } else { if ($this->getIsCreate()) { foreach ($fields as $field) { + if ($field->getIsLocked() || $field->getIsHidden()) { + continue; + } + $field->readValueFromRequest($request); } } else { @@ -668,7 +725,7 @@ abstract class PhabricatorEditEngine $action_button = $this->buildEditFormActionButton($object); if ($this->getIsCreate()) { - $header_text = $this->getObjectCreateTitleText($object); + $header_text = $this->getFormHeaderText($object); } else { $header_text = $this->getObjectEditTitleText($object); } diff --git a/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php b/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php index cb7662c7ba..ca6b9fe370 100644 --- a/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php @@ -39,7 +39,7 @@ abstract class PhabricatorEditEngineAPIMethod final public function getMethodDescription() { // TODO: We don't currently have a real viewer in this method. - $viewer = new PhabricatorUser(); + $viewer = PhabricatorUser::getOmnipotentUser(); $engine = $this->newEditEngine() ->setViewer($viewer); diff --git a/src/applications/transactions/editfield/PhabricatorCommentEditField.php b/src/applications/transactions/editfield/PhabricatorCommentEditField.php new file mode 100644 index 0000000000..6080b9fa73 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorCommentEditField.php @@ -0,0 +1,25 @@ + $this->getValueForTransaction(), + ); + + return head($this->getEditTransactionTypes()) + ->generateTransaction($xaction, $spec); + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php index 55815c3c4d..fcf66c3883 100644 --- a/src/applications/transactions/editfield/PhabricatorEditField.php +++ b/src/applications/transactions/editfield/PhabricatorEditField.php @@ -13,7 +13,16 @@ abstract class PhabricatorEditField extends Phobject { private $metadata = array(); private $description; private $editTypeKey; + private $isLocked; + private $isHidden; + + private $isPreview; + private $isEditDefaults; + + private $isReorderable = true; + private $isDefaultable = true; + private $isLockable = true; public function setKey($key) { $this->key = $key; @@ -78,6 +87,60 @@ abstract class PhabricatorEditField extends Phobject { return $this->isLocked; } + public function setIsPreview($preview) { + $this->isPreview = $preview; + return $this; + } + + public function getIsPreview() { + return $this->isPreview; + } + + public function setIsReorderable($is_reorderable) { + $this->isReorderable = $is_reorderable; + return $this; + } + + public function getIsReorderable() { + return $this->isReorderable; + } + + public function setIsEditDefaults($is_edit_defaults) { + $this->isEditDefaults = $is_edit_defaults; + return $this; + } + + public function getIsEditDefaults() { + return $this->isEditDefaults; + } + + public function setIsDefaultable($is_defaultable) { + $this->isDefaultable = $is_defaultable; + return $this; + } + + public function getIsDefaultable() { + return $this->isDefaultable; + } + + public function setIsLockable($is_lockable) { + $this->isLockable = $is_lockable; + return $this; + } + + public function getIsLockable() { + return $this->isLockable; + } + + public function setIsHidden($is_hidden) { + $this->isHidden = $is_hidden; + return $this; + } + + public function getIsHidden() { + return $this->isHidden; + } + protected function newControl() { throw new PhutilMethodNotImplementedException(); } @@ -96,16 +159,41 @@ abstract class PhabricatorEditField extends Phobject { $control->setLabel($this->getLabel()); } - if ($this->getIsLocked()) { - $control->setDisabled(true); + if ($this->getIsPreview()) { + $disabled = true; + $hidden = false; + } else if ($this->getIsEditDefaults()) { + $disabled = false; + $hidden = false; + } else { + $disabled = $this->getIsLocked(); + $hidden = $this->getIsHidden(); } + if ($hidden) { + return null; + } + + $control->setDisabled($disabled); + return $control; } public function appendToForm(AphrontFormView $form) { $control = $this->renderControl(); if ($control !== null) { + + if ($this->getIsPreview()) { + if ($this->getIsHidden()) { + $control + ->addClass('aphront-form-preview-hidden') + ->setError(pht('Hidden')); + } else if ($this->getIsLocked()) { + $control + ->setError(pht('Locked')); + } + } + $form->appendControl($control); } return $this; @@ -115,6 +203,19 @@ abstract class PhabricatorEditField extends Phobject { return $this->getValue(); } + public function getValueForDefaults() { + $value = $this->getValue(); + + // By default, just treat the empty string like `null` since they're + // equivalent for almost all fields and this reduces the number of + // meaningless transactions we generate when adjusting defaults. + if ($value === '') { + return null; + } + + return $value; + } + protected function getValue() { return $this->value; } @@ -128,6 +229,10 @@ abstract class PhabricatorEditField extends Phobject { public function generateTransaction( PhabricatorApplicationTransaction $xaction) { + if (!$this->getTransactionType()) { + return null; + } + $xaction ->setTransactionType($this->getTransactionType()) ->setNewValue($this->getValueForTransaction()); @@ -149,9 +254,6 @@ abstract class PhabricatorEditField extends Phobject { } public function getTransactionType() { - if (!$this->transactionType) { - throw new PhutilInvalidStateException('setTransactionType'); - } return $this->transactionType; } @@ -218,7 +320,13 @@ abstract class PhabricatorEditField extends Phobject { } protected function getValueExistsInSubmit(AphrontRequest $request, $key) { - return $this->getHTTPParameterType()->getExists($request, $key); + $type = $this->getHTTPParameterType(); + + if ($type) { + return $type->getExists($request, $key); + } + + return false; } protected function getValueFromSubmit(AphrontRequest $request, $key) { @@ -226,7 +334,13 @@ abstract class PhabricatorEditField extends Phobject { } protected function getDefaultValue() { - return $this->getHTTPParameterType()->getDefaultValue(); + $type = $this->getHTTPParameterType(); + + if ($type) { + return $type->getDefaultValue(); + } + + return null; } final public function getHTTPParameterType() { @@ -255,8 +369,17 @@ abstract class PhabricatorEditField extends Phobject { return $this->editTypeKey; } + protected function newEditType() { + return id(new PhabricatorSimpleEditType()) + ->setValueType($this->getHTTPParameterType()->getTypeName()); + } + public function getEditTransactionTypes() { $transaction_type = $this->getTransactionType(); + if ($transaction_type === null) { + return array(); + } + $type_key = $this->getEditTypeKey(); // TODO: This is a pretty big pile of hard-coded hacks for now. @@ -305,10 +428,9 @@ abstract class PhabricatorEditField extends Phobject { } return array( - id(new PhabricatorSimpleEditType()) + $this->newEditType() ->setEditType($type_key) ->setTransactionType($transaction_type) - ->setValueType($this->getHTTPParameterType()->getTypeName()) ->setDescription($this->getDescription()) ->setMetadata($this->metadata), ); diff --git a/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php b/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php index 9da1d49ae6..02014148ae 100644 --- a/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php +++ b/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php @@ -7,4 +7,8 @@ final class PhabricatorInstructionsEditField return $form->appendRemarkupInstructions($this->getValue()); } + protected function newHTTPParameterType() { + return null; + } + } diff --git a/src/applications/transactions/editfield/PhabricatorRemarkupEditField.php b/src/applications/transactions/editfield/PhabricatorRemarkupEditField.php new file mode 100644 index 0000000000..ff0621830f --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorRemarkupEditField.php @@ -0,0 +1,10 @@ + $xaction) { - if ($xaction->getComment()) { + if ($xaction->hasComment()) { $xaction->setTransactionType($type_comment); $xaction->setOldValue(null); $xaction->setNewValue(null); @@ -2867,12 +2867,15 @@ abstract class PhabricatorApplicationTransactionEditor PhabricatorLiskDAO $object, array $xactions) { - $adapter = $this->buildHeraldAdapter($object, $xactions); - $adapter->setContentSource($this->getContentSource()); - $adapter->setIsNewObject($this->getIsNewObject()); + $adapter = $this->buildHeraldAdapter($object, $xactions) + ->setContentSource($this->getContentSource()) + ->setIsNewObject($this->getIsNewObject()) + ->setAppliedTransactions($xactions); + if ($this->getApplicationEmail()) { $adapter->setApplicationEmail($this->getApplicationEmail()); } + $xscript = HeraldEngine::loadAndApplyRules($adapter); $this->setHeraldAdapter($adapter); diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php index e47447c351..d0bbe118be 100644 --- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php +++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php @@ -51,20 +51,21 @@ final class PhabricatorEditEngineConfigurationEditEngine } protected function getObjectViewURI($object) { - $engine_key = $this->getTargetEngine()->getEngineKey(); $id = $object->getID(); - return "/transactions/editengine/{$engine_key}/view/{$id}/"; + return $this->getURI("view/{$id}/"); } - protected function getObjectEditURI($object) { - $engine_key = $this->getTargetEngine()->getEngineKey(); - $id = $object->getID(); - return "/transactions/editengine/{$engine_key}/edit/{$id}/"; + protected function getEditorURI() { + return $this->getURI('edit/'); } protected function getObjectCreateCancelURI($object) { + return $this->getURI(); + } + + private function getURI($path = null) { $engine_key = $this->getTargetEngine()->getEngineKey(); - return "/transactions/editengine/{$engine_key}/"; + return "/transactions/editengine/{$engine_key}/{$path}"; } protected function buildCustomEditFields($object) { @@ -76,6 +77,13 @@ final class PhabricatorEditEngineConfigurationEditEngine ->setTransactionType( PhabricatorEditEngineConfigurationTransaction::TYPE_NAME) ->setValue($object->getName()), + id(new PhabricatorRemarkupEditField()) + ->setKey('preamble') + ->setLabel(pht('Preamble')) + ->setDescription(pht('Optional instructions, shown above the form.')) + ->setTransactionType( + PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE) + ->setValue($object->getPreamble()), ); } diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php index 4736e89efa..9c115254fe 100644 --- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php +++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php @@ -18,6 +18,10 @@ final class PhabricatorEditEngineConfigurationEditor $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_NAME; + $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; + $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; + $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT; + $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS; return $types; } @@ -57,6 +61,15 @@ final class PhabricatorEditEngineConfigurationEditor switch ($xaction->getTransactionType()) { case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: return $object->getName(); + case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; + return $object->getPreamble(); + case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: + return $object->getFieldOrder(); + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + $field_key = $xaction->getMetadataValue('field.key'); + return $object->getFieldDefault($field_key); + case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: + return $object->getFieldLocks(); } } @@ -66,6 +79,10 @@ final class PhabricatorEditEngineConfigurationEditor switch ($xaction->getTransactionType()) { case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: + case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; + case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: return $xaction->getNewValue(); } } @@ -78,6 +95,19 @@ final class PhabricatorEditEngineConfigurationEditor case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: $object->setName($xaction->getNewValue()); return; + case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; + $object->setPreamble($xaction->getNewValue()); + return; + case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: + $object->setFieldOrder($xaction->getNewValue()); + return; + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + $field_key = $xaction->getMetadataValue('field.key'); + $object->setFieldDefault($field_key, $xaction->getNewValue()); + return; + case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: + $object->setFieldLocks($xaction->getNewValue()); + return; } return parent::applyCustomInternalTransaction($object, $xaction); @@ -89,6 +119,10 @@ final class PhabricatorEditEngineConfigurationEditor switch ($xaction->getTransactionType()) { case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: + case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; + case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; + case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: return; } diff --git a/src/applications/transactions/edittype/PhabricatorCommentEditType.php b/src/applications/transactions/edittype/PhabricatorCommentEditType.php new file mode 100644 index 0000000000..5e4df3942f --- /dev/null +++ b/src/applications/transactions/edittype/PhabricatorCommentEditType.php @@ -0,0 +1,31 @@ +getTypeName(); + } + + public function generateTransaction( + PhabricatorApplicationTransaction $template, + array $spec) { + + $comment = $template->getApplicationTransactionCommentObject() + ->setContent(idx($spec, 'value')); + + $template + ->setTransactionType($this->getTransactionType()) + ->attachComment($comment); + + foreach ($this->getMetadata() as $key => $value) { + $template->setMetadataValue($key, $value); + } + + return $template; + } + + public function getValueDescription() { + return pht('Comment to add, formated as remarkup.'); + } + +} diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php index b1c573f775..6fc91dffbc 100644 --- a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php +++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php @@ -134,6 +134,31 @@ final class PhabricatorEditEngineConfigurationQuery return $page; } + protected function willFilterPage(array $configs) { + $engine_keys = mpull($configs, 'getEngineKey'); + + $engines = id(new PhabricatorEditEngineQuery()) + ->setParentQuery($this) + ->setViewer($this->getViewer()) + ->withEngineKeys($engine_keys) + ->execute(); + $engines = mpull($engines, null, 'getEngineKey'); + + foreach ($configs as $key => $config) { + $engine = idx($engines, $config->getEngineKey()); + + if (!$engine) { + $this->didRejectResult($config); + unset($configs[$key]); + continue; + } + + $config->attachEngine($engine); + } + + return $configs; + } + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); diff --git a/src/applications/transactions/query/PhabricatorEditEngineQuery.php b/src/applications/transactions/query/PhabricatorEditEngineQuery.php index 62d5f38c99..ffdbd88535 100644 --- a/src/applications/transactions/query/PhabricatorEditEngineQuery.php +++ b/src/applications/transactions/query/PhabricatorEditEngineQuery.php @@ -20,6 +20,28 @@ final class PhabricatorEditEngineQuery return $engines; } + protected function willFilterPage(array $engines) { + $viewer = $this->getViewer(); + + foreach ($engines as $key => $engine) { + $app_class = $engine->getEngineApplicationClass(); + if ($app_class === null) { + continue; + } + + $can_see = PhabricatorApplication::isClassInstalledForViewer( + $app_class, + $viewer); + if (!$can_see) { + $this->didRejectResult($engine); + unset($engines[$key]); + continue; + } + } + + return $engines; + } + public function getQueryApplicationClass() { return 'PhabricatorTransactionsApplication'; } diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php b/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php index aed81bd8a3..1c48ad8abd 100644 --- a/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php +++ b/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php @@ -17,6 +17,10 @@ final class PhabricatorEditEngineConfiguration private $engine = self::ATTACHABLE; + const LOCK_VISIBLE = 'visible'; + const LOCK_LOCKED = 'locked'; + const LOCK_HIDDEN = 'hidden'; + public function getTableName() { return 'search_editengineconfiguration'; } @@ -97,14 +101,39 @@ final class PhabricatorEditEngineConfiguration } } + $locks = $this->getFieldLocks(); + foreach ($fields as $field) { + $key = $field->getKey(); + switch (idx($locks, $key)) { + case self::LOCK_LOCKED: + $field->setIsHidden(false); + $field->setIsLocked(true); + break; + case self::LOCK_HIDDEN: + $field->setIsHidden(true); + $field->setIsLocked(false); + break; + case self::LOCK_VISIBLE: + $field->setIsHidden(false); + $field->setIsLocked(false); + break; + default: + // If we don't have an explicit value, don't make any adjustments. + break; + } + } + $fields = $this->reorderFields($fields); - $head_instructions = $this->getProperty('instructions.head'); - if (strlen($head_instructions)) { + $preamble = $this->getPreamble(); + if (strlen($preamble)) { $fields = array( - 'config.instructions.head' => id(new PhabricatorInstructionsEditField()) - ->setKey('config.instructions.head') - ->setValue($head_instructions), + 'config.preamble' => id(new PhabricatorInstructionsEditField()) + ->setKey('config.preamble') + ->setIsReorderable(false) + ->setIsDefaultable(false) + ->setIsLockable(false) + ->setValue($preamble), ) + $fields; } @@ -112,21 +141,9 @@ final class PhabricatorEditEngineConfiguration } private function reorderFields(array $fields) { - $keys = array(); + $keys = $this->getFieldOrder(); $fields = array_select_keys($fields, $keys) + $fields; - - // Now, move locked fields to the bottom. - $head = array(); - $tail = array(); - foreach ($fields as $key => $field) { - if (!$field->getIsLocked()) { - $head[$key] = $field; - } else { - $tail[$key] = $field; - } - } - - return $head + $tail; + return $fields; } public function getURI() { @@ -158,6 +175,41 @@ final class PhabricatorEditEngineConfiguration return pht('Untitled Form'); } + public function getPreamble() { + return $this->getProperty('preamble'); + } + + public function setPreamble($preamble) { + return $this->setProperty('preamble', $preamble); + } + + public function setFieldOrder(array $field_order) { + return $this->setProperty('order', $field_order); + } + + public function getFieldOrder() { + return $this->getProperty('order', array()); + } + + public function setFieldLocks(array $field_locks) { + return $this->setProperty('locks', $field_locks); + } + + public function getFieldLocks() { + return $this->getProperty('locks', array()); + } + + public function getFieldDefault($key) { + $defaults = $this->getProperty('defaults', array()); + return idx($defaults, $key); + } + + public function setFieldDefault($key, $value) { + $defaults = $this->getProperty('defaults', array()); + $defaults[$key] = $value; + return $this->setProperty('defaults', $defaults); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php index cbc7d2b911..b79cb2a648 100644 --- a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php @@ -4,6 +4,10 @@ final class PhabricatorEditEngineConfigurationTransaction extends PhabricatorApplicationTransaction { const TYPE_NAME = 'editengine.config.name'; + const TYPE_PREAMBLE = 'editengine.config.preamble'; + const TYPE_ORDER = 'editengine.config.order'; + const TYPE_DEFAULT = 'editengine.config.default'; + const TYPE_LOCKS = 'editengine.config.locks'; public function getApplicationName() { return 'search'; @@ -17,4 +21,48 @@ final class PhabricatorEditEngineConfigurationTransaction return null; } + public function getTitle() { + $author_phid = $this->getAuthorPHID(); + + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + $type = $this->getTransactionType(); + switch ($type) { + case self::TYPE_NAME: + if (strlen($old)) { + return pht( + '%s renamed this form from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $old, + $new); + } else { + return pht( + '%s named this form "%s".', + $this->renderHandleLink($author_phid), + $new); + } + case self::TYPE_PREAMBLE: + return pht( + '%s updated the preamble for this form.', + $this->renderHandleLink($author_phid)); + case self::TYPE_ORDER: + return pht( + '%s reordered the fields in this form.', + $this->renderHandleLink($author_phid)); + case self::TYPE_DEFAULT: + $key = $this->getMetadataValue('field.key'); + return pht( + '%s changed the default value for field "%s".', + $this->renderHandleLink($author_phid), + $key); + case self::TYPE_LOCKS: + return pht( + '%s changed locked and hidden fields.', + $this->renderHandleLink($author_phid)); + } + + return parent::getTitle(); + } + } diff --git a/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php index f1aa36fa61..e8397e6a65 100644 --- a/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php +++ b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php @@ -42,6 +42,7 @@ final class PhabricatorApplicationEditHTTPParameterHelpView $type = $field->getHTTPParameterType(); if ($type === null) { unset($fields[$key]); + continue; } $types[$type->getTypeName()] = $type; } diff --git a/src/docs/contributor/cla.diviner b/src/docs/contributor/cla.diviner new file mode 100644 index 0000000000..f08711483a --- /dev/null +++ b/src/docs/contributor/cla.diviner @@ -0,0 +1,169 @@ +@title Understanding the Phacility CLA +@group detail + +Describes the Contributor License Agreement (CLA). + +Overview +======== + +IMPORTANT: This document is not legal advice. + +Phacility requires contributors to sign a Contributor License Agreement +(often abbreviated "CLA") before we can accept contributions into the upstream. +This document explains what this document means and why we require it. + +This requirement is not unusual, and many large open source projects require a +similar CLA, including Python, Go, jQuery, and Apache Software Foundation +projects. + +You can read more about CLAs and find more examples of companies and projects +which require them on Wikipedia's +[[ https://en.wikipedia.org/wiki/Contributor_License_Agreement | CLA ]] page. + +Our CLA is substantially similar to the CLA required by Apache, the +"Apache Individual Contributor License Agreement V2.0". Many projects which +require a CLA use this CLA or a similar one. + + +Why We Require a CLA +==================== + +While many projects require a CLA, others do not. This project requires a CLA +primarily because: + + - it gives us certain rights, particularly the ability to relicense the work + later; + - it makes the terms of your contribution clear, protecting us from liability + related to copyright and patent disputes. + +**More Rights**: We consider the cost of maintaining changes to greatly +outweigh the cost of writing them in the first place. When we accept work +into the upstream, we are agreeing to bear that maintenance cost. + +This cost is not worthwhile to us unless the changes come with no strings +attached. Among other concerns, we would be unable to redistribute Phabricator +under a different license in the future without the additional rights the CLA +gives us. + +For a concrete example of the problems this causes, Bootstrap switched from +GPLv2 to MIT in 2012-2013. You can see the issue tracking the process and read +about what they had to go through to do this here: + +https://github.com/twbs/bootstrap/issues/2054 + +This took almost 18 months and required a huge amount of effort. We are not +willing to encumber the project with that kind of potential cost in order to +accept contributions. + +The rights you give us by signing the CLA allow us to release the software +under a different license later without asking you for permission, including a +license you may not agree with. + +They do not allow us to //undo// the existing release under the Apache license, +but allow us to make an //additional// release under a different license, or +release under multiple licenses (if we do, users may choose which license or +licenses they wish to use the software under). It would also allow us to +discontinue updating the release under the Apache license. + +While we do not currently plan to relicense Phabricator, we do not want to +give up the ability to do so: we may want or need to in the future. + +The most likely scenario which would lead to us changing the license is if a +new version of the Apache license is released. Open source software licenses +are still largely untested in the US legal system, and they may face challenges +in the future which could require adapting them to a changing legal +environment. If this occurs, we would want to be able to update to a newer +version of the license which accounted for these changes. + +It is also possible that we may want to change open source licenses (for +example, to MIT) or adopt dual-licensing (for example, both Apache and MIT). We +might want to do this so that our license is compatible with the licenses used +by other software we want to be distributed alongside. + +Although we currently believe it is unlikely, it is also possible we may want +to relicense Phabricator under a closed, proprietary, or literally evil license. +By signing the CLA, you are giving us the power to do this without requiring +you to consent. If you are not comfortable with this, do not sign the CLA and +do not contribute to Phabricator. + +**Limitation of Liability**: The second benefit the CLA provides is that it +makes the terms of your contribition explicitly clear upfront, and it puts us +in a much stronger legal position if a contributor later claims there is +ambiguity about ownership of their work. We can point at the document they +signed as proof that they consented to our use and understood the terms of +their contribution. + +//SCO v. IBM// was a lawsuit filed in 2003 alleging (roughly) that IBM had +improperly contributed code owned by SCO to Linux. The details of this and the +subsequent cases are very complex and the situation is not a direct parallel to +anything we are likely to face, but SCO claimed billions of dollars in damages +and the litigation has now been ongoing for more than a decade. + +We want to avoid situations like this in the future by making the terms of +contibution explicit upfront. + +Generally, we believe the terms of the CLA are fair and reasonable for +contributors, and that the primary way contributors benefit from contributing +to Phabricator is that we publish and maintain their changes so they do not +have to fork the software. + +If you have strong ideological reasons for contributing to open source, you may +not be comfortable with the terms of the CLA (for example, it may be important +to you that your changes are never available under a license which you haven't +explicitly approved). This is fine and we can understand why contributors may +hold this viewpoint, but we can not accept your changes into the upstream. + + +Corporate vs Individual CLAs +============================ + +We offer two CLAs: + + - {L28} + - {L30} + +These are both substantially similar to the corresponding Apache CLAs. + +If you own the work you are contributing, sign the individual CLA. If your +employer owns the work you are contributing, have them sign the corporate CLA. + +**If you are employed, there is a substantial possibility that your employer +owns your work.** If they do, you do not have the right to contribute it to us +or assign the rights that we require, and can not contribute under the +individual CLA. Work with your employer to contribute under the corporate CLA +instead. + +Particularly, this clause in the individual CLA is the important one: + +> 4. You represent that you are legally entitled to grant the above license. If +> your employer(s) has rights to intellectual property that you create that +> includes your Contributions, you represent that you have received permission +> to make Contributions on behalf of that employer, that your employer has +> waived such rights for your Contributions to Phacility, or that your employer +> has executed a separate Corporate CLA with Phacility. + +Ownership of your work varies based on where you live, how you are employed, +and your agreements with your employer. However, at least in the US, it is +likely that your employer owns your work unless you have anticipated conflicts +and specifically avoided them. This generally makes sense: if you are paid by +your employer for your work, they own the product of your work and you receive +salary and benefits in fair exchange for that work. + +Your employer may have an ownership claim on your work even if you perform it +on your own time, if you use their equipment (like a company laptop or phone), +resources, facilities, or trade secrets, or signed something like an "Invention +Assignment Agreement" when you were hired. Such agreements are common. The +details of the strength of their claim will vary based on your situation and +local law. + +If you are unsure, you should speak with your employer or a lawyer. If you +contribute code you do not own under the individual CLA, you are exposing +yourself to liability. You may also be exposing us to liablity, but we'll have +the CLA on our side to show that we were unwilling pawns in your malicious +scheme to defraud your employer. + +The good news is that most employers are happy to contribute to open source +projects. Incentives are generally well aligned: they get features they want, +and it reflects well on them. In the past, potential contributors who have +approached their employers about a corporate CLA have generally had little +difficulty getting approval. diff --git a/src/docs/user/userguide/arcanist_lint_script_and_regex.diviner b/src/docs/user/userguide/arcanist_lint_script_and_regex.diviner index e8d021b1ac..fde32b7773 100644 --- a/src/docs/user/userguide/arcanist_lint_script_and_regex.diviner +++ b/src/docs/user/userguide/arcanist_lint_script_and_regex.diviner @@ -29,16 +29,13 @@ configure. == Script... == The script will be invoked once for each file that is to be linted, with -the file passed as the first argument. The file may begin with a "-"; ensure +the file passed as the first argument. The file may begin with a `-`; ensure your script will not interpret such files as flags (perhaps by ending your -script configuration with "--", if its argument parser supports that). +script configuration with `--`, if its argument parser supports that). -Note that when run via `arc diff`, the list of files to be linted includes -deleted files and files that were moved away by the change. The linter should -not assume the path it is given exists, and it is not an error for the -linter to be invoked with paths which are no longer there. (Every affected -path is subject to lint because some linters may raise errors in other files -when a file is removed, or raise an error about its removal.) +Note that when run via `arc diff`, the list of files to be linted does not +include binary files, symlinks, deleted files, or directories. These special +file types are not supported by this linter. The script should emit lint messages to stdout, which will be parsed with the provided regex. diff --git a/src/infrastructure/daemon/overseer/PhabricatorDaemonOverseerModule.php b/src/infrastructure/daemon/overseer/PhabricatorDaemonOverseerModule.php index e9f34028cd..aa238a4bf0 100644 --- a/src/infrastructure/daemon/overseer/PhabricatorDaemonOverseerModule.php +++ b/src/infrastructure/daemon/overseer/PhabricatorDaemonOverseerModule.php @@ -17,7 +17,11 @@ final class PhabricatorDaemonOverseerModule } public function shouldReloadDaemons() { - if ($this->timestamp < PhabricatorTime::getNow() - 10) { + $now = PhabricatorTime::getNow(); + $ago = ($now - $this->timestamp); + + // Don't check more than once every 10 seconds. + if ($ago < 10) { return false; } diff --git a/src/view/page/PhabricatorBarePageView.php b/src/view/page/PhabricatorBarePageView.php index ca6a6a783f..6a4444c981 100644 --- a/src/view/page/PhabricatorBarePageView.php +++ b/src/view/page/PhabricatorBarePageView.php @@ -75,6 +75,16 @@ class PhabricatorBarePageView extends AphrontPageView { 'maximum-scale=1', )); } + + $mask_icon = phutil_tag( + 'link', + array( + 'rel' => 'mask-icon', + 'color' => '#3D4B67', + 'href' => celerity_get_resource_uri( + '/rsrc/favicons/mask-icon.svg'), + )); + $icon_tag_76 = phutil_tag( 'link', array( @@ -130,8 +140,9 @@ class PhabricatorBarePageView extends AphrontPageView { $developer = PhabricatorEnv::getEnvConfig('phabricator.developer-mode'); return hsprintf( - '%s%s%s%s%s%s%s%s', + '%s%s%s%s%s%s%s%s%s', $viewport_tag, + $mask_icon, $icon_tag_76, $icon_tag_120, $icon_tag_152, diff --git a/src/view/phui/PHUIDocumentViewPro.php b/src/view/phui/PHUIDocumentViewPro.php index 1fbdd11cfc..94854fba96 100644 --- a/src/view/phui/PHUIDocumentViewPro.php +++ b/src/view/phui/PHUIDocumentViewPro.php @@ -31,7 +31,7 @@ final class PHUIDocumentViewPro extends AphrontTagView { return $this; } - public function setToc(PHUIListView $toc) { + public function setToc($toc) { $this->toc = $toc; return $this; } diff --git a/src/view/phui/PHUIIconView.php b/src/view/phui/PHUIIconView.php index 08e27b0753..c9d8a0808e 100644 --- a/src/view/phui/PHUIIconView.php +++ b/src/view/phui/PHUIIconView.php @@ -725,7 +725,26 @@ final class PHUIIconView extends AphrontTagView { 'fa-vimeo', 'fa-black-tie', 'fa-fonticons', - + 'fa-reddit-alien', + 'fa-edge', + 'fa-credit-card-alt', + 'fa-codiepie:before', + 'fa-modx', + 'fa-fort-awesome', + 'fa-usb', + 'fa-product-hunt', + 'fa-mixcloud', + 'fa-scribd', + 'fa-pause-circle', + 'fa-pause-circle-o', + 'fa-stop-circle', + 'fa-stop-circle-o', + 'fa-shopping-bag', + 'fa-shopping-basket', + 'fa-hashtag', + 'fa-bluetooth', + 'fa-bluetooth-b', + 'fa-percent', ); } diff --git a/src/view/phui/PHUIRemarkupPreviewPanel.php b/src/view/phui/PHUIRemarkupPreviewPanel.php index 1e10e8ec3f..064379cd0c 100644 --- a/src/view/phui/PHUIRemarkupPreviewPanel.php +++ b/src/view/phui/PHUIRemarkupPreviewPanel.php @@ -9,6 +9,9 @@ final class PHUIRemarkupPreviewPanel extends AphrontTagView { private $loadingText; private $controlID; private $previewURI; + private $previewType; + + const DOCUMENT = 'document'; protected function canAppendChild() { return false; @@ -34,6 +37,11 @@ final class PHUIRemarkupPreviewPanel extends AphrontTagView { return $this; } + public function setPreviewType($type) { + $this->previewType = $type; + return $this; + } + protected function getTagName() { return 'div'; } @@ -73,16 +81,6 @@ final class PHUIRemarkupPreviewPanel extends AphrontTagView { ), nonempty($this->loadingText, pht('Loading preview...'))); - $header = null; - if ($this->header) { - $header = phutil_tag( - 'div', - array( - 'class' => 'phui-preview-header', - ), - $this->header); - } - $preview = phutil_tag( 'div', array( @@ -91,7 +89,26 @@ final class PHUIRemarkupPreviewPanel extends AphrontTagView { ), $loading); - $content = array($header, $preview); + if (!$this->previewType) { + $header = null; + if ($this->header) { + $header = phutil_tag( + 'div', + array( + 'class' => 'phui-preview-header', + ), + $this->header); + } + $content = array($header, $preview); + + } else if ($this->previewType == self::DOCUMENT) { + $header = id(new PHUIHeaderView()) + ->setHeader(pht('%s (Preview)', $this->header)); + + $content = id(new PHUIDocumentViewPro()) + ->setHeader($header) + ->appendChild($preview); + } return id(new PHUIObjectBoxView()) ->appendChild($content) diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css index dc79a4cb64..f7b2c22364 100644 --- a/webroot/rsrc/css/core/remarkup.css +++ b/webroot/rsrc/css/core/remarkup.css @@ -155,8 +155,11 @@ margin: 4px 0; } -.phabricator-remarkup .remarkup-header + .remarkup-header { - margin-top: 0px; +.phabricator-remarkup h3.remarkup-header + h4.remarkup-header { + color: {$bluetext}; + font-weight: normal; + margin-bottom: 16px; + margin-top: -4px; } .phabricator-remarkup blockquote { @@ -168,6 +171,10 @@ background-color: {$lightbluebackground}; } +.phabricator-remarkup blockquote p { + margin: 0; +} + .phabricator-remarkup blockquote blockquote { background-color: rgba(175,175,175, .1); } @@ -363,12 +370,12 @@ body div.phabricator-remarkup.remarkup-has-toc padding-top: 0; } -body .phabricator-remarkup > *:first-child, -body .phabricator-remarkup .remarkup-header + * { +body .phabricator-standard-page div.phabricator-remarkup *:first-child, +body .phabricator-standard-page div.phabricator-remarkup .remarkup-header + * { margin-top: 0; } -body .phabricator-remarkup *:last-child { +body div.phabricator-remarkup > *:last-child { margin-bottom: 0; } diff --git a/webroot/rsrc/css/font/font-awesome.css b/webroot/rsrc/css/font/font-awesome.css index 1658708f4e..ca910e2cc8 100644 --- a/webroot/rsrc/css/font/font-awesome.css +++ b/webroot/rsrc/css/font/font-awesome.css @@ -3,15 +3,15 @@ */ /*! - * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome + * Font Awesome 4.5.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.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'); + src: url('/rsrc/externals/font/fontawesome/fontawesome-webfont.eot?v=4.5.0'); + src: url('/rsrc/externals/font/fontawesome/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('/rsrc/externals/font/fontawesome/fontawesome-webfont.ttf?v=4.5.0') format('truetype'); font-weight: normal; font-style: normal; } @@ -1887,3 +1887,63 @@ .fa-fonticons:before { content: "\f280"; } +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} diff --git a/webroot/rsrc/css/phui/phui-document-pro.css b/webroot/rsrc/css/phui/phui-document-pro.css index 47aa677105..7d211ab956 100644 --- a/webroot/rsrc/css/phui/phui-document-pro.css +++ b/webroot/rsrc/css/phui/phui-document-pro.css @@ -73,6 +73,20 @@ a.button.phui-document-toc { color: #fff; } +.phui-document-view-pro .phui-document-toc-content { + margin: 4px 12px; +} + +.phui-document-view-pro .phui-document-toc-header { + font-weight: bold; + color: {$bluetext}; + margin-bottom: 8px; +} + +.phui-document-view-pro .phui-document-toc-content li { + margin: 4px 8px; +} + .phui-document-view-pro .phui-document-content .phabricator-remarkup { padding: 16px 0; line-height: 1.7em; diff --git a/webroot/rsrc/css/phui/phui-document.css b/webroot/rsrc/css/phui/phui-document.css index eaf90dc468..3ceb445639 100644 --- a/webroot/rsrc/css/phui/phui-document.css +++ b/webroot/rsrc/css/phui/phui-document.css @@ -96,8 +96,9 @@ .legalpad .phui-document-content .phui-property-list-view { border: none; box-shadow: none; + border-radius: 3px; margin: 16px 0 0 0; - background-color: {$lightbluebackground}; + background-color: {$bluebackground}; } .phui-document-content { @@ -122,10 +123,6 @@ display: none; } -.device-phone .phui-document-content .phabricator-remarkup-toc { - width: 120px; -} - .phui-document-content .phabricator-remarkup .remarkup-code-block { clear: both; margin: 16px 0; @@ -139,41 +136,17 @@ background-color: {$lightgreybackground}; } -.phui-document-view .phabricator-remarkup.remarkup-has-toc { - position: relative; - margin-right: 192px; -} - -.phui-document-view .remarkup-has-toc .phabricator-remarkup-toc { - position: absolute; - top: 0; - right: -186px; - bottom: 0; - border-left: 1px solid {$thinblueborder}; - padding: 16px 12px; - margin: 0; - font-size: 12px; -} - -.device-phone .phui-document-view .phabricator-remarkup.remarkup-has-toc { - margin-right: 0; -} - -.device-phone .phui-document-view .remarkup-has-toc .phabricator-remarkup-toc { - display: none; -} - body .phui-document-view .phui-header-shell.phui-bleed-header { padding: 0; } .phui-document-view .phui-property-list-section-header { - padding: 12px 16px 0px; + padding: 20px 24px 0px; border-top: none; } .phui-document-view .phui-property-list-text-content { - padding: 0 16px; + padding: 0 24px 4px; } .phui-document-view .PhabricatorMonospaced, diff --git a/webroot/rsrc/css/phui/phui-fontkit.css b/webroot/rsrc/css/phui/phui-fontkit.css index 80a12f881a..ec711612ad 100644 --- a/webroot/rsrc/css/phui/phui-fontkit.css +++ b/webroot/rsrc/css/phui/phui-fontkit.css @@ -26,8 +26,11 @@ font-family: 'Aleo', {$fontfamily}; } +.phui-document-view .phabricator-remarkup .remarkup-header { + margin-bottom: 8px; +} + .phui-document-view .phabricator-remarkup h2.remarkup-header { padding: 0 24px 8px 0; - border-bottom: 1px solid {$thinblueborder}; - margin: 32px 0 16px; + margin: 32px 0 4px; } diff --git a/webroot/rsrc/css/phui/phui-form-view.css b/webroot/rsrc/css/phui/phui-form-view.css index ae777a8936..8368177cad 100644 --- a/webroot/rsrc/css/phui/phui-form-view.css +++ b/webroot/rsrc/css/phui/phui-form-view.css @@ -527,3 +527,7 @@ properly, and submit values. */ .aphront-form-choose-table .aphront-form-choose-button-cell { padding: 4px 8px; } + +.aphront-form-preview-hidden { + opacity: 0.5; +} diff --git a/webroot/rsrc/css/phui/phui-remarkup-preview.css b/webroot/rsrc/css/phui/phui-remarkup-preview.css index 658e5010ee..c045cae703 100644 --- a/webroot/rsrc/css/phui/phui-remarkup-preview.css +++ b/webroot/rsrc/css/phui/phui-remarkup-preview.css @@ -41,7 +41,7 @@ *
or not. It should probably move to the Engine in all cases, but * until we do that get rid of the extra spacing generated by the inner div. */ -.phui-remarkup-preview .phabricator-remarkup .phabricator-remarkup { +body .phui-remarkup-preview .phabricator-remarkup .phabricator-remarkup { padding: 0; margin: 0; } diff --git a/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.eot b/webroot/rsrc/externals/font/fontawesome/fontawesome-webfont.eot index a30335d748..9b6afaedc0 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 d7994e1308..26dea7951a 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 6fd4ede0f3..dc35ce3c2c 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 5560193ccc..500e517253 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/favicons/mask-icon.svg b/webroot/rsrc/favicons/mask-icon.svg new file mode 100644 index 0000000000..d949114e43 --- /dev/null +++ b/webroot/rsrc/favicons/mask-icon.svg @@ -0,0 +1,20 @@ + + + + + + diff --git a/webroot/rsrc/js/application/phame/phame-post-preview.js b/webroot/rsrc/js/application/phame/phame-post-preview.js index 196b6e6469..377a6f66d5 100644 --- a/webroot/rsrc/js/application/phame/phame-post-preview.js +++ b/webroot/rsrc/js/application/phame/phame-post-preview.js @@ -8,7 +8,6 @@ JX.behavior('phame-post-preview', function(config) { - var body = JX.$(config.body); var title = JX.$(config.title); var phame_title = JX.$(config.phame_title); var sync_titles = true; @@ -54,27 +53,15 @@ JX.behavior('phame-post-preview', function(config) { return s; }; - var callback = function(r) { - JX.DOM.setContent(JX.$(config.preview), JX.$H(r)); - }; - var getdata = function() { return { - body : body.value, title : title.value, phame_title : phame_title.value }; }; - var request = new JX.PhabricatorShapedRequest(config.uri, callback, getdata); - var trigger = JX.bind(request, request.trigger); - - JX.DOM.listen(body, 'keydown', null, trigger); - JX.DOM.listen(title, 'keydown', null, trigger); JX.DOM.listen(title, 'keyup', null, titleCallback); - JX.DOM.listen(phame_title, 'keydown', null, trigger); JX.DOM.listen(phame_title, 'keyup', null, phameTitleKeyupCallback); JX.DOM.listen(phame_title, 'blur', null, phameTitleBlurCallback); - request.start(); }); diff --git a/webroot/rsrc/js/application/transactions/behavior-reorder-fields.js b/webroot/rsrc/js/application/transactions/behavior-reorder-fields.js new file mode 100644 index 0000000000..bfb31f35af --- /dev/null +++ b/webroot/rsrc/js/application/transactions/behavior-reorder-fields.js @@ -0,0 +1,32 @@ +/** + * @provides javelin-behavior-editengine-reorder-fields + * @requires javelin-behavior + * javelin-stratcom + * javelin-workflow + * javelin-dom + * phabricator-draggable-list + */ + +JX.behavior('editengine-reorder-fields', function(config) { + + var root = JX.$(config.listID); + + var list = new JX.DraggableList('editengine-form-field', root) + .setFindItemsHandler(function() { + return JX.DOM.scry(root, 'li', 'editengine-form-field'); + }); + + list.listen('didDrop', function() { + var nodes = list.findItems(); + + var data; + var keys = []; + for (var ii = 0; ii < nodes.length; ii++) { + data = JX.Stratcom.getData(nodes[ii]); + keys.push(data.fieldKey); + } + + JX.$(config.inputID).value = keys.join(','); + }); + +});