diff --git a/externals/skins/oblivious/css/oblivious.css b/externals/skins/oblivious/css/oblivious.css index cad5d6cf9a..044d478aab 100644 --- a/externals/skins/oblivious/css/oblivious.css +++ b/externals/skins/oblivious/css/oblivious.css @@ -29,19 +29,18 @@ html { .oblivious-content { padding-top: 3%; margin-left: 22%; - max-width: 600px; + max-width: 800px; } a { - color: #222222; + color: #2980b9; text-decoration: none; } a:hover { - color: #a00000; + text-decoration: underline; } - h1 { font-size: 24px; font-weight: normal; @@ -50,37 +49,24 @@ h1 { h2 { font-size: 22px; font-weight: bold; + margin-bottom: 8px; } .phame-post { margin: 0 0 2em; } +.phame-post-title { + font-size: 28px; +} + .phame-post-date { font-size: 12px; - margin: .25em 0 1em; + margin: .25em 0 2em; } -.phame-post { - line-height: 1.6em; -} - -.phame-post p { - margin: 0 0 1em; -} - -.phame-post tt { - color: #333333; - background: #ebebeb; - padding: 0 .25em; - white-space: pre-wrap; -} - -.phame-post .remarkup-code-block pre { - overflow: auto; - padding: 10px 10px; - border: 1px solid #dfdfdf; - background-color: #f8f8f8; +.oblivious-content .phabricator-remarkup ul.remarkup-list { + margin-left: 0; } .fb-comments, diff --git a/externals/skins/oblivious/header.php b/externals/skins/oblivious/header.php index c3e7a4d60f..0ea9f331c7 100644 --- a/externals/skins/oblivious/header.php +++ b/externals/skins/oblivious/header.php @@ -13,6 +13,6 @@ echo _e($blog->getName()); ?> -

getDescription()); ?>

+

remarkup($blog->getDescription()); ?>

diff --git a/resources/celerity/map.php b/resources/celerity/map.php index fe97bdc236..91b57e9f5d 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '15e557bc', + 'core.pkg.css' => 'e94665e4', 'core.pkg.js' => '47dc9ebb', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', @@ -25,8 +25,8 @@ return array( 'rsrc/css/aphront/notification.css' => '9c279160', 'rsrc/css/aphront/panel-view.css' => '8427b78d', 'rsrc/css/aphront/phabricator-nav-view.css' => 'a24cb589', - 'rsrc/css/aphront/table-view.css' => '61543e7a', - 'rsrc/css/aphront/tokenizer.css' => '04875312', + 'rsrc/css/aphront/table-view.css' => '6d01d468', + 'rsrc/css/aphront/tokenizer.css' => '056da01b', 'rsrc/css/aphront/tooltip.css' => '7672b60f', 'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c', 'rsrc/css/aphront/typeahead.css' => '0e403212', @@ -36,7 +36,7 @@ return array( 'rsrc/css/application/base/notification-menu.css' => 'f31c0bde', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601', 'rsrc/css/application/base/phui-theme.css' => '6b451f24', - 'rsrc/css/application/base/standard-page-view.css' => '1f53d056', + 'rsrc/css/application/base/standard-page-view.css' => 'a1096ed4', 'rsrc/css/application/calendar/calendar-icon.css' => 'c69aa59f', 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', @@ -100,17 +100,17 @@ return array( 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/search/search-results.css' => '7dea472c', - 'rsrc/css/application/slowvote/slowvote.css' => '475b4bd2', + 'rsrc/css/application/slowvote/slowvote.css' => 'da0afb1b', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', - 'rsrc/css/core/core.css' => 'a76cefc9', - 'rsrc/css/core/remarkup.css' => '8d341238', + 'rsrc/css/core/core.css' => '78e8d7ea', + 'rsrc/css/core/remarkup.css' => '2193fc05', 'rsrc/css/core/syntax.css' => '9fd11da8', 'rsrc/css/core/z-index.css' => '57ddcaa2', - 'rsrc/css/diviner/diviner-shared.css' => '5a337049', + '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-roboto-slab.css' => 'f24a53cb', '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,16 +126,17 @@ return array( 'rsrc/css/phui/phui-box.css' => 'a5bb366d', 'rsrc/css/phui/phui-button.css' => '16020a60', 'rsrc/css/phui/phui-crumbs-view.css' => 'd842f867', - 'rsrc/css/phui/phui-document.css' => '0267054b', + 'rsrc/css/phui/phui-document-pro.css' => '4f2b42e3', + 'rsrc/css/phui/phui-document.css' => '9fa715d2', 'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23', - 'rsrc/css/phui/phui-fontkit.css' => 'cb8ae7ad', + 'rsrc/css/phui/phui-fontkit.css' => 'c9d63950', 'rsrc/css/phui/phui-form-view.css' => '621b21c5', 'rsrc/css/phui/phui-form.css' => 'afdb2c6e', 'rsrc/css/phui/phui-header-view.css' => '55bb32dd', 'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6', 'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', - 'rsrc/css/phui/phui-info-view.css' => '5b16bac6', + 'rsrc/css/phui/phui-info-view.css' => '6d7c3509', 'rsrc/css/phui/phui-list.css' => '125599df', 'rsrc/css/phui/phui-object-box.css' => '407eaf5a', 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', @@ -145,7 +146,7 @@ return array( 'rsrc/css/phui/phui-remarkup-preview.css' => '867f85b3', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '888cedb8', - 'rsrc/css/phui/phui-tag-view.css' => '402691cc', + 'rsrc/css/phui/phui-tag-view.css' => 'e60e227b', 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 'rsrc/css/phui/phui-two-column-view.css' => '39ecafb1', @@ -156,6 +157,14 @@ return array( 'rsrc/css/sprite-menu.css' => '9dd65b92', '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.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.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', @@ -176,10 +185,6 @@ return array( 'rsrc/externals/font/lato/lato-regular.ttf' => 'e270165b', 'rsrc/externals/font/lato/lato-regular.woff' => '13d39fe2', 'rsrc/externals/font/lato/lato-regular.woff2' => '57a9f742', - 'rsrc/externals/font/robotoslab/robotoslab-regular.eot' => 'eaefe21c', - 'rsrc/externals/font/robotoslab/robotoslab-regular.ttf' => '4bfef7d5', - 'rsrc/externals/font/robotoslab/robotoslab-regular.woff' => '7f0552f9', - 'rsrc/externals/font/robotoslab/robotoslab-regular.woff2' => '23bdd43c', 'rsrc/externals/javelin/core/Event.js' => '85ea0626', 'rsrc/externals/javelin/core/Stratcom.js' => '6c53634d', 'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '717554e4', @@ -448,7 +453,7 @@ return array( 'rsrc/js/core/behavior-device.js' => 'a205cf28', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '6d49590e', 'rsrc/js/core/behavior-error-log.js' => '6882e80a', - 'rsrc/js/core/behavior-fancy-datepicker.js' => '665cf6ac', + 'rsrc/js/core/behavior-fancy-datepicker.js' => '8ae55229', 'rsrc/js/core/behavior-file-tree.js' => '88236f00', 'rsrc/js/core/behavior-form.js' => '5c54cbf3', 'rsrc/js/core/behavior-gesture.js' => '3ab51e2c', @@ -493,8 +498,8 @@ return array( 'aphront-list-filter-view-css' => '5d6f0526', 'aphront-multi-column-view-css' => 'fd18389d', 'aphront-panel-view-css' => '8427b78d', - 'aphront-table-view-css' => '61543e7a', - 'aphront-tokenizer-control-css' => '04875312', + 'aphront-table-view-css' => '6d01d468', + 'aphront-tokenizer-control-css' => '056da01b', 'aphront-tooltip-css' => '7672b60f', 'aphront-typeahead-control-css' => '0e403212', 'auth-css' => '0877ed6e', @@ -523,10 +528,10 @@ return array( 'diffusion-icons-css' => '2941baf1', 'diffusion-readme-css' => '2106ea08', 'diffusion-source-css' => '075ba788', - 'diviner-shared-css' => '5a337049', + 'diviner-shared-css' => 'aa3656aa', + 'font-aleo' => 'b61d3062', 'font-fontawesome' => 'd2fc4e8d', 'font-lato' => '5ab1a46a', - 'font-roboto-slab' => 'f24a53cb', 'global-drag-and-drop-css' => '697324ad', 'harbormaster-css' => 'b0758ca5', 'herald-css' => '826075fa', @@ -581,7 +586,7 @@ return array( 'javelin-behavior-durable-column' => 'c72aa091', 'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-event-all-day' => '38dcf3c8', - 'javelin-behavior-fancy-datepicker' => '665cf6ac', + 'javelin-behavior-fancy-datepicker' => '8ae55229', 'javelin-behavior-global-drag-and-drop' => 'c8e57404', 'javelin-behavior-herald-rule-editor' => '7ebaeed3', 'javelin-behavior-high-security-warning' => 'a464fe03', @@ -713,7 +718,7 @@ return array( 'phabricator-busy' => '59a7976a', 'phabricator-chatlog-css' => 'd295b020', 'phabricator-content-source-view-css' => '4b8b05d4', - 'phabricator-core-css' => 'a76cefc9', + 'phabricator-core-css' => '78e8d7ea', 'phabricator-countdown-css' => 'e7544472', 'phabricator-dashboard-css' => 'eb458607', 'phabricator-drag-and-drop-file-upload' => 'ad10aeac', @@ -735,13 +740,13 @@ return array( 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => '6920d200', - 'phabricator-remarkup-css' => '8d341238', + 'phabricator-remarkup-css' => '2193fc05', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-side-menu-view-css' => 'bec2458e', - 'phabricator-slowvote-css' => '475b4bd2', + 'phabricator-slowvote-css' => 'da0afb1b', 'phabricator-source-code-view-css' => 'cbeef983', - 'phabricator-standard-page-view' => '1f53d056', + 'phabricator-standard-page-view' => 'a1096ed4', 'phabricator-textareautils' => '5c93c52c', 'phabricator-title' => 'df5e11d2', 'phabricator-tooltip' => '1d298e3a', @@ -775,17 +780,18 @@ return array( 'phui-calendar-list-css' => 'c1c7f338', 'phui-calendar-month-css' => '476be7e0', 'phui-crumbs-view-css' => 'd842f867', - 'phui-document-view-css' => '0267054b', + 'phui-document-view-css' => '9fa715d2', + 'phui-document-view-pro-css' => '4f2b42e3', 'phui-feed-story-css' => 'b7b26d23', 'phui-font-icon-base-css' => 'ecbbb4c2', - 'phui-fontkit-css' => 'cb8ae7ad', + 'phui-fontkit-css' => 'c9d63950', 'phui-form-css' => 'afdb2c6e', 'phui-form-view-css' => '621b21c5', 'phui-header-view-css' => '55bb32dd', 'phui-icon-view-css' => 'b0a6b1b6', 'phui-image-mask-css' => '5a8b09c8', 'phui-info-panel-css' => '27ea50a1', - 'phui-info-view-css' => '5b16bac6', + 'phui-info-view-css' => '6d7c3509', 'phui-inline-comment-view-css' => '0fdb3667', 'phui-list-view-css' => '125599df', 'phui-object-box-css' => '407eaf5a', @@ -796,7 +802,7 @@ return array( 'phui-remarkup-preview-css' => '867f85b3', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '888cedb8', - 'phui-tag-view-css' => '402691cc', + 'phui-tag-view-css' => 'e60e227b', 'phui-text-css' => 'cf019f54', 'phui-theme-css' => '6b451f24', 'phui-timeline-view-css' => '2efceff8', @@ -861,14 +867,14 @@ return array( 'javelin-stratcom', 'phabricator-prefab', ), - '04875312' => array( - 'aphront-typeahead-control-css', - 'phui-tag-view-css', - ), '05270951' => array( 'javelin-util', 'javelin-magical-init', ), + '056da01b' => array( + 'aphront-typeahead-control-css', + 'phui-tag-view-css', + ), '065227cc' => array( 'javelin-behavior', 'javelin-dom', @@ -1288,13 +1294,6 @@ return array( 'javelin-vector', 'differential-inline-comment-editor', ), - '665cf6ac' => array( - 'javelin-behavior', - 'javelin-util', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-vector', - ), '6882e80a' => array( 'javelin-dom', ), @@ -1494,6 +1493,13 @@ return array( 'javelin-install', 'javelin-dom', ), + '8ae55229' => array( + 'javelin-behavior', + 'javelin-util', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-vector', + ), '8b3fd187' => array( 'javelin-install', 'javelin-util', @@ -1711,6 +1717,9 @@ return array( 'javelin-dom', 'javelin-util', ), + 'b61d3062' => array( + 'phui-fontkit-css', + ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1946,9 +1955,6 @@ return array( 'javelin-workflow', 'javelin-json', ), - 'f24a53cb' => array( - 'phui-fontkit-css', - ), 'f36e01af' => array( 'javelin-behavior', 'javelin-behavior-device', diff --git a/resources/sql/autopatches/20151030.harbormaster.initiator.sql b/resources/sql/autopatches/20151030.harbormaster.initiator.sql new file mode 100644 index 0000000000..f8ba3f6757 --- /dev/null +++ b/resources/sql/autopatches/20151030.harbormaster.initiator.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_build + ADD COLUMN initiatorPHID VARBINARY(64); diff --git a/resources/sql/autopatches/20151106.phame.post.mailkey.1.sql b/resources/sql/autopatches/20151106.phame.post.mailkey.1.sql new file mode 100644 index 0000000000..3e4846d909 --- /dev/null +++ b/resources/sql/autopatches/20151106.phame.post.mailkey.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_phame.phame_post + ADD mailKey binary(20) NOT NULL; diff --git a/resources/sql/autopatches/20151106.phame.post.mailkey.2.php b/resources/sql/autopatches/20151106.phame.post.mailkey.2.php new file mode 100644 index 0000000000..5c9942665d --- /dev/null +++ b/resources/sql/autopatches/20151106.phame.post.mailkey.2.php @@ -0,0 +1,18 @@ +establishConnection('w'); +$iterator = new LiskMigrationIterator($table); +foreach ($iterator as $post) { + $id = $post->getID(); + + echo pht('Adding mail key for Post %d...', $id); + echo "\n"; + + queryfx( + $conn_w, + 'UPDATE %T SET mailKey = %s WHERE id = %d', + $table->getTableName(), + Filesystem::readRandomCharacters(20), + $id); +} diff --git a/scripts/symbols/import_repository_symbols.php b/scripts/symbols/import_repository_symbols.php index 2ac2b3c8a9..c8dabc8508 100755 --- a/scripts/symbols/import_repository_symbols.php +++ b/scripts/symbols/import_repository_symbols.php @@ -102,7 +102,7 @@ function commit_symbols( $repository->getPHID()); } - echo pht('Loading %s symbols...', new PhutilNumber(count($sql))), "\n"; + echo pht('Loading %s symbols...', phutil_count($sql)), "\n"; foreach (array_chunk($sql, 128) as $chunk) { queryfx( $conn_w, diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 398d212913..aaacc2cde4 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -135,6 +135,7 @@ phutil_register_library_map(array( 'AphrontFormView' => 'view/form/AphrontFormView.php', 'AphrontGlyphBarView' => 'view/widget/bars/AphrontGlyphBarView.php', 'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php', + 'AphrontHTTPParameterType' => 'aphront/httpparametertype/AphrontHTTPParameterType.php', 'AphrontHTTPProxyResponse' => 'aphront/response/AphrontHTTPProxyResponse.php', 'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php', 'AphrontHTTPSinkTestCase' => 'aphront/sink/__tests__/AphrontHTTPSinkTestCase.php', @@ -149,10 +150,13 @@ phutil_register_library_map(array( 'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php', 'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php', 'AphrontNullView' => 'view/AphrontNullView.php', + 'AphrontPHIDHTTPParameterType' => 'aphront/httpparametertype/AphrontPHIDHTTPParameterType.php', + 'AphrontPHIDListHTTPParameterType' => 'aphront/httpparametertype/AphrontPHIDListHTTPParameterType.php', 'AphrontPHPHTTPSink' => 'aphront/sink/AphrontPHPHTTPSink.php', 'AphrontPageView' => 'view/page/AphrontPageView.php', 'AphrontPlainTextResponse' => 'aphront/response/AphrontPlainTextResponse.php', 'AphrontProgressBarView' => 'view/widget/bars/AphrontProgressBarView.php', + 'AphrontProjectListHTTPParameterType' => 'aphront/httpparametertype/AphrontProjectListHTTPParameterType.php', 'AphrontProxyResponse' => 'aphront/response/AphrontProxyResponse.php', 'AphrontRedirectResponse' => 'aphront/response/AphrontRedirectResponse.php', 'AphrontRedirectResponseTestCase' => 'aphront/response/__tests__/AphrontRedirectResponseTestCase.php', @@ -164,15 +168,19 @@ phutil_register_library_map(array( 'AphrontResponseProducerInterface' => 'aphront/interface/AphrontResponseProducerInterface.php', 'AphrontRoutingMap' => 'aphront/site/AphrontRoutingMap.php', 'AphrontRoutingResult' => 'aphront/site/AphrontRoutingResult.php', + 'AphrontSelectHTTPParameterType' => 'aphront/httpparametertype/AphrontSelectHTTPParameterType.php', 'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php', 'AphrontSite' => 'aphront/site/AphrontSite.php', 'AphrontStackTraceView' => 'view/widget/AphrontStackTraceView.php', 'AphrontStandaloneHTMLResponse' => 'aphront/response/AphrontStandaloneHTMLResponse.php', + 'AphrontStringHTTPParameterType' => 'aphront/httpparametertype/AphrontStringHTTPParameterType.php', + 'AphrontStringListHTTPParameterType' => 'aphront/httpparametertype/AphrontStringListHTTPParameterType.php', 'AphrontTableView' => 'view/control/AphrontTableView.php', 'AphrontTagView' => 'view/AphrontTagView.php', 'AphrontTokenizerTemplateView' => 'view/control/AphrontTokenizerTemplateView.php', 'AphrontTypeaheadTemplateView' => 'view/control/AphrontTypeaheadTemplateView.php', 'AphrontUnhandledExceptionResponse' => 'aphront/response/AphrontUnhandledExceptionResponse.php', + 'AphrontUserListHTTPParameterType' => 'aphront/httpparametertype/AphrontUserListHTTPParameterType.php', 'AphrontView' => 'view/AphrontView.php', 'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', 'ArcanistConduitAPIMethod' => 'applications/arcanist/conduit/ArcanistConduitAPIMethod.php', @@ -1403,6 +1411,7 @@ phutil_register_library_map(array( 'PHUI' => 'view/phui/PHUI.php', 'PHUIActionPanelExample' => 'applications/uiexample/examples/PHUIActionPanelExample.php', 'PHUIActionPanelView' => 'view/phui/PHUIActionPanelView.php', + 'PHUIApplicationMenuView' => 'view/layout/PHUIApplicationMenuView.php', 'PHUIBadgeBoxView' => 'view/phui/PHUIBadgeBoxView.php', 'PHUIBadgeExample' => 'applications/uiexample/examples/PHUIBadgeExample.php', 'PHUIBadgeMiniView' => 'view/phui/PHUIBadgeMiniView.php', @@ -1433,6 +1442,7 @@ phutil_register_library_map(array( 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php', 'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php', 'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php', + 'PHUIDocumentViewPro' => 'view/phui/PHUIDocumentViewPro.php', 'PHUIFeedStoryExample' => 'applications/uiexample/examples/PHUIFeedStoryExample.php', 'PHUIFeedStoryView' => 'view/phui/PHUIFeedStoryView.php', 'PHUIFormDividerControl' => 'view/form/control/PHUIFormDividerControl.php', @@ -1528,6 +1538,7 @@ phutil_register_library_map(array( 'PasteCreateMailReceiver' => 'applications/paste/mail/PasteCreateMailReceiver.php', 'PasteDefaultEditCapability' => 'applications/paste/capability/PasteDefaultEditCapability.php', 'PasteDefaultViewCapability' => 'applications/paste/capability/PasteDefaultViewCapability.php', + 'PasteEditConduitAPIMethod' => 'applications/paste/conduit/PasteEditConduitAPIMethod.php', 'PasteEmbedView' => 'applications/paste/view/PasteEmbedView.php', 'PasteInfoConduitAPIMethod' => 'applications/paste/conduit/PasteInfoConduitAPIMethod.php', 'PasteMailReceiver' => 'applications/paste/mail/PasteMailReceiver.php', @@ -1568,6 +1579,9 @@ phutil_register_library_map(array( 'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php', 'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php', 'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php', + 'PhabricatorApplicationEditEngine' => 'applications/transactions/editengine/PhabricatorApplicationEditEngine.php', + 'PhabricatorApplicationEditEngineAPIMethod' => 'applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php', + 'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php', 'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php', 'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php', 'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php', @@ -1840,7 +1854,6 @@ phutil_register_library_map(array( 'PhabricatorCommonPasswords' => 'applications/auth/constants/PhabricatorCommonPasswords.php', 'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php', 'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php', - 'PhabricatorConduitCertificateSettingsPanel' => 'applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php', 'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php', 'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php', 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php', @@ -1884,6 +1897,7 @@ phutil_register_library_map(array( 'PhabricatorConfigEntryQuery' => 'applications/config/query/PhabricatorConfigEntryQuery.php', 'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php', 'PhabricatorConfigGroupController' => 'applications/config/controller/PhabricatorConfigGroupController.php', + 'PhabricatorConfigHTTPParameterTypesModule' => 'applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php', 'PhabricatorConfigHistoryController' => 'applications/config/controller/PhabricatorConfigHistoryController.php', 'PhabricatorConfigIgnoreController' => 'applications/config/controller/PhabricatorConfigIgnoreController.php', 'PhabricatorConfigIssueListController' => 'applications/config/controller/PhabricatorConfigIssueListController.php', @@ -2061,6 +2075,7 @@ phutil_register_library_map(array( 'PhabricatorDataCacheSpec' => 'applications/cache/spec/PhabricatorDataCacheSpec.php', 'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php', 'PhabricatorDatabaseSetupCheck' => 'applications/config/check/PhabricatorDatabaseSetupCheck.php', + 'PhabricatorDatasourceEditField' => 'applications/transactions/editfield/PhabricatorDatasourceEditField.php', 'PhabricatorDateTimeSettingsPanel' => 'applications/settings/panel/PhabricatorDateTimeSettingsPanel.php', 'PhabricatorDebugController' => 'applications/system/controller/PhabricatorDebugController.php', 'PhabricatorDefaultRequestExceptionHandler' => 'aphront/handler/PhabricatorDefaultRequestExceptionHandler.php', @@ -2089,12 +2104,15 @@ phutil_register_library_map(array( 'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php', 'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php', 'PhabricatorEdgeCycleException' => 'infrastructure/edges/exception/PhabricatorEdgeCycleException.php', + 'PhabricatorEdgeEditType' => 'applications/transactions/edittype/PhabricatorEdgeEditType.php', 'PhabricatorEdgeEditor' => 'infrastructure/edges/editor/PhabricatorEdgeEditor.php', 'PhabricatorEdgeGraph' => 'infrastructure/edges/util/PhabricatorEdgeGraph.php', 'PhabricatorEdgeQuery' => 'infrastructure/edges/query/PhabricatorEdgeQuery.php', 'PhabricatorEdgeTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeTestCase.php', 'PhabricatorEdgeType' => 'infrastructure/edges/type/PhabricatorEdgeType.php', 'PhabricatorEdgeTypeTestCase' => 'infrastructure/edges/type/__tests__/PhabricatorEdgeTypeTestCase.php', + 'PhabricatorEditField' => 'applications/transactions/editfield/PhabricatorEditField.php', + 'PhabricatorEditType' => 'applications/transactions/edittype/PhabricatorEditType.php', 'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php', 'PhabricatorElasticSearchEngine' => 'applications/search/engine/PhabricatorElasticSearchEngine.php', 'PhabricatorElasticSearchSetupCheck' => 'applications/config/check/PhabricatorElasticSearchSetupCheck.php', @@ -2241,6 +2259,7 @@ phutil_register_library_map(array( 'PhabricatorGlobalLock' => 'infrastructure/util/PhabricatorGlobalLock.php', 'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php', 'PhabricatorGoogleAuthProvider' => 'applications/auth/provider/PhabricatorGoogleAuthProvider.php', + 'PhabricatorHTTPParameterTypeTableView' => 'applications/config/view/PhabricatorHTTPParameterTypeTableView.php', 'PhabricatorHandleList' => 'applications/phid/handle/pool/PhabricatorHandleList.php', 'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/PhabricatorHandleObjectSelectorDataView.php', 'PhabricatorHandlePool' => 'applications/phid/handle/pool/PhabricatorHandlePool.php', @@ -2532,6 +2551,7 @@ phutil_register_library_map(array( 'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php', 'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php', 'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php', + 'PhabricatorPHIDResolver' => 'applications/phid/resolver/PhabricatorPHIDResolver.php', 'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php', 'PhabricatorPHIDTypeTestCase' => 'applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php', 'PhabricatorPHPASTApplication' => 'applications/phpast/application/PhabricatorPHPASTApplication.php', @@ -2552,6 +2572,7 @@ phutil_register_library_map(array( 'PhabricatorPasteController' => 'applications/paste/controller/PhabricatorPasteController.php', 'PhabricatorPasteDAO' => 'applications/paste/storage/PhabricatorPasteDAO.php', 'PhabricatorPasteEditController' => 'applications/paste/controller/PhabricatorPasteEditController.php', + 'PhabricatorPasteEditEngine' => 'applications/paste/editor/PhabricatorPasteEditEngine.php', 'PhabricatorPasteEditor' => 'applications/paste/editor/PhabricatorPasteEditor.php', 'PhabricatorPasteListController' => 'applications/paste/controller/PhabricatorPasteListController.php', 'PhabricatorPastePastePHIDType' => 'applications/paste/phid/PhabricatorPastePastePHIDType.php', @@ -2622,8 +2643,11 @@ phutil_register_library_map(array( 'PhabricatorPhurlApplication' => 'applications/phurl/application/PhabricatorPhurlApplication.php', 'PhabricatorPhurlController' => 'applications/phurl/controller/PhabricatorPhurlController.php', 'PhabricatorPhurlDAO' => 'applications/phurl/storage/PhabricatorPhurlDAO.php', + 'PhabricatorPhurlLinkRemarkupRule' => 'applications/phurl/remarkup/PhabricatorPhurlLinkRemarkupRule.php', + 'PhabricatorPhurlRemarkupRule' => 'applications/phurl/remarkup/PhabricatorPhurlRemarkupRule.php', 'PhabricatorPhurlSchemaSpec' => 'applications/phurl/storage/PhabricatorPhurlSchemaSpec.php', 'PhabricatorPhurlURL' => 'applications/phurl/storage/PhabricatorPhurlURL.php', + 'PhabricatorPhurlURLAccessController' => 'applications/phurl/controller/PhabricatorPhurlURLAccessController.php', 'PhabricatorPhurlURLEditController' => 'applications/phurl/controller/PhabricatorPhurlURLEditController.php', 'PhabricatorPhurlURLEditor' => 'applications/phurl/editor/PhabricatorPhurlURLEditor.php', 'PhabricatorPhurlURLListController' => 'applications/phurl/controller/PhabricatorPhurlURLListController.php', @@ -2651,6 +2675,7 @@ phutil_register_library_map(array( 'PhabricatorPolicyDAO' => 'applications/policy/storage/PhabricatorPolicyDAO.php', 'PhabricatorPolicyDataTestCase' => 'applications/policy/__tests__/PhabricatorPolicyDataTestCase.php', 'PhabricatorPolicyEditController' => 'applications/policy/controller/PhabricatorPolicyEditController.php', + 'PhabricatorPolicyEditField' => 'applications/transactions/editfield/PhabricatorPolicyEditField.php', 'PhabricatorPolicyException' => 'applications/policy/exception/PhabricatorPolicyException.php', 'PhabricatorPolicyExplainController' => 'applications/policy/controller/PhabricatorPolicyExplainController.php', 'PhabricatorPolicyFilter' => 'applications/policy/filter/PhabricatorPolicyFilter.php', @@ -2718,6 +2743,7 @@ phutil_register_library_map(array( 'PhabricatorProjectObjectHasProjectEdgeType' => 'applications/project/edge/PhabricatorProjectObjectHasProjectEdgeType.php', 'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php', 'PhabricatorProjectOrUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserFunctionDatasource.php', + 'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', 'PhabricatorProjectProjectHasMemberEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasMemberEdgeType.php', 'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php', @@ -2740,6 +2766,7 @@ phutil_register_library_map(array( 'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php', 'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php', 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', + 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', 'PhabricatorProjectsPolicyRule' => 'applications/policy/rule/PhabricatorProjectsPolicyRule.php', 'PhabricatorProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorProtocolAdapter.php', 'PhabricatorPygmentSetupCheck' => 'applications/config/check/PhabricatorPygmentSetupCheck.php', @@ -2914,6 +2941,7 @@ phutil_register_library_map(array( 'PhabricatorSearchWorker' => 'applications/search/worker/PhabricatorSearchWorker.php', 'PhabricatorSecurityConfigOptions' => 'applications/config/option/PhabricatorSecurityConfigOptions.php', 'PhabricatorSecuritySetupCheck' => 'applications/config/check/PhabricatorSecuritySetupCheck.php', + 'PhabricatorSelectEditField' => 'applications/transactions/editfield/PhabricatorSelectEditField.php', 'PhabricatorSendGridConfigOptions' => 'applications/config/option/PhabricatorSendGridConfigOptions.php', 'PhabricatorSessionsSettingsPanel' => 'applications/settings/panel/PhabricatorSessionsSettingsPanel.php', 'PhabricatorSettingsAddEmailAction' => 'applications/settings/action/PhabricatorSettingsAddEmailAction.php', @@ -2926,6 +2954,7 @@ phutil_register_library_map(array( 'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php', 'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php', 'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php', + 'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php', 'PhabricatorSite' => 'aphront/site/PhabricatorSite.php', 'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php', 'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php', @@ -2954,6 +2983,7 @@ phutil_register_library_map(array( 'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php', 'PhabricatorSortTableUIExample' => 'applications/uiexample/examples/PhabricatorSortTableUIExample.php', 'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php', + 'PhabricatorSpaceEditField' => 'applications/transactions/editfield/PhabricatorSpaceEditField.php', 'PhabricatorSpacesApplication' => 'applications/spaces/application/PhabricatorSpacesApplication.php', 'PhabricatorSpacesArchiveController' => 'applications/spaces/controller/PhabricatorSpacesArchiveController.php', 'PhabricatorSpacesCapabilityCreateSpaces' => 'applications/spaces/capability/PhabricatorSpacesCapabilityCreateSpaces.php', @@ -3017,6 +3047,7 @@ phutil_register_library_map(array( 'PhabricatorStreamingProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorStreamingProtocolAdapter.php', 'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php', 'PhabricatorSubscribedToObjectEdgeType' => 'applications/transactions/edges/PhabricatorSubscribedToObjectEdgeType.php', + 'PhabricatorSubscribersEditField' => 'applications/transactions/editfield/PhabricatorSubscribersEditField.php', 'PhabricatorSubscribersQuery' => 'applications/subscriptions/query/PhabricatorSubscribersQuery.php', 'PhabricatorSubscriptionTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorSubscriptionTriggerClock.php', 'PhabricatorSubscriptionsAddSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsAddSelfHeraldAction.php', @@ -3060,6 +3091,8 @@ phutil_register_library_map(array( 'PhabricatorTestNoCycleEdgeType' => 'applications/transactions/edges/PhabricatorTestNoCycleEdgeType.php', 'PhabricatorTestStorageEngine' => 'applications/files/engine/PhabricatorTestStorageEngine.php', 'PhabricatorTestWorker' => 'infrastructure/daemon/workers/__tests__/PhabricatorTestWorker.php', + 'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php', + 'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php', 'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php', 'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php', 'PhabricatorTimeTestCase' => 'infrastructure/time/__tests__/PhabricatorTimeTestCase.php', @@ -3081,6 +3114,7 @@ phutil_register_library_map(array( 'PhabricatorTokenReceiverQuery' => 'applications/tokens/query/PhabricatorTokenReceiverQuery.php', 'PhabricatorTokenTokenPHIDType' => 'applications/tokens/phid/PhabricatorTokenTokenPHIDType.php', 'PhabricatorTokenUIEventListener' => 'applications/tokens/event/PhabricatorTokenUIEventListener.php', + 'PhabricatorTokenizerEditField' => 'applications/transactions/editfield/PhabricatorTokenizerEditField.php', 'PhabricatorTokensApplication' => 'applications/tokens/application/PhabricatorTokensApplication.php', 'PhabricatorTokensSettingsPanel' => 'applications/settings/panel/PhabricatorTokensSettingsPanel.php', 'PhabricatorTooltipUIExample' => 'applications/uiexample/examples/PhabricatorTooltipUIExample.php', @@ -3128,6 +3162,7 @@ phutil_register_library_map(array( 'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php', 'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php', 'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php', + 'PhabricatorUserPHIDResolver' => 'applications/phid/resolver/PhabricatorUserPHIDResolver.php', 'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php', 'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php', 'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php', @@ -3140,6 +3175,7 @@ phutil_register_library_map(array( 'PhabricatorUserTestCase' => 'applications/people/storage/__tests__/PhabricatorUserTestCase.php', 'PhabricatorUserTitleField' => 'applications/people/customfield/PhabricatorUserTitleField.php', 'PhabricatorUserTransaction' => 'applications/people/storage/PhabricatorUserTransaction.php', + 'PhabricatorUsersEditField' => 'applications/transactions/editfield/PhabricatorUsersEditField.php', 'PhabricatorUsersPolicyRule' => 'applications/policy/rule/PhabricatorUsersPolicyRule.php', 'PhabricatorUsersSearchField' => 'applications/people/searchfield/PhabricatorUsersSearchField.php', 'PhabricatorVCSResponse' => 'applications/repository/response/PhabricatorVCSResponse.php', @@ -3211,6 +3247,7 @@ phutil_register_library_map(array( 'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php', 'PhameBasicTemplateBlogSkin' => 'applications/phame/skins/PhameBasicTemplateBlogSkin.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', + 'PhameBlogController' => 'applications/phame/controller/blog/PhameBlogController.php', 'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php', @@ -3229,6 +3266,7 @@ phutil_register_library_map(array( 'PhameCreatePostConduitAPIMethod' => 'applications/phame/conduit/PhameCreatePostConduitAPIMethod.php', 'PhameDAO' => 'applications/phame/storage/PhameDAO.php', 'PhamePost' => 'applications/phame/storage/PhamePost.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', @@ -3239,6 +3277,7 @@ phutil_register_library_map(array( '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', 'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php', 'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php', 'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php', @@ -3848,6 +3887,7 @@ phutil_register_library_map(array( 'AphrontFormView' => 'AphrontView', 'AphrontGlyphBarView' => 'AphrontBarView', 'AphrontHTMLResponse' => 'AphrontResponse', + 'AphrontHTTPParameterType' => 'Phobject', 'AphrontHTTPProxyResponse' => 'AphrontResponse', 'AphrontHTTPSink' => 'Phobject', 'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase', @@ -3862,10 +3902,13 @@ phutil_register_library_map(array( 'AphrontMultiColumnView' => 'AphrontView', 'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontNullView' => 'AphrontView', + 'AphrontPHIDHTTPParameterType' => 'AphrontHTTPParameterType', + 'AphrontPHIDListHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontPHPHTTPSink' => 'AphrontHTTPSink', 'AphrontPageView' => 'AphrontView', 'AphrontPlainTextResponse' => 'AphrontResponse', 'AphrontProgressBarView' => 'AphrontBarView', + 'AphrontProjectListHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontProxyResponse' => array( 'AphrontResponse', 'AphrontResponseProducerInterface', @@ -3879,15 +3922,19 @@ phutil_register_library_map(array( 'AphrontResponse' => 'Phobject', 'AphrontRoutingMap' => 'Phobject', 'AphrontRoutingResult' => 'Phobject', + 'AphrontSelectHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontSideNavFilterView' => 'AphrontView', 'AphrontSite' => 'Phobject', 'AphrontStackTraceView' => 'AphrontView', 'AphrontStandaloneHTMLResponse' => 'AphrontHTMLResponse', + 'AphrontStringHTTPParameterType' => 'AphrontHTTPParameterType', + 'AphrontStringListHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontTableView' => 'AphrontView', 'AphrontTagView' => 'AphrontView', 'AphrontTokenizerTemplateView' => 'AphrontView', 'AphrontTypeaheadTemplateView' => 'AphrontView', 'AphrontUnhandledExceptionResponse' => 'AphrontStandaloneHTMLResponse', + 'AphrontUserListHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontView' => array( 'Phobject', 'PhutilSafeHTMLProducerInterface', @@ -5308,6 +5355,7 @@ phutil_register_library_map(array( 'PHUI' => 'Phobject', 'PHUIActionPanelExample' => 'PhabricatorUIExample', 'PHUIActionPanelView' => 'AphrontTagView', + 'PHUIApplicationMenuView' => 'Phobject', 'PHUIBadgeBoxView' => 'AphrontTagView', 'PHUIBadgeExample' => 'PhabricatorUIExample', 'PHUIBadgeMiniView' => 'AphrontTagView', @@ -5338,6 +5386,7 @@ phutil_register_library_map(array( 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 'PHUIDocumentExample' => 'PhabricatorUIExample', 'PHUIDocumentView' => 'AphrontTagView', + 'PHUIDocumentViewPro' => 'AphrontTagView', 'PHUIFeedStoryExample' => 'PhabricatorUIExample', 'PHUIFeedStoryView' => 'AphrontView', 'PHUIFormDividerControl' => 'AphrontFormControl', @@ -5441,6 +5490,7 @@ phutil_register_library_map(array( 'PasteCreateMailReceiver' => 'PhabricatorMailReceiver', 'PasteDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PasteDefaultViewCapability' => 'PhabricatorPolicyCapability', + 'PasteEditConduitAPIMethod' => 'PhabricatorApplicationEditEngineAPIMethod', 'PasteEmbedView' => 'AphrontView', 'PasteInfoConduitAPIMethod' => 'PasteConduitAPIMethod', 'PasteMailReceiver' => 'PhabricatorObjectMailReceiver', @@ -5484,6 +5534,9 @@ phutil_register_library_map(array( 'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController', + 'PhabricatorApplicationEditEngine' => 'Phobject', + 'PhabricatorApplicationEditEngineAPIMethod' => 'ConduitAPIMethod', + 'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView', 'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationLaunchView' => 'AphrontTagView', 'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController', @@ -5812,7 +5865,6 @@ phutil_register_library_map(array( 'PhabricatorCommonPasswords' => 'Phobject', 'PhabricatorConduitAPIController' => 'PhabricatorConduitController', 'PhabricatorConduitApplication' => 'PhabricatorApplication', - 'PhabricatorConduitCertificateSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO', 'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', @@ -5866,6 +5918,7 @@ phutil_register_library_map(array( 'PhabricatorConfigEntryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigGroupController' => 'PhabricatorConfigController', + 'PhabricatorConfigHTTPParameterTypesModule' => 'PhabricatorConfigModule', 'PhabricatorConfigHistoryController' => 'PhabricatorConfigController', 'PhabricatorConfigIgnoreController' => 'PhabricatorConfigController', 'PhabricatorConfigIssueListController' => 'PhabricatorConfigController', @@ -6075,6 +6128,7 @@ phutil_register_library_map(array( 'PhabricatorDataCacheSpec' => 'PhabricatorCacheSpec', 'PhabricatorDataNotAttachedException' => 'Exception', 'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck', + 'PhabricatorDatasourceEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorDateTimeSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorDebugController' => 'PhabricatorController', 'PhabricatorDefaultRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', @@ -6102,12 +6156,15 @@ phutil_register_library_map(array( 'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants', 'PhabricatorEdgeConstants' => 'Phobject', 'PhabricatorEdgeCycleException' => 'Exception', + 'PhabricatorEdgeEditType' => 'PhabricatorEditType', 'PhabricatorEdgeEditor' => 'Phobject', 'PhabricatorEdgeGraph' => 'AbstractDirectedGraph', 'PhabricatorEdgeQuery' => 'PhabricatorQuery', 'PhabricatorEdgeTestCase' => 'PhabricatorTestCase', 'PhabricatorEdgeType' => 'Phobject', 'PhabricatorEdgeTypeTestCase' => 'PhabricatorTestCase', + 'PhabricatorEditField' => 'Phobject', + 'PhabricatorEditType' => 'Phobject', 'PhabricatorEditor' => 'Phobject', 'PhabricatorElasticSearchEngine' => 'PhabricatorSearchEngine', 'PhabricatorElasticSearchSetupCheck' => 'PhabricatorSetupCheck', @@ -6285,6 +6342,7 @@ phutil_register_library_map(array( 'PhabricatorGlobalLock' => 'PhutilLock', 'PhabricatorGlobalUploadTargetView' => 'AphrontView', 'PhabricatorGoogleAuthProvider' => 'PhabricatorOAuth2AuthProvider', + 'PhabricatorHTTPParameterTypeTableView' => 'AphrontView', 'PhabricatorHandleList' => array( 'Phobject', 'Iterator', @@ -6611,6 +6669,7 @@ phutil_register_library_map(array( 'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPHID' => 'Phobject', 'PhabricatorPHIDConstants' => 'Phobject', + 'PhabricatorPHIDResolver' => 'Phobject', 'PhabricatorPHIDType' => 'Phobject', 'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase', 'PhabricatorPHPASTApplication' => 'PhabricatorApplication', @@ -6642,6 +6701,7 @@ phutil_register_library_map(array( 'PhabricatorPasteController' => 'PhabricatorController', 'PhabricatorPasteDAO' => 'PhabricatorLiskDAO', 'PhabricatorPasteEditController' => 'PhabricatorPasteController', + 'PhabricatorPasteEditEngine' => 'PhabricatorApplicationEditEngine', 'PhabricatorPasteEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorPasteListController' => 'PhabricatorPasteController', 'PhabricatorPastePastePHIDType' => 'PhabricatorPHIDType', @@ -6712,6 +6772,8 @@ phutil_register_library_map(array( 'PhabricatorPhurlApplication' => 'PhabricatorApplication', 'PhabricatorPhurlController' => 'PhabricatorController', 'PhabricatorPhurlDAO' => 'PhabricatorLiskDAO', + 'PhabricatorPhurlLinkRemarkupRule' => 'PhutilRemarkupRule', + 'PhabricatorPhurlRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorPhurlSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorPhurlURL' => array( 'PhabricatorPhurlDAO', @@ -6725,6 +6787,7 @@ phutil_register_library_map(array( 'PhabricatorFlaggableInterface', 'PhabricatorSpacesInterface', ), + 'PhabricatorPhurlURLAccessController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLEditController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorPhurlURLListController' => 'PhabricatorPhurlController', @@ -6756,6 +6819,7 @@ phutil_register_library_map(array( 'PhabricatorPolicyDAO' => 'PhabricatorLiskDAO', 'PhabricatorPolicyDataTestCase' => 'PhabricatorTestCase', 'PhabricatorPolicyEditController' => 'PhabricatorPolicyController', + 'PhabricatorPolicyEditField' => 'PhabricatorEditField', 'PhabricatorPolicyException' => 'Exception', 'PhabricatorPolicyExplainController' => 'PhabricatorPolicyController', 'PhabricatorPolicyFilter' => 'Phobject', @@ -6845,6 +6909,7 @@ phutil_register_library_map(array( 'PhabricatorProjectObjectHasProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', + 'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', 'PhabricatorProjectProjectHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType', @@ -6870,6 +6935,7 @@ phutil_register_library_map(array( 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectViewController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController', + 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProtocolAdapter' => 'Phobject', 'PhabricatorPygmentSetupCheck' => 'PhabricatorSetupCheck', @@ -7084,6 +7150,7 @@ phutil_register_library_map(array( 'PhabricatorSearchWorker' => 'PhabricatorWorker', 'PhabricatorSecurityConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSecuritySetupCheck' => 'PhabricatorSetupCheck', + 'PhabricatorSelectEditField' => 'PhabricatorEditField', 'PhabricatorSendGridConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSessionsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsAddEmailAction' => 'PhabricatorSystemAction', @@ -7096,6 +7163,7 @@ phutil_register_library_map(array( 'PhabricatorSetupIssue' => 'Phobject', 'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample', 'PhabricatorSetupIssueView' => 'AphrontView', + 'PhabricatorSimpleEditType' => 'PhabricatorEditType', 'PhabricatorSite' => 'AphrontSite', 'PhabricatorSlowvoteApplication' => 'PhabricatorApplication', 'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO', @@ -7134,6 +7202,7 @@ phutil_register_library_map(array( 'PhabricatorSlugTestCase' => 'PhabricatorTestCase', 'PhabricatorSortTableUIExample' => 'PhabricatorUIExample', 'PhabricatorSourceCodeView' => 'AphrontView', + 'PhabricatorSpaceEditField' => 'PhabricatorEditField', 'PhabricatorSpacesApplication' => 'PhabricatorApplication', 'PhabricatorSpacesArchiveController' => 'PhabricatorSpacesController', 'PhabricatorSpacesCapabilityCreateSpaces' => 'PhabricatorPolicyCapability', @@ -7178,7 +7247,10 @@ phutil_register_library_map(array( 'PhabricatorStandardCustomFieldText' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldTokenizer' => 'PhabricatorStandardCustomFieldPHIDs', 'PhabricatorStandardCustomFieldUsers' => 'PhabricatorStandardCustomFieldTokenizer', - 'PhabricatorStandardPageView' => 'PhabricatorBarePageView', + 'PhabricatorStandardPageView' => array( + 'PhabricatorBarePageView', + 'AphrontResponseProducerInterface', + ), 'PhabricatorStandardSelectCustomFieldDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorStatusController' => 'PhabricatorController', 'PhabricatorStatusUIExample' => 'PhabricatorUIExample', @@ -7200,6 +7272,7 @@ phutil_register_library_map(array( 'PhabricatorStorageSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorStreamingProtocolAdapter' => 'PhabricatorProtocolAdapter', 'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType', + 'PhabricatorSubscribersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', 'PhabricatorSubscriptionTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorSubscriptionsAddSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', @@ -7243,6 +7316,8 @@ phutil_register_library_map(array( 'PhabricatorTestNoCycleEdgeType' => 'PhabricatorEdgeType', 'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorTestWorker' => 'PhabricatorWorker', + 'PhabricatorTextAreaEditField' => 'PhabricatorEditField', + 'PhabricatorTextEditField' => 'PhabricatorEditField', 'PhabricatorTime' => 'Phobject', 'PhabricatorTimeGuard' => 'Phobject', 'PhabricatorTimeTestCase' => 'PhabricatorTestCase', @@ -7269,6 +7344,7 @@ phutil_register_library_map(array( 'PhabricatorTokenReceiverQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorTokenTokenPHIDType' => 'PhabricatorPHIDType', 'PhabricatorTokenUIEventListener' => 'PhabricatorEventListener', + 'PhabricatorTokenizerEditField' => 'PhabricatorEditField', 'PhabricatorTokensApplication' => 'PhabricatorApplication', 'PhabricatorTokensSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorTooltipUIExample' => 'PhabricatorUIExample', @@ -7331,6 +7407,7 @@ phutil_register_library_map(array( 'PhabricatorPolicyInterface', ), 'PhabricatorUserLogView' => 'AphrontView', + 'PhabricatorUserPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorUserPreferences' => 'PhabricatorUserDAO', 'PhabricatorUserProfile' => 'PhabricatorUserDAO', 'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor', @@ -7343,6 +7420,7 @@ phutil_register_library_map(array( 'PhabricatorUserTestCase' => 'PhabricatorTestCase', 'PhabricatorUserTitleField' => 'PhabricatorUserCustomField', 'PhabricatorUserTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorUsersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorUsersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorUsersSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorVCSResponse' => 'AphrontResponse', @@ -7432,18 +7510,19 @@ phutil_register_library_map(array( 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', ), - 'PhameBlogDeleteController' => 'PhameController', - 'PhameBlogEditController' => 'PhameController', + 'PhameBlogController' => 'PhameController', + 'PhameBlogDeleteController' => 'PhameBlogController', + 'PhameBlogEditController' => 'PhameBlogController', 'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor', - 'PhameBlogFeedController' => 'PhameController', - 'PhameBlogListController' => 'PhameController', - 'PhameBlogLiveController' => 'PhameController', + 'PhameBlogFeedController' => 'PhameBlogController', + 'PhameBlogListController' => 'PhameBlogController', + 'PhameBlogLiveController' => 'PhameBlogController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhameBlogSite' => 'PhameSite', 'PhameBlogSkin' => 'PhabricatorController', 'PhameBlogTransaction' => 'PhabricatorApplicationTransaction', - 'PhameBlogViewController' => 'PhameController', + 'PhameBlogViewController' => 'PhameBlogController', 'PhameCelerityResources' => 'CelerityResources', 'PhameConduitAPIMethod' => 'ConduitAPIMethod', 'PhameController' => 'PhabricatorController', @@ -7459,22 +7538,24 @@ phutil_register_library_map(array( 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', ), - 'PhamePostDeleteController' => 'PhameController', - 'PhamePostEditController' => 'PhameController', + 'PhamePostController' => 'PhameController', + 'PhamePostDeleteController' => 'PhamePostController', + 'PhamePostEditController' => 'PhamePostController', 'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor', - 'PhamePostFramedController' => 'PhameController', - 'PhamePostListController' => 'PhameController', - 'PhamePostNewController' => 'PhameController', - 'PhamePostNotLiveController' => 'PhameController', - 'PhamePostPreviewController' => 'PhameController', - 'PhamePostPublishController' => 'PhameController', + 'PhamePostFramedController' => 'PhamePostController', + 'PhamePostListController' => 'PhamePostController', + 'PhamePostNewController' => 'PhamePostController', + 'PhamePostNotLiveController' => 'PhamePostController', + 'PhamePostPreviewController' => 'PhamePostController', + 'PhamePostPublishController' => 'PhamePostController', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhamePostTransaction' => 'PhabricatorApplicationTransaction', 'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery', - 'PhamePostUnpublishController' => 'PhameController', + 'PhamePostUnpublishController' => 'PhamePostController', 'PhamePostView' => 'AphrontView', - 'PhamePostViewController' => 'PhameController', + 'PhamePostViewController' => 'PhamePostController', 'PhameQueryConduitAPIMethod' => 'PhameConduitAPIMethod', 'PhameQueryPostsConduitAPIMethod' => 'PhameConduitAPIMethod', 'PhameResourceController' => 'CelerityResourceController', diff --git a/src/aphront/httpparametertype/AphrontHTTPParameterType.php b/src/aphront/httpparametertype/AphrontHTTPParameterType.php new file mode 100644 index 0000000000..995556a6b9 --- /dev/null +++ b/src/aphront/httpparametertype/AphrontHTTPParameterType.php @@ -0,0 +1,309 @@ +viewer = $viewer; + return $this; + } + + + /** + * Get the current viewer. + * + * @return PhabricatorUser Current viewer. + * @task read + */ + final public function getViewer() { + if (!$this->viewer) { + throw new PhutilInvalidStateException('setViewer'); + } + return $this->viewer; + } + + + /** + * Test if a value is present in a request. + * + * @param AphrontRequest The incoming request. + * @param string The key to examine. + * @return bool True if a readable value is present in the request. + * @task read + */ + final public function getExists(AphrontRequest $request, $key) { + return $this->getParameterExists($request, $key); + } + + + /** + * Read a value from a request. + * + * If the value is not present, a default value is returned (usually `null`). + * Use @{method:getExists} to test if a value is present. + * + * @param AphrontRequest The incoming request. + * @param string The key to examine. + * @return wild Value, or default if value is not present. + * @task read + */ + final public function getValue(AphrontRequest $request, $key) { + + if (!$this->getExists($request, $key)) { + return $this->getParameterDefault(); + } + + return $this->getParameterValue($request, $key); + } + + + /** + * Get the default value for this parameter type. + * + * @return wild Default value for this type. + * @task read + */ + final public function getDefaultValue() { + return $this->getParameterDefault(); + } + + +/* -( Information About the Type )----------------------------------------- */ + + + /** + * Get a short name for this type, like `string` or `list`. + * + * @return string Short type name. + * @task info + */ + final public function getTypeName() { + return $this->getParameterTypeName(); + } + + + /** + * Get a list of human-readable descriptions of acceptable formats for this + * type. + * + * For example, a type might return strings like these: + * + * > Any positive integer. + * > A comma-separated list of PHIDs. + * + * This is used to explain to users how to specify a type when generating + * documentation. + * + * @return list Human-readable list of acceptable formats. + * @task info + */ + final public function getFormatDescriptions() { + return $this->getParameterFormatDescriptions(); + } + + + /** + * Get a list of human-readable examples of how to format this type as an + * HTTP GET parameter. + * + * For example, a type might return strings like these: + * + * > v=123 + * > v[]=1&v[]=2 + * + * This is used to show users how to specify parameters of this type in + * generated documentation. + * + * @return list Human-readable list of format examples. + * @task info + */ + final public function getExamples() { + return $this->getParameterExamples(); + } + + +/* -( Utilities )---------------------------------------------------------- */ + + + /** + * Call another type's existence check. + * + * This method allows a type to reuse the exitence behavior of a different + * type. For example, a "list of users" type may have the same basic + * existence check that a simpler "list of strings" type has, and can just + * call the simpler type to reuse its behavior. + * + * @param AphrontHTTPParameterType The other type. + * @param AphrontRequest Incoming request. + * @param string Key to examine. + * @return bool True if the parameter exists. + * @task util + */ + final protected function getExistsWithType( + AphrontHTTPParameterType $type, + AphrontRequest $request, + $key) { + + $type->setViewer($this->getViewer()); + + return $type->getParameterExists($request, $key); + } + + + /** + * Call another type's value parser. + * + * This method allows a type to reuse the parsing behavior of a different + * type. For example, a "list of users" type may start by running the same + * basic parsing that a simpler "list of strings" type does. + * + * @param AphrontHTTPParameterType The other type. + * @param AphrontRequest Incoming request. + * @param string Key to examine. + * @return wild Parsed value. + * @task util + */ + final protected function getValueWithType( + AphrontHTTPParameterType $type, + AphrontRequest $request, + $key) { + + $type->setViewer($this->getViewer()); + + return $type->getValue($request, $key); + } + + + /** + * Get a list of all available parameter types. + * + * @return list List of all available types. + * @task util + */ + final public static function getAllTypes() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getTypeName') + ->setSortMethod('getTypeName') + ->execute(); + } + + +/* -( Implementation )----------------------------------------------------- */ + + + /** + * Test if a parameter exists in a request. + * + * See @{method:getExists}. By default, this method tests if the key is + * present in the request. + * + * To call another type's behavior in order to perform this check, use + * @{method:getExistsWithType}. + * + * @param AphrontRequest The incoming request. + * @param string The key to examine. + * @return bool True if a readable value is present in the request. + * @task impl + */ + protected function getParameterExists(AphrontRequest $request, $key) { + return $request->getExists($key); + } + + + /** + * Parse a value from a request. + * + * See @{method:getValue}. This method will //only// be called if this type + * has already asserted that the value exists with + * @{method:getParameterExists}. + * + * To call another type's behavior in order to parse a value, use + * @{method:getValueWithType}. + * + * @param AphrontRequest The incoming request. + * @param string The key to examine. + * @return wild Parsed value. + * @task impl + */ + abstract protected function getParameterValue(AphrontRequest $request, $key); + + + /** + * Return a simple type name string, like "string" or "list". + * + * See @{method:getTypeName}. + * + * @return string Short type name. + * @task impl + */ + abstract protected function getParameterTypeName(); + + + /** + * Return a human-readable list of format descriptions. + * + * See @{method:getFormatDescriptions}. + * + * @return list Human-readable list of acceptable formats. + * @task impl + */ + abstract protected function getParameterFormatDescriptions(); + + + /** + * Return a human-readable list of examples. + * + * See @{method:getExamples}. + * + * @return list Human-readable list of format examples. + * @task impl + */ + abstract protected function getParameterExamples(); + + + /** + * Return the default value for this parameter type. + * + * See @{method:getDefaultValue}. If unspecified, the default is `null`. + * + * @return wild Default value. + * @task impl + */ + protected function getParameterDefault() { + return null; + } + +} diff --git a/src/aphront/httpparametertype/AphrontPHIDHTTPParameterType.php b/src/aphront/httpparametertype/AphrontPHIDHTTPParameterType.php new file mode 100644 index 0000000000..645510bc98 --- /dev/null +++ b/src/aphront/httpparametertype/AphrontPHIDHTTPParameterType.php @@ -0,0 +1,26 @@ +getStr($key); + } + + protected function getParameterTypeName() { + return 'phid'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('A single object PHID.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=PHID-XXXX-1111', + ); + } + +} diff --git a/src/aphront/httpparametertype/AphrontPHIDListHTTPParameterType.php b/src/aphront/httpparametertype/AphrontPHIDListHTTPParameterType.php new file mode 100644 index 0000000000..e61bfb0f77 --- /dev/null +++ b/src/aphront/httpparametertype/AphrontPHIDListHTTPParameterType.php @@ -0,0 +1,30 @@ +getValueWithType($type, $request, $key); + } + + protected function getParameterTypeName() { + return 'list'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('Comma-separated list of PHIDs.'), + pht('List of PHIDs, as array.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=PHID-XXXX-1111', + 'v=PHID-XXXX-1111,PHID-XXXX-2222', + 'v[]=PHID-XXXX-1111&v[]=PHID-XXXX-2222', + ); + } + +} diff --git a/src/aphront/httpparametertype/AphrontProjectListHTTPParameterType.php b/src/aphront/httpparametertype/AphrontProjectListHTTPParameterType.php new file mode 100644 index 0000000000..fd7e0db5cd --- /dev/null +++ b/src/aphront/httpparametertype/AphrontProjectListHTTPParameterType.php @@ -0,0 +1,42 @@ +getValueWithType($type, $request, $key); + + return id(new PhabricatorProjectPHIDResolver()) + ->setViewer($this->getViewer()) + ->resolvePHIDs($list); + } + + protected function getParameterTypeName() { + return 'list'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('Comma-separated list of project PHIDs.'), + pht('List of project PHIDs, as array.'), + pht('Comma-separated list of project hashtags.'), + pht('List of project hashtags, as array.'), + pht('Mixture of hashtags and PHIDs.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=PHID-PROJ-1111', + 'v=PHID-PROJ-1111,PHID-PROJ-2222', + 'v=hashtag', + 'v=frontend,backend', + 'v[]=PHID-PROJ-1111&v[]=PHID-PROJ-2222', + 'v[]=frontend&v[]=backend', + 'v=PHID-PROJ-1111,frontend', + 'v[]=PHID-PROJ-1111&v[]=backend', + ); + } + +} diff --git a/src/aphront/httpparametertype/AphrontSelectHTTPParameterType.php b/src/aphront/httpparametertype/AphrontSelectHTTPParameterType.php new file mode 100644 index 0000000000..017900666c --- /dev/null +++ b/src/aphront/httpparametertype/AphrontSelectHTTPParameterType.php @@ -0,0 +1,26 @@ +getStr($key); + } + + protected function getParameterTypeName() { + return 'select'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('A single value from the allowed set.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=value', + ); + } + +} diff --git a/src/aphront/httpparametertype/AphrontStringHTTPParameterType.php b/src/aphront/httpparametertype/AphrontStringHTTPParameterType.php new file mode 100644 index 0000000000..ebcc21cb1e --- /dev/null +++ b/src/aphront/httpparametertype/AphrontStringHTTPParameterType.php @@ -0,0 +1,27 @@ +getStr($key); + } + + protected function getParameterTypeName() { + return 'string'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('A URL-encoded string.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=simple', + 'v=properly%20escaped%20text', + ); + } + +} diff --git a/src/aphront/httpparametertype/AphrontStringListHTTPParameterType.php b/src/aphront/httpparametertype/AphrontStringListHTTPParameterType.php new file mode 100644 index 0000000000..5c34dbc248 --- /dev/null +++ b/src/aphront/httpparametertype/AphrontStringListHTTPParameterType.php @@ -0,0 +1,38 @@ +getArr($key, null); + + if ($list === null) { + $list = $request->getStrList($key); + } + + return $list; + } + + protected function getParameterDefault() { + return array(); + } + + protected function getParameterTypeName() { + return 'list'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('Comma-separated list of strings.'), + pht('List of strings, as array.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=cat,dog,pig', + 'v[]=cat&v[]=dog', + ); + } + +} diff --git a/src/aphront/httpparametertype/AphrontUserListHTTPParameterType.php b/src/aphront/httpparametertype/AphrontUserListHTTPParameterType.php new file mode 100644 index 0000000000..3254542115 --- /dev/null +++ b/src/aphront/httpparametertype/AphrontUserListHTTPParameterType.php @@ -0,0 +1,42 @@ +getValueWithType($type, $request, $key); + + return id(new PhabricatorUserPHIDResolver()) + ->setViewer($this->getViewer()) + ->resolvePHIDs($list); + } + + protected function getParameterTypeName() { + return 'list'; + } + + protected function getParameterFormatDescriptions() { + return array( + pht('Comma-separated list of user PHIDs.'), + pht('List of user PHIDs, as array.'), + pht('Comma-separated list of usernames.'), + pht('List of usernames, as array.'), + pht('Mixture of usernames and PHIDs.'), + ); + } + + protected function getParameterExamples() { + return array( + 'v=PHID-USER-1111', + 'v=PHID-USER-1111,PHID-USER-2222', + 'v=username', + 'v=alincoln,htaft', + 'v[]=PHID-USER-1111&v[]=PHID-USER-2222', + 'v[]=htaft&v[]=alincoln', + 'v=PHID-USER-1111,alincoln', + 'v[]=PHID-USER-1111&v[]=htaft', + ); + } + +} diff --git a/src/applications/almanac/phid/AlmanacBindingPHIDType.php b/src/applications/almanac/phid/AlmanacBindingPHIDType.php index d8fcb510fb..db469690cd 100644 --- a/src/applications/almanac/phid/AlmanacBindingPHIDType.php +++ b/src/applications/almanac/phid/AlmanacBindingPHIDType.php @@ -12,6 +12,10 @@ final class AlmanacBindingPHIDType extends PhabricatorPHIDType { return new AlmanacBinding(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAlmanacApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/almanac/phid/AlmanacDevicePHIDType.php b/src/applications/almanac/phid/AlmanacDevicePHIDType.php index 8a1bb36a90..26c88a7a86 100644 --- a/src/applications/almanac/phid/AlmanacDevicePHIDType.php +++ b/src/applications/almanac/phid/AlmanacDevicePHIDType.php @@ -12,6 +12,10 @@ final class AlmanacDevicePHIDType extends PhabricatorPHIDType { return new AlmanacDevice(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAlmanacApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/almanac/phid/AlmanacInterfacePHIDType.php b/src/applications/almanac/phid/AlmanacInterfacePHIDType.php index 67f9b1664a..581e86e3be 100644 --- a/src/applications/almanac/phid/AlmanacInterfacePHIDType.php +++ b/src/applications/almanac/phid/AlmanacInterfacePHIDType.php @@ -12,6 +12,10 @@ final class AlmanacInterfacePHIDType extends PhabricatorPHIDType { return new AlmanacInterface(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAlmanacApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/almanac/phid/AlmanacNetworkPHIDType.php b/src/applications/almanac/phid/AlmanacNetworkPHIDType.php index e27efa5cd8..2264ce0e5f 100644 --- a/src/applications/almanac/phid/AlmanacNetworkPHIDType.php +++ b/src/applications/almanac/phid/AlmanacNetworkPHIDType.php @@ -12,6 +12,10 @@ final class AlmanacNetworkPHIDType extends PhabricatorPHIDType { return new AlmanacNetwork(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAlmanacApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/almanac/phid/AlmanacServicePHIDType.php b/src/applications/almanac/phid/AlmanacServicePHIDType.php index c64e089ce6..a64a229e94 100644 --- a/src/applications/almanac/phid/AlmanacServicePHIDType.php +++ b/src/applications/almanac/phid/AlmanacServicePHIDType.php @@ -12,6 +12,10 @@ final class AlmanacServicePHIDType extends PhabricatorPHIDType { return new AlmanacService(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAlmanacApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/auth/controller/PhabricatorAuthController.php b/src/applications/auth/controller/PhabricatorAuthController.php index db1c8c6da4..76161e6c77 100644 --- a/src/applications/auth/controller/PhabricatorAuthController.php +++ b/src/applications/auth/controller/PhabricatorAuthController.php @@ -2,18 +2,6 @@ abstract class PhabricatorAuthController extends PhabricatorController { - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); - - $page->setApplicationName(pht('Login')); - $page->setBaseURI('/login/'); - $page->setTitle(idx($data, 'title')); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - } - protected function renderErrorPage($title, array $messages) { $view = new PHUIInfoView(); $view->setTitle($title); diff --git a/src/applications/auth/controller/config/PhabricatorAuthListController.php b/src/applications/auth/controller/config/PhabricatorAuthListController.php index 5be803b895..71aac9e185 100644 --- a/src/applications/auth/controller/config/PhabricatorAuthListController.php +++ b/src/applications/auth/controller/config/PhabricatorAuthListController.php @@ -109,7 +109,7 @@ final class PhabricatorAuthListController 'only users with a verified email address at one of these %s '. 'allowed domain(s) will be able to register an account: %s', $domains_link, - new PhutilNumber(count($domains_value)), + phutil_count($domains_value), phutil_tag('strong', array(), implode(', ', $domains_value))); } else { $issues[] = pht( diff --git a/src/applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php b/src/applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php index 23c0a109cb..fb82d55439 100644 --- a/src/applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php +++ b/src/applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php @@ -78,7 +78,7 @@ final class PhabricatorAuthManagementRefreshWorkflow "%s\n", pht( 'Found %s account(s) to refresh.', - new PhutilNumber(count($accounts)))); + phutil_count($accounts))); } $providers = PhabricatorAuthProvider::getAllEnabledProviders(); diff --git a/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php b/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php index ca21397fb6..2819c84572 100644 --- a/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php +++ b/src/applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorAuthAuthFactorPHIDType extends PhabricatorPHIDType { return new PhabricatorAuthFactorConfig(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAuthApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php b/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php index b271183f5c..e91b66e647 100644 --- a/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php +++ b/src/applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorAuthAuthProviderPHIDType extends PhabricatorPHIDType { return new PhabricatorAuthProviderConfig(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAuthApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php b/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php index 0f1b205763..b633e10eab 100644 --- a/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php +++ b/src/applications/auth/phid/PhabricatorAuthInvitePHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorAuthInvitePHIDType extends PhabricatorPHIDType { return new PhabricatorAuthInvite(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorAuthApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index f499bea5c9..080062a2d9 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -635,4 +635,8 @@ abstract class PhabricatorApplication return array(); } + protected function getEditRoutePattern($base) { + return $base.'(?:(?P[0-9]\d*)/)?(?:(?Pparameters)/)?'; + } + } diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php index 9dcfa62fa2..e10b4b2802 100644 --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -3,7 +3,6 @@ abstract class PhabricatorController extends AphrontController { private $handles; - private $extraQuicksandConfig = array(); public function shouldRequireLogin() { return true; @@ -62,15 +61,6 @@ abstract class PhabricatorController extends AphrontController { return false; } - public function addExtraQuicksandConfig($config) { - $this->extraQuicksandConfig += $config; - return $this; - } - - private function getExtraQuicksandConfig() { - return $this->extraQuicksandConfig; - } - public function willBeginExecution() { $request = $this->getRequest(); @@ -285,32 +275,6 @@ abstract class PhabricatorController extends AphrontController { } } - public function buildStandardPageView() { - $view = new PhabricatorStandardPageView(); - $view->setRequest($this->getRequest()); - $view->setController($this); - return $view; - } - - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); - $page->appendChild($view); - return $this->buildPageResponse($page); - } - - private function buildPageResponse($page) { - if ($this->getRequest()->isQuicksand()) { - $response = id(new AphrontAjaxResponse()) - ->setContent($page->renderForQuicksand( - $this->getExtraQuicksandConfig())); - } else { - $response = id(new AphrontWebpageResponse()) - ->setContent($page->render()); - } - - return $response; - } - public function getApplicationURI($path = '') { if (!$this->getCurrentApplication()) { throw new Exception(pht('No application!')); @@ -318,58 +282,6 @@ abstract class PhabricatorController extends AphrontController { return $this->getCurrentApplication()->getApplicationURI($path); } - public function buildApplicationPage($view, array $options) { - $page = $this->buildStandardPageView(); - - $title = PhabricatorEnv::getEnvConfig('phabricator.serious-business') ? - 'Phabricator' : - pht('Bacon Ice Cream for Breakfast'); - - $application = $this->getCurrentApplication(); - $page->setTitle(idx($options, 'title', $title)); - if ($application) { - $page->setApplicationName($application->getName()); - if ($application->getTitleGlyph()) { - $page->setGlyph($application->getTitleGlyph()); - } - } - - if (!($view instanceof AphrontSideNavFilterView)) { - $nav = new AphrontSideNavFilterView(); - $nav->appendChild($view); - $view = $nav; - } - - $user = $this->getRequest()->getUser(); - $view->setUser($user); - - $page->appendChild($view); - - $object_phids = idx($options, 'pageObjects', array()); - if ($object_phids) { - $page->appendPageObjects($object_phids); - foreach ($object_phids as $object_phid) { - PhabricatorFeedStoryNotification::updateObjectNotificationViews( - $user, - $object_phid); - } - } - - if (idx($options, 'device', true)) { - $page->setDeviceReady(true); - } - - $page->setShowFooter(idx($options, 'showFooter', true)); - $page->setShowChrome(idx($options, 'chrome', true)); - - $application_menu = $this->buildApplicationMenu(); - if ($application_menu) { - $page->setApplicationMenu($application_menu); - } - - return $this->buildPageResponse($page); - } - public function willSendResponse(AphrontResponse $response) { $request = $this->getRequest(); @@ -532,6 +444,36 @@ abstract class PhabricatorController extends AphrontController { ->setSubmitURI($submit_uri); } + public function newPage() { + $page = id(new PhabricatorStandardPageView()) + ->setRequest($this->getRequest()) + ->setController($this) + ->setDeviceReady(true); + + $application = $this->getCurrentApplication(); + if ($application) { + $page->setApplicationName($application->getName()); + if ($application->getTitleGlyph()) { + $page->setGlyph($application->getTitleGlyph()); + } + } + + $viewer = $this->getRequest()->getUser(); + if ($viewer) { + $page->setUser($viewer); + } + + // TODO: Remove after removing callsites to addExtraQuicksandConfig(). + $page->addQuicksandConfig($this->extraQuicksandConfig); + + return $page; + } + + public function newApplicationMenu() { + return id(new PHUIApplicationMenuView()) + ->setViewer($this->getRequest()->getUser()); + } + protected function buildTransactionTimeline( PhabricatorApplicationTransactionInterface $object, PhabricatorApplicationTransactionQuery $query, @@ -579,4 +521,89 @@ abstract class PhabricatorController extends AphrontController { return $timeline; } + + public function buildApplicationCrumbsForEditEngine() { + // TODO: This is kind of gross, I'm bascially just making this public so + // I can use it in EditEngine. We could do this without making it public + // by using controller delegation, or make it properly public. + return $this->buildApplicationCrumbs(); + } + + +/* -( Deprecated )--------------------------------------------------------- */ + + + /** + * DEPRECATED. + */ + private $extraQuicksandConfig = array(); + + + /** + * DEPRECATED. Use @{method:newPage} and call addQuicksandConfig(). + */ + public function addExtraQuicksandConfig($config) { + // TODO: When this method is removed, + $this->extraQuicksandConfig += $config; + return $this; + } + + + /** + * DEPRECATED. Use @{method:newPage}. + */ + public function buildStandardPageView() { + return $this->newPage(); + } + + + /** + * DEPRECATED. Use @{method:newPage}. + */ + public function buildStandardPageResponse($view, array $data) { + $page = $this->buildStandardPageView(); + $page->appendChild($view); + return $page->produceAphrontResponse(); + } + + + /** + * DEPRECATED. Use @{method:newPage}. + */ + public function buildApplicationPage($view, array $options) { + $page = $this->newPage(); + + $title = PhabricatorEnv::getEnvConfig('phabricator.serious-business') ? + 'Phabricator' : + pht('Bacon Ice Cream for Breakfast'); + + $page->setTitle(idx($options, 'title', $title)); + + if (idx($options, 'class')) { + $page->addClass($options['class']); + } + + if (!($view instanceof AphrontSideNavFilterView)) { + $nav = new AphrontSideNavFilterView(); + $nav->appendChild($view); + $view = $nav; + } + + $page->appendChild($view); + + $object_phids = idx($options, 'pageObjects', array()); + if ($object_phids) { + $page->setPageObjectPHIDs($object_phids); + } + + if (!idx($options, 'device', true)) { + $page->setDeviceReady(false); + } + + $page->setShowFooter(idx($options, 'showFooter', true)); + $page->setShowChrome(idx($options, 'chrome', true)); + + return $page->produceAphrontResponse(); + } + } diff --git a/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php b/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php index 7acc968f21..d37be2ef32 100644 --- a/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php +++ b/src/applications/calendar/phid/PhabricatorCalendarEventPHIDType.php @@ -8,14 +8,14 @@ final class PhabricatorCalendarEventPHIDType extends PhabricatorPHIDType { return pht('Event'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorCalendarApplication'; - } - public function newObject() { return new PhabricatorCalendarEvent(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorCalendarApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/celerity/management/CelerityManagementMapWorkflow.php b/src/applications/celerity/management/CelerityManagementMapWorkflow.php index 525a079f53..e838de58f4 100644 --- a/src/applications/celerity/management/CelerityManagementMapWorkflow.php +++ b/src/applications/celerity/management/CelerityManagementMapWorkflow.php @@ -18,7 +18,7 @@ final class CelerityManagementMapWorkflow $this->log( pht( 'Rebuilding %d resource source(s).', - new PhutilNumber(count($resources_map)))); + phutil_count($resources_map))); foreach ($resources_map as $name => $resources) { $this->rebuildResources($resources); diff --git a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php index 368d6406f3..7c230d9869 100644 --- a/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php +++ b/src/applications/celerity/postprocessor/CelerityDefaultPostprocessor.php @@ -172,11 +172,11 @@ final class CelerityDefaultPostprocessor 'sh-pinkbackground' => '#fbeaf8', // Shade Grey - 'sh-lightgreyborder' => '#d8d8d8', + 'sh-lightgreyborder' => '#e3e4e8', 'sh-greyborder' => '#b2b2b2', 'sh-greyicon' => '#757575', 'sh-greytext' => '#555555', - 'sh-greybackground' => '#e7e7e7', + 'sh-greybackground' => '#edeef2', // Shade Disabled 'sh-lightdisabledborder' => '#e5e5e5', diff --git a/src/applications/config/check/PhabricatorDaemonsSetupCheck.php b/src/applications/config/check/PhabricatorDaemonsSetupCheck.php index 3b4b335134..a89590cc18 100644 --- a/src/applications/config/check/PhabricatorDaemonsSetupCheck.php +++ b/src/applications/config/check/PhabricatorDaemonsSetupCheck.php @@ -115,7 +115,7 @@ final class PhabricatorDaemonsSetupCheck extends PhabricatorSetupCheck { $list_section = array( pht( 'The configurations differ in the following %s way(s):', - new PhutilNumber(count($issues))), + phutil_count($issues)), phutil_tag( 'ul', array(), diff --git a/src/applications/config/check/PhabricatorPathSetupCheck.php b/src/applications/config/check/PhabricatorPathSetupCheck.php index 618c81abb9..9f5502e215 100644 --- a/src/applications/config/check/PhabricatorPathSetupCheck.php +++ b/src/applications/config/check/PhabricatorPathSetupCheck.php @@ -111,7 +111,7 @@ final class PhabricatorPathSetupCheck extends PhabricatorSetupCheck { $this ->newIssue('config.PATH.'.$digest) - ->setName(pht('$PATH Component Unusable')) + ->setName(pht('%s Component Unusable', '$PATH')) ->setSummary( pht( 'A component of the configured PATH can not be used by '. diff --git a/src/applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php b/src/applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php new file mode 100644 index 0000000000..66a44c8c83 --- /dev/null +++ b/src/applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php @@ -0,0 +1,27 @@ +getViewer(); + + $types = AphrontHTTPParameterType::getAllTypes(); + + $table = id(new PhabricatorHTTPParameterTypeTableView()) + ->setHTTPParameterTypes($types); + + return id(new PHUIObjectBoxView()) + ->setHeaderText(pht('HTTP Parameter Types')) + ->setTable($table); + } + +} diff --git a/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php b/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php index 161b1e42f4..95c543427f 100644 --- a/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php +++ b/src/applications/config/phid/PhabricatorConfigConfigPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorConfigConfigPHIDType extends PhabricatorPHIDType { return new PhabricatorConfigEntry(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorConfigApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/config/view/PhabricatorHTTPParameterTypeTableView.php b/src/applications/config/view/PhabricatorHTTPParameterTypeTableView.php new file mode 100644 index 0000000000..25e944a9fd --- /dev/null +++ b/src/applications/config/view/PhabricatorHTTPParameterTypeTableView.php @@ -0,0 +1,56 @@ +types = $types; + return $this; + } + + public function getHTTPParameterTypes() { + return $this->types; + } + + public function render() { + $types = $this->getHTTPParameterTypes(); + $types = mpull($types, null, 'getTypeName'); + + $br = phutil_tag('br'); + + $rows = array(); + foreach ($types as $name => $type) { + $formats = $type->getFormatDescriptions(); + $formats = phutil_implode_html($br, $formats); + + $examples = $type->getExamples(); + $examples = phutil_implode_html($br, $examples); + + $rows[] = array( + $name, + $formats, + $examples, + ); + } + + $table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + pht('Type'), + pht('Formats'), + pht('Examples'), + )) + ->setColumnClasses( + array( + 'pri top', + 'top', + 'wide top prewrap', + )); + + return $table; + } + +} diff --git a/src/applications/config/view/PhabricatorSetupIssueView.php b/src/applications/config/view/PhabricatorSetupIssueView.php index 7ece4f865c..cb8859bb86 100644 --- a/src/applications/config/view/PhabricatorSetupIssueView.php +++ b/src/applications/config/view/PhabricatorSetupIssueView.php @@ -387,7 +387,7 @@ final class PhabricatorSetupIssueView extends AphrontView { array(), pht( 'PHP also loaded these %s configuration file(s):', - new PhutilNumber(count($more_loc)))); + phutil_count($more_loc))); $info[] = phutil_tag( 'pre', array(), diff --git a/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php b/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php index c7ea1405cd..d5f3267a06 100644 --- a/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php +++ b/src/applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php @@ -29,14 +29,13 @@ final class ConpherenceUpdateThreadConduitAPIMethod protected function defineErrorTypes() { return array( 'ERR_USAGE_NO_ROOM_ID' => pht( - 'You must specify a room id or room phid to query transactions '. - 'from.'), + 'You must specify a room ID or room PHID to query transactions from.'), 'ERR_USAGE_ROOM_NOT_FOUND' => pht( - 'room does not exist or logged in user can not see it.'), + 'Room does not exist or logged in user can not see it.'), 'ERR_USAGE_ONLY_SELF_REMOVE' => pht( 'Only a user can remove themselves from a room.'), 'ERR_USAGE_NO_UPDATES' => pht( - 'You must specify data that actually updates the conpherence.'), + 'You must specify data that actually updates the Conpherence.'), ); } diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php index 6012c81437..1ab0923fc4 100644 --- a/src/applications/conpherence/controller/ConpherenceUpdateController.php +++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php @@ -325,8 +325,7 @@ final class ConpherenceUpdateController $remove_person = $request->getStr('remove_person'); $participants = $conpherence->getParticipants(); - $message = pht( - 'Are you sure you want to leave this room?'); + $message = pht('Are you sure you want to leave this room?'); $test_conpherence = clone $conpherence; $test_conpherence->attachParticipants(array()); if (!PhabricatorPolicyFilter::hasCapability( @@ -334,17 +333,14 @@ final class ConpherenceUpdateController $test_conpherence, PhabricatorPolicyCapability::CAN_VIEW)) { if (count($participants) == 1) { - $message .= pht( - ' The room will be inaccessible forever and ever.'); + $message .= ' '.pht('The room will be inaccessible forever and ever.'); } else { - $message .= pht( - ' Someone else in the room can add you back later.'); + $message .= ' '.pht('Someone else in the room can add you back later.'); } } $body = phutil_tag( 'p', - array( - ), + array(), $message); require_celerity_resource('conpherence-update-css'); diff --git a/src/applications/conpherence/storage/ConpherenceTransaction.php b/src/applications/conpherence/storage/ConpherenceTransaction.php index ba49cdf9b4..062b9e4a9f 100644 --- a/src/applications/conpherence/storage/ConpherenceTransaction.php +++ b/src/applications/conpherence/storage/ConpherenceTransaction.php @@ -77,14 +77,14 @@ final class ConpherenceTransaction extends PhabricatorApplicationTransaction { count($rem)); } else if ($add) { $title = pht( - '%s added %d files(s).', + '%s added %s files(s).', $this->renderHandleLink($author_phid), - count($add)); + phutil_count($add)); } else { $title = pht( - '%s removed %d file(s).', + '%s removed %s file(s).', $this->renderHandleLink($author_phid), - count($rem)); + phutil_count($rem)); } return $title; break; diff --git a/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php b/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php index 852c5889ed..573d89c843 100644 --- a/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php +++ b/src/applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorCountdownCountdownPHIDType extends PhabricatorPHIDType { return new PhabricatorCountdown(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorCountdownApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php index 1cfa2499b2..a2beba3cd2 100644 --- a/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php @@ -226,7 +226,9 @@ abstract class PhabricatorDaemonManagementWorkflow // Retry without sudo $console->writeOut( "%s\n", - pht('sudo command failed. Starting daemon as current user.')); + pht( + '%s command failed. Starting daemon as current user.', + 'sudo')); $this->executeDaemonLaunchCommand( $command, $daemon_script_dir, @@ -265,8 +267,9 @@ abstract class PhabricatorDaemonManagementWorkflow if (preg_match('/sudo: a password is required/', $stderr)) { throw new Exception( pht( - 'sudo exited with a zero exit code, but emitted output '. - 'consistent with failure under OSX.')); + '%s exited with a zero exit code, but emitted output '. + 'consistent with failure under OSX.', + 'sudo')); } } } diff --git a/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php b/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php index e097dc161d..1450e2aa68 100644 --- a/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php +++ b/src/applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorDashboardDashboardPHIDType extends PhabricatorPHIDType { return new PhabricatorDashboard(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDashboardApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php b/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php index c4aec82b8e..49a5091412 100644 --- a/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php +++ b/src/applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorDashboardPanelPHIDType extends PhabricatorPHIDType { return new PhabricatorDashboardPanel(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDashboardApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/differential/customfield/DifferentialJIRAIssuesField.php b/src/applications/differential/customfield/DifferentialJIRAIssuesField.php index 046539d0da..e40e34f4ad 100644 --- a/src/applications/differential/customfield/DifferentialJIRAIssuesField.php +++ b/src/applications/differential/customfield/DifferentialJIRAIssuesField.php @@ -218,21 +218,21 @@ final class DifferentialJIRAIssuesField return pht( '%s updated JIRA issue(s): added %d %s; removed %d %s.', $xaction->renderHandleLink($author_phid), - new PhutilNumber(count($add)), + phutil_count($add), implode(', ', $add), - new PhutilNumber(count($rem)), + phutil_count($rem), implode(', ', $rem)); } else if ($add) { return pht( '%s added %d JIRA issue(s): %s.', $xaction->renderHandleLink($author_phid), - new PhutilNumber(count($add)), + phutil_count($add), implode(', ', $add)); } else if ($rem) { return pht( '%s removed %d JIRA issue(s): %s.', $xaction->renderHandleLink($author_phid), - new PhutilNumber(count($rem)), + phutil_count($rem), implode(', ', $rem)); } diff --git a/src/applications/differential/customfield/DifferentialUnitField.php b/src/applications/differential/customfield/DifferentialUnitField.php index 3883baba86..17973be7a6 100644 --- a/src/applications/differential/customfield/DifferentialUnitField.php +++ b/src/applications/differential/customfield/DifferentialUnitField.php @@ -125,7 +125,7 @@ final class DifferentialUnitField )) + $groups; foreach ($groups as $result => $group) { - $count = new PhutilNumber(count($group)); + $count = phutil_count($group); switch ($result) { case ArcanistUnitTestResult::RESULT_PASS: $note[] = pht('%s Passed Test(s)', $count); diff --git a/src/applications/differential/herald/DifferentialReviewersHeraldAction.php b/src/applications/differential/herald/DifferentialReviewersHeraldAction.php index c568537f7c..5293af4311 100644 --- a/src/applications/differential/herald/DifferentialReviewersHeraldAction.php +++ b/src/applications/differential/herald/DifferentialReviewersHeraldAction.php @@ -135,12 +135,12 @@ abstract class DifferentialReviewersHeraldAction case self::DO_ADD_REVIEWERS: return pht( 'Added %s reviewer(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_ADD_BLOCKING_REVIEWERS: return pht( 'Added %s blocking reviewer(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } diff --git a/src/applications/differential/mail/DifferentialCreateMailReceiver.php b/src/applications/differential/mail/DifferentialCreateMailReceiver.php index c3198d3642..f5d9dc59f7 100644 --- a/src/applications/differential/mail/DifferentialCreateMailReceiver.php +++ b/src/applications/differential/mail/DifferentialCreateMailReceiver.php @@ -81,14 +81,14 @@ final class DifferentialCreateMailReceiver extends PhabricatorMailReceiver { } else { $subject = pht( 'Diff creation failed; see body for %s error(s).', - new PhutilNumber(count($errors))); + phutil_count($errors)); } $body = new PhabricatorMetaMTAMailBody(); $body->addRawSection($subject); if (count($diffs)) { $text_body = ''; $html_body = array(); - $body_label = pht('%s DIFF LINK(S)', new PhutilNumber(count($diffs))); + $body_label = pht('%s DIFF LINK(S)', phutil_count($diffs)); foreach ($diffs as $filename => $diff_uri) { $text_body .= $filename.': '.$diff_uri."\n"; $html_body[] = phutil_tag( @@ -105,7 +105,7 @@ final class DifferentialCreateMailReceiver extends PhabricatorMailReceiver { if (count($errors)) { $body_section = new PhabricatorMetaMTAMailSection(); - $body_label = pht('%s ERROR(S)', new PhutilNumber(count($errors))); + $body_label = pht('%s ERROR(S)', phutil_count($errors)); foreach ($errors as $error) { $body_section->addFragment($error); } diff --git a/src/applications/differential/phid/DifferentialDiffPHIDType.php b/src/applications/differential/phid/DifferentialDiffPHIDType.php index 887397d57f..746da368c7 100644 --- a/src/applications/differential/phid/DifferentialDiffPHIDType.php +++ b/src/applications/differential/phid/DifferentialDiffPHIDType.php @@ -12,6 +12,10 @@ final class DifferentialDiffPHIDType extends PhabricatorPHIDType { return new DifferentialDiff(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDifferentialApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/differential/phid/DifferentialRevisionPHIDType.php b/src/applications/differential/phid/DifferentialRevisionPHIDType.php index a46dc71c65..b22c8b05cb 100644 --- a/src/applications/differential/phid/DifferentialRevisionPHIDType.php +++ b/src/applications/differential/phid/DifferentialRevisionPHIDType.php @@ -8,14 +8,14 @@ final class DifferentialRevisionPHIDType extends PhabricatorPHIDType { return pht('Differential Revision'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorDifferentialApplication'; - } - public function newObject() { return new DifferentialRevision(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDifferentialApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php b/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php index 32830cb673..a7dbdde682 100644 --- a/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php +++ b/src/applications/diffusion/herald/DiffusionAuditorsHeraldAction.php @@ -68,7 +68,7 @@ abstract class DiffusionAuditorsHeraldAction case self::DO_ADD_AUDITORS: return pht( 'Added %s auditor(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } diff --git a/src/applications/diviner/atomizer/DivinerPHPAtomizer.php b/src/applications/diviner/atomizer/DivinerPHPAtomizer.php index c22cb4bcc3..36616897f2 100644 --- a/src/applications/diviner/atomizer/DivinerPHPAtomizer.php +++ b/src/applications/diviner/atomizer/DivinerPHPAtomizer.php @@ -152,8 +152,8 @@ final class DivinerPHPAtomizer extends DivinerAtomizer { $atom->addWarning( pht( 'This call takes %s parameter(s), but only %s are documented.', - new PhutilNumber(count($params)), - new PhutilNumber(count($docs)))); + phutil_count($params), + phutil_count($docs))); } } diff --git a/src/applications/diviner/controller/DivinerAtomController.php b/src/applications/diviner/controller/DivinerAtomController.php index ecde1218f3..05bb80c16a 100644 --- a/src/applications/diviner/controller/DivinerAtomController.php +++ b/src/applications/diviner/controller/DivinerAtomController.php @@ -58,13 +58,7 @@ final class DivinerAtomController extends DivinerController { $crumbs->addTextCrumb($atom_short_title); $header = id(new PHUIHeaderView()) - ->setHeader($this->renderFullSignature($symbol)) - ->addTag( - id(new PHUITagView()) - ->setType(PHUITagView::TYPE_STATE) - ->setBackgroundColor(PHUITagView::COLOR_BLUE) - ->setName(DivinerAtom::getAtomTypeNameString( - $atom ? $atom->getType() : $symbol->getType()))); + ->setHeader($this->renderFullSignature($symbol)); $properties = new PHUIPropertyListView(); @@ -78,11 +72,11 @@ final class DivinerAtomController extends DivinerController { $prop_list = new PHUIPropertyGroupView(); $prop_list->addPropertyList($properties); - $document = id(new PHUIDocumentView()) + $document = id(new PHUIDocumentViewPro()) ->setBook($book->getTitle(), $group_name) ->setHeader($header) ->addClass('diviner-view') - ->appendChild($prop_list); + ->setPropertyList($prop_list); if ($atom) { $this->buildDefined($properties, $symbol); @@ -163,10 +157,6 @@ final class DivinerAtomController extends DivinerController { ->setHeader($spec['title'])); $task_methods = idx($methods_by_task, $spec['name'], array()); - $inner_box = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_LARGE_LEFT) - ->addPadding(PHUI::PADDING_LARGE_RIGHT) - ->addPadding(PHUI::PADDING_LARGE_BOTTOM); $box_content = array(); if ($task_methods) { @@ -198,7 +188,7 @@ final class DivinerAtomController extends DivinerController { $box_content = phutil_tag('em', array(), $no_methods); } - $inner_box->appendChild($box_content); + $inner_box = phutil_tag_div('diviner-task-items', $box_content); $section->addContent($inner_box); } $document->appendChild($section); @@ -246,7 +236,7 @@ final class DivinerAtomController extends DivinerController { ->setHref('#'.$key)); } - $document->setSideNav($side, PHUIDocumentView::NAV_TOP); + $document->setToc($side); } return $this->buildApplicationPage( @@ -256,6 +246,7 @@ final class DivinerAtomController extends DivinerController { ), array( 'title' => $symbol->getTitle(), + 'class' => 'pro-white-background', )); } @@ -629,7 +620,7 @@ final class DivinerAtomController extends DivinerController { $content = phutil_tag( 'div', array( - 'class' => 'phabricator-remarkup', + 'class' => 'phabricator-remarkup diviner-remarkup-section', ), $content); } else { @@ -668,8 +659,6 @@ final class DivinerAtomController extends DivinerController { if (($impl !== $parent) || $out) { $where = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_MEDIUM_LEFT) - ->addPadding(PHUI::PADDING_MEDIUM_RIGHT) ->addClass('diviner-method-implementation-header') ->appendChild($impl->getName()); $doc = array($where, $doc); diff --git a/src/applications/diviner/controller/DivinerBookController.php b/src/applications/diviner/controller/DivinerBookController.php index ae4b81aa01..2731823588 100644 --- a/src/applications/diviner/controller/DivinerBookController.php +++ b/src/applications/diviner/controller/DivinerBookController.php @@ -53,7 +53,7 @@ final class DivinerBookController extends DivinerController { ->setName($book->getRepository()->getMonogram())); } - $document = new PHUIDocumentView(); + $document = new PHUIDocumentViewPro(); $document->setHeader($header); $document->addClass('diviner-view'); @@ -111,6 +111,7 @@ final class DivinerBookController extends DivinerController { ), array( 'title' => $book->getTitle(), + 'class' => 'pro-white-background', )); } diff --git a/src/applications/diviner/controller/DivinerMainController.php b/src/applications/diviner/controller/DivinerMainController.php index b2233463c0..a68d900d8a 100644 --- a/src/applications/diviner/controller/DivinerMainController.php +++ b/src/applications/diviner/controller/DivinerMainController.php @@ -30,7 +30,7 @@ final class DivinerMainController extends DivinerController { ->setHeader(pht('Documentation Books')) ->addActionLink($query_button); - $document = new PHUIDocumentView(); + $document = new PHUIDocumentViewPro(); $document->setHeader($header); $document->addClass('diviner-view'); @@ -45,10 +45,7 @@ final class DivinerMainController extends DivinerController { $list[] = $item; } $list = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_LARGE_LEFT) - ->addPadding(PHUI::PADDING_LARGE_RIGHT) - ->addPadding(PHUI::PADDING_SMALL_TOP) - ->addPadding(PHUI::PADDING_SMALL_BOTTOM) + ->addPadding(PHUI::PADDING_MEDIUM_TOP) ->appendChild($list); $document->appendChild($list); @@ -82,7 +79,7 @@ final class DivinerMainController extends DivinerController { ), array( 'title' => pht('Documentation Books'), - 'fonts' => true, + 'class' => 'pro-white-background', )); } } diff --git a/src/applications/diviner/publisher/DivinerPublisher.php b/src/applications/diviner/publisher/DivinerPublisher.php index 401a1a331f..e5dcf695db 100644 --- a/src/applications/diviner/publisher/DivinerPublisher.php +++ b/src/applications/diviner/publisher/DivinerPublisher.php @@ -140,14 +140,14 @@ abstract class DivinerPublisher extends Phobject { "%s\n", pht( 'Deleting %s document(s).', - new PhutilNumber(count($deleted)))); + phutil_count($deleted))); $this->deleteDocumentsByHash($deleted); $console->writeOut( "%s\n", pht( 'Creating %s document(s).', - new PhutilNumber(count($created)))); + phutil_count($created))); $this->createDocumentsByHash($created); } diff --git a/src/applications/diviner/view/DivinerSectionView.php b/src/applications/diviner/view/DivinerSectionView.php index f12fb01fab..cc02d9d8b8 100644 --- a/src/applications/diviner/view/DivinerSectionView.php +++ b/src/applications/diviner/view/DivinerSectionView.php @@ -30,12 +30,10 @@ final class DivinerSectionView extends AphrontTagView { $header = id(new PHUIHeaderView()) ->setBleedHeader(true) + ->addClass('diviner-section-header') ->setHeader($this->header); - $content = id(new PHUIBoxView()) - ->addPadding(PHUI::PADDING_LARGE_LEFT) - ->addPadding(PHUI::PADDING_LARGE_RIGHT) - ->appendChild($this->content); + $content = phutil_tag_div('diviner-section-content', $this->content); return array($header, $content); } diff --git a/src/applications/diviner/workflow/DivinerGenerateWorkflow.php b/src/applications/diviner/workflow/DivinerGenerateWorkflow.php index d448de69c0..ad671bbbea 100644 --- a/src/applications/diviner/workflow/DivinerGenerateWorkflow.php +++ b/src/applications/diviner/workflow/DivinerGenerateWorkflow.php @@ -69,7 +69,7 @@ final class DivinerGenerateWorkflow extends DivinerWorkflow { '.book', '--book ')); } else { - $this->log(pht('Found %s book(s).', new PhutilNumber(count($books)))); + $this->log(pht('Found %s book(s).', phutil_count($books))); } } @@ -224,26 +224,26 @@ final class DivinerGenerateWorkflow extends DivinerWorkflow { $this->log( pht( 'Found %s file(s) in project.', - new PhutilNumber(count($file_hashes)))); + phutil_count($file_hashes))); $this->deleteDeadAtoms($file_hashes); $atomize = $this->getFilesToAtomize($file_hashes); $this->log( pht( 'Found %s unatomized, uncached file(s).', - new PhutilNumber(count($atomize)))); + phutil_count($atomize))); $file_atomizers = $this->getAtomizersForFiles($atomize); $this->log( pht( 'Found %s file(s) to atomize.', - new PhutilNumber(count($file_atomizers)))); + phutil_count($file_atomizers))); $futures = $this->buildAtomizerFutures($file_atomizers); $this->log( pht( 'Atomizing %s file(s).', - new PhutilNumber(count($file_atomizers)))); + phutil_count($file_atomizers))); if ($futures) { $this->resolveAtomizerFutures($futures, $file_hashes); @@ -452,7 +452,7 @@ final class DivinerGenerateWorkflow extends DivinerWorkflow { $this->log( pht( 'Found %s obsolete atom(s) in graph.', - new PhutilNumber(count($del_atoms)))); + phutil_count($del_atoms))); foreach ($del_atoms as $nhash => $shash) { $atom_cache->deleteSymbol($nhash); @@ -466,7 +466,7 @@ final class DivinerGenerateWorkflow extends DivinerWorkflow { $this->log( pht( 'Found %s new atom(s) in graph.', - new PhutilNumber(count($new_atoms)))); + phutil_count($new_atoms))); foreach ($new_atoms as $nhash => $ignored) { $shash = $this->computeSymbolHash($nhash); @@ -505,7 +505,7 @@ final class DivinerGenerateWorkflow extends DivinerWorkflow { $this->log( pht( 'Found %s affected atoms.', - new PhutilNumber(count($dirty_nhashes)))); + phutil_count($dirty_nhashes))); foreach ($dirty_nhashes as $nhash => $ignored) { $atom_cache->addGraph($nhash, $this->computeGraphHash($nhash)); diff --git a/src/applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php b/src/applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php index f0cdb5a819..e7f2ef85de 100644 --- a/src/applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php +++ b/src/applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php @@ -96,8 +96,11 @@ final class PhabricatorAsanaConfigOptions } $out = array(); - $out[] = pht('| Workspace ID | Workspace Name |'); - $out[] = '| ------------ | -------------- |'; + $out[] = sprintf( + '| %s | %s |', + pht('Workspace ID'), + pht('Workspace Name')); + $out[] = '| ------------ | -------------- |'; foreach ($workspaces as $workspace) { $out[] = sprintf('| `%s` | `%s` |', $workspace['id'], $workspace['name']); } diff --git a/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php b/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php index e518149945..058ccff6a9 100644 --- a/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php +++ b/src/applications/drydock/phid/DrydockAuthorizationPHIDType.php @@ -12,6 +12,10 @@ final class DrydockAuthorizationPHIDType extends PhabricatorPHIDType { return new DrydockAuthorization(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDrydockApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/drydock/phid/DrydockBlueprintPHIDType.php b/src/applications/drydock/phid/DrydockBlueprintPHIDType.php index e63f1294a7..ef286cf5f1 100644 --- a/src/applications/drydock/phid/DrydockBlueprintPHIDType.php +++ b/src/applications/drydock/phid/DrydockBlueprintPHIDType.php @@ -8,10 +8,6 @@ final class DrydockBlueprintPHIDType extends PhabricatorPHIDType { return pht('Blueprint'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorDrydockApplication'; - } - public function getTypeIcon() { return 'fa-map-o'; } @@ -20,6 +16,10 @@ final class DrydockBlueprintPHIDType extends PhabricatorPHIDType { return new DrydockBlueprint(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDrydockApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/drydock/phid/DrydockLeasePHIDType.php b/src/applications/drydock/phid/DrydockLeasePHIDType.php index fc921cee3a..faa751b0f1 100644 --- a/src/applications/drydock/phid/DrydockLeasePHIDType.php +++ b/src/applications/drydock/phid/DrydockLeasePHIDType.php @@ -8,10 +8,6 @@ final class DrydockLeasePHIDType extends PhabricatorPHIDType { return pht('Drydock Lease'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorDrydockApplication'; - } - public function getTypeIcon() { return 'fa-link'; } @@ -20,6 +16,10 @@ final class DrydockLeasePHIDType extends PhabricatorPHIDType { return new DrydockLease(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDrydockApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php b/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php index d21efd8a86..0926f92388 100644 --- a/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php +++ b/src/applications/drydock/phid/DrydockRepositoryOperationPHIDType.php @@ -12,6 +12,10 @@ final class DrydockRepositoryOperationPHIDType extends PhabricatorPHIDType { return new DrydockRepositoryOperation(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDrydockApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/drydock/phid/DrydockResourcePHIDType.php b/src/applications/drydock/phid/DrydockResourcePHIDType.php index 966cf35abe..a36647964d 100644 --- a/src/applications/drydock/phid/DrydockResourcePHIDType.php +++ b/src/applications/drydock/phid/DrydockResourcePHIDType.php @@ -8,10 +8,6 @@ final class DrydockResourcePHIDType extends PhabricatorPHIDType { return pht('Drydock Resource'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorDrydockApplication'; - } - public function getTypeIcon() { return 'fa-map'; } @@ -20,6 +16,10 @@ final class DrydockResourcePHIDType extends PhabricatorPHIDType { return new DrydockResource(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDrydockApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/feed/controller/PhabricatorFeedController.php b/src/applications/feed/controller/PhabricatorFeedController.php index ce7a9afe76..6e4d353518 100644 --- a/src/applications/feed/controller/PhabricatorFeedController.php +++ b/src/applications/feed/controller/PhabricatorFeedController.php @@ -2,26 +2,6 @@ abstract class PhabricatorFeedController extends PhabricatorController { - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); - - $page->setApplicationName(pht('Feed')); - $page->setBaseURI('/feed/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph("\xE2\x88\x9E"); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - - if (!empty($data['public'])) { - $page->setFrameable(true); - $page->setShowChrome(false); - $response->setFrameable(true); - } - - return $response->setContent($page->render()); - } - protected function buildSideNavView() { $user = $this->getRequest()->getUser(); diff --git a/src/applications/files/phid/PhabricatorFileFilePHIDType.php b/src/applications/files/phid/PhabricatorFileFilePHIDType.php index 7b74065535..c847c7f1a5 100644 --- a/src/applications/files/phid/PhabricatorFileFilePHIDType.php +++ b/src/applications/files/phid/PhabricatorFileFilePHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorFileFilePHIDType extends PhabricatorPHIDType { return new PhabricatorFile(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorFilesApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 4ca26fc03b..f0a5f228e3 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -557,7 +557,7 @@ final class PhabricatorFile extends PhabricatorFileDAO 'Failed to fetch remote URI "%s" after following %s redirect(s) '. '(%s): %s', $uri, - new PhutilNumber(count($redirects)), + phutil_count($redirects), implode(' > ', array_keys($redirects)), $ex->getMessage()), $ex); diff --git a/src/applications/fund/phid/FundBackerPHIDType.php b/src/applications/fund/phid/FundBackerPHIDType.php index f5f1258334..3feff6364a 100644 --- a/src/applications/fund/phid/FundBackerPHIDType.php +++ b/src/applications/fund/phid/FundBackerPHIDType.php @@ -12,6 +12,10 @@ final class FundBackerPHIDType extends PhabricatorPHIDType { return new FundInitiative(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorFundApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php b/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php index 3a2d808239..6d68b0a8b6 100644 --- a/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php +++ b/src/applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php @@ -37,7 +37,7 @@ final class HarbormasterSendMessageConduitAPIMethod $unit_spec = HarbormasterBuildUnitMessage::getParameterSpec(); foreach ($unit_spec as $key => $parameter) { $type = idx($parameter, 'type'); - $type = str_replace('|', pht(' or '), $type); + $type = str_replace('|', ' '.pht('or').' ', $type); $description = idx($parameter, 'description'); $rows[] = "| `{$key}` | //{$type}// | {$description} |"; } @@ -61,7 +61,7 @@ final class HarbormasterSendMessageConduitAPIMethod $lint_spec = HarbormasterBuildLintMessage::getParameterSpec(); foreach ($lint_spec as $key => $parameter) { $type = idx($parameter, 'type'); - $type = str_replace('|', pht(' or '), $type); + $type = str_replace('|', ' '.pht('or').' ', $type); $description = idx($parameter, 'description'); $rows[] = "| `{$key}` | //{$type}// | {$description} |"; } diff --git a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php index 1d655bb2e0..363a05776e 100644 --- a/src/applications/harbormaster/controller/HarbormasterBuildViewController.php +++ b/src/applications/harbormaster/controller/HarbormasterBuildViewController.php @@ -377,7 +377,7 @@ final class HarbormasterBuildViewController array( pht( '%s empty logs are hidden.', - new PhutilNumber(count($empty_logs))), + phutil_count($empty_logs)), ' ', javelin_tag( 'a', diff --git a/src/applications/harbormaster/controller/HarbormasterPlanRunController.php b/src/applications/harbormaster/controller/HarbormasterPlanRunController.php index 6655fd6806..fb664dc084 100644 --- a/src/applications/harbormaster/controller/HarbormasterPlanRunController.php +++ b/src/applications/harbormaster/controller/HarbormasterPlanRunController.php @@ -59,7 +59,7 @@ final class HarbormasterPlanRunController extends HarbormasterController { if (!$errors) { $buildable->save(); - $buildable->applyPlan($plan, array()); + $buildable->applyPlan($plan, array(), $viewer->getPHID()); $buildable_uri = '/B'.$buildable->getID(); return id(new AphrontRedirectResponse())->setURI($buildable_uri); diff --git a/src/applications/harbormaster/controller/HarbormasterStepEditController.php b/src/applications/harbormaster/controller/HarbormasterStepEditController.php index 37bef5f411..f15a3235b9 100644 --- a/src/applications/harbormaster/controller/HarbormasterStepEditController.php +++ b/src/applications/harbormaster/controller/HarbormasterStepEditController.php @@ -231,7 +231,10 @@ final class HarbormasterStepEditController extends HarbormasterController { 'The following variables can be used in most fields. '. 'To reference a variable, use `%s` in a field.', '${name}'); - $rows[] = pht('| Variable | Description |'); + $rows[] = sprintf( + '| %s | %s |', + pht('Variable'), + pht('Description')); $rows[] = '|---|---|'; foreach ($variables as $name => $description) { $rows[] = '| `'.$name.'` | '.$description.' |'; diff --git a/src/applications/harbormaster/engine/HarbormasterBuildRequest.php b/src/applications/harbormaster/engine/HarbormasterBuildRequest.php index 1874f08b27..71721fdaf2 100644 --- a/src/applications/harbormaster/engine/HarbormasterBuildRequest.php +++ b/src/applications/harbormaster/engine/HarbormasterBuildRequest.php @@ -14,6 +14,7 @@ final class HarbormasterBuildRequest extends Phobject { private $buildPlanPHID; + private $initiatorPHID; private $buildParameters = array(); public function setBuildPlanPHID($build_plan_phid) { @@ -34,4 +35,13 @@ final class HarbormasterBuildRequest extends Phobject { return $this->buildParameters; } + public function setInitiatorPHID($phid) { + $this->initiatorPHID = $phid; + return $this; + } + + public function getInitiatorPHID() { + return $this->initiatorPHID; + } + } diff --git a/src/applications/harbormaster/engine/HarbormasterTargetEngine.php b/src/applications/harbormaster/engine/HarbormasterTargetEngine.php index b201891b6b..d9efb8b9fd 100644 --- a/src/applications/harbormaster/engine/HarbormasterTargetEngine.php +++ b/src/applications/harbormaster/engine/HarbormasterTargetEngine.php @@ -6,7 +6,7 @@ final class HarbormasterTargetEngine extends Phobject { private $object; private $autoTargetKeys; - public function setViewer($viewer) { + public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } @@ -163,6 +163,10 @@ final class HarbormasterTargetEngine extends Phobject { array $step_map) { $viewer = $this->getViewer(); + $initiator_phid = null; + if (!$viewer->isOmnipotent()) { + $initiator_phid = $viewer->getPHID(); + } $plan_map = mgroup($step_map, 'getBuildPlanPHID'); $builds = id(new HarbormasterBuildQuery()) @@ -206,7 +210,7 @@ final class HarbormasterTargetEngine extends Phobject { // resource and "own" it, so we don't try to handle this, but may need // to be more careful here if use of autotargets expands. - $build = $buildable->applyPlan($plan, array()); + $build = $buildable->applyPlan($plan, array(), $initiator_phid); PhabricatorWorker::setRunAllTasksInProcess(false); } catch (Exception $ex) { PhabricatorWorker::setRunAllTasksInProcess(false); diff --git a/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php b/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php index db75b36d2f..76bdf9ccc3 100644 --- a/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php +++ b/src/applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php @@ -16,7 +16,7 @@ final class HarbormasterRunBuildPlansHeraldAction return ($adapter instanceof HarbormasterBuildableAdapterInterface); } - protected function applyBuilds(array $phids) { + protected function applyBuilds(array $phids, HeraldRule $rule) { $adapter = $this->getAdapter(); $allowed_types = array( @@ -32,7 +32,8 @@ final class HarbormasterRunBuildPlansHeraldAction foreach ($phids as $phid) { $request = id(new HarbormasterBuildRequest()) - ->setBuildPlanPHID($phid); + ->setBuildPlanPHID($phid) + ->setInitiatorPHID($rule->getPHID()); $adapter->queueHarbormasterBuildRequest($request); } @@ -54,7 +55,7 @@ final class HarbormasterRunBuildPlansHeraldAction case self::DO_BUILD: return pht( 'Started %s build(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } @@ -68,7 +69,7 @@ final class HarbormasterRunBuildPlansHeraldAction } public function applyEffect($object, HeraldEffect $effect) { - return $this->applyBuilds($effect->getTarget()); + return $this->applyBuilds($effect->getTarget(), $effect->getRule()); } public function getHeraldActionStandardType() { diff --git a/src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php b/src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php index 7110d98d6e..6fd3cf2ffd 100644 --- a/src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php +++ b/src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php @@ -98,7 +98,12 @@ final class HarbormasterManagementBuildWorkflow PhabricatorWorker::setRunAllTasksInProcess(true); } - $buildable->applyPlan($plan, array()); + if ($viewer->isOmnipotent()) { + $initiator = id(new PhabricatorHarbormasterApplication())->getPHID(); + } else { + $initiator = $viewer->getPHID(); + } + $buildable->applyPlan($plan, array(), $initiator); $console->writeOut("%s\n", pht('Done.')); diff --git a/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php index 5c3eb992f7..29256afd96 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php @@ -12,6 +12,10 @@ final class HarbormasterBuildArtifactPHIDType extends PhabricatorPHIDType { return new HarbormasterBuildArtifact(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php index 5e2705a40a..c0fba81c43 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php @@ -12,6 +12,10 @@ final class HarbormasterBuildLogPHIDType extends PhabricatorPHIDType { return new HarbormasterBuildLog(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php index 5669df4ee9..27551f13a8 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildPHIDType.php @@ -12,6 +12,10 @@ final class HarbormasterBuildPHIDType extends PhabricatorPHIDType { return new HarbormasterBuild(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php index d2a733630a..86aacfb8d3 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php @@ -16,6 +16,10 @@ final class HarbormasterBuildPlanPHIDType extends PhabricatorPHIDType { return new HarbormasterBuildPlan(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php index c3427fe46f..63e9bc6a12 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php @@ -12,6 +12,10 @@ final class HarbormasterBuildStepPHIDType extends PhabricatorPHIDType { return new HarbormasterBuildStep(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php index e16db13ccb..b20d6dc0a4 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php @@ -12,6 +12,10 @@ final class HarbormasterBuildTargetPHIDType extends PhabricatorPHIDType { return new HarbormasterBuildTarget(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php b/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php index 8c854efdf6..c6ccabf515 100644 --- a/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php +++ b/src/applications/harbormaster/phid/HarbormasterBuildablePHIDType.php @@ -12,6 +12,10 @@ final class HarbormasterBuildablePHIDType extends PhabricatorPHIDType { return new HarbormasterBuildable(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHarbormasterApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/harbormaster/storage/HarbormasterBuildable.php b/src/applications/harbormaster/storage/HarbormasterBuildable.php index e74471e879..3a7df73f52 100644 --- a/src/applications/harbormaster/storage/HarbormasterBuildable.php +++ b/src/applications/harbormaster/storage/HarbormasterBuildable.php @@ -154,11 +154,14 @@ final class HarbormasterBuildable extends HarbormasterDAO } $parameters = $request->getBuildParameters(); - $buildable->applyPlan($plan, $parameters); + $buildable->applyPlan($plan, $parameters, $request->getInitiatorPHID()); } } - public function applyPlan(HarbormasterBuildPlan $plan, array $parameters) { + public function applyPlan( + HarbormasterBuildPlan $plan, + array $parameters, + $initiator_phid) { $viewer = PhabricatorUser::getOmnipotentUser(); $build = HarbormasterBuild::initializeNewBuild($viewer) @@ -166,6 +169,9 @@ final class HarbormasterBuildable extends HarbormasterDAO ->setBuildPlanPHID($plan->getPHID()) ->setBuildParameters($parameters) ->setBuildStatus(HarbormasterBuild::STATUS_PENDING); + if ($initiator_phid) { + $build->setInitiatorPHID($initiator_phid); + } $auto_key = $plan->getPlanAutoKey(); if ($auto_key) { diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php index 154681d93f..c96d0c2710 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php @@ -10,6 +10,7 @@ final class HarbormasterBuild extends HarbormasterDAO protected $buildStatus; protected $buildGeneration; protected $buildParameters = array(); + protected $initiatorPHID; protected $planAutoKey; private $buildable = self::ATTACHABLE; @@ -164,6 +165,7 @@ final class HarbormasterBuild extends HarbormasterDAO 'buildStatus' => 'text32', 'buildGeneration' => 'uint32', 'planAutoKey' => 'text32?', + 'initiatorPHID' => 'phid?', ), self::CONFIG_KEY_SCHEMA => array( 'key_buildable' => array( @@ -260,6 +262,7 @@ final class HarbormasterBuild extends HarbormasterDAO 'repository.uri' => null, 'step.timestamp' => null, 'build.id' => null, + 'initiator.phid' => null, ); foreach ($this->getBuildParameters() as $key => $value) { @@ -275,6 +278,7 @@ final class HarbormasterBuild extends HarbormasterDAO $results['step.timestamp'] = time(); $results['build.id'] = $this->getID(); + $results['initiator.phid'] = $this->getInitiatorPHID(); return $results; } @@ -289,6 +293,9 @@ final class HarbormasterBuild extends HarbormasterDAO 'step.timestamp' => pht('The current UNIX timestamp.'), 'build.id' => pht('The ID of the current build.'), 'target.phid' => pht('The PHID of the current build target.'), + 'initiator.phid' => pht( + 'The PHID of the user or Object that initiated the build, '. + 'if applicable.'), ); foreach ($objects as $object) { diff --git a/src/applications/help/controller/PhabricatorHelpController.php b/src/applications/help/controller/PhabricatorHelpController.php index 247175c3ec..d51618b545 100644 --- a/src/applications/help/controller/PhabricatorHelpController.php +++ b/src/applications/help/controller/PhabricatorHelpController.php @@ -1,18 +1,3 @@ buildStandardPageView(); - - $page->setApplicationName(pht('Help')); - $page->setBaseURI('/help/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph('?'); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - } - -} +abstract class PhabricatorHelpController extends PhabricatorController {} diff --git a/src/applications/herald/action/HeraldAction.php b/src/applications/herald/action/HeraldAction.php index f4217cd4db..6b076fbddf 100644 --- a/src/applications/herald/action/HeraldAction.php +++ b/src/applications/herald/action/HeraldAction.php @@ -346,22 +346,22 @@ abstract class HeraldAction extends Phobject { case self::DO_STANDARD_NO_EFFECT: return pht( 'This action has no effect on %s target(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_STANDARD_INVALID: return pht( '%s target(s) are invalid or of the wrong type: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_STANDARD_UNLOADABLE: return pht( '%s target(s) could not be loaded: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_STANDARD_PERMISSION: return pht( '%s target(s) do not have permission to see this object: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_STANDARD_INVALID_ACTION: return pht( diff --git a/src/applications/herald/controller/HeraldController.php b/src/applications/herald/controller/HeraldController.php index b363232ca5..b3ba2f17c3 100644 --- a/src/applications/herald/controller/HeraldController.php +++ b/src/applications/herald/controller/HeraldController.php @@ -2,20 +2,6 @@ abstract class HeraldController extends PhabricatorController { - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); - - $page->setApplicationName(pht('Herald')); - $page->setBaseURI('/herald/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph("\xE2\x98\xBF"); - - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - } - public function buildApplicationMenu() { return $this->buildSideNavView(true)->getMenu(); } diff --git a/src/applications/herald/phid/HeraldRulePHIDType.php b/src/applications/herald/phid/HeraldRulePHIDType.php index 4820eee62b..f8d5c25db4 100644 --- a/src/applications/herald/phid/HeraldRulePHIDType.php +++ b/src/applications/herald/phid/HeraldRulePHIDType.php @@ -12,6 +12,10 @@ final class HeraldRulePHIDType extends PhabricatorPHIDType { return new HeraldRule(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorHeraldApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/home/controller/PhabricatorHomeController.php b/src/applications/home/controller/PhabricatorHomeController.php index 024807b74b..334a34e99b 100644 --- a/src/applications/home/controller/PhabricatorHomeController.php +++ b/src/applications/home/controller/PhabricatorHomeController.php @@ -2,19 +2,6 @@ abstract class PhabricatorHomeController extends PhabricatorController { - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); - - $page->setBaseURI('/'); - $page->setTitle(idx($data, 'title')); - - $page->setGlyph("\xE2\x9A\x92"); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - } - public function buildNav() { $user = $this->getRequest()->getUser(); diff --git a/src/applications/legalpad/controller/LegalpadDocumentSignController.php b/src/applications/legalpad/controller/LegalpadDocumentSignController.php index 40697eef30..b9c43e377b 100644 --- a/src/applications/legalpad/controller/LegalpadDocumentSignController.php +++ b/src/applications/legalpad/controller/LegalpadDocumentSignController.php @@ -253,7 +253,7 @@ final class LegalpadDocumentSignController extends LegalpadController { ->setIcon( id(new PHUIIconView()) ->setIconFont('fa-pencil')) - ->setText(pht('Manage Document')) + ->setText(pht('Manage')) ->setHref($manage_uri) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); @@ -278,7 +278,7 @@ final class LegalpadDocumentSignController extends LegalpadController { $preamble_box->addPropertyList($preamble); } - $content = id(new PHUIDocumentView()) + $content = id(new PHUIDocumentViewPro()) ->addClass('legalpad') ->setHeader($header) ->appendChild( @@ -288,6 +288,7 @@ final class LegalpadDocumentSignController extends LegalpadController { $document_markup, )); + $signature_box = null; if (!$has_signed) { $error_view = null; if ($errors) { @@ -301,23 +302,21 @@ final class LegalpadDocumentSignController extends LegalpadController { $field_errors); switch ($document->getSignatureType()) { - case LegalpadDocument::SIGNATURE_TYPE_NONE: - $subheader = null; + default: break; case LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL: case LegalpadDocument::SIGNATURE_TYPE_CORPORATION: - $subheader = id(new PHUIHeaderView()) - ->setHeader(pht('Agree and Sign Document')) - ->setBleedHeader(true); + $box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Agree and Sign Document')) + ->setForm($signature_form); + if ($error_view) { + $box->setInfoView($error_view); + } + $signature_box = phutil_tag_div('phui-document-view-pro-box', $box); break; } - $content->appendChild( - array( - $subheader, - $error_view, - $signature_form, - )); + } $crumbs = $this->buildApplicationCrumbs(); @@ -328,9 +327,11 @@ final class LegalpadDocumentSignController extends LegalpadController { array( $crumbs, $content, + $signature_box, ), array( 'title' => $title, + 'class' => 'pro-white-background', 'pageObjects' => array($document->getPHID()), )); } diff --git a/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php b/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php index 22d41449ad..7ff69d37d5 100644 --- a/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php +++ b/src/applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php @@ -95,12 +95,12 @@ final class LegalpadRequireSignatureHeraldAction case self::DO_SIGNED: return pht( '%s document(s) are already signed: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_REQUIRED: return pht( 'Required %s signature(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } diff --git a/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php b/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php index 5b1a4a9833..39c744f271 100644 --- a/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php +++ b/src/applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php @@ -16,6 +16,10 @@ final class PhabricatorLegalpadDocumentPHIDType extends PhabricatorPHIDType { return new LegalpadDocument(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorLegalpadApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/maniphest/phid/ManiphestTaskPHIDType.php b/src/applications/maniphest/phid/ManiphestTaskPHIDType.php index 719b4a8446..3b3c4a203f 100644 --- a/src/applications/maniphest/phid/ManiphestTaskPHIDType.php +++ b/src/applications/maniphest/phid/ManiphestTaskPHIDType.php @@ -8,14 +8,14 @@ final class ManiphestTaskPHIDType extends PhabricatorPHIDType { return pht('Maniphest Task'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorManiphestApplication'; - } - public function newObject() { return new ManiphestTask(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorManiphestApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/maniphest/storage/ManiphestTransaction.php b/src/applications/maniphest/storage/ManiphestTransaction.php index a05cf1ab13..0456673a10 100644 --- a/src/applications/maniphest/storage/ManiphestTransaction.php +++ b/src/applications/maniphest/storage/ManiphestTransaction.php @@ -546,23 +546,23 @@ final class ManiphestTransaction $removed = array_diff($old, $new); if ($added && !$removed) { return pht( - '%s attached %d file(s): %s.', + '%s attached %s file(s): %s.', $this->renderHandleLink($author_phid), - count($added), + phutil_count($added), $this->renderHandleList($added)); } else if ($removed && !$added) { return pht( - '%s detached %d file(s): %s.', + '%s detached %s file(s): %s.', $this->renderHandleLink($author_phid), - count($removed), + phutil_count($removed), $this->renderHandleList($removed)); } else { return pht( - '%s changed file(s), attached %d: %s; detached %d: %s.', + '%s changed file(s), attached %s: %s; detached %s: %s.', $this->renderHandleLink($author_phid), - count($added), + phutil_count($added), $this->renderHandleList($added), - count($removed), + phutil_count($removed), $this->renderHandleList($removed)); } @@ -585,9 +585,9 @@ final class ManiphestTransaction case self::TYPE_MERGED_FROM: return pht( - '%s merged %d task(s): %s.', + '%s merged %s task(s): %s.', $this->renderHandleLink($author_phid), - count($new), + phutil_count($new), $this->renderHandleList($new)); break; diff --git a/src/applications/maniphest/view/ManiphestTaskResultListView.php b/src/applications/maniphest/view/ManiphestTaskResultListView.php index cd05d7f7f7..52f4a3b2d6 100644 --- a/src/applications/maniphest/view/ManiphestTaskResultListView.php +++ b/src/applications/maniphest/view/ManiphestTaskResultListView.php @@ -82,7 +82,7 @@ final class ManiphestTaskResultListView extends ManiphestView { $header = id(new PHUIHeaderView()) ->addSigil('task-group') ->setMetadata(array('priority' => head($list)->getPriority())) - ->setHeader(pht('%s (%s)', $group, new PhutilNumber(count($list)))); + ->setHeader(pht('%s (%s)', $group, phutil_count($list))); $lists[] = id(new PHUIObjectBoxView()) ->setHeader($header) diff --git a/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php b/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php index 23ac83ac92..63f2d256e1 100644 --- a/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php +++ b/src/applications/meta/controller/PhabricatorApplicationEmailCommandsController.php @@ -115,6 +115,7 @@ final class PhabricatorApplicationEmailCommandsController $crumbs = $this->buildApplicationCrumbs(); $this->addApplicationCrumb($crumbs, $selected); $crumbs->addTextCrumb($title); + $crumbs->setBorder(true); $content_box = PhabricatorMarkupEngine::renderOneObject( id(new PhabricatorMarkupOneOff())->setContent($content), @@ -134,7 +135,7 @@ final class PhabricatorApplicationEmailCommandsController $header = id(new PHUIHeaderView()) ->setHeader($title); - $document = id(new PHUIDocumentView()) + $document = id(new PHUIDocumentViewPro()) ->setHeader($header) ->appendChild($info_view) ->appendChild($content_box); @@ -146,6 +147,7 @@ final class PhabricatorApplicationEmailCommandsController ), array( 'title' => $title, + 'class' => 'pro-white-background', )); } diff --git a/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php b/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php index aa2b21b967..d0b1f763a4 100644 --- a/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php +++ b/src/applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php @@ -17,6 +17,10 @@ final class PhabricatorApplicationApplicationPHIDType return null; } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorApplicationsApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php b/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php index ec7036ebe0..2b29fe2443 100644 --- a/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php +++ b/src/applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php @@ -75,13 +75,13 @@ abstract class PhabricatorMetaMTAEmailHeraldAction case self::DO_SEND: return pht( 'Queued email to be delivered to %s target(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_FORCE: return pht( 'Queued email to be delivered to %s target(s), ignoring their '. 'notification preferences: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } diff --git a/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php b/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php index 7117b50f8e..1436038fae 100644 --- a/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php +++ b/src/applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php @@ -8,14 +8,14 @@ final class PhabricatorMetaMTAMailPHIDType extends PhabricatorPHIDType { return pht('MetaMTA Mail'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorMetaMTAApplication'; - } - public function newObject() { return new PhabricatorMetaMTAMail(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorMetaMTAApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/multimeter/controller/MultimeterSampleController.php b/src/applications/multimeter/controller/MultimeterSampleController.php index a62d10ef30..f9a36b37d1 100644 --- a/src/applications/multimeter/controller/MultimeterSampleController.php +++ b/src/applications/multimeter/controller/MultimeterSampleController.php @@ -90,7 +90,7 @@ final class MultimeterSampleController extends MultimeterController { $events_col = $this->renderGroupingLink( $group, 'id', - pht('%s Events', new PhutilNumber($row['N']))); + pht('%s Event(s)', new PhutilNumber($row['N']))); } if (isset($group['request'])) { diff --git a/src/applications/notification/controller/PhabricatorNotificationController.php b/src/applications/notification/controller/PhabricatorNotificationController.php index 576625eab8..11e60c17f8 100644 --- a/src/applications/notification/controller/PhabricatorNotificationController.php +++ b/src/applications/notification/controller/PhabricatorNotificationController.php @@ -1,21 +1,4 @@ buildStandardPageView(); - - $page->setApplicationName(pht('Notification')); - $page->setBaseURI('/notification/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph('!'); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - - } - -} + extends PhabricatorController {} diff --git a/src/applications/nuance/phid/NuanceItemPHIDType.php b/src/applications/nuance/phid/NuanceItemPHIDType.php index e1068cc50d..f401c63594 100644 --- a/src/applications/nuance/phid/NuanceItemPHIDType.php +++ b/src/applications/nuance/phid/NuanceItemPHIDType.php @@ -12,6 +12,10 @@ final class NuanceItemPHIDType extends PhabricatorPHIDType { return new NuanceItem(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorNuanceApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/nuance/phid/NuanceQueuePHIDType.php b/src/applications/nuance/phid/NuanceQueuePHIDType.php index 13bcfa5d20..b51812320d 100644 --- a/src/applications/nuance/phid/NuanceQueuePHIDType.php +++ b/src/applications/nuance/phid/NuanceQueuePHIDType.php @@ -12,6 +12,10 @@ final class NuanceQueuePHIDType extends PhabricatorPHIDType { return new NuanceQueue(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorNuanceApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/nuance/phid/NuanceRequestorPHIDType.php b/src/applications/nuance/phid/NuanceRequestorPHIDType.php index 2cf06bbb10..a2442d3b48 100644 --- a/src/applications/nuance/phid/NuanceRequestorPHIDType.php +++ b/src/applications/nuance/phid/NuanceRequestorPHIDType.php @@ -12,6 +12,10 @@ final class NuanceRequestorPHIDType extends PhabricatorPHIDType { return new NuanceRequestor(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorNuanceApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/nuance/phid/NuanceSourcePHIDType.php b/src/applications/nuance/phid/NuanceSourcePHIDType.php index d259fe48a9..774939bf29 100644 --- a/src/applications/nuance/phid/NuanceSourcePHIDType.php +++ b/src/applications/nuance/phid/NuanceSourcePHIDType.php @@ -12,6 +12,10 @@ final class NuanceSourcePHIDType extends PhabricatorPHIDType { return new NuanceSource(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorNuanceApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php index e3ff50a6f7..b2fc1554fd 100644 --- a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php +++ b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php @@ -13,6 +13,10 @@ final class PhabricatorOAuthServerClientAuthorizationPHIDType return new PhabricatorOAuthClientAuthorization(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorOAuthServerApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php index 81b8fdacde..a4d8834b96 100644 --- a/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php +++ b/src/applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorOAuthServerClientPHIDType extends PhabricatorPHIDType { return new PhabricatorOAuthServerClient(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorOAuthServerApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php b/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php index b2492b0bef..fa667d4dcb 100644 --- a/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php +++ b/src/applications/owners/phid/PhabricatorOwnersPackagePHIDType.php @@ -16,6 +16,10 @@ final class PhabricatorOwnersPackagePHIDType extends PhabricatorPHIDType { return new PhabricatorOwnersPackage(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorOwnersApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/paste/application/PhabricatorPasteApplication.php b/src/applications/paste/application/PhabricatorPasteApplication.php index 7fe3ec41e7..e066d4cd9d 100644 --- a/src/applications/paste/application/PhabricatorPasteApplication.php +++ b/src/applications/paste/application/PhabricatorPasteApplication.php @@ -39,7 +39,7 @@ final class PhabricatorPasteApplication extends PhabricatorApplication { '/paste/' => array( '(query/(?P[^/]+)/)?' => 'PhabricatorPasteListController', 'create/' => 'PhabricatorPasteEditController', - 'edit/(?P[1-9]\d*)/' => 'PhabricatorPasteEditController', + $this->getEditRoutePattern('edit/') => 'PhabricatorPasteEditController', 'raw/(?P[1-9]\d*)/' => 'PhabricatorPasteRawController', 'comment/(?P[1-9]\d*)/' => 'PhabricatorPasteCommentController', ), diff --git a/src/applications/paste/conduit/PasteCreateConduitAPIMethod.php b/src/applications/paste/conduit/PasteCreateConduitAPIMethod.php index 379f5b6e8d..d5ce021f13 100644 --- a/src/applications/paste/conduit/PasteCreateConduitAPIMethod.php +++ b/src/applications/paste/conduit/PasteCreateConduitAPIMethod.php @@ -44,16 +44,11 @@ final class PasteCreateConduitAPIMethod extends PasteConduitAPIMethod { $paste = PhabricatorPaste::initializeNewPaste($viewer); - $file = PhabricatorPasteEditor::initializeFileForPaste( - $viewer, - $title, - $content); - $xactions = array(); $xactions[] = id(new PhabricatorPasteTransaction()) ->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT) - ->setNewValue($file->getPHID()); + ->setNewValue($content); $xactions[] = id(new PhabricatorPasteTransaction()) ->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE) diff --git a/src/applications/paste/conduit/PasteEditConduitAPIMethod.php b/src/applications/paste/conduit/PasteEditConduitAPIMethod.php new file mode 100644 index 0000000000..c02fb940e8 --- /dev/null +++ b/src/applications/paste/conduit/PasteEditConduitAPIMethod.php @@ -0,0 +1,19 @@ +getRequest()->getUser(); - - $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - - if ($for_app) { - $nav->addFilter('create', pht('Create Paste')); - } - - id(new PhabricatorPasteSearchEngine()) - ->setViewer($user) - ->addNavigationItems($nav->getMenu()); - - $nav->selectFilter(null); - - return $nav; - } - public function buildApplicationMenu() { - return $this->buildSideNavView(true)->getMenu(); - } - - protected function buildApplicationCrumbs() { - $crumbs = parent::buildApplicationCrumbs(); - - $crumbs->addAction( - id(new PHUIListItemView()) - ->setName(pht('Create Paste')) - ->setHref($this->getApplicationURI('create/')) - ->setIcon('fa-plus-square')); - - return $crumbs; + return $this->newApplicationMenu() + ->setSearchEngine(new PhabricatorPasteSearchEngine()); } public function buildSourceCodeView( diff --git a/src/applications/paste/controller/PhabricatorPasteEditController.php b/src/applications/paste/controller/PhabricatorPasteEditController.php index 19b394c18a..c9ee5a289e 100644 --- a/src/applications/paste/controller/PhabricatorPasteEditController.php +++ b/src/applications/paste/controller/PhabricatorPasteEditController.php @@ -3,248 +3,9 @@ final class PhabricatorPasteEditController extends PhabricatorPasteController { public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - $id = $request->getURIData('id'); - - $parent = null; - $parent_id = null; - if (!$id) { - $is_create = true; - - $paste = PhabricatorPaste::initializeNewPaste($viewer); - - $parent_id = $request->getStr('parent'); - if ($parent_id) { - // NOTE: If the Paste is forked from a paste which the user no longer - // has permission to see, we still let them edit it. - $parent = id(new PhabricatorPasteQuery()) - ->setViewer($viewer) - ->withIDs(array($parent_id)) - ->needContent(true) - ->needRawContent(true) - ->execute(); - $parent = head($parent); - - if ($parent) { - $paste->setParentPHID($parent->getPHID()); - $paste->setViewPolicy($parent->getViewPolicy()); - } - } - - $paste->setAuthorPHID($viewer->getPHID()); - $paste->attachRawContent(''); - } else { - $is_create = false; - - $paste = id(new PhabricatorPasteQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->withIDs(array($id)) - ->needRawContent(true) - ->executeOne(); - if (!$paste) { - return new Aphront404Response(); - } - } - - $v_space = $paste->getSpacePHID(); - if ($is_create && $parent) { - $v_title = pht('Fork of %s', $parent->getFullName()); - $v_language = $parent->getLanguage(); - $v_text = $parent->getRawContent(); - $v_space = $parent->getSpacePHID(); - } else { - $v_title = $paste->getTitle(); - $v_language = $paste->getLanguage(); - $v_text = $paste->getRawContent(); - } - $v_view_policy = $paste->getViewPolicy(); - $v_edit_policy = $paste->getEditPolicy(); - $v_status = $paste->getStatus(); - - if ($is_create) { - $v_projects = array(); - } else { - $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $paste->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $v_projects = array_reverse($v_projects); - } - - $validation_exception = null; - if ($request->isFormPost()) { - $xactions = array(); - - $v_text = $request->getStr('text'); - $v_title = $request->getStr('title'); - $v_language = $request->getStr('language'); - $v_view_policy = $request->getStr('can_view'); - $v_edit_policy = $request->getStr('can_edit'); - $v_projects = $request->getArr('projects'); - $v_space = $request->getStr('spacePHID'); - $v_status = $request->getStr('status'); - - // NOTE: The author is the only editor and can always view the paste, - // so it's impossible for them to choose an invalid policy. - - if ($is_create || ($v_text !== $paste->getRawContent())) { - $file = PhabricatorPasteEditor::initializeFileForPaste( - $viewer, - $v_title, - $v_text); - - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT) - ->setNewValue($file->getPHID()); - } - - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE) - ->setNewValue($v_title); - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorPasteTransaction::TYPE_LANGUAGE) - ->setNewValue($v_language); - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) - ->setNewValue($v_view_policy); - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) - ->setNewValue($v_edit_policy); - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) - ->setNewValue($v_space); - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorPasteTransaction::TYPE_STATUS) - ->setNewValue($v_status); - - $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $proj_edge_type) - ->setNewValue(array('=' => array_fuse($v_projects))); - - $editor = id(new PhabricatorPasteEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - try { - $xactions = $editor->applyTransactions($paste, $xactions); - return id(new AphrontRedirectResponse())->setURI($paste->getURI()); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - } - } - - $form = new AphrontFormView(); - - $langs = array( - '' => pht('(Detect From Filename in Title)'), - ) + PhabricatorEnv::getEnvConfig('pygments.dropdown-choices'); - - $form - ->setUser($viewer) - ->addHiddenInput('parent', $parent_id) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Title')) - ->setValue($v_title) - ->setName('title')) - ->appendChild( - id(new AphrontFormSelectControl()) - ->setLabel(pht('Language')) - ->setName('language') - ->setValue($v_language) - ->setOptions($langs)); - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($paste) - ->execute(); - - $form->appendChild( - id(new AphrontFormPolicyControl()) - ->setUser($viewer) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicyObject($paste) - ->setPolicies($policies) - ->setValue($v_view_policy) - ->setSpacePHID($v_space) - ->setName('can_view')); - - $form->appendChild( - id(new AphrontFormPolicyControl()) - ->setUser($viewer) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicyObject($paste) - ->setPolicies($policies) - ->setValue($v_edit_policy) - ->setName('can_edit')); - - $form->appendChild( - id(new AphrontFormSelectControl()) - ->setLabel(pht('Status')) - ->setName('status') - ->setValue($v_status) - ->setOptions($paste->getStatusNameMap())); - - $form->appendControl( - id(new AphrontFormTokenizerControl()) - ->setLabel(pht('Projects')) - ->setName('projects') - ->setValue($v_projects) - ->setDatasource(new PhabricatorProjectDatasource())); - - $form - ->appendChild( - id(new AphrontFormTextAreaControl()) - ->setLabel(pht('Text')) - ->setValue($v_text) - ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) - ->setCustomClass('PhabricatorMonospaced') - ->setName('text')); - - $submit = new AphrontFormSubmitControl(); - - if (!$is_create) { - $submit->addCancelButton($paste->getURI()); - $submit->setValue(pht('Save Paste')); - $title = pht('Edit %s', $paste->getFullName()); - $short = pht('Edit'); - } else { - $submit->setValue(pht('Create Paste')); - $title = pht('Create New Paste'); - $short = pht('Create'); - } - - $form->appendChild($submit); - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText($title) - ->setForm($form); - - if ($validation_exception) { - $form_box->setValidationException($validation_exception); - } - - $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()); - if (!$is_create) { - $crumbs->addTextCrumb('P'.$paste->getID(), '/P'.$paste->getID()); - } - $crumbs->addTextCrumb($short); - - return $this->buildApplicationPage( - array( - $crumbs, - $form_box, - ), - array( - 'title' => $title, - )); + return id(new PhabricatorPasteEditEngine()) + ->setController($this) + ->buildResponse(); } } diff --git a/src/applications/paste/controller/PhabricatorPasteListController.php b/src/applications/paste/controller/PhabricatorPasteListController.php index 2092443ffc..e867b4e773 100644 --- a/src/applications/paste/controller/PhabricatorPasteListController.php +++ b/src/applications/paste/controller/PhabricatorPasteListController.php @@ -7,15 +7,21 @@ final class PhabricatorPasteListController extends PhabricatorPasteController { } public function handleRequest(AphrontRequest $request) { - $querykey = $request->getURIData('queryKey'); - - $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($querykey) - ->setSearchEngine(new PhabricatorPasteSearchEngine()) - ->setNavigation($this->buildSideNavView()); - - return $this->delegateToController($controller); + return id(new PhabricatorPasteSearchEngine()) + ->setController($this) + ->buildResponse(); } + protected function buildApplicationCrumbs() { + $crumbs = parent::buildApplicationCrumbs(); + + $crumbs->addAction( + id(new PHUIListItemView()) + ->setName(pht('Create Paste')) + ->setHref($this->getApplicationURI('edit/')) + ->setIcon('fa-plus-square')); + + return $crumbs; + } } diff --git a/src/applications/paste/controller/PhabricatorPasteViewController.php b/src/applications/paste/controller/PhabricatorPasteViewController.php index 46239e7fca..43a7058f59 100644 --- a/src/applications/paste/controller/PhabricatorPasteViewController.php +++ b/src/applications/paste/controller/PhabricatorPasteViewController.php @@ -66,7 +66,7 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { ), $source_code); - $crumbs = $this->buildApplicationCrumbs($this->buildSideNavView()) + $crumbs = $this->buildApplicationCrumbs() ->addTextCrumb('P'.$paste->getID(), '/P'.$paste->getID()); $timeline = $this->buildTransactionTimeline( @@ -89,18 +89,20 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { ->setAction($this->getApplicationURI('/comment/'.$paste->getID().'/')) ->setSubmitButtonName(pht('Add Comment')); - return $this->buildApplicationPage( - array( - $crumbs, - $object_box, - $source_code, - $timeline, - $add_comment_form, - ), - array( - 'title' => $paste->getFullName(), - 'pageObjects' => array($paste->getPHID()), - )); + return $this->newPage() + ->setTitle($paste->getFullName()) + ->setCrumbs($crumbs) + ->setPageObjectPHIDs( + array( + $paste->getPHID(), + )) + ->appendChild( + array( + $object_box, + $source_code, + $timeline, + $add_comment_form, + )); } private function buildHeaderView(PhabricatorPaste $paste) { @@ -135,9 +137,7 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { $paste, PhabricatorPolicyCapability::CAN_EDIT); - $can_fork = $viewer->isLoggedIn(); $id = $paste->getID(); - $fork_uri = $this->getApplicationURI('/create/?parent='.$id); return id(new PhabricatorActionListView()) ->setUser($viewer) @@ -150,13 +150,6 @@ final class PhabricatorPasteViewController extends PhabricatorPasteController { ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref($this->getApplicationURI("edit/{$id}/"))) - ->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Fork This Paste')) - ->setIcon('fa-code-fork') - ->setDisabled(!$can_fork) - ->setWorkflow(!$can_fork) - ->setHref($fork_uri)) ->addAction( id(new PhabricatorActionView()) ->setName(pht('View Raw File')) diff --git a/src/applications/paste/editor/PhabricatorPasteEditEngine.php b/src/applications/paste/editor/PhabricatorPasteEditEngine.php new file mode 100644 index 0000000000..b92042f93f --- /dev/null +++ b/src/applications/paste/editor/PhabricatorPasteEditEngine.php @@ -0,0 +1,77 @@ +getViewer()); + } + + protected function newObjectQuery() { + return id(new PhabricatorPasteQuery()) + ->needRawContent(true); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Paste'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit %s %s', $object->getMonogram(), $object->getTitle()); + } + + protected function getObjectEditShortText($object) { + return $object->getMonogram(); + } + + protected function getObjectCreateShortText($object) { + return pht('Create Paste'); + } + + protected function getObjectViewURI($object) { + return '/P'.$object->getID(); + } + + protected function buildCustomEditFields($object) { + $langs = array( + '' => pht('(Detect From Filename in Title)'), + ) + PhabricatorEnv::getEnvConfig('pygments.dropdown-choices'); + + return array( + id(new PhabricatorTextEditField()) + ->setKey('title') + ->setLabel(pht('Title')) + ->setDescription(pht('Name of the paste.')) + ->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE) + ->setValue($object->getTitle()), + id(new PhabricatorSelectEditField()) + ->setKey('language') + ->setLabel(pht('Language')) + ->setDescription( + pht( + 'Programming language to interpret the paste as for syntax '. + 'highlighting. By default, the language is inferred from the '. + 'title.')) + ->setAliases(array('lang')) + ->setTransactionType(PhabricatorPasteTransaction::TYPE_LANGUAGE) + ->setValue($object->getLanguage()) + ->setOptions($langs), + id(new PhabricatorSelectEditField()) + ->setKey('status') + ->setLabel(pht('Status')) + ->setDescription(pht('Archive the paste.')) + ->setTransactionType(PhabricatorPasteTransaction::TYPE_STATUS) + ->setValue($object->getStatus()) + ->setOptions(PhabricatorPaste::getStatusNameMap()), + id(new PhabricatorTextAreaEditField()) + ->setKey('text') + ->setLabel(pht('Text')) + ->setDescription(pht('The main body text of the paste.')) + ->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT) + ->setMonospaced(true) + ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) + ->setValue($object->getRawContent()), + ); + } + +} diff --git a/src/applications/paste/editor/PhabricatorPasteEditor.php b/src/applications/paste/editor/PhabricatorPasteEditor.php index bae2003afe..cd7a0f271a 100644 --- a/src/applications/paste/editor/PhabricatorPasteEditor.php +++ b/src/applications/paste/editor/PhabricatorPasteEditor.php @@ -3,6 +3,8 @@ final class PhabricatorPasteEditor extends PhabricatorApplicationTransactionEditor { + private $fileName; + public function getEditorApplicationClass() { return 'PhabricatorPasteApplication'; } @@ -41,6 +43,59 @@ final class PhabricatorPasteEditor return $types; } + protected function shouldApplyInitialEffects( + PhabricatorLiskDAO $object, + array $xactions) { + return true; + } + + protected function applyInitialEffects( + PhabricatorLiskDAO $object, + array $xactions) { + + // Find the most user-friendly filename we can by examining the title of + // the paste and the pending transactions. We'll use this if we create a + // new file to store raw content later. + + $name = $object->getTitle(); + if (!strlen($name)) { + $name = 'paste.raw'; + } + + $type_title = PhabricatorPasteTransaction::TYPE_TITLE; + foreach ($xactions as $xaction) { + if ($xaction->getTransactionType() == $type_title) { + $name = $xaction->getNewValue(); + } + } + + $this->fileName = $name; + } + + protected function validateTransaction( + PhabricatorLiskDAO $object, + $type, + array $xactions) { + + $errors = parent::validateTransaction($object, $type, $xactions); + switch ($type) { + case PhabricatorPasteTransaction::TYPE_CONTENT: + if (!$object->getFilePHID() && !$xactions) { + $error = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Required'), + pht('You must provide content to create a paste.'), + null); + + $error->setIsMissingFieldError(true); + $errors[] = $error; + } + break; + } + + return $errors; + } + protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { @@ -62,11 +117,26 @@ final class PhabricatorPasteEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorPasteTransaction::TYPE_CONTENT: case PhabricatorPasteTransaction::TYPE_TITLE: case PhabricatorPasteTransaction::TYPE_LANGUAGE: case PhabricatorPasteTransaction::TYPE_STATUS: return $xaction->getNewValue(); + case PhabricatorPasteTransaction::TYPE_CONTENT: + // If this transaction does not really change the paste content, return + // the current file PHID so this transaction no-ops. + $new_content = $xaction->getNewValue(); + $old_content = $object->getRawContent(); + $file_phid = $object->getFilePHID(); + if (($new_content === $old_content) && $file_phid) { + return $file_phid; + } + + $file = self::initializeFileForPaste( + $this->getActor(), + $this->fileName, + $xaction->getNewValue()); + + return $file->getPHID(); } } diff --git a/src/applications/paste/mail/PasteCreateMailReceiver.php b/src/applications/paste/mail/PasteCreateMailReceiver.php index d0c50d5fcf..672667cd65 100644 --- a/src/applications/paste/mail/PasteCreateMailReceiver.php +++ b/src/applications/paste/mail/PasteCreateMailReceiver.php @@ -21,16 +21,11 @@ final class PasteCreateMailReceiver extends PhabricatorMailReceiver { $title = pht('Email Paste'); } - $file = PhabricatorPasteEditor::initializeFileForPaste( - $sender, - $title, - $mail->getCleanTextBody()); - $xactions = array(); $xactions[] = id(new PhabricatorPasteTransaction()) ->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT) - ->setNewValue($file->getPHID()); + ->setNewValue($mail->getCleanTextBody()); $xactions[] = id(new PhabricatorPasteTransaction()) ->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE) diff --git a/src/applications/paste/phid/PhabricatorPastePastePHIDType.php b/src/applications/paste/phid/PhabricatorPastePastePHIDType.php index c07f902316..d08d52e2e1 100644 --- a/src/applications/paste/phid/PhabricatorPastePastePHIDType.php +++ b/src/applications/paste/phid/PhabricatorPastePastePHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorPastePastePHIDType extends PhabricatorPHIDType { return new PhabricatorPaste(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPasteApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/paste/storage/PhabricatorPaste.php b/src/applications/paste/storage/PhabricatorPaste.php index 8aeda09aae..ee381e9493 100644 --- a/src/applications/paste/storage/PhabricatorPaste.php +++ b/src/applications/paste/storage/PhabricatorPaste.php @@ -41,11 +41,13 @@ final class PhabricatorPaste extends PhabricatorPasteDAO return id(new PhabricatorPaste()) ->setTitle('') + ->setLanguage('') ->setStatus(self::STATUS_ACTIVE) ->setAuthorPHID($actor->getPHID()) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) - ->setSpacePHID($actor->getDefaultSpacePHID()); + ->setSpacePHID($actor->getDefaultSpacePHID()) + ->attachRawContent(null); } public static function getStatusNameMap() { diff --git a/src/applications/people/controller/PhabricatorPeopleDeleteController.php b/src/applications/people/controller/PhabricatorPeopleDeleteController.php index e95dd4c646..01b37b37fe 100644 --- a/src/applications/people/controller/PhabricatorPeopleDeleteController.php +++ b/src/applications/people/controller/PhabricatorPeopleDeleteController.php @@ -49,9 +49,9 @@ final class PhabricatorPeopleDeleteController $form = id(new AphrontFormView()) ->setUser($admin) ->appendRemarkupInstructions( - pht( - " phabricator/ $ ./bin/remove destroy %s\n", - csprintf('%R', '@'.$user->getUsername()))); + csprintf( + " phabricator/ $ ./bin/remove destroy %R\n", + '@'.$user->getUsername())); return $this->newDialog() ->setWidth(AphrontDialogView::WIDTH_FORM) diff --git a/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php b/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php index 9fd565700c..4be4cc5359 100644 --- a/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php +++ b/src/applications/people/phid/PhabricatorPeopleExternalPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorPeopleExternalPHIDType extends PhabricatorPHIDType { return new PhabricatorExternalAccount(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPeopleApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php index f09c75087e..0304173f90 100644 --- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php +++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php @@ -8,10 +8,6 @@ final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType { return pht('User'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorPeopleApplication'; - } - public function getTypeIcon() { return 'fa-user bluegrey'; } @@ -20,6 +16,10 @@ final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType { return new PhabricatorUser(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPeopleApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phame/controller/PhameController.php b/src/applications/phame/controller/PhameController.php index fba717e8d9..0cfe877898 100644 --- a/src/applications/phame/controller/PhameController.php +++ b/src/applications/phame/controller/PhameController.php @@ -2,27 +2,6 @@ abstract class PhameController extends PhabricatorController { - protected function renderSideNavFilterView() { - - $base_uri = new PhutilURI($this->getApplicationURI()); - - $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI($base_uri); - - $nav->addLabel(pht('Posts')); - $nav->addFilter('post/all', pht('Latest Posts')); - $nav->addFilter('post/draft', pht('My Drafts')); - $nav->addFilter('post', pht('My Posts')); - - $nav->addLabel(pht('Blogs')); - $nav->addFilter('blog/user', pht('Joinable Blogs')); - $nav->addFilter('blog/all', pht('All Blogs')); - - $nav->selectFilter(null); - - return $nav; - } - protected function renderPostList( array $posts, PhabricatorUser $viewer, @@ -111,10 +90,6 @@ abstract class PhameController extends PhabricatorController { return $stories; } - public function buildApplicationMenu() { - return $this->renderSideNavFilterView()->getMenu(); - } - protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); $crumbs->addAction( diff --git a/src/applications/phame/controller/blog/PhameBlogController.php b/src/applications/phame/controller/blog/PhameBlogController.php new file mode 100644 index 0000000000..97152e5813 --- /dev/null +++ b/src/applications/phame/controller/blog/PhameBlogController.php @@ -0,0 +1,10 @@ +newApplicationMenu() + ->setSearchEngine(new PhameBlogSearchEngine()); + } + +} diff --git a/src/applications/phame/controller/blog/PhameBlogDeleteController.php b/src/applications/phame/controller/blog/PhameBlogDeleteController.php index 33282582ae..c60e27b2d7 100644 --- a/src/applications/phame/controller/blog/PhameBlogDeleteController.php +++ b/src/applications/phame/controller/blog/PhameBlogDeleteController.php @@ -1,13 +1,13 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -27,7 +27,7 @@ final class PhameBlogDeleteController extends PhameController { $cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/'); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Delete Blog?')) ->appendChild( pht( diff --git a/src/applications/phame/controller/blog/PhameBlogEditController.php b/src/applications/phame/controller/blog/PhameBlogEditController.php index 19862fbfbe..24c5681583 100644 --- a/src/applications/phame/controller/blog/PhameBlogEditController.php +++ b/src/applications/phame/controller/blog/PhameBlogEditController.php @@ -1,15 +1,15 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); if ($id) { $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -30,7 +30,7 @@ final class PhameBlogEditController $v_projects = array_reverse($v_projects); } else { - $blog = PhameBlog::initializeNewBlog($user); + $blog = PhameBlog::initializeNewBlog($viewer); $submit_button = pht('Create Blog'); $page_title = pht('Create Blog'); @@ -90,7 +90,7 @@ final class PhameBlogEditController ->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PhameBlogEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true); @@ -111,7 +111,7 @@ final class PhameBlogEditController } $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) + ->setViewer($viewer) ->setObject($blog) ->execute(); @@ -119,7 +119,7 @@ final class PhameBlogEditController $skins = mpull($skins, 'getName'); $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Name')) @@ -129,16 +129,16 @@ final class PhameBlogEditController ->setError($e_name)) ->appendChild( id(new PhabricatorRemarkupControl()) - ->setUser($user) + ->setUser($viewer) ->setLabel(pht('Description')) ->setName('description') ->setValue($description) ->setID('blog-description') - ->setUser($user) + ->setUser($viewer) ->setDisableMacros(true)) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicyObject($blog) ->setPolicies($policies) @@ -147,7 +147,7 @@ final class PhameBlogEditController ->setName('can_view')) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicyObject($blog) ->setPolicies($policies) @@ -155,7 +155,7 @@ final class PhameBlogEditController ->setName('can_edit')) ->appendChild( id(new AphrontFormPolicyControl()) - ->setUser($user) + ->setUser($viewer) ->setCapability(PhabricatorPolicyCapability::CAN_JOIN) ->setPolicyObject($blog) ->setPolicies($policies) @@ -195,13 +195,12 @@ final class PhameBlogEditController $crumbs->addTextCrumb(pht('Blogs'), $this->getApplicationURI('blog/')); $crumbs->addTextCrumb($page_title, $this->getApplicationURI('blog/new')); - return $this->buildApplicationPage( - array( - $crumbs, - $form_box, - ), - array( - 'title' => $page_title, + return $this->newPage() + ->setTitle($page_title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $form_box, )); } } diff --git a/src/applications/phame/controller/blog/PhameBlogFeedController.php b/src/applications/phame/controller/blog/PhameBlogFeedController.php index fc8c1c48da..0941555ed2 100644 --- a/src/applications/phame/controller/blog/PhameBlogFeedController.php +++ b/src/applications/phame/controller/blog/PhameBlogFeedController.php @@ -1,17 +1,17 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$blog) { @@ -19,7 +19,7 @@ final class PhameBlogFeedController extends PhameController { } $posts = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withBlogPHIDs(array($blog->getPHID())) ->withVisibility(PhamePost::VISIBILITY_PUBLISHED) ->execute(); @@ -47,7 +47,7 @@ final class PhameBlogFeedController extends PhameController { $content[] = phutil_tag('subtitle', array(), $description); } - $engine = id(new PhabricatorMarkupEngine())->setViewer($user); + $engine = id(new PhabricatorMarkupEngine())->setViewer($viewer); foreach ($posts as $post) { $engine->addObject($post, PhamePost::MARKUP_FIELD_BODY); } @@ -55,7 +55,7 @@ final class PhameBlogFeedController extends PhameController { $blogger_phids = mpull($posts, 'getBloggerPHID'); $bloggers = id(new PhabricatorHandleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs($blogger_phids) ->execute(); diff --git a/src/applications/phame/controller/blog/PhameBlogListController.php b/src/applications/phame/controller/blog/PhameBlogListController.php index 965e1eec49..c162b82b6b 100644 --- a/src/applications/phame/controller/blog/PhameBlogListController.php +++ b/src/applications/phame/controller/blog/PhameBlogListController.php @@ -1,6 +1,6 @@ getUser(); + $viewer = $request->getViewer(); $site = $request->getSite(); if ($site instanceof PhameBlogSite) { @@ -16,7 +16,7 @@ final class PhameBlogLiveController extends PhameController { $id = $request->getURIData('id'); $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$blog) { @@ -38,7 +38,7 @@ final class PhameBlogLiveController extends PhameController { $dialog = id(new AphrontDialogView()) ->setTitle(pht('Blog Moved')) - ->setUser($user) + ->setUser($viewer) ->appendParagraph(pht('This blog is now hosted here:')) ->appendParagraph( phutil_tag( diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index c8eddfbad3..03dfc8c1c6 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -1,13 +1,13 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$blog) { @@ -18,20 +18,20 @@ final class PhameBlogViewController extends PhameController { ->readFromRequest($request); $posts = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withBlogPHIDs(array($blog->getPHID())) ->executeWithCursorPager($pager); $header = id(new PHUIHeaderView()) ->setHeader($blog->getName()) - ->setUser($user) + ->setUser($viewer) ->setPolicyObject($blog); - $actions = $this->renderActions($blog, $user); - $properties = $this->renderProperties($blog, $user, $actions); + $actions = $this->renderActions($blog, $viewer); + $properties = $this->renderProperties($blog, $viewer, $actions); $post_list = $this->renderPostList( $posts, - $user, + $viewer, pht('This blog has no visible posts.')); $post_list = id(new PHUIObjectBoxView()) @@ -46,27 +46,26 @@ final class PhameBlogViewController extends PhameController { ->setHeader($header) ->addPropertyList($properties); - return $this->buildApplicationPage( - array( - $crumbs, - $object_box, - $post_list, - ), - array( - 'title' => $blog->getName(), + return $this->newPage() + ->setTitle($blog->getName()) + ->setCrumbs($crumbs) + ->appendChild( + array( + $object_box, + $post_list, )); } private function renderProperties( PhameBlog $blog, - PhabricatorUser $user, + PhabricatorUser $viewer, PhabricatorActionListView $actions) { require_celerity_resource('aphront-tooltip-css'); Javelin::initBehavior('phabricator-tooltips'); $properties = id(new PHUIPropertyListView()) - ->setUser($user) + ->setUser($viewer) ->setObject($blog) ->setActionList($actions); @@ -94,7 +93,7 @@ final class PhameBlogViewController extends PhameController { $feed_uri)); $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( - $user, + $viewer, $blog); $properties->addProperty( @@ -106,7 +105,7 @@ final class PhameBlogViewController extends PhameController { $descriptions[PhabricatorPolicyCapability::CAN_JOIN]); $engine = id(new PhabricatorMarkupEngine()) - ->setViewer($user) + ->setViewer($viewer) ->addObject($blog, PhameBlog::MARKUP_FIELD_DESCRIPTION) ->process(); @@ -116,7 +115,7 @@ final class PhameBlogViewController extends PhameController { $description = PhabricatorMarkupEngine::renderOneObject( id(new PhabricatorMarkupOneOff())->setContent($blog->getDescription()), 'default', - $user); + $viewer); $properties->addSectionHeader( pht('Description'), PHUIPropertyListView::ICON_SUMMARY); @@ -126,19 +125,19 @@ final class PhameBlogViewController extends PhameController { return $properties; } - private function renderActions(PhameBlog $blog, PhabricatorUser $user) { + private function renderActions(PhameBlog $blog, PhabricatorUser $viewer) { $actions = id(new PhabricatorActionListView()) ->setObject($blog) ->setObjectURI($this->getRequest()->getRequestURI()) - ->setUser($user); + ->setUser($viewer); $can_edit = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, $blog, PhabricatorPolicyCapability::CAN_EDIT); $can_join = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, $blog, PhabricatorPolicyCapability::CAN_JOIN); @@ -152,7 +151,7 @@ final class PhameBlogViewController extends PhameController { $actions->addAction( id(new PhabricatorActionView()) - ->setUser($user) + ->setUser($viewer) ->setIcon('fa-globe') ->setHref($blog->getLiveURI()) ->setName(pht('View Live'))); diff --git a/src/applications/phame/controller/post/PhamePostController.php b/src/applications/phame/controller/post/PhamePostController.php new file mode 100644 index 0000000000..c6ee2fb86b --- /dev/null +++ b/src/applications/phame/controller/post/PhamePostController.php @@ -0,0 +1,10 @@ +newApplicationMenu() + ->setSearchEngine(new PhamePostSearchEngine()); + } + +} diff --git a/src/applications/phame/controller/post/PhamePostDeleteController.php b/src/applications/phame/controller/post/PhamePostDeleteController.php index 80038edd1d..292fa6c18c 100644 --- a/src/applications/phame/controller/post/PhamePostDeleteController.php +++ b/src/applications/phame/controller/post/PhamePostDeleteController.php @@ -1,12 +1,12 @@ getUser(); + $viewer = $request->getViewer(); $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->requireCapabilities( array( @@ -26,7 +26,7 @@ final class PhamePostDeleteController extends PhameController { $cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/'); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Delete Post?')) ->appendChild( pht( diff --git a/src/applications/phame/controller/post/PhamePostEditController.php b/src/applications/phame/controller/post/PhamePostEditController.php index e79d435deb..3de92906a8 100644 --- a/src/applications/phame/controller/post/PhamePostEditController.php +++ b/src/applications/phame/controller/post/PhamePostEditController.php @@ -1,14 +1,14 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); if ($id) { $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -29,7 +29,7 @@ final class PhamePostEditController extends PhameController { $v_projects = array_reverse($v_projects); } else { $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getInt('blog'))) ->requireCapabilities( array( @@ -42,7 +42,7 @@ final class PhamePostEditController extends PhameController { } $v_projects = array(); - $post = PhamePost::initializePost($user, $blog); + $post = PhamePost::initializePost($viewer, $blog); $cancel_uri = $this->getApplicationURI('/blog/view/'.$blog->getID().'/'); $submit_button = pht('Save Draft'); @@ -87,7 +87,7 @@ final class PhamePostEditController extends PhameController { ->setNewValue(array('=' => array_fuse($v_projects))); $editor = id(new PhamePostEditor()) - ->setActor($user) + ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true); @@ -106,12 +106,12 @@ final class PhamePostEditController extends PhameController { } $handle = id(new PhabricatorHandleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs(array($post->getBlogPHID())) ->executeOne(); $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->addHiddenInput('blog', $request->getInt('blog')) ->appendChild( id(new AphrontFormMarkupControl()) @@ -141,7 +141,7 @@ final class PhamePostEditController extends PhameController { ->setValue($body) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) ->setID('post-body') - ->setUser($user) + ->setUser($viewer) ->setDisableMacros(true)) ->appendControl( id(new AphrontFormTokenizerControl()) @@ -160,14 +160,18 @@ final class PhamePostEditController extends PhameController { ->addCancelButton($cancel_uri) ->setValue($submit_button)); - $loading = phutil_tag_div( - 'aphront-panel-preview-loading-text', - pht('Loading preview...')); + $header = id(new PHUIHeaderView()) + ->setHeader(pht('%s (Post Preview)', $title)); - $preview_panel = phutil_tag_div('aphront-panel-preview', array( - phutil_tag_div('phame-post-preview-header', pht('Post Preview')), - phutil_tag('div', array('id' => 'post-preview'), $loading), - )); + $container = id(new PHUIBoxView()) + ->setID('post-preview'); + + $document = id(new PHUIDocumentViewPro()) + ->setHeader($header) + ->appendChild($container); + + $preview_panel = id(new PHUIObjectBoxView()) + ->appendChild($document); Javelin::initBehavior( 'phame-post-preview', @@ -189,14 +193,13 @@ final class PhamePostEditController extends PhameController { $page_title, $this->getApplicationURI('/post/view/'.$id.'/')); - return $this->buildApplicationPage( - array( - $crumbs, - $form_box, - $preview_panel, - ), - array( - 'title' => $page_title, + return $this->newPage() + ->setTitle($page_title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $form_box, + $preview_panel, )); } diff --git a/src/applications/phame/controller/post/PhamePostFramedController.php b/src/applications/phame/controller/post/PhamePostFramedController.php index 46f723aa81..180eca0849 100644 --- a/src/applications/phame/controller/post/PhamePostFramedController.php +++ b/src/applications/phame/controller/post/PhamePostFramedController.php @@ -1,13 +1,13 @@ getViewer(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( diff --git a/src/applications/phame/controller/post/PhamePostListController.php b/src/applications/phame/controller/post/PhamePostListController.php index fb38a830bb..71e73f1dc6 100644 --- a/src/applications/phame/controller/post/PhamePostListController.php +++ b/src/applications/phame/controller/post/PhamePostListController.php @@ -1,6 +1,6 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $post = null; $view_uri = null; if ($id) { $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -26,7 +26,7 @@ final class PhamePostNewController extends PhameController { if ($request->isFormPost()) { $blog = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getInt('blog'))) ->requireCapabilities( array( @@ -49,7 +49,7 @@ final class PhamePostNewController extends PhameController { } $blogs = id(new PhameBlogQuery()) - ->setViewer($user) + ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_JOIN, @@ -58,9 +58,9 @@ final class PhamePostNewController extends PhameController { $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title, $view_uri); - $display = array(); - $display[] = $crumbs; + $notification = null; + $form_box = null; if (!$blogs) { $notification = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) @@ -68,7 +68,6 @@ final class PhamePostNewController extends PhameController { pht('You do not have permission to join any blogs. Create a blog '. 'first, then you can post to it.')); - $display[] = $notification; } else { $options = mpull($blogs, 'getName', 'getID'); asort($options); @@ -79,7 +78,7 @@ final class PhamePostNewController extends PhameController { } $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Blog')) @@ -102,19 +101,20 @@ final class PhamePostNewController extends PhameController { ->setValue(pht('Continue'))); } - $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setForm($form); - - $display[] = $form_box; } - return $this->buildApplicationPage( - $display, - array( - 'title' => $title, + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $notification, + $form_box, )); - } + + } } diff --git a/src/applications/phame/controller/post/PhamePostNotLiveController.php b/src/applications/phame/controller/post/PhamePostNotLiveController.php index 3f69860003..c0f986ffda 100644 --- a/src/applications/phame/controller/post/PhamePostNotLiveController.php +++ b/src/applications/phame/controller/post/PhamePostNotLiveController.php @@ -1,13 +1,13 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$post) { @@ -32,7 +32,7 @@ final class PhamePostNotLiveController extends PhameController { $cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/'); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Post Not Live')) ->addCancelButton($cancel_uri); diff --git a/src/applications/phame/controller/post/PhamePostPreviewController.php b/src/applications/phame/controller/post/PhamePostPreviewController.php index 5b87ec680b..3f81481576 100644 --- a/src/applications/phame/controller/post/PhamePostPreviewController.php +++ b/src/applications/phame/controller/post/PhamePostPreviewController.php @@ -1,15 +1,14 @@ getRequest(); - $user = $request->getUser(); - $body = $request->getStr('body'); + public function handleRequest(AphrontRequest $request) { + $viewer = $request->getViewer(); + $body = $request->getStr('body'); $post = id(new PhamePost()) ->setBody($body); @@ -17,7 +16,7 @@ final class PhamePostPreviewController extends PhameController { $content = PhabricatorMarkupEngine::renderOneObject( $post, PhamePost::MARKUP_FIELD_BODY, - $user); + $viewer); $content = phutil_tag_div('phabricator-remarkup', $content); diff --git a/src/applications/phame/controller/post/PhamePostPublishController.php b/src/applications/phame/controller/post/PhamePostPublishController.php index 1b3cac79a4..6ca8ff5d54 100644 --- a/src/applications/phame/controller/post/PhamePostPublishController.php +++ b/src/applications/phame/controller/post/PhamePostPublishController.php @@ -1,13 +1,13 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -29,7 +29,7 @@ final class PhamePostPublishController extends PhameController { } $form = id(new AphrontFormView()) - ->setUser($user) + ->setUser($viewer) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Publish Post')) @@ -44,35 +44,30 @@ final class PhamePostPublishController extends PhameController { $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Preview'), $view_uri); - $nav = $this->renderSideNavFilterView(null); - $nav->appendChild( - array( - $crumbs, - $form_box, - $frame, - )); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => pht('Preview Post'), + return $this->newPage() + ->setTitle(pht('Preview Post')) + ->setCrumbs($crumbs) + ->appendChild( + array( + $form_box, + $frame, )); } private function renderPreviewFrame(PhamePost $post) { - // TODO: Clean up this CSS. - return phutil_tag( 'div', array( - 'style' => 'text-align: center; padding: 1em;', + 'style' => 'text-align: center; padding: 16px;', ), phutil_tag( 'iframe', array( 'style' => 'width: 100%; height: 600px; '. - 'border: 1px solid #303030;', + 'border: 1px solid #BFCFDA; '. + 'background-color: #fff; '. + 'border-radius: 3px; ', 'src' => $this->getApplicationURI('/post/framed/'.$post->getID().'/'), ), '')); diff --git a/src/applications/phame/controller/post/PhamePostUnpublishController.php b/src/applications/phame/controller/post/PhamePostUnpublishController.php index e2634e710e..80a320344d 100644 --- a/src/applications/phame/controller/post/PhamePostUnpublishController.php +++ b/src/applications/phame/controller/post/PhamePostUnpublishController.php @@ -1,13 +1,13 @@ getUser(); + $viewer = $request->getViewer(); $id = $request->getURIData('id'); $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( @@ -30,7 +30,7 @@ final class PhamePostUnpublishController extends PhameController { $cancel_uri = $this->getApplicationURI('/post/view/'.$post->getID().'/'); $dialog = id(new AphrontDialogView()) - ->setUser($user) + ->setUser($viewer) ->setTitle(pht('Unpublish Post?')) ->appendChild( pht( diff --git a/src/applications/phame/controller/post/PhamePostViewController.php b/src/applications/phame/controller/post/PhamePostViewController.php index 1b2b8c1a3c..3afdf5401d 100644 --- a/src/applications/phame/controller/post/PhamePostViewController.php +++ b/src/applications/phame/controller/post/PhamePostViewController.php @@ -1,12 +1,12 @@ getUser(); + $viewer = $request->getViewer(); $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->executeOne(); @@ -14,29 +14,35 @@ final class PhamePostViewController extends PhameController { return new Aphront404Response(); } - $nav = $this->renderSideNavFilterView(); - - $actions = $this->renderActions($post, $user); - $properties = $this->renderProperties($post, $user, $actions); - $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( $post->getTitle(), $this->getApplicationURI('post/view/'.$post->getID().'/')); + $crumbs->setBorder(true); - $nav->appendChild($crumbs); + $actions = $this->renderActions($post, $viewer); + $properties = $this->renderProperties($post, $viewer); + + $action_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText(pht('Actions')) + ->setHref('#') + ->setIconFont('fa-bars') + ->addClass('phui-mobile-menu') + ->setDropdownMenu($actions); $header = id(new PHUIHeaderView()) - ->setHeader($post->getTitle()) - ->setUser($user) - ->setPolicyObject($post); + ->setHeader($post->getTitle()) + ->setUser($viewer) + ->setPolicyObject($post) + ->addActionLink($action_button); - $object_box = id(new PHUIObjectBoxView()) + $document = id(new PHUIDocumentViewPro()) ->setHeader($header) - ->addPropertyList($properties); + ->setPropertyList($properties); if ($post->isDraft()) { - $object_box->appendChild( + $document->appendChild( id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setTitle(pht('Draft Post')) @@ -47,7 +53,7 @@ final class PhamePostViewController extends PhameController { } if (!$post->getBlog()) { - $object_box->appendChild( + $document->appendChild( id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setTitle(pht('Not On A Blog')) @@ -57,32 +63,40 @@ final class PhamePostViewController extends PhameController { 'been deleted). Use "Move Post" to move it to a new blog.'))); } - $nav->appendChild( - array( - $object_box, - $this->buildTransactionTimeline( - $post, - new PhamePostTransactionQuery()), - )); + $engine = id(new PhabricatorMarkupEngine()) + ->setViewer($viewer) + ->addObject($post, PhamePost::MARKUP_FIELD_BODY) + ->process(); - return $this->buildApplicationPage( - $nav, - array( - 'title' => $post->getTitle(), + $document->appendChild( + phutil_tag( + 'div', + array( + 'class' => 'phabricator-remarkup', + ), + $engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY))); + + return $this->newPage() + ->setTitle($post->getTitle()) + ->addClass('pro-white-background') + ->setCrumbs($crumbs) + ->appendChild( + array( + $document, )); } private function renderActions( PhamePost $post, - PhabricatorUser $user) { + PhabricatorUser $viewer) { $actions = id(new PhabricatorActionListView()) ->setObject($post) ->setObjectURI($this->getRequest()->getRequestURI()) - ->setUser($user); + ->setUser($viewer); $can_edit = PhabricatorPolicyFilter::hasCapability( - $user, + $viewer, $post, PhabricatorPolicyCapability::CAN_EDIT); @@ -139,7 +153,7 @@ final class PhamePostViewController extends PhameController { $actions->addAction( id(new PhabricatorActionView()) - ->setUser($user) + ->setUser($viewer) ->setIcon('fa-globe') ->setHref($live_uri) ->setName(pht('View Live')) @@ -151,43 +165,28 @@ final class PhamePostViewController extends PhameController { private function renderProperties( PhamePost $post, - PhabricatorUser $user, - PhabricatorActionListView $actions) { + PhabricatorUser $viewer) { $properties = id(new PHUIPropertyListView()) - ->setUser($user) - ->setObject($post) - ->setActionList($actions); + ->setUser($viewer) + ->setObject($post); $properties->addProperty( pht('Blog'), - $user->renderHandle($post->getBlogPHID())); + $viewer->renderHandle($post->getBlogPHID())); $properties->addProperty( pht('Blogger'), - $user->renderHandle($post->getBloggerPHID())); + $viewer->renderHandle($post->getBloggerPHID())); $properties->addProperty( pht('Published'), $post->isDraft() ? pht('Draft') - : phabricator_datetime($post->getDatePublished(), $user)); - - $engine = id(new PhabricatorMarkupEngine()) - ->setViewer($user) - ->addObject($post, PhamePost::MARKUP_FIELD_BODY) - ->process(); + : phabricator_datetime($post->getDatePublished(), $viewer)); $properties->invokeWillRenderEvent(); - $properties->addTextContent( - phutil_tag( - 'div', - array( - 'class' => 'phabricator-remarkup', - ), - $engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY))); - return $properties; } diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php index 289b55cf57..d665d92541 100644 --- a/src/applications/phame/editor/PhameBlogEditor.php +++ b/src/applications/phame/editor/PhameBlogEditor.php @@ -8,7 +8,7 @@ final class PhameBlogEditor } public function getEditorObjectsDescription() { - return pht('Blogs'); + return pht('Phame Blogs'); } public function getTransactionTypes() { diff --git a/src/applications/phame/editor/PhamePostEditor.php b/src/applications/phame/editor/PhamePostEditor.php index ef6cd21307..ab4b1a1465 100644 --- a/src/applications/phame/editor/PhamePostEditor.php +++ b/src/applications/phame/editor/PhamePostEditor.php @@ -8,7 +8,7 @@ final class PhamePostEditor } public function getEditorObjectsDescription() { - return pht('Blog Posts'); + return pht('Phame Posts'); } public function getTransactionTypes() { @@ -149,13 +149,74 @@ final class PhamePostEditor protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { - return false; + if ($object->isDraft()) { + return false; + } + return true; } protected function shouldPublishFeedStory( PhabricatorLiskDAO $object, array $xactions) { - return false; + if ($object->isDraft()) { + return false; + } + return true; + } + + protected function getMailTo(PhabricatorLiskDAO $object) { + $phids = array(); + $phids[] = $object->getBloggerPHID(); + $phids[] = $this->requireActor()->getPHID(); + + $blog_phid = $object->getBlogPHID(); + if ($blog_phid) { + $phids[] = PhabricatorSubscribersQuery::loadSubscribersForPHID( + $blog_phid); + } + return $phids; + } + + protected function buildMailTemplate(PhabricatorLiskDAO $object) { + $phid = $object->getPHID(); + $title = $object->getTitle(); + + return id(new PhabricatorMetaMTAMail()) + ->setSubject($title) + ->addHeader('Thread-Topic', $phid); + } + + protected function buildReplyHandler(PhabricatorLiskDAO $object) { + return id(new PhamePostReplyHandler()) + ->setMailReceiver($object); + } + + protected function buildMailBody( + PhabricatorLiskDAO $object, + array $xactions) { + + $body = parent::buildMailBody($object, $xactions); + + $body->addLinkSection( + pht('POST DETAIL'), + PhabricatorEnv::getProductionURI($object->getViewURI())); + + return $body; + } + + public function getMailTagsMap() { + return array( + PhamePostTransaction::MAILTAG_CONTENT => + pht("A post's content changes."), + PhamePostTransaction::MAILTAG_COMMENT => + pht('Someone comments on a post.'), + PhamePostTransaction::MAILTAG_OTHER => + pht('Other post activity not listed above occurs.'), + ); + } + + protected function getMailSubjectPrefix() { + return '[Phame]'; } protected function supportsSearch() { diff --git a/src/applications/phame/mail/PhamePostReplyHandler.php b/src/applications/phame/mail/PhamePostReplyHandler.php new file mode 100644 index 0000000000..f994763709 --- /dev/null +++ b/src/applications/phame/mail/PhamePostReplyHandler.php @@ -0,0 +1,21 @@ + pht('All'), + 'all' => pht('All Blogs'), ); return $names; } diff --git a/src/applications/phame/query/PhamePostSearchEngine.php b/src/applications/phame/query/PhamePostSearchEngine.php index cedc02cc7a..d832b08192 100644 --- a/src/applications/phame/query/PhamePostSearchEngine.php +++ b/src/applications/phame/query/PhamePostSearchEngine.php @@ -44,9 +44,9 @@ final class PhamePostSearchEngine protected function getBuiltinQueryNames() { $names = array( - 'all' => pht('All'), - 'live' => pht('Live'), - 'draft' => pht('Draft'), + 'all' => pht('All Posts'), + 'live' => pht('Live Posts'), + 'draft' => pht('Draft Posts'), ); return $names; } diff --git a/src/applications/phame/skins/PhameBasicBlogSkin.php b/src/applications/phame/skins/PhameBasicBlogSkin.php index efaa85ec8a..5ba8d0999b 100644 --- a/src/applications/phame/skins/PhameBasicBlogSkin.php +++ b/src/applications/phame/skins/PhameBasicBlogSkin.php @@ -16,6 +16,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $this->uriPath = $uri_path; return $this; } + public function getURIPath() { return $this->uriPath; } @@ -24,6 +25,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $this->oGType = $og_type; return $this; } + protected function getOGType() { return $this->oGType; } @@ -32,6 +34,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $this->description = $description; return $this; } + protected function getDescription() { return $this->description; } @@ -40,13 +43,12 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $this->title = $title; return $this; } + protected function getTitle() { return $this->title; } - public function processRequest() { - $request = $this->getRequest(); - + public function handleRequest(AphrontRequest $request) { $content = $this->renderContent($request); if (!$content) { @@ -69,7 +71,6 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $view->setFrameable(true); } - $view->appendChild($content); $response = new AphrontWebpageResponse(); @@ -222,7 +223,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { * @task internal */ protected function renderContent(AphrontRequest $request) { - $user = $request->getUser(); + $viewer = $request->getViewer(); $matches = null; $path = $request->getPath(); @@ -233,7 +234,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $this->setURIPath(''); if (preg_match('@^/post/(?P.*)$@', $path, $matches)) { $post = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withBlogPHIDs(array($this->getBlog()->getPHID())) ->withPhameTitles(array($matches['name'])) ->executeOne(); @@ -263,7 +264,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $pager->setPageSize($this->getPageSize()); $posts = id(new PhamePostQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withBlogPHIDs(array($this->getBlog()->getPHID())) ->executeWithCursorPager($pager); @@ -280,10 +281,10 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { private function buildPostViews(array $posts) { assert_instances_of($posts, 'PhamePost'); - $user = $this->getRequest()->getUser(); + $viewer = $this->getViewer(); $engine = id(new PhabricatorMarkupEngine()) - ->setViewer($user); + ->setViewer($viewer); $phids = array(); foreach ($posts as $post) { @@ -294,7 +295,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { } $handles = id(new PhabricatorHandleQuery()) - ->setViewer($user) + ->setViewer($viewer) ->withPHIDs($phids) ->execute(); @@ -303,7 +304,7 @@ abstract class PhameBasicBlogSkin extends PhameBlogSkin { $views = array(); foreach ($posts as $post) { $view = id(new PhamePostView()) - ->setUser($user) + ->setUser($viewer) ->setSkin($this) ->setPost($post) ->setBody($engine->getOutput($post, PhamePost::MARKUP_FIELD_BODY)) diff --git a/src/applications/phame/skins/PhameBasicTemplateBlogSkin.php b/src/applications/phame/skins/PhameBasicTemplateBlogSkin.php index 5b4c802c6f..f473eedd49 100644 --- a/src/applications/phame/skins/PhameBasicTemplateBlogSkin.php +++ b/src/applications/phame/skins/PhameBasicTemplateBlogSkin.php @@ -27,15 +27,26 @@ final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin { } $map = CelerityResourceMap::getNamedInstance('phabricator'); - $resource_symbol = 'syntax-highlighting-css'; - $resource_uri = $map->getURIForSymbol($resource_symbol); + $highlight_symbol = 'syntax-highlighting-css'; + $highlight_uri = $map->getURIForSymbol($highlight_symbol); $this->cssResources[] = phutil_tag( 'link', array( 'rel' => 'stylesheet', 'type' => 'text/css', - 'href' => PhabricatorEnv::getCDNURI($resource_uri), + 'href' => PhabricatorEnv::getCDNURI($highlight_uri), + )); + + $remarkup_symbol = 'phabricator-remarkup-css'; + $remarkup_uri = $map->getURIForSymbol($remarkup_symbol); + + $this->cssResources[] = phutil_tag( + 'link', + array( + 'rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => PhabricatorEnv::getCDNURI($remarkup_uri), )); $this->cssResources = phutil_implode_html("\n", $this->cssResources); @@ -68,6 +79,12 @@ final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin { return $this->cssResources; } + public function remarkup($corpus) { + $view = id(new PHUIRemarkupView($this->getViewer(), $corpus)); + + return hsprintf('%s', $view); + } + public function getName() { return $this->getSpecification()->getName(); } @@ -96,13 +113,16 @@ final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin { private function getDefaultScope() { return array( - 'skin' => $this, - 'blog' => $this->getBlog(), - 'uri' => $this->getURI($this->getURIPath()), - 'home_uri' => $this->getURI(''), - 'title' => $this->getTitle(), + 'skin' => $this, + 'blog' => $this->getBlog(), + 'uri' => $this->getURI($this->getURIPath()), + 'home_uri' => $this->getURI(''), + + // TODO: This is wrong for detail pages, which should show the post + // title, but getting it right is a pain and this is better than nothing. + 'title' => $this->getBlog()->getName(), 'description' => $this->getDescription(), - 'og_type' => $this->getOGType(), + 'og_type' => $this->getOGType(), ); } @@ -124,7 +144,7 @@ final class PhameBasicTemplateBlogSkin extends PhameBasicBlogSkin { return $this->renderTemplate( 'post-detail.php', array( - 'post' => $post, + 'post' => $post, )); } diff --git a/src/applications/phame/storage/PhamePost.php b/src/applications/phame/storage/PhamePost.php index afbb4e8e16..eecb27b566 100644 --- a/src/applications/phame/storage/PhamePost.php +++ b/src/applications/phame/storage/PhamePost.php @@ -24,6 +24,7 @@ final class PhamePost extends PhameDAO protected $configData; protected $datePublished; protected $blogPHID; + protected $mailKey; private $blog; @@ -102,6 +103,7 @@ final class PhamePost extends PhameDAO 'title' => 'text255', 'phameTitle' => 'sort64', 'visibility' => 'uint32', + 'mailKey' => 'bytes20', // T6203/NULLABILITY // These seem like they should always be non-null? @@ -135,6 +137,13 @@ final class PhamePost extends PhameDAO ) + parent::getConfiguration(); } + public function save() { + if (!$this->getMailKey()) { + $this->setMailKey(Filesystem::readRandomCharacters(20)); + } + return parent::save(); + } + public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPhamePostPHIDType::TYPECONST); diff --git a/src/applications/phame/storage/PhamePostTransaction.php b/src/applications/phame/storage/PhamePostTransaction.php index 04841cda9f..38910c9845 100644 --- a/src/applications/phame/storage/PhamePostTransaction.php +++ b/src/applications/phame/storage/PhamePostTransaction.php @@ -3,10 +3,14 @@ final class PhamePostTransaction extends PhabricatorApplicationTransaction { - const TYPE_TITLE = 'phame.post.title'; - const TYPE_PHAME_TITLE = 'phame.post.phame.title'; - const TYPE_BODY = 'phame.post.body'; - const TYPE_COMMENTS_WIDGET = 'phame.post.comments.widget'; + const TYPE_TITLE = 'phame.post.title'; + const TYPE_PHAME_TITLE = 'phame.post.phame.title'; + const TYPE_BODY = 'phame.post.body'; + const TYPE_COMMENTS_WIDGET = 'phame.post.comments.widget'; + + const MAILTAG_CONTENT = 'phame-post-content'; + const MAILTAG_COMMENT = 'phame-post-comment'; + const MAILTAG_OTHER = 'phame-post-other'; public function getApplicationName() { return 'phame'; @@ -57,6 +61,27 @@ final class PhamePostTransaction return parent::getIcon(); } + public function getMailTags() { + $tags = parent::getMailTags(); + + switch ($this->getTransactionType()) { + case self::TYPE_COMMENTS_WIDGET: + case PhabricatorTransactions::TYPE_COMMENT: + $tags[] = self::MAILTAG_COMMENT; + break; + case self::TYPE_TITLE: + case self::TYPE_PHAME_TITLE: + case self::TYPE_BODY: + $tags[] = self::MAILTAG_CONTENT; + break; + default: + $tags[] = self::MAILTAG_OTHER; + break; + } + return $tags; + } + + public function getTitle() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); @@ -69,7 +94,7 @@ final class PhamePostTransaction case self::TYPE_TITLE: if ($old === null) { return pht( - '%s created this post.', + '%s authored this post.', $this->renderHandleLink($author_phid)); } else { return pht( @@ -80,12 +105,12 @@ final class PhamePostTransaction break; case self::TYPE_BODY: return pht( - '%s updated the post\'s body.', + '%s updated the blog post.', $this->renderHandleLink($author_phid)); break; case self::TYPE_PHAME_TITLE: return pht( - '%s updated the post\'s phame title to "%s".', + '%s updated the post\'s Phame title to "%s".', $this->renderHandleLink($author_phid), rtrim($new, '/')); break; @@ -112,7 +137,7 @@ final class PhamePostTransaction case self::TYPE_TITLE: if ($old === null) { return pht( - '%s created %s.', + '%s authored %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } else { @@ -124,13 +149,13 @@ final class PhamePostTransaction break; case self::TYPE_BODY: return pht( - '%s updated the body for %s.', + '%s updated the blog post %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; case self::TYPE_PHAME_TITLE: return pht( - '%s updated the phame title for %s.', + '%s updated the Phame title for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); break; @@ -145,6 +170,23 @@ final class PhamePostTransaction return parent::getTitleForFeed(); } + public function getBodyForFeed(PhabricatorFeedStory $story) { + $new = $this->getNewValue(); + + $body = null; + + switch ($this->getTransactionType()) { + case self::TYPE_TITLE: + case self::TYPE_BODY: + return phutil_escape_html_newlines( + id(new PhutilUTF8StringTruncator()) + ->setMaximumGlyphs(128) + ->truncateString($new)); + break; + } + return parent::getBodyForFeed($story); + } + public function getColor() { $old = $this->getOldValue(); diff --git a/src/applications/phame/view/PhamePostView.php b/src/applications/phame/view/PhamePostView.php index f35125f255..9fef145e02 100644 --- a/src/applications/phame/view/PhamePostView.php +++ b/src/applications/phame/view/PhamePostView.php @@ -87,7 +87,7 @@ final class PhamePostView extends AphrontView { return phutil_tag( 'div', array( - 'class' => 'phame-post-body', + 'class' => 'phame-post-body phabricator-remarkup', ), $this->getBody()); } @@ -96,7 +96,7 @@ final class PhamePostView extends AphrontView { return phutil_tag( 'div', array( - 'class' => 'phame-post-body', + 'class' => 'phame-post-body phabricator-remarkup', ), $this->getSummary()); } diff --git a/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php index 1069b35793..93d8a47de7 100644 --- a/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php +++ b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php @@ -9,10 +9,6 @@ final class PhabricatorMetaMTAApplicationEmailPHIDType return pht('Application Email'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorMetaMTAApplication'; - } - public function getTypeIcon() { return 'fa-email bluegrey'; } @@ -21,6 +17,10 @@ final class PhabricatorMetaMTAApplicationEmailPHIDType return new PhabricatorMetaMTAApplicationEmail(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorMetaMTAApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phid/resolver/PhabricatorPHIDResolver.php b/src/applications/phid/resolver/PhabricatorPHIDResolver.php new file mode 100644 index 0000000000..9070139a0b --- /dev/null +++ b/src/applications/phid/resolver/PhabricatorPHIDResolver.php @@ -0,0 +1,46 @@ +viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + final public function resolvePHIDs(array $phids) { + $type_unknown = PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN; + + $names = array(); + foreach ($phids as $key => $phid) { + if (phid_get_type($phid) == $type_unknown) { + $names[$key] = $phid; + } + } + + if ($names) { + $map = $this->getResolutionMap($names); + foreach ($names as $key => $name) { + if (isset($map[$name])) { + $phids[$key] = $map[$name]; + } + } + } + + return $phids; + } + + abstract protected function getResolutionMap(array $names); + +} diff --git a/src/applications/phid/resolver/PhabricatorProjectPHIDResolver.php b/src/applications/phid/resolver/PhabricatorProjectPHIDResolver.php new file mode 100644 index 0000000000..7abecd730b --- /dev/null +++ b/src/applications/phid/resolver/PhabricatorProjectPHIDResolver.php @@ -0,0 +1,28 @@ + $name) { + $names[$key] = '#'.$name; + } + + $query = id(new PhabricatorObjectQuery()) + ->setViewer($this->getViewer()); + + $projects = id(new PhabricatorProjectProjectPHIDType()) + ->loadNamedObjects($query, $names); + + $results = array(); + foreach ($projects as $hashtag => $project) { + $results[substr($hashtag, 1)] = $project->getPHID(); + } + + return $results; + } + +} diff --git a/src/applications/phid/resolver/PhabricatorUserPHIDResolver.php b/src/applications/phid/resolver/PhabricatorUserPHIDResolver.php new file mode 100644 index 0000000000..a2a75fe310 --- /dev/null +++ b/src/applications/phid/resolver/PhabricatorUserPHIDResolver.php @@ -0,0 +1,27 @@ + $name) { + $names[$key] = '@'.$name; + } + + $query = id(new PhabricatorObjectQuery()) + ->setViewer($this->getViewer()); + + $users = id(new PhabricatorPeopleUserPHIDType()) + ->loadNamedObjects($query, $names); + + $results = array(); + foreach ($users as $at_username => $user) { + $results[substr($at_username, 1)] = $user->getPHID(); + } + + return $results; + } + +} diff --git a/src/applications/phid/type/PhabricatorPHIDType.php b/src/applications/phid/type/PhabricatorPHIDType.php index a8502b12f7..e39ff5f562 100644 --- a/src/applications/phid/type/PhabricatorPHIDType.php +++ b/src/applications/phid/type/PhabricatorPHIDType.php @@ -20,10 +20,6 @@ abstract class PhabricatorPHIDType extends Phobject { abstract public function getTypeName(); - public function newObject() { - return null; - } - public function getTypeIcon() { // Default to the application icon if the type doesn't specify one. $application_class = $this->getPHIDTypeApplicationClass(); @@ -35,6 +31,10 @@ abstract class PhabricatorPHIDType extends Phobject { return null; } + public function newObject() { + return null; + } + /** * Get the class name for the application this type belongs to. @@ -42,12 +42,7 @@ abstract class PhabricatorPHIDType extends Phobject { * @return string|null Class name of the corresponding application, or null * if the type is not bound to an application. */ - public function getPHIDTypeApplicationClass() { - // TODO: Some day this should probably be abstract, but for now it only - // affects global search and there's no real burning need to go classify - // every PHID type. - return null; - } + abstract public function getPHIDTypeApplicationClass(); /** * Build a @{class:PhabricatorPolicyAwareQuery} to load objects of this type diff --git a/src/applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php b/src/applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php index e7707095ad..ec2d932047 100644 --- a/src/applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php +++ b/src/applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php @@ -7,4 +7,16 @@ final class PhabricatorPHIDTypeTestCase extends PhutilTestCase { $this->assertTrue(true); } + public function testGetPHIDTypeApplicationClass() { + $types = PhabricatorPHIDType::getAllTypes(); + + foreach ($types as $type) { + $application_class = $type->getPHIDTypeApplicationClass(); + + if ($application_class !== null) { + $this->assertTrue(class_exists($application_class)); + } + } + } + } diff --git a/src/applications/phlux/phid/PhluxVariablePHIDType.php b/src/applications/phlux/phid/PhluxVariablePHIDType.php index 643025fd9c..97525c4052 100644 --- a/src/applications/phlux/phid/PhluxVariablePHIDType.php +++ b/src/applications/phlux/phid/PhluxVariablePHIDType.php @@ -12,6 +12,10 @@ final class PhluxVariablePHIDType extends PhabricatorPHIDType { return new PhluxVariable(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhluxApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/pholio/phid/PholioImagePHIDType.php b/src/applications/pholio/phid/PholioImagePHIDType.php index 9278977b77..b28dbd64d5 100644 --- a/src/applications/pholio/phid/PholioImagePHIDType.php +++ b/src/applications/pholio/phid/PholioImagePHIDType.php @@ -12,6 +12,10 @@ final class PholioImagePHIDType extends PhabricatorPHIDType { return new PholioImage(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPholioApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/pholio/phid/PholioMockPHIDType.php b/src/applications/pholio/phid/PholioMockPHIDType.php index e41f326e94..13ee4cb81f 100644 --- a/src/applications/pholio/phid/PholioMockPHIDType.php +++ b/src/applications/pholio/phid/PholioMockPHIDType.php @@ -8,14 +8,14 @@ final class PholioMockPHIDType extends PhabricatorPHIDType { return pht('Pholio Mock'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorPholioApplication'; - } - public function newObject() { return new PholioMock(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPholioApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/pholio/view/PholioMockThumbGridView.php b/src/applications/pholio/view/PholioMockThumbGridView.php index d7d174d928..6467106c14 100644 --- a/src/applications/pholio/view/PholioMockThumbGridView.php +++ b/src/applications/pholio/view/PholioMockThumbGridView.php @@ -156,7 +156,7 @@ final class PholioMockThumbGridView extends AphrontView { array( 'class' => 'pholio-mock-thumb-grid-comment-count', ), - pht('%s', new PhutilNumber(count($image->getInlineComments())))); + pht('%s', phutil_count($image->getInlineComments()))); } return javelin_tag( diff --git a/src/applications/phortune/phid/PhortuneAccountPHIDType.php b/src/applications/phortune/phid/PhortuneAccountPHIDType.php index b9d1bee1a6..cf5f5d06f2 100644 --- a/src/applications/phortune/phid/PhortuneAccountPHIDType.php +++ b/src/applications/phortune/phid/PhortuneAccountPHIDType.php @@ -12,6 +12,10 @@ final class PhortuneAccountPHIDType extends PhabricatorPHIDType { return new PhortuneAccount(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortuneCartPHIDType.php b/src/applications/phortune/phid/PhortuneCartPHIDType.php index f42e563cee..c805a4a921 100644 --- a/src/applications/phortune/phid/PhortuneCartPHIDType.php +++ b/src/applications/phortune/phid/PhortuneCartPHIDType.php @@ -12,6 +12,10 @@ final class PhortuneCartPHIDType extends PhabricatorPHIDType { return new PhortuneCart(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortuneChargePHIDType.php b/src/applications/phortune/phid/PhortuneChargePHIDType.php index b88a605d0c..013db6ab1c 100644 --- a/src/applications/phortune/phid/PhortuneChargePHIDType.php +++ b/src/applications/phortune/phid/PhortuneChargePHIDType.php @@ -12,6 +12,10 @@ final class PhortuneChargePHIDType extends PhabricatorPHIDType { return new PhortuneCharge(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortuneMerchantPHIDType.php b/src/applications/phortune/phid/PhortuneMerchantPHIDType.php index a1b8b73871..941f704ab8 100644 --- a/src/applications/phortune/phid/PhortuneMerchantPHIDType.php +++ b/src/applications/phortune/phid/PhortuneMerchantPHIDType.php @@ -12,6 +12,10 @@ final class PhortuneMerchantPHIDType extends PhabricatorPHIDType { return new PhortuneMerchant(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php b/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php index 2df0a0acd5..7906f87414 100644 --- a/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php +++ b/src/applications/phortune/phid/PhortunePaymentMethodPHIDType.php @@ -12,6 +12,10 @@ final class PhortunePaymentMethodPHIDType extends PhabricatorPHIDType { return new PhortunePaymentMethod(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php b/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php index 7391e71108..dc96d08648 100644 --- a/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php +++ b/src/applications/phortune/phid/PhortunePaymentProviderPHIDType.php @@ -12,6 +12,10 @@ final class PhortunePaymentProviderPHIDType extends PhabricatorPHIDType { return new PhortunePaymentProviderConfig(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortuneProductPHIDType.php b/src/applications/phortune/phid/PhortuneProductPHIDType.php index 7acbafe9a3..409377186f 100644 --- a/src/applications/phortune/phid/PhortuneProductPHIDType.php +++ b/src/applications/phortune/phid/PhortuneProductPHIDType.php @@ -12,6 +12,10 @@ final class PhortuneProductPHIDType extends PhabricatorPHIDType { return new PhortuneProduct(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortunePurchasePHIDType.php b/src/applications/phortune/phid/PhortunePurchasePHIDType.php index b00faa585c..08f88b1d33 100644 --- a/src/applications/phortune/phid/PhortunePurchasePHIDType.php +++ b/src/applications/phortune/phid/PhortunePurchasePHIDType.php @@ -12,6 +12,10 @@ final class PhortunePurchasePHIDType extends PhabricatorPHIDType { return new PhortunePurchase(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php b/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php index 9eafc4ed83..6d7275c62b 100644 --- a/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php +++ b/src/applications/phortune/phid/PhortuneSubscriptionPHIDType.php @@ -12,6 +12,10 @@ final class PhortuneSubscriptionPHIDType extends PhabricatorPHIDType { return new PhortuneSubscription(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhortuneApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phragment/controller/PhragmentController.php b/src/applications/phragment/controller/PhragmentController.php index a96c25878e..c08adcecc6 100644 --- a/src/applications/phragment/controller/PhragmentController.php +++ b/src/applications/phragment/controller/PhragmentController.php @@ -199,7 +199,9 @@ abstract class PhragmentController extends PhabricatorController { $alt = PhabricatorEnv::getEnvConfig('security.alternate-file-domain'); if ($alt === null) { return id(new PHUIInfoView()) - ->setTitle(pht('security.alternate-file-domain must be configured!')) + ->setTitle(pht( + '%s must be configured!', + 'security.alternate-file-domain')) ->setSeverity(PHUIInfoView::SEVERITY_ERROR) ->appendChild( phutil_tag( diff --git a/src/applications/phragment/phid/PhragmentFragmentPHIDType.php b/src/applications/phragment/phid/PhragmentFragmentPHIDType.php index 3722b2fd69..2947bca98e 100644 --- a/src/applications/phragment/phid/PhragmentFragmentPHIDType.php +++ b/src/applications/phragment/phid/PhragmentFragmentPHIDType.php @@ -12,6 +12,10 @@ final class PhragmentFragmentPHIDType extends PhabricatorPHIDType { return new PhragmentFragment(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhragmentApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phragment/phid/PhragmentFragmentVersionPHIDType.php b/src/applications/phragment/phid/PhragmentFragmentVersionPHIDType.php index 2ab0240b5c..2fa00b15ce 100644 --- a/src/applications/phragment/phid/PhragmentFragmentVersionPHIDType.php +++ b/src/applications/phragment/phid/PhragmentFragmentVersionPHIDType.php @@ -12,6 +12,10 @@ final class PhragmentFragmentVersionPHIDType extends PhabricatorPHIDType { return new PhragmentFragmentVersion(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhragmentApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phragment/phid/PhragmentSnapshotPHIDType.php b/src/applications/phragment/phid/PhragmentSnapshotPHIDType.php index 060b37963c..d97026a601 100644 --- a/src/applications/phragment/phid/PhragmentSnapshotPHIDType.php +++ b/src/applications/phragment/phid/PhragmentSnapshotPHIDType.php @@ -12,6 +12,10 @@ final class PhragmentSnapshotPHIDType extends PhabricatorPHIDType { return new PhragmentSnapshot(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhragmentApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phriction/phid/PhrictionDocumentPHIDType.php b/src/applications/phriction/phid/PhrictionDocumentPHIDType.php index 934dc73b30..57afdb84d6 100644 --- a/src/applications/phriction/phid/PhrictionDocumentPHIDType.php +++ b/src/applications/phriction/phid/PhrictionDocumentPHIDType.php @@ -8,14 +8,14 @@ final class PhrictionDocumentPHIDType extends PhabricatorPHIDType { return pht('Phriction Wiki Document'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorPhrictionApplication'; - } - public function newObject() { return new PhrictionDocument(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhrictionApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phurl/application/PhabricatorPhurlApplication.php b/src/applications/phurl/application/PhabricatorPhurlApplication.php index c0cf1bf86d..7b01a3f4c5 100644 --- a/src/applications/phurl/application/PhabricatorPhurlApplication.php +++ b/src/applications/phurl/application/PhabricatorPhurlApplication.php @@ -26,9 +26,18 @@ final class PhabricatorPhurlApplication extends PhabricatorApplication { return true; } + public function getRemarkupRules() { + return array( + new PhabricatorPhurlRemarkupRule(), + new PhabricatorPhurlLinkRemarkupRule(), + ); + } + public function getRoutes() { return array( '/U(?P[1-9]\d*)' => 'PhabricatorPhurlURLViewController', + '/u/(?P[1-9]\d*)' => 'PhabricatorPhurlURLAccessController', + '/u/(?P[^/]+)' => 'PhabricatorPhurlURLAccessController', '/phurl/' => array( '(?:query/(?P[^/]+)/)?' => 'PhabricatorPhurlURLListController', diff --git a/src/applications/phurl/controller/PhabricatorPhurlURLAccessController.php b/src/applications/phurl/controller/PhabricatorPhurlURLAccessController.php new file mode 100644 index 0000000000..8d15f7a37b --- /dev/null +++ b/src/applications/phurl/controller/PhabricatorPhurlURLAccessController.php @@ -0,0 +1,36 @@ +getViewer(); + $id = $request->getURIData('id'); + $alias = $request->getURIData('alias'); + + if ($id) { + $url = id(new PhabricatorPhurlURLQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + } else if ($alias) { + $url = id(new PhabricatorPhurlURLQuery()) + ->setViewer($viewer) + ->withAliases(array($alias)) + ->executeOne(); + } + + if (!$url) { + return new Aphront404Response(); + } + + if ($url->isValid()) { + return id(new AphrontRedirectResponse()) + ->setURI($url->getLongURL()) + ->setIsExternal(true); + } else { + return id(new AphrontRedirectResponse())->setURI('/'.$url->getMonogram()); + } + } + +} diff --git a/src/applications/phurl/controller/PhabricatorPhurlURLEditController.php b/src/applications/phurl/controller/PhabricatorPhurlURLEditController.php index 15c25408a8..5a7cd9686d 100644 --- a/src/applications/phurl/controller/PhabricatorPhurlURLEditController.php +++ b/src/applications/phurl/controller/PhabricatorPhurlURLEditController.php @@ -7,10 +7,11 @@ final class PhabricatorPhurlURLEditController $id = $request->getURIData('id'); $is_create = !$id; - $viewer = $request->getViewer(); + $viewer = $this->getViewer(); $user_phid = $viewer->getPHID(); $error_name = true; $error_long_url = true; + $error_alias = null; $validation_exception = null; $next_workflow = $request->getStr('next'); @@ -58,6 +59,7 @@ final class PhabricatorPhurlURLEditController $name = $url->getName(); $long_url = $url->getLongURL(); + $alias = $url->getAlias(); $description = $url->getDescription(); $edit_policy = $url->getEditPolicy(); $view_policy = $url->getViewPolicy(); @@ -67,6 +69,7 @@ final class PhabricatorPhurlURLEditController $xactions = array(); $name = $request->getStr('name'); $long_url = $request->getStr('longURL'); + $alias = $request->getStr('alias'); $projects = $request->getArr('projects'); $description = $request->getStr('description'); $subscribers = $request->getArr('subscribers'); @@ -84,6 +87,11 @@ final class PhabricatorPhurlURLEditController PhabricatorPhurlURLTransaction::TYPE_URL) ->setNewValue($long_url); + $xactions[] = id(new PhabricatorPhurlURLTransaction()) + ->setTransactionType( + PhabricatorPhurlURLTransaction::TYPE_ALIAS) + ->setNewValue($alias); + $xactions[] = id(new PhabricatorPhurlURLTransaction()) ->setTransactionType( PhabricatorTransactions::TYPE_SUBSCRIBERS) @@ -127,6 +135,8 @@ final class PhabricatorPhurlURLEditController PhabricatorPhurlURLTransaction::TYPE_NAME); $error_long_url = $ex->getShortMessage( PhabricatorPhurlURLTransaction::TYPE_URL); + $error_alias = $ex->getShortMessage( + PhabricatorPhurlURLTransaction::TYPE_ALIAS); } } @@ -147,6 +157,12 @@ final class PhabricatorPhurlURLEditController ->setValue($long_url) ->setError($error_long_url); + $alias = id(new AphrontFormTextControl()) + ->setLabel(pht('Alias')) + ->setName('alias') + ->setValue($alias) + ->setError($error_alias); + $projects = id(new AphrontFormTokenizerControl()) ->setLabel(pht('Projects')) ->setName('projects') @@ -187,6 +203,7 @@ final class PhabricatorPhurlURLEditController ->setUser($viewer) ->appendChild($name) ->appendChild($long_url) + ->appendChild($alias) ->appendControl($view_policies) ->appendControl($edit_policies) ->appendControl($subscribers) diff --git a/src/applications/phurl/controller/PhabricatorPhurlURLViewController.php b/src/applications/phurl/controller/PhabricatorPhurlURLViewController.php index 4483b9bb77..7702d67b7c 100644 --- a/src/applications/phurl/controller/PhabricatorPhurlURLViewController.php +++ b/src/applications/phurl/controller/PhabricatorPhurlURLViewController.php @@ -35,9 +35,13 @@ final class PhabricatorPhurlURLViewController $properties = $this->buildPropertyView($url); $properties->setActionList($actions); + $url_error = id(new PHUIInfoView()) + ->setErrors(array(pht('This URL is invalid due to a bad protocol.'))) + ->setIsHidden($url->isValid()); $box = id(new PHUIObjectBoxView()) ->setHeader($header) - ->addPropertyList($properties); + ->addPropertyList($properties) + ->setInfoView($url_error); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $add_comment_header = $is_serious @@ -96,13 +100,20 @@ final class PhabricatorPhurlURLViewController $url, PhabricatorPolicyCapability::CAN_EDIT); - $actions->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Edit')) - ->setIcon('fa-pencil') - ->setHref($this->getApplicationURI("url/edit/{$id}/")) - ->setDisabled(!$can_edit) - ->setWorkflow(!$can_edit)); + $actions + ->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit')) + ->setIcon('fa-pencil') + ->setHref($this->getApplicationURI("url/edit/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)) + ->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Visit URL')) + ->setIcon('fa-external-link') + ->setHref("u/{$id}") + ->setDisabled(!$url->isValid())); return $actions; } @@ -118,6 +129,10 @@ final class PhabricatorPhurlURLViewController pht('Original URL'), $url->getLongURL()); + $properties->addProperty( + pht('Alias'), + $url->getAlias()); + $properties->invokeWillRenderEvent(); if (strlen($url->getDescription())) { diff --git a/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php b/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php index 2065245e36..e7a3c7394b 100644 --- a/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php +++ b/src/applications/phurl/editor/PhabricatorPhurlURLEditor.php @@ -16,6 +16,7 @@ final class PhabricatorPhurlURLEditor $types[] = PhabricatorPhurlURLTransaction::TYPE_NAME; $types[] = PhabricatorPhurlURLTransaction::TYPE_URL; + $types[] = PhabricatorPhurlURLTransaction::TYPE_ALIAS; $types[] = PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION; $types[] = PhabricatorTransactions::TYPE_COMMENT; @@ -33,6 +34,8 @@ final class PhabricatorPhurlURLEditor return $object->getName(); case PhabricatorPhurlURLTransaction::TYPE_URL: return $object->getLongURL(); + case PhabricatorPhurlURLTransaction::TYPE_ALIAS: + return $object->getAlias(); case PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION: return $object->getDescription(); } @@ -48,6 +51,11 @@ final class PhabricatorPhurlURLEditor case PhabricatorPhurlURLTransaction::TYPE_URL: case PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION: return $xaction->getNewValue(); + case PhabricatorPhurlURLTransaction::TYPE_ALIAS: + if (!strlen($xaction->getNewValue())) { + return null; + } + return $xaction->getNewValue(); } return parent::getCustomTransactionNewValue($object, $xaction); @@ -64,6 +72,9 @@ final class PhabricatorPhurlURLEditor case PhabricatorPhurlURLTransaction::TYPE_URL: $object->setLongURL($xaction->getNewValue()); return; + case PhabricatorPhurlURLTransaction::TYPE_ALIAS: + $object->setAlias($xaction->getNewValue()); + return; case PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION: $object->setDescription($xaction->getNewValue()); return; @@ -79,6 +90,7 @@ final class PhabricatorPhurlURLEditor switch ($xaction->getTransactionType()) { case PhabricatorPhurlURLTransaction::TYPE_NAME: case PhabricatorPhurlURLTransaction::TYPE_URL: + case PhabricatorPhurlURLTransaction::TYPE_ALIAS: case PhabricatorPhurlURLTransaction::TYPE_DESCRIPTION: return; } @@ -109,6 +121,41 @@ final class PhabricatorPhurlURLEditor $error->setIsMissingFieldError(true); $errors[] = $error; } + break; + case PhabricatorPhurlURLTransaction::TYPE_ALIAS: + $overdrawn = $this->validateIsTextFieldTooLong( + $object->getName(), + $xactions, + 64); + + if ($overdrawn) { + $errors[] = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Alias Too Long'), + pht('The alias can be no longer than 64 characters.'), + nonempty(last($xactions), null)); + } + + foreach ($xactions as $xaction) { + if ($xaction->getOldValue() != $xaction->getNewValue()) { + $new_alias = $xaction->getNewValue(); + if (!preg_match('/[a-zA-Z]/', $new_alias)) { + $errors[] = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Invalid Alias'), + pht('The alias must contain at least one letter.'), + $xaction); + } + if (preg_match('/[^a-z0-9]/i', $new_alias)) { + $errors[] = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Invalid Alias'), + pht('The alias may only contain letters and numbers.'), + $xaction); + } + } + } + break; case PhabricatorPhurlURLTransaction::TYPE_URL: $missing = $this->validateIsEmptyTextField( @@ -125,6 +172,21 @@ final class PhabricatorPhurlURLEditor $error->setIsMissingFieldError(true); $errors[] = $error; } + + foreach ($xactions as $xaction) { + if ($xaction->getOldValue() != $xaction->getNewValue()) { + $protocols = PhabricatorEnv::getEnvConfig('uri.allowed-protocols'); + $uri = new PhutilURI($xaction->getNewValue()); + if (!isset($protocols[$uri->getProtocol()])) { + $errors[] = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Invalid URL'), + pht('The protocol of the URL is invalid.'), + null); + } + } + } + break; } @@ -203,5 +265,19 @@ final class PhabricatorPhurlURLEditor return $body; } + protected function didCatchDuplicateKeyException( + PhabricatorLiskDAO $object, + array $xactions, + Exception $ex) { + + $errors = array(); + $errors[] = new PhabricatorApplicationTransactionValidationError( + PhabricatorPhurlURLTransaction::TYPE_ALIAS, + pht('Duplicate'), + pht('This alias is already in use.'), + null); + + throw new PhabricatorApplicationTransactionValidationException($errors); + } } diff --git a/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php b/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php index f273732b82..979b25c791 100644 --- a/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php +++ b/src/applications/phurl/phid/PhabricatorPhurlURLPHIDType.php @@ -8,14 +8,14 @@ final class PhabricatorPhurlURLPHIDType extends PhabricatorPHIDType { return pht('URL'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorPhurlApplication'; - } - public function newObject() { return new PhabricatorPhurlURL(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPhurlApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/phurl/query/PhabricatorPhurlURLQuery.php b/src/applications/phurl/query/PhabricatorPhurlURLQuery.php index 1edcb1e5c3..412b085635 100644 --- a/src/applications/phurl/query/PhabricatorPhurlURLQuery.php +++ b/src/applications/phurl/query/PhabricatorPhurlURLQuery.php @@ -7,6 +7,7 @@ final class PhabricatorPhurlURLQuery private $phids; private $names; private $longURLs; + private $aliases; private $authorPHIDs; public function newResultObject() { @@ -33,6 +34,11 @@ final class PhabricatorPhurlURLQuery return $this; } + public function withAliases(array $aliases) { + $this->aliases = $aliases; + return $this; + } + public function withAuthorPHIDs(array $author_phids) { $this->authorPHIDs = $author_phids; return $this; @@ -87,6 +93,13 @@ final class PhabricatorPhurlURLQuery $this->longURLs); } + if ($this->aliases !== null) { + $where[] = qsprintf( + $conn, + 'url.alias IN (%Ls)', + $this->aliases); + } + return $where; } diff --git a/src/applications/phurl/remarkup/PhabricatorPhurlLinkRemarkupRule.php b/src/applications/phurl/remarkup/PhabricatorPhurlLinkRemarkupRule.php new file mode 100644 index 0000000000..bdb6c1959f --- /dev/null +++ b/src/applications/phurl/remarkup/PhabricatorPhurlLinkRemarkupRule.php @@ -0,0 +1,63 @@ +getEngine(); + $viewer = $engine->getConfig('viewer'); + $text_mode = $engine->isTextMode(); + + if (!$this->isFlatText($matches[0])) { + return $matches[0]; + } + + $ref = $matches[1]; + + if (ctype_digit($ref)) { + $phurls = id(new PhabricatorPhurlURLQuery()) + ->setViewer($viewer) + ->withIDs(array($ref)) + ->execute(); + } else { + $phurls = id(new PhabricatorPhurlURLQuery()) + ->setViewer($viewer) + ->withAliases(array($ref)) + ->execute(); + } + + $phurl = head($phurls); + + if ($phurl) { + if ($text_mode) { + return $phurl->getName().' <'.$phurl->getLongURL().'>'; + } + + $link = phutil_tag( + 'a', + array( + 'href' => $phurl->getLongURL(), + 'target' => '_blank', + ), + $phurl->getName()); + + return $this->getEngine()->storeText($link); + } else { + return $matches[0]; + } + } + + +} diff --git a/src/applications/phurl/remarkup/PhabricatorPhurlRemarkupRule.php b/src/applications/phurl/remarkup/PhabricatorPhurlRemarkupRule.php new file mode 100644 index 0000000000..f444cdc7bd --- /dev/null +++ b/src/applications/phurl/remarkup/PhabricatorPhurlRemarkupRule.php @@ -0,0 +1,19 @@ +getEngine()->getConfig('viewer'); + + return id(new PhabricatorPhurlURLQuery()) + ->setViewer($viewer) + ->withIDs($ids) + ->execute(); + } + +} diff --git a/src/applications/phurl/storage/PhabricatorPhurlURL.php b/src/applications/phurl/storage/PhabricatorPhurlURL.php index e59aea63fa..35c5382d52 100644 --- a/src/applications/phurl/storage/PhabricatorPhurlURL.php +++ b/src/applications/phurl/storage/PhabricatorPhurlURL.php @@ -72,6 +72,13 @@ final class PhabricatorPhurlURL extends PhabricatorPhurlDAO return $uri; } + public function isValid() { + $allowed_protocols = PhabricatorEnv::getEnvConfig('uri.allowed-protocols'); + $uri = new PhutilURI($this->getLongURL()); + + return isset($allowed_protocols[$uri->getProtocol()]); + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/phurl/storage/PhabricatorPhurlURLTransaction.php b/src/applications/phurl/storage/PhabricatorPhurlURLTransaction.php index 0c00c67f2d..6d275bcefb 100644 --- a/src/applications/phurl/storage/PhabricatorPhurlURLTransaction.php +++ b/src/applications/phurl/storage/PhabricatorPhurlURLTransaction.php @@ -5,6 +5,7 @@ final class PhabricatorPhurlURLTransaction const TYPE_NAME = 'phurl.name'; const TYPE_URL = 'phurl.longurl'; + const TYPE_ALIAS = 'phurl.alias'; const TYPE_DESCRIPTION = 'phurl.description'; const MAILTAG_CONTENT = 'phurl:content'; @@ -28,6 +29,7 @@ final class PhabricatorPhurlURLTransaction switch ($this->getTransactionType()) { case self::TYPE_NAME: case self::TYPE_URL: + case self::TYPE_ALIAS: case self::TYPE_DESCRIPTION: $phids[] = $this->getObjectPHID(); break; @@ -49,6 +51,7 @@ final class PhabricatorPhurlURLTransaction switch ($this->getTransactionType()) { case self::TYPE_NAME: case self::TYPE_URL: + case self::TYPE_ALIAS: case self::TYPE_DESCRIPTION: return 'fa-pencil'; break; @@ -78,11 +81,35 @@ final class PhabricatorPhurlURLTransaction $new); } case self::TYPE_URL: - return pht( - '%s changed the destination of the URL from %s to %s.', - $this->renderHandleLink($author_phid), - $old, - $new); + if ($old === null) { + return pht( + '%s set the destination of the URL to %s.', + $this->renderHandleLink($author_phid), + $new); + } else { + return pht( + '%s changed the destination of the URL from %s to %s.', + $this->renderHandleLink($author_phid), + $old, + $new); + } + case self::TYPE_ALIAS: + if ($old === null) { + return pht( + '%s set the alias of the URL to %s.', + $this->renderHandleLink($author_phid), + $new); + } else if ($new === null) { + return pht( + '%s removed the alias of the URL.', + $this->renderHandleLink($author_phid)); + } else { + return pht( + '%s changed the alias of the URL from %s to %s.', + $this->renderHandleLink($author_phid), + $old, + $new); + } case self::TYPE_DESCRIPTION: return pht( "%s updated the URL's description.", @@ -119,12 +146,33 @@ final class PhabricatorPhurlURLTransaction case self::TYPE_URL: if ($old === null) { return pht( - '%s created %s.', + '%s set the destination of %s to %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $new); + } else { + return pht( + '%s changed the destination of %s from %s to %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $old, + $new); + } + case self::TYPE_ALIAS: + if ($old === null) { + return pht( + '%s set the alias of %s to %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid), + $new); + } else if ($new === null) { + return pht( + '%s removed the alias of %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } else { return pht( - '%s changed the destination of %s from %s to %s', + '%s changed the alias of %s from %s to %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), $old, @@ -147,6 +195,7 @@ final class PhabricatorPhurlURLTransaction switch ($this->getTransactionType()) { case self::TYPE_NAME: case self::TYPE_URL: + case self::TYPE_ALIAS: case self::TYPE_DESCRIPTION: return PhabricatorTransactions::COLOR_GREEN; } @@ -185,6 +234,7 @@ final class PhabricatorPhurlURLTransaction case self::TYPE_NAME: case self::TYPE_DESCRIPTION: case self::TYPE_URL: + case self::TYPE_ALIAS: $tags[] = self::MAILTAG_CONTENT; break; } diff --git a/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php b/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php index 225aa22ac1..ed75561327 100644 --- a/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php +++ b/src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php @@ -12,6 +12,10 @@ final class PhabricatorPolicyPHIDTypePolicy extends PhabricatorPHIDType { return new PhabricatorPolicy(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPolicyApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/ponder/controller/PonderQuestionViewController.php b/src/applications/ponder/controller/PonderQuestionViewController.php index f7e70caab0..0e92f8e90c 100644 --- a/src/applications/ponder/controller/PonderQuestionViewController.php +++ b/src/applications/ponder/controller/PonderQuestionViewController.php @@ -292,7 +292,9 @@ final class PonderQuestionViewController extends PonderController { $item->setObject($question); $item->addAttribute( - pht('%d Answer(s)', $question->getAnswerCount())); + pht( + '%s Answer(s)', + new PhutilNumber($question->getAnswerCount()))); $list->addItem($item); } diff --git a/src/applications/ponder/phid/PonderQuestionPHIDType.php b/src/applications/ponder/phid/PonderQuestionPHIDType.php index db1d5acff2..9bdd80aae6 100644 --- a/src/applications/ponder/phid/PonderQuestionPHIDType.php +++ b/src/applications/ponder/phid/PonderQuestionPHIDType.php @@ -8,14 +8,14 @@ final class PonderQuestionPHIDType extends PhabricatorPHIDType { return pht('Ponder Question'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorPonderApplication'; - } - public function newObject() { return new PonderQuestion(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorPonderApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/ponder/query/PonderQuestionSearchEngine.php b/src/applications/ponder/query/PonderQuestionSearchEngine.php index 6692d8282a..c16c5442db 100644 --- a/src/applications/ponder/query/PonderQuestionSearchEngine.php +++ b/src/applications/ponder/query/PonderQuestionSearchEngine.php @@ -134,11 +134,11 @@ final class PonderQuestionSearchEngine foreach ($questions as $question) { $color = PonderQuestionStatus::getQuestionStatusTagColor( - $question->getStatus()); + $question->getStatus()); $icon = PonderQuestionStatus::getQuestionStatusIcon( - $question->getStatus()); + $question->getStatus()); $full_status = PonderQuestionStatus::getQuestionStatusFullName( - $question->getStatus()); + $question->getStatus()); $item = new PHUIObjectItemView(); $item->setObjectName('Q'.$question->getID()); $item->setHeader($question->getTitle()); @@ -158,7 +158,9 @@ final class PonderQuestionSearchEngine $handles[$question->getAuthorPHID()]->renderLink())); $item->addAttribute( - pht('%d Answer(s)', $question->getAnswerCount())); + pht( + '%s Answer(s)', + new PhutilNumber($question->getAnswerCount()))); if ($project_handles) { $item->addAttribute( diff --git a/src/applications/project/herald/PhabricatorProjectHeraldAction.php b/src/applications/project/herald/PhabricatorProjectHeraldAction.php index a720ebe5b0..3459da92cc 100644 --- a/src/applications/project/herald/PhabricatorProjectHeraldAction.php +++ b/src/applications/project/herald/PhabricatorProjectHeraldAction.php @@ -112,12 +112,12 @@ abstract class PhabricatorProjectHeraldAction case self::DO_ADD_PROJECTS: return pht( 'Added %s project(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_REMOVE_PROJECTS: return pht( 'Removed %s project(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } diff --git a/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php b/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php index 4ac0399cf7..07c7f7a0ee 100644 --- a/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php +++ b/src/applications/project/phid/PhabricatorProjectColumnPHIDType.php @@ -8,12 +8,16 @@ final class PhabricatorProjectColumnPHIDType extends PhabricatorPHIDType { return pht('Project Column'); } + public function getTypeIcon() { + return 'fa-columns bluegrey'; + } + public function newObject() { return new PhabricatorProjectColumn(); } - public function getTypeIcon() { - return 'fa-columns bluegrey'; + public function getPHIDTypeApplicationClass() { + return 'PhabricatorProjectApplication'; } protected function buildQueryForObjects( diff --git a/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php b/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php index 5689be49ce..c3d9bdd3fb 100644 --- a/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php +++ b/src/applications/project/phid/PhabricatorProjectProjectPHIDType.php @@ -8,10 +8,6 @@ final class PhabricatorProjectProjectPHIDType extends PhabricatorPHIDType { return pht('Project'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorProjectApplication'; - } - public function getTypeIcon() { return 'fa-briefcase bluegrey'; } @@ -20,6 +16,10 @@ final class PhabricatorProjectProjectPHIDType extends PhabricatorPHIDType { return new PhabricatorProject(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorProjectApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/releeph/controller/product/ReleephProductEditController.php b/src/applications/releeph/controller/product/ReleephProductEditController.php index 7fd8e81563..6a58a39bd9 100644 --- a/src/applications/releeph/controller/product/ReleephProductEditController.php +++ b/src/applications/releeph/controller/product/ReleephProductEditController.php @@ -49,7 +49,7 @@ final class ReleephProductEditController extends ReleephProductController { if (!$product_name) { $e_name = pht('Required'); $errors[] = - pht('Your releeph product should have a simple descriptive name.'); + pht('Your Releeph product should have a simple descriptive name.'); } if (!$trunk_branch) { diff --git a/src/applications/releeph/field/specification/ReleephDiffChurnFieldSpecification.php b/src/applications/releeph/field/specification/ReleephDiffChurnFieldSpecification.php index 18c3c78c87..112ef09885 100644 --- a/src/applications/releeph/field/specification/ReleephDiffChurnFieldSpecification.php +++ b/src/applications/releeph/field/specification/ReleephDiffChurnFieldSpecification.php @@ -31,6 +31,7 @@ final class ReleephDiffChurnFieldSpecification $rejections = 0; $comments = 0; $updates = 0; + foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: @@ -60,13 +61,13 @@ final class ReleephDiffChurnFieldSpecification } else { $parts = array(); if ($rejections) { - $parts[] = pht('%d rejection(s)', $rejections); + $parts[] = pht('%s rejection(s)', new PhutilNumber($rejections)); } if ($comments) { - $parts[] = pht('%d comment(s)', $comments); + $parts[] = pht('%s comment(s)', new PhutilNumber($comments)); } if ($updates) { - $parts[] = pht('%d update(s)', $updates); + $parts[] = pht('%s update(s)', new PhutilNumber($updates)); } if (count($parts) === 0) { diff --git a/src/applications/releeph/field/specification/ReleephDiffSizeFieldSpecification.php b/src/applications/releeph/field/specification/ReleephDiffSizeFieldSpecification.php index fe1a39277c..5975f208e6 100644 --- a/src/applications/releeph/field/specification/ReleephDiffSizeFieldSpecification.php +++ b/src/applications/releeph/field/specification/ReleephDiffSizeFieldSpecification.php @@ -55,7 +55,7 @@ final class ReleephDiffSizeFieldSpecification $mr_changes['tests']['lines'], count($mr_changes['tests']['paths'])); foreach ($mr_changes['tests']['paths'] as $mr_test_path) { - $test_blurb .= pht("%s\n", $mr_test_path); + $test_blurb .= sprintf("%s\n", $mr_test_path); } $test_tag = javelin_tag( diff --git a/src/applications/releeph/phid/ReleephBranchPHIDType.php b/src/applications/releeph/phid/ReleephBranchPHIDType.php index 487f5eebb0..d3a545d0df 100644 --- a/src/applications/releeph/phid/ReleephBranchPHIDType.php +++ b/src/applications/releeph/phid/ReleephBranchPHIDType.php @@ -12,6 +12,10 @@ final class ReleephBranchPHIDType extends PhabricatorPHIDType { return new ReleephBranch(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorReleephApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/releeph/phid/ReleephProductPHIDType.php b/src/applications/releeph/phid/ReleephProductPHIDType.php index 7e8079b309..c7979cfba3 100644 --- a/src/applications/releeph/phid/ReleephProductPHIDType.php +++ b/src/applications/releeph/phid/ReleephProductPHIDType.php @@ -12,6 +12,10 @@ final class ReleephProductPHIDType extends PhabricatorPHIDType { return new ReleephProject(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorReleephApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/releeph/phid/ReleephRequestPHIDType.php b/src/applications/releeph/phid/ReleephRequestPHIDType.php index 202b146fe8..7bd853f984 100644 --- a/src/applications/releeph/phid/ReleephRequestPHIDType.php +++ b/src/applications/releeph/phid/ReleephRequestPHIDType.php @@ -12,6 +12,10 @@ final class ReleephRequestPHIDType extends PhabricatorPHIDType { return new ReleephRequest(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorReleephApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/releeph/query/ReleephBranchSearchEngine.php b/src/applications/releeph/query/ReleephBranchSearchEngine.php index cbe5da5339..68ec126eb5 100644 --- a/src/applications/releeph/query/ReleephBranchSearchEngine.php +++ b/src/applications/releeph/query/ReleephBranchSearchEngine.php @@ -182,7 +182,9 @@ final class ReleephBranchSearchEngine $item->setStatusIcon('fa-code-fork orange'); $item->addIcon( 'fa-code-fork', - pht('%d Open Pull Request(s)', new PhutilNumber($open_count))); + pht( + '%s Open Pull Request(s)', + new PhutilNumber($open_count))); } $list->addItem($item); diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php index 3ed78f5161..bccb58e35a 100644 --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -172,7 +172,7 @@ final class PhabricatorRepositoryPullLocalDaemon pht( 'Not enough process slots to schedule the other %s '. 'repository(s) for updates yet.', - new PhutilNumber(count($queue)))); + phutil_count($queue))); } if ($futures) { diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php index d42ecf9526..adee507c51 100644 --- a/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php +++ b/src/applications/repository/management/PhabricatorRepositoryManagementEditWorkflow.php @@ -7,7 +7,10 @@ final class PhabricatorRepositoryManagementEditWorkflow $this ->setName('edit') ->setExamples('**edit** --as __username__ __repository__ ...') - ->setSynopsis(pht('Edit __repository__, named by callsign.')) + ->setSynopsis( + pht( + 'Edit __repository__, named by callsign '. + '(will eventually be deprecated by Conduit).')) ->setArguments( array( array( @@ -24,6 +27,16 @@ final class PhabricatorRepositoryManagementEditWorkflow 'param' => 'path', 'help' => pht('Edit the local path.'), ), + array( + 'name' => 'serve-http', + 'param' => 'string', + 'help' => pht('Edit the http serving policy.'), + ), + array( + 'name' => 'serve-ssh', + 'param' => 'string', + 'help' => pht('Edit the ssh serving policy.'), + ), )); } @@ -68,12 +81,33 @@ final class PhabricatorRepositoryManagementEditWorkflow $xactions = array(); $type_local_path = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH; + $type_protocol_http = + PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP; + $type_protocol_ssh = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH; + $allowed_serve_modes = array( + PhabricatorRepository::SERVE_OFF, + PhabricatorRepository::SERVE_READONLY, + PhabricatorRepository::SERVE_READWRITE, + ); if ($args->getArg('local-path')) { $xactions[] = id(new PhabricatorRepositoryTransaction()) ->setTransactionType($type_local_path) ->setNewValue($args->getArg('local-path')); } + $serve_http = $args->getArg('serve-http'); + if ($serve_http && in_array($serve_http, $allowed_serve_modes)) { + $xactions[] = id(new PhabricatorRepositoryTransaction()) + ->setTransactionType($type_protocol_http) + ->setNewValue($serve_http); + } + $serve_ssh = $args->getArg('serve-ssh'); + if ($serve_ssh && in_array($serve_ssh, $allowed_serve_modes)) { + $xactions[] = id(new PhabricatorRepositoryTransaction()) + ->setTransactionType($type_protocol_ssh) + ->setNewValue($serve_ssh); + } + if (!$xactions) { throw new PhutilArgumentUsageException( diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementParentsWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementParentsWorkflow.php index 3cbbf5b5bf..61c5fedf96 100644 --- a/src/applications/repository/management/PhabricatorRepositoryManagementParentsWorkflow.php +++ b/src/applications/repository/management/PhabricatorRepositoryManagementParentsWorkflow.php @@ -91,7 +91,7 @@ final class PhabricatorRepositoryManagementParentsWorkflow "%s\n", pht( 'Found %s total commit(s); updating...', - new PhutilNumber(count($graph)))); + phutil_count($graph))); $commit_table = id(new PhabricatorRepositoryCommit()); $commit_table_name = $commit_table->getTableName(); diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php index d36fb3f4ee..524cc606aa 100644 --- a/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php +++ b/src/applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php @@ -260,11 +260,12 @@ final class PhabricatorRepositoryManagementReparseWorkflow if ($all_from_repo && !$force_local) { $console->writeOut("%s\n", pht( - '**NOTE**: This script will queue tasks to reparse the data. Once the '. - 'tasks have been queued, you need to run Taskmaster daemons to '. - 'execute them.'."\n\n". - "QUEUEING TASKS (%s Commits):", - new PhutilNumber(count($commits)))); + "**NOTE**: This script will queue tasks to reparse the data. Once the ". + "tasks have been queued, you need to run Taskmaster daemons to ". + "execute them.\n\n%s", + pht( + 'QUEUEING TASKS (%s Commit(s)):', + phutil_count($commits)))); } $progress = new PhutilConsoleProgressBar(); diff --git a/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php index a176c5b7dd..0f62d523d2 100644 --- a/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php +++ b/src/applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php @@ -8,14 +8,14 @@ final class PhabricatorRepositoryCommitPHIDType extends PhabricatorPHIDType { return pht('Diffusion Commit'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorDiffusionApplication'; - } - public function newObject() { return new PhabricatorRepositoryCommit(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDiffusionApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/repository/phid/PhabricatorRepositoryMirrorPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryMirrorPHIDType.php index f10af8ac58..42737c7281 100644 --- a/src/applications/repository/phid/PhabricatorRepositoryMirrorPHIDType.php +++ b/src/applications/repository/phid/PhabricatorRepositoryMirrorPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorRepositoryMirrorPHIDType extends PhabricatorPHIDType { return new PhabricatorRepositoryMirror(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDiffusionApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php index db02bd8c1f..364ce62e5d 100644 --- a/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php +++ b/src/applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorRepositoryPushEventPHIDType extends PhabricatorPHIDType { return new PhabricatorRepositoryPushEvent(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDiffusionApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php index 4a315ac004..6af117db19 100644 --- a/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php +++ b/src/applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorRepositoryPushLogPHIDType extends PhabricatorPHIDType { return new PhabricatorRepositoryPushLog(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDiffusionApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php b/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php index d46a69dd33..5a3bca339d 100644 --- a/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php +++ b/src/applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php @@ -17,6 +17,10 @@ final class PhabricatorRepositoryRepositoryPHIDType return new PhabricatorRepository(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDiffusionApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php index 16faecbfc8..6f6891d781 100644 --- a/src/applications/search/controller/PhabricatorApplicationSearchController.php +++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php @@ -58,11 +58,6 @@ final class PhabricatorApplicationSearchController throw new PhutilInvalidStateException('setEngine'); } - $nav = $this->getNavigation(); - if (!$nav) { - throw new PhutilInvalidStateException('setNavigation'); - } - $engine->setViewer($this->getRequest()->getUser()); $parent = $this->getDelegatingController(); @@ -85,6 +80,9 @@ final class PhabricatorApplicationSearchController $user = $request->getUser(); $engine = $this->getSearchEngine(); $nav = $this->getNavigation(); + if (!$nav) { + $nav = $this->buildNavigation(); + } if ($request->isFormPost()) { $saved_query = $engine->buildSavedQueryFromRequest($request); @@ -174,9 +172,10 @@ final class PhabricatorApplicationSearchController // we sort out T5307. $form->appendChild($submit); + $body = array(); if ($this->getPreface()) { - $nav->appendChild($this->getPreface()); + $body[] = $this->getPreface(); } if ($named_query) { @@ -202,7 +201,7 @@ final class PhabricatorApplicationSearchController $box->setForm($form); } - $nav->appendChild($box); + $body[] = $box; if ($run_query) { $box->setAnchor( @@ -257,7 +256,7 @@ final class PhabricatorApplicationSearchController ->addMargin(PHUI::MARGIN_LARGE) ->setBorder(true) ->appendChild($pager); - $nav->appendChild($pager_box); + $body[] = $pager_box; } } catch (PhabricatorTypeaheadInvalidTokenException $ex) { @@ -275,13 +274,12 @@ final class PhabricatorApplicationSearchController ->buildApplicationCrumbs() ->addTextCrumb($title); - $nav->setCrumbs($crumbs); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => pht('Query: %s', $title), - )); + return $this->newPage() + ->setApplicationMenu($this->buildApplicationMenu()) + ->setTitle(pht('Query: %s', $title)) + ->setCrumbs($crumbs) + ->setNavigation($nav) + ->appendChild($body); } private function processEditRequest() { @@ -289,7 +287,11 @@ final class PhabricatorApplicationSearchController $request = $this->getRequest(); $user = $request->getUser(); $engine = $this->getSearchEngine(); + $nav = $this->getNavigation(); + if (!$nav) { + $nav = $this->buildNavigation(); + } $named_queries = $engine->loadAllNamedQueries(); @@ -357,23 +359,41 @@ final class PhabricatorApplicationSearchController ->addTextCrumb(pht('Saved Queries'), $engine->getQueryManagementURI()); $nav->selectFilter('query/edit'); - $nav->setCrumbs($crumbs); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Saved Queries')) ->setObjectList($list); - $nav->appendChild($box); - - return $parent->buildApplicationPage( - $nav, - array( - 'title' => pht('Saved Queries'), - )); + return $this->newPage() + ->setApplicationMenu($this->buildApplicationMenu()) + ->setTitle(pht('Saved Queries')) + ->setCrumbs($crumbs) + ->setNavigation($nav) + ->appendChild($box); } public function buildApplicationMenu() { - return $this->getDelegatingController()->buildApplicationMenu(); + $menu = $this->getDelegatingController() + ->buildApplicationMenu(); + + if ($menu instanceof PHUIApplicationMenuView) { + $menu->setSearchEngine($this->getSearchEngine()); + } + + return $menu; + } + + private function buildNavigation() { + $viewer = $this->getViewer(); + $engine = $this->getSearchEngine(); + + $nav = id(new AphrontSideNavFilterView()) + ->setUser($viewer) + ->setBaseURI(new PhutilURI($this->getApplicationURI())); + + $engine->addNavigationItems($nav->getMenu()); + + return $nav; } } diff --git a/src/applications/search/controller/PhabricatorSearchBaseController.php b/src/applications/search/controller/PhabricatorSearchBaseController.php index 86573b38bd..85ac1eb285 100644 --- a/src/applications/search/controller/PhabricatorSearchBaseController.php +++ b/src/applications/search/controller/PhabricatorSearchBaseController.php @@ -8,17 +8,4 @@ abstract class PhabricatorSearchBaseController extends PhabricatorController { const ACTION_BLOCKS = 'blocks'; const ACTION_EDGE = 'edge'; - public function buildStandardPageResponse($view, array $data) { - $page = $this->buildStandardPageView(); - - $page->setApplicationName('Search'); - $page->setBaseURI('/search/'); - $page->setTitle(idx($data, 'title')); - $page->setGlyph("\xC2\xBF"); - $page->appendChild($view); - - $response = new AphrontWebpageResponse(); - return $response->setContent($page->render()); - } - } diff --git a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php index 036b3871ce..4edd9df2cb 100644 --- a/src/applications/search/engine/PhabricatorApplicationSearchEngine.php +++ b/src/applications/search/engine/PhabricatorApplicationSearchEngine.php @@ -22,10 +22,32 @@ abstract class PhabricatorApplicationSearchEngine extends Phobject { private $customFields = false; private $request; private $context; + private $controller; + private $namedQueries; const CONTEXT_LIST = 'list'; const CONTEXT_PANEL = 'panel'; + public function setController(PhabricatorController $controller) { + $this->controller = $controller; + return $this; + } + + public function getController() { + return $this->controller; + } + + public function buildResponse() { + $controller = $this->getController(); + $request = $controller->getRequest(); + + $search = id(new PhabricatorApplicationSearchController()) + ->setQueryKey($request->getURIData('queryKey')) + ->setSearchEngine($this); + + return $controller->delegateToController($search); + } + public function newResultObject() { // We may be able to get this automatically if newQuery() is implemented. $query = $this->newQuery(); @@ -459,33 +481,36 @@ abstract class PhabricatorApplicationSearchEngine extends Phobject { public function loadAllNamedQueries() { $viewer = $this->requireViewer(); - - $named_queries = id(new PhabricatorNamedQueryQuery()) - ->setViewer($viewer) - ->withUserPHIDs(array($viewer->getPHID())) - ->withEngineClassNames(array(get_class($this))) - ->execute(); - $named_queries = mpull($named_queries, null, 'getQueryKey'); - $builtin = $this->getBuiltinQueries($viewer); - $builtin = mpull($builtin, null, 'getQueryKey'); - foreach ($named_queries as $key => $named_query) { - if ($named_query->getIsBuiltin()) { - if (isset($builtin[$key])) { - $named_queries[$key]->setQueryName($builtin[$key]->getQueryName()); - unset($builtin[$key]); - } else { - unset($named_queries[$key]); + if ($this->namedQueries === null) { + $named_queries = id(new PhabricatorNamedQueryQuery()) + ->setViewer($viewer) + ->withUserPHIDs(array($viewer->getPHID())) + ->withEngineClassNames(array(get_class($this))) + ->execute(); + $named_queries = mpull($named_queries, null, 'getQueryKey'); + + $builtin = mpull($builtin, null, 'getQueryKey'); + + foreach ($named_queries as $key => $named_query) { + if ($named_query->getIsBuiltin()) { + if (isset($builtin[$key])) { + $named_queries[$key]->setQueryName($builtin[$key]->getQueryName()); + unset($builtin[$key]); + } else { + unset($named_queries[$key]); + } } + + unset($builtin[$key]); } - unset($builtin[$key]); + $named_queries = msort($named_queries, 'getSortKey'); + $this->namedQueries = $named_queries; } - $named_queries = msort($named_queries, 'getSortKey'); - - return $named_queries + $builtin; + return $this->namedQueries + $builtin; } public function loadEnabledNamedQueries() { diff --git a/src/applications/search/engine/PhabricatorElasticSearchEngine.php b/src/applications/search/engine/PhabricatorElasticSearchEngine.php index e99160839f..fa6bdf8fee 100644 --- a/src/applications/search/engine/PhabricatorElasticSearchEngine.php +++ b/src/applications/search/engine/PhabricatorElasticSearchEngine.php @@ -79,7 +79,7 @@ final class PhabricatorElasticSearchEngine extends PhabricatorSearchEngine { $spec['relationship'][$rtype][] = array( 'phid' => $to_phid, 'phidType' => $to_type, - 'when' => $time, + 'when' => (int)$time, ); } diff --git a/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php b/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php deleted file mode 100644 index aca40d5521..0000000000 --- a/src/applications/settings/panel/PhabricatorConduitCertificateSettingsPanel.php +++ /dev/null @@ -1,138 +0,0 @@ -getUser()->getIsMailingList()) { - return false; - } - - return true; - } - - public function processRequest(AphrontRequest $request) { - $user = $this->getUser(); - $viewer = $request->getUser(); - - id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession( - $viewer, - $request, - '/settings/'); - - if ($request->isFormPost()) { - if (!$request->isDialogFormPost()) { - $dialog = new AphrontDialogView(); - $dialog->setUser($viewer); - $dialog->setTitle(pht('Really regenerate session?')); - $dialog->setSubmitURI($this->getPanelURI()); - $dialog->addSubmitButton(pht('Regenerate')); - $dialog->addCancelbutton($this->getPanelURI()); - $dialog->appendChild(phutil_tag('p', array(), pht( - 'Really destroy the old certificate? Any established '. - 'sessions will be terminated.'))); - - return id(new AphrontDialogResponse()) - ->setDialog($dialog); - } - - $sessions = id(new PhabricatorAuthSessionQuery()) - ->setViewer($user) - ->withIdentityPHIDs(array($user->getPHID())) - ->withSessionTypes(array(PhabricatorAuthSession::TYPE_CONDUIT)) - ->execute(); - foreach ($sessions as $session) { - $session->delete(); - } - - // This implicitly regenerates the certificate. - $user->setConduitCertificate(null); - $user->save(); - return id(new AphrontRedirectResponse()) - ->setURI($this->getPanelURI('?regenerated=true')); - } - - if ($request->getStr('regenerated')) { - $notice = new PHUIInfoView(); - $notice->setSeverity(PHUIInfoView::SEVERITY_NOTICE); - $notice->setTitle(pht('Certificate Regenerated')); - $notice->appendChild(phutil_tag( - 'p', - array(), - pht( - 'Your old certificate has been destroyed and you have been issued '. - 'a new certificate. Sessions established under the old certificate '. - 'are no longer valid.'))); - $notice = $notice->render(); - } else { - $notice = null; - } - - Javelin::initBehavior('select-on-click'); - - $cert_form = new AphrontFormView(); - $cert_form - ->setUser($viewer) - ->appendChild(phutil_tag( - 'p', - array('class' => 'aphront-form-instructions'), - pht( - 'This certificate allows you to authenticate over Conduit, '. - 'the Phabricator API. Normally, you just run %s to install it.', - phutil_tag('tt', array(), 'arc install-certificate')))) - ->appendChild( - id(new AphrontFormTextAreaControl()) - ->setLabel(pht('Certificate')) - ->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT) - ->setReadonly(true) - ->setSigil('select-on-click') - ->setValue($user->getConduitCertificate())); - - $cert_form = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Arcanist Certificate')) - ->setForm($cert_form); - - $regen_instruction = pht( - 'You can regenerate this certificate, which '. - 'will invalidate the old certificate and create a new one.'); - - $regen_form = new AphrontFormView(); - $regen_form - ->setUser($viewer) - ->setAction($this->getPanelURI()) - ->setWorkflow(true) - ->appendChild(phutil_tag( - 'p', - array('class' => 'aphront-form-instructions'), - $regen_instruction)) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Regenerate Certificate'))); - - $regen_form = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Regenerate Certificate')) - ->setForm($regen_form); - - return array( - $notice, - $cert_form, - $regen_form, - ); - } -} diff --git a/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php b/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php index 927e6a3942..42ced85b22 100644 --- a/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php +++ b/src/applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorSlowvotePollPHIDType extends PhabricatorPHIDType { return new PhabricatorSlowvotePoll(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorSlowvoteApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php b/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php index 6645c7edbd..86371d6420 100644 --- a/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php +++ b/src/applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php @@ -9,14 +9,14 @@ final class PhabricatorSpacesNamespacePHIDType return pht('Space'); } - public function getPHIDTypeApplicationClass() { - return 'PhabricatorSpacesApplication'; - } - public function newObject() { return new PhabricatorSpacesNamespace(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorSpacesApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php b/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php index 6ec7b6f776..bf0df4fd97 100644 --- a/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php +++ b/src/applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php @@ -163,22 +163,22 @@ abstract class PhabricatorSubscriptionsHeraldAction return pht( 'Declined to resubscribe %s target(s) because they previously '. 'unsubscribed: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_AUTOSUBSCRIBED: return pht( '%s automatically subscribed target(s) were not affected: %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_SUBSCRIBED: return pht( 'Added %s subscriber(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); case self::DO_UNSUBSCRIBED: return pht( 'Removed %s subscriber(s): %s.', - new PhutilNumber(count($data)), + phutil_count($data), $this->renderHandleList($data)); } } diff --git a/src/applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php b/src/applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php index 2abbc52691..baaf4f7af9 100644 --- a/src/applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php +++ b/src/applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php @@ -119,7 +119,7 @@ EOBANNER; $console->writeOut( pht( 'These %s object(s) will be destroyed forever:', - new PhutilNumber(count($named_objects)))."\n\n"); + phutil_count($named_objects))."\n\n"); foreach ($named_objects as $object_name => $object) { $phid = $object->getPHID(); @@ -136,7 +136,7 @@ EOBANNER; $ok = $console->confirm( pht( 'Are you absolutely certain you want to destroy these %s object(s)?', - new PhutilNumber(count($named_objects)))); + phutil_count($named_objects))); if (!$ok) { throw new PhutilArgumentUsageException( pht('Aborted, your objects are safe.')); @@ -160,7 +160,7 @@ EOBANNER; "%s\n", pht( 'Permanently destroyed %s object(s).', - new PhutilNumber(count($named_objects)))); + phutil_count($named_objects))); return 0; } diff --git a/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php b/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php index 1791cc88c7..93ff9500ac 100644 --- a/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php +++ b/src/applications/tokens/phid/PhabricatorTokenTokenPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorTokenTokenPHIDType extends PhabricatorPHIDType { return new PhabricatorToken(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorTokensApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php b/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php new file mode 100644 index 0000000000..86a03b51f4 --- /dev/null +++ b/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php @@ -0,0 +1,776 @@ +viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + final public function setController(PhabricatorController $controller) { + $this->controller = $controller; + $this->setViewer($controller->getViewer()); + return $this; + } + + final public function getController() { + return $this->controller; + } + + +/* -( Managing Fields )---------------------------------------------------- */ + + + abstract protected function buildCustomEditFields($object); + + final protected function buildEditFields($object) { + $viewer = $this->getViewer(); + $editor = $object->getApplicationTransactionEditor(); + + $types = $editor->getTransactionTypesForObject($object); + $types = array_fuse($types); + + $fields = $this->buildCustomEditFields($object); + + if ($object instanceof PhabricatorPolicyInterface) { + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($viewer) + ->setObject($object) + ->execute(); + + $map = array( + PhabricatorTransactions::TYPE_VIEW_POLICY => array( + 'key' => 'policy.view', + 'aliases' => array('view'), + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, + 'label' => pht('View Policy'), + 'description' => pht('Controls who can view the object.'), + 'edit' => 'view', + ), + PhabricatorTransactions::TYPE_EDIT_POLICY => array( + 'key' => 'policy.edit', + 'aliases' => array('edit'), + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, + 'label' => pht('Edit Policy'), + 'description' => pht('Controls who can edit the object.'), + 'edit' => 'edit', + ), + PhabricatorTransactions::TYPE_JOIN_POLICY => array( + 'key' => 'policy.join', + 'aliases' => array('join'), + 'capability' => PhabricatorPolicyCapability::CAN_JOIN, + 'label' => pht('Join Policy'), + 'description' => pht('Controls who can join the object.'), + 'edit' => 'join', + ), + ); + + foreach ($map as $type => $spec) { + if (empty($types[$type])) { + continue; + } + + $capability = $spec['capability']; + $key = $spec['key']; + $aliases = $spec['aliases']; + $label = $spec['label']; + $description = $spec['description']; + $edit = $spec['edit']; + + $policy_field = id(new PhabricatorPolicyEditField()) + ->setKey($key) + ->setLabel($label) + ->setDescription($description) + ->setAliases($aliases) + ->setCapability($capability) + ->setPolicies($policies) + ->setTransactionType($type) + ->setEditTypeKey($edit) + ->setValue($object->getPolicy($capability)); + $fields[] = $policy_field; + + if ($object instanceof PhabricatorSpacesInterface) { + if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { + $type_space = PhabricatorTransactions::TYPE_SPACE; + if (isset($types[$type_space])) { + $space_field = id(new PhabricatorSpaceEditField()) + ->setKey('spacePHID') + ->setLabel(pht('Space')) + ->setEditTypeKey('space') + ->setDescription( + pht('Shifts the object in the Spaces application.')) + ->setAliases(array('space', 'policy.space')) + ->setTransactionType($type_space) + ->setValue($object->getSpacePHID()); + $fields[] = $space_field; + + $policy_field->setSpaceField($space_field); + } + } + } + } + } + + $edge_type = PhabricatorTransactions::TYPE_EDGE; + $object_phid = $object->getPHID(); + + $project_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; + + if ($object instanceof PhabricatorProjectInterface) { + if (isset($types[$edge_type])) { + if ($object_phid) { + $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( + $object_phid, + $project_edge_type); + $project_phids = array_reverse($project_phids); + } else { + $project_phids = array(); + } + + $edge_field = id(new PhabricatorProjectsEditField()) + ->setKey('projectPHIDs') + ->setLabel(pht('Projects')) + ->setEditTypeKey('projects') + ->setDescription(pht('Add or remove associated projects.')) + ->setAliases(array('project', 'projects')) + ->setTransactionType($edge_type) + ->setMetadataValue('edge:type', $project_edge_type) + ->setValue($project_phids); + $fields[] = $edge_field; + } + } + + $subscribers_type = PhabricatorTransactions::TYPE_SUBSCRIBERS; + + if ($object instanceof PhabricatorSubscribableInterface) { + if (isset($types[$subscribers_type])) { + if ($object_phid) { + $sub_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID( + $object_phid); + } else { + // TODO: Allow applications to provide default subscribers; Maniphest + // does this at a minimum. + $sub_phids = array(); + } + + $subscribers_field = id(new PhabricatorSubscribersEditField()) + ->setKey('subscriberPHIDs') + ->setLabel(pht('Subscribers')) + ->setEditTypeKey('subscribers') + ->setDescription(pht('Manage subscribers.')) + ->setAliases(array('subscriber', 'subscribers')) + ->setTransactionType($subscribers_type) + ->setValue($sub_phids); + $fields[] = $subscribers_field; + } + } + + foreach ($fields as $field) { + $field + ->setViewer($viewer) + ->setObject($object); + } + + return $fields; + } + + +/* -( Display Text )------------------------------------------------------- */ + + + /** + * @task text + */ + abstract protected function getObjectCreateTitleText($object); + + + /** + * @task text + */ + abstract protected function getObjectEditTitleText($object); + + + /** + * @task text + */ + abstract protected function getObjectCreateShortText($object); + + + /** + * @task text + */ + abstract protected function getObjectEditShortText($object); + + + /** + * @task text + */ + protected function getObjectCreateButtonText($object) { + return $this->getObjectCreateTitleText($object); + } + + + /** + * @task text + */ + protected function getObjectEditButtonText($object) { + return pht('Save Changes'); + } + + +/* -( Managing URIs )------------------------------------------------------ */ + + + /** + * @task uri + */ + abstract protected function getObjectViewURI($object); + + + /** + * @task uri + */ + protected function getObjectEditURI($object) { + return $this->getController()->getApplicationURI('edit/'); + } + + + /** + * @task uri + */ + protected function getObjectCreateCancelURI($object) { + return $this->getController()->getApplicationURI(); + } + + + /** + * @task uri + */ + protected function getObjectEditCancelURI($object) { + return $this->getObjectViewURI($object); + } + + + /** + * @task uri + */ + protected function getEditURI($object, $path = null) { + $parts = array( + $this->getObjectEditURI($object), + ); + + if (!$this->getIsCreate()) { + $parts[] = $object->getID().'/'; + } + + if ($path !== null) { + $parts[] = $path; + } + + return implode('', $parts); + } + + +/* -( Creating and Loading Objects )--------------------------------------- */ + + + /** + * Initialize a new object for creation. + * + * @return object Newly initialized object. + * @task load + */ + abstract protected function newEditableObject(); + + + /** + * Build an empty query for objects. + * + * @return PhabricatorPolicyAwareQuery Query. + * @task load + */ + abstract protected function newObjectQuery(); + + + /** + * Test if this workflow is creating a new object or editing an existing one. + * + * @return bool True if a new object is being created. + * @task load + */ + final protected function getIsCreate() { + return $this->isCreate; + } + + + /** + * Flag this workflow as a create or edit. + * + * @param bool True if this is a create workflow. + * @return this + * @task load + */ + private function setIsCreate($is_create) { + $this->isCreate = $is_create; + return $this; + } + + + /** + * Load an object by ID. + * + * @param int Object ID. + * @return object|null Object, or null if no such object exists. + * @task load + */ + private function newObjectFromID($id) { + $query = $this->newObjectQuery() + ->withIDs(array($id)); + + return $this->newObjectFromQuery($query); + } + + + /** + * Load an object by PHID. + * + * @param phid Object PHID. + * @return object|null Object, or null if no such object exists. + * @task load + */ + private function newObjectFromPHID($phid) { + $query = $this->newObjectQuery() + ->withPHIDs(array($phid)); + + return $this->newObjectFromQuery($query); + } + + + /** + * Load an object given a configured query. + * + * @param PhabricatorPolicyAwareQuery Configured query. + * @return object|null Object, or null if no such object exists. + * @task load + */ + private function newObjectFromQuery(PhabricatorPolicyAwareQuery $query) { + $viewer = $this->getViewer(); + + $object = $query + ->setViewer($viewer) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$object) { + return null; + } + + return $object; + } + + +/* -( Responding to Web Requests )----------------------------------------- */ + + + final public function buildResponse() { + $viewer = $this->getViewer(); + $controller = $this->getController(); + $request = $controller->getRequest(); + + $id = $request->getURIData('id'); + if ($id) { + $this->setIsCreate(false); + $object = $this->newObjectFromID($id); + if (!$object) { + return new Aphront404Response(); + } + } else { + $this->setIsCreate(true); + $object = $this->newEditableObject(); + } + + $action = $request->getURIData('editAction'); + switch ($action) { + case 'parameters': + return $this->buildParametersResponse($object); + default: + return $this->buildEditResponse($object); + } + } + + private function buildCrumbs($object, $final = false) { + $controller = $this->getcontroller(); + + $crumbs = $controller->buildApplicationCrumbsForEditEngine(); + if ($this->getIsCreate()) { + $create_text = $this->getObjectCreateShortText($object); + if ($final) { + $crumbs->addTextCrumb($create_text); + } else { + $edit_uri = $this->getEditURI($object); + $crumbs->addTextCrumb($create_text, $edit_uri); + } + } else { + $crumbs->addTextCrumb( + $this->getObjectEditShortText($object), + $this->getObjectViewURI($object)); + + $edit_text = pht('Edit'); + if ($final) { + $crumbs->addTextCrumb($edit_text); + } else { + $edit_uri = $this->getEditURI($object); + $crumbs->addTextCrumb($edit_text, $edit_uri); + } + } + + return $crumbs; + } + + private function buildEditResponse($object) { + $viewer = $this->getViewer(); + $controller = $this->getController(); + $request = $controller->getRequest(); + + $fields = $this->buildEditFields($object); + $template = $object->getApplicationTransactionTemplate(); + + $validation_exception = null; + if ($request->isFormPost()) { + foreach ($fields as $field) { + $field->readValueFromSubmit($request); + } + + $xactions = array(); + foreach ($fields as $field) { + $xactions[] = $field->generateTransaction(clone $template); + } + + $editor = $object->getApplicationTransactionEditor() + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true); + + try { + + $editor->applyTransactions($object, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($this->getObjectViewURI($object)); + } catch (PhabricatorApplicationTransactionValidationException $ex) { + $validation_exception = $ex; + } + } else { + if ($this->getIsCreate()) { + foreach ($fields as $field) { + $field->readValueFromRequest($request); + } + } else { + foreach ($fields as $field) { + $field->readValueFromObject($object); + } + } + } + + $action_button = $this->buildEditFormActionButton($object); + + if ($this->getIsCreate()) { + $header_text = $this->getObjectCreateTitleText($object); + } else { + $header_text = $this->getObjectEditTitleText($object); + } + + $header = id(new PHUIHeaderView()) + ->setHeader($header_text) + ->addActionLink($action_button); + + $crumbs = $this->buildCrumbs($object, $final = true); + $form = $this->buildEditForm($object, $fields); + + $box = id(new PHUIObjectBoxView()) + ->setUser($viewer) + ->setHeader($header) + ->setValidationException($validation_exception) + ->appendChild($form); + + return $controller->newPage() + ->setTitle($header_text) + ->setCrumbs($crumbs) + ->appendChild($box); + } + + private function buildEditForm($object, array $fields) { + $viewer = $this->getViewer(); + + $form = id(new AphrontFormView()) + ->setUser($viewer); + + foreach ($fields as $field) { + $field->appendToForm($form); + } + + if ($this->getIsCreate()) { + $cancel_uri = $this->getObjectCreateCancelURI($object); + $submit_button = $this->getObjectCreateButtonText($object); + } else { + $cancel_uri = $this->getObjectEditCancelURI($object); + $submit_button = $this->getObjectEditButtonText($object); + } + + $form->appendControl( + id(new AphrontFormSubmitControl()) + ->addCancelButton($cancel_uri) + ->setValue($submit_button)); + + return $form; + } + + private function buildEditFormActionButton($object) { + $viewer = $this->getViewer(); + + $action_view = id(new PhabricatorActionListView()) + ->setUser($viewer); + + foreach ($this->buildEditFormActions($object) as $action) { + $action_view->addAction($action); + } + + $action_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText(pht('Actions')) + ->setHref('#') + ->setIconFont('fa-bars') + ->setDropdownMenu($action_view); + + return $action_button; + } + + private function buildEditFormActions($object) { + $actions = array(); + + $actions[] = id(new PhabricatorActionView()) + ->setName(pht('Show HTTP Parameters')) + ->setIcon('fa-crosshairs') + ->setHref($this->getEditURI($object, 'parameters/')); + + return $actions; + } + + +/* -( Responding to HTTP Parameter Requests )------------------------------ */ + + + /** + * Respond to a request for documentation on HTTP parameters. + * + * @param object Editable object. + * @return AphrontResponse Response object. + * @task http + */ + private function buildParametersResponse($object) { + $controller = $this->getController(); + $viewer = $this->getViewer(); + $request = $controller->getRequest(); + $fields = $this->buildEditFields($object); + + $crumbs = $this->buildCrumbs($object); + $crumbs->addTextCrumb(pht('HTTP Parameters')); + $crumbs->setBorder(true); + + $header_text = pht( + 'HTTP Parameters: %s', + $this->getObjectCreateShortText($object)); + + $header = id(new PHUIHeaderView()) + ->setHeader($header_text); + + $help_view = id(new PhabricatorApplicationEditHTTPParameterHelpView()) + ->setUser($viewer) + ->setFields($fields); + + $document = id(new PHUIDocumentViewPro()) + ->setUser($viewer) + ->setHeader($header) + ->appendChild($help_view); + + return $controller->newPage() + ->setTitle(pht('HTTP Parameters')) + ->setCrumbs($crumbs) + ->addClass('pro-white-background') + ->appendChild($document); + } + + +/* -( Conduit )------------------------------------------------------------ */ + + + /** + * Respond to a Conduit edit request. + * + * This method accepts a list of transactions to apply to an object, and + * either edits an existing object or creates a new one. + * + * @task conduit + */ + final public function buildConduitResponse(ConduitAPIRequest $request) { + $viewer = $this->getViewer(); + + $phid = $request->getValue('objectPHID'); + if ($phid) { + $this->setIsCreate(false); + $object = $this->newObjectFromPHID($phid); + if (!$object) { + throw new Exception(pht('No such object with PHID "%s".', $phid)); + } + } else { + $this->setIsCreate(true); + $object = $this->newEditableObject(); + } + + $fields = $this->buildEditFields($object); + + $types = $this->getAllEditTypesFromFields($fields); + $template = $object->getApplicationTransactionTemplate(); + + $xactions = $this->getConduitTransactions($request, $types, $template); + + $editor = $object->getApplicationTransactionEditor() + ->setActor($viewer) + ->setContentSourceFromConduitRequest($request) + ->setContinueOnNoEffect(true); + + $xactions = $editor->applyTransactions($object, $xactions); + + $xactions_struct = array(); + foreach ($xactions as $xaction) { + $xactions_struct[] = array( + 'phid' => $xaction->getPHID(), + ); + } + + return array( + 'object' => array( + 'id' => $object->getID(), + 'phid' => $object->getPHID(), + ), + 'transactions' => $xactions_struct, + ); + } + + + /** + * Generate transactions which can be applied from edit actions in a Conduit + * request. + * + * @param ConduitAPIRequest The request. + * @param list Supported edit types. + * @param PhabricatorApplicationTransaction Template transaction. + * @return list Generated transactions. + * @task conduit + */ + private function getConduitTransactions( + ConduitAPIRequest $request, + array $types, + PhabricatorApplicationTransaction $template) { + + $transactions_key = 'transactions'; + + $xactions = $request->getValue($transactions_key); + if (!is_array($xactions)) { + throw new Exception( + pht( + 'Parameter "%s" is not a list of transactions.', + $transactions_key)); + } + + foreach ($xactions as $key => $xaction) { + if (!is_array($xaction)) { + throw new Exception( + pht( + 'Parameter "%s" must contain a list of transaction descriptions, '. + 'but item with key "%s" is not a dictionary.', + $transactions_key, + $key)); + } + + if (!array_key_exists('type', $xaction)) { + throw new Exception( + pht( + 'Parameter "%s" must contain a list of transaction descriptions, '. + 'but item with key "%s" is missing a "type" field. Each '. + 'transaction must have a type field.', + $transactions_key, + $key)); + } + + $type = $xaction['type']; + if (empty($types[$type])) { + throw new Exception( + pht( + 'Transaction with key "%s" has invalid type "%s". This type is '. + 'not recognized. Valid types are: %s.', + $key, + $type, + implode(', ', array_keys($types)))); + } + } + + $results = array(); + foreach ($xactions as $xaction) { + $type = $types[$xaction['type']]; + + $results[] = $type->generateTransaction( + clone $template, + $xaction); + } + + return $results; + } + + + /** + * @return map + * @task conduit + */ + private function getAllEditTypesFromFields(array $fields) { + $types = array(); + foreach ($fields as $field) { + $field_types = $field->getEditTransactionTypes(); + foreach ($field_types as $field_type) { + $field_type->setField($field); + $types[$field_type->getEditType()] = $field_type; + } + } + return $types; + } + + public function getAllEditTypes() { + $object = $this->newEditableObject(); + $fields = $this->buildEditFields($object); + return $this->getAllEditTypesFromFields($fields); + } + + +} diff --git a/src/applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php b/src/applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php new file mode 100644 index 0000000000..9fc6495455 --- /dev/null +++ b/src/applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php @@ -0,0 +1,188 @@ + 'list>', + 'objectPHID' => 'optional phid', + ); + } + + final protected function defineReturnType() { + return 'map'; + } + + final protected function execute(ConduitAPIRequest $request) { + $engine = $this->newEditEngine() + ->setViewer($request->getUser()); + + return $engine->buildConduitResponse($request); + } + + final public function getMethodDescription() { + // TODO: We don't currently have a real viewer in this method. + $viewer = new PhabricatorUser(); + + $engine = $this->newEditEngine() + ->setViewer($viewer); + + $types = $engine->getAllEditTypes(); + + $out = array(); + + $out[] = pht(<<getEditType(); + $edit_summary = $type->getSummary(); + $table[] = "| `{$edit_type}` | {$edit_summary} |"; + } + + $out[] = implode("\n", $table); + + foreach ($types as $type) { + $section = array(); + $section[] = pht('Edit Type: %s', $type->getEditType()); + $section[] = '---------'; + $section[] = null; + $section[] = $type->getDescription(); + $section[] = null; + $section[] = pht( + 'This edit generates transactions of type `%s` internally.', + $type->getTransactionType()); + $section[] = null; + + $type_description = pht( + 'Use `%s` to select this edit type.', + $type->getEditType()); + + $value_type = $type->getValueType(); + $value_description = $type->getValueDescription(); + + $table = array(); + $table[] = "| {$key} | {$head_type} | {$description} |"; + $table[] = '|--------|--------------|----------------|'; + $table[] = "| `type` | `const` | {$type_description} |"; + $table[] = "| `value` | `{$value_type}` | {$value_description} |"; + $section[] = implode("\n", $table); + + $out[] = implode("\n", $section); + } + + $out = implode("\n\n", $out); + return $out; + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorDatasourceEditField.php b/src/applications/transactions/editfield/PhabricatorDatasourceEditField.php new file mode 100644 index 0000000000..f3cf5fe079 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorDatasourceEditField.php @@ -0,0 +1,21 @@ +datasource = $datasource; + return $this; + } + + public function getDatasource() { + return $this->datasource; + } + + protected function newDatasource() { + return id(clone $this->getDatasource()); + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php new file mode 100644 index 0000000000..bfb8529933 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorEditField.php @@ -0,0 +1,293 @@ +key = $key; + return $this; + } + + public function getKey() { + return $this->key; + } + + public function setLabel($label) { + $this->label = $label; + return $this; + } + + public function getLabel() { + return $this->label; + } + + public function setViewer(PhabricatorUser $viewer) { + $this->viewer = $viewer; + return $this; + } + + public function getViewer() { + return $this->viewer; + } + + public function setAliases(array $aliases) { + $this->aliases = $aliases; + return $this; + } + + public function getAliases() { + return $this->aliases; + } + + public function setObject($object) { + $this->object = $object; + return $this; + } + + public function getObject() { + return $this->object; + } + + public function setDescription($description) { + $this->description = $description; + return $this; + } + + public function getDescription() { + return $this->description; + } + + abstract protected function newControl(); + + protected function renderControl() { + $control = $this->newControl(); + if ($control === null) { + return null; + } + + $control + ->setValue($this->getValueForControl()) + ->setName($this->getKey()); + + if (!$control->getLabel()) { + $control->setLabel($this->getLabel()); + } + + return $control; + } + + public function appendToForm(AphrontFormView $form) { + $control = $this->renderControl(); + if ($control !== null) { + $form->appendControl($control); + } + return $this; + } + + protected function getValueForControl() { + return $this->getValue(); + } + + protected function getValue() { + return $this->value; + } + + public function setValue($value) { + $this->hasValue = true; + $this->value = $value; + return $this; + } + + public function generateTransaction( + PhabricatorApplicationTransaction $xaction) { + + $xaction + ->setTransactionType($this->getTransactionType()) + ->setNewValue($this->getValueForTransaction()); + + foreach ($this->metadata as $key => $value) { + $xaction->setMetadataValue($key, $value); + } + + return $xaction; + } + + public function setMetadataValue($key, $value) { + $this->metadata[$key] = $value; + return $this; + } + + protected function getValueForTransaction() { + return $this->getValue(); + } + + public function getTransactionType() { + if (!$this->transactionType) { + throw new PhutilInvalidStateException('setTransactionType'); + } + return $this->transactionType; + } + + public function setTransactionType($type) { + $this->transactionType = $type; + return $this; + } + + public function readValueFromRequest(AphrontRequest $request) { + $check = array_merge(array($this->getKey()), $this->getAliases()); + foreach ($check as $key) { + if (!$this->getValueExistsInRequest($request, $key)) { + continue; + } + + $this->value = $this->getValueFromRequest($request, $key); + return; + } + + $this->readValueFromObject($this->getObject()); + + return $this; + } + + public function readValueFromObject($object) { + $this->value = $this->getValueFromObject($object); + return $this; + } + + protected function getValueFromObject($object) { + if ($this->hasValue) { + return $this->value; + } else { + return $this->getDefaultValue(); + } + } + + protected function getValueExistsInRequest(AphrontRequest $request, $key) { + return $this->getValueExistsInSubmit($request, $key); + } + + protected function getValueFromRequest(AphrontRequest $request, $key) { + return $this->getValueFromSubmit($request, $key); + } + + public function readValueFromSubmit(AphrontRequest $request) { + $key = $this->getKey(); + if ($this->getValueExistsInSubmit($request, $key)) { + $value = $this->getValueFromSubmit($request, $key); + } else { + $value = $this->getDefaultValue(); + } + $this->value = $value; + return $this; + } + + protected function getValueExistsInSubmit(AphrontRequest $request, $key) { + return $this->getHTTPParameterType()->getExists($request, $key); + } + + protected function getValueFromSubmit(AphrontRequest $request, $key) { + return $this->getHTTPParameterType()->getValue($request, $key); + } + + protected function getDefaultValue() { + return $this->getHTTPParameterType()->getDefaultValue(); + } + + final public function getHTTPParameterType() { + $type = $this->newHTTPParameterType(); + + if ($type) { + $type->setViewer($this->getViewer()); + } + + return $type; + } + + protected function newHTTPParameterType() { + return new AphrontStringHTTPParameterType(); + } + + public function setEditTypeKey($edit_type_key) { + $this->editTypeKey = $edit_type_key; + return $this; + } + + public function getEditTypeKey() { + if ($this->editTypeKey === null) { + return $this->getKey(); + } + return $this->editTypeKey; + } + + public function getEditTransactionTypes() { + $transaction_type = $this->getTransactionType(); + $type_key = $this->getEditTypeKey(); + + // TODO: This is a pretty big pile of hard-coded hacks for now. + + $edge_types = array( + PhabricatorTransactions::TYPE_EDGE => array( + '+' => pht('Add projects.'), + '-' => pht('Remove projects.'), + '=' => pht('Set associated projects, overwriting current value.'), + ), + PhabricatorTransactions::TYPE_SUBSCRIBERS => array( + '+' => pht('Add subscribers.'), + '-' => pht('Remove subscribers.'), + '=' => pht('Set subscribers, overwriting current value.'), + ), + ); + + if (isset($edge_types[$transaction_type])) { + $base = id(new PhabricatorEdgeEditType()) + ->setTransactionType($transaction_type) + ->setMetadata($this->metadata); + + $strings = $edge_types[$transaction_type]; + + $add = id(clone $base) + ->setEditType($type_key.'.add') + ->setEdgeOperation('+') + ->setDescription($strings['+']) + ->setValueDescription(pht('List of PHIDs to add.')); + $rem = id(clone $base) + ->setEditType($type_key.'.remove') + ->setEdgeOperation('-') + ->setDescription($strings['-']) + ->setValueDescription(pht('List of PHIDs to remove.')); + $set = id(clone $base) + ->setEditType($type_key.'.set') + ->setEdgeOperation('=') + ->setDescription($strings['=']) + ->setValueDescription(pht('List of PHIDs to set.')); + + return array( + $add, + $rem, + $set, + ); + } + + return array( + id(new PhabricatorSimpleEditType()) + ->setEditType($type_key) + ->setTransactionType($transaction_type) + ->setValueType($this->getHTTPParameterType()->getTypeName()) + ->setDescription($this->getDescription()) + ->setMetadata($this->metadata), + ); + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorPolicyEditField.php b/src/applications/transactions/editfield/PhabricatorPolicyEditField.php new file mode 100644 index 0000000000..a4457e9fe6 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorPolicyEditField.php @@ -0,0 +1,58 @@ +policies = $policies; + return $this; + } + + public function getPolicies() { + if ($this->policies === null) { + throw new PhutilInvalidStateException('setPolicies'); + } + return $this->policies; + } + + public function setCapability($capability) { + $this->capability = $capability; + return $this; + } + + public function getCapability() { + return $this->capability; + } + + public function setSpaceField(PhabricatorSpaceEditField $space_field) { + $this->spaceField = $space_field; + return $this; + } + + public function getSpaceField() { + return $this->spaceField; + } + + protected function newControl() { + $control = id(new AphrontFormPolicyControl()) + ->setCapability($this->getCapability()) + ->setPolicyObject($this->getObject()) + ->setPolicies($this->getPolicies()); + + $space_field = $this->getSpaceField(); + if ($space_field) { + $control->setSpacePHID($space_field->getValueForControl()); + } + + return $control; + } + + protected function newHTTPParameterType() { + return new AphrontPHIDHTTPParameterType(); + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorProjectsEditField.php b/src/applications/transactions/editfield/PhabricatorProjectsEditField.php new file mode 100644 index 0000000000..60e497b4d2 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorProjectsEditField.php @@ -0,0 +1,14 @@ +options = $options; + return $this; + } + + public function getOptions() { + if ($this->options === null) { + throw new PhutilInvalidStateException('setOptions'); + } + return $this->options; + } + + protected function newControl() { + return id(new AphrontFormSelectControl()) + ->setOptions($this->getOptions()); + } + + protected function newHTTPParameterType() { + return new AphrontSelectHTTPParameterType(); + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorSpaceEditField.php b/src/applications/transactions/editfield/PhabricatorSpaceEditField.php new file mode 100644 index 0000000000..124f0c2ddf --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorSpaceEditField.php @@ -0,0 +1,16 @@ +monospaced = $monospaced; + return $this; + } + + public function getMonospaced() { + return $this->monospaced; + } + + public function setHeight($height) { + $this->height = $height; + return $this; + } + + public function getHeight() { + return $this->height; + } + + protected function newControl() { + $control = new AphrontFormTextAreaControl(); + + if ($this->getMonospaced()) { + $control->setCustomClass('PhabricatorMonospaced'); + } + + $height = $this->getHeight(); + if ($height) { + $control->setHeight($height); + } + + return $control; + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorTextEditField.php b/src/applications/transactions/editfield/PhabricatorTextEditField.php new file mode 100644 index 0000000000..25659d5710 --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorTextEditField.php @@ -0,0 +1,10 @@ +setDatasource($this->newDatasource()); + + if ($this->originalValue !== null) { + $control->setOriginalValue($this->originalValue); + } + + return $control; + } + + public function setValue($value) { + $this->originalValue = $value; + return parent::setValue($value); + } + + protected function getValueFromSubmit(AphrontRequest $request, $key) { + // TODO: Maybe move this unusual read somewhere else so subclassing this + // correctly is easier? + $this->originalValue = $request->getArr($key.'.original'); + + return parent::getValueFromSubmit($request, $key); + } + + protected function getValueForTransaction() { + $new = parent::getValueForTransaction(); + + $edge_types = array( + PhabricatorTransactions::TYPE_EDGE => true, + PhabricatorTransactions::TYPE_SUBSCRIBERS => true, + ); + + if (isset($edge_types[$this->getTransactionType()])) { + if ($this->originalValue !== null) { + // If we're building an edge transaction and the request has data + // about the original value the user saw when they loaded the form, + // interpret the edit as a mixture of "+" and "-" operations instead + // of a single "=" operation. This limits our exposure to race + // conditions by making most concurrent edits merge correctly. + + $new = parent::getValueForTransaction(); + $old = $this->originalValue; + + $add = array_diff($new, $old); + $rem = array_diff($old, $new); + + $value = array(); + + if ($add) { + $value['+'] = array_fuse($add); + } + if ($rem) { + $value['-'] = array_fuse($rem); + } + + return $value; + } else { + + if (!is_array($new)) { + throw new Exception(print_r($new, true)); + } + + return array( + '=' => array_fuse($new), + ); + } + } + + return $new; + } + + protected function newHTTPParameterType() { + return new AphrontPHIDListHTTPParameterType(); + } + +} diff --git a/src/applications/transactions/editfield/PhabricatorUsersEditField.php b/src/applications/transactions/editfield/PhabricatorUsersEditField.php new file mode 100644 index 0000000000..0f5cb6dcbe --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorUsersEditField.php @@ -0,0 +1,14 @@ +applicationEmail; } + public function getTransactionTypesForObject($object) { + $old = $this->object; + try { + $this->object = $object; + $result = $this->getTransactionTypes(); + $this->object = $old; + } catch (Exception $ex) { + $this->object = $old; + throw $ex; + } + return $result; + } + public function getTransactionTypes() { $types = array(); @@ -1650,7 +1663,7 @@ abstract class PhabricatorApplicationTransactionEditor throw new Exception( pht( "Invalid '%s' value for PHID transaction. Value should contain only ". - "keys '%s' (add PHIDs), '%' (remove PHIDs) and '%s' (set PHIDS).", + "keys '%s' (add PHIDs), '%s' (remove PHIDs) and '%s' (set PHIDS).", 'new', '+', '-', @@ -2164,6 +2177,51 @@ abstract class PhabricatorApplicationTransactionEditor return true; } + /** + * Check that text field input isn't longer than a specified length. + * + * A text field input is invalid if the length of the input is longer than a + * specified length. This length can be determined by the space allotted in + * the database, or given arbitrarily. + * This method is intended to make implementing @{method:validateTransaction} + * more convenient: + * + * $overdrawn = $this->validateIsTextFieldTooLong( + * $object->getName(), + * $xactions, + * $field_length); + * + * This will return `true` if the net effect of the object and transactions + * is a field that is too long. + * + * @param wild Current field value. + * @param list Transactions editing the + * field. + * @param integer for maximum field length. + * @return bool True if the field will be too long after edits. + */ + protected function validateIsTextFieldTooLong( + $field_value, + array $xactions, + $length) { + + if ($xactions) { + $new_value_length = phutil_utf8_strlen(last($xactions)->getNewValue()); + if ($new_value_length <= $length) { + return false; + } else { + return true; + } + } + + $old_value_length = phutil_utf8_strlen($field_value); + if ($old_value_length <= $length) { + return false; + } + + return true; + } + /* -( Implicit CCs )------------------------------------------------------- */ diff --git a/src/applications/transactions/edittype/PhabricatorEdgeEditType.php b/src/applications/transactions/edittype/PhabricatorEdgeEditType.php new file mode 100644 index 0000000000..17d1441a80 --- /dev/null +++ b/src/applications/transactions/edittype/PhabricatorEdgeEditType.php @@ -0,0 +1,51 @@ +edgeOperation = $edge_operation; + return $this; + } + + public function getEdgeOperation() { + return $this->edgeOperation; + } + + public function getValueType() { + return 'list'; + } + + public function generateTransaction( + PhabricatorApplicationTransaction $template, + array $spec) { + + $value = idx($spec, 'value'); + $value = array_fuse($value); + $value = array( + $this->getEdgeOperation() => $value, + ); + + $template + ->setTransactionType($this->getTransactionType()) + ->setNewValue($value); + + foreach ($this->getMetadata() as $key => $value) { + $template->setMetadataValue($key, $value); + } + + return $template; + } + + public function setValueDescription($value_description) { + $this->valueDescription = $value_description; + return $this; + } + + public function getValueDescription() { + return $this->valueDescription; + } + +} diff --git a/src/applications/transactions/edittype/PhabricatorEditType.php b/src/applications/transactions/edittype/PhabricatorEditType.php new file mode 100644 index 0000000000..a1e580f6fd --- /dev/null +++ b/src/applications/transactions/edittype/PhabricatorEditType.php @@ -0,0 +1,76 @@ +description = $description; + return $this; + } + + public function getDescription() { + return $this->description; + } + + public function setSummary($summary) { + $this->summary = $summary; + return $this; + } + + public function getSummary() { + if ($this->summary === null) { + return $this->getDescription(); + } + return $this->summary; + } + + public function setField(PhabricatorEditField $field) { + $this->field = $field; + return $this; + } + + public function getField() { + return $this->field; + } + + public function setEditType($edit_type) { + $this->editType = $edit_type; + return $this; + } + + public function getEditType() { + return $this->editType; + } + + public function setMetadata($metadata) { + $this->metadata = $metadata; + return $this; + } + + public function getMetadata() { + return $this->metadata; + } + + public function setTransactionType($transaction_type) { + $this->transactionType = $transaction_type; + return $this; + } + + public function getTransactionType() { + return $this->transactionType; + } + + abstract public function generateTransaction( + PhabricatorApplicationTransaction $template, + array $spec); + + abstract public function getValueType(); + abstract public function getValueDescription(); + +} diff --git a/src/applications/transactions/edittype/PhabricatorSimpleEditType.php b/src/applications/transactions/edittype/PhabricatorSimpleEditType.php new file mode 100644 index 0000000000..3aa0575579 --- /dev/null +++ b/src/applications/transactions/edittype/PhabricatorSimpleEditType.php @@ -0,0 +1,41 @@ +valueType = $value_type; + return $this; + } + + public function getValueType() { + return $this->valueType; + } + + public function generateTransaction( + PhabricatorApplicationTransaction $template, + array $spec) { + + $template + ->setTransactionType($this->getTransactionType()) + ->setNewValue(idx($spec, 'value')); + + foreach ($this->getMetadata() as $key => $value) { + $template->setMetadataValue($key, $value); + } + + return $template; + } + + public function setValueDescription($value_description) { + $this->valueDescription = $value_description; + return $this; + } + + public function getValueDescription() { + return $this->valueDescription; + } + +} diff --git a/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php b/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php index ccb5d271ab..e6184b1ae4 100644 --- a/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php +++ b/src/applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php @@ -16,6 +16,10 @@ final class PhabricatorApplicationTransactionTransactionPHIDType return null; } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorTransactionsApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $object_query, array $phids) { diff --git a/src/applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php b/src/applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php index c5af940f41..c4f6defc21 100644 --- a/src/applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php +++ b/src/applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php @@ -32,16 +32,16 @@ final class PhabricatorApplicationTransactionNoEffectResponse $only_empty_comment = (count($xactions) == 1) && (head($xactions)->getTransactionType() == $type_comment); - $count = new PhutilNumber(count($xactions)); + $count = phutil_count($xactions); if ($ex->hasAnyEffect()) { - $title = pht('%d Action(s) With No Effect', $count); - $head = pht('Some of your %d action(s) have no effect:', $count); + $title = pht('%s Action(s) With No Effect', $count); + $head = pht('Some of your %s action(s) have no effect:', $count); $tail = pht('Apply remaining actions?'); $continue = pht('Apply Remaining Actions'); } else if ($ex->hasComment()) { $title = pht('Post as Comment'); - $head = pht('The %d action(s) you are taking have no effect:', $count); + $head = pht('The %s action(s) you are taking have no effect:', $count); $tail = pht('Do you want to post your comment anyway?'); $continue = pht('Post Comment'); } else if ($only_empty_comment) { @@ -52,8 +52,8 @@ final class PhabricatorApplicationTransactionNoEffectResponse $tail = null; $continue = null; } else { - $title = pht('%d Action(s) Have No Effect', $count); - $head = pht('The %d action(s) you are taking have no effect:', $count); + $title = pht('%s Action(s) Have No Effect', $count); + $head = pht('The %s action(s) you are taking have no effect:', $count); $tail = null; $continue = null; } diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index e33049dcc7..a61de01978 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -710,19 +710,19 @@ abstract class PhabricatorApplicationTransaction return $type_obj->getTransactionEditString( $this->renderHandleLink($author_phid), new PhutilNumber(count($add) + count($rem)), - new PhutilNumber(count($add)), + phutil_count($add), $this->renderHandleList($add), - new PhutilNumber(count($rem)), + phutil_count($rem), $this->renderHandleList($rem)); } else if ($add) { return $type_obj->getTransactionAddString( $this->renderHandleLink($author_phid), - new PhutilNumber(count($add)), + phutil_count($add), $this->renderHandleList($add)); } else if ($rem) { return $type_obj->getTransactionRemoveString( $this->renderHandleLink($author_phid), - new PhutilNumber(count($rem)), + phutil_count($rem), $this->renderHandleList($rem)); } else { return $type_obj->getTransactionPreviewString( @@ -871,21 +871,21 @@ abstract class PhabricatorApplicationTransaction $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), new PhutilNumber(count($add) + count($rem)), - new PhutilNumber(count($add)), + phutil_count($add), $this->renderHandleList($add), - new PhutilNumber(count($rem)), + phutil_count($rem), $this->renderHandleList($rem)); } else if ($add) { return $type_obj->getFeedAddString( $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), - new PhutilNumber(count($add)), + phutil_count($add), $this->renderHandleList($add)); } else if ($rem) { return $type_obj->getFeedRemoveString( $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), - new PhutilNumber(count($rem)), + phutil_count($rem), $this->renderHandleList($rem)); } else { return pht( diff --git a/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php new file mode 100644 index 0000000000..e75ef846fc --- /dev/null +++ b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php @@ -0,0 +1,257 @@ +object = $object; + return $this; + } + + public function getObject() { + return $this->object; + } + + public function setFields(array $fields) { + $this->fields = $fields; + return $this; + } + + public function getFields() { + return $this->fields; + } + + public function render() { + $object = $this->getObject(); + $fields = $this->getFields(); + + $uri = 'https://your.install.com/application/edit/'; + + // Remove fields which do not expose an HTTP parameter type. + $types = array(); + foreach ($fields as $key => $field) { + $type = $field->getHTTPParameterType(); + if ($type === null) { + unset($fields[$key]); + } + $types[$type->getTypeName()] = $type; + } + + $intro = pht(<<getLabel(), + $field->getKey(), + $field->getHTTPParameterType()->getTypeName(), + $field->getDescription(), + ); + } + + $main_table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + pht('Label'), + pht('Key'), + pht('Type'), + pht('Description'), + )) + ->setColumnClasses( + array( + 'pri', + null, + null, + 'wide', + )); + + $aliases_text = pht(<<getAliases(); + if (!$aliases) { + continue; + } + $rows[] = array( + $field->getLabel(), + $field->getKey(), + implode(', ', $aliases), + ); + } + + $alias_table = id(new AphrontTableView($rows)) + ->setNoDataString(pht('This object has no fields with aliases.')) + ->setHeaders( + array( + pht('Label'), + pht('Key'), + pht('Aliases'), + )) + ->setColumnClasses( + array( + 'pri', + null, + 'wide', + )); + + $select_text = pht(<<getOptions(); + $label = $field->getLabel(); + foreach ($options as $option_key => $option_value) { + if (strlen($option_key)) { + $option_display = $option_key; + } else { + $option_display = phutil_tag('em', array(), pht('')); + } + + $rows[] = array( + $label, + $option_display, + $option_value, + ); + $label = null; + } + } + + $select_table = id(new AphrontTableView($rows)) + ->setNoDataString(pht('This object has no select fields.')) + ->setHeaders( + array( + pht('Field'), + pht('Value'), + pht('Label'), + )) + ->setColumnClasses( + array( + 'pri', + null, + 'wide', + )); + + $types_text = pht(<<setHTTPParameterTypes($types); + + return array( + $this->renderInstructions($intro), + $main_table, + $this->renderInstructions($aliases_text), + $alias_table, + $this->renderInstructions($select_text), + $select_table, + $this->renderInstructions($types_text), + $types_table, + ); + } + + protected function renderInstructions($corpus) { + $viewer = $this->getUser(); + return new PHUIRemarkupView($viewer, $corpus); + } + +} diff --git a/src/docs/contributor/phabricator_code_layout.diviner b/src/docs/contributor/phabricator_code_layout.diviner index d563d0e2e0..19ec048f73 100644 --- a/src/docs/contributor/phabricator_code_layout.diviner +++ b/src/docs/contributor/phabricator_code_layout.diviner @@ -85,10 +85,9 @@ However, it is likely that `Derp` is even more complex, and rather than containing one class, each directory has several classes. A typical example happens around the CRUD of an object: - - **DerpBaseController**: typically extends @{class:PhabricatorController}, - implements `buildStandardPageResponse` with the `Derp` application name - and other `Derp`-specific meta-data, and contains any controller-specific - functionality used throughout the `Derp` application. + - **DerpBaseController**: typically extends @{class:PhabricatorController} + and contains any controller-specific functionality used throughout the + `Derp` application. - **DerpDeleteController**: typically extends `DerpBaseController` and presents a confirmation dialogue to the user about deleting a `Derp`. - **DerpEditController**: typically extends `DerpBaseController` and diff --git a/src/docs/user/userguide/remarkup.diviner b/src/docs/user/userguide/remarkup.diviner index ca20751c47..c56600ebdf 100644 --- a/src/docs/user/userguide/remarkup.diviner +++ b/src/docs/user/userguide/remarkup.diviner @@ -19,6 +19,7 @@ formatting text in Remarkup. These are inline styles, and can be applied to most text: **bold** //italic// `monospaced` ##monospaced## ~~deleted~~ __underlined__ + !!highlighted!! D123 T123 rX123 # Link to Objects {D123} {T123} # Link to Objects (Full Name) {F123} # Embed Images @@ -63,9 +64,11 @@ Format **basic text styles** like this: ##monospaced text## ~~deleted text~~ __underlined text__ + !!highlighted text!! Those produce **bold text**, //italic text//, `monospaced text`, ##monospaced -text##, ~~deleted text~~, and __underlined text__, respectively. +text##, ~~deleted text~~, __underlined text__, and !!highlighted text!! +respectively. = Layout = diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php index 81b94aff31..4c3159a621 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php @@ -117,23 +117,23 @@ abstract class PhabricatorStandardCustomFieldPHIDs '%s updated %s, added %d: %s.', $xaction->renderHandleLink($author_phid), $this->getFieldName(), - new PhutilNumber(count($add)), + phutil_count($add), $xaction->renderHandleList($add)); } else if ($rem && !$add) { return pht( - '%s updated %s, removed %d: %s.', + '%s updated %s, removed %s: %s.', $xaction->renderHandleLink($author_phid), $this->getFieldName(), - new PhutilNumber(count($rem)), + phutil_count($rem), $xaction->renderHandleList($rem)); } else { return pht( - '%s updated %s, added %d: %s; removed %d: %s.', + '%s updated %s, added %s: %s; removed %s: %s.', $xaction->renderHandleLink($author_phid), $this->getFieldName(), - new PhutilNumber(count($add)), + phutil_count($add), $xaction->renderHandleList($add), - new PhutilNumber(count($rem)), + phutil_count($rem), $xaction->renderHandleList($rem)); } } diff --git a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php index 7550d1cf02..b94f7eab27 100644 --- a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php +++ b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorWorkerBulkJobPHIDType extends PhabricatorPHIDType { return new PhabricatorWorkerBulkJob(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDaemonsApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php index 02112c91b5..b1dadb568e 100644 --- a/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php +++ b/src/infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php @@ -12,6 +12,10 @@ final class PhabricatorWorkerTriggerPHIDType extends PhabricatorPHIDType { return new PhabricatorWorkerTrigger(); } + public function getPHIDTypeApplicationClass() { + return 'PhabricatorDaemonsApplication'; + } + protected function buildQueryForObjects( PhabricatorObjectQuery $query, array $phids) { diff --git a/src/infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php b/src/infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php index 3554a113ed..b22040de1a 100644 --- a/src/infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php +++ b/src/infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php @@ -37,7 +37,7 @@ final class PhabricatorInternationalizationManagementExtractWorkflow $console->writeOut( "%s\n", - pht('Found %s file(s)...', new PhutilNumber(count($futures)))); + pht('Found %s file(s)...', phutil_count($futures))); $results = array(); diff --git a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php index 5d3dc359d0..fd529dc35d 100644 --- a/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php +++ b/src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php @@ -32,7 +32,7 @@ final class PhabricatorUSEnglishTranslation '%d path(s)' => array('%d path', '%d paths'), '%d diff(s)' => array('%d diff', '%d diffs'), - '%d Answer(s)' => array('%d Answer', '%d Answers'), + '%s Answer(s)' => array('%s Answer', '%s Answers'), 'Show %d Comment(s)' => array('Show %d Comment', 'Show %d Comments'), '%s DIFF LINK(S)' => array('DIFF LINK', 'DIFF LINKS'), @@ -114,17 +114,17 @@ final class PhabricatorUSEnglishTranslation 'This is a binary file. It is %s bytes in length.', ), - '%d Action(s) Have No Effect' => array( + '%s Action(s) Have No Effect' => array( 'Action Has No Effect', 'Actions Have No Effect', ), - '%d Action(s) With No Effect' => array( + '%s Action(s) With No Effect' => array( 'Action With No Effect', 'Actions With No Effect', ), - 'Some of your %d action(s) have no effect:' => array( + 'Some of your %s action(s) have no effect:' => array( 'One of your actions has no effect:', 'Some of your actions have no effect:', ), @@ -139,7 +139,7 @@ final class PhabricatorUSEnglishTranslation 'Apply Remaining Actions', ), - 'The %d action(s) you are taking have no effect:' => array( + 'The %s action(s) you are taking have no effect:' => array( 'The action you are taking has no effect:', 'The actions you are taking have no effect:', ), @@ -550,9 +550,9 @@ final class PhabricatorUSEnglishTranslation ), ), - '%d comment(s)' => array('%d comment', '%d comments'), - '%d rejection(s)' => array('%d rejection', '%d rejections'), - '%d update(s)' => array('%d update', '%d updates'), + '%s comment(s)' => array('%s comment', '%s comments'), + '%s rejection(s)' => array('%s rejection', '%s rejections'), + '%s update(s)' => array('%s update', '%s updates'), 'This configuration value is defined in these %d '. 'configuration source(s): %s.' => array( @@ -562,9 +562,9 @@ final class PhabricatorUSEnglishTranslation 'configuration sources: %s.', ), - '%d Open Pull Request(s)' => array( - '%d Open Pull Request', - '%d Open Pull Requests', + '%s Open Pull Request(s)' => array( + '%s Open Pull Request', + '%s Open Pull Requests', ), 'Stale (%s day(s))' => array( @@ -816,8 +816,10 @@ final class PhabricatorUSEnglishTranslation ), '%s, %s line(s)' => array( - '%s, %s line', - '%s, %s lines', + array( + '%s, %s line', + '%s, %s lines', + ), ), '%s pushed %d commit(s) to %s.' => array( @@ -1153,6 +1155,10 @@ final class PhabricatorUSEnglishTranslation 'Found %s book.', 'Found %s books.', ), + 'Found %s file(s)...' => array( + 'Found %s file...', + 'Found %s files...', + ), 'Found %s file(s) in project.' => array( 'Found %s file in project.', 'Found %s files in project.', @@ -1392,6 +1398,10 @@ final class PhabricatorUSEnglishTranslation '%s Day', '%s Days', ), + '%s Day(s) Ago' => array( + '%s Day Ago', + '%s Days Ago', + ), 'Setting retention policy for "%s" to %s day(s).' => array( 'Setting retention policy for "%s" to one day.', @@ -1425,6 +1435,59 @@ final class PhabricatorUSEnglishTranslation 'WARNING: There are unapproved authorizations!', ), + 'Found %s Open Resource(s)' => array( + 'Found %s Open Resource', + 'Found %s Open Resources', + ), + + '%s Open Resource(s) Remain' => array( + '%s Open Resource Remain', + '%s Open Resources Remain', + ), + + 'Found %s Blueprint(s)' => array( + 'Found %s Blueprint', + 'Found %s Blueprints', + ), + + '%s Blueprint(s) Can Allocate' => array( + '%s Blueprint Can Allocate', + '%s Blueprints Can Allocate', + ), + + '%s Blueprint(s) Enabled' => array( + '%s Blueprint Enabled', + '%s Blueprints Enabled', + ), + + '%s Event(s)' => array( + '%s Event', + '%s Events', + ), + + '%s Unit(s)' => array( + '%s Unit', + '%s Units', + ), + + 'QUEUEING TASKS (%s Commit(s)):' => array( + 'QUEUEING TASKS (%s Commit):', + 'QUEUEING TASKS (%s Commits):', + ), + + 'Found %s total commit(s); updating...' => array( + 'Found %s total commit; updating...', + 'Found %s total commits; updating...', + ), + + 'Not enough process slots to schedule the other %s '. + 'repository(s) for updates yet.' => array( + 'Not enough process slots to schedule the other '.' + repository for update yet.', + 'Not enough process slots to schedule the other %s '. + 'repositories for updates yet.', + ), + ); } diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php index c6babe99e0..ed51b00175 100644 --- a/src/infrastructure/markup/PhabricatorMarkupEngine.php +++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php @@ -510,6 +510,7 @@ final class PhabricatorMarkupEngine extends Phobject { $rules[] = new PhutilRemarkupItalicRule(); $rules[] = new PhutilRemarkupDelRule(); $rules[] = new PhutilRemarkupUnderlineRule(); + $rules[] = new PhutilRemarkupHighlightRule(); foreach (self::loadCustomInlineRules() as $rule) { $rules[] = $rule; diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php index e31e484c53..62b2651f70 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php @@ -126,7 +126,7 @@ abstract class PhabricatorStorageManagementWorkflow "documentation.\n\n". "MySQL needs to copy table data to make some adjustments, so these ". "migrations may take some time.", - new PhutilNumber(count($adjustments)))); + phutil_count($adjustments))); $prompt = pht('Fix these schema issues?'); if (!phutil_console_confirm($prompt, $default_no = true)) { diff --git a/src/view/control/AphrontTokenizerTemplateView.php b/src/view/control/AphrontTokenizerTemplateView.php index fd4893dd4d..b8c2c6f2cc 100644 --- a/src/view/control/AphrontTokenizerTemplateView.php +++ b/src/view/control/AphrontTokenizerTemplateView.php @@ -6,6 +6,7 @@ final class AphrontTokenizerTemplateView extends AphrontView { private $name; private $id; private $browseURI; + private $originalValue; public function setBrowseURI($browse_uri) { $this->browseURI = $browse_uri; @@ -36,6 +37,15 @@ final class AphrontTokenizerTemplateView extends AphrontView { return $this->name; } + public function setOriginalValue(array $original_value) { + $this->originalValue = $original_value; + return $this; + } + + public function getOriginalValue() { + return $this->originalValue; + } + public function render() { require_celerity_resource('aphront-tokenizer-control-css'); @@ -85,6 +95,20 @@ final class AphrontTokenizerTemplateView extends AphrontView { $classes[] = 'has-browse'; } + $original = array(); + $original_value = $this->getOriginalValue(); + if ($original_value) { + foreach ($this->getOriginalValue() as $value) { + $original[] = phutil_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => $name.'.original[]', + 'value' => $value, + )); + } + } + $frame = javelin_tag( 'div', array( @@ -94,6 +118,7 @@ final class AphrontTokenizerTemplateView extends AphrontView { array( $container, $browse, + $original, )); return $frame; diff --git a/src/view/form/control/AphrontFormTokenizerControl.php b/src/view/form/control/AphrontFormTokenizerControl.php index fd25f66a1f..60c8962e78 100644 --- a/src/view/form/control/AphrontFormTokenizerControl.php +++ b/src/view/form/control/AphrontFormTokenizerControl.php @@ -7,6 +7,7 @@ final class AphrontFormTokenizerControl extends AphrontFormControl { private $limit; private $placeholder; private $handles; + private $originalValue; public function setDatasource(PhabricatorTypeaheadDatasource $datasource) { $this->datasource = $datasource; @@ -32,6 +33,15 @@ final class AphrontFormTokenizerControl extends AphrontFormControl { return $this; } + public function setOriginalValue(array $original_value) { + $this->originalValue = $original_value; + return $this; + } + + public function getOriginalValue() { + return $this->originalValue; + } + public function willRender() { // Load the handles now so we'll get a bulk load later on when we actually // render them. @@ -69,10 +79,15 @@ final class AphrontFormTokenizerControl extends AphrontFormControl { $token->setInputName($this->getName()); } - $template = new AphrontTokenizerTemplateView(); - $template->setName($name); - $template->setID($id); - $template->setValue($tokens); + $template = id(new AphrontTokenizerTemplateView()) + ->setName($name) + ->setID($id) + ->setValue($tokens); + + $original_value = $this->getOriginalValue(); + if ($original_value !== null) { + $template->setOriginalValue($original_value); + } $username = null; if ($this->user) { diff --git a/src/view/layout/PHUIApplicationMenuView.php b/src/view/layout/PHUIApplicationMenuView.php new file mode 100644 index 0000000000..624b1f982d --- /dev/null +++ b/src/view/layout/PHUIApplicationMenuView.php @@ -0,0 +1,89 @@ +viewer = $viewer; + return $this; + } + + public function getViewer() { + return $this->viewer; + } + + public function addLabel($name) { + $item = id(new PHUIListItemView()) + ->setName($name); + + return $this->addItem($item); + } + + public function addLink($name, $href) { + $item = id(new PHUIListItemView()) + ->setName($name) + ->setHref($href); + + return $this->addItem($item); + } + + public function addItem(PHUIListItemView $item) { + $this->items[] = $item; + return $this; + } + + public function setSearchEngine(PhabricatorApplicationSearchEngine $engine) { + $this->searchEngine = $engine; + return $this; + } + + public function getSearchEngine() { + return $this->searchEngine; + } + + public function setCrumbs(PHUICrumbsView $crumbs) { + $this->crumbs = $crumbs; + return $this; + } + + public function getCrumbs() { + return $this->crumbs; + } + + public function buildListView() { + $viewer = $this->getViewer(); + + $view = id(new PHUIListView()) + ->setUser($viewer); + + $crumbs = $this->getCrumbs(); + if ($crumbs) { + $actions = $crumbs->getActions(); + if ($actions) { + $view->newLabel(pht('Create')); + foreach ($crumbs->getActions() as $action) { + $view->addMenuItem($action); + } + } + } + + $engine = $this->getSearchEngine(); + if ($engine) { + $engine + ->setViewer($viewer) + ->addNavigationItems($view); + } + + foreach ($this->items as $item) { + $view->addMenuItem($item); + } + + return $view; + } + +} diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index 90325bd54e..4aedb1a911 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -4,18 +4,23 @@ * This is a standard Phabricator page with menus, Javelin, DarkConsole, and * basic styles. */ -final class PhabricatorStandardPageView extends PhabricatorBarePageView { +final class PhabricatorStandardPageView extends PhabricatorBarePageView + implements AphrontResponseProducerInterface { private $baseURI; private $applicationName; private $glyph; private $menuContent; private $showChrome = true; + private $classes = array(); private $disableConsole; private $pageObjects = array(); private $applicationMenu; private $showFooter = true; private $showDurableColumn = true; + private $quicksandConfig = array(); + private $crumbs; + private $navigation; public function setShowFooter($show_footer) { $this->showFooter = $show_footer; @@ -26,7 +31,10 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { return $this->showFooter; } - public function setApplicationMenu(PHUIListView $application_menu) { + public function setApplicationMenu($application_menu) { + // NOTE: For now, this can either be a PHUIListView or a + // PHUIApplicationMenuView. + $this->applicationMenu = $application_menu; return $this; } @@ -67,10 +75,14 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { return $this->showChrome; } - public function appendPageObjects(array $objs) { - foreach ($objs as $obj) { - $this->pageObjects[] = $obj; - } + public function addClass($class) { + $this->classes[] = $class; + return $this; + } + + public function setPageObjectPHIDs(array $phids) { + $this->pageObjects = $phids; + return $this; } public function setShowDurableColumn($show) { @@ -124,6 +136,32 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { return (bool)$this->getUserPreference($column_key, 0); } + public function addQuicksandConfig(array $config) { + $this->quicksandConfig = $config + $this->quicksandConfig; + return $this; + } + + public function getQuicksandConfig() { + return $this->quicksandConfig; + } + + public function setCrumbs(PHUICrumbsView $crumbs) { + $this->crumbs = $crumbs; + return $this; + } + + public function getCrumbs() { + return $this->crumbs; + } + + public function setNavigation(AphrontSideNavFilterView $navigation) { + $this->navigation = $navigation; + return $this; + } + + public function getNavigation() { + return $this->navigation; + } public function getTitle() { $glyph_key = PhabricatorUserPreferences::PREFERENCE_TITLES; @@ -174,7 +212,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { require_celerity_resource('phabricator-standard-page-view'); require_celerity_resource('conpherence-durable-column-view'); require_celerity_resource('font-lato'); - require_celerity_resource('font-roboto-slab'); + require_celerity_resource('font-aleo'); Javelin::initBehavior('workflow', array()); @@ -265,8 +303,18 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { $menu->setController($this->getController()); } - if ($this->getApplicationMenu()) { - $menu->setApplicationMenu($this->getApplicationMenu()); + $application_menu = $this->getApplicationMenu(); + if ($application_menu) { + if ($application_menu instanceof PHUIApplicationMenuView) { + $crumbs = $this->getCrumbs(); + if ($crumbs) { + $application_menu->setCrumbs($crumbs); + } + + $application_menu = $application_menu->buildListView(); + } + + $menu->setApplicationMenu($application_menu); } $this->menuContent = $menu->render(); @@ -427,9 +475,26 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { private function renderPageBodyContent() { $console = $this->getConsole(); + $body = parent::getBody(); + + $nav = $this->getNavigation(); + if ($nav) { + $crumbs = $this->getCrumbs(); + if ($crumbs) { + $nav->setCrumbs($crumbs); + } + $nav->appendChild($body); + $body = phutil_implode_html('', array($nav->render())); + } else { + $crumbs = $this->getCrumbs(); + if ($crumbs) { + $body = phutil_implode_html('', array($crumbs, $body)); + } + } + return array( ($console ? hsprintf('') : null), - parent::getBody(), + $body, $this->renderFooter(), ); } @@ -511,7 +576,9 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { } $classes[] = 'phui-theme-'.PhabricatorEnv::getEnvConfig('ui.header-color'); - + foreach ($this->classes as $class) { + $classes[] = $class; + } return implode(' ', $classes); } @@ -611,11 +678,13 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { $foot); } - public function renderForQuicksand(array $extra_config) { + public function renderForQuicksand() { parent::willRenderPage(); $response = $this->renderPageBodyContent(); $response = $this->willSendResponse($response); + $extra_config = $this->getQuicksandConfig(); + return array( 'content' => hsprintf('%s', $response), ) + $this->buildQuicksandConfig() @@ -724,4 +793,37 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { return $user->loadPreferences()->getPreference($key, $default); } + public function produceAphrontResponse() { + $controller = $this->getController(); + + if (!$this->getApplicationMenu()) { + $application_menu = $controller->buildApplicationMenu(); + if ($application_menu) { + $this->setApplicationMenu($application_menu); + } + } + + $viewer = $this->getUser(); + if ($viewer && $viewer->getPHID()) { + $object_phids = $this->pageObjects; + foreach ($object_phids as $object_phid) { + PhabricatorFeedStoryNotification::updateObjectNotificationViews( + $viewer, + $object_phid); + } + } + + if ($this->getRequest()->isQuicksand()) { + $content = $this->renderForQuicksand(); + $response = id(new AphrontAjaxResponse()) + ->setContent($content); + } else { + $content = $this->render(); + $response = id(new AphrontWebpageResponse()) + ->setContent($content); + } + + return $response; + } + } diff --git a/src/view/phui/PHUICrumbsView.php b/src/view/phui/PHUICrumbsView.php index 11ec90fafe..f8f25b389c 100644 --- a/src/view/phui/PHUICrumbsView.php +++ b/src/view/phui/PHUICrumbsView.php @@ -41,6 +41,10 @@ final class PHUICrumbsView extends AphrontView { return $this; } + public function getActions() { + return $this->actions; + } + public function render() { require_celerity_resource('phui-crumbs-view-css'); diff --git a/src/view/phui/PHUIDocumentViewPro.php b/src/view/phui/PHUIDocumentViewPro.php new file mode 100644 index 0000000000..1fbdd11cfc --- /dev/null +++ b/src/view/phui/PHUIDocumentViewPro.php @@ -0,0 +1,136 @@ +setTall(true); + $this->header = $header; + return $this; + } + + public function setBook($name, $description) { + $this->bookname = $name; + $this->bookdescription = $description; + return $this; + } + + public function setFluid($fluid) { + $this->fluid = $fluid; + return $this; + } + + public function setPropertyList($view) { + $this->propertyList = $view; + return $this; + } + + public function setToc(PHUIListView $toc) { + $this->toc = $toc; + return $this; + } + + protected function getTagAttributes() { + $classes = array(); + + if ($this->fluid) { + $classes[] = 'phui-document-fluid'; + } + + return array( + 'class' => $classes, + ); + } + + protected function getTagContent() { + require_celerity_resource('phui-document-view-css'); + require_celerity_resource('phui-document-view-pro-css'); + Javelin::initBehavior('phabricator-reveal-content'); + + $classes = array(); + $classes[] = 'phui-document-view'; + $classes[] = 'phui-document-view-pro'; + + $book = null; + if ($this->bookname) { + $book = pht('%s (%s)', $this->bookname, $this->bookdescription); + } + + $main_content = $this->renderChildren(); + + if ($book) { + $this->header->setSubheader($book); + } + + $table_of_contents = null; + if ($this->toc) { + $toc = array(); + $toc_id = celerity_generate_unique_node_id(); + $toc[] = id(new PHUIButtonView()) + ->setTag('a') + ->setIconFont('fa-align-left') + ->setColor(PHUIButtonView::SIMPLE) + ->addClass('phui-document-toc') + ->addSigil('jx-toggle-class') + ->setMetaData(array( + 'map' => array( + $toc_id => 'phui-document-toc-open', + ), + )); + + $toc[] = phutil_tag( + 'div', + array( + 'class' => 'phui-list-sidenav phui-document-toc-list', + ), + $this->toc); + + $table_of_contents = phutil_tag( + 'div', + array( + 'class' => 'phui-document-toc-container', + 'id' => $toc_id, + ), + $toc); + } + + $content_inner = phutil_tag( + 'div', + array( + 'class' => 'phui-document-inner', + ), + array( + $table_of_contents, + $this->header, + $main_content, + )); + + $content = phutil_tag( + 'div', + array( + 'class' => 'phui-document-content', + ), + $content_inner); + + $view = phutil_tag( + 'div', + array( + 'class' => implode(' ', $classes), + ), + $content); + + $list = null; + if ($this->propertyList) { + $list = phutil_tag_div('phui-document-properties', $this->propertyList); + } + + return array($view, $list); + } + +} diff --git a/src/view/phui/PHUIHeaderView.php b/src/view/phui/PHUIHeaderView.php index 3370519ebf..45b176f9a4 100644 --- a/src/view/phui/PHUIHeaderView.php +++ b/src/view/phui/PHUIHeaderView.php @@ -128,7 +128,7 @@ final class PHUIHeaderView extends AphrontTagView { } else if ($age == 1) { $when = pht('Yesterday'); } else { - $when = pht('%d Days Ago', $age); + $when = pht('%s Day(s) Ago', new PhutilNumber($age)); } $this->setStatus('fa-clock-o bluegrey', null, pht('Updated %s', $when)); diff --git a/webroot/rsrc/css/aphront/table-view.css b/webroot/rsrc/css/aphront/table-view.css index 254599625f..b235fd9c47 100644 --- a/webroot/rsrc/css/aphront/table-view.css +++ b/webroot/rsrc/css/aphront/table-view.css @@ -155,6 +155,10 @@ th.aphront-table-view-sortable-selected { color: {$darkbluetext}; } +.aphront-table-view td.top { + vertical-align: top; +} + .aphront-table-view td.wide { white-space: normal; width: 100%; diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css index 3e24e597e3..35ccc5b1b3 100644 --- a/webroot/rsrc/css/application/base/standard-page-view.css +++ b/webroot/rsrc/css/application/base/standard-page-view.css @@ -25,6 +25,10 @@ color: {$greytext}; } +.device .phabricator-standard-page-footer { + margin: 4px 8px; +} + !print .phabricator-standard-page-footer { display: none; } diff --git a/webroot/rsrc/css/core/core.css b/webroot/rsrc/css/core/core.css index 87e6a98cce..c7229a54ae 100644 --- a/webroot/rsrc/css/core/core.css +++ b/webroot/rsrc/css/core/core.css @@ -173,3 +173,7 @@ hr { height: 2px; background: {$sky}; } + +html body.pro-white-background { + background-color: white; +} diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css index 3f4516f135..dc79a4cb64 100644 --- a/webroot/rsrc/css/core/remarkup.css +++ b/webroot/rsrc/css/core/remarkup.css @@ -363,35 +363,12 @@ body div.phabricator-remarkup.remarkup-has-toc padding-top: 0; } -body .phabricator-remarkup p:first-child, -body .phabricator-remarkup ul.remarkup-list:first-child, -body .phabricator-remarkup ol.remarkup-list:first-child, -body .phabricator-remarkup .remarkup-code-block:first-child, -body .phabricator-remarkup h1.remarkup-header:first-child, -body .phabricator-remarkup h2.remarkup-header:first-child, -body .phabricator-remarkup h3.remarkup-header:first-child, -body .phabricator-remarkup h4.remarkup-header:first-child, -body .phabricator-remarkup h5.remarkup-header:first-child, -body .phabricator-remarkup h6.remarkup-header:first-child, -body .phabricator-remarkup blockquote:first-child, -body .phabricator-remarkup table.remarkup-table:first-child, -body .phabricator-remarkup .remarkup-note:first-child { +body .phabricator-remarkup > *:first-child, +body .phabricator-remarkup .remarkup-header + * { margin-top: 0; } -body .phabricator-remarkup p:last-child, -body .phabricator-remarkup ul.remarkup-list:last-child, -body .phabricator-remarkup ol.remarkup-list:last-child, -body .phabricator-remarkup .remarkup-code-block:last-child, -body .phabricator-remarkup h1.remarkup-header:last-child, -body .phabricator-remarkup h2.remarkup-header:last-child, -body .phabricator-remarkup h3.remarkup-header:last-child, -body .phabricator-remarkup h4.remarkup-header:last-child, -body .phabricator-remarkup h5.remarkup-header:last-child, -body .phabricator-remarkup h6.remarkup-header:last-child, -body .phabricator-remarkup blockquote:last-child, -body .phabricator-remarkup table.remarkup-table:last-child, -body .phabricator-remarkup .remarkup-note:last-child { +body .phabricator-remarkup *:last-child { margin-bottom: 0; } @@ -543,3 +520,8 @@ var.remarkup-assist-textarea { background: {$thinblueborder}; margin: 24px 0; } + +.phabricator-remarkup .remarkup-highlight { + background-color: {$lightviolet}; + padding: 0 4px; +} diff --git a/webroot/rsrc/css/diviner/diviner-shared.css b/webroot/rsrc/css/diviner/diviner-shared.css index c43479f9d0..67a09616f7 100644 --- a/webroot/rsrc/css/diviner/diviner-shared.css +++ b/webroot/rsrc/css/diviner/diviner-shared.css @@ -8,7 +8,7 @@ } .diviner-table-view { - margin: 0 16px 24px; + margin: 0 0 24px; } .device-phone .diviner-table-view { @@ -65,38 +65,64 @@ padding: 0 8px 16px 0; } -body .diviner-document-section .phui-header-header { - width: 100%; +.phui-header-shell.diviner-section-header .phui-header-header { + color: #000; font-size: 20px; - font-weight: bold; - margin: 0; - padding: 0; +} + +body .diviner-view .diviner-document-section + .phui-header-shell.diviner-section-header { + padding: 0 24px 8px 0; + border-bottom: 1px solid {$thinblueborder}; + margin: 32px 0 16px; } body .diviner-document-section .phui-header-shell.phui-bleed-header { - padding: 0; + padding: 16px 0 0 0; + border-bottom: none; } -.phui-property-list-view + .diviner-document-section { - margin-top: -1px; +body .diviner-view .diviner-section-content .phui-header-shell { + margin: 24px 0 8px; + padding: 0; + border: none; } .diviner-message-not-documented { color: {$lightgreytext}; font-style: italic; - margin: 16px; + margin: 12px 0 32px; + font-size: {$biggerfontsize}; } -.diviner-atom-signature { - font-weight: normal; +.diviner-document-section .diviner-message-not-documented { + margin-left: 0; + margin-right: 0; +} + +.phui-document-content .phabricator-remarkup.diviner-remarkup-section { + padding: 16px 0 32px 0; } .diviner-atom-signature-name { font-weight: bold; + color: {$violet}; +} + +.diviner-atom-signature { + font-weight: normal; + color: #000; +} + +.phui-header-view .phui-header-header a.diviner-atom-signature-name { + color: {$violet}; +} + +.phui-header-view .phui-header-header a.diviner-atom-signature-name:hover { + text-decoration: underline !important; } .diviner-list .diviner-atom-signature { - color: {$violet}; margin-left: -16px; } @@ -126,7 +152,7 @@ body .diviner-document-section .phui-header-shell.phui-bleed-header { } .diviner-list { - padding-left: 12px; + padding-left: 17px; } .diviner-list li { @@ -150,8 +176,8 @@ body .diviner-document-section .phui-header-shell.phui-bleed-header { text-decoration: none; } -.device-desktop .diviner-book-item:hover { - background-color: #F5EEFF; +.device-desktop .diviner-book-item:hover .diviner-book-item-title { + color: {$violet}; } .diviner-book-item-title { diff --git a/webroot/rsrc/css/font/font-aleo.css b/webroot/rsrc/css/font/font-aleo.css new file mode 100644 index 0000000000..91ef6e2dc4 --- /dev/null +++ b/webroot/rsrc/css/font/font-aleo.css @@ -0,0 +1,40 @@ +/** + * @provides font-aleo + * @requires phui-fontkit-css + */ + +@font-face { + font-family: 'Aleo'; + font-weight: bold; + font-style: normal; + src: url(/rsrc/externals/font/aleo/aleo-bold.eot); + src: url(/rsrc/externals/font/aleo/aleo-bold.eot?#iefix) + format('embedded-opentype'), + url(/rsrc/externals/font/aleo/aleo-bold.woff2) + format('woff2'), + url(/rsrc/externals/font/aleo/aleo-bold.woff) + format('woff'), + url(/rsrc/externals/font/aleo/aleo-bold.ttf) + format('truetype'), + url(/rsrc/externals/font/aleo/aleo-bold.svg#aleo-bold) + format('svg'); + +} + +@font-face { + font-family: 'Aleo'; + font-weight: normal; + font-style: normal; + src: url(/rsrc/externals/font/aleo/aleo-regular.eot); + src: url(/rsrc/externals/font/aleo/aleo-regular.eot?#iefix) + format('embedded-opentype'), + url(/rsrc/externals/font/aleo/aleo-regular.woff2) + format('woff2'), + url(/rsrc/externals/font/aleo/aleo-regular.woff) + format('woff'), + url(/rsrc/externals/font/aleo/aleo-regular.ttf) + format('truetype'), + url(/rsrc/externals/font/aleo/aleo-regular.svg#aleo-regular) + format('svg'); + +} diff --git a/webroot/rsrc/css/font/font-roboto-slab.css b/webroot/rsrc/css/font/font-roboto-slab.css deleted file mode 100644 index fbfd5c7a35..0000000000 --- a/webroot/rsrc/css/font/font-roboto-slab.css +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @provides font-roboto-slab - * @requires phui-fontkit-css - */ - -@font-face { - font-family: 'Roboto Slab'; - font-weight: normal; - font-style: normal; - src: url(/rsrc/externals/font/robotoslab/robotoslab-regular.eot); - src: url(/rsrc/externals/font/robotoslab/robotoslab-regular.eot?#iefix) - format('embedded-opentype'), - url(/rsrc/externals/font/robotoslab/robotoslab-regular.woff2) - format('woff2'), - url(/rsrc/externals/font/robotoslab/robotoslab-regular.woff) - format('woff'), - url(/rsrc/externals/font/robotoslab/robotoslab-regular.ttf) - format('truetype'), - url(/rsrc/externals/font/robotoslab/robotoslab-regular.svg#roboto_slabregular) - format('svg'); - -} diff --git a/webroot/rsrc/css/phui/phui-document-pro.css b/webroot/rsrc/css/phui/phui-document-pro.css new file mode 100644 index 0000000000..3408c5b094 --- /dev/null +++ b/webroot/rsrc/css/phui/phui-document-pro.css @@ -0,0 +1,114 @@ +/** + * @provides phui-document-view-pro-css + */ + +.phui-document-view.phui-document-view-pro, +.phui-document-view-pro-box, +.phui-document-properties { + max-width: 800px; + padding: 0 16px; + position: relative; + margin: 16px auto; +} + +.phui-document-properties { + max-width: 768px; + background-color: {$lightgreybackground}; + margin: 16px auto; + border-radius: 3px; +} + +.device .phui-document-properties { + margin: 0 8px 16px; +} + +.device-phone .phui-document-view.phui-document-view-pro { + padding: 0 8px; + margin: 0 auto; +} + +.phui-document-view-pro .phui-document-toc { + position: absolute; + top: 18px; + left: -36px; +} + +a.button.phui-document-toc { + display: inline-block; + height: 16px; + width: 16px; + padding: 3px 8px 4px 8px; +} + +.phui-document-view-pro .phui-document-toc-list { + margin: 8px; + border: 1px solid {$blueborder}; + border-radius: 3px; + box-shadow: {$dropshadow}; + width: 200px; + position: absolute; + z-index: 30; + background-color: #fff; + top: 38px; + left: -44px; +} + +.device .phui-document-view-pro .phui-document-toc { + display: none; +} + +.phui-document-toc-list { + display: none; +} + +.phui-document-toc-open .phui-document-toc-list { + display: block; +} + +.phui-document-toc-open .phui-document-toc { + background-color: {$blue}; +} + +.phui-document-toc-open .phui-document-toc .phui-icon-view { + color: #fff; +} + +.phui-document-view-pro .phui-document-content .phabricator-remarkup { + padding: 16px 0; + line-height: 1.7em; +} + +.device-desktop .phui-document-view.phui-document-view-pro { + border: 0; +} + +.phui-document-view.phui-document-view-pro .phui-header-shell { + background: transparent; + border-bottom: 1px solid {$thinblueborder}; +} + +.phui-document-view.phui-document-view-pro .phui-header-shell { + margin: 0; + padding: 16px 0 32px; +} + +.device-phone .phui-document-view.phui-document-view-pro .phui-header-shell { + margin: 8px 0 0 0; + padding: 8px 0 20px; +} + +.phui-document-view.phui-document-view-pro .phui-header-tall + .phui-header-header { + font-size: 24px; + line-height: 30px; + color: #000; +} + +.device-phone .phui-document-view-pro .phui-header-subheader { + display: block; + padding: 8px 0 0 0; +} + +.phui-document-view-pro .phui-info-view { + margin: 16px 0 0 0; +} diff --git a/webroot/rsrc/css/phui/phui-document.css b/webroot/rsrc/css/phui/phui-document.css index d054850cf8..c13d99930c 100644 --- a/webroot/rsrc/css/phui/phui-document.css +++ b/webroot/rsrc/css/phui/phui-document.css @@ -86,18 +86,17 @@ .phui-header-shell.phui-header-no-backgound .phui-header-view { padding: 8px 0 4px; - font-size: {$biggestfontsize}; } .phui-document-content .phui-property-list-container { border-color: {$thinblueborder}; } -.phui-document-content .phui-property-list-view { +.legalpad .phui-document-content .phui-property-list-view { border: none; box-shadow: none; - margin: 0; - background-color: {$lightgreybackground}; + margin: 16px 0 0 0; + background-color: {$lightbluebackground}; } .phui-document-content { @@ -135,10 +134,6 @@ padding-right: 120px; } -.phui-document-view .phui-property-list-view { - border-bottom: 1px solid {$thinblueborder}; -} - .phui-document-view .phui-info-severity-nodata { background-color: {$lightgreybackground}; } @@ -173,19 +168,20 @@ body .phui-document-view .phui-header-shell.phui-bleed-header { .phui-document-view .phui-property-list-section-header { padding: 12px 16px 0px; + border-top: none; } .phui-document-view .phui-property-list-text-content { - padding: 0; + padding: 0 16px; } .phui-document-view .PhabricatorMonospaced, .phui-document-view .phabricator-remarkup .remarkup-code-block .remarkup-code { - font: 11px/14px "Menlo", "Consolas", "Monaco", monospace; + font: 11px/16px "Menlo", "Consolas", "Monaco", monospace; } .platform-windows .phui-document-view .PhabricatorMonospaced, .platform-windows .phui-document-view .phabricator-remarkup .remarkup-code-block .remarkup-code { - font: 12px/14px "Menlo", "Consolas", "Monaco", monospace; + font: 12px/16px "Menlo", "Consolas", "Monaco", monospace; } diff --git a/webroot/rsrc/css/phui/phui-fontkit.css b/webroot/rsrc/css/phui/phui-fontkit.css index 4021bf6f47..80a12f881a 100644 --- a/webroot/rsrc/css/phui/phui-fontkit.css +++ b/webroot/rsrc/css/phui/phui-fontkit.css @@ -9,13 +9,12 @@ */ .diviner-document-section .phui-header-header { - font-family: 'Roboto Slab', {$fontfamily}; - font-size: 20px; + font-family: 'Aleo', {$fontfamily}; color: #000; } .phui-document-view .phui-header-tall .phui-header-header { - font-family: 'Roboto Slab', {$fontfamily}; + font-family: 'Aleo', {$fontfamily}; } .phui-document-view .phabricator-remarkup h1.remarkup-header, @@ -24,11 +23,11 @@ .phui-document-view .phabricator-remarkup h4.remarkup-header, .phui-document-view .phabricator-remarkup h5.remarkup-header, .phui-document-view .phabricator-remarkup h6.remarkup-header { - font-family: 'Roboto Slab', {$fontfamily}; + font-family: 'Aleo', {$fontfamily}; } .phui-document-view .phabricator-remarkup h2.remarkup-header { padding: 0 24px 8px 0; border-bottom: 1px solid {$thinblueborder}; - margin: 24px 0 16px; + margin: 32px 0 16px; } diff --git a/webroot/rsrc/css/phui/phui-info-view.css b/webroot/rsrc/css/phui/phui-info-view.css index 24bbd18b1b..cb7c7e77ba 100644 --- a/webroot/rsrc/css/phui/phui-info-view.css +++ b/webroot/rsrc/css/phui/phui-info-view.css @@ -108,12 +108,6 @@ h1.phui-info-view-head { color: {$sh-greentext}; } -.legalpad .phui-info-view { - margin: 0; - border-radius: 0; - border-width: 0; -} - .aphront-dialog-body .phui-info-view { margin: 0 0 8px 0; } diff --git a/webroot/rsrc/externals/font/robotoslab/LICENSE.txt b/webroot/rsrc/externals/font/aleo/LICENSE.txt similarity index 100% rename from webroot/rsrc/externals/font/robotoslab/LICENSE.txt rename to webroot/rsrc/externals/font/aleo/LICENSE.txt diff --git a/webroot/rsrc/externals/font/aleo/aleo-bold.eot b/webroot/rsrc/externals/font/aleo/aleo-bold.eot new file mode 100644 index 0000000000..294fef7412 Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-bold.eot differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-bold.svg b/webroot/rsrc/externals/font/aleo/aleo-bold.svg new file mode 100644 index 0000000000..e49c14686d --- /dev/null +++ b/webroot/rsrc/externals/font/aleo/aleo-bold.svg @@ -0,0 +1,5078 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webroot/rsrc/externals/font/aleo/aleo-bold.ttf b/webroot/rsrc/externals/font/aleo/aleo-bold.ttf new file mode 100644 index 0000000000..b05d3e78e2 Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-bold.ttf differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-bold.woff b/webroot/rsrc/externals/font/aleo/aleo-bold.woff new file mode 100644 index 0000000000..a2c7a9d77b Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-bold.woff differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-bold.woff2 b/webroot/rsrc/externals/font/aleo/aleo-bold.woff2 new file mode 100644 index 0000000000..9f91470113 Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-bold.woff2 differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-regular.eot b/webroot/rsrc/externals/font/aleo/aleo-regular.eot new file mode 100644 index 0000000000..d73b2fa04b Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-regular.eot differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-regular.svg b/webroot/rsrc/externals/font/aleo/aleo-regular.svg new file mode 100644 index 0000000000..ec074310d0 --- /dev/null +++ b/webroot/rsrc/externals/font/aleo/aleo-regular.svg @@ -0,0 +1,4644 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/webroot/rsrc/externals/font/aleo/aleo-regular.ttf b/webroot/rsrc/externals/font/aleo/aleo-regular.ttf new file mode 100644 index 0000000000..dd20f0c10f Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-regular.ttf differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-regular.woff b/webroot/rsrc/externals/font/aleo/aleo-regular.woff new file mode 100644 index 0000000000..f484ee8aa6 Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-regular.woff differ diff --git a/webroot/rsrc/externals/font/aleo/aleo-regular.woff2 b/webroot/rsrc/externals/font/aleo/aleo-regular.woff2 new file mode 100644 index 0000000000..31f38c898f Binary files /dev/null and b/webroot/rsrc/externals/font/aleo/aleo-regular.woff2 differ diff --git a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.eot b/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.eot deleted file mode 100644 index 53cd255767..0000000000 Binary files a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.eot and /dev/null differ diff --git a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.svg b/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.svg deleted file mode 100644 index ffaa980bc1..0000000000 --- a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.svg +++ /dev/null @@ -1,8190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.ttf b/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.ttf deleted file mode 100644 index e3b5c681a5..0000000000 Binary files a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.ttf and /dev/null differ diff --git a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.woff b/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.woff deleted file mode 100644 index 8846ee68ef..0000000000 Binary files a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.woff and /dev/null differ diff --git a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.woff2 b/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.woff2 deleted file mode 100644 index 747f2eb6a1..0000000000 Binary files a/webroot/rsrc/externals/font/robotoslab/robotoslab-regular.woff2 and /dev/null differ diff --git a/webroot/rsrc/js/core/behavior-fancy-datepicker.js b/webroot/rsrc/js/core/behavior-fancy-datepicker.js index c56d005dd8..4c58974fc5 100644 --- a/webroot/rsrc/js/core/behavior-fancy-datepicker.js +++ b/webroot/rsrc/js/core/behavior-fancy-datepicker.js @@ -300,10 +300,10 @@ JX.behavior('fancy-datepicker', function(config, statics) { // Render the calendar itself. NOTE: Javascript uses 0-based month indexes // while we use 1-based month indexes, so we have to adjust for that. var days = []; - var start = new Date( + var start = (new Date( valid_date.getYear() + 1900, valid_date.getMonth(), - 1).getDay() - week_start; + 1).getDay() - week_start + 7) % 7; while (start--) { days.push(cell('', null, false, 'day-placeholder'));