diff --git a/bin/hunks b/bin/hunks deleted file mode 120000 index dc2cf5492e..0000000000 --- a/bin/hunks +++ /dev/null @@ -1 +0,0 @@ -../scripts/setup/manage_hunks.php \ No newline at end of file diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 7771a79107..db83e57fc0 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -1,2459 +1,2489 @@ array( 'conpherence.pkg.css' => '0b64e988', 'conpherence.pkg.js' => '6249a1cf', - 'core.pkg.css' => '35e6c1ed', + 'core.pkg.css' => '55d12594', 'core.pkg.js' => 'e4260032', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => 'a4ba74b5', 'differential.pkg.js' => '634399e9', 'diffusion.pkg.css' => '91c5d3a6', 'diffusion.pkg.js' => '84c8f8fd', 'favicon.ico' => '30672e08', 'maniphest.pkg.css' => '4845691a', - 'maniphest.pkg.js' => '949a7498', + 'maniphest.pkg.js' => '5ab2753f', 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', 'rsrc/css/aphront/dark-console.css' => 'f54bf286', - 'rsrc/css/aphront/dialog-view.css' => '49b2a8a3', + 'rsrc/css/aphront/dialog-view.css' => '938f52c5', 'rsrc/css/aphront/list-filter-view.css' => '5d6f0526', 'rsrc/css/aphront/multi-column.css' => '84cc6640', 'rsrc/css/aphront/notification.css' => '3f6c89c9', 'rsrc/css/aphront/panel-view.css' => '8427b78d', 'rsrc/css/aphront/phabricator-nav-view.css' => 'b29426e9', 'rsrc/css/aphront/table-view.css' => '3225137a', 'rsrc/css/aphront/tokenizer.css' => '9a8cb501', 'rsrc/css/aphront/tooltip.css' => '1a07aea8', 'rsrc/css/aphront/typeahead-browse.css' => '8904346a', 'rsrc/css/aphront/typeahead.css' => 'd4f16145', 'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af', 'rsrc/css/application/auth/auth.css' => '0877ed6e', 'rsrc/css/application/base/main-menu-view.css' => 'f03e17be', 'rsrc/css/application/base/notification-menu.css' => '1e055865', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601', 'rsrc/css/application/base/phui-theme.css' => '798c69b8', 'rsrc/css/application/base/standard-page-view.css' => '894d8a25', 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/config/config-options.css' => '0ede4c9b', - 'rsrc/css/application/config/config-page.css' => 'b80124ae', + 'rsrc/css/application/config/config-page.css' => 'c1d5121b', 'rsrc/css/application/config/config-template.css' => '8f18fa41', 'rsrc/css/application/config/setup-issue.css' => 'f794cfc3', 'rsrc/css/application/config/unhandled-exception.css' => '4c96257a', 'rsrc/css/application/conpherence/durable-column.css' => 'd82e130c', 'rsrc/css/application/conpherence/header-pane.css' => '1c81cda6', 'rsrc/css/application/conpherence/menu.css' => '4f51db5a', 'rsrc/css/application/conpherence/message-pane.css' => 'b085d40d', 'rsrc/css/application/conpherence/notification.css' => '965db05b', 'rsrc/css/application/conpherence/participant-pane.css' => 'ac1baaa8', 'rsrc/css/application/conpherence/transaction.css' => '85129c68', 'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', 'rsrc/css/application/countdown/timer.css' => '16c52f5c', 'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a', 'rsrc/css/application/dashboard/dashboard.css' => 'bc6f2127', 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', 'rsrc/css/application/differential/add-comment.css' => 'c47f8c40', 'rsrc/css/application/differential/changeset-view.css' => 'b158cc46', 'rsrc/css/application/differential/core.css' => '5b7b8ff4', 'rsrc/css/application/differential/phui-inline-comment.css' => '5953c28e', 'rsrc/css/application/differential/revision-comment.css' => '14b8565a', 'rsrc/css/application/differential/revision-history.css' => '0e8eb855', 'rsrc/css/application/differential/revision-list.css' => 'f3c47d33', 'rsrc/css/application/differential/table-of-contents.css' => 'ae4b7a55', 'rsrc/css/application/diffusion/diffusion-icons.css' => 'd678600a', 'rsrc/css/application/diffusion/diffusion-readme.css' => '297373eb', 'rsrc/css/application/diffusion/diffusion-source.css' => '68b30fd3', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2', - 'rsrc/css/application/flag/flag.css' => '5337623f', + 'rsrc/css/application/flag/flag.css' => 'bba8f811', 'rsrc/css/application/harbormaster/harbormaster.css' => 'f491c9f4', 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 'rsrc/css/application/herald/herald.css' => 'dc31f6e9', 'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5', 'rsrc/css/application/maniphest/report.css' => '9b9580b7', 'rsrc/css/application/maniphest/task-edit.css' => 'fda62a9b', 'rsrc/css/application/maniphest/task-summary.css' => '11cc5344', 'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6', 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => '1898e534', 'rsrc/css/application/people/people-profile.css' => '2473d929', - 'rsrc/css/application/phame/phame.css' => '654dd9ef', + 'rsrc/css/application/phame/phame.css' => 'aeb61182', 'rsrc/css/application/pholio/pholio-edit.css' => '07676f51', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio.css' => 'ca89d380', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '8391eb02', 'rsrc/css/application/phortune/phortune-invoice.css' => '476055e2', 'rsrc/css/application/phortune/phortune.css' => '5b99dae0', 'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', 'rsrc/css/application/phriction/phriction-document-css.css' => '4282e4ad', 'rsrc/css/application/policy/policy-edit.css' => '815c66f7', 'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43', 'rsrc/css/application/policy/policy.css' => '957ea14c', 'rsrc/css/application/ponder/ponder-view.css' => 'fbd45f96', 'rsrc/css/application/project/project-card-view.css' => '9418c97d', - 'rsrc/css/application/project/project-view.css' => '55d99221', + 'rsrc/css/application/project/project-view.css' => '1e6f7072', 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/search/application-search-view.css' => '8452c849', - 'rsrc/css/application/search/search-results.css' => '7dea472c', + 'rsrc/css/application/search/search-results.css' => '64ad079a', 'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/core/core.css' => 'd0801452', 'rsrc/css/core/remarkup.css' => '8606d9c6', 'rsrc/css/core/syntax.css' => '769d3498', 'rsrc/css/core/z-index.css' => 'd1270942', 'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa', 'rsrc/css/font/font-aleo.css' => '8bdb2835', 'rsrc/css/font/font-awesome.css' => '2b7ebbcc', 'rsrc/css/font/font-lato.css' => 'c7ccd872', 'rsrc/css/font/phui-font-icon-base.css' => '870a7360', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', - 'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983', + 'rsrc/css/layout/phabricator-source-code-view.css' => '4383192f', 'rsrc/css/phui/calendar/phui-calendar-day.css' => '572b1893', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'fcc9fb41', 'rsrc/css/phui/calendar/phui-calendar-month.css' => '8e10e92c', 'rsrc/css/phui/calendar/phui-calendar.css' => '477acfaa', + 'rsrc/css/phui/object-item/phui-oi-big-ui.css' => '19f9369b', + 'rsrc/css/phui/object-item/phui-oi-color.css' => 'cd2b9b77', + 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'f12cbc9f', + 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6', + 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'bff632a4', + 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea', 'rsrc/css/phui/phui-action-list.css' => 'e1d48300', 'rsrc/css/phui/phui-action-panel.css' => '91c7b835', 'rsrc/css/phui/phui-badge.css' => '3baef8db', 'rsrc/css/phui/phui-basic-nav-view.css' => '7093573b', 'rsrc/css/phui/phui-big-info-view.css' => 'bd903741', - 'rsrc/css/phui/phui-box.css' => '5c8387cf', - 'rsrc/css/phui/phui-button.css' => '4a5fbe3d', + 'rsrc/css/phui/phui-box.css' => '33b629f8', + 'rsrc/css/phui/phui-button.css' => '43f4912e', 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', 'rsrc/css/phui/phui-cms.css' => 'be43c8a8', 'rsrc/css/phui/phui-comment-form.css' => 'c953b75e', 'rsrc/css/phui/phui-comment-panel.css' => 'f50152ad', - 'rsrc/css/phui/phui-crumbs-view.css' => '195ac419', + 'rsrc/css/phui/phui-crumbs-view.css' => 'f82868f2', 'rsrc/css/phui/phui-curtain-view.css' => '947bf1a4', 'rsrc/css/phui/phui-document-pro.css' => 'c354e312', 'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf', 'rsrc/css/phui/phui-document.css' => 'c32e8dec', 'rsrc/css/phui/phui-feed-story.css' => '44a9c8e9', 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', 'rsrc/css/phui/phui-form-view.css' => 'cd79ff6a', 'rsrc/css/phui/phui-form.css' => '2342b0e5', 'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f', 'rsrc/css/phui/phui-header-view.css' => '6ec8f155', 'rsrc/css/phui/phui-hovercard.css' => 'de1a2119', 'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad', 'rsrc/css/phui/phui-icon.css' => '09f46dd9', 'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-view.css' => 'ec92802a', 'rsrc/css/phui/phui-invisible-character-view.css' => '6993d9f0', 'rsrc/css/phui/phui-lightbox.css' => '0a035e40', 'rsrc/css/phui/phui-list.css' => '9da2aa00', 'rsrc/css/phui/phui-object-box.css' => '6b487c57', - 'rsrc/css/phui/phui-object-item-list-view.css' => '87278fa0', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', 'rsrc/css/phui/phui-profile-menu.css' => '4768721a', 'rsrc/css/phui/phui-property-list-view.css' => '6d8e58ac', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-segment-bar-view.css' => '46342871', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => 'd5263e49', - 'rsrc/css/phui/phui-tag-view.css' => '6bbd83e2', + 'rsrc/css/phui/phui-tag-view.css' => '84d65f26', 'rsrc/css/phui/phui-timeline-view.css' => 'bc523970', - 'rsrc/css/phui/phui-two-column-view.css' => 'ee61d056', + 'rsrc/css/phui/phui-two-column-view.css' => '7babf5b9', 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'b60ef38a', 'rsrc/css/phui/workboards/phui-workboard.css' => '16441d5e', - 'rsrc/css/phui/workboards/phui-workcard.css' => '0c62d7c5', - 'rsrc/css/phui/workboards/phui-workpanel.css' => '92197373', + 'rsrc/css/phui/workboards/phui-workcard.css' => '00979e40', + 'rsrc/css/phui/workboards/phui-workpanel.css' => 'a3a63478', 'rsrc/css/sprite-login.css' => '587d92d7', 'rsrc/css/sprite-tokens.css' => '9cdfd599', 'rsrc/css/syntax/syntax-default.css' => '9923583c', 'rsrc/externals/d3/d3.min.js' => 'a11a5ff2', 'rsrc/externals/font/aleo/aleo-bold.eot' => 'd3d3bed7', 'rsrc/externals/font/aleo/aleo-bold.svg' => '45899c8e', 'rsrc/externals/font/aleo/aleo-bold.ttf' => '4b08bef0', 'rsrc/externals/font/aleo/aleo-bold.woff' => '93b513a1', 'rsrc/externals/font/aleo/aleo-bold.woff2' => '75fbf322', 'rsrc/externals/font/aleo/aleo-regular.eot' => 'a4e29e2f', 'rsrc/externals/font/aleo/aleo-regular.svg' => '42a86f7a', 'rsrc/externals/font/aleo/aleo-regular.ttf' => '751e7479', 'rsrc/externals/font/aleo/aleo-regular.woff' => 'c3744be9', 'rsrc/externals/font/aleo/aleo-regular.woff2' => '851aa0ee', 'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '59b3076c', 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '45ad7e57', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => 'f861e2a8', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '0ee0f078', 'rsrc/externals/font/lato/lato-bold.eot' => '99fbcf8c', 'rsrc/externals/font/lato/lato-bold.svg' => '2aa83045', 'rsrc/externals/font/lato/lato-bold.ttf' => '0a7141f7', 'rsrc/externals/font/lato/lato-bold.woff' => 'f5db2061', 'rsrc/externals/font/lato/lato-bold.woff2' => '37a94ecd', 'rsrc/externals/font/lato/lato-bolditalic.eot' => 'b93389d0', 'rsrc/externals/font/lato/lato-bolditalic.svg' => '5442e1ef', 'rsrc/externals/font/lato/lato-bolditalic.ttf' => 'dad31252', 'rsrc/externals/font/lato/lato-bolditalic.woff' => 'e53bcf47', 'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'd035007f', 'rsrc/externals/font/lato/lato-italic.eot' => '6a903f5d', 'rsrc/externals/font/lato/lato-italic.svg' => '0dc7cf2f', 'rsrc/externals/font/lato/lato-italic.ttf' => '629f64f0', 'rsrc/externals/font/lato/lato-italic.woff' => '678dc4bb', 'rsrc/externals/font/lato/lato-italic.woff2' => '7c8dd650', 'rsrc/externals/font/lato/lato-regular.eot' => '848dfb1e', 'rsrc/externals/font/lato/lato-regular.svg' => 'cbd5fd6b', 'rsrc/externals/font/lato/lato-regular.ttf' => 'e270165b', 'rsrc/externals/font/lato/lato-regular.woff' => '13d39fe2', 'rsrc/externals/font/lato/lato-regular.woff2' => '57a9f742', 'rsrc/externals/javelin/core/Event.js' => '2ee659ce', 'rsrc/externals/javelin/core/Stratcom.js' => '6ad39b6f', 'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '717554e4', 'rsrc/externals/javelin/core/__tests__/install.js' => 'c432ee85', 'rsrc/externals/javelin/core/__tests__/stratcom.js' => '88bf7313', 'rsrc/externals/javelin/core/__tests__/util.js' => 'e251703d', 'rsrc/externals/javelin/core/init.js' => '3010e992', 'rsrc/externals/javelin/core/init_node.js' => 'c234aded', 'rsrc/externals/javelin/core/install.js' => '05270951', 'rsrc/externals/javelin/core/util.js' => '93cc50d6', 'rsrc/externals/javelin/docs/Base.js' => '74676256', 'rsrc/externals/javelin/docs/onload.js' => 'e819c479', 'rsrc/externals/javelin/ext/fx/Color.js' => '7e41274a', 'rsrc/externals/javelin/ext/fx/FX.js' => '54b612ba', 'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => 'f6555212', 'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => '2b8de964', 'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '1ad0a787', 'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '76f4ebed', 'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => 'c90a04fc', 'rsrc/externals/javelin/ext/view/HTMLView.js' => 'fe287620', 'rsrc/externals/javelin/ext/view/View.js' => '0f764c35', 'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => 'f829edb3', 'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => '47830651', 'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '6c2b09a2', 'rsrc/externals/javelin/ext/view/ViewVisitor.js' => 'efe49472', 'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => 'f92d7bcb', 'rsrc/externals/javelin/ext/view/__tests__/View.js' => '6450b38b', 'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => '7a94d6a5', 'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '6ea96ac9', 'rsrc/externals/javelin/lib/Cookie.js' => '62dfea03', 'rsrc/externals/javelin/lib/DOM.js' => '805b806a', 'rsrc/externals/javelin/lib/History.js' => 'd4505101', 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 'rsrc/externals/javelin/lib/Leader.js' => 'fea0eb47', 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', 'rsrc/externals/javelin/lib/Quicksand.js' => '6b8ef10b', 'rsrc/externals/javelin/lib/Request.js' => '94b750d2', 'rsrc/externals/javelin/lib/Resource.js' => '44959b73', 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', 'rsrc/externals/javelin/lib/Router.js' => '29274e2b', 'rsrc/externals/javelin/lib/Scrollbar.js' => '087e919c', 'rsrc/externals/javelin/lib/Sound.js' => '949c0fe5', 'rsrc/externals/javelin/lib/URI.js' => 'c989ade3', 'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8', 'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4', 'rsrc/externals/javelin/lib/Workflow.js' => '1e911d0f', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '837a7d68', 'rsrc/externals/javelin/lib/__tests__/URI.js' => '1e45fda9', 'rsrc/externals/javelin/lib/__tests__/behavior.js' => '1ea62783', 'rsrc/externals/javelin/lib/behavior.js' => '61cbc29a', 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => '8d3bc1b2', 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => '70baed2f', 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => '185bbd53', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '013ffff9', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '0fcf201c', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '6c0e62fa', 'rsrc/favicons/apple-touch-icon-114x114.png' => '12a24178', 'rsrc/favicons/apple-touch-icon-120x120.png' => '0d1543c7', 'rsrc/favicons/apple-touch-icon-144x144.png' => '8043b5a5', 'rsrc/favicons/apple-touch-icon-152x152.png' => '65905ecd', 'rsrc/favicons/apple-touch-icon-57x57.png' => '2bfc7b0a', 'rsrc/favicons/apple-touch-icon-60x60.png' => '8ff52925', 'rsrc/favicons/apple-touch-icon-72x72.png' => 'a2bb65d6', 'rsrc/favicons/apple-touch-icon-76x76.png' => '2d061a11', 'rsrc/favicons/favicon-128.png' => '72f7e812', 'rsrc/favicons/favicon-16x16.png' => 'fc6275ba', 'rsrc/favicons/favicon-196x196.png' => '95db275e', 'rsrc/favicons/favicon-32x32.png' => '5bd18b6c', 'rsrc/favicons/favicon-96x96.png' => '7242c8e9', 'rsrc/favicons/favicon-mention.ico' => '1fdd0fa4', 'rsrc/favicons/favicon-message.ico' => '115bc010', 'rsrc/favicons/favicon.ico' => 'cdb11121', 'rsrc/favicons/mask-icon.svg' => 'e132a80f', 'rsrc/favicons/mstile-144x144.png' => '310c2ee5', 'rsrc/favicons/mstile-150x150.png' => '74bf5133', 'rsrc/favicons/mstile-310x150.png' => '4a49d3ee', 'rsrc/favicons/mstile-310x310.png' => 'a52ab264', 'rsrc/favicons/mstile-70x70.png' => '5edce7b8', 'rsrc/image/BFCFDA.png' => 'd5ec91f4', 'rsrc/image/actions/edit.png' => '2fc41442', 'rsrc/image/avatar.png' => 'e132bb6a', 'rsrc/image/checker_dark.png' => 'd8e65881', 'rsrc/image/checker_light.png' => 'a0155918', 'rsrc/image/checker_lighter.png' => 'd5da91b6', 'rsrc/image/d5d8e1.png' => '0c2a1497', 'rsrc/image/darkload.gif' => '1ffd3ec6', 'rsrc/image/divot.png' => '94dded62', 'rsrc/image/examples/hero.png' => '979a86ae', 'rsrc/image/grippy_texture.png' => 'aca81e2f', 'rsrc/image/icon/fatcow/arrow_branch.png' => '2537c01c', 'rsrc/image/icon/fatcow/arrow_merge.png' => '21b660e0', 'rsrc/image/icon/fatcow/calendar_edit.png' => '24632275', 'rsrc/image/icon/fatcow/document_black.png' => '45fe1c60', 'rsrc/image/icon/fatcow/flag_blue.png' => 'a01abb1d', 'rsrc/image/icon/fatcow/flag_finish.png' => '67825cee', 'rsrc/image/icon/fatcow/flag_ghost.png' => '20ca8783', 'rsrc/image/icon/fatcow/flag_green.png' => '7e0eaa7a', 'rsrc/image/icon/fatcow/flag_orange.png' => '9e73df66', 'rsrc/image/icon/fatcow/flag_pink.png' => '7e92f3b2', 'rsrc/image/icon/fatcow/flag_purple.png' => 'cc517522', 'rsrc/image/icon/fatcow/flag_red.png' => '04ec726f', 'rsrc/image/icon/fatcow/flag_yellow.png' => '73946fd4', 'rsrc/image/icon/fatcow/key_question.png' => '52a0c26a', 'rsrc/image/icon/fatcow/link.png' => '7afd4d5e', 'rsrc/image/icon/fatcow/page_white_edit.png' => '39a2eed8', 'rsrc/image/icon/fatcow/page_white_put.png' => '08c95a0c', 'rsrc/image/icon/fatcow/source/conduit.png' => '4ea01d2f', 'rsrc/image/icon/fatcow/source/email.png' => '9bab3239', 'rsrc/image/icon/fatcow/source/fax.png' => '04195e68', 'rsrc/image/icon/fatcow/source/mobile.png' => 'f1321264', 'rsrc/image/icon/fatcow/source/tablet.png' => '49396799', 'rsrc/image/icon/fatcow/source/web.png' => '136ccb5d', 'rsrc/image/icon/subscribe.png' => 'd03ed5a5', 'rsrc/image/icon/tango/attachment.png' => 'ecc8022e', 'rsrc/image/icon/tango/edit.png' => '929a1363', 'rsrc/image/icon/tango/go-down.png' => '96d95e43', 'rsrc/image/icon/tango/log.png' => 'b08cc63a', 'rsrc/image/icon/tango/upload.png' => '7bbb7984', 'rsrc/image/icon/unsubscribe.png' => '25725013', 'rsrc/image/lightblue-header.png' => '5c168b6d', 'rsrc/image/logo/light-eye.png' => '1a576ddd', 'rsrc/image/main_texture.png' => '29a2c5ad', 'rsrc/image/menu_texture.png' => '5a17580d', 'rsrc/image/people/harding.png' => '45aa614e', 'rsrc/image/people/jefferson.png' => 'afca0e53', 'rsrc/image/people/lincoln.png' => '9369126d', 'rsrc/image/people/mckinley.png' => 'fb8f16ce', 'rsrc/image/people/taft.png' => 'd7bc402c', 'rsrc/image/people/user0.png' => '03dacaea', 'rsrc/image/people/user1.png' => '4a4e7702', 'rsrc/image/people/user2.png' => '47a0ee40', 'rsrc/image/people/user3.png' => '835ff627', 'rsrc/image/people/user4.png' => 'b0e830f1', 'rsrc/image/people/user5.png' => '9c95b369', 'rsrc/image/people/user6.png' => 'ba3fbfb0', 'rsrc/image/people/user7.png' => 'da613924', 'rsrc/image/people/user8.png' => 'f1035edf', 'rsrc/image/people/user9.png' => '66730be3', 'rsrc/image/people/washington.png' => '40dd301c', 'rsrc/image/phrequent_active.png' => 'a466a8ed', 'rsrc/image/phrequent_inactive.png' => 'bfc15a69', 'rsrc/image/resize.png' => 'fd476de4', 'rsrc/image/sprite-login-X2.png' => '4abee916', 'rsrc/image/sprite-login.png' => '2b9663fd', 'rsrc/image/sprite-tokens-X2.png' => '804a5232', 'rsrc/image/sprite-tokens.png' => 'b41d03da', 'rsrc/image/texture/card-gradient.png' => '815f26e8', 'rsrc/image/texture/dark-menu-hover.png' => '5fa7ece8', 'rsrc/image/texture/dark-menu.png' => '7e22296e', 'rsrc/image/texture/grip.png' => '719404f3', 'rsrc/image/texture/panel-header-gradient.png' => 'e3b8dcfe', 'rsrc/image/texture/phlnx-bg.png' => '8d819209', 'rsrc/image/texture/pholio-background.gif' => 'ba29239c', 'rsrc/image/texture/table_header.png' => '5c433037', 'rsrc/image/texture/table_header_hover.png' => '038ec3b9', 'rsrc/image/texture/table_header_tall.png' => 'd56b434f', 'rsrc/js/application/aphlict/Aphlict.js' => '5359e785', 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '2a171a9d', 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'fb20ac8d', 'rsrc/js/application/aphlict/behavior-aphlict-status.js' => '5e2634b9', 'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => 'edd1ba66', 'rsrc/js/application/calendar/behavior-day-view.js' => '4b3c4443', 'rsrc/js/application/calendar/behavior-event-all-day.js' => 'b41537c9', 'rsrc/js/application/calendar/behavior-month-view.js' => 'fe33e256', 'rsrc/js/application/config/behavior-reorder-fields.js' => 'b6993408', 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'c8b5ee6f', 'rsrc/js/application/conpherence/behavior-conpherence-search.js' => '9bbf3762', 'rsrc/js/application/conpherence/behavior-durable-column.js' => 'aa3bd034', 'rsrc/js/application/conpherence/behavior-menu.js' => '7524fcfa', 'rsrc/js/application/conpherence/behavior-participant-pane.js' => '8604caa8', 'rsrc/js/application/conpherence/behavior-pontificate.js' => 'f2e58483', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3', 'rsrc/js/application/conpherence/behavior-toggle-widget.js' => '3dbf94d5', 'rsrc/js/application/countdown/timer.js' => 'e4cc26b3', 'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => 'edf8a145', 'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e', 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '019f36c4', 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63', 'rsrc/js/application/differential/ChangesetViewManager.js' => 'a2828756', 'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => '64a5550f', 'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18', 'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d', 'rsrc/js/application/differential/behavior-comment-preview.js' => 'b064af76', 'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1', 'rsrc/js/application/differential/behavior-dropdown-menus.js' => '9a6b9324', 'rsrc/js/application/differential/behavior-edit-inline-comments.js' => '4fbbc3e9', 'rsrc/js/application/differential/behavior-keyboard-nav.js' => '2c426492', 'rsrc/js/application/differential/behavior-populate.js' => '8694b1df', 'rsrc/js/application/differential/behavior-toggle-files.js' => 'ca3f91eb', 'rsrc/js/application/differential/behavior-user-select.js' => 'a8d8459d', 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => 'b42eddc7', 'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'd835b03a', 'rsrc/js/application/diffusion/behavior-commit-branches.js' => 'bdaf4d04', 'rsrc/js/application/diffusion/behavior-commit-graph.js' => '49ae8328', 'rsrc/js/application/diffusion/behavior-diffusion-browse-file.js' => '054a0f0b', 'rsrc/js/application/diffusion/behavior-jump-to.js' => '73d09eef', 'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667', 'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947', 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc', 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', 'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', 'rsrc/js/application/herald/HeraldRuleEditor.js' => 'd6a7e717', 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', 'rsrc/js/application/maniphest/behavior-batch-editor.js' => '782ab6e7', - 'rsrc/js/application/maniphest/behavior-batch-selector.js' => '7b98d7c5', + 'rsrc/js/application/maniphest/behavior-batch-selector.js' => '0825c27a', 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'e4232876', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '71237763', 'rsrc/js/application/owners/OwnersPathEditor.js' => 'aa1733d0', 'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => 'bee502c8', 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => 'fbe497e7', 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '3f5d6dbf', 'rsrc/js/application/phortune/behavior-test-payment-form.js' => 'fc91ab6c', 'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef', 'rsrc/js/application/policy/behavior-policy-control.js' => 'd0c516d5', 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '5e9f347c', 'rsrc/js/application/projects/WorkboardBoard.js' => 'fe7cb52a', 'rsrc/js/application/projects/WorkboardCard.js' => 'c587b80f', 'rsrc/js/application/projects/WorkboardColumn.js' => '21df4ff5', 'rsrc/js/application/projects/WorkboardController.js' => '55baf5ed', 'rsrc/js/application/projects/behavior-project-boards.js' => '14a1faae', 'rsrc/js/application/projects/behavior-project-create.js' => '065227cc', 'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb', 'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf', 'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8', 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f', 'rsrc/js/application/repository/repository-crossreference.js' => 'e5339c43', 'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08', 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f', 'rsrc/js/application/transactions/behavior-comment-actions.js' => '1be09f3f', 'rsrc/js/application/transactions/behavior-reorder-configs.js' => 'd7a74243', 'rsrc/js/application/transactions/behavior-reorder-fields.js' => 'b59e1e96', 'rsrc/js/application/transactions/behavior-show-older-transactions.js' => '94c65b72', 'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => 'b23b49e6', 'rsrc/js/application/transactions/behavior-transaction-list.js' => '13c739ea', 'rsrc/js/application/typeahead/behavior-typeahead-browse.js' => '635de1ec', 'rsrc/js/application/typeahead/behavior-typeahead-search.js' => '93d0c9e3', 'rsrc/js/application/uiexample/JavelinViewExample.js' => 'd4a14807', 'rsrc/js/application/uiexample/ReactorButtonExample.js' => 'd19198c8', 'rsrc/js/application/uiexample/ReactorCheckboxExample.js' => '519705ea', 'rsrc/js/application/uiexample/ReactorFocusExample.js' => '40a6a403', 'rsrc/js/application/uiexample/ReactorInputExample.js' => '886fd850', 'rsrc/js/application/uiexample/ReactorMouseoverExample.js' => '47c794d8', 'rsrc/js/application/uiexample/ReactorRadioExample.js' => '988040b4', 'rsrc/js/application/uiexample/ReactorSelectExample.js' => 'a155550f', 'rsrc/js/application/uiexample/ReactorSendClassExample.js' => '1def2711', 'rsrc/js/application/uiexample/ReactorSendPropertiesExample.js' => 'b1f0ccee', 'rsrc/js/application/uiexample/busy-example.js' => '60479091', 'rsrc/js/application/uiexample/gesture-example.js' => '558829c2', 'rsrc/js/application/uiexample/notification-example.js' => '8ce821c5', 'rsrc/js/core/Busy.js' => '59a7976a', 'rsrc/js/core/DragAndDropFileUpload.js' => '58dea2fa', 'rsrc/js/core/DraggableList.js' => 'bea6e7f4', 'rsrc/js/core/Favicon.js' => '1fe2510c', 'rsrc/js/core/FileUpload.js' => '680ea2c8', 'rsrc/js/core/Hovercard.js' => '1bd28176', 'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2', 'rsrc/js/core/KeyboardShortcutManager.js' => '4a021c10', 'rsrc/js/core/MultirowRowManager.js' => 'b5d57730', 'rsrc/js/core/Notification.js' => 'ccf1cbf8', 'rsrc/js/core/Prefab.js' => '8d40ae75', 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', 'rsrc/js/core/TextAreaUtils.js' => '320810c8', 'rsrc/js/core/Title.js' => '485aaa6c', 'rsrc/js/core/ToolTip.js' => '6323f942', 'rsrc/js/core/behavior-active-nav.js' => 'e379b58e', 'rsrc/js/core/behavior-audio-source.js' => '59b251eb', 'rsrc/js/core/behavior-autofocus.js' => '7319e029', 'rsrc/js/core/behavior-badge-view.js' => '8ff5e24c', 'rsrc/js/core/behavior-choose-control.js' => '327a00d1', 'rsrc/js/core/behavior-dark-console.js' => 'f411b6ae', 'rsrc/js/core/behavior-detect-timezone.js' => '4c193c96', 'rsrc/js/core/behavior-device.js' => 'bb1dd507', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '484a6e22', 'rsrc/js/core/behavior-error-log.js' => '6882e80a', 'rsrc/js/core/behavior-fancy-datepicker.js' => 'a9210d03', 'rsrc/js/core/behavior-file-tree.js' => '88236f00', 'rsrc/js/core/behavior-form.js' => '5c54cbf3', 'rsrc/js/core/behavior-gesture.js' => '3ab51e2c', 'rsrc/js/core/behavior-global-drag-and-drop.js' => '960f6a39', 'rsrc/js/core/behavior-high-security-warning.js' => 'a464fe03', 'rsrc/js/core/behavior-history-install.js' => '7ee2b591', 'rsrc/js/core/behavior-hovercard.js' => 'bcaccd64', 'rsrc/js/core/behavior-keyboard-pager.js' => 'a8da01f0', 'rsrc/js/core/behavior-keyboard-shortcuts.js' => '01fca1f0', 'rsrc/js/core/behavior-lightbox-attachments.js' => 'ddcd41cf', 'rsrc/js/core/behavior-line-linker.js' => '1499a8cb', 'rsrc/js/core/behavior-more.js' => 'a80d0378', 'rsrc/js/core/behavior-object-selector.js' => 'e0ec7f2f', 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 'rsrc/js/core/behavior-phabricator-nav.js' => '08675c6d', 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '116cf19b', 'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207', 'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b', 'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e', 'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e', 'rsrc/js/core/behavior-reveal-content.js' => '60821bc7', 'rsrc/js/core/behavior-scrollbar.js' => '834a1173', 'rsrc/js/core/behavior-search-typeahead.js' => '06c32383', 'rsrc/js/core/behavior-select-content.js' => 'bf5374ef', 'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6', 'rsrc/js/core/behavior-setup-check-https.js' => '491416b3', 'rsrc/js/core/behavior-time-typeahead.js' => '522431f7', 'rsrc/js/core/behavior-toggle-class.js' => '92b9ec77', 'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884', 'rsrc/js/core/behavior-tooltip.js' => '42fcb747', 'rsrc/js/core/behavior-watch-anchor.js' => '9f36c42d', 'rsrc/js/core/behavior-workflow.js' => '0a3f3021', 'rsrc/js/core/phtize.js' => 'd254d646', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '1aa4c968', 'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb', 'rsrc/js/phui/behavior-phui-profile-menu.js' => '12884df9', 'rsrc/js/phui/behavior-phui-submenu.js' => 'a6f7a73b', 'rsrc/js/phui/behavior-phui-tab-group.js' => '0a0b10e9', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', 'rsrc/js/phuix/PHUIXAutocomplete.js' => '6d86ce8b', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => '82e270da', 'rsrc/js/phuix/PHUIXFormControl.js' => '301b7812', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', ), 'symbols' => array( 'almanac-css' => 'dbb9b3af', 'aphront-bars' => '231ac33c', 'aphront-dark-console-css' => 'f54bf286', - 'aphront-dialog-view-css' => '49b2a8a3', + 'aphront-dialog-view-css' => '938f52c5', 'aphront-list-filter-view-css' => '5d6f0526', 'aphront-multi-column-view-css' => '84cc6640', 'aphront-panel-view-css' => '8427b78d', 'aphront-table-view-css' => '3225137a', 'aphront-tokenizer-control-css' => '9a8cb501', 'aphront-tooltip-css' => '1a07aea8', 'aphront-typeahead-control-css' => 'd4f16145', 'application-search-view-css' => '8452c849', 'auth-css' => '0877ed6e', 'bulk-job-css' => 'df9c1d4a', 'changeset-view-manager' => 'a2828756', 'conduit-api-css' => '7bc725c4', 'config-options-css' => '0ede4c9b', - 'config-page-css' => 'b80124ae', + 'config-page-css' => 'c1d5121b', 'conpherence-durable-column-view' => 'd82e130c', 'conpherence-header-pane-css' => '1c81cda6', 'conpherence-menu-css' => '4f51db5a', 'conpherence-message-pane-css' => 'b085d40d', 'conpherence-notification-css' => '965db05b', 'conpherence-participant-pane-css' => 'ac1baaa8', 'conpherence-thread-manager' => 'c8b5ee6f', 'conpherence-transaction-css' => '85129c68', 'd3' => 'a11a5ff2', 'differential-changeset-view-css' => 'b158cc46', 'differential-core-view-css' => '5b7b8ff4', 'differential-inline-comment-editor' => '64a5550f', 'differential-revision-add-comment-css' => 'c47f8c40', 'differential-revision-comment-css' => '14b8565a', 'differential-revision-history-css' => '0e8eb855', 'differential-revision-list-css' => 'f3c47d33', 'differential-table-of-contents-css' => 'ae4b7a55', 'diffusion-icons-css' => 'd678600a', 'diffusion-readme-css' => '297373eb', 'diffusion-source-css' => '68b30fd3', 'diviner-shared-css' => 'aa3656aa', 'font-aleo' => '8bdb2835', 'font-fontawesome' => '2b7ebbcc', 'font-lato' => 'c7ccd872', 'global-drag-and-drop-css' => '5c1b47c2', 'harbormaster-css' => 'f491c9f4', 'herald-css' => 'dc31f6e9', 'herald-rule-editor' => 'd6a7e717', 'herald-test-css' => 'a52e323e', 'inline-comment-summary-css' => '51efda3a', 'javelin-aphlict' => '5359e785', 'javelin-behavior' => '61cbc29a', 'javelin-behavior-aphlict-dropdown' => '2a171a9d', 'javelin-behavior-aphlict-listen' => 'fb20ac8d', 'javelin-behavior-aphlict-status' => '5e2634b9', 'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', 'javelin-behavior-aphront-drag-and-drop-textarea' => '484a6e22', 'javelin-behavior-aphront-form-disable-on-submit' => '5c54cbf3', 'javelin-behavior-aphront-more' => 'a80d0378', 'javelin-behavior-audio-source' => '59b251eb', 'javelin-behavior-audit-preview' => 'd835b03a', 'javelin-behavior-badge-view' => '8ff5e24c', 'javelin-behavior-bulk-job-reload' => 'edf8a145', 'javelin-behavior-calendar-month-view' => 'fe33e256', 'javelin-behavior-choose-control' => '327a00d1', 'javelin-behavior-comment-actions' => '1be09f3f', 'javelin-behavior-config-reorder-fields' => 'b6993408', 'javelin-behavior-conpherence-menu' => '7524fcfa', 'javelin-behavior-conpherence-participant-pane' => '8604caa8', 'javelin-behavior-conpherence-pontificate' => 'f2e58483', 'javelin-behavior-conpherence-search' => '9bbf3762', 'javelin-behavior-countdown-timer' => 'e4cc26b3', 'javelin-behavior-dark-console' => 'f411b6ae', 'javelin-behavior-dashboard-async-panel' => '469c0d9e', 'javelin-behavior-dashboard-move-panels' => '019f36c4', 'javelin-behavior-dashboard-query-panel-select' => '453c5375', 'javelin-behavior-dashboard-tab-panel' => 'd4eecc63', 'javelin-behavior-day-view' => '4b3c4443', 'javelin-behavior-desktop-notifications-control' => 'edd1ba66', 'javelin-behavior-detect-timezone' => '4c193c96', 'javelin-behavior-device' => 'bb1dd507', 'javelin-behavior-differential-add-reviewers-and-ccs' => 'e10f8e18', 'javelin-behavior-differential-comment-jump' => '4fdb476d', 'javelin-behavior-differential-diff-radios' => 'e1ff79b1', 'javelin-behavior-differential-dropdown-menus' => '9a6b9324', 'javelin-behavior-differential-edit-inline-comments' => '4fbbc3e9', 'javelin-behavior-differential-feedback-preview' => 'b064af76', 'javelin-behavior-differential-keyboard-navigation' => '2c426492', 'javelin-behavior-differential-populate' => '8694b1df', 'javelin-behavior-differential-toggle-files' => 'ca3f91eb', 'javelin-behavior-differential-user-select' => 'a8d8459d', 'javelin-behavior-diffusion-browse-file' => '054a0f0b', 'javelin-behavior-diffusion-commit-branches' => 'bdaf4d04', 'javelin-behavior-diffusion-commit-graph' => '49ae8328', 'javelin-behavior-diffusion-jump-to' => '73d09eef', 'javelin-behavior-diffusion-locate-file' => '6d3e1947', 'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc', 'javelin-behavior-doorkeeper-tag' => 'e5822781', 'javelin-behavior-drydock-live-operation-status' => '901935ef', 'javelin-behavior-durable-column' => 'aa3bd034', 'javelin-behavior-editengine-reorder-configs' => 'd7a74243', 'javelin-behavior-editengine-reorder-fields' => 'b59e1e96', 'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-event-all-day' => 'b41537c9', 'javelin-behavior-fancy-datepicker' => 'a9210d03', 'javelin-behavior-global-drag-and-drop' => '960f6a39', 'javelin-behavior-herald-rule-editor' => '7ebaeed3', 'javelin-behavior-high-security-warning' => 'a464fe03', 'javelin-behavior-history-install' => '7ee2b591', 'javelin-behavior-icon-composer' => '8499b6ab', 'javelin-behavior-launch-icon-composer' => '48086888', 'javelin-behavior-lightbox-attachments' => 'ddcd41cf', 'javelin-behavior-line-chart' => 'e4232876', 'javelin-behavior-load-blame' => '42126667', 'javelin-behavior-maniphest-batch-editor' => '782ab6e7', - 'javelin-behavior-maniphest-batch-selector' => '7b98d7c5', + 'javelin-behavior-maniphest-batch-selector' => '0825c27a', 'javelin-behavior-maniphest-list-editor' => 'a9f88de2', 'javelin-behavior-maniphest-subpriority-editor' => '71237763', 'javelin-behavior-owners-path-editor' => '7a68dda3', 'javelin-behavior-passphrase-credential-control' => '3cb0b2fc', 'javelin-behavior-phabricator-active-nav' => 'e379b58e', 'javelin-behavior-phabricator-autofocus' => '7319e029', 'javelin-behavior-phabricator-busy-example' => '60479091', 'javelin-behavior-phabricator-file-tree' => '88236f00', 'javelin-behavior-phabricator-gesture' => '3ab51e2c', 'javelin-behavior-phabricator-gesture-example' => '558829c2', 'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0', 'javelin-behavior-phabricator-keyboard-shortcuts' => '01fca1f0', 'javelin-behavior-phabricator-line-linker' => '1499a8cb', 'javelin-behavior-phabricator-nav' => '08675c6d', 'javelin-behavior-phabricator-notification-example' => '8ce821c5', 'javelin-behavior-phabricator-object-selector' => 'e0ec7f2f', 'javelin-behavior-phabricator-oncopy' => '2926fff2', 'javelin-behavior-phabricator-remarkup-assist' => '116cf19b', 'javelin-behavior-phabricator-reveal-content' => '60821bc7', 'javelin-behavior-phabricator-search-typeahead' => '06c32383', 'javelin-behavior-phabricator-show-older-transactions' => '94c65b72', 'javelin-behavior-phabricator-tooltips' => '42fcb747', 'javelin-behavior-phabricator-transaction-comment-form' => 'b23b49e6', 'javelin-behavior-phabricator-transaction-list' => '13c739ea', 'javelin-behavior-phabricator-watch-anchor' => '9f36c42d', 'javelin-behavior-pholio-mock-edit' => 'bee502c8', 'javelin-behavior-pholio-mock-view' => 'fbe497e7', 'javelin-behavior-phui-dropdown-menu' => '1aa4c968', 'javelin-behavior-phui-file-upload' => 'b003d4fb', 'javelin-behavior-phui-hovercards' => 'bcaccd64', 'javelin-behavior-phui-profile-menu' => '12884df9', 'javelin-behavior-phui-submenu' => 'a6f7a73b', 'javelin-behavior-phui-tab-group' => '0a0b10e9', 'javelin-behavior-policy-control' => 'd0c516d5', 'javelin-behavior-policy-rule-editor' => '5e9f347c', 'javelin-behavior-project-boards' => '14a1faae', 'javelin-behavior-project-create' => '065227cc', 'javelin-behavior-quicksand-blacklist' => '7927a7d3', 'javelin-behavior-read-only-warning' => 'ba158207', 'javelin-behavior-refresh-csrf' => 'ab2f381b', 'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf', 'javelin-behavior-releeph-request-state-change' => 'a0b57eb8', 'javelin-behavior-releeph-request-typeahead' => 'de2e896f', 'javelin-behavior-remarkup-preview' => '4b700e9e', 'javelin-behavior-reorder-applications' => '76b9fc3e', 'javelin-behavior-reorder-columns' => 'e1d25dfb', 'javelin-behavior-reorder-profile-menu-items' => 'e2e0a072', 'javelin-behavior-repository-crossreference' => 'e5339c43', 'javelin-behavior-scrollbar' => '834a1173', 'javelin-behavior-search-reorder-queries' => 'e9581f08', 'javelin-behavior-select-content' => 'bf5374ef', 'javelin-behavior-select-on-click' => '4e3e79a6', 'javelin-behavior-setup-check-https' => '491416b3', 'javelin-behavior-slowvote-embed' => '887ad43f', 'javelin-behavior-stripe-payment-form' => '3f5d6dbf', 'javelin-behavior-test-payment-form' => 'fc91ab6c', 'javelin-behavior-time-typeahead' => '522431f7', 'javelin-behavior-toggle-class' => '92b9ec77', 'javelin-behavior-toggle-widget' => '3dbf94d5', 'javelin-behavior-typeahead-browse' => '635de1ec', 'javelin-behavior-typeahead-search' => '93d0c9e3', 'javelin-behavior-view-placeholder' => '47830651', 'javelin-behavior-workflow' => '0a3f3021', 'javelin-color' => '7e41274a', 'javelin-cookie' => '62dfea03', 'javelin-diffusion-locate-file-source' => 'b42eddc7', 'javelin-dom' => '805b806a', 'javelin-dynval' => 'f6555212', 'javelin-event' => '2ee659ce', 'javelin-fx' => '54b612ba', 'javelin-history' => 'd4505101', 'javelin-install' => '05270951', 'javelin-json' => '69adf288', 'javelin-leader' => 'fea0eb47', 'javelin-magical-init' => '3010e992', 'javelin-mask' => '8a41885b', 'javelin-quicksand' => '6b8ef10b', 'javelin-reactor' => '2b8de964', 'javelin-reactor-dom' => 'c90a04fc', 'javelin-reactor-node-calmer' => '76f4ebed', 'javelin-reactornode' => '1ad0a787', 'javelin-request' => '94b750d2', 'javelin-resource' => '44959b73', 'javelin-routable' => 'b3e7d692', 'javelin-router' => '29274e2b', 'javelin-scrollbar' => '087e919c', 'javelin-sound' => '949c0fe5', 'javelin-stratcom' => '6ad39b6f', 'javelin-tokenizer' => '8d3bc1b2', 'javelin-typeahead' => '70baed2f', 'javelin-typeahead-composite-source' => '503e17fd', 'javelin-typeahead-normalizer' => '185bbd53', 'javelin-typeahead-ondemand-source' => '013ffff9', 'javelin-typeahead-preloaded-source' => '54f314a0', 'javelin-typeahead-source' => '0fcf201c', 'javelin-typeahead-static-source' => '6c0e62fa', 'javelin-uri' => 'c989ade3', 'javelin-util' => '93cc50d6', 'javelin-vector' => '2caa8fb8', 'javelin-view' => '0f764c35', 'javelin-view-html' => 'fe287620', 'javelin-view-interpreter' => 'f829edb3', 'javelin-view-renderer' => '6c2b09a2', 'javelin-view-visitor' => 'efe49472', 'javelin-websocket' => 'e292eaf4', 'javelin-workboard-board' => 'fe7cb52a', 'javelin-workboard-card' => 'c587b80f', 'javelin-workboard-column' => '21df4ff5', 'javelin-workboard-controller' => '55baf5ed', 'javelin-workflow' => '1e911d0f', 'maniphest-batch-editor' => 'b0f0b6d5', 'maniphest-report-css' => '9b9580b7', 'maniphest-task-edit-css' => 'fda62a9b', 'maniphest-task-summary-css' => '11cc5344', 'multirow-row-manager' => 'b5d57730', 'owners-path-editor' => 'aa1733d0', 'owners-path-editor-css' => '2f00933b', 'paste-css' => '1898e534', 'path-typeahead' => 'f7fc67ec', 'people-profile-css' => '2473d929', 'phabricator-action-list-view-css' => 'e1d48300', 'phabricator-application-launch-view-css' => '95351601', 'phabricator-busy' => '59a7976a', 'phabricator-chatlog-css' => 'd295b020', 'phabricator-content-source-view-css' => '4b8b05d4', 'phabricator-core-css' => 'd0801452', 'phabricator-countdown-css' => '16c52f5c', 'phabricator-dashboard-css' => 'bc6f2127', 'phabricator-drag-and-drop-file-upload' => '58dea2fa', 'phabricator-draggable-list' => 'bea6e7f4', 'phabricator-fatal-config-template-css' => '8f18fa41', 'phabricator-favicon' => '1fe2510c', 'phabricator-feed-css' => 'ecd4ec57', 'phabricator-file-upload' => '680ea2c8', 'phabricator-filetree-view-css' => 'fccf9f82', - 'phabricator-flag-css' => '5337623f', + 'phabricator-flag-css' => 'bba8f811', 'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut-manager' => '4a021c10', 'phabricator-main-menu-view' => 'f03e17be', 'phabricator-nav-view-css' => 'b29426e9', 'phabricator-notification' => 'ccf1cbf8', 'phabricator-notification-css' => '3f6c89c9', 'phabricator-notification-menu-css' => '1e055865', 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => '8d40ae75', 'phabricator-remarkup-css' => '8606d9c6', - 'phabricator-search-results-css' => '7dea472c', + 'phabricator-search-results-css' => '64ad079a', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-slowvote-css' => 'a94b7230', - 'phabricator-source-code-view-css' => 'cbeef983', + 'phabricator-source-code-view-css' => '4383192f', 'phabricator-standard-page-view' => '894d8a25', 'phabricator-textareautils' => '320810c8', 'phabricator-title' => '485aaa6c', 'phabricator-tooltip' => '6323f942', 'phabricator-ui-example-css' => '528b19de', 'phabricator-uiexample-javelin-view' => 'd4a14807', 'phabricator-uiexample-reactor-button' => 'd19198c8', 'phabricator-uiexample-reactor-checkbox' => '519705ea', 'phabricator-uiexample-reactor-focus' => '40a6a403', 'phabricator-uiexample-reactor-input' => '886fd850', 'phabricator-uiexample-reactor-mouseover' => '47c794d8', 'phabricator-uiexample-reactor-radio' => '988040b4', 'phabricator-uiexample-reactor-select' => 'a155550f', 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 'phabricator-zindex-css' => 'd1270942', - 'phame-css' => '654dd9ef', + 'phame-css' => 'aeb61182', 'pholio-css' => 'ca89d380', 'pholio-edit-css' => '07676f51', 'pholio-inline-comments-css' => '8e545e49', 'phortune-credit-card-form' => '2290aeef', 'phortune-credit-card-form-css' => '8391eb02', 'phortune-css' => '5b99dae0', 'phortune-invoice-css' => '476055e2', 'phrequent-css' => 'ffc185ad', 'phriction-document-css' => '4282e4ad', 'phui-action-panel-css' => '91c7b835', 'phui-badge-view-css' => '3baef8db', 'phui-basic-nav-view-css' => '7093573b', 'phui-big-info-view-css' => 'bd903741', - 'phui-box-css' => '5c8387cf', - 'phui-button-css' => '4a5fbe3d', + 'phui-box-css' => '33b629f8', + 'phui-button-css' => '43f4912e', 'phui-calendar-css' => '477acfaa', 'phui-calendar-day-css' => '572b1893', 'phui-calendar-list-css' => 'fcc9fb41', 'phui-calendar-month-css' => '8e10e92c', 'phui-chart-css' => '6bf6f78e', 'phui-cms-css' => 'be43c8a8', 'phui-comment-form-css' => 'c953b75e', 'phui-comment-panel-css' => 'f50152ad', - 'phui-crumbs-view-css' => '195ac419', + 'phui-crumbs-view-css' => 'f82868f2', 'phui-curtain-view-css' => '947bf1a4', 'phui-document-summary-view-css' => '9ca48bdf', 'phui-document-view-css' => 'c32e8dec', 'phui-document-view-pro-css' => 'c354e312', 'phui-feed-story-css' => '44a9c8e9', 'phui-font-icon-base-css' => '870a7360', 'phui-fontkit-css' => '9cda225e', 'phui-form-css' => '2342b0e5', 'phui-form-view-css' => 'cd79ff6a', 'phui-head-thing-view-css' => 'fd311e5f', 'phui-header-view-css' => '6ec8f155', 'phui-hovercard' => '1bd28176', 'phui-hovercard-view-css' => 'de1a2119', 'phui-icon-set-selector-css' => '1ab67aad', 'phui-icon-view-css' => '09f46dd9', 'phui-image-mask-css' => 'a8498f9c', 'phui-info-panel-css' => '27ea50a1', 'phui-info-view-css' => 'ec92802a', 'phui-inline-comment-view-css' => '5953c28e', 'phui-invisible-character-view-css' => '6993d9f0', 'phui-lightbox-css' => '0a035e40', 'phui-list-view-css' => '9da2aa00', 'phui-object-box-css' => '6b487c57', - 'phui-object-item-list-view-css' => '87278fa0', + 'phui-oi-big-ui-css' => '19f9369b', + 'phui-oi-color-css' => 'cd2b9b77', + 'phui-oi-drag-ui-css' => 'f12cbc9f', + 'phui-oi-flush-ui-css' => '9d9685d6', + 'phui-oi-list-view-css' => 'bff632a4', + 'phui-oi-simple-ui-css' => 'a8beebea', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', 'phui-profile-menu-css' => '4768721a', 'phui-property-list-view-css' => '6d8e58ac', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-segment-bar-view-css' => '46342871', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => 'd5263e49', - 'phui-tag-view-css' => '6bbd83e2', + 'phui-tag-view-css' => '84d65f26', 'phui-theme-css' => '798c69b8', 'phui-timeline-view-css' => 'bc523970', - 'phui-two-column-view-css' => 'ee61d056', + 'phui-two-column-view-css' => '7babf5b9', 'phui-workboard-color-css' => 'b60ef38a', 'phui-workboard-view-css' => '16441d5e', - 'phui-workcard-view-css' => '0c62d7c5', - 'phui-workpanel-view-css' => '92197373', + 'phui-workcard-view-css' => '00979e40', + 'phui-workpanel-view-css' => 'a3a63478', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', 'phuix-autocomplete' => '6d86ce8b', 'phuix-dropdown-menu' => '82e270da', 'phuix-form-control-view' => '301b7812', 'phuix-icon-view' => 'bff6884b', 'policy-css' => '957ea14c', 'policy-edit-css' => '815c66f7', 'policy-transaction-detail-css' => '82100a43', 'ponder-view-css' => 'fbd45f96', 'project-card-view-css' => '9418c97d', - 'project-view-css' => '55d99221', + 'project-view-css' => '1e6f7072', 'releeph-core' => '9b3c5733', 'releeph-preview-branch' => 'b7a6f4a5', 'releeph-request-differential-create-dialog' => '8d8b92cd', 'releeph-request-typeahead-css' => '667a48ae', 'setup-issue-css' => 'f794cfc3', 'sprite-login-css' => '587d92d7', 'sprite-tokens-css' => '9cdfd599', 'syntax-default-css' => '9923583c', 'syntax-highlighting-css' => '769d3498', 'tokens-css' => '3d0f239e', 'typeahead-browse-css' => '8904346a', 'unhandled-exception-css' => '4c96257a', ), 'requires' => array( '013ffff9' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), '019f36c4' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '01fca1f0' => array( 'javelin-behavior', 'javelin-workflow', 'javelin-json', 'javelin-dom', 'phabricator-keyboard-shortcut', ), '05270951' => array( 'javelin-util', 'javelin-magical-init', ), '054a0f0b' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-tooltip', ), '065227cc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', ), '06c32383' => array( 'javelin-behavior', 'javelin-typeahead-ondemand-source', 'javelin-typeahead', 'javelin-dom', 'javelin-uri', 'javelin-util', 'javelin-stratcom', 'phabricator-prefab', 'phuix-icon-view', ), + '0825c27a' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + ), '08675c6d' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-dom', 'javelin-magical-init', 'javelin-vector', 'javelin-request', 'javelin-util', ), '087e919c' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), '0a0b10e9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '0a3f3021' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-router', ), '0f764c35' => array( 'javelin-install', 'javelin-util', ), '0fcf201c' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-typeahead-normalizer', ), '116cf19b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-phtize', 'phabricator-textareautils', 'javelin-workflow', 'javelin-vector', 'phuix-autocomplete', ), '12884df9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '13c739ea' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-uri', 'phabricator-textareautils', ), '1499a8cb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-history', ), '14a1faae' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'javelin-workboard-controller', ), '185bbd53' => array( 'javelin-install', ), + '19f9369b' => array( + 'phui-oi-list-view-css', + ), '1aa4c968' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), '1ad0a787' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', 'javelin-reactor-node-calmer', ), '1ae869f2' => array( 'javelin-install', 'javelin-util', 'phabricator-keyboard-shortcut-manager', ), '1bd28176' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-request', 'javelin-uri', ), '1be09f3f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phuix-form-control-view', 'phuix-icon-view', 'javelin-behavior-phabricator-gesture', ), '1def2711' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), '1e911d0f' => array( 'javelin-stratcom', 'javelin-request', 'javelin-dom', 'javelin-vector', 'javelin-install', 'javelin-util', 'javelin-mask', 'javelin-uri', 'javelin-routable', ), '1fe2510c' => array( 'javelin-install', 'javelin-dom', ), '21df4ff5' => array( 'javelin-install', 'javelin-workboard-card', ), '2290aeef' => array( 'javelin-install', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-util', ), '2926fff2' => array( 'javelin-behavior', 'javelin-dom', ), '29274e2b' => array( 'javelin-install', 'javelin-util', ), '2a171a9d' => array( 'javelin-behavior', 'javelin-request', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', 'javelin-behavior-device', 'phabricator-title', 'phabricator-favicon', ), '2b8de964' => array( 'javelin-install', 'javelin-util', ), '2c426492' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-keyboard-shortcut', ), '2caa8fb8' => array( 'javelin-install', 'javelin-event', ), '2ee659ce' => array( 'javelin-install', ), '301b7812' => array( 'javelin-install', 'javelin-dom', ), '320810c8' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', ), '327a00d1' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-magical-init', ), '3cb0b2fc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'javelin-uri', ), '3dbf94d5' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', ), '3f5d6dbf' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), '40a6a403' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 42126667 => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', ), '42fcb747' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'phabricator-tooltip', ), '44959b73' => array( 'javelin-util', 'javelin-uri', 'javelin-install', ), '453c5375' => array( 'javelin-behavior', 'javelin-dom', ), '469c0d9e' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), 47830651 => array( 'javelin-behavior', 'javelin-dom', 'javelin-view-renderer', 'javelin-install', ), '47c794d8' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 48086888 => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), '484a6e22' => array( 'javelin-behavior', 'javelin-dom', 'phabricator-drag-and-drop-file-upload', 'phabricator-textareautils', ), '485aaa6c' => array( 'javelin-install', ), '491416b3' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), '49ae8328' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '4a021c10' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), '4b3c4443' => array( 'phuix-icon-view', ), '4b700e9e' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), '4c193c96' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), '4e3e79a6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '4fbbc3e9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-util', 'javelin-vector', 'differential-inline-comment-editor', ), '4fdb476d' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '503e17fd' => array( 'javelin-install', 'javelin-typeahead-source', 'javelin-util', ), '519705ea' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), '522431f7' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', 'javelin-typeahead-static-source', ), '5359e785' => array( 'javelin-install', 'javelin-util', 'javelin-websocket', 'javelin-leader', 'javelin-json', ), '54b612ba' => array( 'javelin-color', 'javelin-install', 'javelin-util', ), '54f314a0' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), '558829c2' => array( 'javelin-stratcom', 'javelin-behavior', 'javelin-vector', 'javelin-dom', ), '55baf5ed' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'phabricator-drag-and-drop-file-upload', 'javelin-workboard-board', ), '58dea2fa' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-dom', 'javelin-uri', 'phabricator-file-upload', ), '59a7976a' => array( 'javelin-install', 'javelin-dom', 'javelin-fx', ), '59b251eb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', ), '5c54cbf3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5e2634b9' => array( 'javelin-behavior', 'javelin-aphlict', 'phabricator-phtize', 'javelin-dom', ), '5e9f347c' => array( 'javelin-behavior', 'multirow-row-manager', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'javelin-json', ), 60479091 => array( 'phabricator-busy', 'javelin-behavior', ), '60821bc7' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '61cbc29a' => array( 'javelin-magical-init', 'javelin-util', ), '62dfea03' => array( 'javelin-install', 'javelin-util', ), '6323f942' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', ), '635de1ec' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '64a5550f' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-request', 'javelin-workflow', ), '680ea2c8' => array( 'javelin-install', 'javelin-dom', 'phabricator-notification', ), '6882e80a' => array( 'javelin-dom', ), '69adf288' => array( 'javelin-install', ), '6ad39b6f' => array( 'javelin-install', 'javelin-event', 'javelin-util', 'javelin-magical-init', ), '6b8ef10b' => array( 'javelin-install', ), '6c0e62fa' => array( 'javelin-install', 'javelin-typeahead-source', ), '6c2b09a2' => array( 'javelin-install', 'javelin-util', ), '6d3e1947' => array( 'javelin-behavior', 'javelin-diffusion-locate-file-source', 'javelin-dom', 'javelin-typeahead', 'javelin-uri', ), '6d86ce8b' => array( 'javelin-install', 'javelin-dom', 'phuix-icon-view', 'phabricator-prefab', ), '70baed2f' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-util', ), 71237763 => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '7319e029' => array( 'javelin-behavior', 'javelin-dom', ), '73d09eef' => array( 'javelin-behavior', 'javelin-vector', 'javelin-dom', ), '7524fcfa' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'javelin-behavior-device', 'javelin-history', 'javelin-vector', 'javelin-scrollbar', 'phabricator-title', 'phabricator-shaped-request', 'conpherence-thread-manager', ), '769d3498' => array( 'syntax-default-css', ), '76b9fc3e' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '76f4ebed' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', ), '782ab6e7' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'multirow-row-manager', 'javelin-json', ), '7927a7d3' => array( 'javelin-behavior', 'javelin-quicksand', ), '7a68dda3' => array( 'owners-path-editor', 'javelin-behavior', ), - '7b98d7c5' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - ), '7cbe244b' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-router', ), '7e41274a' => array( 'javelin-install', ), '7ebaeed3' => array( 'herald-rule-editor', 'javelin-behavior', ), '7ee2b591' => array( 'javelin-behavior', 'javelin-history', ), '805b806a' => array( 'javelin-magical-init', 'javelin-install', 'javelin-util', 'javelin-vector', 'javelin-stratcom', ), '82e270da' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', 'javelin-stratcom', ), '834a1173' => array( 'javelin-behavior', 'javelin-scrollbar', ), '8499b6ab' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '85ee8ce6' => array( 'aphront-dialog-view-css', ), '8604caa8' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-notification', 'conpherence-thread-manager', ), '8694b1df' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-tooltip', 'changeset-view-manager', ), '88236f00' => array( 'javelin-behavior', 'phabricator-keyboard-shortcut', 'javelin-stratcom', ), '886fd850' => array( 'javelin-install', 'javelin-reactor-dom', 'javelin-view-html', 'javelin-view-interpreter', 'javelin-view-renderer', ), '887ad43f' => array( 'javelin-behavior', 'javelin-request', 'javelin-stratcom', 'javelin-dom', ), '8a41885b' => array( 'javelin-install', 'javelin-dom', ), '8bdb2835' => array( 'phui-fontkit-css', ), '8ce821c5' => array( 'phabricator-notification', 'javelin-stratcom', 'javelin-behavior', ), '8cf6d262' => array( 'javelin-install', 'javelin-dom', 'javelin-util', ), '8d3bc1b2' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', ), '8d40ae75' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-typeahead', 'javelin-tokenizer', 'javelin-typeahead-preloaded-source', 'javelin-typeahead-ondemand-source', 'javelin-dom', 'javelin-stratcom', 'javelin-util', ), '8ff5e24c' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '901935ef' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', ), - 92197373 => array( - 'phui-workcard-view-css', - ), '92b9ec77' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '93d0c9e3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '949c0fe5' => array( 'javelin-install', ), '94b750d2' => array( 'javelin-install', 'javelin-stratcom', 'javelin-util', 'javelin-behavior', 'javelin-json', 'javelin-dom', 'javelin-resource', 'javelin-routable', ), '94c65b72' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-busy', ), '960f6a39' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-mask', 'phabricator-drag-and-drop-file-upload', ), '988040b4' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), '9a6b9324' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'phabricator-phtize', 'changeset-view-manager', ), '9a8cb501' => array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), '9bbf3762' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', ), + '9d9685d6' => array( + 'phui-oi-list-view-css', + ), '9f36c42d' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), 'a0b57eb8' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-keyboard-shortcut', ), 'a155550f' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 'a2828756' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', ), + 'a3a63478' => array( + 'phui-workcard-view-css', + ), 'a464fe03' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'a6f7a73b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'a80d0378' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), + 'a8beebea' => array( + 'phui-oi-list-view-css', + ), 'a8d8459d' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'a8da01f0' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-keyboard-shortcut', ), 'a9210d03' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), 'a9f88de2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-fx', 'javelin-util', ), 'aa1733d0' => array( 'multirow-row-manager', 'javelin-install', 'path-typeahead', 'javelin-dom', 'javelin-util', 'phabricator-prefab', ), 'aa3bd034' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-behavior-device', 'javelin-scrollbar', 'javelin-quicksand', 'phabricator-keyboard-shortcut', 'conpherence-thread-manager', ), 'ab2f381b' => array( 'javelin-request', 'javelin-behavior', 'javelin-dom', 'javelin-router', 'javelin-util', 'phabricator-busy', ), 'b003d4fb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), 'b064af76' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-request', 'javelin-util', 'phabricator-shaped-request', ), 'b158cc46' => array( 'phui-inline-comment-view-css', ), 'b1f0ccee' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 'b23b49e6' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', 'phabricator-shaped-request', ), 'b2b4fbaf' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-request', ), 'b3a4b884' => array( 'javelin-behavior', 'phabricator-prefab', ), 'b3e7d692' => array( 'javelin-install', ), 'b42eddc7' => array( 'javelin-install', 'javelin-dom', 'javelin-typeahead-preloaded-source', 'javelin-util', ), 'b59e1e96' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'b5c256b8' => array( 'javelin-install', 'javelin-dom', ), 'b5d57730' => array( 'javelin-install', 'javelin-stratcom', 'javelin-dom', 'javelin-util', ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-json', 'phabricator-draggable-list', ), 'ba158207' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'bb1dd507' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', 'javelin-install', ), 'bcaccd64' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'phui-hovercard', ), 'bdaf4d04' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', ), 'bea6e7f4' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'javelin-vector', 'javelin-magical-init', ), 'bee502c8' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', 'javelin-quicksand', 'phabricator-phtize', 'phabricator-drag-and-drop-file-upload', 'phabricator-draggable-list', ), 'bf5374ef' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'bff6884b' => array( 'javelin-install', 'javelin-dom', ), 'c587b80f' => array( 'javelin-install', ), 'c7ccd872' => array( 'phui-fontkit-css', ), 'c8b5ee6f' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-aphlict', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', ), 'c90a04fc' => array( 'javelin-dom', 'javelin-dynval', 'javelin-reactor', 'javelin-reactornode', 'javelin-install', 'javelin-util', ), 'c989ade3' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', ), 'ca3f91eb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-phtize', ), 'ccf1cbf8' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'phabricator-notification-css', ), + 'cd2b9b77' => array( + 'phui-oi-list-view-css', + ), 'd0c516d5' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'javelin-workflow', 'phuix-icon-view', ), 'd19198c8' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-dynval', 'javelin-reactor-dom', ), 'd254d646' => array( 'javelin-util', ), 'd4505101' => array( 'javelin-stratcom', 'javelin-install', 'javelin-uri', 'javelin-util', ), 'd4a14807' => array( 'javelin-install', 'javelin-dom', 'javelin-view', ), 'd4eecc63' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'd6a7e717' => array( 'multirow-row-manager', 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-json', 'phabricator-prefab', ), 'd7a74243' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'd835b03a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'ddcd41cf' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-mask', 'javelin-util', 'phuix-icon-view', 'phabricator-busy', ), 'de2e896f' => array( 'javelin-behavior', 'javelin-dom', 'javelin-typeahead', 'javelin-typeahead-ondemand-source', 'javelin-dom', ), 'e0ec7f2f' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', 'javelin-util', ), 'e10f8e18' => array( 'javelin-behavior', 'javelin-dom', 'phabricator-prefab', ), 'e1d25dfb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'e1ff79b1' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'e292eaf4' => array( 'javelin-install', ), 'e2e0a072' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'e379b58e' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', ), 'e4232876' => array( 'javelin-behavior', 'javelin-dom', 'javelin-vector', 'phui-chart-css', ), 'e4cc26b3' => array( 'javelin-behavior', 'javelin-dom', ), 'e5339c43' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-uri', ), 'e5822781' => array( 'javelin-behavior', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-magical-init', ), 'e9581f08' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'edd1ba66' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-uri', 'phabricator-notification', ), 'edf8a145' => array( 'javelin-behavior', 'javelin-uri', ), 'efe49472' => array( 'javelin-install', 'javelin-util', ), 'f01586dc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-json', ), 'f03e17be' => array( 'phui-theme-css', ), + 'f12cbc9f' => array( + 'phui-oi-list-view-css', + ), 'f2e58483' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', 'conpherence-thread-manager', ), 'f411b6ae' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-util', 'javelin-dom', 'javelin-request', 'phabricator-keyboard-shortcut', ), 'f50152ad' => array( 'phui-timeline-view-css', ), 'f6555212' => array( 'javelin-install', 'javelin-reactornode', 'javelin-util', 'javelin-reactor', ), 'f7fc67ec' => array( 'javelin-install', 'javelin-typeahead', 'javelin-dom', 'javelin-request', 'javelin-typeahead-ondemand-source', 'javelin-util', ), 'f829edb3' => array( 'javelin-view', 'javelin-install', 'javelin-dom', ), 'fb20ac8d' => array( 'javelin-behavior', 'javelin-aphlict', 'javelin-stratcom', 'javelin-request', 'javelin-uri', 'javelin-dom', 'javelin-json', 'javelin-router', 'javelin-util', 'javelin-leader', 'javelin-sound', 'phabricator-notification', ), 'fbe497e7' => array( 'javelin-behavior', 'javelin-util', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', 'javelin-magical-init', 'javelin-request', 'javelin-history', 'javelin-workflow', 'javelin-mask', 'javelin-behavior-device', 'phabricator-keyboard-shortcut', ), 'fc91ab6c' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), 'fe287620' => array( 'javelin-install', 'javelin-dom', 'javelin-view-visitor', 'javelin-util', ), 'fe7cb52a' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', 'javelin-workboard-column', ), 'fea0eb47' => array( 'javelin-install', ), ), 'packages' => array( 'conpherence.pkg.css' => array( 'conpherence-durable-column-view', 'conpherence-menu-css', 'conpherence-message-pane-css', 'conpherence-notification-css', 'conpherence-transaction-css', 'conpherence-participant-pane-css', 'conpherence-header-pane-css', ), 'conpherence.pkg.js' => array( 'javelin-behavior-conpherence-menu', 'javelin-behavior-conpherence-participant-pane', 'javelin-behavior-conpherence-pontificate', 'javelin-behavior-toggle-widget', ), 'core.pkg.css' => array( 'phabricator-core-css', 'phabricator-zindex-css', 'phui-button-css', 'phui-theme-css', 'phabricator-standard-page-view', 'aphront-dialog-view-css', 'phui-form-view-css', 'aphront-panel-view-css', 'aphront-table-view-css', 'aphront-tokenizer-control-css', 'aphront-typeahead-control-css', 'aphront-list-filter-view-css', 'application-search-view-css', 'phabricator-remarkup-css', 'syntax-highlighting-css', 'syntax-default-css', 'phui-pager-css', 'aphront-tooltip-css', 'phabricator-flag-css', 'phui-info-view-css', 'phabricator-main-menu-view', 'phabricator-notification-css', 'phabricator-notification-menu-css', 'phui-lightbox-css', 'phui-comment-panel-css', 'phui-header-view-css', 'phabricator-nav-view-css', 'phui-basic-nav-view-css', 'phui-crumbs-view-css', - 'phui-object-item-list-view-css', + 'phui-oi-list-view-css', + 'phui-oi-color-css', + 'phui-oi-big-ui-css', + 'phui-oi-drag-ui-css', + 'phui-oi-simple-ui-css', + 'phui-oi-flush-ui-css', 'global-drag-and-drop-css', 'phui-spacing-css', 'phui-form-css', 'phui-icon-view-css', 'phui-profile-menu-css', 'phabricator-application-launch-view-css', 'phabricator-action-list-view-css', 'phui-property-list-view-css', 'phui-tag-view-css', 'phui-list-view-css', 'font-fontawesome', 'font-lato', 'font-aleo', 'phui-font-icon-base-css', 'phui-fontkit-css', 'phui-box-css', 'phui-object-box-css', 'phui-timeline-view-css', 'phui-two-column-view-css', 'phui-curtain-view-css', 'sprite-login-css', 'sprite-tokens-css', 'tokens-css', 'auth-css', 'phui-status-list-view-css', 'phui-feed-story-css', 'phabricator-feed-css', 'phabricator-dashboard-css', 'aphront-multi-column-view-css', ), 'core.pkg.js' => array( 'javelin-util', 'javelin-install', 'javelin-event', 'javelin-stratcom', 'javelin-behavior', 'javelin-resource', 'javelin-request', 'javelin-vector', 'javelin-dom', 'javelin-json', 'javelin-uri', 'javelin-workflow', 'javelin-mask', 'javelin-typeahead', 'javelin-typeahead-normalizer', 'javelin-typeahead-source', 'javelin-typeahead-preloaded-source', 'javelin-typeahead-ondemand-source', 'javelin-tokenizer', 'javelin-history', 'javelin-router', 'javelin-routable', 'javelin-behavior-aphront-basic-tokenizer', 'javelin-behavior-workflow', 'javelin-behavior-aphront-form-disable-on-submit', 'phabricator-keyboard-shortcut-manager', 'phabricator-keyboard-shortcut', 'javelin-behavior-phabricator-keyboard-shortcuts', 'javelin-behavior-refresh-csrf', 'javelin-behavior-phabricator-watch-anchor', 'javelin-behavior-phabricator-autofocus', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'phuix-icon-view', 'phabricator-phtize', 'javelin-behavior-phabricator-oncopy', 'phabricator-tooltip', 'javelin-behavior-phabricator-tooltips', 'phabricator-prefab', 'javelin-behavior-device', 'javelin-behavior-toggle-class', 'javelin-behavior-lightbox-attachments', 'phabricator-busy', 'javelin-aphlict', 'phabricator-notification', 'javelin-behavior-aphlict-listen', 'javelin-behavior-phabricator-search-typeahead', 'javelin-behavior-aphlict-dropdown', 'javelin-behavior-history-install', 'javelin-behavior-phabricator-gesture', 'javelin-behavior-phabricator-active-nav', 'javelin-behavior-phabricator-nav', 'javelin-behavior-phabricator-remarkup-assist', 'phabricator-textareautils', 'phabricator-file-upload', 'javelin-behavior-global-drag-and-drop', 'javelin-behavior-phabricator-reveal-content', 'phui-hovercard', 'javelin-behavior-phui-hovercards', 'javelin-color', 'javelin-fx', 'phabricator-draggable-list', 'javelin-behavior-phabricator-transaction-list', 'javelin-behavior-phabricator-show-older-transactions', 'javelin-behavior-phui-dropdown-menu', 'javelin-behavior-doorkeeper-tag', 'phabricator-title', 'javelin-leader', 'javelin-websocket', 'javelin-behavior-dashboard-async-panel', 'javelin-behavior-dashboard-tab-panel', 'javelin-quicksand', 'javelin-behavior-quicksand-blacklist', 'javelin-behavior-high-security-warning', 'javelin-behavior-read-only-warning', 'javelin-scrollbar', 'javelin-behavior-scrollbar', 'javelin-behavior-durable-column', 'conpherence-thread-manager', 'javelin-behavior-detect-timezone', 'javelin-behavior-setup-check-https', ), 'darkconsole.pkg.js' => array( 'javelin-behavior-dark-console', 'javelin-behavior-error-log', ), 'differential.pkg.css' => array( 'differential-core-view-css', 'differential-changeset-view-css', 'differential-revision-history-css', 'differential-revision-list-css', 'differential-table-of-contents-css', 'differential-revision-comment-css', 'differential-revision-add-comment-css', 'phabricator-object-selector-css', 'phabricator-content-source-view-css', 'inline-comment-summary-css', 'phui-inline-comment-view-css', 'phabricator-filetree-view-css', ), 'differential.pkg.js' => array( 'phabricator-drag-and-drop-file-upload', 'phabricator-shaped-request', 'javelin-behavior-differential-feedback-preview', 'javelin-behavior-differential-edit-inline-comments', 'javelin-behavior-differential-populate', 'javelin-behavior-differential-diff-radios', 'javelin-behavior-differential-comment-jump', 'javelin-behavior-differential-add-reviewers-and-ccs', 'javelin-behavior-differential-keyboard-navigation', 'javelin-behavior-aphront-drag-and-drop-textarea', 'javelin-behavior-phabricator-object-selector', 'javelin-behavior-repository-crossreference', 'javelin-behavior-load-blame', 'differential-inline-comment-editor', 'javelin-behavior-differential-dropdown-menus', 'javelin-behavior-differential-toggle-files', 'javelin-behavior-differential-user-select', 'javelin-behavior-aphront-more', 'changeset-view-manager', ), 'diffusion.pkg.css' => array( 'diffusion-icons-css', ), 'diffusion.pkg.js' => array( 'javelin-behavior-diffusion-pull-lastmodified', 'javelin-behavior-diffusion-commit-graph', 'javelin-behavior-audit-preview', ), 'maniphest.pkg.css' => array( 'maniphest-task-summary-css', ), 'maniphest.pkg.js' => array( 'javelin-behavior-maniphest-batch-selector', 'javelin-behavior-maniphest-subpriority-editor', 'javelin-behavior-maniphest-list-editor', ), ), ); diff --git a/resources/celerity/packages.php b/resources/celerity/packages.php index affa180dc1..95cf5303ef 100644 --- a/resources/celerity/packages.php +++ b/resources/celerity/packages.php @@ -1,227 +1,232 @@ array( 'javelin-util', 'javelin-install', 'javelin-event', 'javelin-stratcom', 'javelin-behavior', 'javelin-resource', 'javelin-request', 'javelin-vector', 'javelin-dom', 'javelin-json', 'javelin-uri', 'javelin-workflow', 'javelin-mask', 'javelin-typeahead', 'javelin-typeahead-normalizer', 'javelin-typeahead-source', 'javelin-typeahead-preloaded-source', 'javelin-typeahead-ondemand-source', 'javelin-tokenizer', 'javelin-history', 'javelin-router', 'javelin-routable', 'javelin-behavior-aphront-basic-tokenizer', 'javelin-behavior-workflow', 'javelin-behavior-aphront-form-disable-on-submit', 'phabricator-keyboard-shortcut-manager', 'phabricator-keyboard-shortcut', 'javelin-behavior-phabricator-keyboard-shortcuts', 'javelin-behavior-refresh-csrf', 'javelin-behavior-phabricator-watch-anchor', 'javelin-behavior-phabricator-autofocus', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'phuix-icon-view', 'phabricator-phtize', 'javelin-behavior-phabricator-oncopy', 'phabricator-tooltip', 'javelin-behavior-phabricator-tooltips', 'phabricator-prefab', 'javelin-behavior-device', 'javelin-behavior-toggle-class', 'javelin-behavior-lightbox-attachments', 'phabricator-busy', 'javelin-aphlict', 'phabricator-notification', 'javelin-behavior-aphlict-listen', 'javelin-behavior-phabricator-search-typeahead', 'javelin-behavior-aphlict-dropdown', 'javelin-behavior-history-install', 'javelin-behavior-phabricator-gesture', 'javelin-behavior-phabricator-active-nav', 'javelin-behavior-phabricator-nav', 'javelin-behavior-phabricator-remarkup-assist', 'phabricator-textareautils', 'phabricator-file-upload', 'javelin-behavior-global-drag-and-drop', 'javelin-behavior-phabricator-reveal-content', 'phui-hovercard', 'javelin-behavior-phui-hovercards', 'javelin-color', 'javelin-fx', 'phabricator-draggable-list', 'javelin-behavior-phabricator-transaction-list', 'javelin-behavior-phabricator-show-older-transactions', 'javelin-behavior-phui-dropdown-menu', 'javelin-behavior-doorkeeper-tag', 'phabricator-title', 'javelin-leader', 'javelin-websocket', 'javelin-behavior-dashboard-async-panel', 'javelin-behavior-dashboard-tab-panel', 'javelin-quicksand', 'javelin-behavior-quicksand-blacklist', 'javelin-behavior-high-security-warning', 'javelin-behavior-read-only-warning', 'javelin-scrollbar', 'javelin-behavior-scrollbar', 'javelin-behavior-durable-column', 'conpherence-thread-manager', 'javelin-behavior-detect-timezone', 'javelin-behavior-setup-check-https', ), 'core.pkg.css' => array( 'phabricator-core-css', 'phabricator-zindex-css', 'phui-button-css', 'phui-theme-css', 'phabricator-standard-page-view', 'aphront-dialog-view-css', 'phui-form-view-css', 'aphront-panel-view-css', 'aphront-table-view-css', 'aphront-tokenizer-control-css', 'aphront-typeahead-control-css', 'aphront-list-filter-view-css', 'application-search-view-css', 'phabricator-remarkup-css', 'syntax-highlighting-css', 'syntax-default-css', 'phui-pager-css', 'aphront-tooltip-css', 'phabricator-flag-css', 'phui-info-view-css', 'phabricator-main-menu-view', 'phabricator-notification-css', 'phabricator-notification-menu-css', 'phui-lightbox-css', 'phui-comment-panel-css', 'phui-header-view-css', 'phabricator-nav-view-css', 'phui-basic-nav-view-css', 'phui-crumbs-view-css', - 'phui-object-item-list-view-css', + 'phui-oi-list-view-css', + 'phui-oi-color-css', + 'phui-oi-big-ui-css', + 'phui-oi-drag-ui-css', + 'phui-oi-simple-ui-css', + 'phui-oi-flush-ui-css', 'global-drag-and-drop-css', 'phui-spacing-css', 'phui-form-css', 'phui-icon-view-css', 'phui-profile-menu-css', 'phabricator-application-launch-view-css', 'phabricator-action-list-view-css', 'phui-property-list-view-css', 'phui-tag-view-css', 'phui-list-view-css', 'font-fontawesome', 'font-lato', 'font-aleo', 'phui-font-icon-base-css', 'phui-fontkit-css', 'phui-box-css', 'phui-object-box-css', 'phui-timeline-view-css', 'phui-two-column-view-css', 'phui-curtain-view-css', 'sprite-login-css', 'sprite-tokens-css', 'tokens-css', 'auth-css', 'phui-status-list-view-css', 'phui-feed-story-css', 'phabricator-feed-css', 'phabricator-dashboard-css', 'aphront-multi-column-view-css', ), 'conpherence.pkg.css' => array( 'conpherence-durable-column-view', 'conpherence-menu-css', 'conpherence-message-pane-css', 'conpherence-notification-css', 'conpherence-transaction-css', 'conpherence-participant-pane-css', 'conpherence-header-pane-css', ), 'conpherence.pkg.js' => array( 'javelin-behavior-conpherence-menu', 'javelin-behavior-conpherence-participant-pane', 'javelin-behavior-conpherence-pontificate', 'javelin-behavior-toggle-widget', ), 'differential.pkg.css' => array( 'differential-core-view-css', 'differential-changeset-view-css', 'differential-revision-history-css', 'differential-revision-list-css', 'differential-table-of-contents-css', 'differential-revision-comment-css', 'differential-revision-add-comment-css', 'phabricator-object-selector-css', 'phabricator-content-source-view-css', 'inline-comment-summary-css', 'phui-inline-comment-view-css', 'phabricator-filetree-view-css', ), 'differential.pkg.js' => array( 'phabricator-drag-and-drop-file-upload', 'phabricator-shaped-request', 'javelin-behavior-differential-feedback-preview', 'javelin-behavior-differential-edit-inline-comments', 'javelin-behavior-differential-populate', 'javelin-behavior-differential-diff-radios', 'javelin-behavior-differential-comment-jump', 'javelin-behavior-differential-add-reviewers-and-ccs', 'javelin-behavior-differential-keyboard-navigation', 'javelin-behavior-aphront-drag-and-drop-textarea', 'javelin-behavior-phabricator-object-selector', 'javelin-behavior-repository-crossreference', 'javelin-behavior-load-blame', 'differential-inline-comment-editor', 'javelin-behavior-differential-dropdown-menus', 'javelin-behavior-differential-toggle-files', 'javelin-behavior-differential-user-select', 'javelin-behavior-aphront-more', 'changeset-view-manager', ), 'diffusion.pkg.css' => array( 'diffusion-icons-css', ), 'diffusion.pkg.js' => array( 'javelin-behavior-diffusion-pull-lastmodified', 'javelin-behavior-diffusion-commit-graph', 'javelin-behavior-audit-preview', ), 'maniphest.pkg.css' => array( 'maniphest-task-summary-css', ), 'maniphest.pkg.js' => array( 'javelin-behavior-maniphest-batch-selector', 'javelin-behavior-maniphest-subpriority-editor', 'javelin-behavior-maniphest-list-editor', ), 'darkconsole.pkg.js' => array( 'javelin-behavior-dark-console', 'javelin-behavior-error-log', ), ); diff --git a/resources/sql/autopatches/20140521.projectslug.2.mig.php b/resources/sql/autopatches/20140521.projectslug.2.mig.php index ca6ccf886a..e0ad4b5070 100644 --- a/resources/sql/autopatches/20140521.projectslug.2.mig.php +++ b/resources/sql/autopatches/20140521.projectslug.2.mig.php @@ -1,33 +1,36 @@ getTableName(); $conn_w = $project_table->establishConnection('w'); $slug_table_name = id(new PhabricatorProjectSlug())->getTableName(); -$time = time(); +$time = PhabricatorTime::getNow(); -echo pht('Migrating project phriction slugs...')."\n"; +echo pht('Migrating projects to slugs...')."\n"; foreach (new LiskMigrationIterator($project_table) as $project) { $id = $project->getID(); echo pht('Migrating project %d...', $id)."\n"; - $phriction_slug = rtrim($project->getPhrictionSlug(), '/'); + + $slug_text = PhabricatorSlug::normalizeProjectSlug($project->getName()); $slug = id(new PhabricatorProjectSlug()) - ->loadOneWhere('slug = %s', $phriction_slug); + ->loadOneWhere('slug = %s', $slug_text); + if ($slug) { echo pht('Already migrated %d... Continuing.', $id)."\n"; continue; } + queryfx( $conn_w, 'INSERT INTO %T (projectPHID, slug, dateCreated, dateModified) '. 'VALUES (%s, %s, %d, %d)', $slug_table_name, $project->getPHID(), - $phriction_slug, + $slug_text, $time, $time); echo pht('Migrated %d.', $id)."\n"; } echo pht('Done.')."\n"; diff --git a/resources/sql/autopatches/20160122.project.1.boarddefault.php b/resources/sql/autopatches/20160122.project.1.boarddefault.php index 8765184629..0ffce8d834 100644 --- a/resources/sql/autopatches/20160122.project.1.boarddefault.php +++ b/resources/sql/autopatches/20160122.project.1.boarddefault.php @@ -1,60 +1,60 @@ establishConnection('w'); -$panel_table = id(new PhabricatorProfilePanelConfiguration()); +$panel_table = id(new PhabricatorProfileMenuItemConfiguration()); $panel_conn = $panel_table->establishConnection('w'); foreach (new LiskMigrationIterator($project_table) as $project) { $columns = queryfx_all( $conn_w, 'SELECT * FROM %T WHERE projectPHID = %s', id(new PhabricatorProjectColumn())->getTableName(), $project->getPHID()); // This project has no columns, so we don't need to change anything. if (!$columns) { continue; } // This project has columns, so set its workboard flag. queryfx( $conn_w, 'UPDATE %T SET hasWorkboard = 1 WHERE id = %d', $project->getTableName(), $project->getID()); // Try to set the default menu item to "Workboard". $config = queryfx_all( $panel_conn, 'SELECT * FROM %T WHERE profilePHID = %s', $panel_table->getTableName(), $project->getPHID()); // There are already some settings, so don't touch them. if ($config) { continue; } queryfx( $panel_conn, 'INSERT INTO %T (phid, profilePHID, panelKey, builtinKey, visibility, panelProperties, panelOrder, dateCreated, dateModified) VALUES (%s, %s, %s, %s, %s, %s, %d, %d, %d)', $panel_table->getTableName(), $panel_table->generatePHID(), $project->getPHID(), - PhabricatorProjectWorkboardProfilePanel::PANELKEY, - PhabricatorProject::PANEL_WORKBOARD, - PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT, + PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY, + PhabricatorProject::ITEM_WORKBOARD, + PhabricatorProfileMenuItemConfiguration::VISIBILITY_DEFAULT, '{}', 2, PhabricatorTime::getNow(), PhabricatorTime::getNow()); } diff --git a/resources/sql/autopatches/20161210.dashboards.01.author.sql b/resources/sql/autopatches/20161210.dashboards.01.author.sql new file mode 100644 index 0000000000..405ed5727c --- /dev/null +++ b/resources/sql/autopatches/20161210.dashboards.01.author.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard + ADD authorPHID VARBINARY(64) NOT NULL; diff --git a/resources/sql/autopatches/20161210.dashboards.02.author.php b/resources/sql/autopatches/20161210.dashboards.02.author.php new file mode 100644 index 0000000000..84f6fbf8d7 --- /dev/null +++ b/resources/sql/autopatches/20161210.dashboards.02.author.php @@ -0,0 +1,39 @@ +establishConnection('w'); + +$txn_table = new PhabricatorDashboardTransaction(); +$txn_conn = $table->establishConnection('r'); + +echo pht("Building Dashboard authorPHIDs...\n"); + +foreach (new LiskMigrationIterator($table) as $dashboard) { + + if ($dashboard->getAuthorPHID()) { + continue; + } + + $author_row = queryfx_one( + $txn_conn, + 'SELECT authorPHID FROM %T WHERE objectPHID = %s ORDER BY id ASC LIMIT 1', + $txn_table->getTableName(), + $dashboard->getPHID()); + + if (!$author_row) { + $author_phid = id(new PhabricatorDashboardApplication())->getPHID(); + } else { + $author_phid = $author_row['authorPHID']; + } + + queryfx( + $conn_w, + 'UPDATE %T SET authorPHID = %s WHERE id = %d', + $table->getTableName(), + $author_phid, + $dashboard->getID()); +} + +echo pht("Done\n"); diff --git a/resources/sql/autopatches/20161211.menu.01.itemkey.sql b/resources/sql/autopatches/20161211.menu.01.itemkey.sql new file mode 100644 index 0000000000..71bfe257f0 --- /dev/null +++ b/resources/sql/autopatches/20161211.menu.01.itemkey.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration + CHANGE panelKey menuItemKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20161211.menu.02.itemprops.sql b/resources/sql/autopatches/20161211.menu.02.itemprops.sql new file mode 100644 index 0000000000..cb9e296d42 --- /dev/null +++ b/resources/sql/autopatches/20161211.menu.02.itemprops.sql @@ -0,0 +1,3 @@ +ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration + CHANGE panelProperties menuItemProperties + LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20161211.menu.03.order.sql b/resources/sql/autopatches/20161211.menu.03.order.sql new file mode 100644 index 0000000000..01291ad4c6 --- /dev/null +++ b/resources/sql/autopatches/20161211.menu.03.order.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_search.search_profilepanelconfiguration + CHANGE panelOrder menuItemOrder INT UNSIGNED; diff --git a/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql b/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql new file mode 100644 index 0000000000..00c52d19cb --- /dev/null +++ b/resources/sql/autopatches/20161212.dashboardpanel.01.author.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard_panel + ADD authorPHID VARBINARY(64) NOT NULL; diff --git a/resources/sql/autopatches/20161212.dashboardpanel.02.author.php b/resources/sql/autopatches/20161212.dashboardpanel.02.author.php new file mode 100644 index 0000000000..bc87aef91c --- /dev/null +++ b/resources/sql/autopatches/20161212.dashboardpanel.02.author.php @@ -0,0 +1,39 @@ +establishConnection('w'); + +$txn_table = new PhabricatorDashboardPanelTransaction(); +$txn_conn = $table->establishConnection('r'); + +echo pht("Building Dashboard Panel authorPHIDs...\n"); + +foreach (new LiskMigrationIterator($table) as $panel) { + + if ($panel->getAuthorPHID()) { + continue; + } + + $panel_row = queryfx_one( + $txn_conn, + 'SELECT authorPHID FROM %T WHERE objectPHID = %s ORDER BY id ASC LIMIT 1', + $txn_table->getTableName(), + $panel->getPHID()); + + if (!$panel_row) { + $author_phid = id(new PhabricatorDashboardApplication())->getPHID(); + } else { + $author_phid = $panel_row['authorPHID']; + } + + queryfx( + $conn_w, + 'UPDATE %T SET authorPHID = %s WHERE id = %d', + $table->getTableName(), + $author_phid, + $panel->getID()); +} + +echo pht("Done\n"); diff --git a/resources/sql/autopatches/20161212.dashboards.01.icon.sql b/resources/sql/autopatches/20161212.dashboards.01.icon.sql new file mode 100644 index 0000000000..e2783ab5bc --- /dev/null +++ b/resources/sql/autopatches/20161212.dashboards.01.icon.sql @@ -0,0 +1,5 @@ +ALTER TABLE {$NAMESPACE}_dashboard.dashboard + ADD icon VARCHAR(32) NOT NULL; + +UPDATE {$NAMESPACE}_dashboard.dashboard + SET icon = 'fa-dashboard'; diff --git a/resources/sql/autopatches/20161213.diff.01.hunks.php b/resources/sql/autopatches/20161213.diff.01.hunks.php new file mode 100644 index 0000000000..c6394defce --- /dev/null +++ b/resources/sql/autopatches/20161213.diff.01.hunks.php @@ -0,0 +1,38 @@ +establishConnection('w'); +$src_table = 'differential_hunk'; +$dst_table = 'differential_hunk_modern'; + +echo tsprintf( + "%s\n", + pht('Migrating old hunks...')); + +foreach (new LiskRawMigrationIterator($conn, $src_table) as $row) { + queryfx( + $conn, + 'INSERT INTO %T + (changesetID, oldOffset, oldLen, newOffset, newLen, + dataType, dataEncoding, dataFormat, data, + dateCreated, dateModified) + VALUES + (%d, %d, %d, %d, %d, + %s, %s, %s, %s, + %d, %d)', + $dst_table, + $row['changesetID'], + $row['oldOffset'], + $row['oldLen'], + $row['newOffset'], + $row['newLen'], + DifferentialModernHunk::DATATYPE_TEXT, + 'utf8', + DifferentialModernHunk::DATAFORMAT_RAW, + $row['changes'], + $row['dateCreated'], + $row['dateModified']); +} + +echo tsprintf( + "%s\n", + pht('Done.')); diff --git a/resources/sql/autopatches/20161216.dashboard.ngram.01.sql b/resources/sql/autopatches/20161216.dashboard.ngram.01.sql new file mode 100644 index 0000000000..8fd237fe82 --- /dev/null +++ b/resources/sql/autopatches/20161216.dashboard.ngram.01.sql @@ -0,0 +1,15 @@ +CREATE TABLE {$NAMESPACE}_dashboard.dashboard_dashboard_ngrams ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + objectID INT UNSIGNED NOT NULL, + ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, + KEY `key_object` (objectID), + KEY `key_ngram` (ngram, objectID) +) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; + +CREATE TABLE {$NAMESPACE}_dashboard.dashboard_dashboardpanel_ngrams ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, + objectID INT UNSIGNED NOT NULL, + ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, + KEY `key_object` (objectID), + KEY `key_ngram` (ngram, objectID) +) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20161216.dashboard.ngram.02.php b/resources/sql/autopatches/20161216.dashboard.ngram.02.php new file mode 100644 index 0000000000..a7abc99b23 --- /dev/null +++ b/resources/sql/autopatches/20161216.dashboard.ngram.02.php @@ -0,0 +1,21 @@ +getPHID(), + array( + 'force' => true, + )); +} + +$table_dbp = new PhabricatorDashboardPanel(); + +foreach (new LiskMigrationIterator($table_dbp) as $panel) { + PhabricatorSearchWorker::queueDocumentForIndexing( + $panel->getPHID(), + array( + 'force' => true, + )); +} diff --git a/resources/sql/patches/090.forceuniqueprojectnames.php b/resources/sql/patches/090.forceuniqueprojectnames.php index a3e029d50a..486856c1c3 100644 --- a/resources/sql/patches/090.forceuniqueprojectnames.php +++ b/resources/sql/patches/090.forceuniqueprojectnames.php @@ -1,112 +1,114 @@ openTransaction(); $table->beginReadLocking(); $projects = $table->loadAll(); $slug_map = array(); foreach ($projects as $project) { $slug = PhabricatorSlug::normalizeProjectSlug($project->getName()); if (!strlen($slug)) { $project_id = $project->getID(); echo pht("Project #%d doesn't have a meaningful name...", $project_id)."\n"; $project->setName(trim(pht('Unnamed Project %s', $project->getName()))); } $slug_map[$slug][] = $project->getID(); } foreach ($slug_map as $slug => $similar) { if (count($similar) <= 1) { continue; } echo pht("Too many projects are similar to '%s'...", $slug)."\n"; foreach (array_slice($similar, 1, null, true) as $key => $project_id) { $project = $projects[$project_id]; $old_name = $project->getName(); $new_name = rename_project($project, $projects); echo pht( "Renaming project #%d from '%s' to '%s'.\n", $project_id, $old_name, $new_name); $project->setName($new_name); } } $update = $projects; while ($update) { $size = count($update); foreach ($update as $key => $project) { $id = $project->getID(); $name = $project->getName(); $slug = PhabricatorSlug::normalizeProjectSlug($name).'/'; echo pht("Updating project #%d '%s' (%s)... ", $id, $name, $slug); try { queryfx( $project->establishConnection('w'), 'UPDATE %T SET name = %s, phrictionSlug = %s WHERE id = %d', $project->getTableName(), $name, $slug, $project->getID()); unset($update[$key]); echo pht('OKAY')."\n"; } catch (AphrontDuplicateKeyQueryException $ex) { echo pht('Failed, will retry.')."\n"; } } if (count($update) == $size) { throw new Exception( pht( 'Failed to make any progress while updating projects. Schema upgrade '. 'has failed. Go manually fix your project names to be unique '. '(they are probably ridiculous?) and then try again.')); } } $table->endReadLocking(); $table->saveTransaction(); echo pht('Done.')."\n"; /** * Rename the project so that it has a unique slug, by appending (2), (3), etc. * to its name. */ function rename_project($project, $projects) { $suffix = 2; while (true) { $new_name = $project->getName().' ('.$suffix.')'; $new_slug = PhabricatorSlug::normalizeProjectSlug($new_name).'/'; $okay = true; foreach ($projects as $other) { if ($other->getID() == $project->getID()) { continue; } - if ($other->getPhrictionSlug() == $new_slug) { + + $other_slug = PhabricatorSlug::normalizeProjectSlug($other->getName()); + if ($other_slug == $new_slug) { $okay = false; break; } } if ($okay) { break; } else { $suffix++; } } return $new_name; } diff --git a/scripts/setup/manage_hunks.php b/scripts/setup/manage_hunks.php deleted file mode 100755 index a2d35779de..0000000000 --- a/scripts/setup/manage_hunks.php +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env php -setTagline(pht('manage hunks')); -$args->setSynopsis(<<parseStandardArguments(); - -$workflows = id(new PhutilClassMapQuery()) - ->setAncestorClass('PhabricatorHunksManagementWorkflow') - ->execute(); -$workflows[] = new PhutilHelpArgumentWorkflow(); -$args->parseWorkflows($workflows); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 97799da03e..b3438afc96 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,9917 +1,9957 @@ 2, 'class' => array( 'AlmanacAddress' => 'applications/almanac/util/AlmanacAddress.php', 'AlmanacBinding' => 'applications/almanac/storage/AlmanacBinding.php', 'AlmanacBindingDisableController' => 'applications/almanac/controller/AlmanacBindingDisableController.php', 'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php', 'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php', 'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php', 'AlmanacBindingPropertyEditEngine' => 'applications/almanac/editor/AlmanacBindingPropertyEditEngine.php', 'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php', 'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php', 'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php', 'AlmanacBindingTransactionQuery' => 'applications/almanac/query/AlmanacBindingTransactionQuery.php', 'AlmanacBindingViewController' => 'applications/almanac/controller/AlmanacBindingViewController.php', 'AlmanacBindingsSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php', 'AlmanacCacheEngineExtension' => 'applications/almanac/engineextension/AlmanacCacheEngineExtension.php', 'AlmanacClusterDatabaseServiceType' => 'applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php', 'AlmanacClusterRepositoryServiceType' => 'applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php', 'AlmanacClusterServiceType' => 'applications/almanac/servicetype/AlmanacClusterServiceType.php', 'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php', 'AlmanacController' => 'applications/almanac/controller/AlmanacController.php', 'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php', 'AlmanacCreateNamespacesCapability' => 'applications/almanac/capability/AlmanacCreateNamespacesCapability.php', 'AlmanacCreateNetworksCapability' => 'applications/almanac/capability/AlmanacCreateNetworksCapability.php', 'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php', 'AlmanacCustomServiceType' => 'applications/almanac/servicetype/AlmanacCustomServiceType.php', 'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php', 'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php', 'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php', 'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php', 'AlmanacDeviceEditEngine' => 'applications/almanac/editor/AlmanacDeviceEditEngine.php', 'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php', 'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php', 'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php', 'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php', 'AlmanacDevicePropertyEditEngine' => 'applications/almanac/editor/AlmanacDevicePropertyEditEngine.php', 'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php', 'AlmanacDeviceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php', 'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php', 'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php', 'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php', 'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php', 'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php', 'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php', 'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php', 'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php', 'AlmanacInterfaceDeleteController' => 'applications/almanac/controller/AlmanacInterfaceDeleteController.php', 'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php', 'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php', 'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php', 'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php', 'AlmanacKeys' => 'applications/almanac/util/AlmanacKeys.php', 'AlmanacManageClusterServicesCapability' => 'applications/almanac/capability/AlmanacManageClusterServicesCapability.php', 'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php', 'AlmanacManagementTrustKeyWorkflow' => 'applications/almanac/management/AlmanacManagementTrustKeyWorkflow.php', 'AlmanacManagementUntrustKeyWorkflow' => 'applications/almanac/management/AlmanacManagementUntrustKeyWorkflow.php', 'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php', 'AlmanacNames' => 'applications/almanac/util/AlmanacNames.php', 'AlmanacNamesTestCase' => 'applications/almanac/util/__tests__/AlmanacNamesTestCase.php', 'AlmanacNamespace' => 'applications/almanac/storage/AlmanacNamespace.php', 'AlmanacNamespaceController' => 'applications/almanac/controller/AlmanacNamespaceController.php', 'AlmanacNamespaceEditController' => 'applications/almanac/controller/AlmanacNamespaceEditController.php', 'AlmanacNamespaceEditEngine' => 'applications/almanac/editor/AlmanacNamespaceEditEngine.php', 'AlmanacNamespaceEditor' => 'applications/almanac/editor/AlmanacNamespaceEditor.php', 'AlmanacNamespaceListController' => 'applications/almanac/controller/AlmanacNamespaceListController.php', 'AlmanacNamespaceNameNgrams' => 'applications/almanac/storage/AlmanacNamespaceNameNgrams.php', 'AlmanacNamespacePHIDType' => 'applications/almanac/phid/AlmanacNamespacePHIDType.php', 'AlmanacNamespaceQuery' => 'applications/almanac/query/AlmanacNamespaceQuery.php', 'AlmanacNamespaceSearchEngine' => 'applications/almanac/query/AlmanacNamespaceSearchEngine.php', 'AlmanacNamespaceTransaction' => 'applications/almanac/storage/AlmanacNamespaceTransaction.php', 'AlmanacNamespaceTransactionQuery' => 'applications/almanac/query/AlmanacNamespaceTransactionQuery.php', 'AlmanacNamespaceViewController' => 'applications/almanac/controller/AlmanacNamespaceViewController.php', 'AlmanacNetwork' => 'applications/almanac/storage/AlmanacNetwork.php', 'AlmanacNetworkController' => 'applications/almanac/controller/AlmanacNetworkController.php', 'AlmanacNetworkEditController' => 'applications/almanac/controller/AlmanacNetworkEditController.php', 'AlmanacNetworkEditEngine' => 'applications/almanac/editor/AlmanacNetworkEditEngine.php', 'AlmanacNetworkEditor' => 'applications/almanac/editor/AlmanacNetworkEditor.php', 'AlmanacNetworkListController' => 'applications/almanac/controller/AlmanacNetworkListController.php', 'AlmanacNetworkNameNgrams' => 'applications/almanac/storage/AlmanacNetworkNameNgrams.php', 'AlmanacNetworkPHIDType' => 'applications/almanac/phid/AlmanacNetworkPHIDType.php', 'AlmanacNetworkQuery' => 'applications/almanac/query/AlmanacNetworkQuery.php', 'AlmanacNetworkSearchEngine' => 'applications/almanac/query/AlmanacNetworkSearchEngine.php', 'AlmanacNetworkTransaction' => 'applications/almanac/storage/AlmanacNetworkTransaction.php', 'AlmanacNetworkTransactionQuery' => 'applications/almanac/query/AlmanacNetworkTransactionQuery.php', 'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php', 'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php', 'AlmanacPropertiesSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php', 'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php', 'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php', 'AlmanacPropertyDeleteController' => 'applications/almanac/controller/AlmanacPropertyDeleteController.php', 'AlmanacPropertyEditController' => 'applications/almanac/controller/AlmanacPropertyEditController.php', 'AlmanacPropertyEditEngine' => 'applications/almanac/editor/AlmanacPropertyEditEngine.php', 'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php', 'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.php', 'AlmanacQuery' => 'applications/almanac/query/AlmanacQuery.php', 'AlmanacSchemaSpec' => 'applications/almanac/storage/AlmanacSchemaSpec.php', 'AlmanacSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacSearchEngineAttachment.php', 'AlmanacService' => 'applications/almanac/storage/AlmanacService.php', 'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php', 'AlmanacServiceDatasource' => 'applications/almanac/typeahead/AlmanacServiceDatasource.php', 'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php', 'AlmanacServiceEditEngine' => 'applications/almanac/editor/AlmanacServiceEditEngine.php', 'AlmanacServiceEditor' => 'applications/almanac/editor/AlmanacServiceEditor.php', 'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php', 'AlmanacServiceNameNgrams' => 'applications/almanac/storage/AlmanacServiceNameNgrams.php', 'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php', 'AlmanacServicePropertyEditEngine' => 'applications/almanac/editor/AlmanacServicePropertyEditEngine.php', 'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php', 'AlmanacServiceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacServiceSearchConduitAPIMethod.php', 'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php', 'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php', 'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php', 'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php', 'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php', 'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php', 'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php', 'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php', 'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php', 'Aphront304Response' => 'aphront/response/Aphront304Response.php', 'Aphront400Response' => 'aphront/response/Aphront400Response.php', 'Aphront403Response' => 'aphront/response/Aphront403Response.php', 'Aphront404Response' => 'aphront/response/Aphront404Response.php', 'AphrontAjaxResponse' => 'aphront/response/AphrontAjaxResponse.php', 'AphrontApplicationConfiguration' => 'aphront/configuration/AphrontApplicationConfiguration.php', 'AphrontBarView' => 'view/widget/bars/AphrontBarView.php', 'AphrontBoolHTTPParameterType' => 'aphront/httpparametertype/AphrontBoolHTTPParameterType.php', 'AphrontCalendarEventView' => 'applications/calendar/view/AphrontCalendarEventView.php', 'AphrontController' => 'aphront/AphrontController.php', 'AphrontCursorPagerView' => 'view/control/AphrontCursorPagerView.php', 'AphrontDefaultApplicationConfiguration' => 'aphront/configuration/AphrontDefaultApplicationConfiguration.php', 'AphrontDialogResponse' => 'aphront/response/AphrontDialogResponse.php', 'AphrontDialogView' => 'view/AphrontDialogView.php', 'AphrontEpochHTTPParameterType' => 'aphront/httpparametertype/AphrontEpochHTTPParameterType.php', 'AphrontException' => 'aphront/exception/AphrontException.php', 'AphrontFileHTTPParameterType' => 'aphront/httpparametertype/AphrontFileHTTPParameterType.php', 'AphrontFileResponse' => 'aphront/response/AphrontFileResponse.php', 'AphrontFormCheckboxControl' => 'view/form/control/AphrontFormCheckboxControl.php', 'AphrontFormControl' => 'view/form/control/AphrontFormControl.php', 'AphrontFormDateControl' => 'view/form/control/AphrontFormDateControl.php', 'AphrontFormDateControlValue' => 'view/form/control/AphrontFormDateControlValue.php', 'AphrontFormDividerControl' => 'view/form/control/AphrontFormDividerControl.php', 'AphrontFormFileControl' => 'view/form/control/AphrontFormFileControl.php', 'AphrontFormHandlesControl' => 'view/form/control/AphrontFormHandlesControl.php', 'AphrontFormMarkupControl' => 'view/form/control/AphrontFormMarkupControl.php', 'AphrontFormPasswordControl' => 'view/form/control/AphrontFormPasswordControl.php', 'AphrontFormPolicyControl' => 'view/form/control/AphrontFormPolicyControl.php', 'AphrontFormRadioButtonControl' => 'view/form/control/AphrontFormRadioButtonControl.php', 'AphrontFormRecaptchaControl' => 'view/form/control/AphrontFormRecaptchaControl.php', 'AphrontFormSelectControl' => 'view/form/control/AphrontFormSelectControl.php', 'AphrontFormStaticControl' => 'view/form/control/AphrontFormStaticControl.php', 'AphrontFormSubmitControl' => 'view/form/control/AphrontFormSubmitControl.php', 'AphrontFormTextAreaControl' => 'view/form/control/AphrontFormTextAreaControl.php', 'AphrontFormTextControl' => 'view/form/control/AphrontFormTextControl.php', 'AphrontFormTextWithSubmitControl' => 'view/form/control/AphrontFormTextWithSubmitControl.php', 'AphrontFormTokenizerControl' => 'view/form/control/AphrontFormTokenizerControl.php', 'AphrontFormTypeaheadControl' => 'view/form/control/AphrontFormTypeaheadControl.php', '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', 'AphrontIntHTTPParameterType' => 'aphront/httpparametertype/AphrontIntHTTPParameterType.php', 'AphrontIsolatedDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontIsolatedDatabaseConnectionTestCase.php', 'AphrontIsolatedHTTPSink' => 'aphront/sink/AphrontIsolatedHTTPSink.php', 'AphrontJSONResponse' => 'aphront/response/AphrontJSONResponse.php', 'AphrontJavelinView' => 'view/AphrontJavelinView.php', 'AphrontKeyboardShortcutsAvailableView' => 'view/widget/AphrontKeyboardShortcutsAvailableView.php', 'AphrontListFilterView' => 'view/layout/AphrontListFilterView.php', 'AphrontListHTTPParameterType' => 'aphront/httpparametertype/AphrontListHTTPParameterType.php', 'AphrontMalformedRequestException' => 'aphront/exception/AphrontMalformedRequestException.php', 'AphrontMoreView' => 'view/layout/AphrontMoreView.php', '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', 'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php', 'AphrontRequest' => 'aphront/AphrontRequest.php', 'AphrontRequestExceptionHandler' => 'aphront/handler/AphrontRequestExceptionHandler.php', 'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php', 'AphrontResponse' => 'aphront/response/AphrontResponse.php', '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', 'AuditConduitAPIMethod' => 'applications/audit/conduit/AuditConduitAPIMethod.php', 'AuditQueryConduitAPIMethod' => 'applications/audit/conduit/AuditQueryConduitAPIMethod.php', 'AuthManageProvidersCapability' => 'applications/auth/capability/AuthManageProvidersCapability.php', 'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php', 'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php', 'CelerityAPI' => 'applications/celerity/CelerityAPI.php', 'CelerityDefaultPostprocessor' => 'applications/celerity/postprocessor/CelerityDefaultPostprocessor.php', 'CelerityHighContrastPostprocessor' => 'applications/celerity/postprocessor/CelerityHighContrastPostprocessor.php', 'CelerityLargeFontPostprocessor' => 'applications/celerity/postprocessor/CelerityLargeFontPostprocessor.php', 'CelerityManagementMapWorkflow' => 'applications/celerity/management/CelerityManagementMapWorkflow.php', 'CelerityManagementSyntaxWorkflow' => 'applications/celerity/management/CelerityManagementSyntaxWorkflow.php', 'CelerityManagementWorkflow' => 'applications/celerity/management/CelerityManagementWorkflow.php', 'CelerityPhabricatorResourceController' => 'applications/celerity/controller/CelerityPhabricatorResourceController.php', 'CelerityPhabricatorResources' => 'applications/celerity/resources/CelerityPhabricatorResources.php', 'CelerityPhysicalResources' => 'applications/celerity/resources/CelerityPhysicalResources.php', 'CelerityPhysicalResourcesTestCase' => 'applications/celerity/resources/__tests__/CelerityPhysicalResourcesTestCase.php', 'CelerityPostprocessor' => 'applications/celerity/postprocessor/CelerityPostprocessor.php', 'CelerityPostprocessorTestCase' => 'applications/celerity/__tests__/CelerityPostprocessorTestCase.php', 'CelerityResourceController' => 'applications/celerity/controller/CelerityResourceController.php', 'CelerityResourceGraph' => 'applications/celerity/CelerityResourceGraph.php', 'CelerityResourceMap' => 'applications/celerity/CelerityResourceMap.php', 'CelerityResourceMapGenerator' => 'applications/celerity/CelerityResourceMapGenerator.php', 'CelerityResourceTransformer' => 'applications/celerity/CelerityResourceTransformer.php', 'CelerityResourceTransformerTestCase' => 'applications/celerity/__tests__/CelerityResourceTransformerTestCase.php', 'CelerityResources' => 'applications/celerity/resources/CelerityResources.php', 'CelerityResourcesOnDisk' => 'applications/celerity/resources/CelerityResourcesOnDisk.php', 'CeleritySpriteGenerator' => 'applications/celerity/CeleritySpriteGenerator.php', 'CelerityStaticResourceResponse' => 'applications/celerity/CelerityStaticResourceResponse.php', 'ChatLogConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogConduitAPIMethod.php', 'ChatLogQueryConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogQueryConduitAPIMethod.php', 'ChatLogRecordConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogRecordConduitAPIMethod.php', 'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php', 'ConduitAPIMethodTestCase' => 'applications/conduit/method/__tests__/ConduitAPIMethodTestCase.php', 'ConduitAPIRequest' => 'applications/conduit/protocol/ConduitAPIRequest.php', 'ConduitAPIResponse' => 'applications/conduit/protocol/ConduitAPIResponse.php', 'ConduitApplicationNotInstalledException' => 'applications/conduit/protocol/exception/ConduitApplicationNotInstalledException.php', 'ConduitBoolParameterType' => 'applications/conduit/parametertype/ConduitBoolParameterType.php', 'ConduitCall' => 'applications/conduit/call/ConduitCall.php', 'ConduitCallTestCase' => 'applications/conduit/call/__tests__/ConduitCallTestCase.php', 'ConduitColumnsParameterType' => 'applications/conduit/parametertype/ConduitColumnsParameterType.php', 'ConduitConnectConduitAPIMethod' => 'applications/conduit/method/ConduitConnectConduitAPIMethod.php', 'ConduitEpochParameterType' => 'applications/conduit/parametertype/ConduitEpochParameterType.php', 'ConduitException' => 'applications/conduit/protocol/exception/ConduitException.php', 'ConduitGetCapabilitiesConduitAPIMethod' => 'applications/conduit/method/ConduitGetCapabilitiesConduitAPIMethod.php', 'ConduitGetCertificateConduitAPIMethod' => 'applications/conduit/method/ConduitGetCertificateConduitAPIMethod.php', 'ConduitIntListParameterType' => 'applications/conduit/parametertype/ConduitIntListParameterType.php', 'ConduitIntParameterType' => 'applications/conduit/parametertype/ConduitIntParameterType.php', 'ConduitListParameterType' => 'applications/conduit/parametertype/ConduitListParameterType.php', 'ConduitLogGarbageCollector' => 'applications/conduit/garbagecollector/ConduitLogGarbageCollector.php', 'ConduitMethodDoesNotExistException' => 'applications/conduit/protocol/exception/ConduitMethodDoesNotExistException.php', 'ConduitMethodNotFoundException' => 'applications/conduit/protocol/exception/ConduitMethodNotFoundException.php', 'ConduitPHIDListParameterType' => 'applications/conduit/parametertype/ConduitPHIDListParameterType.php', 'ConduitPHIDParameterType' => 'applications/conduit/parametertype/ConduitPHIDParameterType.php', 'ConduitParameterType' => 'applications/conduit/parametertype/ConduitParameterType.php', 'ConduitPingConduitAPIMethod' => 'applications/conduit/method/ConduitPingConduitAPIMethod.php', 'ConduitPointsParameterType' => 'applications/conduit/parametertype/ConduitPointsParameterType.php', 'ConduitProjectListParameterType' => 'applications/conduit/parametertype/ConduitProjectListParameterType.php', 'ConduitQueryConduitAPIMethod' => 'applications/conduit/method/ConduitQueryConduitAPIMethod.php', 'ConduitResultSearchEngineExtension' => 'applications/conduit/query/ConduitResultSearchEngineExtension.php', 'ConduitSSHWorkflow' => 'applications/conduit/ssh/ConduitSSHWorkflow.php', 'ConduitStringListParameterType' => 'applications/conduit/parametertype/ConduitStringListParameterType.php', 'ConduitStringParameterType' => 'applications/conduit/parametertype/ConduitStringParameterType.php', 'ConduitTokenGarbageCollector' => 'applications/conduit/garbagecollector/ConduitTokenGarbageCollector.php', 'ConduitUserListParameterType' => 'applications/conduit/parametertype/ConduitUserListParameterType.php', 'ConduitUserParameterType' => 'applications/conduit/parametertype/ConduitUserParameterType.php', 'ConduitWildParameterType' => 'applications/conduit/parametertype/ConduitWildParameterType.php', 'ConpherenceColumnViewController' => 'applications/conpherence/controller/ConpherenceColumnViewController.php', 'ConpherenceConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceConduitAPIMethod.php', 'ConpherenceConfigOptions' => 'applications/conpherence/config/ConpherenceConfigOptions.php', 'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php', 'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php', 'ConpherenceCreateThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php', 'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php', 'ConpherenceDurableColumnView' => 'applications/conpherence/view/ConpherenceDurableColumnView.php', 'ConpherenceEditor' => 'applications/conpherence/editor/ConpherenceEditor.php', 'ConpherenceFulltextQuery' => 'applications/conpherence/query/ConpherenceFulltextQuery.php', 'ConpherenceIndex' => 'applications/conpherence/storage/ConpherenceIndex.php', 'ConpherenceLayoutView' => 'applications/conpherence/view/ConpherenceLayoutView.php', 'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php', 'ConpherenceMenuItemView' => 'applications/conpherence/view/ConpherenceMenuItemView.php', 'ConpherenceNewRoomController' => 'applications/conpherence/controller/ConpherenceNewRoomController.php', 'ConpherenceNotificationPanelController' => 'applications/conpherence/controller/ConpherenceNotificationPanelController.php', 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', 'ConpherenceParticipantController' => 'applications/conpherence/controller/ConpherenceParticipantController.php', 'ConpherenceParticipantCountQuery' => 'applications/conpherence/query/ConpherenceParticipantCountQuery.php', 'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php', 'ConpherenceParticipantView' => 'applications/conpherence/view/ConpherenceParticipantView.php', 'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php', 'ConpherenceQueryThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryThreadConduitAPIMethod.php', 'ConpherenceQueryTransactionConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php', 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', 'ConpherenceRoomListController' => 'applications/conpherence/controller/ConpherenceRoomListController.php', 'ConpherenceRoomPictureController' => 'applications/conpherence/controller/ConpherenceRoomPictureController.php', 'ConpherenceRoomTestCase' => 'applications/conpherence/__tests__/ConpherenceRoomTestCase.php', 'ConpherenceSchemaSpec' => 'applications/conpherence/storage/ConpherenceSchemaSpec.php', 'ConpherenceTestCase' => 'applications/conpherence/__tests__/ConpherenceTestCase.php', 'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php', 'ConpherenceThreadDatasource' => 'applications/conpherence/typeahead/ConpherenceThreadDatasource.php', 'ConpherenceThreadIndexEngineExtension' => 'applications/conpherence/engineextension/ConpherenceThreadIndexEngineExtension.php', 'ConpherenceThreadListView' => 'applications/conpherence/view/ConpherenceThreadListView.php', 'ConpherenceThreadMailReceiver' => 'applications/conpherence/mail/ConpherenceThreadMailReceiver.php', 'ConpherenceThreadMembersPolicyRule' => 'applications/conpherence/policyrule/ConpherenceThreadMembersPolicyRule.php', 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', 'ConpherenceThreadRemarkupRule' => 'applications/conpherence/remarkup/ConpherenceThreadRemarkupRule.php', 'ConpherenceThreadSearchController' => 'applications/conpherence/controller/ConpherenceThreadSearchController.php', 'ConpherenceThreadSearchEngine' => 'applications/conpherence/query/ConpherenceThreadSearchEngine.php', 'ConpherenceThreadTitleNgrams' => 'applications/conpherence/storage/ConpherenceThreadTitleNgrams.php', 'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php', 'ConpherenceTransactionComment' => 'applications/conpherence/storage/ConpherenceTransactionComment.php', 'ConpherenceTransactionQuery' => 'applications/conpherence/query/ConpherenceTransactionQuery.php', 'ConpherenceTransactionRenderer' => 'applications/conpherence/ConpherenceTransactionRenderer.php', 'ConpherenceTransactionView' => 'applications/conpherence/view/ConpherenceTransactionView.php', 'ConpherenceUpdateActions' => 'applications/conpherence/constants/ConpherenceUpdateActions.php', 'ConpherenceUpdateController' => 'applications/conpherence/controller/ConpherenceUpdateController.php', 'ConpherenceUpdateThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceUpdateThreadConduitAPIMethod.php', 'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php', 'DarkConsoleController' => 'applications/console/controller/DarkConsoleController.php', 'DarkConsoleCore' => 'applications/console/core/DarkConsoleCore.php', 'DarkConsoleDataController' => 'applications/console/controller/DarkConsoleDataController.php', 'DarkConsoleErrorLogPlugin' => 'applications/console/plugin/DarkConsoleErrorLogPlugin.php', 'DarkConsoleErrorLogPluginAPI' => 'applications/console/plugin/errorlog/DarkConsoleErrorLogPluginAPI.php', 'DarkConsoleEventPlugin' => 'applications/console/plugin/DarkConsoleEventPlugin.php', 'DarkConsoleEventPluginAPI' => 'applications/console/plugin/event/DarkConsoleEventPluginAPI.php', 'DarkConsolePlugin' => 'applications/console/plugin/DarkConsolePlugin.php', 'DarkConsoleRequestPlugin' => 'applications/console/plugin/DarkConsoleRequestPlugin.php', 'DarkConsoleServicesPlugin' => 'applications/console/plugin/DarkConsoleServicesPlugin.php', 'DarkConsoleStartupPlugin' => 'applications/console/plugin/DarkConsoleStartupPlugin.php', 'DarkConsoleXHProfPlugin' => 'applications/console/plugin/DarkConsoleXHProfPlugin.php', 'DarkConsoleXHProfPluginAPI' => 'applications/console/plugin/xhprof/DarkConsoleXHProfPluginAPI.php', 'DifferentialAction' => 'applications/differential/constants/DifferentialAction.php', 'DifferentialActionEmailCommand' => 'applications/differential/command/DifferentialActionEmailCommand.php', 'DifferentialAddCommentView' => 'applications/differential/view/DifferentialAddCommentView.php', 'DifferentialAdjustmentMapTestCase' => 'applications/differential/storage/__tests__/DifferentialAdjustmentMapTestCase.php', 'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php', - 'DifferentialApplyPatchField' => 'applications/differential/customfield/DifferentialApplyPatchField.php', 'DifferentialAsanaRepresentationField' => 'applications/differential/customfield/DifferentialAsanaRepresentationField.php', + 'DifferentialAuditorsCommitMessageField' => 'applications/differential/field/DifferentialAuditorsCommitMessageField.php', 'DifferentialAuditorsField' => 'applications/differential/customfield/DifferentialAuditorsField.php', - 'DifferentialAuthorField' => 'applications/differential/customfield/DifferentialAuthorField.php', + 'DifferentialBlameRevisionCommitMessageField' => 'applications/differential/field/DifferentialBlameRevisionCommitMessageField.php', 'DifferentialBlameRevisionField' => 'applications/differential/customfield/DifferentialBlameRevisionField.php', 'DifferentialBlockHeraldAction' => 'applications/differential/herald/DifferentialBlockHeraldAction.php', 'DifferentialBlockingReviewerDatasource' => 'applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php', 'DifferentialBranchField' => 'applications/differential/customfield/DifferentialBranchField.php', 'DifferentialChangeDetailMailView' => 'applications/differential/mail/DifferentialChangeDetailMailView.php', 'DifferentialChangeHeraldFieldGroup' => 'applications/differential/herald/DifferentialChangeHeraldFieldGroup.php', 'DifferentialChangeType' => 'applications/differential/constants/DifferentialChangeType.php', 'DifferentialChangesSinceLastUpdateField' => 'applications/differential/customfield/DifferentialChangesSinceLastUpdateField.php', 'DifferentialChangeset' => 'applications/differential/storage/DifferentialChangeset.php', 'DifferentialChangesetDetailView' => 'applications/differential/view/DifferentialChangesetDetailView.php', 'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php', 'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php', 'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php', 'DifferentialChangesetOneUpMailRenderer' => 'applications/differential/render/DifferentialChangesetOneUpMailRenderer.php', 'DifferentialChangesetOneUpRenderer' => 'applications/differential/render/DifferentialChangesetOneUpRenderer.php', 'DifferentialChangesetOneUpTestRenderer' => 'applications/differential/render/DifferentialChangesetOneUpTestRenderer.php', 'DifferentialChangesetParser' => 'applications/differential/parser/DifferentialChangesetParser.php', 'DifferentialChangesetParserTestCase' => 'applications/differential/parser/__tests__/DifferentialChangesetParserTestCase.php', 'DifferentialChangesetQuery' => 'applications/differential/query/DifferentialChangesetQuery.php', 'DifferentialChangesetRenderer' => 'applications/differential/render/DifferentialChangesetRenderer.php', 'DifferentialChangesetTestRenderer' => 'applications/differential/render/DifferentialChangesetTestRenderer.php', 'DifferentialChangesetTwoUpRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpRenderer.php', 'DifferentialChangesetTwoUpTestRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpTestRenderer.php', 'DifferentialChangesetViewController' => 'applications/differential/controller/DifferentialChangesetViewController.php', - 'DifferentialChildRevisionsField' => 'applications/differential/customfield/DifferentialChildRevisionsField.php', 'DifferentialCloseConduitAPIMethod' => 'applications/differential/conduit/DifferentialCloseConduitAPIMethod.php', 'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php', 'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php', + 'DifferentialCommitMessageCustomField' => 'applications/differential/field/DifferentialCommitMessageCustomField.php', + 'DifferentialCommitMessageField' => 'applications/differential/field/DifferentialCommitMessageField.php', 'DifferentialCommitMessageParser' => 'applications/differential/parser/DifferentialCommitMessageParser.php', 'DifferentialCommitMessageParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php', 'DifferentialCommitsField' => 'applications/differential/customfield/DifferentialCommitsField.php', 'DifferentialConduitAPIMethod' => 'applications/differential/conduit/DifferentialConduitAPIMethod.php', - 'DifferentialConflictsField' => 'applications/differential/customfield/DifferentialConflictsField.php', + 'DifferentialConflictsCommitMessageField' => 'applications/differential/field/DifferentialConflictsCommitMessageField.php', 'DifferentialController' => 'applications/differential/controller/DifferentialController.php', 'DifferentialCoreCustomField' => 'applications/differential/customfield/DifferentialCoreCustomField.php', 'DifferentialCreateCommentConduitAPIMethod' => 'applications/differential/conduit/DifferentialCreateCommentConduitAPIMethod.php', 'DifferentialCreateDiffConduitAPIMethod' => 'applications/differential/conduit/DifferentialCreateDiffConduitAPIMethod.php', 'DifferentialCreateInlineConduitAPIMethod' => 'applications/differential/conduit/DifferentialCreateInlineConduitAPIMethod.php', 'DifferentialCreateMailReceiver' => 'applications/differential/mail/DifferentialCreateMailReceiver.php', 'DifferentialCreateRawDiffConduitAPIMethod' => 'applications/differential/conduit/DifferentialCreateRawDiffConduitAPIMethod.php', 'DifferentialCreateRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php', 'DifferentialCustomField' => 'applications/differential/customfield/DifferentialCustomField.php', 'DifferentialCustomFieldDependsOnParser' => 'applications/differential/parser/DifferentialCustomFieldDependsOnParser.php', 'DifferentialCustomFieldDependsOnParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCustomFieldDependsOnParserTestCase.php', 'DifferentialCustomFieldNumericIndex' => 'applications/differential/storage/DifferentialCustomFieldNumericIndex.php', 'DifferentialCustomFieldRevertsParser' => 'applications/differential/parser/DifferentialCustomFieldRevertsParser.php', 'DifferentialCustomFieldRevertsParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCustomFieldRevertsParserTestCase.php', 'DifferentialCustomFieldStorage' => 'applications/differential/storage/DifferentialCustomFieldStorage.php', 'DifferentialCustomFieldStringIndex' => 'applications/differential/storage/DifferentialCustomFieldStringIndex.php', 'DifferentialDAO' => 'applications/differential/storage/DifferentialDAO.php', 'DifferentialDefaultViewCapability' => 'applications/differential/capability/DifferentialDefaultViewCapability.php', 'DifferentialDiff' => 'applications/differential/storage/DifferentialDiff.php', 'DifferentialDiffAffectedFilesHeraldField' => 'applications/differential/herald/DifferentialDiffAffectedFilesHeraldField.php', 'DifferentialDiffAuthorHeraldField' => 'applications/differential/herald/DifferentialDiffAuthorHeraldField.php', 'DifferentialDiffAuthorProjectsHeraldField' => 'applications/differential/herald/DifferentialDiffAuthorProjectsHeraldField.php', 'DifferentialDiffContentAddedHeraldField' => 'applications/differential/herald/DifferentialDiffContentAddedHeraldField.php', 'DifferentialDiffContentHeraldField' => 'applications/differential/herald/DifferentialDiffContentHeraldField.php', 'DifferentialDiffContentRemovedHeraldField' => 'applications/differential/herald/DifferentialDiffContentRemovedHeraldField.php', 'DifferentialDiffCreateController' => 'applications/differential/controller/DifferentialDiffCreateController.php', 'DifferentialDiffEditor' => 'applications/differential/editor/DifferentialDiffEditor.php', 'DifferentialDiffExtractionEngine' => 'applications/differential/engine/DifferentialDiffExtractionEngine.php', 'DifferentialDiffHeraldField' => 'applications/differential/herald/DifferentialDiffHeraldField.php', 'DifferentialDiffHeraldFieldGroup' => 'applications/differential/herald/DifferentialDiffHeraldFieldGroup.php', 'DifferentialDiffInlineCommentQuery' => 'applications/differential/query/DifferentialDiffInlineCommentQuery.php', 'DifferentialDiffPHIDType' => 'applications/differential/phid/DifferentialDiffPHIDType.php', 'DifferentialDiffProperty' => 'applications/differential/storage/DifferentialDiffProperty.php', 'DifferentialDiffQuery' => 'applications/differential/query/DifferentialDiffQuery.php', 'DifferentialDiffRepositoryHeraldField' => 'applications/differential/herald/DifferentialDiffRepositoryHeraldField.php', 'DifferentialDiffRepositoryProjectsHeraldField' => 'applications/differential/herald/DifferentialDiffRepositoryProjectsHeraldField.php', 'DifferentialDiffTestCase' => 'applications/differential/storage/__tests__/DifferentialDiffTestCase.php', 'DifferentialDiffTransaction' => 'applications/differential/storage/DifferentialDiffTransaction.php', 'DifferentialDiffTransactionQuery' => 'applications/differential/query/DifferentialDiffTransactionQuery.php', 'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php', 'DifferentialDraft' => 'applications/differential/storage/DifferentialDraft.php', - 'DifferentialEditPolicyField' => 'applications/differential/customfield/DifferentialEditPolicyField.php', 'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', 'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', 'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php', 'DifferentialFindConduitAPIMethod' => 'applications/differential/conduit/DifferentialFindConduitAPIMethod.php', 'DifferentialGetAllDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetAllDiffsConduitAPIMethod.php', 'DifferentialGetCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php', 'DifferentialGetCommitPathsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitPathsConduitAPIMethod.php', 'DifferentialGetDiffConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetDiffConduitAPIMethod.php', 'DifferentialGetRawDiffConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRawDiffConduitAPIMethod.php', 'DifferentialGetRevisionCommentsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRevisionCommentsConduitAPIMethod.php', 'DifferentialGetRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetRevisionConduitAPIMethod.php', 'DifferentialGetWorkingCopy' => 'applications/differential/DifferentialGetWorkingCopy.php', 'DifferentialGitHubLandingStrategy' => 'applications/differential/landing/DifferentialGitHubLandingStrategy.php', - 'DifferentialGitSVNIDField' => 'applications/differential/customfield/DifferentialGitSVNIDField.php', + 'DifferentialGitSVNIDCommitMessageField' => 'applications/differential/field/DifferentialGitSVNIDCommitMessageField.php', 'DifferentialHarbormasterField' => 'applications/differential/customfield/DifferentialHarbormasterField.php', 'DifferentialHiddenComment' => 'applications/differential/storage/DifferentialHiddenComment.php', 'DifferentialHostField' => 'applications/differential/customfield/DifferentialHostField.php', 'DifferentialHostedGitLandingStrategy' => 'applications/differential/landing/DifferentialHostedGitLandingStrategy.php', 'DifferentialHostedMercurialLandingStrategy' => 'applications/differential/landing/DifferentialHostedMercurialLandingStrategy.php', 'DifferentialHovercardEngineExtension' => 'applications/differential/engineextension/DifferentialHovercardEngineExtension.php', 'DifferentialHunk' => 'applications/differential/storage/DifferentialHunk.php', 'DifferentialHunkParser' => 'applications/differential/parser/DifferentialHunkParser.php', 'DifferentialHunkParserTestCase' => 'applications/differential/parser/__tests__/DifferentialHunkParserTestCase.php', 'DifferentialHunkQuery' => 'applications/differential/query/DifferentialHunkQuery.php', 'DifferentialHunkTestCase' => 'applications/differential/storage/__tests__/DifferentialHunkTestCase.php', 'DifferentialInlineComment' => 'applications/differential/storage/DifferentialInlineComment.php', 'DifferentialInlineCommentEditController' => 'applications/differential/controller/DifferentialInlineCommentEditController.php', 'DifferentialInlineCommentMailView' => 'applications/differential/mail/DifferentialInlineCommentMailView.php', 'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/DifferentialInlineCommentPreviewController.php', 'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php', + 'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php', 'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php', 'DifferentialLandingActionMenuEventListener' => 'applications/differential/landing/DifferentialLandingActionMenuEventListener.php', 'DifferentialLandingStrategy' => 'applications/differential/landing/DifferentialLandingStrategy.php', 'DifferentialLegacyHunk' => 'applications/differential/storage/DifferentialLegacyHunk.php', 'DifferentialLineAdjustmentMap' => 'applications/differential/parser/DifferentialLineAdjustmentMap.php', 'DifferentialLintField' => 'applications/differential/customfield/DifferentialLintField.php', 'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php', 'DifferentialLocalCommitsView' => 'applications/differential/view/DifferentialLocalCommitsView.php', 'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php', 'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php', 'DifferentialModernHunk' => 'applications/differential/storage/DifferentialModernHunk.php', - 'DifferentialNextStepField' => 'applications/differential/customfield/DifferentialNextStepField.php', - 'DifferentialParentRevisionsField' => 'applications/differential/customfield/DifferentialParentRevisionsField.php', 'DifferentialParseCacheGarbageCollector' => 'applications/differential/garbagecollector/DifferentialParseCacheGarbageCollector.php', 'DifferentialParseCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php', 'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php', 'DifferentialPathField' => 'applications/differential/customfield/DifferentialPathField.php', 'DifferentialProjectReviewersField' => 'applications/differential/customfield/DifferentialProjectReviewersField.php', - 'DifferentialProjectsField' => 'applications/differential/customfield/DifferentialProjectsField.php', 'DifferentialQueryConduitAPIMethod' => 'applications/differential/conduit/DifferentialQueryConduitAPIMethod.php', 'DifferentialQueryDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialQueryDiffsConduitAPIMethod.php', 'DifferentialRawDiffRenderer' => 'applications/differential/render/DifferentialRawDiffRenderer.php', 'DifferentialReleephRequestFieldSpecification' => 'applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php', 'DifferentialRemarkupRule' => 'applications/differential/remarkup/DifferentialRemarkupRule.php', 'DifferentialReplyHandler' => 'applications/differential/mail/DifferentialReplyHandler.php', 'DifferentialRepositoryDatasource' => 'applications/differential/typeahead/DifferentialRepositoryDatasource.php', 'DifferentialRepositoryField' => 'applications/differential/customfield/DifferentialRepositoryField.php', 'DifferentialRepositoryLookup' => 'applications/differential/query/DifferentialRepositoryLookup.php', 'DifferentialRequiredSignaturesField' => 'applications/differential/customfield/DifferentialRequiredSignaturesField.php', 'DifferentialResponsibleDatasource' => 'applications/differential/typeahead/DifferentialResponsibleDatasource.php', 'DifferentialResponsibleUserDatasource' => 'applications/differential/typeahead/DifferentialResponsibleUserDatasource.php', 'DifferentialResponsibleViewerFunctionDatasource' => 'applications/differential/typeahead/DifferentialResponsibleViewerFunctionDatasource.php', + 'DifferentialRevertPlanCommitMessageField' => 'applications/differential/field/DifferentialRevertPlanCommitMessageField.php', 'DifferentialRevertPlanField' => 'applications/differential/customfield/DifferentialRevertPlanField.php', - 'DifferentialReviewedByField' => 'applications/differential/customfield/DifferentialReviewedByField.php', - 'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php', + 'DifferentialReviewedByCommitMessageField' => 'applications/differential/field/DifferentialReviewedByCommitMessageField.php', 'DifferentialReviewerDatasource' => 'applications/differential/typeahead/DifferentialReviewerDatasource.php', 'DifferentialReviewerForRevisionEdgeType' => 'applications/differential/edge/DifferentialReviewerForRevisionEdgeType.php', + 'DifferentialReviewerProxy' => 'applications/differential/storage/DifferentialReviewerProxy.php', 'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php', 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php', 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php', 'DifferentialReviewersAddReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php', 'DifferentialReviewersAddSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php', + 'DifferentialReviewersCommitMessageField' => 'applications/differential/field/DifferentialReviewersCommitMessageField.php', 'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php', 'DifferentialReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersHeraldAction.php', 'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php', 'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php', 'DifferentialRevisionAffectedFilesHeraldField' => 'applications/differential/herald/DifferentialRevisionAffectedFilesHeraldField.php', 'DifferentialRevisionAuthorHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorHeraldField.php', 'DifferentialRevisionAuthorProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorProjectsHeraldField.php', 'DifferentialRevisionCloseDetailsController' => 'applications/differential/controller/DifferentialRevisionCloseDetailsController.php', 'DifferentialRevisionContentAddedHeraldField' => 'applications/differential/herald/DifferentialRevisionContentAddedHeraldField.php', 'DifferentialRevisionContentHeraldField' => 'applications/differential/herald/DifferentialRevisionContentHeraldField.php', 'DifferentialRevisionContentRemovedHeraldField' => 'applications/differential/herald/DifferentialRevisionContentRemovedHeraldField.php', 'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependedOnByRevisionEdgeType.php', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'applications/differential/edge/DifferentialRevisionDependsOnRevisionEdgeType.php', + 'DifferentialRevisionEditConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php', 'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', + 'DifferentialRevisionEditEngine' => 'applications/differential/editor/DifferentialRevisionEditEngine.php', 'DifferentialRevisionFulltextEngine' => 'applications/differential/search/DifferentialRevisionFulltextEngine.php', 'DifferentialRevisionGraph' => 'infrastructure/graph/DifferentialRevisionGraph.php', 'DifferentialRevisionHasChildRelationship' => 'applications/differential/relationships/DifferentialRevisionHasChildRelationship.php', 'DifferentialRevisionHasCommitEdgeType' => 'applications/differential/edge/DifferentialRevisionHasCommitEdgeType.php', 'DifferentialRevisionHasCommitRelationship' => 'applications/differential/relationships/DifferentialRevisionHasCommitRelationship.php', 'DifferentialRevisionHasParentRelationship' => 'applications/differential/relationships/DifferentialRevisionHasParentRelationship.php', 'DifferentialRevisionHasReviewerEdgeType' => 'applications/differential/edge/DifferentialRevisionHasReviewerEdgeType.php', 'DifferentialRevisionHasTaskEdgeType' => 'applications/differential/edge/DifferentialRevisionHasTaskEdgeType.php', 'DifferentialRevisionHasTaskRelationship' => 'applications/differential/relationships/DifferentialRevisionHasTaskRelationship.php', 'DifferentialRevisionHeraldField' => 'applications/differential/herald/DifferentialRevisionHeraldField.php', 'DifferentialRevisionHeraldFieldGroup' => 'applications/differential/herald/DifferentialRevisionHeraldFieldGroup.php', - 'DifferentialRevisionIDField' => 'applications/differential/customfield/DifferentialRevisionIDField.php', + 'DifferentialRevisionIDCommitMessageField' => 'applications/differential/field/DifferentialRevisionIDCommitMessageField.php', 'DifferentialRevisionLandController' => 'applications/differential/controller/DifferentialRevisionLandController.php', 'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php', 'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php', 'DifferentialRevisionMailReceiver' => 'applications/differential/mail/DifferentialRevisionMailReceiver.php', 'DifferentialRevisionOperationController' => 'applications/differential/controller/DifferentialRevisionOperationController.php', 'DifferentialRevisionPHIDType' => 'applications/differential/phid/DifferentialRevisionPHIDType.php', 'DifferentialRevisionPackageHeraldField' => 'applications/differential/herald/DifferentialRevisionPackageHeraldField.php', 'DifferentialRevisionPackageOwnerHeraldField' => 'applications/differential/herald/DifferentialRevisionPackageOwnerHeraldField.php', 'DifferentialRevisionQuery' => 'applications/differential/query/DifferentialRevisionQuery.php', 'DifferentialRevisionRelationship' => 'applications/differential/relationships/DifferentialRevisionRelationship.php', 'DifferentialRevisionRelationshipSource' => 'applications/search/relationship/DifferentialRevisionRelationshipSource.php', 'DifferentialRevisionRepositoryHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryHeraldField.php', 'DifferentialRevisionRepositoryProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryProjectsHeraldField.php', + 'DifferentialRevisionRepositoryTransaction' => 'applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php', 'DifferentialRevisionRequiredActionResultBucket' => 'applications/differential/query/DifferentialRevisionRequiredActionResultBucket.php', 'DifferentialRevisionResultBucket' => 'applications/differential/query/DifferentialRevisionResultBucket.php', 'DifferentialRevisionReviewersHeraldField' => 'applications/differential/herald/DifferentialRevisionReviewersHeraldField.php', + 'DifferentialRevisionReviewersTransaction' => 'applications/differential/xaction/DifferentialRevisionReviewersTransaction.php', 'DifferentialRevisionSearchConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionSearchConduitAPIMethod.php', 'DifferentialRevisionSearchEngine' => 'applications/differential/query/DifferentialRevisionSearchEngine.php', 'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php', 'DifferentialRevisionSummaryHeraldField' => 'applications/differential/herald/DifferentialRevisionSummaryHeraldField.php', + 'DifferentialRevisionSummaryTransaction' => 'applications/differential/xaction/DifferentialRevisionSummaryTransaction.php', + 'DifferentialRevisionTestPlanTransaction' => 'applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php', 'DifferentialRevisionTitleHeraldField' => 'applications/differential/herald/DifferentialRevisionTitleHeraldField.php', + 'DifferentialRevisionTitleTransaction' => 'applications/differential/xaction/DifferentialRevisionTitleTransaction.php', + 'DifferentialRevisionTransactionType' => 'applications/differential/xaction/DifferentialRevisionTransactionType.php', 'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/DifferentialRevisionUpdateHistoryView.php', 'DifferentialRevisionViewController' => 'applications/differential/controller/DifferentialRevisionViewController.php', 'DifferentialSchemaSpec' => 'applications/differential/storage/DifferentialSchemaSpec.php', 'DifferentialSetDiffPropertyConduitAPIMethod' => 'applications/differential/conduit/DifferentialSetDiffPropertyConduitAPIMethod.php', 'DifferentialStoredCustomField' => 'applications/differential/customfield/DifferentialStoredCustomField.php', - 'DifferentialSubscribersField' => 'applications/differential/customfield/DifferentialSubscribersField.php', + 'DifferentialSubscribersCommitMessageField' => 'applications/differential/field/DifferentialSubscribersCommitMessageField.php', + 'DifferentialSummaryCommitMessageField' => 'applications/differential/field/DifferentialSummaryCommitMessageField.php', 'DifferentialSummaryField' => 'applications/differential/customfield/DifferentialSummaryField.php', + 'DifferentialTagsCommitMessageField' => 'applications/differential/field/DifferentialTagsCommitMessageField.php', + 'DifferentialTasksCommitMessageField' => 'applications/differential/field/DifferentialTasksCommitMessageField.php', + 'DifferentialTestPlanCommitMessageField' => 'applications/differential/field/DifferentialTestPlanCommitMessageField.php', 'DifferentialTestPlanField' => 'applications/differential/customfield/DifferentialTestPlanField.php', - 'DifferentialTitleField' => 'applications/differential/customfield/DifferentialTitleField.php', + 'DifferentialTitleCommitMessageField' => 'applications/differential/field/DifferentialTitleCommitMessageField.php', 'DifferentialTransaction' => 'applications/differential/storage/DifferentialTransaction.php', 'DifferentialTransactionComment' => 'applications/differential/storage/DifferentialTransactionComment.php', 'DifferentialTransactionEditor' => 'applications/differential/editor/DifferentialTransactionEditor.php', 'DifferentialTransactionQuery' => 'applications/differential/query/DifferentialTransactionQuery.php', 'DifferentialTransactionView' => 'applications/differential/view/DifferentialTransactionView.php', 'DifferentialUnitField' => 'applications/differential/customfield/DifferentialUnitField.php', 'DifferentialUnitStatus' => 'applications/differential/constants/DifferentialUnitStatus.php', 'DifferentialUnitTestResult' => 'applications/differential/constants/DifferentialUnitTestResult.php', 'DifferentialUpdateRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateRevisionConduitAPIMethod.php', - 'DifferentialViewPolicyField' => 'applications/differential/customfield/DifferentialViewPolicyField.php', 'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php', 'DiffusionAuditorFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php', 'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php', 'DiffusionAuditorsAddSelfHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php', 'DiffusionAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsHeraldAction.php', 'DiffusionBlameConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBlameConduitAPIMethod.php', 'DiffusionBlameQuery' => 'applications/diffusion/query/blame/DiffusionBlameQuery.php', 'DiffusionBlockHeraldAction' => 'applications/diffusion/herald/DiffusionBlockHeraldAction.php', 'DiffusionBranchQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBranchQueryConduitAPIMethod.php', 'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php', 'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php', 'DiffusionBrowseController' => 'applications/diffusion/controller/DiffusionBrowseController.php', 'DiffusionBrowseQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php', 'DiffusionBrowseResultSet' => 'applications/diffusion/data/DiffusionBrowseResultSet.php', 'DiffusionBrowseTableView' => 'applications/diffusion/view/DiffusionBrowseTableView.php', 'DiffusionCacheEngineExtension' => 'applications/diffusion/engineextension/DiffusionCacheEngineExtension.php', 'DiffusionCachedResolveRefsQuery' => 'applications/diffusion/query/DiffusionCachedResolveRefsQuery.php', 'DiffusionChangeController' => 'applications/diffusion/controller/DiffusionChangeController.php', 'DiffusionChangeHeraldFieldGroup' => 'applications/diffusion/herald/DiffusionChangeHeraldFieldGroup.php', 'DiffusionCloneURIView' => 'applications/diffusion/view/DiffusionCloneURIView.php', 'DiffusionCommandEngine' => 'applications/diffusion/protocol/DiffusionCommandEngine.php', 'DiffusionCommandEngineTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionCommandEngineTestCase.php', 'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.php', 'DiffusionCommitAuthorHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuthorHeraldField.php', 'DiffusionCommitAutocloseHeraldField' => 'applications/diffusion/herald/DiffusionCommitAutocloseHeraldField.php', 'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php', 'DiffusionCommitBranchesHeraldField' => 'applications/diffusion/herald/DiffusionCommitBranchesHeraldField.php', 'DiffusionCommitCommitterHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterHeraldField.php', 'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php', 'DiffusionCommitDiffContentAddedHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentAddedHeraldField.php', 'DiffusionCommitDiffContentHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentHeraldField.php', 'DiffusionCommitDiffContentRemovedHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentRemovedHeraldField.php', 'DiffusionCommitDiffEnormousHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffEnormousHeraldField.php', 'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php', 'DiffusionCommitFulltextEngine' => 'applications/repository/search/DiffusionCommitFulltextEngine.php', 'DiffusionCommitHasRevisionEdgeType' => 'applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php', 'DiffusionCommitHasRevisionRelationship' => 'applications/diffusion/relationships/DiffusionCommitHasRevisionRelationship.php', 'DiffusionCommitHasTaskEdgeType' => 'applications/diffusion/edge/DiffusionCommitHasTaskEdgeType.php', 'DiffusionCommitHasTaskRelationship' => 'applications/diffusion/relationships/DiffusionCommitHasTaskRelationship.php', 'DiffusionCommitHash' => 'applications/diffusion/data/DiffusionCommitHash.php', 'DiffusionCommitHeraldField' => 'applications/diffusion/herald/DiffusionCommitHeraldField.php', 'DiffusionCommitHeraldFieldGroup' => 'applications/diffusion/herald/DiffusionCommitHeraldFieldGroup.php', 'DiffusionCommitHintQuery' => 'applications/diffusion/query/DiffusionCommitHintQuery.php', 'DiffusionCommitHookEngine' => 'applications/diffusion/engine/DiffusionCommitHookEngine.php', 'DiffusionCommitHookRejectException' => 'applications/diffusion/exception/DiffusionCommitHookRejectException.php', 'DiffusionCommitMergeHeraldField' => 'applications/diffusion/herald/DiffusionCommitMergeHeraldField.php', 'DiffusionCommitMessageHeraldField' => 'applications/diffusion/herald/DiffusionCommitMessageHeraldField.php', 'DiffusionCommitPackageAuditHeraldField' => 'applications/diffusion/herald/DiffusionCommitPackageAuditHeraldField.php', 'DiffusionCommitPackageHeraldField' => 'applications/diffusion/herald/DiffusionCommitPackageHeraldField.php', 'DiffusionCommitPackageOwnerHeraldField' => 'applications/diffusion/herald/DiffusionCommitPackageOwnerHeraldField.php', 'DiffusionCommitParentsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCommitParentsQueryConduitAPIMethod.php', 'DiffusionCommitQuery' => 'applications/diffusion/query/DiffusionCommitQuery.php', 'DiffusionCommitRef' => 'applications/diffusion/data/DiffusionCommitRef.php', 'DiffusionCommitRelationship' => 'applications/diffusion/relationships/DiffusionCommitRelationship.php', 'DiffusionCommitRelationshipSource' => 'applications/search/relationship/DiffusionCommitRelationshipSource.php', 'DiffusionCommitRemarkupRule' => 'applications/diffusion/remarkup/DiffusionCommitRemarkupRule.php', 'DiffusionCommitRemarkupRuleTestCase' => 'applications/diffusion/remarkup/__tests__/DiffusionCommitRemarkupRuleTestCase.php', 'DiffusionCommitRepositoryHeraldField' => 'applications/diffusion/herald/DiffusionCommitRepositoryHeraldField.php', 'DiffusionCommitRepositoryProjectsHeraldField' => 'applications/diffusion/herald/DiffusionCommitRepositoryProjectsHeraldField.php', 'DiffusionCommitRevertedByCommitEdgeType' => 'applications/diffusion/edge/DiffusionCommitRevertedByCommitEdgeType.php', 'DiffusionCommitRevertsCommitEdgeType' => 'applications/diffusion/edge/DiffusionCommitRevertsCommitEdgeType.php', 'DiffusionCommitReviewerHeraldField' => 'applications/diffusion/herald/DiffusionCommitReviewerHeraldField.php', 'DiffusionCommitRevisionAcceptedHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionAcceptedHeraldField.php', 'DiffusionCommitRevisionHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionHeraldField.php', 'DiffusionCommitRevisionReviewersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionReviewersHeraldField.php', 'DiffusionCommitRevisionSubscribersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionSubscribersHeraldField.php', 'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php', 'DiffusionCompareController' => 'applications/diffusion/controller/DiffusionCompareController.php', 'DiffusionConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionConduitAPIMethod.php', 'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php', 'DiffusionCreateCommentConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCreateCommentConduitAPIMethod.php', 'DiffusionCreateRepositoriesCapability' => 'applications/diffusion/capability/DiffusionCreateRepositoriesCapability.php', 'DiffusionDaemonLockException' => 'applications/diffusion/exception/DiffusionDaemonLockException.php', 'DiffusionDefaultEditCapability' => 'applications/diffusion/capability/DiffusionDefaultEditCapability.php', 'DiffusionDefaultPushCapability' => 'applications/diffusion/capability/DiffusionDefaultPushCapability.php', 'DiffusionDefaultViewCapability' => 'applications/diffusion/capability/DiffusionDefaultViewCapability.php', 'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php', 'DiffusionDiffInlineCommentQuery' => 'applications/diffusion/query/DiffusionDiffInlineCommentQuery.php', 'DiffusionDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionDiffQueryConduitAPIMethod.php', 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php', 'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php', 'DiffusionExistsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionExistsQueryConduitAPIMethod.php', 'DiffusionExternalController' => 'applications/diffusion/controller/DiffusionExternalController.php', 'DiffusionExternalSymbolQuery' => 'applications/diffusion/symbol/DiffusionExternalSymbolQuery.php', 'DiffusionExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionExternalSymbolsSource.php', 'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionFileContentQuery.php', 'DiffusionFileContentQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionFileContentQueryConduitAPIMethod.php', 'DiffusionFileFutureQuery' => 'applications/diffusion/query/DiffusionFileFutureQuery.php', 'DiffusionFindSymbolsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionFindSymbolsConduitAPIMethod.php', 'DiffusionGetLintMessagesConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionGetLintMessagesConduitAPIMethod.php', 'DiffusionGetRecentCommitsByPathConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionGetRecentCommitsByPathConduitAPIMethod.php', 'DiffusionGitBlameQuery' => 'applications/diffusion/query/blame/DiffusionGitBlameQuery.php', 'DiffusionGitBranch' => 'applications/diffusion/data/DiffusionGitBranch.php', 'DiffusionGitBranchTestCase' => 'applications/diffusion/data/__tests__/DiffusionGitBranchTestCase.php', 'DiffusionGitCommandEngine' => 'applications/diffusion/protocol/DiffusionGitCommandEngine.php', 'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php', 'DiffusionGitLFSAuthenticateWorkflow' => 'applications/diffusion/gitlfs/DiffusionGitLFSAuthenticateWorkflow.php', 'DiffusionGitLFSResponse' => 'applications/diffusion/response/DiffusionGitLFSResponse.php', 'DiffusionGitLFSTemporaryTokenType' => 'applications/diffusion/gitlfs/DiffusionGitLFSTemporaryTokenType.php', 'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php', 'DiffusionGitReceivePackSSHWorkflow' => 'applications/diffusion/ssh/DiffusionGitReceivePackSSHWorkflow.php', 'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php', 'DiffusionGitResponse' => 'applications/diffusion/response/DiffusionGitResponse.php', 'DiffusionGitSSHWorkflow' => 'applications/diffusion/ssh/DiffusionGitSSHWorkflow.php', 'DiffusionGitUploadPackSSHWorkflow' => 'applications/diffusion/ssh/DiffusionGitUploadPackSSHWorkflow.php', 'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php', 'DiffusionHistoryQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php', 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php', 'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', 'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', 'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalGitRawDiffQueryConduitAPIMethod.php', 'DiffusionLastModifiedController' => 'applications/diffusion/controller/DiffusionLastModifiedController.php', 'DiffusionLastModifiedQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionLastModifiedQueryConduitAPIMethod.php', 'DiffusionLintController' => 'applications/diffusion/controller/DiffusionLintController.php', 'DiffusionLintCountQuery' => 'applications/diffusion/query/DiffusionLintCountQuery.php', 'DiffusionLintSaveRunner' => 'applications/diffusion/DiffusionLintSaveRunner.php', 'DiffusionLocalRepositoryFilter' => 'applications/diffusion/data/DiffusionLocalRepositoryFilter.php', 'DiffusionLookSoonConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionLookSoonConduitAPIMethod.php', 'DiffusionLowLevelCommitFieldsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php', 'DiffusionLowLevelCommitQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitQuery.php', 'DiffusionLowLevelGitRefQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelGitRefQuery.php', 'DiffusionLowLevelMercurialBranchesQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialBranchesQuery.php', 'DiffusionLowLevelMercurialPathsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialPathsQuery.php', 'DiffusionLowLevelMercurialPathsQueryTests' => 'applications/diffusion/query/lowlevel/__tests__/DiffusionLowLevelMercurialPathsQueryTests.php', 'DiffusionLowLevelParentsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelParentsQuery.php', 'DiffusionLowLevelQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelQuery.php', 'DiffusionLowLevelResolveRefsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php', 'DiffusionMercurialBlameQuery' => 'applications/diffusion/query/blame/DiffusionMercurialBlameQuery.php', 'DiffusionMercurialCommandEngine' => 'applications/diffusion/protocol/DiffusionMercurialCommandEngine.php', 'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php', 'DiffusionMercurialRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionMercurialRawDiffQuery.php', 'DiffusionMercurialRequest' => 'applications/diffusion/request/DiffusionMercurialRequest.php', 'DiffusionMercurialResponse' => 'applications/diffusion/response/DiffusionMercurialResponse.php', 'DiffusionMercurialSSHWorkflow' => 'applications/diffusion/ssh/DiffusionMercurialSSHWorkflow.php', 'DiffusionMercurialServeSSHWorkflow' => 'applications/diffusion/ssh/DiffusionMercurialServeSSHWorkflow.php', 'DiffusionMercurialWireClientSSHProtocolChannel' => 'applications/diffusion/ssh/DiffusionMercurialWireClientSSHProtocolChannel.php', 'DiffusionMercurialWireProtocol' => 'applications/diffusion/protocol/DiffusionMercurialWireProtocol.php', 'DiffusionMercurialWireProtocolTests' => 'applications/diffusion/protocol/__tests__/DiffusionMercurialWireProtocolTests.php', 'DiffusionMercurialWireSSHTestCase' => 'applications/diffusion/ssh/__tests__/DiffusionMercurialWireSSHTestCase.php', 'DiffusionMergedCommitsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionMergedCommitsQueryConduitAPIMethod.php', 'DiffusionPathChange' => 'applications/diffusion/data/DiffusionPathChange.php', 'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/DiffusionPathChangeQuery.php', 'DiffusionPathCompleteController' => 'applications/diffusion/controller/DiffusionPathCompleteController.php', 'DiffusionPathIDQuery' => 'applications/diffusion/query/pathid/DiffusionPathIDQuery.php', 'DiffusionPathQuery' => 'applications/diffusion/query/DiffusionPathQuery.php', 'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/__tests__/DiffusionPathQueryTestCase.php', 'DiffusionPathTreeController' => 'applications/diffusion/controller/DiffusionPathTreeController.php', 'DiffusionPathValidateController' => 'applications/diffusion/controller/DiffusionPathValidateController.php', 'DiffusionPhpExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionPhpExternalSymbolsSource.php', 'DiffusionPreCommitContentAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAffectedFilesHeraldField.php', 'DiffusionPreCommitContentAuthorHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorHeraldField.php', 'DiffusionPreCommitContentAuthorRawHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorRawHeraldField.php', 'DiffusionPreCommitContentBranchesHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentBranchesHeraldField.php', 'DiffusionPreCommitContentCommitterHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentCommitterHeraldField.php', 'DiffusionPreCommitContentCommitterRawHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentCommitterRawHeraldField.php', 'DiffusionPreCommitContentDiffContentAddedHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentDiffContentAddedHeraldField.php', 'DiffusionPreCommitContentDiffContentHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentDiffContentHeraldField.php', 'DiffusionPreCommitContentDiffContentRemovedHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentDiffContentRemovedHeraldField.php', 'DiffusionPreCommitContentDiffEnormousHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentDiffEnormousHeraldField.php', 'DiffusionPreCommitContentHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentHeraldField.php', 'DiffusionPreCommitContentMergeHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentMergeHeraldField.php', 'DiffusionPreCommitContentMessageHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentMessageHeraldField.php', 'DiffusionPreCommitContentPusherHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPusherHeraldField.php', 'DiffusionPreCommitContentPusherIsCommitterHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPusherIsCommitterHeraldField.php', 'DiffusionPreCommitContentPusherProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPusherProjectsHeraldField.php', 'DiffusionPreCommitContentRepositoryHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRepositoryHeraldField.php', 'DiffusionPreCommitContentRepositoryProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRepositoryProjectsHeraldField.php', 'DiffusionPreCommitContentRevisionAcceptedHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRevisionAcceptedHeraldField.php', 'DiffusionPreCommitContentRevisionHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRevisionHeraldField.php', 'DiffusionPreCommitContentRevisionReviewersHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRevisionReviewersHeraldField.php', 'DiffusionPreCommitContentRevisionSubscribersHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRevisionSubscribersHeraldField.php', 'DiffusionPreCommitRefChangeHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefChangeHeraldField.php', 'DiffusionPreCommitRefHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefHeraldField.php', 'DiffusionPreCommitRefHeraldFieldGroup' => 'applications/diffusion/herald/DiffusionPreCommitRefHeraldFieldGroup.php', 'DiffusionPreCommitRefNameHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefNameHeraldField.php', 'DiffusionPreCommitRefPusherHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefPusherHeraldField.php', 'DiffusionPreCommitRefPusherProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefPusherProjectsHeraldField.php', 'DiffusionPreCommitRefRepositoryHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefRepositoryHeraldField.php', 'DiffusionPreCommitRefRepositoryProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefRepositoryProjectsHeraldField.php', 'DiffusionPreCommitRefTypeHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitRefTypeHeraldField.php', 'DiffusionPullEventGarbageCollector' => 'applications/diffusion/garbagecollector/DiffusionPullEventGarbageCollector.php', 'DiffusionPushCapability' => 'applications/diffusion/capability/DiffusionPushCapability.php', 'DiffusionPushEventViewController' => 'applications/diffusion/controller/DiffusionPushEventViewController.php', 'DiffusionPushLogController' => 'applications/diffusion/controller/DiffusionPushLogController.php', 'DiffusionPushLogListController' => 'applications/diffusion/controller/DiffusionPushLogListController.php', 'DiffusionPushLogListView' => 'applications/diffusion/view/DiffusionPushLogListView.php', 'DiffusionPythonExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionPythonExternalSymbolsSource.php', 'DiffusionQuery' => 'applications/diffusion/query/DiffusionQuery.php', 'DiffusionQueryCommitsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionQueryCommitsConduitAPIMethod.php', 'DiffusionQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionQueryConduitAPIMethod.php', 'DiffusionQueryPathsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionQueryPathsConduitAPIMethod.php', 'DiffusionRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionRawDiffQuery.php', 'DiffusionRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRawDiffQueryConduitAPIMethod.php', 'DiffusionReadmeView' => 'applications/diffusion/view/DiffusionReadmeView.php', 'DiffusionRefDatasource' => 'applications/diffusion/typeahead/DiffusionRefDatasource.php', 'DiffusionRefNotFoundException' => 'applications/diffusion/exception/DiffusionRefNotFoundException.php', 'DiffusionRefTableController' => 'applications/diffusion/controller/DiffusionRefTableController.php', 'DiffusionRefsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRefsQueryConduitAPIMethod.php', 'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php', 'DiffusionRepositoryActionsManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryActionsManagementPanel.php', 'DiffusionRepositoryAutomationManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryAutomationManagementPanel.php', 'DiffusionRepositoryBasicsManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryBasicsManagementPanel.php', 'DiffusionRepositoryBranchesManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryBranchesManagementPanel.php', 'DiffusionRepositoryByIDRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryByIDRemarkupRule.php', 'DiffusionRepositoryClusterEngine' => 'applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php', 'DiffusionRepositoryClusterEngineLogInterface' => 'applications/diffusion/protocol/DiffusionRepositoryClusterEngineLogInterface.php', 'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php', 'DiffusionRepositoryDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryDatasource.php', 'DiffusionRepositoryDefaultController' => 'applications/diffusion/controller/DiffusionRepositoryDefaultController.php', 'DiffusionRepositoryDocumentationManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryDocumentationManagementPanel.php', 'DiffusionRepositoryEditActivateController' => 'applications/diffusion/controller/DiffusionRepositoryEditActivateController.php', 'DiffusionRepositoryEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositoryEditConduitAPIMethod.php', 'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php', 'DiffusionRepositoryEditDangerousController' => 'applications/diffusion/controller/DiffusionRepositoryEditDangerousController.php', 'DiffusionRepositoryEditDeleteController' => 'applications/diffusion/controller/DiffusionRepositoryEditDeleteController.php', 'DiffusionRepositoryEditEngine' => 'applications/diffusion/editor/DiffusionRepositoryEditEngine.php', 'DiffusionRepositoryEditUpdateController' => 'applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php', 'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php', 'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php', 'DiffusionRepositoryManageController' => 'applications/diffusion/controller/DiffusionRepositoryManageController.php', 'DiffusionRepositoryManagePanelsController' => 'applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php', 'DiffusionRepositoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryManagementPanel.php', 'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php', 'DiffusionRepositoryPoliciesManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php', 'DiffusionRepositoryRef' => 'applications/diffusion/data/DiffusionRepositoryRef.php', 'DiffusionRepositoryRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRepositoryRemarkupRule.php', 'DiffusionRepositorySearchConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionRepositorySearchConduitAPIMethod.php', 'DiffusionRepositoryStagingManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStagingManagementPanel.php', 'DiffusionRepositoryStatusManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStatusManagementPanel.php', 'DiffusionRepositoryStorageManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryStorageManagementPanel.php', 'DiffusionRepositorySubversionManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySubversionManagementPanel.php', 'DiffusionRepositorySymbolsManagementPanel' => 'applications/diffusion/management/DiffusionRepositorySymbolsManagementPanel.php', 'DiffusionRepositoryTag' => 'applications/diffusion/data/DiffusionRepositoryTag.php', 'DiffusionRepositoryTestAutomationController' => 'applications/diffusion/controller/DiffusionRepositoryTestAutomationController.php', 'DiffusionRepositoryURICredentialController' => 'applications/diffusion/controller/DiffusionRepositoryURICredentialController.php', 'DiffusionRepositoryURIDisableController' => 'applications/diffusion/controller/DiffusionRepositoryURIDisableController.php', 'DiffusionRepositoryURIEditController' => 'applications/diffusion/controller/DiffusionRepositoryURIEditController.php', 'DiffusionRepositoryURIViewController' => 'applications/diffusion/controller/DiffusionRepositoryURIViewController.php', 'DiffusionRepositoryURIsIndexEngineExtension' => 'applications/diffusion/engineextension/DiffusionRepositoryURIsIndexEngineExtension.php', 'DiffusionRepositoryURIsManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryURIsManagementPanel.php', 'DiffusionRepositoryURIsSearchEngineAttachment' => 'applications/diffusion/engineextension/DiffusionRepositoryURIsSearchEngineAttachment.php', 'DiffusionRequest' => 'applications/diffusion/request/DiffusionRequest.php', 'DiffusionResolveRefsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionResolveRefsConduitAPIMethod.php', 'DiffusionResolveUserQuery' => 'applications/diffusion/query/DiffusionResolveUserQuery.php', 'DiffusionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSSHWorkflow.php', 'DiffusionSearchQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionSearchQueryConduitAPIMethod.php', 'DiffusionServeController' => 'applications/diffusion/controller/DiffusionServeController.php', 'DiffusionSetPasswordSettingsPanel' => 'applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php', 'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php', 'DiffusionSubversionCommandEngine' => 'applications/diffusion/protocol/DiffusionSubversionCommandEngine.php', 'DiffusionSubversionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSubversionSSHWorkflow.php', 'DiffusionSubversionServeSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSubversionServeSSHWorkflow.php', 'DiffusionSubversionWireProtocol' => 'applications/diffusion/protocol/DiffusionSubversionWireProtocol.php', 'DiffusionSubversionWireProtocolTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionSubversionWireProtocolTestCase.php', 'DiffusionSvnBlameQuery' => 'applications/diffusion/query/blame/DiffusionSvnBlameQuery.php', 'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php', 'DiffusionSvnRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionSvnRawDiffQuery.php', 'DiffusionSvnRequest' => 'applications/diffusion/request/DiffusionSvnRequest.php', 'DiffusionSymbolController' => 'applications/diffusion/controller/DiffusionSymbolController.php', 'DiffusionSymbolDatasource' => 'applications/diffusion/typeahead/DiffusionSymbolDatasource.php', 'DiffusionSymbolQuery' => 'applications/diffusion/query/DiffusionSymbolQuery.php', 'DiffusionTagListController' => 'applications/diffusion/controller/DiffusionTagListController.php', 'DiffusionTagListView' => 'applications/diffusion/view/DiffusionTagListView.php', 'DiffusionTaggedRepositoriesFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionTaggedRepositoriesFunctionDatasource.php', 'DiffusionTagsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionTagsQueryConduitAPIMethod.php', 'DiffusionURIEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionURIEditConduitAPIMethod.php', 'DiffusionURIEditEngine' => 'applications/diffusion/editor/DiffusionURIEditEngine.php', 'DiffusionURIEditor' => 'applications/diffusion/editor/DiffusionURIEditor.php', 'DiffusionURITestCase' => 'applications/diffusion/request/__tests__/DiffusionURITestCase.php', 'DiffusionUpdateCoverageConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionUpdateCoverageConduitAPIMethod.php', 'DiffusionView' => 'applications/diffusion/view/DiffusionView.php', 'DivinerArticleAtomizer' => 'applications/diviner/atomizer/DivinerArticleAtomizer.php', 'DivinerAtom' => 'applications/diviner/atom/DivinerAtom.php', 'DivinerAtomCache' => 'applications/diviner/cache/DivinerAtomCache.php', 'DivinerAtomController' => 'applications/diviner/controller/DivinerAtomController.php', 'DivinerAtomListController' => 'applications/diviner/controller/DivinerAtomListController.php', 'DivinerAtomPHIDType' => 'applications/diviner/phid/DivinerAtomPHIDType.php', 'DivinerAtomQuery' => 'applications/diviner/query/DivinerAtomQuery.php', 'DivinerAtomRef' => 'applications/diviner/atom/DivinerAtomRef.php', 'DivinerAtomSearchEngine' => 'applications/diviner/query/DivinerAtomSearchEngine.php', 'DivinerAtomizeWorkflow' => 'applications/diviner/workflow/DivinerAtomizeWorkflow.php', 'DivinerAtomizer' => 'applications/diviner/atomizer/DivinerAtomizer.php', 'DivinerBookController' => 'applications/diviner/controller/DivinerBookController.php', 'DivinerBookDatasource' => 'applications/diviner/typeahead/DivinerBookDatasource.php', 'DivinerBookEditController' => 'applications/diviner/controller/DivinerBookEditController.php', 'DivinerBookItemView' => 'applications/diviner/view/DivinerBookItemView.php', 'DivinerBookPHIDType' => 'applications/diviner/phid/DivinerBookPHIDType.php', 'DivinerBookQuery' => 'applications/diviner/query/DivinerBookQuery.php', 'DivinerController' => 'applications/diviner/controller/DivinerController.php', 'DivinerDAO' => 'applications/diviner/storage/DivinerDAO.php', 'DivinerDefaultEditCapability' => 'applications/diviner/capability/DivinerDefaultEditCapability.php', 'DivinerDefaultRenderer' => 'applications/diviner/renderer/DivinerDefaultRenderer.php', 'DivinerDefaultViewCapability' => 'applications/diviner/capability/DivinerDefaultViewCapability.php', 'DivinerDiskCache' => 'applications/diviner/cache/DivinerDiskCache.php', 'DivinerFileAtomizer' => 'applications/diviner/atomizer/DivinerFileAtomizer.php', 'DivinerFindController' => 'applications/diviner/controller/DivinerFindController.php', 'DivinerGenerateWorkflow' => 'applications/diviner/workflow/DivinerGenerateWorkflow.php', 'DivinerLiveAtom' => 'applications/diviner/storage/DivinerLiveAtom.php', 'DivinerLiveBook' => 'applications/diviner/storage/DivinerLiveBook.php', 'DivinerLiveBookEditor' => 'applications/diviner/editor/DivinerLiveBookEditor.php', 'DivinerLiveBookFulltextEngine' => 'applications/diviner/search/DivinerLiveBookFulltextEngine.php', 'DivinerLiveBookTransaction' => 'applications/diviner/storage/DivinerLiveBookTransaction.php', 'DivinerLiveBookTransactionQuery' => 'applications/diviner/query/DivinerLiveBookTransactionQuery.php', 'DivinerLivePublisher' => 'applications/diviner/publisher/DivinerLivePublisher.php', 'DivinerLiveSymbol' => 'applications/diviner/storage/DivinerLiveSymbol.php', 'DivinerLiveSymbolFulltextEngine' => 'applications/diviner/search/DivinerLiveSymbolFulltextEngine.php', 'DivinerMainController' => 'applications/diviner/controller/DivinerMainController.php', 'DivinerPHPAtomizer' => 'applications/diviner/atomizer/DivinerPHPAtomizer.php', 'DivinerParameterTableView' => 'applications/diviner/view/DivinerParameterTableView.php', 'DivinerPublishCache' => 'applications/diviner/cache/DivinerPublishCache.php', 'DivinerPublisher' => 'applications/diviner/publisher/DivinerPublisher.php', 'DivinerRenderer' => 'applications/diviner/renderer/DivinerRenderer.php', 'DivinerReturnTableView' => 'applications/diviner/view/DivinerReturnTableView.php', 'DivinerSchemaSpec' => 'applications/diviner/storage/DivinerSchemaSpec.php', 'DivinerSectionView' => 'applications/diviner/view/DivinerSectionView.php', 'DivinerStaticPublisher' => 'applications/diviner/publisher/DivinerStaticPublisher.php', 'DivinerSymbolRemarkupRule' => 'applications/diviner/markup/DivinerSymbolRemarkupRule.php', 'DivinerWorkflow' => 'applications/diviner/workflow/DivinerWorkflow.php', 'DoorkeeperAsanaFeedWorker' => 'applications/doorkeeper/worker/DoorkeeperAsanaFeedWorker.php', 'DoorkeeperAsanaRemarkupRule' => 'applications/doorkeeper/remarkup/DoorkeeperAsanaRemarkupRule.php', 'DoorkeeperBridge' => 'applications/doorkeeper/bridge/DoorkeeperBridge.php', 'DoorkeeperBridgeAsana' => 'applications/doorkeeper/bridge/DoorkeeperBridgeAsana.php', 'DoorkeeperBridgeGitHub' => 'applications/doorkeeper/bridge/DoorkeeperBridgeGitHub.php', 'DoorkeeperBridgeGitHubIssue' => 'applications/doorkeeper/bridge/DoorkeeperBridgeGitHubIssue.php', 'DoorkeeperBridgeGitHubUser' => 'applications/doorkeeper/bridge/DoorkeeperBridgeGitHubUser.php', 'DoorkeeperBridgeJIRA' => 'applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php', 'DoorkeeperBridgeJIRATestCase' => 'applications/doorkeeper/bridge/__tests__/DoorkeeperBridgeJIRATestCase.php', 'DoorkeeperBridgedObjectCurtainExtension' => 'applications/doorkeeper/engineextension/DoorkeeperBridgedObjectCurtainExtension.php', 'DoorkeeperBridgedObjectInterface' => 'applications/doorkeeper/bridge/DoorkeeperBridgedObjectInterface.php', 'DoorkeeperDAO' => 'applications/doorkeeper/storage/DoorkeeperDAO.php', 'DoorkeeperExternalObject' => 'applications/doorkeeper/storage/DoorkeeperExternalObject.php', 'DoorkeeperExternalObjectPHIDType' => 'applications/doorkeeper/phid/DoorkeeperExternalObjectPHIDType.php', 'DoorkeeperExternalObjectQuery' => 'applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php', 'DoorkeeperFeedStoryPublisher' => 'applications/doorkeeper/engine/DoorkeeperFeedStoryPublisher.php', 'DoorkeeperFeedWorker' => 'applications/doorkeeper/worker/DoorkeeperFeedWorker.php', 'DoorkeeperImportEngine' => 'applications/doorkeeper/engine/DoorkeeperImportEngine.php', 'DoorkeeperJIRAFeedWorker' => 'applications/doorkeeper/worker/DoorkeeperJIRAFeedWorker.php', 'DoorkeeperJIRARemarkupRule' => 'applications/doorkeeper/remarkup/DoorkeeperJIRARemarkupRule.php', 'DoorkeeperMissingLinkException' => 'applications/doorkeeper/exception/DoorkeeperMissingLinkException.php', 'DoorkeeperObjectRef' => 'applications/doorkeeper/engine/DoorkeeperObjectRef.php', 'DoorkeeperRemarkupRule' => 'applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php', 'DoorkeeperSchemaSpec' => 'applications/doorkeeper/storage/DoorkeeperSchemaSpec.php', 'DoorkeeperTagView' => 'applications/doorkeeper/view/DoorkeeperTagView.php', 'DoorkeeperTagsController' => 'applications/doorkeeper/controller/DoorkeeperTagsController.php', 'DrydockAlmanacServiceHostBlueprintImplementation' => 'applications/drydock/blueprint/DrydockAlmanacServiceHostBlueprintImplementation.php', 'DrydockApacheWebrootInterface' => 'applications/drydock/interface/webroot/DrydockApacheWebrootInterface.php', 'DrydockAuthorization' => 'applications/drydock/storage/DrydockAuthorization.php', 'DrydockAuthorizationAuthorizeController' => 'applications/drydock/controller/DrydockAuthorizationAuthorizeController.php', 'DrydockAuthorizationListController' => 'applications/drydock/controller/DrydockAuthorizationListController.php', 'DrydockAuthorizationListView' => 'applications/drydock/view/DrydockAuthorizationListView.php', 'DrydockAuthorizationPHIDType' => 'applications/drydock/phid/DrydockAuthorizationPHIDType.php', 'DrydockAuthorizationQuery' => 'applications/drydock/query/DrydockAuthorizationQuery.php', 'DrydockAuthorizationSearchConduitAPIMethod' => 'applications/drydock/conduit/DrydockAuthorizationSearchConduitAPIMethod.php', 'DrydockAuthorizationSearchEngine' => 'applications/drydock/query/DrydockAuthorizationSearchEngine.php', 'DrydockAuthorizationViewController' => 'applications/drydock/controller/DrydockAuthorizationViewController.php', 'DrydockBlueprint' => 'applications/drydock/storage/DrydockBlueprint.php', 'DrydockBlueprintController' => 'applications/drydock/controller/DrydockBlueprintController.php', 'DrydockBlueprintCoreCustomField' => 'applications/drydock/customfield/DrydockBlueprintCoreCustomField.php', 'DrydockBlueprintCustomField' => 'applications/drydock/customfield/DrydockBlueprintCustomField.php', 'DrydockBlueprintDatasource' => 'applications/drydock/typeahead/DrydockBlueprintDatasource.php', 'DrydockBlueprintDisableController' => 'applications/drydock/controller/DrydockBlueprintDisableController.php', 'DrydockBlueprintEditController' => 'applications/drydock/controller/DrydockBlueprintEditController.php', 'DrydockBlueprintEditEngine' => 'applications/drydock/editor/DrydockBlueprintEditEngine.php', 'DrydockBlueprintEditor' => 'applications/drydock/editor/DrydockBlueprintEditor.php', 'DrydockBlueprintImplementation' => 'applications/drydock/blueprint/DrydockBlueprintImplementation.php', 'DrydockBlueprintImplementationTestCase' => 'applications/drydock/blueprint/__tests__/DrydockBlueprintImplementationTestCase.php', 'DrydockBlueprintListController' => 'applications/drydock/controller/DrydockBlueprintListController.php', 'DrydockBlueprintNameNgrams' => 'applications/drydock/storage/DrydockBlueprintNameNgrams.php', 'DrydockBlueprintPHIDType' => 'applications/drydock/phid/DrydockBlueprintPHIDType.php', 'DrydockBlueprintQuery' => 'applications/drydock/query/DrydockBlueprintQuery.php', 'DrydockBlueprintSearchConduitAPIMethod' => 'applications/drydock/conduit/DrydockBlueprintSearchConduitAPIMethod.php', 'DrydockBlueprintSearchEngine' => 'applications/drydock/query/DrydockBlueprintSearchEngine.php', 'DrydockBlueprintTransaction' => 'applications/drydock/storage/DrydockBlueprintTransaction.php', 'DrydockBlueprintTransactionQuery' => 'applications/drydock/query/DrydockBlueprintTransactionQuery.php', 'DrydockBlueprintViewController' => 'applications/drydock/controller/DrydockBlueprintViewController.php', 'DrydockCommand' => 'applications/drydock/storage/DrydockCommand.php', 'DrydockCommandError' => 'applications/drydock/exception/DrydockCommandError.php', 'DrydockCommandInterface' => 'applications/drydock/interface/command/DrydockCommandInterface.php', 'DrydockCommandQuery' => 'applications/drydock/query/DrydockCommandQuery.php', 'DrydockConsoleController' => 'applications/drydock/controller/DrydockConsoleController.php', 'DrydockConstants' => 'applications/drydock/constants/DrydockConstants.php', 'DrydockController' => 'applications/drydock/controller/DrydockController.php', 'DrydockCreateBlueprintsCapability' => 'applications/drydock/capability/DrydockCreateBlueprintsCapability.php', 'DrydockDAO' => 'applications/drydock/storage/DrydockDAO.php', 'DrydockDefaultEditCapability' => 'applications/drydock/capability/DrydockDefaultEditCapability.php', 'DrydockDefaultViewCapability' => 'applications/drydock/capability/DrydockDefaultViewCapability.php', 'DrydockFilesystemInterface' => 'applications/drydock/interface/filesystem/DrydockFilesystemInterface.php', 'DrydockInterface' => 'applications/drydock/interface/DrydockInterface.php', 'DrydockLandRepositoryOperation' => 'applications/drydock/operation/DrydockLandRepositoryOperation.php', 'DrydockLease' => 'applications/drydock/storage/DrydockLease.php', 'DrydockLeaseAcquiredLogType' => 'applications/drydock/logtype/DrydockLeaseAcquiredLogType.php', 'DrydockLeaseActivatedLogType' => 'applications/drydock/logtype/DrydockLeaseActivatedLogType.php', 'DrydockLeaseActivationFailureLogType' => 'applications/drydock/logtype/DrydockLeaseActivationFailureLogType.php', 'DrydockLeaseActivationYieldLogType' => 'applications/drydock/logtype/DrydockLeaseActivationYieldLogType.php', 'DrydockLeaseController' => 'applications/drydock/controller/DrydockLeaseController.php', 'DrydockLeaseDatasource' => 'applications/drydock/typeahead/DrydockLeaseDatasource.php', 'DrydockLeaseDestroyedLogType' => 'applications/drydock/logtype/DrydockLeaseDestroyedLogType.php', 'DrydockLeaseListController' => 'applications/drydock/controller/DrydockLeaseListController.php', 'DrydockLeaseListView' => 'applications/drydock/view/DrydockLeaseListView.php', 'DrydockLeaseNoAuthorizationsLogType' => 'applications/drydock/logtype/DrydockLeaseNoAuthorizationsLogType.php', 'DrydockLeaseNoBlueprintsLogType' => 'applications/drydock/logtype/DrydockLeaseNoBlueprintsLogType.php', 'DrydockLeasePHIDType' => 'applications/drydock/phid/DrydockLeasePHIDType.php', 'DrydockLeaseQuery' => 'applications/drydock/query/DrydockLeaseQuery.php', 'DrydockLeaseQueuedLogType' => 'applications/drydock/logtype/DrydockLeaseQueuedLogType.php', 'DrydockLeaseReclaimLogType' => 'applications/drydock/logtype/DrydockLeaseReclaimLogType.php', 'DrydockLeaseReleaseController' => 'applications/drydock/controller/DrydockLeaseReleaseController.php', 'DrydockLeaseReleasedLogType' => 'applications/drydock/logtype/DrydockLeaseReleasedLogType.php', 'DrydockLeaseSearchEngine' => 'applications/drydock/query/DrydockLeaseSearchEngine.php', 'DrydockLeaseStatus' => 'applications/drydock/constants/DrydockLeaseStatus.php', 'DrydockLeaseUpdateWorker' => 'applications/drydock/worker/DrydockLeaseUpdateWorker.php', 'DrydockLeaseViewController' => 'applications/drydock/controller/DrydockLeaseViewController.php', 'DrydockLeaseWaitingForResourcesLogType' => 'applications/drydock/logtype/DrydockLeaseWaitingForResourcesLogType.php', 'DrydockLog' => 'applications/drydock/storage/DrydockLog.php', 'DrydockLogController' => 'applications/drydock/controller/DrydockLogController.php', 'DrydockLogGarbageCollector' => 'applications/drydock/garbagecollector/DrydockLogGarbageCollector.php', 'DrydockLogListController' => 'applications/drydock/controller/DrydockLogListController.php', 'DrydockLogListView' => 'applications/drydock/view/DrydockLogListView.php', 'DrydockLogQuery' => 'applications/drydock/query/DrydockLogQuery.php', 'DrydockLogSearchEngine' => 'applications/drydock/query/DrydockLogSearchEngine.php', 'DrydockLogType' => 'applications/drydock/logtype/DrydockLogType.php', 'DrydockManagementCommandWorkflow' => 'applications/drydock/management/DrydockManagementCommandWorkflow.php', 'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php', 'DrydockManagementReclaimWorkflow' => 'applications/drydock/management/DrydockManagementReclaimWorkflow.php', 'DrydockManagementReleaseLeaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseLeaseWorkflow.php', 'DrydockManagementReleaseResourceWorkflow' => 'applications/drydock/management/DrydockManagementReleaseResourceWorkflow.php', 'DrydockManagementUpdateLeaseWorkflow' => 'applications/drydock/management/DrydockManagementUpdateLeaseWorkflow.php', 'DrydockManagementUpdateResourceWorkflow' => 'applications/drydock/management/DrydockManagementUpdateResourceWorkflow.php', 'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php', 'DrydockObjectAuthorizationView' => 'applications/drydock/view/DrydockObjectAuthorizationView.php', 'DrydockQuery' => 'applications/drydock/query/DrydockQuery.php', 'DrydockRepositoryOperation' => 'applications/drydock/storage/DrydockRepositoryOperation.php', 'DrydockRepositoryOperationController' => 'applications/drydock/controller/DrydockRepositoryOperationController.php', 'DrydockRepositoryOperationDismissController' => 'applications/drydock/controller/DrydockRepositoryOperationDismissController.php', 'DrydockRepositoryOperationListController' => 'applications/drydock/controller/DrydockRepositoryOperationListController.php', 'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php', 'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.php', 'DrydockRepositoryOperationSearchEngine' => 'applications/drydock/query/DrydockRepositoryOperationSearchEngine.php', 'DrydockRepositoryOperationStatusController' => 'applications/drydock/controller/DrydockRepositoryOperationStatusController.php', 'DrydockRepositoryOperationStatusView' => 'applications/drydock/view/DrydockRepositoryOperationStatusView.php', 'DrydockRepositoryOperationType' => 'applications/drydock/operation/DrydockRepositoryOperationType.php', 'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php', 'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php', 'DrydockResource' => 'applications/drydock/storage/DrydockResource.php', 'DrydockResourceActivationFailureLogType' => 'applications/drydock/logtype/DrydockResourceActivationFailureLogType.php', 'DrydockResourceActivationYieldLogType' => 'applications/drydock/logtype/DrydockResourceActivationYieldLogType.php', 'DrydockResourceController' => 'applications/drydock/controller/DrydockResourceController.php', 'DrydockResourceDatasource' => 'applications/drydock/typeahead/DrydockResourceDatasource.php', 'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php', 'DrydockResourceListView' => 'applications/drydock/view/DrydockResourceListView.php', 'DrydockResourcePHIDType' => 'applications/drydock/phid/DrydockResourcePHIDType.php', 'DrydockResourceQuery' => 'applications/drydock/query/DrydockResourceQuery.php', 'DrydockResourceReclaimLogType' => 'applications/drydock/logtype/DrydockResourceReclaimLogType.php', 'DrydockResourceReleaseController' => 'applications/drydock/controller/DrydockResourceReleaseController.php', 'DrydockResourceSearchEngine' => 'applications/drydock/query/DrydockResourceSearchEngine.php', 'DrydockResourceStatus' => 'applications/drydock/constants/DrydockResourceStatus.php', 'DrydockResourceUpdateWorker' => 'applications/drydock/worker/DrydockResourceUpdateWorker.php', 'DrydockResourceViewController' => 'applications/drydock/controller/DrydockResourceViewController.php', 'DrydockSFTPFilesystemInterface' => 'applications/drydock/interface/filesystem/DrydockSFTPFilesystemInterface.php', 'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/DrydockSSHCommandInterface.php', 'DrydockSchemaSpec' => 'applications/drydock/storage/DrydockSchemaSpec.php', 'DrydockSlotLock' => 'applications/drydock/storage/DrydockSlotLock.php', 'DrydockSlotLockException' => 'applications/drydock/exception/DrydockSlotLockException.php', 'DrydockSlotLockFailureLogType' => 'applications/drydock/logtype/DrydockSlotLockFailureLogType.php', 'DrydockTestRepositoryOperation' => 'applications/drydock/operation/DrydockTestRepositoryOperation.php', 'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php', 'DrydockWorker' => 'applications/drydock/worker/DrydockWorker.php', 'DrydockWorkingCopyBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php', 'FeedConduitAPIMethod' => 'applications/feed/conduit/FeedConduitAPIMethod.php', 'FeedPublishConduitAPIMethod' => 'applications/feed/conduit/FeedPublishConduitAPIMethod.php', 'FeedPublisherHTTPWorker' => 'applications/feed/worker/FeedPublisherHTTPWorker.php', 'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php', 'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php', 'FeedQueryConduitAPIMethod' => 'applications/feed/conduit/FeedQueryConduitAPIMethod.php', 'FeedStoryNotificationGarbageCollector' => 'applications/notification/garbagecollector/FeedStoryNotificationGarbageCollector.php', 'FileAllocateConduitAPIMethod' => 'applications/files/conduit/FileAllocateConduitAPIMethod.php', 'FileConduitAPIMethod' => 'applications/files/conduit/FileConduitAPIMethod.php', 'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php', 'FileDownloadConduitAPIMethod' => 'applications/files/conduit/FileDownloadConduitAPIMethod.php', 'FileInfoConduitAPIMethod' => 'applications/files/conduit/FileInfoConduitAPIMethod.php', 'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php', 'FileQueryChunksConduitAPIMethod' => 'applications/files/conduit/FileQueryChunksConduitAPIMethod.php', 'FileReplyHandler' => 'applications/files/mail/FileReplyHandler.php', 'FileTypeIcon' => 'applications/files/constants/FileTypeIcon.php', 'FileUploadChunkConduitAPIMethod' => 'applications/files/conduit/FileUploadChunkConduitAPIMethod.php', 'FileUploadConduitAPIMethod' => 'applications/files/conduit/FileUploadConduitAPIMethod.php', 'FileUploadHashConduitAPIMethod' => 'applications/files/conduit/FileUploadHashConduitAPIMethod.php', 'FilesDefaultViewCapability' => 'applications/files/capability/FilesDefaultViewCapability.php', 'FlagConduitAPIMethod' => 'applications/flag/conduit/FlagConduitAPIMethod.php', 'FlagDeleteConduitAPIMethod' => 'applications/flag/conduit/FlagDeleteConduitAPIMethod.php', 'FlagEditConduitAPIMethod' => 'applications/flag/conduit/FlagEditConduitAPIMethod.php', 'FlagQueryConduitAPIMethod' => 'applications/flag/conduit/FlagQueryConduitAPIMethod.php', 'FundBacker' => 'applications/fund/storage/FundBacker.php', 'FundBackerCart' => 'applications/fund/phortune/FundBackerCart.php', 'FundBackerEditor' => 'applications/fund/editor/FundBackerEditor.php', 'FundBackerListController' => 'applications/fund/controller/FundBackerListController.php', 'FundBackerPHIDType' => 'applications/fund/phid/FundBackerPHIDType.php', 'FundBackerProduct' => 'applications/fund/phortune/FundBackerProduct.php', 'FundBackerQuery' => 'applications/fund/query/FundBackerQuery.php', 'FundBackerSearchEngine' => 'applications/fund/query/FundBackerSearchEngine.php', 'FundBackerTransaction' => 'applications/fund/storage/FundBackerTransaction.php', 'FundBackerTransactionQuery' => 'applications/fund/query/FundBackerTransactionQuery.php', 'FundController' => 'applications/fund/controller/FundController.php', 'FundCreateInitiativesCapability' => 'applications/fund/capability/FundCreateInitiativesCapability.php', 'FundDAO' => 'applications/fund/storage/FundDAO.php', 'FundDefaultViewCapability' => 'applications/fund/capability/FundDefaultViewCapability.php', 'FundInitiative' => 'applications/fund/storage/FundInitiative.php', 'FundInitiativeBackController' => 'applications/fund/controller/FundInitiativeBackController.php', 'FundInitiativeCloseController' => 'applications/fund/controller/FundInitiativeCloseController.php', 'FundInitiativeCommentController' => 'applications/fund/controller/FundInitiativeCommentController.php', 'FundInitiativeEditController' => 'applications/fund/controller/FundInitiativeEditController.php', 'FundInitiativeEditor' => 'applications/fund/editor/FundInitiativeEditor.php', 'FundInitiativeFulltextEngine' => 'applications/fund/search/FundInitiativeFulltextEngine.php', 'FundInitiativeListController' => 'applications/fund/controller/FundInitiativeListController.php', 'FundInitiativePHIDType' => 'applications/fund/phid/FundInitiativePHIDType.php', 'FundInitiativeQuery' => 'applications/fund/query/FundInitiativeQuery.php', 'FundInitiativeRemarkupRule' => 'applications/fund/remarkup/FundInitiativeRemarkupRule.php', 'FundInitiativeReplyHandler' => 'applications/fund/mail/FundInitiativeReplyHandler.php', 'FundInitiativeSearchEngine' => 'applications/fund/query/FundInitiativeSearchEngine.php', 'FundInitiativeTransaction' => 'applications/fund/storage/FundInitiativeTransaction.php', 'FundInitiativeTransactionComment' => 'applications/fund/storage/FundInitiativeTransactionComment.php', 'FundInitiativeTransactionQuery' => 'applications/fund/query/FundInitiativeTransactionQuery.php', 'FundInitiativeViewController' => 'applications/fund/controller/FundInitiativeViewController.php', 'FundSchemaSpec' => 'applications/fund/storage/FundSchemaSpec.php', 'HarbormasterArcLintBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterArcLintBuildStepImplementation.php', 'HarbormasterArcUnitBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterArcUnitBuildStepImplementation.php', 'HarbormasterArtifact' => 'applications/harbormaster/artifact/HarbormasterArtifact.php', 'HarbormasterAutotargetsTestCase' => 'applications/harbormaster/__tests__/HarbormasterAutotargetsTestCase.php', 'HarbormasterBuild' => 'applications/harbormaster/storage/build/HarbormasterBuild.php', 'HarbormasterBuildAbortedException' => 'applications/harbormaster/exception/HarbormasterBuildAbortedException.php', 'HarbormasterBuildActionController' => 'applications/harbormaster/controller/HarbormasterBuildActionController.php', 'HarbormasterBuildArcanistAutoplan' => 'applications/harbormaster/autoplan/HarbormasterBuildArcanistAutoplan.php', 'HarbormasterBuildArtifact' => 'applications/harbormaster/storage/build/HarbormasterBuildArtifact.php', 'HarbormasterBuildArtifactPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildArtifactPHIDType.php', 'HarbormasterBuildArtifactQuery' => 'applications/harbormaster/query/HarbormasterBuildArtifactQuery.php', 'HarbormasterBuildAutoplan' => 'applications/harbormaster/autoplan/HarbormasterBuildAutoplan.php', 'HarbormasterBuildCommand' => 'applications/harbormaster/storage/HarbormasterBuildCommand.php', 'HarbormasterBuildDependencyDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildDependencyDatasource.php', 'HarbormasterBuildEngine' => 'applications/harbormaster/engine/HarbormasterBuildEngine.php', 'HarbormasterBuildFailureException' => 'applications/harbormaster/exception/HarbormasterBuildFailureException.php', 'HarbormasterBuildGraph' => 'applications/harbormaster/engine/HarbormasterBuildGraph.php', 'HarbormasterBuildInitiatorDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildInitiatorDatasource.php', 'HarbormasterBuildLintMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildLintMessage.php', 'HarbormasterBuildListController' => 'applications/harbormaster/controller/HarbormasterBuildListController.php', 'HarbormasterBuildLog' => 'applications/harbormaster/storage/build/HarbormasterBuildLog.php', 'HarbormasterBuildLogChunk' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunk.php', 'HarbormasterBuildLogChunkIterator' => 'applications/harbormaster/storage/build/HarbormasterBuildLogChunkIterator.php', 'HarbormasterBuildLogPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php', 'HarbormasterBuildLogQuery' => 'applications/harbormaster/query/HarbormasterBuildLogQuery.php', 'HarbormasterBuildMessage' => 'applications/harbormaster/storage/HarbormasterBuildMessage.php', 'HarbormasterBuildMessageQuery' => 'applications/harbormaster/query/HarbormasterBuildMessageQuery.php', 'HarbormasterBuildPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildPHIDType.php', 'HarbormasterBuildPlan' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php', 'HarbormasterBuildPlanDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildPlanDatasource.php', 'HarbormasterBuildPlanDefaultEditCapability' => 'applications/harbormaster/capability/HarbormasterBuildPlanDefaultEditCapability.php', 'HarbormasterBuildPlanDefaultViewCapability' => 'applications/harbormaster/capability/HarbormasterBuildPlanDefaultViewCapability.php', 'HarbormasterBuildPlanEditEngine' => 'applications/harbormaster/editor/HarbormasterBuildPlanEditEngine.php', 'HarbormasterBuildPlanEditor' => 'applications/harbormaster/editor/HarbormasterBuildPlanEditor.php', 'HarbormasterBuildPlanNameNgrams' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlanNameNgrams.php', 'HarbormasterBuildPlanPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildPlanPHIDType.php', 'HarbormasterBuildPlanQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanQuery.php', 'HarbormasterBuildPlanSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildPlanSearchEngine.php', 'HarbormasterBuildPlanTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlanTransaction.php', 'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php', 'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php', 'HarbormasterBuildRequest' => 'applications/harbormaster/engine/HarbormasterBuildRequest.php', 'HarbormasterBuildSearchConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildSearchConduitAPIMethod.php', 'HarbormasterBuildSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildSearchEngine.php', 'HarbormasterBuildStatus' => 'applications/harbormaster/constants/HarbormasterBuildStatus.php', 'HarbormasterBuildStatusDatasource' => 'applications/harbormaster/typeahead/HarbormasterBuildStatusDatasource.php', 'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php', 'HarbormasterBuildStepCoreCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php', 'HarbormasterBuildStepCustomField' => 'applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php', 'HarbormasterBuildStepEditor' => 'applications/harbormaster/editor/HarbormasterBuildStepEditor.php', 'HarbormasterBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuildStepGroup.php', 'HarbormasterBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterBuildStepImplementation.php', 'HarbormasterBuildStepImplementationTestCase' => 'applications/harbormaster/step/__tests__/HarbormasterBuildStepImplementationTestCase.php', 'HarbormasterBuildStepPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildStepPHIDType.php', 'HarbormasterBuildStepQuery' => 'applications/harbormaster/query/HarbormasterBuildStepQuery.php', 'HarbormasterBuildStepTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStepTransaction.php', 'HarbormasterBuildStepTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildStepTransactionQuery.php', 'HarbormasterBuildTarget' => 'applications/harbormaster/storage/build/HarbormasterBuildTarget.php', 'HarbormasterBuildTargetPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildTargetPHIDType.php', 'HarbormasterBuildTargetQuery' => 'applications/harbormaster/query/HarbormasterBuildTargetQuery.php', 'HarbormasterBuildTransaction' => 'applications/harbormaster/storage/HarbormasterBuildTransaction.php', 'HarbormasterBuildTransactionEditor' => 'applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php', 'HarbormasterBuildTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildTransactionQuery.php', 'HarbormasterBuildUnitMessage' => 'applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php', 'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php', 'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php', 'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php', 'HarbormasterBuildableActionController' => 'applications/harbormaster/controller/HarbormasterBuildableActionController.php', 'HarbormasterBuildableAdapterInterface' => 'applications/harbormaster/herald/HarbormasterBuildableAdapterInterface.php', 'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php', 'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php', 'HarbormasterBuildablePHIDType' => 'applications/harbormaster/phid/HarbormasterBuildablePHIDType.php', 'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php', 'HarbormasterBuildableSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildableSearchEngine.php', 'HarbormasterBuildableTransaction' => 'applications/harbormaster/storage/HarbormasterBuildableTransaction.php', 'HarbormasterBuildableTransactionEditor' => 'applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php', 'HarbormasterBuildableTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildableTransactionQuery.php', 'HarbormasterBuildableViewController' => 'applications/harbormaster/controller/HarbormasterBuildableViewController.php', 'HarbormasterBuiltinBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterBuiltinBuildStepGroup.php', 'HarbormasterCircleCIBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterCircleCIBuildStepImplementation.php', 'HarbormasterCircleCIBuildableInterface' => 'applications/harbormaster/interface/HarbormasterCircleCIBuildableInterface.php', 'HarbormasterCircleCIHookController' => 'applications/harbormaster/controller/HarbormasterCircleCIHookController.php', 'HarbormasterConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterConduitAPIMethod.php', 'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php', 'HarbormasterCreateArtifactConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php', 'HarbormasterCreatePlansCapability' => 'applications/harbormaster/capability/HarbormasterCreatePlansCapability.php', 'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php', 'HarbormasterDrydockBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterDrydockBuildStepGroup.php', 'HarbormasterDrydockCommandBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterDrydockCommandBuildStepImplementation.php', 'HarbormasterDrydockLeaseArtifact' => 'applications/harbormaster/artifact/HarbormasterDrydockLeaseArtifact.php', 'HarbormasterExecFuture' => 'applications/harbormaster/future/HarbormasterExecFuture.php', 'HarbormasterExternalBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterExternalBuildStepGroup.php', 'HarbormasterFileArtifact' => 'applications/harbormaster/artifact/HarbormasterFileArtifact.php', 'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php', 'HarbormasterHostArtifact' => 'applications/harbormaster/artifact/HarbormasterHostArtifact.php', 'HarbormasterLeaseWorkingCopyBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php', 'HarbormasterLintMessagesController' => 'applications/harbormaster/controller/HarbormasterLintMessagesController.php', 'HarbormasterLintPropertyView' => 'applications/harbormaster/view/HarbormasterLintPropertyView.php', 'HarbormasterManagementArchiveLogsWorkflow' => 'applications/harbormaster/management/HarbormasterManagementArchiveLogsWorkflow.php', 'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php', 'HarbormasterManagementRestartWorkflow' => 'applications/harbormaster/management/HarbormasterManagementRestartWorkflow.php', 'HarbormasterManagementUpdateWorkflow' => 'applications/harbormaster/management/HarbormasterManagementUpdateWorkflow.php', 'HarbormasterManagementWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWorkflow.php', 'HarbormasterMessageType' => 'applications/harbormaster/engine/HarbormasterMessageType.php', 'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php', 'HarbormasterOtherBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterOtherBuildStepGroup.php', 'HarbormasterPlanController' => 'applications/harbormaster/controller/HarbormasterPlanController.php', 'HarbormasterPlanDisableController' => 'applications/harbormaster/controller/HarbormasterPlanDisableController.php', 'HarbormasterPlanEditController' => 'applications/harbormaster/controller/HarbormasterPlanEditController.php', 'HarbormasterPlanListController' => 'applications/harbormaster/controller/HarbormasterPlanListController.php', 'HarbormasterPlanRunController' => 'applications/harbormaster/controller/HarbormasterPlanRunController.php', 'HarbormasterPlanViewController' => 'applications/harbormaster/controller/HarbormasterPlanViewController.php', 'HarbormasterPrototypeBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterPrototypeBuildStepGroup.php', 'HarbormasterPublishFragmentBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterPublishFragmentBuildStepImplementation.php', 'HarbormasterQueryAutotargetsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryAutotargetsConduitAPIMethod.php', 'HarbormasterQueryBuildablesConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildablesConduitAPIMethod.php', 'HarbormasterQueryBuildsConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterQueryBuildsConduitAPIMethod.php', 'HarbormasterQueryBuildsSearchEngineAttachment' => 'applications/harbormaster/engineextension/HarbormasterQueryBuildsSearchEngineAttachment.php', 'HarbormasterRemarkupRule' => 'applications/harbormaster/remarkup/HarbormasterRemarkupRule.php', 'HarbormasterRunBuildPlansHeraldAction' => 'applications/harbormaster/herald/HarbormasterRunBuildPlansHeraldAction.php', 'HarbormasterSchemaSpec' => 'applications/harbormaster/storage/HarbormasterSchemaSpec.php', 'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php', 'HarbormasterSendMessageConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterSendMessageConduitAPIMethod.php', 'HarbormasterSleepBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterSleepBuildStepImplementation.php', 'HarbormasterStepAddController' => 'applications/harbormaster/controller/HarbormasterStepAddController.php', 'HarbormasterStepDeleteController' => 'applications/harbormaster/controller/HarbormasterStepDeleteController.php', 'HarbormasterStepEditController' => 'applications/harbormaster/controller/HarbormasterStepEditController.php', 'HarbormasterStepViewController' => 'applications/harbormaster/controller/HarbormasterStepViewController.php', 'HarbormasterTargetEngine' => 'applications/harbormaster/engine/HarbormasterTargetEngine.php', 'HarbormasterTargetWorker' => 'applications/harbormaster/worker/HarbormasterTargetWorker.php', 'HarbormasterTestBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterTestBuildStepGroup.php', 'HarbormasterThrowExceptionBuildStep' => 'applications/harbormaster/step/HarbormasterThrowExceptionBuildStep.php', 'HarbormasterUIEventListener' => 'applications/harbormaster/event/HarbormasterUIEventListener.php', 'HarbormasterURIArtifact' => 'applications/harbormaster/artifact/HarbormasterURIArtifact.php', 'HarbormasterUnitMessageListController' => 'applications/harbormaster/controller/HarbormasterUnitMessageListController.php', 'HarbormasterUnitMessageViewController' => 'applications/harbormaster/controller/HarbormasterUnitMessageViewController.php', 'HarbormasterUnitPropertyView' => 'applications/harbormaster/view/HarbormasterUnitPropertyView.php', 'HarbormasterUnitStatus' => 'applications/harbormaster/constants/HarbormasterUnitStatus.php', 'HarbormasterUnitSummaryView' => 'applications/harbormaster/view/HarbormasterUnitSummaryView.php', 'HarbormasterUploadArtifactBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterUploadArtifactBuildStepImplementation.php', 'HarbormasterWaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php', 'HarbormasterWorker' => 'applications/harbormaster/worker/HarbormasterWorker.php', 'HarbormasterWorkingCopyArtifact' => 'applications/harbormaster/artifact/HarbormasterWorkingCopyArtifact.php', 'HeraldAction' => 'applications/herald/action/HeraldAction.php', 'HeraldActionGroup' => 'applications/herald/action/HeraldActionGroup.php', 'HeraldActionRecord' => 'applications/herald/storage/HeraldActionRecord.php', 'HeraldAdapter' => 'applications/herald/adapter/HeraldAdapter.php', 'HeraldAlwaysField' => 'applications/herald/field/HeraldAlwaysField.php', 'HeraldAnotherRuleField' => 'applications/herald/field/HeraldAnotherRuleField.php', 'HeraldApplicationActionGroup' => 'applications/herald/action/HeraldApplicationActionGroup.php', 'HeraldApplyTranscript' => 'applications/herald/storage/transcript/HeraldApplyTranscript.php', 'HeraldBasicFieldGroup' => 'applications/herald/field/HeraldBasicFieldGroup.php', 'HeraldCommitAdapter' => 'applications/diffusion/herald/HeraldCommitAdapter.php', 'HeraldCondition' => 'applications/herald/storage/HeraldCondition.php', 'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php', 'HeraldContentSourceField' => 'applications/herald/field/HeraldContentSourceField.php', 'HeraldController' => 'applications/herald/controller/HeraldController.php', 'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php', 'HeraldDifferentialAdapter' => 'applications/differential/herald/HeraldDifferentialAdapter.php', 'HeraldDifferentialDiffAdapter' => 'applications/differential/herald/HeraldDifferentialDiffAdapter.php', 'HeraldDifferentialRevisionAdapter' => 'applications/differential/herald/HeraldDifferentialRevisionAdapter.php', 'HeraldDisableController' => 'applications/herald/controller/HeraldDisableController.php', 'HeraldDoNothingAction' => 'applications/herald/action/HeraldDoNothingAction.php', 'HeraldEditFieldGroup' => 'applications/herald/field/HeraldEditFieldGroup.php', 'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php', 'HeraldEmptyFieldValue' => 'applications/herald/value/HeraldEmptyFieldValue.php', 'HeraldEngine' => 'applications/herald/engine/HeraldEngine.php', 'HeraldExactProjectsField' => 'applications/project/herald/HeraldExactProjectsField.php', 'HeraldField' => 'applications/herald/field/HeraldField.php', 'HeraldFieldGroup' => 'applications/herald/field/HeraldFieldGroup.php', 'HeraldFieldTestCase' => 'applications/herald/field/__tests__/HeraldFieldTestCase.php', 'HeraldFieldValue' => 'applications/herald/value/HeraldFieldValue.php', 'HeraldGroup' => 'applications/herald/group/HeraldGroup.php', 'HeraldInvalidActionException' => 'applications/herald/engine/exception/HeraldInvalidActionException.php', 'HeraldInvalidConditionException' => 'applications/herald/engine/exception/HeraldInvalidConditionException.php', 'HeraldManageGlobalRulesCapability' => 'applications/herald/capability/HeraldManageGlobalRulesCapability.php', 'HeraldManiphestTaskAdapter' => 'applications/maniphest/herald/HeraldManiphestTaskAdapter.php', 'HeraldNewController' => 'applications/herald/controller/HeraldNewController.php', 'HeraldNewObjectField' => 'applications/herald/field/HeraldNewObjectField.php', 'HeraldNotifyActionGroup' => 'applications/herald/action/HeraldNotifyActionGroup.php', 'HeraldObjectTranscript' => 'applications/herald/storage/transcript/HeraldObjectTranscript.php', 'HeraldPhameBlogAdapter' => 'applications/phame/herald/HeraldPhameBlogAdapter.php', 'HeraldPhamePostAdapter' => 'applications/phame/herald/HeraldPhamePostAdapter.php', 'HeraldPholioMockAdapter' => 'applications/pholio/herald/HeraldPholioMockAdapter.php', 'HeraldPonderQuestionAdapter' => 'applications/ponder/herald/HeraldPonderQuestionAdapter.php', 'HeraldPreCommitAdapter' => 'applications/diffusion/herald/HeraldPreCommitAdapter.php', 'HeraldPreCommitContentAdapter' => 'applications/diffusion/herald/HeraldPreCommitContentAdapter.php', 'HeraldPreCommitRefAdapter' => 'applications/diffusion/herald/HeraldPreCommitRefAdapter.php', 'HeraldPreventActionGroup' => 'applications/herald/action/HeraldPreventActionGroup.php', 'HeraldProjectsField' => 'applications/project/herald/HeraldProjectsField.php', 'HeraldRecursiveConditionsException' => 'applications/herald/engine/exception/HeraldRecursiveConditionsException.php', 'HeraldRelatedFieldGroup' => 'applications/herald/field/HeraldRelatedFieldGroup.php', 'HeraldRemarkupRule' => 'applications/herald/remarkup/HeraldRemarkupRule.php', 'HeraldRepetitionPolicyConfig' => 'applications/herald/config/HeraldRepetitionPolicyConfig.php', 'HeraldRule' => 'applications/herald/storage/HeraldRule.php', 'HeraldRuleController' => 'applications/herald/controller/HeraldRuleController.php', 'HeraldRuleDatasource' => 'applications/herald/typeahead/HeraldRuleDatasource.php', 'HeraldRuleEditor' => 'applications/herald/editor/HeraldRuleEditor.php', 'HeraldRuleListController' => 'applications/herald/controller/HeraldRuleListController.php', 'HeraldRulePHIDType' => 'applications/herald/phid/HeraldRulePHIDType.php', 'HeraldRuleQuery' => 'applications/herald/query/HeraldRuleQuery.php', 'HeraldRuleSearchEngine' => 'applications/herald/query/HeraldRuleSearchEngine.php', 'HeraldRuleSerializer' => 'applications/herald/editor/HeraldRuleSerializer.php', 'HeraldRuleTestCase' => 'applications/herald/storage/__tests__/HeraldRuleTestCase.php', 'HeraldRuleTransaction' => 'applications/herald/storage/HeraldRuleTransaction.php', 'HeraldRuleTransactionComment' => 'applications/herald/storage/HeraldRuleTransactionComment.php', 'HeraldRuleTranscript' => 'applications/herald/storage/transcript/HeraldRuleTranscript.php', 'HeraldRuleTypeConfig' => 'applications/herald/config/HeraldRuleTypeConfig.php', 'HeraldRuleViewController' => 'applications/herald/controller/HeraldRuleViewController.php', 'HeraldSchemaSpec' => 'applications/herald/storage/HeraldSchemaSpec.php', 'HeraldSelectFieldValue' => 'applications/herald/value/HeraldSelectFieldValue.php', 'HeraldSpaceField' => 'applications/spaces/herald/HeraldSpaceField.php', 'HeraldSubscribersField' => 'applications/subscriptions/herald/HeraldSubscribersField.php', 'HeraldSupportActionGroup' => 'applications/herald/action/HeraldSupportActionGroup.php', 'HeraldSupportFieldGroup' => 'applications/herald/field/HeraldSupportFieldGroup.php', 'HeraldTestConsoleController' => 'applications/herald/controller/HeraldTestConsoleController.php', 'HeraldTextFieldValue' => 'applications/herald/value/HeraldTextFieldValue.php', 'HeraldTokenizerFieldValue' => 'applications/herald/value/HeraldTokenizerFieldValue.php', 'HeraldTransactionQuery' => 'applications/herald/query/HeraldTransactionQuery.php', 'HeraldTranscript' => 'applications/herald/storage/transcript/HeraldTranscript.php', 'HeraldTranscriptController' => 'applications/herald/controller/HeraldTranscriptController.php', 'HeraldTranscriptDestructionEngineExtension' => 'applications/herald/engineextension/HeraldTranscriptDestructionEngineExtension.php', 'HeraldTranscriptGarbageCollector' => 'applications/herald/garbagecollector/HeraldTranscriptGarbageCollector.php', 'HeraldTranscriptListController' => 'applications/herald/controller/HeraldTranscriptListController.php', 'HeraldTranscriptPHIDType' => 'applications/herald/phid/HeraldTranscriptPHIDType.php', 'HeraldTranscriptQuery' => 'applications/herald/query/HeraldTranscriptQuery.php', 'HeraldTranscriptSearchEngine' => 'applications/herald/query/HeraldTranscriptSearchEngine.php', 'HeraldTranscriptTestCase' => 'applications/herald/storage/__tests__/HeraldTranscriptTestCase.php', 'HeraldUtilityActionGroup' => 'applications/herald/action/HeraldUtilityActionGroup.php', 'Javelin' => 'infrastructure/javelin/Javelin.php', 'JavelinReactorUIExample' => 'applications/uiexample/examples/JavelinReactorUIExample.php', 'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php', 'JavelinViewExampleServerView' => 'applications/uiexample/examples/JavelinViewExampleServerView.php', 'JavelinViewUIExample' => 'applications/uiexample/examples/JavelinViewUIExample.php', 'LegalpadController' => 'applications/legalpad/controller/LegalpadController.php', 'LegalpadCreateDocumentsCapability' => 'applications/legalpad/capability/LegalpadCreateDocumentsCapability.php', 'LegalpadDAO' => 'applications/legalpad/storage/LegalpadDAO.php', 'LegalpadDefaultEditCapability' => 'applications/legalpad/capability/LegalpadDefaultEditCapability.php', 'LegalpadDefaultViewCapability' => 'applications/legalpad/capability/LegalpadDefaultViewCapability.php', 'LegalpadDocument' => 'applications/legalpad/storage/LegalpadDocument.php', 'LegalpadDocumentBody' => 'applications/legalpad/storage/LegalpadDocumentBody.php', 'LegalpadDocumentCommentController' => 'applications/legalpad/controller/LegalpadDocumentCommentController.php', 'LegalpadDocumentDatasource' => 'applications/legalpad/typeahead/LegalpadDocumentDatasource.php', 'LegalpadDocumentDoneController' => 'applications/legalpad/controller/LegalpadDocumentDoneController.php', 'LegalpadDocumentEditController' => 'applications/legalpad/controller/LegalpadDocumentEditController.php', 'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php', 'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php', 'LegalpadDocumentManageController' => 'applications/legalpad/controller/LegalpadDocumentManageController.php', 'LegalpadDocumentQuery' => 'applications/legalpad/query/LegalpadDocumentQuery.php', 'LegalpadDocumentRemarkupRule' => 'applications/legalpad/remarkup/LegalpadDocumentRemarkupRule.php', 'LegalpadDocumentSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSearchEngine.php', 'LegalpadDocumentSignController' => 'applications/legalpad/controller/LegalpadDocumentSignController.php', 'LegalpadDocumentSignature' => 'applications/legalpad/storage/LegalpadDocumentSignature.php', 'LegalpadDocumentSignatureAddController' => 'applications/legalpad/controller/LegalpadDocumentSignatureAddController.php', 'LegalpadDocumentSignatureListController' => 'applications/legalpad/controller/LegalpadDocumentSignatureListController.php', 'LegalpadDocumentSignatureQuery' => 'applications/legalpad/query/LegalpadDocumentSignatureQuery.php', 'LegalpadDocumentSignatureSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php', 'LegalpadDocumentSignatureVerificationController' => 'applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php', 'LegalpadDocumentSignatureViewController' => 'applications/legalpad/controller/LegalpadDocumentSignatureViewController.php', 'LegalpadMailReceiver' => 'applications/legalpad/mail/LegalpadMailReceiver.php', 'LegalpadObjectNeedsSignatureEdgeType' => 'applications/legalpad/edge/LegalpadObjectNeedsSignatureEdgeType.php', 'LegalpadReplyHandler' => 'applications/legalpad/mail/LegalpadReplyHandler.php', 'LegalpadRequireSignatureHeraldAction' => 'applications/legalpad/herald/LegalpadRequireSignatureHeraldAction.php', 'LegalpadSchemaSpec' => 'applications/legalpad/storage/LegalpadSchemaSpec.php', 'LegalpadSignatureNeededByObjectEdgeType' => 'applications/legalpad/edge/LegalpadSignatureNeededByObjectEdgeType.php', 'LegalpadTransaction' => 'applications/legalpad/storage/LegalpadTransaction.php', 'LegalpadTransactionComment' => 'applications/legalpad/storage/LegalpadTransactionComment.php', 'LegalpadTransactionQuery' => 'applications/legalpad/query/LegalpadTransactionQuery.php', 'LegalpadTransactionView' => 'applications/legalpad/view/LegalpadTransactionView.php', 'LiskChunkTestCase' => 'infrastructure/storage/lisk/__tests__/LiskChunkTestCase.php', 'LiskDAO' => 'infrastructure/storage/lisk/LiskDAO.php', 'LiskDAOSet' => 'infrastructure/storage/lisk/LiskDAOSet.php', 'LiskDAOTestCase' => 'infrastructure/storage/lisk/__tests__/LiskDAOTestCase.php', 'LiskEphemeralObjectException' => 'infrastructure/storage/lisk/LiskEphemeralObjectException.php', 'LiskFixtureTestCase' => 'infrastructure/storage/lisk/__tests__/LiskFixtureTestCase.php', 'LiskIsolationTestCase' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestCase.php', 'LiskIsolationTestDAO' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAO.php', 'LiskIsolationTestDAOException' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAOException.php', 'LiskMigrationIterator' => 'infrastructure/storage/lisk/LiskMigrationIterator.php', 'LiskRawMigrationIterator' => 'infrastructure/storage/lisk/LiskRawMigrationIterator.php', 'MacroConduitAPIMethod' => 'applications/macro/conduit/MacroConduitAPIMethod.php', 'MacroCreateMemeConduitAPIMethod' => 'applications/macro/conduit/MacroCreateMemeConduitAPIMethod.php', 'MacroQueryConduitAPIMethod' => 'applications/macro/conduit/MacroQueryConduitAPIMethod.php', 'ManiphestAssignEmailCommand' => 'applications/maniphest/command/ManiphestAssignEmailCommand.php', 'ManiphestAssigneeDatasource' => 'applications/maniphest/typeahead/ManiphestAssigneeDatasource.php', 'ManiphestBatchEditController' => 'applications/maniphest/controller/ManiphestBatchEditController.php', 'ManiphestBulkEditCapability' => 'applications/maniphest/capability/ManiphestBulkEditCapability.php', 'ManiphestClaimEmailCommand' => 'applications/maniphest/command/ManiphestClaimEmailCommand.php', 'ManiphestCloseEmailCommand' => 'applications/maniphest/command/ManiphestCloseEmailCommand.php', 'ManiphestConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestConduitAPIMethod.php', 'ManiphestConfiguredCustomField' => 'applications/maniphest/field/ManiphestConfiguredCustomField.php', 'ManiphestConstants' => 'applications/maniphest/constants/ManiphestConstants.php', 'ManiphestController' => 'applications/maniphest/controller/ManiphestController.php', 'ManiphestCreateMailReceiver' => 'applications/maniphest/mail/ManiphestCreateMailReceiver.php', 'ManiphestCreateTaskConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestCreateTaskConduitAPIMethod.php', 'ManiphestCustomField' => 'applications/maniphest/field/ManiphestCustomField.php', 'ManiphestCustomFieldNumericIndex' => 'applications/maniphest/storage/ManiphestCustomFieldNumericIndex.php', 'ManiphestCustomFieldStatusParser' => 'applications/maniphest/field/parser/ManiphestCustomFieldStatusParser.php', 'ManiphestCustomFieldStatusParserTestCase' => 'applications/maniphest/field/parser/__tests__/ManiphestCustomFieldStatusParserTestCase.php', 'ManiphestCustomFieldStorage' => 'applications/maniphest/storage/ManiphestCustomFieldStorage.php', 'ManiphestCustomFieldStringIndex' => 'applications/maniphest/storage/ManiphestCustomFieldStringIndex.php', 'ManiphestDAO' => 'applications/maniphest/storage/ManiphestDAO.php', 'ManiphestDefaultEditCapability' => 'applications/maniphest/capability/ManiphestDefaultEditCapability.php', 'ManiphestDefaultViewCapability' => 'applications/maniphest/capability/ManiphestDefaultViewCapability.php', 'ManiphestEditAssignCapability' => 'applications/maniphest/capability/ManiphestEditAssignCapability.php', 'ManiphestEditConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestEditConduitAPIMethod.php', 'ManiphestEditEngine' => 'applications/maniphest/editor/ManiphestEditEngine.php', 'ManiphestEditPoliciesCapability' => 'applications/maniphest/capability/ManiphestEditPoliciesCapability.php', 'ManiphestEditPriorityCapability' => 'applications/maniphest/capability/ManiphestEditPriorityCapability.php', 'ManiphestEditProjectsCapability' => 'applications/maniphest/capability/ManiphestEditProjectsCapability.php', 'ManiphestEditStatusCapability' => 'applications/maniphest/capability/ManiphestEditStatusCapability.php', 'ManiphestEmailCommand' => 'applications/maniphest/command/ManiphestEmailCommand.php', 'ManiphestExcelDefaultFormat' => 'applications/maniphest/export/ManiphestExcelDefaultFormat.php', 'ManiphestExcelFormat' => 'applications/maniphest/export/ManiphestExcelFormat.php', 'ManiphestExcelFormatTestCase' => 'applications/maniphest/export/__tests__/ManiphestExcelFormatTestCase.php', 'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php', 'ManiphestGetTaskTransactionsConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestGetTaskTransactionsConduitAPIMethod.php', 'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php', 'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php', 'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php', 'ManiphestPointsConfigOptionType' => 'applications/maniphest/config/ManiphestPointsConfigOptionType.php', 'ManiphestPriorityConfigOptionType' => 'applications/maniphest/config/ManiphestPriorityConfigOptionType.php', 'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php', 'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php', 'ManiphestQueryConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryConduitAPIMethod.php', 'ManiphestQueryStatusesConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestQueryStatusesConduitAPIMethod.php', 'ManiphestRemarkupRule' => 'applications/maniphest/remarkup/ManiphestRemarkupRule.php', 'ManiphestReplyHandler' => 'applications/maniphest/mail/ManiphestReplyHandler.php', 'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php', 'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php', 'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php', 'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php', 'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php', 'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php', 'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php', 'ManiphestTaskAssignHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php', 'ManiphestTaskAssignOtherHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php', 'ManiphestTaskAssignSelfHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignSelfHeraldAction.php', 'ManiphestTaskAssigneeHeraldField' => 'applications/maniphest/herald/ManiphestTaskAssigneeHeraldField.php', 'ManiphestTaskAuthorHeraldField' => 'applications/maniphest/herald/ManiphestTaskAuthorHeraldField.php', 'ManiphestTaskAuthorPolicyRule' => 'applications/maniphest/policyrule/ManiphestTaskAuthorPolicyRule.php', 'ManiphestTaskCloseAsDuplicateRelationship' => 'applications/maniphest/relationship/ManiphestTaskCloseAsDuplicateRelationship.php', 'ManiphestTaskClosedStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php', 'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php', 'ManiphestTaskDependsOnTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependsOnTaskEdgeType.php', 'ManiphestTaskDescriptionHeraldField' => 'applications/maniphest/herald/ManiphestTaskDescriptionHeraldField.php', 'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php', 'ManiphestTaskEditBulkJobType' => 'applications/maniphest/bulk/ManiphestTaskEditBulkJobType.php', 'ManiphestTaskEditController' => 'applications/maniphest/controller/ManiphestTaskEditController.php', 'ManiphestTaskFulltextEngine' => 'applications/maniphest/search/ManiphestTaskFulltextEngine.php', 'ManiphestTaskGraph' => 'infrastructure/graph/ManiphestTaskGraph.php', 'ManiphestTaskHasCommitEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasCommitEdgeType.php', 'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php', 'ManiphestTaskHasDuplicateTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasDuplicateTaskEdgeType.php', 'ManiphestTaskHasMockEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasMockEdgeType.php', 'ManiphestTaskHasMockRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasMockRelationship.php', 'ManiphestTaskHasParentRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasParentRelationship.php', 'ManiphestTaskHasRevisionEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasRevisionEdgeType.php', 'ManiphestTaskHasRevisionRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasRevisionRelationship.php', 'ManiphestTaskHasSubtaskRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasSubtaskRelationship.php', 'ManiphestTaskHeraldField' => 'applications/maniphest/herald/ManiphestTaskHeraldField.php', 'ManiphestTaskHeraldFieldGroup' => 'applications/maniphest/herald/ManiphestTaskHeraldFieldGroup.php', 'ManiphestTaskIsDuplicateOfTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskIsDuplicateOfTaskEdgeType.php', 'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php', 'ManiphestTaskListHTTPParameterType' => 'applications/maniphest/httpparametertype/ManiphestTaskListHTTPParameterType.php', 'ManiphestTaskListView' => 'applications/maniphest/view/ManiphestTaskListView.php', 'ManiphestTaskMailReceiver' => 'applications/maniphest/mail/ManiphestTaskMailReceiver.php', 'ManiphestTaskMergeInRelationship' => 'applications/maniphest/relationship/ManiphestTaskMergeInRelationship.php', 'ManiphestTaskOpenStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php', 'ManiphestTaskPHIDResolver' => 'applications/maniphest/httpparametertype/ManiphestTaskPHIDResolver.php', 'ManiphestTaskPHIDType' => 'applications/maniphest/phid/ManiphestTaskPHIDType.php', 'ManiphestTaskPoints' => 'applications/maniphest/constants/ManiphestTaskPoints.php', 'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php', 'ManiphestTaskPriorityDatasource' => 'applications/maniphest/typeahead/ManiphestTaskPriorityDatasource.php', 'ManiphestTaskPriorityHeraldAction' => 'applications/maniphest/herald/ManiphestTaskPriorityHeraldAction.php', 'ManiphestTaskPriorityHeraldField' => 'applications/maniphest/herald/ManiphestTaskPriorityHeraldField.php', 'ManiphestTaskQuery' => 'applications/maniphest/query/ManiphestTaskQuery.php', 'ManiphestTaskRelationship' => 'applications/maniphest/relationship/ManiphestTaskRelationship.php', 'ManiphestTaskRelationshipSource' => 'applications/search/relationship/ManiphestTaskRelationshipSource.php', 'ManiphestTaskResultListView' => 'applications/maniphest/view/ManiphestTaskResultListView.php', 'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php', 'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php', 'ManiphestTaskStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusDatasource.php', 'ManiphestTaskStatusFunctionDatasource' => 'applications/maniphest/typeahead/ManiphestTaskStatusFunctionDatasource.php', 'ManiphestTaskStatusHeraldAction' => 'applications/maniphest/herald/ManiphestTaskStatusHeraldAction.php', 'ManiphestTaskStatusHeraldField' => 'applications/maniphest/herald/ManiphestTaskStatusHeraldField.php', 'ManiphestTaskStatusTestCase' => 'applications/maniphest/constants/__tests__/ManiphestTaskStatusTestCase.php', 'ManiphestTaskTestCase' => 'applications/maniphest/__tests__/ManiphestTaskTestCase.php', 'ManiphestTaskTitleHeraldField' => 'applications/maniphest/herald/ManiphestTaskTitleHeraldField.php', 'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php', 'ManiphestTransactionComment' => 'applications/maniphest/storage/ManiphestTransactionComment.php', 'ManiphestTransactionEditor' => 'applications/maniphest/editor/ManiphestTransactionEditor.php', 'ManiphestTransactionQuery' => 'applications/maniphest/query/ManiphestTransactionQuery.php', 'ManiphestUpdateConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php', 'ManiphestView' => 'applications/maniphest/view/ManiphestView.php', 'MetaMTAEmailTransactionCommand' => 'applications/metamta/command/MetaMTAEmailTransactionCommand.php', 'MetaMTAEmailTransactionCommandTestCase' => 'applications/metamta/command/__tests__/MetaMTAEmailTransactionCommandTestCase.php', 'MetaMTAMailReceivedGarbageCollector' => 'applications/metamta/garbagecollector/MetaMTAMailReceivedGarbageCollector.php', 'MetaMTAMailSentGarbageCollector' => 'applications/metamta/garbagecollector/MetaMTAMailSentGarbageCollector.php', 'MetaMTAReceivedMailStatus' => 'applications/metamta/constants/MetaMTAReceivedMailStatus.php', 'MultimeterContext' => 'applications/multimeter/storage/MultimeterContext.php', 'MultimeterControl' => 'applications/multimeter/data/MultimeterControl.php', 'MultimeterController' => 'applications/multimeter/controller/MultimeterController.php', 'MultimeterDAO' => 'applications/multimeter/storage/MultimeterDAO.php', 'MultimeterDimension' => 'applications/multimeter/storage/MultimeterDimension.php', 'MultimeterEvent' => 'applications/multimeter/storage/MultimeterEvent.php', 'MultimeterEventGarbageCollector' => 'applications/multimeter/garbagecollector/MultimeterEventGarbageCollector.php', 'MultimeterHost' => 'applications/multimeter/storage/MultimeterHost.php', 'MultimeterLabel' => 'applications/multimeter/storage/MultimeterLabel.php', 'MultimeterSampleController' => 'applications/multimeter/controller/MultimeterSampleController.php', 'MultimeterViewer' => 'applications/multimeter/storage/MultimeterViewer.php', 'NuanceConduitAPIMethod' => 'applications/nuance/conduit/NuanceConduitAPIMethod.php', 'NuanceConsoleController' => 'applications/nuance/controller/NuanceConsoleController.php', 'NuanceContentSource' => 'applications/nuance/contentsource/NuanceContentSource.php', 'NuanceController' => 'applications/nuance/controller/NuanceController.php', 'NuanceDAO' => 'applications/nuance/storage/NuanceDAO.php', 'NuanceGitHubEventItemType' => 'applications/nuance/item/NuanceGitHubEventItemType.php', 'NuanceGitHubImportCursor' => 'applications/nuance/cursor/NuanceGitHubImportCursor.php', 'NuanceGitHubIssuesImportCursor' => 'applications/nuance/cursor/NuanceGitHubIssuesImportCursor.php', 'NuanceGitHubRawEvent' => 'applications/nuance/github/NuanceGitHubRawEvent.php', 'NuanceGitHubRawEventTestCase' => 'applications/nuance/github/__tests__/NuanceGitHubRawEventTestCase.php', 'NuanceGitHubRepositoryImportCursor' => 'applications/nuance/cursor/NuanceGitHubRepositoryImportCursor.php', 'NuanceGitHubRepositorySourceDefinition' => 'applications/nuance/source/NuanceGitHubRepositorySourceDefinition.php', 'NuanceImportCursor' => 'applications/nuance/cursor/NuanceImportCursor.php', 'NuanceImportCursorData' => 'applications/nuance/storage/NuanceImportCursorData.php', 'NuanceImportCursorDataQuery' => 'applications/nuance/query/NuanceImportCursorDataQuery.php', 'NuanceImportCursorPHIDType' => 'applications/nuance/phid/NuanceImportCursorPHIDType.php', 'NuanceItem' => 'applications/nuance/storage/NuanceItem.php', 'NuanceItemActionController' => 'applications/nuance/controller/NuanceItemActionController.php', 'NuanceItemCommand' => 'applications/nuance/storage/NuanceItemCommand.php', 'NuanceItemCommandQuery' => 'applications/nuance/query/NuanceItemCommandQuery.php', 'NuanceItemController' => 'applications/nuance/controller/NuanceItemController.php', 'NuanceItemEditor' => 'applications/nuance/editor/NuanceItemEditor.php', 'NuanceItemListController' => 'applications/nuance/controller/NuanceItemListController.php', 'NuanceItemManageController' => 'applications/nuance/controller/NuanceItemManageController.php', 'NuanceItemPHIDType' => 'applications/nuance/phid/NuanceItemPHIDType.php', 'NuanceItemQuery' => 'applications/nuance/query/NuanceItemQuery.php', 'NuanceItemSearchEngine' => 'applications/nuance/query/NuanceItemSearchEngine.php', 'NuanceItemTransaction' => 'applications/nuance/storage/NuanceItemTransaction.php', 'NuanceItemTransactionComment' => 'applications/nuance/storage/NuanceItemTransactionComment.php', 'NuanceItemTransactionQuery' => 'applications/nuance/query/NuanceItemTransactionQuery.php', 'NuanceItemType' => 'applications/nuance/item/NuanceItemType.php', 'NuanceItemUpdateWorker' => 'applications/nuance/worker/NuanceItemUpdateWorker.php', 'NuanceItemViewController' => 'applications/nuance/controller/NuanceItemViewController.php', 'NuanceManagementImportWorkflow' => 'applications/nuance/management/NuanceManagementImportWorkflow.php', 'NuanceManagementUpdateWorkflow' => 'applications/nuance/management/NuanceManagementUpdateWorkflow.php', 'NuanceManagementWorkflow' => 'applications/nuance/management/NuanceManagementWorkflow.php', 'NuancePhabricatorFormSourceDefinition' => 'applications/nuance/source/NuancePhabricatorFormSourceDefinition.php', 'NuanceQuery' => 'applications/nuance/query/NuanceQuery.php', 'NuanceQueue' => 'applications/nuance/storage/NuanceQueue.php', 'NuanceQueueController' => 'applications/nuance/controller/NuanceQueueController.php', 'NuanceQueueDatasource' => 'applications/nuance/typeahead/NuanceQueueDatasource.php', 'NuanceQueueEditController' => 'applications/nuance/controller/NuanceQueueEditController.php', 'NuanceQueueEditEngine' => 'applications/nuance/editor/NuanceQueueEditEngine.php', 'NuanceQueueEditor' => 'applications/nuance/editor/NuanceQueueEditor.php', 'NuanceQueueListController' => 'applications/nuance/controller/NuanceQueueListController.php', 'NuanceQueuePHIDType' => 'applications/nuance/phid/NuanceQueuePHIDType.php', 'NuanceQueueQuery' => 'applications/nuance/query/NuanceQueueQuery.php', 'NuanceQueueSearchEngine' => 'applications/nuance/query/NuanceQueueSearchEngine.php', 'NuanceQueueTransaction' => 'applications/nuance/storage/NuanceQueueTransaction.php', 'NuanceQueueTransactionComment' => 'applications/nuance/storage/NuanceQueueTransactionComment.php', 'NuanceQueueTransactionQuery' => 'applications/nuance/query/NuanceQueueTransactionQuery.php', 'NuanceQueueViewController' => 'applications/nuance/controller/NuanceQueueViewController.php', 'NuanceSchemaSpec' => 'applications/nuance/storage/NuanceSchemaSpec.php', 'NuanceSource' => 'applications/nuance/storage/NuanceSource.php', 'NuanceSourceActionController' => 'applications/nuance/controller/NuanceSourceActionController.php', 'NuanceSourceController' => 'applications/nuance/controller/NuanceSourceController.php', 'NuanceSourceDefaultEditCapability' => 'applications/nuance/capability/NuanceSourceDefaultEditCapability.php', 'NuanceSourceDefaultViewCapability' => 'applications/nuance/capability/NuanceSourceDefaultViewCapability.php', 'NuanceSourceDefinition' => 'applications/nuance/source/NuanceSourceDefinition.php', 'NuanceSourceDefinitionTestCase' => 'applications/nuance/source/__tests__/NuanceSourceDefinitionTestCase.php', 'NuanceSourceEditController' => 'applications/nuance/controller/NuanceSourceEditController.php', 'NuanceSourceEditEngine' => 'applications/nuance/editor/NuanceSourceEditEngine.php', 'NuanceSourceEditor' => 'applications/nuance/editor/NuanceSourceEditor.php', 'NuanceSourceListController' => 'applications/nuance/controller/NuanceSourceListController.php', 'NuanceSourceManageCapability' => 'applications/nuance/capability/NuanceSourceManageCapability.php', 'NuanceSourceNameNgrams' => 'applications/nuance/storage/NuanceSourceNameNgrams.php', 'NuanceSourcePHIDType' => 'applications/nuance/phid/NuanceSourcePHIDType.php', 'NuanceSourceQuery' => 'applications/nuance/query/NuanceSourceQuery.php', 'NuanceSourceSearchEngine' => 'applications/nuance/query/NuanceSourceSearchEngine.php', 'NuanceSourceTransaction' => 'applications/nuance/storage/NuanceSourceTransaction.php', 'NuanceSourceTransactionComment' => 'applications/nuance/storage/NuanceSourceTransactionComment.php', 'NuanceSourceTransactionQuery' => 'applications/nuance/query/NuanceSourceTransactionQuery.php', 'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php', 'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php', 'NuanceWorker' => 'applications/nuance/worker/NuanceWorker.php', 'OwnersConduitAPIMethod' => 'applications/owners/conduit/OwnersConduitAPIMethod.php', 'OwnersEditConduitAPIMethod' => 'applications/owners/conduit/OwnersEditConduitAPIMethod.php', 'OwnersPackageReplyHandler' => 'applications/owners/mail/OwnersPackageReplyHandler.php', 'OwnersQueryConduitAPIMethod' => 'applications/owners/conduit/OwnersQueryConduitAPIMethod.php', 'OwnersSearchConduitAPIMethod' => 'applications/owners/conduit/OwnersSearchConduitAPIMethod.php', 'PHIDConduitAPIMethod' => 'applications/phid/conduit/PHIDConduitAPIMethod.php', 'PHIDInfoConduitAPIMethod' => 'applications/phid/conduit/PHIDInfoConduitAPIMethod.php', 'PHIDLookupConduitAPIMethod' => 'applications/phid/conduit/PHIDLookupConduitAPIMethod.php', 'PHIDQueryConduitAPIMethod' => 'applications/phid/conduit/PHIDQueryConduitAPIMethod.php', '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', 'PHUIBadgeView' => 'view/phui/PHUIBadgeView.php', 'PHUIBigInfoView' => 'view/phui/PHUIBigInfoView.php', 'PHUIBoxExample' => 'applications/uiexample/examples/PHUIBoxExample.php', 'PHUIBoxView' => 'view/phui/PHUIBoxView.php', 'PHUIButtonBarExample' => 'applications/uiexample/examples/PHUIButtonBarExample.php', 'PHUIButtonBarView' => 'view/phui/PHUIButtonBarView.php', 'PHUIButtonExample' => 'applications/uiexample/examples/PHUIButtonExample.php', 'PHUIButtonView' => 'view/phui/PHUIButtonView.php', 'PHUICMSView' => 'view/phui/PHUICMSView.php', 'PHUICalendarDayView' => 'view/phui/calendar/PHUICalendarDayView.php', 'PHUICalendarListView' => 'view/phui/calendar/PHUICalendarListView.php', 'PHUICalendarMonthView' => 'view/phui/calendar/PHUICalendarMonthView.php', 'PHUICalendarWeekView' => 'view/phui/calendar/PHUICalendarWeekView.php', 'PHUICalendarWidgetView' => 'view/phui/calendar/PHUICalendarWidgetView.php', 'PHUIColorPalletteExample' => 'applications/uiexample/examples/PHUIColorPalletteExample.php', 'PHUICrumbView' => 'view/phui/PHUICrumbView.php', 'PHUICrumbsView' => 'view/phui/PHUICrumbsView.php', 'PHUICurtainExtension' => 'view/extension/PHUICurtainExtension.php', 'PHUICurtainPanelView' => 'view/layout/PHUICurtainPanelView.php', 'PHUICurtainView' => 'view/layout/PHUICurtainView.php', 'PHUIDiffGraphView' => 'infrastructure/diff/view/PHUIDiffGraphView.php', 'PHUIDiffGraphViewTestCase' => 'infrastructure/diff/view/__tests__/PHUIDiffGraphViewTestCase.php', 'PHUIDiffInlineCommentDetailView' => 'infrastructure/diff/view/PHUIDiffInlineCommentDetailView.php', 'PHUIDiffInlineCommentEditView' => 'infrastructure/diff/view/PHUIDiffInlineCommentEditView.php', 'PHUIDiffInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffInlineCommentRowScaffold.php', 'PHUIDiffInlineCommentTableScaffold' => 'infrastructure/diff/view/PHUIDiffInlineCommentTableScaffold.php', 'PHUIDiffInlineCommentUndoView' => 'infrastructure/diff/view/PHUIDiffInlineCommentUndoView.php', 'PHUIDiffInlineCommentView' => 'infrastructure/diff/view/PHUIDiffInlineCommentView.php', 'PHUIDiffOneUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffOneUpInlineCommentRowScaffold.php', 'PHUIDiffRevealIconView' => 'infrastructure/diff/view/PHUIDiffRevealIconView.php', 'PHUIDiffTableOfContentsItemView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php', 'PHUIDiffTableOfContentsListView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsListView.php', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php', 'PHUIDocumentSummaryView' => 'view/phui/PHUIDocumentSummaryView.php', 'PHUIDocumentViewPro' => 'view/phui/PHUIDocumentViewPro.php', 'PHUIFeedStoryExample' => 'applications/uiexample/examples/PHUIFeedStoryExample.php', 'PHUIFeedStoryView' => 'view/phui/PHUIFeedStoryView.php', 'PHUIFormDividerControl' => 'view/form/control/PHUIFormDividerControl.php', 'PHUIFormFileControl' => 'view/form/control/PHUIFormFileControl.php', 'PHUIFormFreeformDateControl' => 'view/form/control/PHUIFormFreeformDateControl.php', 'PHUIFormIconSetControl' => 'view/form/control/PHUIFormIconSetControl.php', 'PHUIFormInsetView' => 'view/form/PHUIFormInsetView.php', 'PHUIFormLayoutView' => 'view/form/PHUIFormLayoutView.php', 'PHUIFormNumberControl' => 'view/form/control/PHUIFormNumberControl.php', 'PHUIHandleListView' => 'applications/phid/view/PHUIHandleListView.php', 'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', 'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', 'PHUIHeadThingView' => 'view/phui/PHUIHeadThingView.php', 'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php', 'PHUIHovercardUIExample' => 'applications/uiexample/examples/PHUIHovercardUIExample.php', 'PHUIHovercardView' => 'view/phui/PHUIHovercardView.php', 'PHUIIconCircleView' => 'view/phui/PHUIIconCircleView.php', 'PHUIIconExample' => 'applications/uiexample/examples/PHUIIconExample.php', 'PHUIIconView' => 'view/phui/PHUIIconView.php', 'PHUIImageMaskExample' => 'applications/uiexample/examples/PHUIImageMaskExample.php', 'PHUIImageMaskView' => 'view/phui/PHUIImageMaskView.php', 'PHUIInfoExample' => 'applications/uiexample/examples/PHUIInfoExample.php', 'PHUIInfoPanelExample' => 'applications/uiexample/examples/PHUIInfoPanelExample.php', 'PHUIInfoPanelView' => 'view/phui/PHUIInfoPanelView.php', 'PHUIInfoView' => 'view/form/PHUIInfoView.php', 'PHUIInvisibleCharacterTestCase' => 'view/phui/__tests__/PHUIInvisibleCharacterTestCase.php', 'PHUIInvisibleCharacterView' => 'view/phui/PHUIInvisibleCharacterView.php', 'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php', 'PHUIListItemView' => 'view/phui/PHUIListItemView.php', 'PHUIListView' => 'view/phui/PHUIListView.php', 'PHUIListViewTestCase' => 'view/layout/__tests__/PHUIListViewTestCase.php', 'PHUIMainMenuView' => 'view/phui/PHUIMainMenuView.php', 'PHUIObjectBoxView' => 'view/phui/PHUIObjectBoxView.php', 'PHUIObjectItemListExample' => 'applications/uiexample/examples/PHUIObjectItemListExample.php', 'PHUIObjectItemListView' => 'view/phui/PHUIObjectItemListView.php', 'PHUIObjectItemView' => 'view/phui/PHUIObjectItemView.php', 'PHUIPagerView' => 'view/phui/PHUIPagerView.php', 'PHUIPinboardItemView' => 'view/phui/PHUIPinboardItemView.php', 'PHUIPinboardView' => 'view/phui/PHUIPinboardView.php', 'PHUIPolicySectionView' => 'applications/policy/view/PHUIPolicySectionView.php', 'PHUIPropertyGroupView' => 'view/phui/PHUIPropertyGroupView.php', 'PHUIPropertyListExample' => 'applications/uiexample/examples/PHUIPropertyListExample.php', 'PHUIPropertyListView' => 'view/phui/PHUIPropertyListView.php', 'PHUIRemarkupPreviewPanel' => 'view/phui/PHUIRemarkupPreviewPanel.php', 'PHUIRemarkupView' => 'infrastructure/markup/view/PHUIRemarkupView.php', 'PHUISegmentBarSegmentView' => 'view/phui/PHUISegmentBarSegmentView.php', 'PHUISegmentBarView' => 'view/phui/PHUISegmentBarView.php', 'PHUISpacesNamespaceContextView' => 'applications/spaces/view/PHUISpacesNamespaceContextView.php', 'PHUIStatusItemView' => 'view/phui/PHUIStatusItemView.php', 'PHUIStatusListView' => 'view/phui/PHUIStatusListView.php', 'PHUITabGroupView' => 'view/phui/PHUITabGroupView.php', 'PHUITabView' => 'view/phui/PHUITabView.php', 'PHUITagExample' => 'applications/uiexample/examples/PHUITagExample.php', 'PHUITagView' => 'view/phui/PHUITagView.php', 'PHUITimelineEventView' => 'view/phui/PHUITimelineEventView.php', 'PHUITimelineExample' => 'applications/uiexample/examples/PHUITimelineExample.php', 'PHUITimelineView' => 'view/phui/PHUITimelineView.php', 'PHUITwoColumnView' => 'view/phui/PHUITwoColumnView.php', 'PHUITypeaheadExample' => 'applications/uiexample/examples/PHUITypeaheadExample.php', 'PHUIUserAvailabilityView' => 'applications/calendar/view/PHUIUserAvailabilityView.php', 'PHUIWorkboardView' => 'view/phui/PHUIWorkboardView.php', 'PHUIWorkpanelView' => 'view/phui/PHUIWorkpanelView.php', 'PassphraseAbstractKey' => 'applications/passphrase/keys/PassphraseAbstractKey.php', 'PassphraseConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseConduitAPIMethod.php', 'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php', 'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php', 'PassphraseCredentialAuthorPolicyRule' => 'applications/passphrase/policyrule/PassphraseCredentialAuthorPolicyRule.php', 'PassphraseCredentialConduitController' => 'applications/passphrase/controller/PassphraseCredentialConduitController.php', 'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php', 'PassphraseCredentialCreateController' => 'applications/passphrase/controller/PassphraseCredentialCreateController.php', 'PassphraseCredentialDestroyController' => 'applications/passphrase/controller/PassphraseCredentialDestroyController.php', 'PassphraseCredentialEditController' => 'applications/passphrase/controller/PassphraseCredentialEditController.php', 'PassphraseCredentialFulltextEngine' => 'applications/passphrase/search/PassphraseCredentialFulltextEngine.php', 'PassphraseCredentialListController' => 'applications/passphrase/controller/PassphraseCredentialListController.php', 'PassphraseCredentialLockController' => 'applications/passphrase/controller/PassphraseCredentialLockController.php', 'PassphraseCredentialPHIDType' => 'applications/passphrase/phid/PassphraseCredentialPHIDType.php', 'PassphraseCredentialPublicController' => 'applications/passphrase/controller/PassphraseCredentialPublicController.php', 'PassphraseCredentialQuery' => 'applications/passphrase/query/PassphraseCredentialQuery.php', 'PassphraseCredentialRevealController' => 'applications/passphrase/controller/PassphraseCredentialRevealController.php', 'PassphraseCredentialSearchEngine' => 'applications/passphrase/query/PassphraseCredentialSearchEngine.php', 'PassphraseCredentialTransaction' => 'applications/passphrase/storage/PassphraseCredentialTransaction.php', 'PassphraseCredentialTransactionEditor' => 'applications/passphrase/editor/PassphraseCredentialTransactionEditor.php', 'PassphraseCredentialTransactionQuery' => 'applications/passphrase/query/PassphraseCredentialTransactionQuery.php', 'PassphraseCredentialType' => 'applications/passphrase/credentialtype/PassphraseCredentialType.php', 'PassphraseCredentialTypeTestCase' => 'applications/passphrase/credentialtype/__tests__/PassphraseCredentialTypeTestCase.php', 'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php', 'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php', 'PassphraseDefaultEditCapability' => 'applications/passphrase/capability/PassphraseDefaultEditCapability.php', 'PassphraseDefaultViewCapability' => 'applications/passphrase/capability/PassphraseDefaultViewCapability.php', 'PassphraseNoteCredentialType' => 'applications/passphrase/credentialtype/PassphraseNoteCredentialType.php', 'PassphrasePasswordCredentialType' => 'applications/passphrase/credentialtype/PassphrasePasswordCredentialType.php', 'PassphrasePasswordKey' => 'applications/passphrase/keys/PassphrasePasswordKey.php', 'PassphraseQueryConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php', 'PassphraseRemarkupRule' => 'applications/passphrase/remarkup/PassphraseRemarkupRule.php', 'PassphraseSSHGeneratedKeyCredentialType' => 'applications/passphrase/credentialtype/PassphraseSSHGeneratedKeyCredentialType.php', 'PassphraseSSHKey' => 'applications/passphrase/keys/PassphraseSSHKey.php', 'PassphraseSSHPrivateKeyCredentialType' => 'applications/passphrase/credentialtype/PassphraseSSHPrivateKeyCredentialType.php', 'PassphraseSSHPrivateKeyFileCredentialType' => 'applications/passphrase/credentialtype/PassphraseSSHPrivateKeyFileCredentialType.php', 'PassphraseSSHPrivateKeyTextCredentialType' => 'applications/passphrase/credentialtype/PassphraseSSHPrivateKeyTextCredentialType.php', 'PassphraseSchemaSpec' => 'applications/passphrase/storage/PassphraseSchemaSpec.php', 'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php', 'PassphraseTokenCredentialType' => 'applications/passphrase/credentialtype/PassphraseTokenCredentialType.php', 'PasteConduitAPIMethod' => 'applications/paste/conduit/PasteConduitAPIMethod.php', 'PasteCreateConduitAPIMethod' => 'applications/paste/conduit/PasteCreateConduitAPIMethod.php', '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', 'PasteLanguageSelectDatasource' => 'applications/paste/typeahead/PasteLanguageSelectDatasource.php', 'PasteMailReceiver' => 'applications/paste/mail/PasteMailReceiver.php', 'PasteQueryConduitAPIMethod' => 'applications/paste/conduit/PasteQueryConduitAPIMethod.php', 'PasteReplyHandler' => 'applications/paste/mail/PasteReplyHandler.php', 'PasteSearchConduitAPIMethod' => 'applications/paste/conduit/PasteSearchConduitAPIMethod.php', 'PeopleBrowseUserDirectoryCapability' => 'applications/people/capability/PeopleBrowseUserDirectoryCapability.php', 'PeopleCreateUsersCapability' => 'applications/people/capability/PeopleCreateUsersCapability.php', 'PeopleHovercardEngineExtension' => 'applications/people/engineextension/PeopleHovercardEngineExtension.php', 'PeopleUserLogGarbageCollector' => 'applications/people/garbagecollector/PeopleUserLogGarbageCollector.php', 'Phabricator404Controller' => 'applications/base/controller/Phabricator404Controller.php', 'PhabricatorAWSConfigOptions' => 'applications/config/option/PhabricatorAWSConfigOptions.php', 'PhabricatorAccessControlTestCase' => 'applications/base/controller/__tests__/PhabricatorAccessControlTestCase.php', 'PhabricatorAccessLog' => 'infrastructure/log/PhabricatorAccessLog.php', 'PhabricatorAccessLogConfigOptions' => 'applications/config/option/PhabricatorAccessLogConfigOptions.php', 'PhabricatorAccessibilitySetting' => 'applications/settings/setting/PhabricatorAccessibilitySetting.php', 'PhabricatorAccountSettingsPanel' => 'applications/settings/panel/PhabricatorAccountSettingsPanel.php', 'PhabricatorActionListView' => 'view/layout/PhabricatorActionListView.php', 'PhabricatorActionView' => 'view/layout/PhabricatorActionView.php', 'PhabricatorActivitySettingsPanel' => 'applications/settings/panel/PhabricatorActivitySettingsPanel.php', 'PhabricatorAdministratorsPolicyRule' => 'applications/people/policyrule/PhabricatorAdministratorsPolicyRule.php', 'PhabricatorAjaxRequestExceptionHandler' => 'aphront/handler/PhabricatorAjaxRequestExceptionHandler.php', 'PhabricatorAlmanacApplication' => 'applications/almanac/application/PhabricatorAlmanacApplication.php', 'PhabricatorAmazonAuthProvider' => 'applications/auth/provider/PhabricatorAmazonAuthProvider.php', 'PhabricatorAnchorView' => 'view/layout/PhabricatorAnchorView.php', 'PhabricatorAphlictManagementDebugWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementDebugWorkflow.php', 'PhabricatorAphlictManagementRestartWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementRestartWorkflow.php', 'PhabricatorAphlictManagementStartWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementStartWorkflow.php', 'PhabricatorAphlictManagementStatusWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementStatusWorkflow.php', 'PhabricatorAphlictManagementStopWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementStopWorkflow.php', 'PhabricatorAphlictManagementWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php', 'PhabricatorAphlictSetupCheck' => 'applications/notification/setup/PhabricatorAphlictSetupCheck.php', 'PhabricatorAphrontBarUIExample' => 'applications/uiexample/examples/PhabricatorAphrontBarUIExample.php', 'PhabricatorAphrontViewTestCase' => 'view/__tests__/PhabricatorAphrontViewTestCase.php', 'PhabricatorAppSearchEngine' => 'applications/meta/query/PhabricatorAppSearchEngine.php', 'PhabricatorApplication' => 'applications/base/PhabricatorApplication.php', 'PhabricatorApplicationApplicationPHIDType' => 'applications/meta/phid/PhabricatorApplicationApplicationPHIDType.php', 'PhabricatorApplicationConfigOptions' => 'applications/config/option/PhabricatorApplicationConfigOptions.php', 'PhabricatorApplicationConfigurationPanel' => 'applications/meta/panel/PhabricatorApplicationConfigurationPanel.php', 'PhabricatorApplicationConfigurationPanelTestCase' => 'applications/meta/panel/__tests__/PhabricatorApplicationConfigurationPanelTestCase.php', 'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php', 'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php', 'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.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', - 'PhabricatorApplicationProfilePanel' => 'applications/search/profilepanel/PhabricatorApplicationProfilePanel.php', + 'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php', 'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php', 'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php', 'PhabricatorApplicationSearchEngine' => 'applications/search/engine/PhabricatorApplicationSearchEngine.php', 'PhabricatorApplicationSearchEngineTestCase' => 'applications/search/engine/__tests__/PhabricatorApplicationSearchEngineTestCase.php', 'PhabricatorApplicationSearchResultView' => 'applications/search/view/PhabricatorApplicationSearchResultView.php', 'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php', 'PhabricatorApplicationTestCase' => 'applications/base/__tests__/PhabricatorApplicationTestCase.php', 'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php', 'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php', 'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php', 'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php', 'PhabricatorApplicationTransactionCommentHistoryController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php', 'PhabricatorApplicationTransactionCommentQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php', 'PhabricatorApplicationTransactionCommentQuoteController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentQuoteController.php', 'PhabricatorApplicationTransactionCommentRawController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentRawController.php', 'PhabricatorApplicationTransactionCommentRemoveController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentRemoveController.php', 'PhabricatorApplicationTransactionCommentView' => 'applications/transactions/view/PhabricatorApplicationTransactionCommentView.php', 'PhabricatorApplicationTransactionController' => 'applications/transactions/controller/PhabricatorApplicationTransactionController.php', 'PhabricatorApplicationTransactionDetailController' => 'applications/transactions/controller/PhabricatorApplicationTransactionDetailController.php', 'PhabricatorApplicationTransactionEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionEditor.php', 'PhabricatorApplicationTransactionFeedStory' => 'applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php', 'PhabricatorApplicationTransactionInterface' => 'applications/transactions/interface/PhabricatorApplicationTransactionInterface.php', 'PhabricatorApplicationTransactionNoEffectException' => 'applications/transactions/exception/PhabricatorApplicationTransactionNoEffectException.php', 'PhabricatorApplicationTransactionNoEffectResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php', 'PhabricatorApplicationTransactionPublishWorker' => 'applications/transactions/worker/PhabricatorApplicationTransactionPublishWorker.php', 'PhabricatorApplicationTransactionQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionQuery.php', 'PhabricatorApplicationTransactionRemarkupPreviewController' => 'applications/transactions/controller/PhabricatorApplicationTransactionRemarkupPreviewController.php', 'PhabricatorApplicationTransactionReplyHandler' => 'applications/transactions/replyhandler/PhabricatorApplicationTransactionReplyHandler.php', 'PhabricatorApplicationTransactionResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionResponse.php', 'PhabricatorApplicationTransactionShowOlderController' => 'applications/transactions/controller/PhabricatorApplicationTransactionShowOlderController.php', 'PhabricatorApplicationTransactionStructureException' => 'applications/transactions/exception/PhabricatorApplicationTransactionStructureException.php', 'PhabricatorApplicationTransactionTemplatedCommentQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionTemplatedCommentQuery.php', 'PhabricatorApplicationTransactionTextDiffDetailView' => 'applications/transactions/view/PhabricatorApplicationTransactionTextDiffDetailView.php', 'PhabricatorApplicationTransactionTransactionPHIDType' => 'applications/transactions/phid/PhabricatorApplicationTransactionTransactionPHIDType.php', 'PhabricatorApplicationTransactionValidationError' => 'applications/transactions/error/PhabricatorApplicationTransactionValidationError.php', 'PhabricatorApplicationTransactionValidationException' => 'applications/transactions/exception/PhabricatorApplicationTransactionValidationException.php', 'PhabricatorApplicationTransactionValidationResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionValidationResponse.php', 'PhabricatorApplicationTransactionValueController' => 'applications/transactions/controller/PhabricatorApplicationTransactionValueController.php', 'PhabricatorApplicationTransactionView' => 'applications/transactions/view/PhabricatorApplicationTransactionView.php', 'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php', 'PhabricatorApplicationsApplication' => 'applications/meta/application/PhabricatorApplicationsApplication.php', 'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php', 'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php', 'PhabricatorAsanaAuthProvider' => 'applications/auth/provider/PhabricatorAsanaAuthProvider.php', 'PhabricatorAsanaConfigOptions' => 'applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php', 'PhabricatorAsanaSubtaskHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorAsanaSubtaskHasObjectEdgeType.php', 'PhabricatorAsanaTaskHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorAsanaTaskHasObjectEdgeType.php', 'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php', 'PhabricatorAuditAddCommentController' => 'applications/audit/controller/PhabricatorAuditAddCommentController.php', 'PhabricatorAuditApplication' => 'applications/audit/application/PhabricatorAuditApplication.php', 'PhabricatorAuditCommentEditor' => 'applications/audit/editor/PhabricatorAuditCommentEditor.php', 'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/PhabricatorAuditCommitStatusConstants.php', 'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php', 'PhabricatorAuditEditor' => 'applications/audit/editor/PhabricatorAuditEditor.php', 'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.php', 'PhabricatorAuditListController' => 'applications/audit/controller/PhabricatorAuditListController.php', 'PhabricatorAuditListView' => 'applications/audit/view/PhabricatorAuditListView.php', 'PhabricatorAuditMailReceiver' => 'applications/audit/mail/PhabricatorAuditMailReceiver.php', 'PhabricatorAuditManagementDeleteWorkflow' => 'applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php', 'PhabricatorAuditManagementWorkflow' => 'applications/audit/management/PhabricatorAuditManagementWorkflow.php', 'PhabricatorAuditPreviewController' => 'applications/audit/controller/PhabricatorAuditPreviewController.php', 'PhabricatorAuditReplyHandler' => 'applications/audit/mail/PhabricatorAuditReplyHandler.php', 'PhabricatorAuditStatusConstants' => 'applications/audit/constants/PhabricatorAuditStatusConstants.php', 'PhabricatorAuditTransaction' => 'applications/audit/storage/PhabricatorAuditTransaction.php', 'PhabricatorAuditTransactionComment' => 'applications/audit/storage/PhabricatorAuditTransactionComment.php', 'PhabricatorAuditTransactionQuery' => 'applications/audit/query/PhabricatorAuditTransactionQuery.php', 'PhabricatorAuditTransactionView' => 'applications/audit/view/PhabricatorAuditTransactionView.php', 'PhabricatorAuthAccountView' => 'applications/auth/view/PhabricatorAuthAccountView.php', 'PhabricatorAuthApplication' => 'applications/auth/application/PhabricatorAuthApplication.php', 'PhabricatorAuthAuthFactorPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php', 'PhabricatorAuthAuthProviderPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php', 'PhabricatorAuthConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthConduitAPIMethod.php', 'PhabricatorAuthConfirmLinkController' => 'applications/auth/controller/PhabricatorAuthConfirmLinkController.php', 'PhabricatorAuthController' => 'applications/auth/controller/PhabricatorAuthController.php', 'PhabricatorAuthDAO' => 'applications/auth/storage/PhabricatorAuthDAO.php', 'PhabricatorAuthDisableController' => 'applications/auth/controller/config/PhabricatorAuthDisableController.php', 'PhabricatorAuthDowngradeSessionController' => 'applications/auth/controller/PhabricatorAuthDowngradeSessionController.php', 'PhabricatorAuthEditController' => 'applications/auth/controller/config/PhabricatorAuthEditController.php', 'PhabricatorAuthFactor' => 'applications/auth/factor/PhabricatorAuthFactor.php', 'PhabricatorAuthFactorConfig' => 'applications/auth/storage/PhabricatorAuthFactorConfig.php', 'PhabricatorAuthFactorTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthFactorTestCase.php', 'PhabricatorAuthFinishController' => 'applications/auth/controller/PhabricatorAuthFinishController.php', 'PhabricatorAuthHighSecurityRequiredException' => 'applications/auth/exception/PhabricatorAuthHighSecurityRequiredException.php', 'PhabricatorAuthHighSecurityToken' => 'applications/auth/data/PhabricatorAuthHighSecurityToken.php', 'PhabricatorAuthInvite' => 'applications/auth/storage/PhabricatorAuthInvite.php', 'PhabricatorAuthInviteAccountException' => 'applications/auth/exception/PhabricatorAuthInviteAccountException.php', 'PhabricatorAuthInviteAction' => 'applications/auth/data/PhabricatorAuthInviteAction.php', 'PhabricatorAuthInviteActionTableView' => 'applications/auth/view/PhabricatorAuthInviteActionTableView.php', 'PhabricatorAuthInviteController' => 'applications/auth/controller/PhabricatorAuthInviteController.php', 'PhabricatorAuthInviteDialogException' => 'applications/auth/exception/PhabricatorAuthInviteDialogException.php', 'PhabricatorAuthInviteEngine' => 'applications/auth/engine/PhabricatorAuthInviteEngine.php', 'PhabricatorAuthInviteException' => 'applications/auth/exception/PhabricatorAuthInviteException.php', 'PhabricatorAuthInviteInvalidException' => 'applications/auth/exception/PhabricatorAuthInviteInvalidException.php', 'PhabricatorAuthInviteLoginException' => 'applications/auth/exception/PhabricatorAuthInviteLoginException.php', 'PhabricatorAuthInvitePHIDType' => 'applications/auth/phid/PhabricatorAuthInvitePHIDType.php', 'PhabricatorAuthInviteQuery' => 'applications/auth/query/PhabricatorAuthInviteQuery.php', 'PhabricatorAuthInviteRegisteredException' => 'applications/auth/exception/PhabricatorAuthInviteRegisteredException.php', 'PhabricatorAuthInviteSearchEngine' => 'applications/auth/query/PhabricatorAuthInviteSearchEngine.php', 'PhabricatorAuthInviteTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthInviteTestCase.php', 'PhabricatorAuthInviteVerifyException' => 'applications/auth/exception/PhabricatorAuthInviteVerifyException.php', 'PhabricatorAuthInviteWorker' => 'applications/auth/worker/PhabricatorAuthInviteWorker.php', 'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php', 'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php', 'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php', 'PhabricatorAuthLoginHandler' => 'applications/auth/handler/PhabricatorAuthLoginHandler.php', 'PhabricatorAuthLogoutConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthLogoutConduitAPIMethod.php', 'PhabricatorAuthMainMenuBarExtension' => 'applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php', 'PhabricatorAuthManagementCachePKCS8Workflow' => 'applications/auth/management/PhabricatorAuthManagementCachePKCS8Workflow.php', 'PhabricatorAuthManagementLDAPWorkflow' => 'applications/auth/management/PhabricatorAuthManagementLDAPWorkflow.php', 'PhabricatorAuthManagementListFactorsWorkflow' => 'applications/auth/management/PhabricatorAuthManagementListFactorsWorkflow.php', 'PhabricatorAuthManagementRecoverWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRecoverWorkflow.php', 'PhabricatorAuthManagementRefreshWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php', 'PhabricatorAuthManagementStripWorkflow' => 'applications/auth/management/PhabricatorAuthManagementStripWorkflow.php', 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementTrustOAuthClientWorkflow.php', 'PhabricatorAuthManagementUnlimitWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUnlimitWorkflow.php', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php', 'PhabricatorAuthManagementVerifyWorkflow' => 'applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php', 'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php', 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', 'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php', 'PhabricatorAuthOldOAuthRedirectController' => 'applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php', 'PhabricatorAuthOneTimeLoginController' => 'applications/auth/controller/PhabricatorAuthOneTimeLoginController.php', 'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthOneTimeLoginTemporaryTokenType.php', 'PhabricatorAuthPasswordResetTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthPasswordResetTemporaryTokenType.php', 'PhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorAuthProvider.php', 'PhabricatorAuthProviderConfig' => 'applications/auth/storage/PhabricatorAuthProviderConfig.php', 'PhabricatorAuthProviderConfigController' => 'applications/auth/controller/config/PhabricatorAuthProviderConfigController.php', 'PhabricatorAuthProviderConfigEditor' => 'applications/auth/editor/PhabricatorAuthProviderConfigEditor.php', 'PhabricatorAuthProviderConfigQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigQuery.php', 'PhabricatorAuthProviderConfigTransaction' => 'applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php', 'PhabricatorAuthProviderConfigTransactionQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigTransactionQuery.php', 'PhabricatorAuthProvidersGuidanceContext' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceContext.php', 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php', 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthQueryPublicKeysConduitAPIMethod.php', 'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php', 'PhabricatorAuthRevokeTokenController' => 'applications/auth/controller/PhabricatorAuthRevokeTokenController.php', 'PhabricatorAuthSSHKey' => 'applications/auth/storage/PhabricatorAuthSSHKey.php', 'PhabricatorAuthSSHKeyController' => 'applications/auth/controller/PhabricatorAuthSSHKeyController.php', 'PhabricatorAuthSSHKeyDeactivateController' => 'applications/auth/controller/PhabricatorAuthSSHKeyDeactivateController.php', 'PhabricatorAuthSSHKeyEditController' => 'applications/auth/controller/PhabricatorAuthSSHKeyEditController.php', 'PhabricatorAuthSSHKeyEditor' => 'applications/auth/editor/PhabricatorAuthSSHKeyEditor.php', 'PhabricatorAuthSSHKeyGenerateController' => 'applications/auth/controller/PhabricatorAuthSSHKeyGenerateController.php', 'PhabricatorAuthSSHKeyListController' => 'applications/auth/controller/PhabricatorAuthSSHKeyListController.php', 'PhabricatorAuthSSHKeyPHIDType' => 'applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php', 'PhabricatorAuthSSHKeyQuery' => 'applications/auth/query/PhabricatorAuthSSHKeyQuery.php', 'PhabricatorAuthSSHKeyReplyHandler' => 'applications/auth/mail/PhabricatorAuthSSHKeyReplyHandler.php', 'PhabricatorAuthSSHKeySearchEngine' => 'applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php', 'PhabricatorAuthSSHKeyTableView' => 'applications/auth/view/PhabricatorAuthSSHKeyTableView.php', 'PhabricatorAuthSSHKeyTransaction' => 'applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php', 'PhabricatorAuthSSHKeyTransactionQuery' => 'applications/auth/query/PhabricatorAuthSSHKeyTransactionQuery.php', 'PhabricatorAuthSSHKeyViewController' => 'applications/auth/controller/PhabricatorAuthSSHKeyViewController.php', 'PhabricatorAuthSSHPublicKey' => 'applications/auth/sshkey/PhabricatorAuthSSHPublicKey.php', 'PhabricatorAuthSession' => 'applications/auth/storage/PhabricatorAuthSession.php', 'PhabricatorAuthSessionEngine' => 'applications/auth/engine/PhabricatorAuthSessionEngine.php', 'PhabricatorAuthSessionEngineExtension' => 'applications/auth/engine/PhabricatorAuthSessionEngineExtension.php', 'PhabricatorAuthSessionEngineExtensionModule' => 'applications/auth/engine/PhabricatorAuthSessionEngineExtensionModule.php', 'PhabricatorAuthSessionGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthSessionGarbageCollector.php', 'PhabricatorAuthSessionInfo' => 'applications/auth/data/PhabricatorAuthSessionInfo.php', 'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php', 'PhabricatorAuthSetupCheck' => 'applications/config/check/PhabricatorAuthSetupCheck.php', 'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php', 'PhabricatorAuthTOTPKeyTemporaryTokenType' => 'applications/auth/factor/PhabricatorAuthTOTPKeyTemporaryTokenType.php', 'PhabricatorAuthTemporaryToken' => 'applications/auth/storage/PhabricatorAuthTemporaryToken.php', 'PhabricatorAuthTemporaryTokenGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthTemporaryTokenGarbageCollector.php', 'PhabricatorAuthTemporaryTokenQuery' => 'applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php', 'PhabricatorAuthTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthTemporaryTokenType.php', 'PhabricatorAuthTemporaryTokenTypeModule' => 'applications/auth/tokentype/PhabricatorAuthTemporaryTokenTypeModule.php', 'PhabricatorAuthTerminateSessionController' => 'applications/auth/controller/PhabricatorAuthTerminateSessionController.php', 'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php', 'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php', 'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php', 'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php', 'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.php', 'PhabricatorBadgeHasRecipientEdgeType' => 'applications/badges/edge/PhabricatorBadgeHasRecipientEdgeType.php', 'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php', 'PhabricatorBadgesArchiveController' => 'applications/badges/controller/PhabricatorBadgesArchiveController.php', 'PhabricatorBadgesAward' => 'applications/badges/storage/PhabricatorBadgesAward.php', 'PhabricatorBadgesAwardController' => 'applications/badges/controller/PhabricatorBadgesAwardController.php', 'PhabricatorBadgesAwardQuery' => 'applications/badges/query/PhabricatorBadgesAwardQuery.php', 'PhabricatorBadgesBadge' => 'applications/badges/storage/PhabricatorBadgesBadge.php', 'PhabricatorBadgesBadgeNameNgrams' => 'applications/badges/storage/PhabricatorBadgesBadgeNameNgrams.php', 'PhabricatorBadgesCommentController' => 'applications/badges/controller/PhabricatorBadgesCommentController.php', 'PhabricatorBadgesController' => 'applications/badges/controller/PhabricatorBadgesController.php', 'PhabricatorBadgesCreateCapability' => 'applications/badges/capability/PhabricatorBadgesCreateCapability.php', 'PhabricatorBadgesDAO' => 'applications/badges/storage/PhabricatorBadgesDAO.php', 'PhabricatorBadgesDatasource' => 'applications/badges/typeahead/PhabricatorBadgesDatasource.php', 'PhabricatorBadgesDefaultEditCapability' => 'applications/badges/capability/PhabricatorBadgesDefaultEditCapability.php', 'PhabricatorBadgesEditConduitAPIMethod' => 'applications/badges/conduit/PhabricatorBadgesEditConduitAPIMethod.php', 'PhabricatorBadgesEditController' => 'applications/badges/controller/PhabricatorBadgesEditController.php', 'PhabricatorBadgesEditEngine' => 'applications/badges/editor/PhabricatorBadgesEditEngine.php', 'PhabricatorBadgesEditRecipientsController' => 'applications/badges/controller/PhabricatorBadgesEditRecipientsController.php', 'PhabricatorBadgesEditor' => 'applications/badges/editor/PhabricatorBadgesEditor.php', 'PhabricatorBadgesIconSet' => 'applications/badges/icon/PhabricatorBadgesIconSet.php', 'PhabricatorBadgesListController' => 'applications/badges/controller/PhabricatorBadgesListController.php', 'PhabricatorBadgesMailReceiver' => 'applications/badges/mail/PhabricatorBadgesMailReceiver.php', 'PhabricatorBadgesPHIDType' => 'applications/badges/phid/PhabricatorBadgesPHIDType.php', 'PhabricatorBadgesQuality' => 'applications/badges/constants/PhabricatorBadgesQuality.php', 'PhabricatorBadgesQuery' => 'applications/badges/query/PhabricatorBadgesQuery.php', 'PhabricatorBadgesRecipientsListView' => 'applications/badges/view/PhabricatorBadgesRecipientsListView.php', 'PhabricatorBadgesRemoveRecipientsController' => 'applications/badges/controller/PhabricatorBadgesRemoveRecipientsController.php', 'PhabricatorBadgesReplyHandler' => 'applications/badges/mail/PhabricatorBadgesReplyHandler.php', 'PhabricatorBadgesSchemaSpec' => 'applications/badges/storage/PhabricatorBadgesSchemaSpec.php', 'PhabricatorBadgesSearchConduitAPIMethod' => 'applications/badges/conduit/PhabricatorBadgesSearchConduitAPIMethod.php', 'PhabricatorBadgesSearchEngine' => 'applications/badges/query/PhabricatorBadgesSearchEngine.php', 'PhabricatorBadgesTransaction' => 'applications/badges/storage/PhabricatorBadgesTransaction.php', 'PhabricatorBadgesTransactionComment' => 'applications/badges/storage/PhabricatorBadgesTransactionComment.php', 'PhabricatorBadgesTransactionQuery' => 'applications/badges/query/PhabricatorBadgesTransactionQuery.php', 'PhabricatorBadgesViewController' => 'applications/badges/controller/PhabricatorBadgesViewController.php', 'PhabricatorBarePageUIExample' => 'applications/uiexample/examples/PhabricatorBarePageUIExample.php', 'PhabricatorBarePageView' => 'view/page/PhabricatorBarePageView.php', 'PhabricatorBaseURISetupCheck' => 'applications/config/check/PhabricatorBaseURISetupCheck.php', 'PhabricatorBcryptPasswordHasher' => 'infrastructure/util/password/PhabricatorBcryptPasswordHasher.php', 'PhabricatorBinariesSetupCheck' => 'applications/config/check/PhabricatorBinariesSetupCheck.php', 'PhabricatorBitbucketAuthProvider' => 'applications/auth/provider/PhabricatorBitbucketAuthProvider.php', 'PhabricatorBoardLayoutEngine' => 'applications/project/engine/PhabricatorBoardLayoutEngine.php', 'PhabricatorBoardRenderingEngine' => 'applications/project/engine/PhabricatorBoardRenderingEngine.php', 'PhabricatorBoardResponseEngine' => 'applications/project/engine/PhabricatorBoardResponseEngine.php', 'PhabricatorBoolEditField' => 'applications/transactions/editfield/PhabricatorBoolEditField.php', 'PhabricatorBot' => 'infrastructure/daemon/bot/PhabricatorBot.php', 'PhabricatorBotChannel' => 'infrastructure/daemon/bot/target/PhabricatorBotChannel.php', 'PhabricatorBotDebugLogHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotDebugLogHandler.php', 'PhabricatorBotFeedNotificationHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotFeedNotificationHandler.php', 'PhabricatorBotFlowdockProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorBotFlowdockProtocolAdapter.php', 'PhabricatorBotHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotHandler.php', 'PhabricatorBotLogHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotLogHandler.php', 'PhabricatorBotMacroHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotMacroHandler.php', 'PhabricatorBotMessage' => 'infrastructure/daemon/bot/PhabricatorBotMessage.php', 'PhabricatorBotObjectNameHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php', 'PhabricatorBotSymbolHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotSymbolHandler.php', 'PhabricatorBotTarget' => 'infrastructure/daemon/bot/target/PhabricatorBotTarget.php', 'PhabricatorBotUser' => 'infrastructure/daemon/bot/target/PhabricatorBotUser.php', 'PhabricatorBotWhatsNewHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.php', 'PhabricatorBritishEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorBritishEnglishTranslation.php', 'PhabricatorBuiltinPatchList' => 'infrastructure/storage/patch/PhabricatorBuiltinPatchList.php', 'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php', 'PhabricatorBusyUIExample' => 'applications/uiexample/examples/PhabricatorBusyUIExample.php', 'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php', 'PhabricatorCacheEngine' => 'applications/system/engine/PhabricatorCacheEngine.php', 'PhabricatorCacheEngineExtension' => 'applications/system/engine/PhabricatorCacheEngineExtension.php', 'PhabricatorCacheGeneralGarbageCollector' => 'applications/cache/garbagecollector/PhabricatorCacheGeneralGarbageCollector.php', 'PhabricatorCacheManagementPurgeWorkflow' => 'applications/cache/management/PhabricatorCacheManagementPurgeWorkflow.php', 'PhabricatorCacheManagementWorkflow' => 'applications/cache/management/PhabricatorCacheManagementWorkflow.php', 'PhabricatorCacheMarkupGarbageCollector' => 'applications/cache/garbagecollector/PhabricatorCacheMarkupGarbageCollector.php', 'PhabricatorCacheSchemaSpec' => 'applications/cache/storage/PhabricatorCacheSchemaSpec.php', 'PhabricatorCacheSetupCheck' => 'applications/config/check/PhabricatorCacheSetupCheck.php', 'PhabricatorCacheSpec' => 'applications/cache/spec/PhabricatorCacheSpec.php', 'PhabricatorCacheTTLGarbageCollector' => 'applications/cache/garbagecollector/PhabricatorCacheTTLGarbageCollector.php', 'PhabricatorCachedClassMapQuery' => 'applications/cache/PhabricatorCachedClassMapQuery.php', 'PhabricatorCaches' => 'applications/cache/PhabricatorCaches.php', 'PhabricatorCachesTestCase' => 'applications/cache/__tests__/PhabricatorCachesTestCase.php', 'PhabricatorCalendarApplication' => 'applications/calendar/application/PhabricatorCalendarApplication.php', 'PhabricatorCalendarController' => 'applications/calendar/controller/PhabricatorCalendarController.php', 'PhabricatorCalendarDAO' => 'applications/calendar/storage/PhabricatorCalendarDAO.php', 'PhabricatorCalendarEvent' => 'applications/calendar/storage/PhabricatorCalendarEvent.php', 'PhabricatorCalendarEventAcceptTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventAcceptTransaction.php', 'PhabricatorCalendarEventAllDayTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventAllDayTransaction.php', 'PhabricatorCalendarEventAvailabilityController' => 'applications/calendar/controller/PhabricatorCalendarEventAvailabilityController.php', 'PhabricatorCalendarEventCancelController' => 'applications/calendar/controller/PhabricatorCalendarEventCancelController.php', 'PhabricatorCalendarEventCancelTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventCancelTransaction.php', 'PhabricatorCalendarEventDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDateTransaction.php', 'PhabricatorCalendarEventDeclineTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDeclineTransaction.php', 'PhabricatorCalendarEventDefaultEditCapability' => 'applications/calendar/capability/PhabricatorCalendarEventDefaultEditCapability.php', 'PhabricatorCalendarEventDefaultViewCapability' => 'applications/calendar/capability/PhabricatorCalendarEventDefaultViewCapability.php', 'PhabricatorCalendarEventDescriptionTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventDescriptionTransaction.php', 'PhabricatorCalendarEventDragController' => 'applications/calendar/controller/PhabricatorCalendarEventDragController.php', 'PhabricatorCalendarEventEditConduitAPIMethod' => 'applications/calendar/conduit/PhabricatorCalendarEventEditConduitAPIMethod.php', 'PhabricatorCalendarEventEditController' => 'applications/calendar/controller/PhabricatorCalendarEventEditController.php', 'PhabricatorCalendarEventEditEngine' => 'applications/calendar/editor/PhabricatorCalendarEventEditEngine.php', 'PhabricatorCalendarEventEditor' => 'applications/calendar/editor/PhabricatorCalendarEventEditor.php', 'PhabricatorCalendarEventEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventEmailCommand.php', 'PhabricatorCalendarEventEndDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php', 'PhabricatorCalendarEventExportController' => 'applications/calendar/controller/PhabricatorCalendarEventExportController.php', 'PhabricatorCalendarEventForkTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventForkTransaction.php', 'PhabricatorCalendarEventFrequencyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventFrequencyTransaction.php', 'PhabricatorCalendarEventFulltextEngine' => 'applications/calendar/search/PhabricatorCalendarEventFulltextEngine.php', 'PhabricatorCalendarEventHeraldAdapter' => 'applications/calendar/herald/PhabricatorCalendarEventHeraldAdapter.php', 'PhabricatorCalendarEventHeraldField' => 'applications/calendar/herald/PhabricatorCalendarEventHeraldField.php', 'PhabricatorCalendarEventHeraldFieldGroup' => 'applications/calendar/herald/PhabricatorCalendarEventHeraldFieldGroup.php', 'PhabricatorCalendarEventHostPolicyRule' => 'applications/calendar/policyrule/PhabricatorCalendarEventHostPolicyRule.php', 'PhabricatorCalendarEventHostTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventHostTransaction.php', 'PhabricatorCalendarEventIconTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventIconTransaction.php', 'PhabricatorCalendarEventInviteTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventInviteTransaction.php', 'PhabricatorCalendarEventInvitee' => 'applications/calendar/storage/PhabricatorCalendarEventInvitee.php', 'PhabricatorCalendarEventInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarEventInviteeQuery.php', 'PhabricatorCalendarEventInviteesPolicyRule' => 'applications/calendar/policyrule/PhabricatorCalendarEventInviteesPolicyRule.php', 'PhabricatorCalendarEventJoinController' => 'applications/calendar/controller/PhabricatorCalendarEventJoinController.php', 'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php', 'PhabricatorCalendarEventMailReceiver' => 'applications/calendar/mail/PhabricatorCalendarEventMailReceiver.php', 'PhabricatorCalendarEventNameHeraldField' => 'applications/calendar/herald/PhabricatorCalendarEventNameHeraldField.php', 'PhabricatorCalendarEventNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventNameTransaction.php', 'PhabricatorCalendarEventNotificationView' => 'applications/calendar/notifications/PhabricatorCalendarEventNotificationView.php', 'PhabricatorCalendarEventPHIDType' => 'applications/calendar/phid/PhabricatorCalendarEventPHIDType.php', 'PhabricatorCalendarEventPolicyCodex' => 'applications/calendar/codex/PhabricatorCalendarEventPolicyCodex.php', 'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php', 'PhabricatorCalendarEventRSVPEmailCommand' => 'applications/calendar/command/PhabricatorCalendarEventRSVPEmailCommand.php', 'PhabricatorCalendarEventRecurringTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventRecurringTransaction.php', 'PhabricatorCalendarEventReplyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventReplyTransaction.php', 'PhabricatorCalendarEventSearchConduitAPIMethod' => 'applications/calendar/conduit/PhabricatorCalendarEventSearchConduitAPIMethod.php', 'PhabricatorCalendarEventSearchEngine' => 'applications/calendar/query/PhabricatorCalendarEventSearchEngine.php', 'PhabricatorCalendarEventStartDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php', 'PhabricatorCalendarEventTransaction' => 'applications/calendar/storage/PhabricatorCalendarEventTransaction.php', 'PhabricatorCalendarEventTransactionComment' => 'applications/calendar/storage/PhabricatorCalendarEventTransactionComment.php', 'PhabricatorCalendarEventTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarEventTransactionQuery.php', 'PhabricatorCalendarEventTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarEventTransactionType.php', 'PhabricatorCalendarEventUntilDateTransaction' => 'applications/calendar/xaction/PhabricatorCalendarEventUntilDateTransaction.php', 'PhabricatorCalendarEventViewController' => 'applications/calendar/controller/PhabricatorCalendarEventViewController.php', 'PhabricatorCalendarExport' => 'applications/calendar/storage/PhabricatorCalendarExport.php', 'PhabricatorCalendarExportDisableController' => 'applications/calendar/controller/PhabricatorCalendarExportDisableController.php', 'PhabricatorCalendarExportDisableTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportDisableTransaction.php', 'PhabricatorCalendarExportEditController' => 'applications/calendar/controller/PhabricatorCalendarExportEditController.php', 'PhabricatorCalendarExportEditEngine' => 'applications/calendar/editor/PhabricatorCalendarExportEditEngine.php', 'PhabricatorCalendarExportEditor' => 'applications/calendar/editor/PhabricatorCalendarExportEditor.php', 'PhabricatorCalendarExportICSController' => 'applications/calendar/controller/PhabricatorCalendarExportICSController.php', 'PhabricatorCalendarExportListController' => 'applications/calendar/controller/PhabricatorCalendarExportListController.php', 'PhabricatorCalendarExportModeTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportModeTransaction.php', 'PhabricatorCalendarExportNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportNameTransaction.php', 'PhabricatorCalendarExportPHIDType' => 'applications/calendar/phid/PhabricatorCalendarExportPHIDType.php', 'PhabricatorCalendarExportQuery' => 'applications/calendar/query/PhabricatorCalendarExportQuery.php', 'PhabricatorCalendarExportQueryKeyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarExportQueryKeyTransaction.php', 'PhabricatorCalendarExportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarExportSearchEngine.php', 'PhabricatorCalendarExportTransaction' => 'applications/calendar/storage/PhabricatorCalendarExportTransaction.php', 'PhabricatorCalendarExportTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarExportTransactionQuery.php', 'PhabricatorCalendarExportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarExportTransactionType.php', 'PhabricatorCalendarExportViewController' => 'applications/calendar/controller/PhabricatorCalendarExportViewController.php', 'PhabricatorCalendarExternalInvitee' => 'applications/calendar/storage/PhabricatorCalendarExternalInvitee.php', 'PhabricatorCalendarExternalInviteePHIDType' => 'applications/calendar/phid/PhabricatorCalendarExternalInviteePHIDType.php', 'PhabricatorCalendarExternalInviteeQuery' => 'applications/calendar/query/PhabricatorCalendarExternalInviteeQuery.php', 'PhabricatorCalendarICSFileImportEngine' => 'applications/calendar/import/PhabricatorCalendarICSFileImportEngine.php', 'PhabricatorCalendarICSImportEngine' => 'applications/calendar/import/PhabricatorCalendarICSImportEngine.php', 'PhabricatorCalendarICSURIImportEngine' => 'applications/calendar/import/PhabricatorCalendarICSURIImportEngine.php', 'PhabricatorCalendarICSWriter' => 'applications/calendar/util/PhabricatorCalendarICSWriter.php', 'PhabricatorCalendarIconSet' => 'applications/calendar/icon/PhabricatorCalendarIconSet.php', 'PhabricatorCalendarImport' => 'applications/calendar/storage/PhabricatorCalendarImport.php', 'PhabricatorCalendarImportDefaultLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDefaultLogType.php', 'PhabricatorCalendarImportDeleteController' => 'applications/calendar/controller/PhabricatorCalendarImportDeleteController.php', 'PhabricatorCalendarImportDeleteLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDeleteLogType.php', 'PhabricatorCalendarImportDeleteTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportDeleteTransaction.php', 'PhabricatorCalendarImportDisableController' => 'applications/calendar/controller/PhabricatorCalendarImportDisableController.php', 'PhabricatorCalendarImportDisableTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportDisableTransaction.php', 'PhabricatorCalendarImportDropController' => 'applications/calendar/controller/PhabricatorCalendarImportDropController.php', 'PhabricatorCalendarImportDuplicateLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportDuplicateLogType.php', 'PhabricatorCalendarImportEditController' => 'applications/calendar/controller/PhabricatorCalendarImportEditController.php', 'PhabricatorCalendarImportEditEngine' => 'applications/calendar/editor/PhabricatorCalendarImportEditEngine.php', 'PhabricatorCalendarImportEditor' => 'applications/calendar/editor/PhabricatorCalendarImportEditor.php', 'PhabricatorCalendarImportEmptyLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportEmptyLogType.php', 'PhabricatorCalendarImportEngine' => 'applications/calendar/import/PhabricatorCalendarImportEngine.php', 'PhabricatorCalendarImportEpochLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportEpochLogType.php', 'PhabricatorCalendarImportFetchLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportFetchLogType.php', 'PhabricatorCalendarImportFrequencyLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportFrequencyLogType.php', 'PhabricatorCalendarImportFrequencyTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportFrequencyTransaction.php', 'PhabricatorCalendarImportICSFileTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportICSFileTransaction.php', 'PhabricatorCalendarImportICSLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportICSLogType.php', 'PhabricatorCalendarImportICSURITransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportICSURITransaction.php', 'PhabricatorCalendarImportICSWarningLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportICSWarningLogType.php', 'PhabricatorCalendarImportIgnoredNodeLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportIgnoredNodeLogType.php', 'PhabricatorCalendarImportListController' => 'applications/calendar/controller/PhabricatorCalendarImportListController.php', 'PhabricatorCalendarImportLog' => 'applications/calendar/storage/PhabricatorCalendarImportLog.php', 'PhabricatorCalendarImportLogListController' => 'applications/calendar/controller/PhabricatorCalendarImportLogListController.php', 'PhabricatorCalendarImportLogQuery' => 'applications/calendar/query/PhabricatorCalendarImportLogQuery.php', 'PhabricatorCalendarImportLogSearchEngine' => 'applications/calendar/query/PhabricatorCalendarImportLogSearchEngine.php', 'PhabricatorCalendarImportLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportLogType.php', 'PhabricatorCalendarImportLogView' => 'applications/calendar/view/PhabricatorCalendarImportLogView.php', 'PhabricatorCalendarImportNameTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportNameTransaction.php', 'PhabricatorCalendarImportOriginalLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportOriginalLogType.php', 'PhabricatorCalendarImportOrphanLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportOrphanLogType.php', 'PhabricatorCalendarImportPHIDType' => 'applications/calendar/phid/PhabricatorCalendarImportPHIDType.php', 'PhabricatorCalendarImportQuery' => 'applications/calendar/query/PhabricatorCalendarImportQuery.php', 'PhabricatorCalendarImportQueueLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportQueueLogType.php', 'PhabricatorCalendarImportReloadController' => 'applications/calendar/controller/PhabricatorCalendarImportReloadController.php', 'PhabricatorCalendarImportReloadTransaction' => 'applications/calendar/xaction/PhabricatorCalendarImportReloadTransaction.php', 'PhabricatorCalendarImportReloadWorker' => 'applications/calendar/worker/PhabricatorCalendarImportReloadWorker.php', 'PhabricatorCalendarImportSearchEngine' => 'applications/calendar/query/PhabricatorCalendarImportSearchEngine.php', 'PhabricatorCalendarImportTransaction' => 'applications/calendar/storage/PhabricatorCalendarImportTransaction.php', 'PhabricatorCalendarImportTransactionQuery' => 'applications/calendar/query/PhabricatorCalendarImportTransactionQuery.php', 'PhabricatorCalendarImportTransactionType' => 'applications/calendar/xaction/PhabricatorCalendarImportTransactionType.php', 'PhabricatorCalendarImportTriggerLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportTriggerLogType.php', 'PhabricatorCalendarImportUpdateLogType' => 'applications/calendar/importlog/PhabricatorCalendarImportUpdateLogType.php', 'PhabricatorCalendarImportViewController' => 'applications/calendar/controller/PhabricatorCalendarImportViewController.php', 'PhabricatorCalendarInviteeDatasource' => 'applications/calendar/typeahead/PhabricatorCalendarInviteeDatasource.php', 'PhabricatorCalendarInviteeUserDatasource' => 'applications/calendar/typeahead/PhabricatorCalendarInviteeUserDatasource.php', 'PhabricatorCalendarInviteeViewerFunctionDatasource' => 'applications/calendar/typeahead/PhabricatorCalendarInviteeViewerFunctionDatasource.php', 'PhabricatorCalendarManagementNotifyWorkflow' => 'applications/calendar/management/PhabricatorCalendarManagementNotifyWorkflow.php', 'PhabricatorCalendarManagementReloadWorkflow' => 'applications/calendar/management/PhabricatorCalendarManagementReloadWorkflow.php', 'PhabricatorCalendarManagementWorkflow' => 'applications/calendar/management/PhabricatorCalendarManagementWorkflow.php', 'PhabricatorCalendarNotification' => 'applications/calendar/storage/PhabricatorCalendarNotification.php', 'PhabricatorCalendarNotificationEngine' => 'applications/calendar/notifications/PhabricatorCalendarNotificationEngine.php', 'PhabricatorCalendarRemarkupRule' => 'applications/calendar/remarkup/PhabricatorCalendarRemarkupRule.php', 'PhabricatorCalendarReplyHandler' => 'applications/calendar/mail/PhabricatorCalendarReplyHandler.php', 'PhabricatorCalendarSchemaSpec' => 'applications/calendar/storage/PhabricatorCalendarSchemaSpec.php', 'PhabricatorCampfireProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php', 'PhabricatorCelerityApplication' => 'applications/celerity/application/PhabricatorCelerityApplication.php', 'PhabricatorCelerityTestCase' => '__tests__/PhabricatorCelerityTestCase.php', 'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php', 'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', 'PhabricatorChatLogApplication' => 'applications/chatlog/application/PhabricatorChatLogApplication.php', 'PhabricatorChatLogChannel' => 'applications/chatlog/storage/PhabricatorChatLogChannel.php', 'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/PhabricatorChatLogChannelListController.php', 'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/PhabricatorChatLogChannelLogController.php', 'PhabricatorChatLogChannelQuery' => 'applications/chatlog/query/PhabricatorChatLogChannelQuery.php', 'PhabricatorChatLogController' => 'applications/chatlog/controller/PhabricatorChatLogController.php', 'PhabricatorChatLogDAO' => 'applications/chatlog/storage/PhabricatorChatLogDAO.php', 'PhabricatorChatLogEvent' => 'applications/chatlog/storage/PhabricatorChatLogEvent.php', 'PhabricatorChatLogQuery' => 'applications/chatlog/query/PhabricatorChatLogQuery.php', 'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php', 'PhabricatorClusterConfigOptions' => 'applications/config/option/PhabricatorClusterConfigOptions.php', 'PhabricatorClusterDatabasesConfigOptionType' => 'infrastructure/cluster/PhabricatorClusterDatabasesConfigOptionType.php', 'PhabricatorClusterException' => 'infrastructure/cluster/PhabricatorClusterException.php', 'PhabricatorClusterExceptionHandler' => 'infrastructure/cluster/PhabricatorClusterExceptionHandler.php', 'PhabricatorClusterImpossibleWriteException' => 'infrastructure/cluster/PhabricatorClusterImpossibleWriteException.php', 'PhabricatorClusterImproperWriteException' => 'infrastructure/cluster/PhabricatorClusterImproperWriteException.php', 'PhabricatorClusterStrandedException' => 'infrastructure/cluster/PhabricatorClusterStrandedException.php', 'PhabricatorColumnProxyInterface' => 'applications/project/interface/PhabricatorColumnProxyInterface.php', 'PhabricatorColumnsEditField' => 'applications/transactions/editfield/PhabricatorColumnsEditField.php', 'PhabricatorCommentEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php', 'PhabricatorCommentEditField' => 'applications/transactions/editfield/PhabricatorCommentEditField.php', 'PhabricatorCommentEditType' => 'applications/transactions/edittype/PhabricatorCommentEditType.php', 'PhabricatorCommitBranchesField' => 'applications/repository/customfield/PhabricatorCommitBranchesField.php', 'PhabricatorCommitCustomField' => 'applications/repository/customfield/PhabricatorCommitCustomField.php', 'PhabricatorCommitMergedCommitsField' => 'applications/repository/customfield/PhabricatorCommitMergedCommitsField.php', 'PhabricatorCommitRepositoryField' => 'applications/repository/customfield/PhabricatorCommitRepositoryField.php', 'PhabricatorCommitSearchEngine' => 'applications/audit/query/PhabricatorCommitSearchEngine.php', 'PhabricatorCommitTagsField' => 'applications/repository/customfield/PhabricatorCommitTagsField.php', 'PhabricatorCommonPasswords' => 'applications/auth/constants/PhabricatorCommonPasswords.php', 'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php', 'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php', 'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php', 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php', 'PhabricatorConduitContentSource' => 'infrastructure/contentsource/PhabricatorConduitContentSource.php', 'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php', 'PhabricatorConduitDAO' => 'applications/conduit/storage/PhabricatorConduitDAO.php', 'PhabricatorConduitEditField' => 'applications/transactions/editfield/PhabricatorConduitEditField.php', 'PhabricatorConduitListController' => 'applications/conduit/controller/PhabricatorConduitListController.php', 'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php', 'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php', 'PhabricatorConduitLogSearchEngine' => 'applications/conduit/query/PhabricatorConduitLogSearchEngine.php', 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php', 'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php', 'PhabricatorConduitRequestExceptionHandler' => 'aphront/handler/PhabricatorConduitRequestExceptionHandler.php', 'PhabricatorConduitResultInterface' => 'applications/conduit/interface/PhabricatorConduitResultInterface.php', 'PhabricatorConduitSearchEngine' => 'applications/conduit/query/PhabricatorConduitSearchEngine.php', 'PhabricatorConduitSearchFieldSpecification' => 'applications/conduit/interface/PhabricatorConduitSearchFieldSpecification.php', 'PhabricatorConduitTestCase' => '__tests__/PhabricatorConduitTestCase.php', 'PhabricatorConduitToken' => 'applications/conduit/storage/PhabricatorConduitToken.php', 'PhabricatorConduitTokenController' => 'applications/conduit/controller/PhabricatorConduitTokenController.php', 'PhabricatorConduitTokenEditController' => 'applications/conduit/controller/PhabricatorConduitTokenEditController.php', 'PhabricatorConduitTokenHandshakeController' => 'applications/conduit/controller/PhabricatorConduitTokenHandshakeController.php', 'PhabricatorConduitTokenQuery' => 'applications/conduit/query/PhabricatorConduitTokenQuery.php', 'PhabricatorConduitTokenTerminateController' => 'applications/conduit/controller/PhabricatorConduitTokenTerminateController.php', 'PhabricatorConduitTokensSettingsPanel' => 'applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php', 'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php', 'PhabricatorConfigApplication' => 'applications/config/application/PhabricatorConfigApplication.php', 'PhabricatorConfigApplicationController' => 'applications/config/controller/PhabricatorConfigApplicationController.php', 'PhabricatorConfigCacheController' => 'applications/config/controller/PhabricatorConfigCacheController.php', 'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/PhabricatorConfigClusterDatabasesController.php', 'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/PhabricatorConfigClusterNotificationsController.php', 'PhabricatorConfigClusterRepositoriesController' => 'applications/config/controller/PhabricatorConfigClusterRepositoriesController.php', 'PhabricatorConfigCollectorsModule' => 'applications/config/module/PhabricatorConfigCollectorsModule.php', 'PhabricatorConfigColumnSchema' => 'applications/config/schema/PhabricatorConfigColumnSchema.php', 'PhabricatorConfigConfigPHIDType' => 'applications/config/phid/PhabricatorConfigConfigPHIDType.php', 'PhabricatorConfigConstants' => 'applications/config/constants/PhabricatorConfigConstants.php', 'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php', 'PhabricatorConfigCoreSchemaSpec' => 'applications/config/schema/PhabricatorConfigCoreSchemaSpec.php', 'PhabricatorConfigDatabaseController' => 'applications/config/controller/PhabricatorConfigDatabaseController.php', 'PhabricatorConfigDatabaseIssueController' => 'applications/config/controller/PhabricatorConfigDatabaseIssueController.php', 'PhabricatorConfigDatabaseSchema' => 'applications/config/schema/PhabricatorConfigDatabaseSchema.php', 'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php', 'PhabricatorConfigDatabaseStatusController' => 'applications/config/controller/PhabricatorConfigDatabaseStatusController.php', 'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php', 'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php', 'PhabricatorConfigEdgeModule' => 'applications/config/module/PhabricatorConfigEdgeModule.php', 'PhabricatorConfigEditController' => 'applications/config/controller/PhabricatorConfigEditController.php', 'PhabricatorConfigEditor' => 'applications/config/editor/PhabricatorConfigEditor.php', 'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php', 'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php', 'PhabricatorConfigEntryQuery' => 'applications/config/query/PhabricatorConfigEntryQuery.php', 'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php', 'PhabricatorConfigGroupConstants' => 'applications/config/constants/PhabricatorConfigGroupConstants.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', 'PhabricatorConfigIssuePanelController' => 'applications/config/controller/PhabricatorConfigIssuePanelController.php', 'PhabricatorConfigIssueViewController' => 'applications/config/controller/PhabricatorConfigIssueViewController.php', 'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php', 'PhabricatorConfigJSONOptionType' => 'applications/config/custom/PhabricatorConfigJSONOptionType.php', 'PhabricatorConfigKeySchema' => 'applications/config/schema/PhabricatorConfigKeySchema.php', 'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php', 'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php', 'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php', 'PhabricatorConfigManagementDoneWorkflow' => 'applications/config/management/PhabricatorConfigManagementDoneWorkflow.php', 'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php', 'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php', 'PhabricatorConfigManagementMigrateWorkflow' => 'applications/config/management/PhabricatorConfigManagementMigrateWorkflow.php', 'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php', 'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php', 'PhabricatorConfigManualActivity' => 'applications/config/storage/PhabricatorConfigManualActivity.php', 'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php', 'PhabricatorConfigModuleController' => 'applications/config/controller/PhabricatorConfigModuleController.php', 'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php', 'PhabricatorConfigOptionType' => 'applications/config/custom/PhabricatorConfigOptionType.php', 'PhabricatorConfigPHIDModule' => 'applications/config/module/PhabricatorConfigPHIDModule.php', 'PhabricatorConfigPageView' => 'applications/config/view/PhabricatorConfigPageView.php', 'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php', 'PhabricatorConfigPurgeCacheController' => 'applications/config/controller/PhabricatorConfigPurgeCacheController.php', 'PhabricatorConfigRequestExceptionHandlerModule' => 'applications/config/module/PhabricatorConfigRequestExceptionHandlerModule.php', 'PhabricatorConfigResponse' => 'applications/config/response/PhabricatorConfigResponse.php', 'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php', 'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php', 'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php', 'PhabricatorConfigSetupCheckModule' => 'applications/config/module/PhabricatorConfigSetupCheckModule.php', 'PhabricatorConfigSiteModule' => 'applications/config/module/PhabricatorConfigSiteModule.php', 'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php', 'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php', 'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php', 'PhabricatorConfigStorageSchema' => 'applications/config/schema/PhabricatorConfigStorageSchema.php', 'PhabricatorConfigTableSchema' => 'applications/config/schema/PhabricatorConfigTableSchema.php', 'PhabricatorConfigTransaction' => 'applications/config/storage/PhabricatorConfigTransaction.php', 'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php', 'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php', 'PhabricatorConfigVersionController' => 'applications/config/controller/PhabricatorConfigVersionController.php', 'PhabricatorConpherenceApplication' => 'applications/conpherence/application/PhabricatorConpherenceApplication.php', 'PhabricatorConpherenceColumnMinimizeSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnMinimizeSetting.php', 'PhabricatorConpherenceColumnVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnVisibleSetting.php', 'PhabricatorConpherenceNotificationsSetting' => 'applications/settings/setting/PhabricatorConpherenceNotificationsSetting.php', 'PhabricatorConpherencePreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorConpherencePreferencesSettingsPanel.php', 'PhabricatorConpherenceThreadPHIDType' => 'applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php', 'PhabricatorConpherenceWidgetVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceWidgetVisibleSetting.php', 'PhabricatorConsoleApplication' => 'applications/console/application/PhabricatorConsoleApplication.php', 'PhabricatorConsoleContentSource' => 'infrastructure/contentsource/PhabricatorConsoleContentSource.php', 'PhabricatorContentSource' => 'infrastructure/contentsource/PhabricatorContentSource.php', 'PhabricatorContentSourceModule' => 'infrastructure/contentsource/PhabricatorContentSourceModule.php', 'PhabricatorContentSourceView' => 'infrastructure/contentsource/PhabricatorContentSourceView.php', 'PhabricatorContributedToObjectEdgeType' => 'applications/transactions/edges/PhabricatorContributedToObjectEdgeType.php', 'PhabricatorController' => 'applications/base/controller/PhabricatorController.php', 'PhabricatorCookies' => 'applications/auth/constants/PhabricatorCookies.php', 'PhabricatorCoreConfigOptions' => 'applications/config/option/PhabricatorCoreConfigOptions.php', 'PhabricatorCoreCreateTransaction' => 'applications/transactions/xaction/PhabricatorCoreCreateTransaction.php', 'PhabricatorCoreTransactionType' => 'applications/transactions/xaction/PhabricatorCoreTransactionType.php', 'PhabricatorCoreVoidTransaction' => 'applications/transactions/xaction/PhabricatorCoreVoidTransaction.php', 'PhabricatorCountdown' => 'applications/countdown/storage/PhabricatorCountdown.php', 'PhabricatorCountdownApplication' => 'applications/countdown/application/PhabricatorCountdownApplication.php', 'PhabricatorCountdownController' => 'applications/countdown/controller/PhabricatorCountdownController.php', 'PhabricatorCountdownCountdownPHIDType' => 'applications/countdown/phid/PhabricatorCountdownCountdownPHIDType.php', 'PhabricatorCountdownDAO' => 'applications/countdown/storage/PhabricatorCountdownDAO.php', 'PhabricatorCountdownDefaultEditCapability' => 'applications/countdown/capability/PhabricatorCountdownDefaultEditCapability.php', 'PhabricatorCountdownDefaultViewCapability' => 'applications/countdown/capability/PhabricatorCountdownDefaultViewCapability.php', 'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/PhabricatorCountdownDeleteController.php', 'PhabricatorCountdownEditController' => 'applications/countdown/controller/PhabricatorCountdownEditController.php', 'PhabricatorCountdownEditEngine' => 'applications/countdown/editor/PhabricatorCountdownEditEngine.php', 'PhabricatorCountdownEditor' => 'applications/countdown/editor/PhabricatorCountdownEditor.php', 'PhabricatorCountdownListController' => 'applications/countdown/controller/PhabricatorCountdownListController.php', 'PhabricatorCountdownMailReceiver' => 'applications/countdown/mail/PhabricatorCountdownMailReceiver.php', 'PhabricatorCountdownQuery' => 'applications/countdown/query/PhabricatorCountdownQuery.php', 'PhabricatorCountdownRemarkupRule' => 'applications/countdown/remarkup/PhabricatorCountdownRemarkupRule.php', 'PhabricatorCountdownReplyHandler' => 'applications/countdown/mail/PhabricatorCountdownReplyHandler.php', 'PhabricatorCountdownSchemaSpec' => 'applications/countdown/storage/PhabricatorCountdownSchemaSpec.php', 'PhabricatorCountdownSearchEngine' => 'applications/countdown/query/PhabricatorCountdownSearchEngine.php', 'PhabricatorCountdownTransaction' => 'applications/countdown/storage/PhabricatorCountdownTransaction.php', 'PhabricatorCountdownTransactionComment' => 'applications/countdown/storage/PhabricatorCountdownTransactionComment.php', 'PhabricatorCountdownTransactionQuery' => 'applications/countdown/query/PhabricatorCountdownTransactionQuery.php', 'PhabricatorCountdownView' => 'applications/countdown/view/PhabricatorCountdownView.php', 'PhabricatorCountdownViewController' => 'applications/countdown/controller/PhabricatorCountdownViewController.php', 'PhabricatorCursorPagedPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php', 'PhabricatorCustomField' => 'infrastructure/customfield/field/PhabricatorCustomField.php', 'PhabricatorCustomFieldAttachment' => 'infrastructure/customfield/field/PhabricatorCustomFieldAttachment.php', 'PhabricatorCustomFieldConfigOptionType' => 'infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php', 'PhabricatorCustomFieldDataNotAvailableException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldDataNotAvailableException.php', 'PhabricatorCustomFieldEditEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php', 'PhabricatorCustomFieldEditField' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php', 'PhabricatorCustomFieldEditType' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php', 'PhabricatorCustomFieldFulltextEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldFulltextEngineExtension.php', 'PhabricatorCustomFieldHeraldField' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldField.php', 'PhabricatorCustomFieldHeraldFieldGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldFieldGroup.php', 'PhabricatorCustomFieldImplementationIncompleteException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldImplementationIncompleteException.php', 'PhabricatorCustomFieldIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldIndexStorage.php', 'PhabricatorCustomFieldInterface' => 'infrastructure/customfield/interface/PhabricatorCustomFieldInterface.php', 'PhabricatorCustomFieldList' => 'infrastructure/customfield/field/PhabricatorCustomFieldList.php', 'PhabricatorCustomFieldMonogramParser' => 'infrastructure/customfield/parser/PhabricatorCustomFieldMonogramParser.php', 'PhabricatorCustomFieldNotAttachedException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldNotAttachedException.php', 'PhabricatorCustomFieldNotProxyException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldNotProxyException.php', 'PhabricatorCustomFieldNumericIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldNumericIndexStorage.php', 'PhabricatorCustomFieldSearchEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldSearchEngineExtension.php', 'PhabricatorCustomFieldStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStorage.php', 'PhabricatorCustomFieldStorageQuery' => 'infrastructure/customfield/query/PhabricatorCustomFieldStorageQuery.php', 'PhabricatorCustomFieldStringIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStringIndexStorage.php', 'PhabricatorCustomLogoConfigType' => 'applications/config/custom/PhabricatorCustomLogoConfigType.php', 'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php', 'PhabricatorDaemonBulkJobController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobController.php', 'PhabricatorDaemonBulkJobListController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobListController.php', 'PhabricatorDaemonBulkJobMonitorController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobMonitorController.php', 'PhabricatorDaemonBulkJobViewController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobViewController.php', 'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/PhabricatorDaemonConsoleController.php', 'PhabricatorDaemonContentSource' => 'infrastructure/daemon/contentsource/PhabricatorDaemonContentSource.php', 'PhabricatorDaemonController' => 'applications/daemon/controller/PhabricatorDaemonController.php', 'PhabricatorDaemonDAO' => 'applications/daemon/storage/PhabricatorDaemonDAO.php', 'PhabricatorDaemonEventListener' => 'applications/daemon/event/PhabricatorDaemonEventListener.php', 'PhabricatorDaemonLog' => 'applications/daemon/storage/PhabricatorDaemonLog.php', 'PhabricatorDaemonLogEvent' => 'applications/daemon/storage/PhabricatorDaemonLogEvent.php', 'PhabricatorDaemonLogEventGarbageCollector' => 'applications/daemon/garbagecollector/PhabricatorDaemonLogEventGarbageCollector.php', 'PhabricatorDaemonLogEventViewController' => 'applications/daemon/controller/PhabricatorDaemonLogEventViewController.php', 'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/PhabricatorDaemonLogEventsView.php', 'PhabricatorDaemonLogGarbageCollector' => 'applications/daemon/garbagecollector/PhabricatorDaemonLogGarbageCollector.php', 'PhabricatorDaemonLogListController' => 'applications/daemon/controller/PhabricatorDaemonLogListController.php', 'PhabricatorDaemonLogListView' => 'applications/daemon/view/PhabricatorDaemonLogListView.php', 'PhabricatorDaemonLogQuery' => 'applications/daemon/query/PhabricatorDaemonLogQuery.php', 'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/PhabricatorDaemonLogViewController.php', 'PhabricatorDaemonManagementDebugWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementDebugWorkflow.php', 'PhabricatorDaemonManagementLaunchWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementLaunchWorkflow.php', 'PhabricatorDaemonManagementListWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementListWorkflow.php', 'PhabricatorDaemonManagementLogWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementLogWorkflow.php', 'PhabricatorDaemonManagementReloadWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementReloadWorkflow.php', 'PhabricatorDaemonManagementRestartWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php', 'PhabricatorDaemonManagementStartWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStartWorkflow.php', 'PhabricatorDaemonManagementStatusWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php', 'PhabricatorDaemonManagementStopWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php', 'PhabricatorDaemonManagementWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementWorkflow.php', 'PhabricatorDaemonOverseerModule' => 'infrastructure/daemon/overseer/PhabricatorDaemonOverseerModule.php', 'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php', 'PhabricatorDaemonTaskGarbageCollector' => 'applications/daemon/garbagecollector/PhabricatorDaemonTaskGarbageCollector.php', 'PhabricatorDaemonTasksTableView' => 'applications/daemon/view/PhabricatorDaemonTasksTableView.php', 'PhabricatorDaemonsApplication' => 'applications/daemon/application/PhabricatorDaemonsApplication.php', 'PhabricatorDaemonsSetupCheck' => 'applications/config/check/PhabricatorDaemonsSetupCheck.php', 'PhabricatorDailyRoutineTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorDailyRoutineTriggerClock.php', 'PhabricatorDarkConsoleSetting' => 'applications/settings/setting/PhabricatorDarkConsoleSetting.php', 'PhabricatorDarkConsoleTabSetting' => 'applications/settings/setting/PhabricatorDarkConsoleTabSetting.php', 'PhabricatorDarkConsoleVisibleSetting' => 'applications/settings/setting/PhabricatorDarkConsoleVisibleSetting.php', 'PhabricatorDashboard' => 'applications/dashboard/storage/PhabricatorDashboard.php', 'PhabricatorDashboardAddPanelController' => 'applications/dashboard/controller/PhabricatorDashboardAddPanelController.php', 'PhabricatorDashboardApplication' => 'applications/dashboard/application/PhabricatorDashboardApplication.php', 'PhabricatorDashboardArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardArchiveController.php', 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', 'PhabricatorDashboardCopyController' => 'applications/dashboard/controller/PhabricatorDashboardCopyController.php', 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardDashboardHasPanelEdgeType.php', 'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php', + 'PhabricatorDashboardDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardDatasource.php', 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php', + 'PhabricatorDashboardIconSet' => 'applications/dashboard/icon/PhabricatorDashboardIconSet.php', 'PhabricatorDashboardInstall' => 'applications/dashboard/storage/PhabricatorDashboardInstall.php', 'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/PhabricatorDashboardInstallController.php', 'PhabricatorDashboardLayoutConfig' => 'applications/dashboard/layoutconfig/PhabricatorDashboardLayoutConfig.php', 'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php', 'PhabricatorDashboardManageController' => 'applications/dashboard/controller/PhabricatorDashboardManageController.php', 'PhabricatorDashboardMovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardMovePanelController.php', + 'PhabricatorDashboardNgrams' => 'applications/dashboard/storage/PhabricatorDashboardNgrams.php', 'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php', 'PhabricatorDashboardPanelArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardPanelArchiveController.php', 'PhabricatorDashboardPanelCoreCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCoreCustomField.php', 'PhabricatorDashboardPanelCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelCustomField.php', + 'PhabricatorDashboardPanelDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php', 'PhabricatorDashboardPanelEditConduitAPIMethod' => 'applications/dashboard/conduit/PhabricatorDashboardPanelEditConduitAPIMethod.php', 'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/PhabricatorDashboardPanelEditController.php', 'PhabricatorDashboardPanelEditEngine' => 'applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php', 'PhabricatorDashboardPanelEditproController' => 'applications/dashboard/controller/PhabricatorDashboardPanelEditproController.php', 'PhabricatorDashboardPanelHasDashboardEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardPanelHasDashboardEdgeType.php', 'PhabricatorDashboardPanelListController' => 'applications/dashboard/controller/PhabricatorDashboardPanelListController.php', + 'PhabricatorDashboardPanelNgrams' => 'applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php', 'PhabricatorDashboardPanelPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardPanelPHIDType.php', 'PhabricatorDashboardPanelQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelQuery.php', 'PhabricatorDashboardPanelRenderController' => 'applications/dashboard/controller/PhabricatorDashboardPanelRenderController.php', 'PhabricatorDashboardPanelRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php', 'PhabricatorDashboardPanelSearchApplicationCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelSearchApplicationCustomField.php', 'PhabricatorDashboardPanelSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php', 'PhabricatorDashboardPanelSearchQueryCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelSearchQueryCustomField.php', 'PhabricatorDashboardPanelTabsCustomField' => 'applications/dashboard/customfield/PhabricatorDashboardPanelTabsCustomField.php', 'PhabricatorDashboardPanelTransaction' => 'applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php', 'PhabricatorDashboardPanelTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php', 'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php', 'PhabricatorDashboardPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelType.php', 'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php', + 'PhabricatorDashboardProfileMenuItem' => 'applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php', 'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', 'PhabricatorDashboardQueryPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php', 'PhabricatorDashboardRemarkupRule' => 'applications/dashboard/remarkup/PhabricatorDashboardRemarkupRule.php', 'PhabricatorDashboardRemovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardRemovePanelController.php', 'PhabricatorDashboardRenderingEngine' => 'applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php', 'PhabricatorDashboardSchemaSpec' => 'applications/dashboard/storage/PhabricatorDashboardSchemaSpec.php', 'PhabricatorDashboardSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardSearchEngine.php', 'PhabricatorDashboardTabsPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php', 'PhabricatorDashboardTextPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardTextPanelType.php', 'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php', 'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php', 'PhabricatorDashboardTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardTransactionQuery.php', 'PhabricatorDashboardUninstallController' => 'applications/dashboard/controller/PhabricatorDashboardUninstallController.php', 'PhabricatorDashboardViewController' => 'applications/dashboard/controller/PhabricatorDashboardViewController.php', 'PhabricatorDataCacheSpec' => 'applications/cache/spec/PhabricatorDataCacheSpec.php', 'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php', 'PhabricatorDatabaseHealthRecord' => 'infrastructure/cluster/PhabricatorDatabaseHealthRecord.php', 'PhabricatorDatabaseRef' => 'infrastructure/cluster/PhabricatorDatabaseRef.php', 'PhabricatorDatabaseRefParser' => 'infrastructure/cluster/PhabricatorDatabaseRefParser.php', 'PhabricatorDatabaseSetupCheck' => 'applications/config/check/PhabricatorDatabaseSetupCheck.php', 'PhabricatorDatasourceEditField' => 'applications/transactions/editfield/PhabricatorDatasourceEditField.php', 'PhabricatorDatasourceEditType' => 'applications/transactions/edittype/PhabricatorDatasourceEditType.php', 'PhabricatorDateFormatSetting' => 'applications/settings/setting/PhabricatorDateFormatSetting.php', 'PhabricatorDateTimeSettingsPanel' => 'applications/settings/panel/PhabricatorDateTimeSettingsPanel.php', 'PhabricatorDebugController' => 'applications/system/controller/PhabricatorDebugController.php', 'PhabricatorDefaultRequestExceptionHandler' => 'aphront/handler/PhabricatorDefaultRequestExceptionHandler.php', 'PhabricatorDefaultSyntaxStyle' => 'infrastructure/syntax/PhabricatorDefaultSyntaxStyle.php', 'PhabricatorDesktopNotificationsSetting' => 'applications/settings/setting/PhabricatorDesktopNotificationsSetting.php', 'PhabricatorDesktopNotificationsSettingsPanel' => 'applications/settings/panel/PhabricatorDesktopNotificationsSettingsPanel.php', 'PhabricatorDestructibleInterface' => 'applications/system/interface/PhabricatorDestructibleInterface.php', 'PhabricatorDestructionEngine' => 'applications/system/engine/PhabricatorDestructionEngine.php', 'PhabricatorDestructionEngineExtension' => 'applications/system/engine/PhabricatorDestructionEngineExtension.php', 'PhabricatorDestructionEngineExtensionModule' => 'applications/system/engine/PhabricatorDestructionEngineExtensionModule.php', 'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php', 'PhabricatorDeveloperPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDeveloperPreferencesSettingsPanel.php', 'PhabricatorDiffInlineCommentQuery' => 'infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php', 'PhabricatorDiffPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDiffPreferencesSettingsPanel.php', 'PhabricatorDifferenceEngine' => 'infrastructure/diff/PhabricatorDifferenceEngine.php', 'PhabricatorDifferentialApplication' => 'applications/differential/application/PhabricatorDifferentialApplication.php', 'PhabricatorDifferentialAttachCommitWorkflow' => 'applications/differential/management/PhabricatorDifferentialAttachCommitWorkflow.php', 'PhabricatorDifferentialConfigOptions' => 'applications/differential/config/PhabricatorDifferentialConfigOptions.php', 'PhabricatorDifferentialExtractWorkflow' => 'applications/differential/management/PhabricatorDifferentialExtractWorkflow.php', 'PhabricatorDifferentialManagementWorkflow' => 'applications/differential/management/PhabricatorDifferentialManagementWorkflow.php', 'PhabricatorDifferentialRevisionTestDataGenerator' => 'applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php', 'PhabricatorDiffusionApplication' => 'applications/diffusion/application/PhabricatorDiffusionApplication.php', 'PhabricatorDiffusionBlameSetting' => 'applications/settings/setting/PhabricatorDiffusionBlameSetting.php', 'PhabricatorDiffusionConfigOptions' => 'applications/diffusion/config/PhabricatorDiffusionConfigOptions.php', 'PhabricatorDisabledUserController' => 'applications/auth/controller/PhabricatorDisabledUserController.php', 'PhabricatorDisplayPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDisplayPreferencesSettingsPanel.php', 'PhabricatorDisqusAuthProvider' => 'applications/auth/provider/PhabricatorDisqusAuthProvider.php', - 'PhabricatorDividerProfilePanel' => 'applications/search/profilepanel/PhabricatorDividerProfilePanel.php', + 'PhabricatorDividerEditField' => 'applications/transactions/editfield/PhabricatorDividerEditField.php', + 'PhabricatorDividerProfileMenuItem' => 'applications/search/menuitem/PhabricatorDividerProfileMenuItem.php', 'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php', 'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php', 'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php', 'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php', 'PhabricatorDrydockApplication' => 'applications/drydock/application/PhabricatorDrydockApplication.php', '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', 'PhabricatorEdgesDestructionEngineExtension' => 'infrastructure/edges/engineextension/PhabricatorEdgesDestructionEngineExtension.php', 'PhabricatorEditEngine' => 'applications/transactions/editengine/PhabricatorEditEngine.php', 'PhabricatorEditEngineAPIMethod' => 'applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php', 'PhabricatorEditEngineColumnsCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineColumnsCommentAction.php', 'PhabricatorEditEngineCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineCommentAction.php', 'PhabricatorEditEngineConfiguration' => 'applications/transactions/storage/PhabricatorEditEngineConfiguration.php', 'PhabricatorEditEngineConfigurationDefaultCreateController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultCreateController.php', 'PhabricatorEditEngineConfigurationDefaultsController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationDefaultsController.php', 'PhabricatorEditEngineConfigurationDisableController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationDisableController.php', 'PhabricatorEditEngineConfigurationEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php', 'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php', 'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php', 'PhabricatorEditEngineConfigurationIsEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationIsEditController.php', 'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php', 'PhabricatorEditEngineConfigurationLockController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php', 'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php', 'PhabricatorEditEngineConfigurationQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php', 'PhabricatorEditEngineConfigurationReorderController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php', 'PhabricatorEditEngineConfigurationSaveController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php', 'PhabricatorEditEngineConfigurationSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php', 'PhabricatorEditEngineConfigurationSortController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSortController.php', 'PhabricatorEditEngineConfigurationTransaction' => 'applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php', 'PhabricatorEditEngineConfigurationTransactionQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php', 'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php', 'PhabricatorEditEngineController' => 'applications/transactions/controller/PhabricatorEditEngineController.php', 'PhabricatorEditEngineCreateQuickActions' => 'applications/settings/quickmenu/PhabricatorEditEngineCreateQuickActions.php', + 'PhabricatorEditEngineDatasource' => 'applications/transactions/typeahead/PhabricatorEditEngineDatasource.php', 'PhabricatorEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditEngineExtension.php', 'PhabricatorEditEngineExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditEngineExtensionModule.php', 'PhabricatorEditEngineListController' => 'applications/transactions/controller/PhabricatorEditEngineListController.php', 'PhabricatorEditEnginePointsCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEnginePointsCommentAction.php', 'PhabricatorEditEngineQuery' => 'applications/transactions/query/PhabricatorEditEngineQuery.php', 'PhabricatorEditEngineSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineSearchEngine.php', 'PhabricatorEditEngineSelectCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineSelectCommentAction.php', 'PhabricatorEditEngineSettingsPanel' => 'applications/settings/panel/PhabricatorEditEngineSettingsPanel.php', 'PhabricatorEditEngineTokenizerCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineTokenizerCommentAction.php', 'PhabricatorEditField' => 'applications/transactions/editfield/PhabricatorEditField.php', 'PhabricatorEditPage' => 'applications/transactions/editengine/PhabricatorEditPage.php', 'PhabricatorEditType' => 'applications/transactions/edittype/PhabricatorEditType.php', 'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php', 'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php', 'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php', 'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php', 'PhabricatorElasticSearchSetupCheck' => 'applications/config/check/PhabricatorElasticSearchSetupCheck.php', 'PhabricatorEmailAddressesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailAddressesSettingsPanel.php', 'PhabricatorEmailContentSource' => 'applications/metamta/contentsource/PhabricatorEmailContentSource.php', 'PhabricatorEmailDeliverySettingsPanel' => 'applications/settings/panel/PhabricatorEmailDeliverySettingsPanel.php', 'PhabricatorEmailFormatSetting' => 'applications/settings/setting/PhabricatorEmailFormatSetting.php', 'PhabricatorEmailFormatSettingsPanel' => 'applications/settings/panel/PhabricatorEmailFormatSettingsPanel.php', 'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php', 'PhabricatorEmailNotificationsSetting' => 'applications/settings/setting/PhabricatorEmailNotificationsSetting.php', 'PhabricatorEmailPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailPreferencesSettingsPanel.php', 'PhabricatorEmailRePrefixSetting' => 'applications/settings/setting/PhabricatorEmailRePrefixSetting.php', 'PhabricatorEmailSelfActionsSetting' => 'applications/settings/setting/PhabricatorEmailSelfActionsSetting.php', 'PhabricatorEmailTagsSetting' => 'applications/settings/setting/PhabricatorEmailTagsSetting.php', 'PhabricatorEmailVarySubjectsSetting' => 'applications/settings/setting/PhabricatorEmailVarySubjectsSetting.php', 'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php', 'PhabricatorEmbedFileRemarkupRule' => 'applications/files/markup/PhabricatorEmbedFileRemarkupRule.php', 'PhabricatorEmojiRemarkupRule' => 'applications/macro/markup/PhabricatorEmojiRemarkupRule.php', 'PhabricatorEmojiTranslation' => 'infrastructure/internationalization/translation/PhabricatorEmojiTranslation.php', 'PhabricatorEmptyQueryException' => 'infrastructure/query/PhabricatorEmptyQueryException.php', 'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php', 'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php', 'PhabricatorEpochEditField' => 'applications/transactions/editfield/PhabricatorEpochEditField.php', 'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php', 'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php', 'PhabricatorEventListener' => 'infrastructure/events/PhabricatorEventListener.php', 'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php', 'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php', 'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php', 'PhabricatorExtendedPolicyInterface' => 'applications/policy/interface/PhabricatorExtendedPolicyInterface.php', 'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php', 'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php', 'PhabricatorExternalAccount' => 'applications/people/storage/PhabricatorExternalAccount.php', 'PhabricatorExternalAccountQuery' => 'applications/auth/query/PhabricatorExternalAccountQuery.php', 'PhabricatorExternalAccountsSettingsPanel' => 'applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php', 'PhabricatorExtraConfigSetupCheck' => 'applications/config/check/PhabricatorExtraConfigSetupCheck.php', 'PhabricatorFacebookAuthProvider' => 'applications/auth/provider/PhabricatorFacebookAuthProvider.php', 'PhabricatorFactAggregate' => 'applications/fact/storage/PhabricatorFactAggregate.php', 'PhabricatorFactApplication' => 'applications/fact/application/PhabricatorFactApplication.php', 'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php', 'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php', 'PhabricatorFactCountEngine' => 'applications/fact/engine/PhabricatorFactCountEngine.php', 'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php', 'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php', 'PhabricatorFactDaemon' => 'applications/fact/daemon/PhabricatorFactDaemon.php', 'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php', 'PhabricatorFactEngineTestCase' => 'applications/fact/engine/__tests__/PhabricatorFactEngineTestCase.php', 'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php', 'PhabricatorFactLastUpdatedEngine' => 'applications/fact/engine/PhabricatorFactLastUpdatedEngine.php', 'PhabricatorFactManagementAnalyzeWorkflow' => 'applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php', 'PhabricatorFactManagementCursorsWorkflow' => 'applications/fact/management/PhabricatorFactManagementCursorsWorkflow.php', 'PhabricatorFactManagementDestroyWorkflow' => 'applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php', 'PhabricatorFactManagementListWorkflow' => 'applications/fact/management/PhabricatorFactManagementListWorkflow.php', 'PhabricatorFactManagementStatusWorkflow' => 'applications/fact/management/PhabricatorFactManagementStatusWorkflow.php', 'PhabricatorFactManagementWorkflow' => 'applications/fact/management/PhabricatorFactManagementWorkflow.php', 'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php', 'PhabricatorFactSimpleSpec' => 'applications/fact/spec/PhabricatorFactSimpleSpec.php', 'PhabricatorFactSpec' => 'applications/fact/spec/PhabricatorFactSpec.php', 'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php', 'PhabricatorFaxContentSource' => 'infrastructure/contentsource/PhabricatorFaxContentSource.php', 'PhabricatorFeedApplication' => 'applications/feed/application/PhabricatorFeedApplication.php', 'PhabricatorFeedBuilder' => 'applications/feed/builder/PhabricatorFeedBuilder.php', 'PhabricatorFeedConfigOptions' => 'applications/feed/config/PhabricatorFeedConfigOptions.php', 'PhabricatorFeedController' => 'applications/feed/controller/PhabricatorFeedController.php', 'PhabricatorFeedDAO' => 'applications/feed/storage/PhabricatorFeedDAO.php', 'PhabricatorFeedDetailController' => 'applications/feed/controller/PhabricatorFeedDetailController.php', 'PhabricatorFeedListController' => 'applications/feed/controller/PhabricatorFeedListController.php', 'PhabricatorFeedManagementRepublishWorkflow' => 'applications/feed/management/PhabricatorFeedManagementRepublishWorkflow.php', 'PhabricatorFeedManagementWorkflow' => 'applications/feed/management/PhabricatorFeedManagementWorkflow.php', 'PhabricatorFeedQuery' => 'applications/feed/query/PhabricatorFeedQuery.php', 'PhabricatorFeedSearchEngine' => 'applications/feed/query/PhabricatorFeedSearchEngine.php', 'PhabricatorFeedStory' => 'applications/feed/story/PhabricatorFeedStory.php', 'PhabricatorFeedStoryData' => 'applications/feed/storage/PhabricatorFeedStoryData.php', 'PhabricatorFeedStoryNotification' => 'applications/notification/storage/PhabricatorFeedStoryNotification.php', 'PhabricatorFeedStoryPublisher' => 'applications/feed/PhabricatorFeedStoryPublisher.php', 'PhabricatorFeedStoryReference' => 'applications/feed/storage/PhabricatorFeedStoryReference.php', 'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php', 'PhabricatorFileAES256StorageFormat' => 'applications/files/format/PhabricatorFileAES256StorageFormat.php', 'PhabricatorFileBundleLoader' => 'applications/files/query/PhabricatorFileBundleLoader.php', 'PhabricatorFileChunk' => 'applications/files/storage/PhabricatorFileChunk.php', 'PhabricatorFileChunkIterator' => 'applications/files/engine/PhabricatorFileChunkIterator.php', 'PhabricatorFileChunkQuery' => 'applications/files/query/PhabricatorFileChunkQuery.php', 'PhabricatorFileCommentController' => 'applications/files/controller/PhabricatorFileCommentController.php', 'PhabricatorFileComposeController' => 'applications/files/controller/PhabricatorFileComposeController.php', 'PhabricatorFileController' => 'applications/files/controller/PhabricatorFileController.php', 'PhabricatorFileDAO' => 'applications/files/storage/PhabricatorFileDAO.php', 'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php', 'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php', 'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php', 'PhabricatorFileEditController' => 'applications/files/controller/PhabricatorFileEditController.php', 'PhabricatorFileEditField' => 'applications/transactions/editfield/PhabricatorFileEditField.php', 'PhabricatorFileEditor' => 'applications/files/editor/PhabricatorFileEditor.php', 'PhabricatorFileExternalRequest' => 'applications/files/storage/PhabricatorFileExternalRequest.php', 'PhabricatorFileExternalRequestGarbageCollector' => 'applications/files/garbagecollector/PhabricatorFileExternalRequestGarbageCollector.php', 'PhabricatorFileFilePHIDType' => 'applications/files/phid/PhabricatorFileFilePHIDType.php', 'PhabricatorFileHasObjectEdgeType' => 'applications/files/edge/PhabricatorFileHasObjectEdgeType.php', 'PhabricatorFileIconSetSelectController' => 'applications/files/controller/PhabricatorFileIconSetSelectController.php', 'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php', 'PhabricatorFileImageProxyController' => 'applications/files/controller/PhabricatorFileImageProxyController.php', 'PhabricatorFileImageTransform' => 'applications/files/transform/PhabricatorFileImageTransform.php', 'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php', 'PhabricatorFileLightboxController' => 'applications/files/controller/PhabricatorFileLightboxController.php', 'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php', 'PhabricatorFileListController' => 'applications/files/controller/PhabricatorFileListController.php', 'PhabricatorFileQuery' => 'applications/files/query/PhabricatorFileQuery.php', 'PhabricatorFileROT13StorageFormat' => 'applications/files/format/PhabricatorFileROT13StorageFormat.php', 'PhabricatorFileRawStorageFormat' => 'applications/files/format/PhabricatorFileRawStorageFormat.php', 'PhabricatorFileSchemaSpec' => 'applications/files/storage/PhabricatorFileSchemaSpec.php', 'PhabricatorFileSearchEngine' => 'applications/files/query/PhabricatorFileSearchEngine.php', 'PhabricatorFileStorageBlob' => 'applications/files/storage/PhabricatorFileStorageBlob.php', 'PhabricatorFileStorageConfigurationException' => 'applications/files/exception/PhabricatorFileStorageConfigurationException.php', 'PhabricatorFileStorageEngine' => 'applications/files/engine/PhabricatorFileStorageEngine.php', 'PhabricatorFileStorageEngineTestCase' => 'applications/files/engine/__tests__/PhabricatorFileStorageEngineTestCase.php', 'PhabricatorFileStorageFormat' => 'applications/files/format/PhabricatorFileStorageFormat.php', 'PhabricatorFileStorageFormatTestCase' => 'applications/files/format/__tests__/PhabricatorFileStorageFormatTestCase.php', 'PhabricatorFileTemporaryGarbageCollector' => 'applications/files/garbagecollector/PhabricatorFileTemporaryGarbageCollector.php', 'PhabricatorFileTestCase' => 'applications/files/storage/__tests__/PhabricatorFileTestCase.php', 'PhabricatorFileTestDataGenerator' => 'applications/files/lipsum/PhabricatorFileTestDataGenerator.php', 'PhabricatorFileThumbnailTransform' => 'applications/files/transform/PhabricatorFileThumbnailTransform.php', 'PhabricatorFileTransaction' => 'applications/files/storage/PhabricatorFileTransaction.php', 'PhabricatorFileTransactionComment' => 'applications/files/storage/PhabricatorFileTransactionComment.php', 'PhabricatorFileTransactionQuery' => 'applications/files/query/PhabricatorFileTransactionQuery.php', 'PhabricatorFileTransform' => 'applications/files/transform/PhabricatorFileTransform.php', 'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php', 'PhabricatorFileTransformListController' => 'applications/files/controller/PhabricatorFileTransformListController.php', 'PhabricatorFileTransformTestCase' => 'applications/files/transform/__tests__/PhabricatorFileTransformTestCase.php', 'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php', 'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php', 'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php', 'PhabricatorFileUploadSource' => 'applications/files/uploadsource/PhabricatorFileUploadSource.php', 'PhabricatorFileinfoSetupCheck' => 'applications/config/check/PhabricatorFileinfoSetupCheck.php', 'PhabricatorFilesApplication' => 'applications/files/application/PhabricatorFilesApplication.php', 'PhabricatorFilesApplicationStorageEnginePanel' => 'applications/files/applicationpanel/PhabricatorFilesApplicationStorageEnginePanel.php', 'PhabricatorFilesBuiltinFile' => 'applications/files/builtin/PhabricatorFilesBuiltinFile.php', 'PhabricatorFilesComposeIconBuiltinFile' => 'applications/files/builtin/PhabricatorFilesComposeIconBuiltinFile.php', 'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php', 'PhabricatorFilesManagementCatWorkflow' => 'applications/files/management/PhabricatorFilesManagementCatWorkflow.php', 'PhabricatorFilesManagementCompactWorkflow' => 'applications/files/management/PhabricatorFilesManagementCompactWorkflow.php', 'PhabricatorFilesManagementCycleWorkflow' => 'applications/files/management/PhabricatorFilesManagementCycleWorkflow.php', 'PhabricatorFilesManagementEncodeWorkflow' => 'applications/files/management/PhabricatorFilesManagementEncodeWorkflow.php', 'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php', 'PhabricatorFilesManagementGenerateKeyWorkflow' => 'applications/files/management/PhabricatorFilesManagementGenerateKeyWorkflow.php', 'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php', 'PhabricatorFilesManagementPurgeWorkflow' => 'applications/files/management/PhabricatorFilesManagementPurgeWorkflow.php', 'PhabricatorFilesManagementRebuildWorkflow' => 'applications/files/management/PhabricatorFilesManagementRebuildWorkflow.php', 'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php', 'PhabricatorFilesOnDiskBuiltinFile' => 'applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php', 'PhabricatorFilesOutboundRequestAction' => 'applications/files/action/PhabricatorFilesOutboundRequestAction.php', 'PhabricatorFiletreeVisibleSetting' => 'applications/settings/setting/PhabricatorFiletreeVisibleSetting.php', 'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php', 'PhabricatorFlagAddFlagHeraldAction' => 'applications/flag/herald/PhabricatorFlagAddFlagHeraldAction.php', 'PhabricatorFlagColor' => 'applications/flag/constants/PhabricatorFlagColor.php', 'PhabricatorFlagConstants' => 'applications/flag/constants/PhabricatorFlagConstants.php', 'PhabricatorFlagController' => 'applications/flag/controller/PhabricatorFlagController.php', 'PhabricatorFlagDAO' => 'applications/flag/storage/PhabricatorFlagDAO.php', 'PhabricatorFlagDeleteController' => 'applications/flag/controller/PhabricatorFlagDeleteController.php', 'PhabricatorFlagDestructionEngineExtension' => 'applications/flag/engineextension/PhabricatorFlagDestructionEngineExtension.php', 'PhabricatorFlagEditController' => 'applications/flag/controller/PhabricatorFlagEditController.php', 'PhabricatorFlagListController' => 'applications/flag/controller/PhabricatorFlagListController.php', 'PhabricatorFlagQuery' => 'applications/flag/query/PhabricatorFlagQuery.php', 'PhabricatorFlagSearchEngine' => 'applications/flag/query/PhabricatorFlagSearchEngine.php', 'PhabricatorFlagSelectControl' => 'applications/flag/view/PhabricatorFlagSelectControl.php', 'PhabricatorFlaggableInterface' => 'applications/flag/interface/PhabricatorFlaggableInterface.php', 'PhabricatorFlagsApplication' => 'applications/flag/application/PhabricatorFlagsApplication.php', 'PhabricatorFlagsUIEventListener' => 'applications/flag/events/PhabricatorFlagsUIEventListener.php', 'PhabricatorFulltextEngine' => 'applications/search/index/PhabricatorFulltextEngine.php', 'PhabricatorFulltextEngineExtension' => 'applications/search/index/PhabricatorFulltextEngineExtension.php', 'PhabricatorFulltextEngineExtensionModule' => 'applications/search/index/PhabricatorFulltextEngineExtensionModule.php', 'PhabricatorFulltextIndexEngineExtension' => 'applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php', 'PhabricatorFulltextInterface' => 'applications/search/interface/PhabricatorFulltextInterface.php', 'PhabricatorFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorFulltextStorageEngine.php', 'PhabricatorFundApplication' => 'applications/fund/application/PhabricatorFundApplication.php', 'PhabricatorGDSetupCheck' => 'applications/config/check/PhabricatorGDSetupCheck.php', 'PhabricatorGarbageCollector' => 'infrastructure/daemon/garbagecollector/PhabricatorGarbageCollector.php', 'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCollectWorkflow.php', 'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementSetPolicyWorkflow.php', 'PhabricatorGarbageCollectorManagementWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementWorkflow.php', 'PhabricatorGestureUIExample' => 'applications/uiexample/examples/PhabricatorGestureUIExample.php', 'PhabricatorGitGraphStream' => 'applications/repository/daemon/PhabricatorGitGraphStream.php', 'PhabricatorGitHubAuthProvider' => 'applications/auth/provider/PhabricatorGitHubAuthProvider.php', 'PhabricatorGlobalLock' => 'infrastructure/util/PhabricatorGlobalLock.php', 'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php', 'PhabricatorGoogleAuthProvider' => 'applications/auth/provider/PhabricatorGoogleAuthProvider.php', 'PhabricatorGuidanceContext' => 'applications/guides/guidance/PhabricatorGuidanceContext.php', 'PhabricatorGuidanceEngine' => 'applications/guides/guidance/PhabricatorGuidanceEngine.php', 'PhabricatorGuidanceEngineExtension' => 'applications/guides/guidance/PhabricatorGuidanceEngineExtension.php', 'PhabricatorGuidanceMessage' => 'applications/guides/guidance/PhabricatorGuidanceMessage.php', 'PhabricatorGuideApplication' => 'applications/guides/application/PhabricatorGuideApplication.php', 'PhabricatorGuideController' => 'applications/guides/controller/PhabricatorGuideController.php', 'PhabricatorGuideInstallModule' => 'applications/guides/module/PhabricatorGuideInstallModule.php', 'PhabricatorGuideItemView' => 'applications/guides/view/PhabricatorGuideItemView.php', 'PhabricatorGuideListView' => 'applications/guides/view/PhabricatorGuideListView.php', 'PhabricatorGuideModule' => 'applications/guides/module/PhabricatorGuideModule.php', 'PhabricatorGuideModuleController' => 'applications/guides/controller/PhabricatorGuideModuleController.php', 'PhabricatorGuideQuickStartModule' => 'applications/guides/module/PhabricatorGuideQuickStartModule.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', 'PhabricatorHandlePoolTestCase' => 'applications/phid/handle/pool/__tests__/PhabricatorHandlePoolTestCase.php', 'PhabricatorHandleQuery' => 'applications/phid/query/PhabricatorHandleQuery.php', 'PhabricatorHandleRemarkupRule' => 'applications/phid/remarkup/PhabricatorHandleRemarkupRule.php', 'PhabricatorHandlesEditField' => 'applications/transactions/editfield/PhabricatorHandlesEditField.php', 'PhabricatorHarbormasterApplication' => 'applications/harbormaster/application/PhabricatorHarbormasterApplication.php', 'PhabricatorHash' => 'infrastructure/util/PhabricatorHash.php', 'PhabricatorHashTestCase' => 'infrastructure/util/__tests__/PhabricatorHashTestCase.php', 'PhabricatorHelpApplication' => 'applications/help/application/PhabricatorHelpApplication.php', 'PhabricatorHelpController' => 'applications/help/controller/PhabricatorHelpController.php', 'PhabricatorHelpDocumentationController' => 'applications/help/controller/PhabricatorHelpDocumentationController.php', 'PhabricatorHelpEditorProtocolController' => 'applications/help/controller/PhabricatorHelpEditorProtocolController.php', 'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', 'PhabricatorHelpMainMenuBarExtension' => 'applications/help/extension/PhabricatorHelpMainMenuBarExtension.php', 'PhabricatorHeraldApplication' => 'applications/herald/application/PhabricatorHeraldApplication.php', 'PhabricatorHeraldContentSource' => 'applications/herald/contentsource/PhabricatorHeraldContentSource.php', 'PhabricatorHighSecurityRequestExceptionHandler' => 'aphront/handler/PhabricatorHighSecurityRequestExceptionHandler.php', 'PhabricatorHomeApplication' => 'applications/home/application/PhabricatorHomeApplication.php', 'PhabricatorHomeController' => 'applications/home/controller/PhabricatorHomeController.php', 'PhabricatorHomeMainController' => 'applications/home/controller/PhabricatorHomeMainController.php', 'PhabricatorHomePreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php', 'PhabricatorHomeQuickCreateController' => 'applications/home/controller/PhabricatorHomeQuickCreateController.php', 'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php', 'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php', - 'PhabricatorHunksManagementMigrateWorkflow' => 'applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php', - 'PhabricatorHunksManagementWorkflow' => 'applications/differential/management/PhabricatorHunksManagementWorkflow.php', 'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php', 'PhabricatorIDsSearchField' => 'applications/search/field/PhabricatorIDsSearchField.php', 'PhabricatorIRCProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php', 'PhabricatorIconRemarkupRule' => 'applications/macro/markup/PhabricatorIconRemarkupRule.php', 'PhabricatorIconSet' => 'applications/files/iconset/PhabricatorIconSet.php', 'PhabricatorIconSetEditField' => 'applications/transactions/editfield/PhabricatorIconSetEditField.php', 'PhabricatorIconSetIcon' => 'applications/files/iconset/PhabricatorIconSetIcon.php', 'PhabricatorImageMacroRemarkupRule' => 'applications/macro/markup/PhabricatorImageMacroRemarkupRule.php', 'PhabricatorImageRemarkupRule' => 'applications/files/markup/PhabricatorImageRemarkupRule.php', 'PhabricatorImageTransformer' => 'applications/files/PhabricatorImageTransformer.php', 'PhabricatorImagemagickSetupCheck' => 'applications/config/check/PhabricatorImagemagickSetupCheck.php', 'PhabricatorInFlightErrorView' => 'applications/config/view/PhabricatorInFlightErrorView.php', 'PhabricatorIndexEngine' => 'applications/search/index/PhabricatorIndexEngine.php', 'PhabricatorIndexEngineExtension' => 'applications/search/index/PhabricatorIndexEngineExtension.php', 'PhabricatorIndexEngineExtensionModule' => 'applications/search/index/PhabricatorIndexEngineExtensionModule.php', 'PhabricatorInfrastructureTestCase' => '__tests__/PhabricatorInfrastructureTestCase.php', 'PhabricatorInlineCommentController' => 'infrastructure/diff/PhabricatorInlineCommentController.php', 'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/PhabricatorInlineCommentInterface.php', 'PhabricatorInlineCommentPreviewController' => 'infrastructure/diff/PhabricatorInlineCommentPreviewController.php', 'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php', 'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php', 'PhabricatorInternalSetting' => 'applications/settings/setting/PhabricatorInternalSetting.php', 'PhabricatorInternationalizationManagementExtractWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php', 'PhabricatorInternationalizationManagementWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementWorkflow.php', 'PhabricatorInvalidConfigSetupCheck' => 'applications/config/check/PhabricatorInvalidConfigSetupCheck.php', 'PhabricatorIteratedMD5PasswordHasher' => 'infrastructure/util/password/PhabricatorIteratedMD5PasswordHasher.php', 'PhabricatorIteratedMD5PasswordHasherTestCase' => 'infrastructure/util/password/__tests__/PhabricatorIteratedMD5PasswordHasherTestCase.php', 'PhabricatorIteratorFileUploadSource' => 'applications/files/uploadsource/PhabricatorIteratorFileUploadSource.php', 'PhabricatorJIRAAuthProvider' => 'applications/auth/provider/PhabricatorJIRAAuthProvider.php', 'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php', 'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php', 'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php', 'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php', 'PhabricatorKeyValueSerializingCacheProxy' => 'applications/cache/PhabricatorKeyValueSerializingCacheProxy.php', 'PhabricatorKeyboardRemarkupRule' => 'infrastructure/markup/rule/PhabricatorKeyboardRemarkupRule.php', 'PhabricatorKeyring' => 'applications/files/keyring/PhabricatorKeyring.php', 'PhabricatorKeyringConfigOptionType' => 'applications/files/keyring/PhabricatorKeyringConfigOptionType.php', 'PhabricatorLDAPAuthProvider' => 'applications/auth/provider/PhabricatorLDAPAuthProvider.php', 'PhabricatorLegalpadApplication' => 'applications/legalpad/application/PhabricatorLegalpadApplication.php', 'PhabricatorLegalpadConfigOptions' => 'applications/legalpad/config/PhabricatorLegalpadConfigOptions.php', 'PhabricatorLegalpadDocumentPHIDType' => 'applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php', 'PhabricatorLegalpadSignaturePolicyRule' => 'applications/legalpad/policyrule/PhabricatorLegalpadSignaturePolicyRule.php', 'PhabricatorLibraryTestCase' => '__tests__/PhabricatorLibraryTestCase.php', - 'PhabricatorLinkProfilePanel' => 'applications/search/profilepanel/PhabricatorLinkProfilePanel.php', + 'PhabricatorLinkProfileMenuItem' => 'applications/search/menuitem/PhabricatorLinkProfileMenuItem.php', 'PhabricatorLipsumArtist' => 'applications/lipsum/image/PhabricatorLipsumArtist.php', 'PhabricatorLipsumContentSource' => 'infrastructure/contentsource/PhabricatorLipsumContentSource.php', 'PhabricatorLipsumGenerateWorkflow' => 'applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php', 'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php', 'PhabricatorLipsumMondrianArtist' => 'applications/lipsum/image/PhabricatorLipsumMondrianArtist.php', 'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php', 'PhabricatorLiskFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorLiskFulltextEngineExtension.php', 'PhabricatorLiskSearchEngineExtension' => 'applications/search/engineextension/PhabricatorLiskSearchEngineExtension.php', 'PhabricatorLiskSerializer' => 'infrastructure/storage/lisk/PhabricatorLiskSerializer.php', 'PhabricatorListFilterUIExample' => 'applications/uiexample/examples/PhabricatorListFilterUIExample.php', 'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php', 'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php', 'PhabricatorLocaleScopeGuard' => 'infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php', 'PhabricatorLocaleScopeGuardTestCase' => 'infrastructure/internationalization/scope/__tests__/PhabricatorLocaleScopeGuardTestCase.php', 'PhabricatorLogTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorLogTriggerAction.php', 'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php', 'PhabricatorLunarPhasePolicyRule' => 'applications/policy/rule/PhabricatorLunarPhasePolicyRule.php', 'PhabricatorMacroApplication' => 'applications/macro/application/PhabricatorMacroApplication.php', 'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php', 'PhabricatorMacroCommentController' => 'applications/macro/controller/PhabricatorMacroCommentController.php', 'PhabricatorMacroConfigOptions' => 'applications/macro/config/PhabricatorMacroConfigOptions.php', 'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php', 'PhabricatorMacroDatasource' => 'applications/macro/typeahead/PhabricatorMacroDatasource.php', 'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php', 'PhabricatorMacroEditController' => 'applications/macro/controller/PhabricatorMacroEditController.php', 'PhabricatorMacroEditor' => 'applications/macro/editor/PhabricatorMacroEditor.php', 'PhabricatorMacroListController' => 'applications/macro/controller/PhabricatorMacroListController.php', 'PhabricatorMacroMacroPHIDType' => 'applications/macro/phid/PhabricatorMacroMacroPHIDType.php', 'PhabricatorMacroMailReceiver' => 'applications/macro/mail/PhabricatorMacroMailReceiver.php', 'PhabricatorMacroManageCapability' => 'applications/macro/capability/PhabricatorMacroManageCapability.php', 'PhabricatorMacroMemeController' => 'applications/macro/controller/PhabricatorMacroMemeController.php', 'PhabricatorMacroMemeDialogController' => 'applications/macro/controller/PhabricatorMacroMemeDialogController.php', 'PhabricatorMacroQuery' => 'applications/macro/query/PhabricatorMacroQuery.php', 'PhabricatorMacroReplyHandler' => 'applications/macro/mail/PhabricatorMacroReplyHandler.php', 'PhabricatorMacroSearchEngine' => 'applications/macro/query/PhabricatorMacroSearchEngine.php', 'PhabricatorMacroTransaction' => 'applications/macro/storage/PhabricatorMacroTransaction.php', 'PhabricatorMacroTransactionComment' => 'applications/macro/storage/PhabricatorMacroTransactionComment.php', 'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php', 'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php', 'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php', 'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php', 'PhabricatorMailEmailSubjectHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailSubjectHeraldField.php', 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php', 'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php', 'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php', 'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php', 'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php', 'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php', 'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php', 'PhabricatorMailManagementListOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListOutboundWorkflow.php', 'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php', 'PhabricatorMailManagementResendWorkflow' => 'applications/metamta/management/PhabricatorMailManagementResendWorkflow.php', 'PhabricatorMailManagementSendTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php', 'PhabricatorMailManagementShowInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowInboundWorkflow.php', 'PhabricatorMailManagementShowOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php', 'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php', 'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php', 'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php', 'PhabricatorMailOutboundRoutingHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingHeraldAction.php', 'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php', 'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfNotificationHeraldAction.php', 'PhabricatorMailOutboundStatus' => 'applications/metamta/constants/PhabricatorMailOutboundStatus.php', 'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php', 'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php', 'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php', 'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php', 'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php', 'PhabricatorMailgunConfigOptions' => 'applications/config/option/PhabricatorMailgunConfigOptions.php', 'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php', 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', 'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php', 'PhabricatorManagementWorkflow' => 'infrastructure/management/PhabricatorManagementWorkflow.php', 'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php', 'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php', 'PhabricatorManiphestTaskTestDataGenerator' => 'applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php', 'PhabricatorManualActivitySetupCheck' => 'applications/config/check/PhabricatorManualActivitySetupCheck.php', 'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php', 'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php', 'PhabricatorMarkupEngineTestCase' => 'infrastructure/markup/__tests__/PhabricatorMarkupEngineTestCase.php', 'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php', 'PhabricatorMarkupOneOff' => 'infrastructure/markup/PhabricatorMarkupOneOff.php', 'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php', 'PhabricatorMemeRemarkupRule' => 'applications/macro/markup/PhabricatorMemeRemarkupRule.php', 'PhabricatorMentionRemarkupRule' => 'applications/people/markup/PhabricatorMentionRemarkupRule.php', 'PhabricatorMentionableInterface' => 'applications/transactions/interface/PhabricatorMentionableInterface.php', 'PhabricatorMercurialGraphStream' => 'applications/repository/daemon/PhabricatorMercurialGraphStream.php', 'PhabricatorMetaMTAActor' => 'applications/metamta/query/PhabricatorMetaMTAActor.php', 'PhabricatorMetaMTAActorQuery' => 'applications/metamta/query/PhabricatorMetaMTAActorQuery.php', 'PhabricatorMetaMTAApplication' => 'applications/metamta/application/PhabricatorMetaMTAApplication.php', 'PhabricatorMetaMTAApplicationEmail' => 'applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php', 'PhabricatorMetaMTAApplicationEmailDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAApplicationEmailDatasource.php', 'PhabricatorMetaMTAApplicationEmailEditor' => 'applications/metamta/editor/PhabricatorMetaMTAApplicationEmailEditor.php', 'PhabricatorMetaMTAApplicationEmailHeraldField' => 'applications/metamta/herald/PhabricatorMetaMTAApplicationEmailHeraldField.php', 'PhabricatorMetaMTAApplicationEmailPHIDType' => 'applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php', 'PhabricatorMetaMTAApplicationEmailPanel' => 'applications/metamta/applicationpanel/PhabricatorMetaMTAApplicationEmailPanel.php', 'PhabricatorMetaMTAApplicationEmailQuery' => 'applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php', 'PhabricatorMetaMTAApplicationEmailTransaction' => 'applications/metamta/storage/PhabricatorMetaMTAApplicationEmailTransaction.php', 'PhabricatorMetaMTAApplicationEmailTransactionQuery' => 'applications/metamta/query/PhabricatorMetaMTAApplicationEmailTransactionQuery.php', 'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/PhabricatorMetaMTAAttachment.php', 'PhabricatorMetaMTAConfigOptions' => 'applications/config/option/PhabricatorMetaMTAConfigOptions.php', 'PhabricatorMetaMTAController' => 'applications/metamta/controller/PhabricatorMetaMTAController.php', 'PhabricatorMetaMTADAO' => 'applications/metamta/storage/PhabricatorMetaMTADAO.php', 'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser/PhabricatorMetaMTAEmailBodyParser.php', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__/PhabricatorMetaMTAEmailBodyParserTestCase.php', 'PhabricatorMetaMTAEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMetaMTAEmailHeraldAction.php', 'PhabricatorMetaMTAEmailOthersHeraldAction' => 'applications/metamta/herald/PhabricatorMetaMTAEmailOthersHeraldAction.php', 'PhabricatorMetaMTAEmailSelfHeraldAction' => 'applications/metamta/herald/PhabricatorMetaMTAEmailSelfHeraldAction.php', 'PhabricatorMetaMTAErrorMailAction' => 'applications/metamta/action/PhabricatorMetaMTAErrorMailAction.php', 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php', 'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php', 'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php', 'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'applications/metamta/edge/PhabricatorMetaMTAMailHasRecipientEdgeType.php', 'PhabricatorMetaMTAMailListController' => 'applications/metamta/controller/PhabricatorMetaMTAMailListController.php', 'PhabricatorMetaMTAMailPHIDType' => 'applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php', 'PhabricatorMetaMTAMailQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailQuery.php', 'PhabricatorMetaMTAMailSearchEngine' => 'applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php', 'PhabricatorMetaMTAMailSection' => 'applications/metamta/view/PhabricatorMetaMTAMailSection.php', 'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php', 'PhabricatorMetaMTAMailViewController' => 'applications/metamta/controller/PhabricatorMetaMTAMailViewController.php', 'PhabricatorMetaMTAMailableDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableDatasource.php', 'PhabricatorMetaMTAMailableFunctionDatasource' => 'applications/metamta/typeahead/PhabricatorMetaMTAMailableFunctionDatasource.php', 'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php', 'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php', 'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php', 'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php', 'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php', 'PhabricatorMetaMTASchemaSpec' => 'applications/metamta/storage/PhabricatorMetaMTASchemaSpec.php', 'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php', 'PhabricatorMetaMTAWorker' => 'applications/metamta/PhabricatorMetaMTAWorker.php', 'PhabricatorMetronomicTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorMetronomicTriggerClock.php', 'PhabricatorModularTransaction' => 'applications/transactions/storage/PhabricatorModularTransaction.php', 'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php', 'PhabricatorMonospacedFontSetting' => 'applications/settings/setting/PhabricatorMonospacedFontSetting.php', 'PhabricatorMonospacedTextareasSetting' => 'applications/settings/setting/PhabricatorMonospacedTextareasSetting.php', - 'PhabricatorMotivatorProfilePanel' => 'applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php', + 'PhabricatorMotivatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php', 'PhabricatorMultiColumnUIExample' => 'applications/uiexample/examples/PhabricatorMultiColumnUIExample.php', 'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php', 'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php', 'PhabricatorMustVerifyEmailController' => 'applications/auth/controller/PhabricatorMustVerifyEmailController.php', 'PhabricatorMySQLConfigOptions' => 'applications/config/option/PhabricatorMySQLConfigOptions.php', 'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php', 'PhabricatorMySQLFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorMySQLFulltextStorageEngine.php', 'PhabricatorMySQLSetupCheck' => 'applications/config/check/PhabricatorMySQLSetupCheck.php', 'PhabricatorNamedQuery' => 'applications/search/storage/PhabricatorNamedQuery.php', 'PhabricatorNamedQueryQuery' => 'applications/search/query/PhabricatorNamedQueryQuery.php', 'PhabricatorNavigationRemarkupRule' => 'infrastructure/markup/rule/PhabricatorNavigationRemarkupRule.php', 'PhabricatorNeverTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorNeverTriggerClock.php', 'PhabricatorNgramsIndexEngineExtension' => 'applications/search/engineextension/PhabricatorNgramsIndexEngineExtension.php', 'PhabricatorNgramsInterface' => 'applications/search/interface/PhabricatorNgramsInterface.php', 'PhabricatorNotificationBuilder' => 'applications/notification/builder/PhabricatorNotificationBuilder.php', 'PhabricatorNotificationClearController' => 'applications/notification/controller/PhabricatorNotificationClearController.php', 'PhabricatorNotificationClient' => 'applications/notification/client/PhabricatorNotificationClient.php', 'PhabricatorNotificationConfigOptions' => 'applications/config/option/PhabricatorNotificationConfigOptions.php', 'PhabricatorNotificationController' => 'applications/notification/controller/PhabricatorNotificationController.php', 'PhabricatorNotificationDestructionEngineExtension' => 'applications/notification/engineextension/PhabricatorNotificationDestructionEngineExtension.php', 'PhabricatorNotificationIndividualController' => 'applications/notification/controller/PhabricatorNotificationIndividualController.php', 'PhabricatorNotificationListController' => 'applications/notification/controller/PhabricatorNotificationListController.php', 'PhabricatorNotificationPanelController' => 'applications/notification/controller/PhabricatorNotificationPanelController.php', 'PhabricatorNotificationQuery' => 'applications/notification/query/PhabricatorNotificationQuery.php', 'PhabricatorNotificationSearchEngine' => 'applications/notification/query/PhabricatorNotificationSearchEngine.php', 'PhabricatorNotificationServerRef' => 'applications/notification/client/PhabricatorNotificationServerRef.php', 'PhabricatorNotificationServersConfigOptionType' => 'applications/notification/config/PhabricatorNotificationServersConfigOptionType.php', 'PhabricatorNotificationStatusView' => 'applications/notification/view/PhabricatorNotificationStatusView.php', 'PhabricatorNotificationTestController' => 'applications/notification/controller/PhabricatorNotificationTestController.php', 'PhabricatorNotificationTestFeedStory' => 'applications/notification/feed/PhabricatorNotificationTestFeedStory.php', 'PhabricatorNotificationUIExample' => 'applications/uiexample/examples/PhabricatorNotificationUIExample.php', 'PhabricatorNotificationsApplication' => 'applications/notification/application/PhabricatorNotificationsApplication.php', 'PhabricatorNuanceApplication' => 'applications/nuance/application/PhabricatorNuanceApplication.php', 'PhabricatorOAuth1AuthProvider' => 'applications/auth/provider/PhabricatorOAuth1AuthProvider.php', 'PhabricatorOAuth1SecretTemporaryTokenType' => 'applications/auth/provider/PhabricatorOAuth1SecretTemporaryTokenType.php', 'PhabricatorOAuth2AuthProvider' => 'applications/auth/provider/PhabricatorOAuth2AuthProvider.php', 'PhabricatorOAuthAuthProvider' => 'applications/auth/provider/PhabricatorOAuthAuthProvider.php', 'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php', 'PhabricatorOAuthClientAuthorizationQuery' => 'applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php', 'PhabricatorOAuthClientController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientController.php', 'PhabricatorOAuthClientDisableController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientDisableController.php', 'PhabricatorOAuthClientEditController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientEditController.php', 'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientListController.php', 'PhabricatorOAuthClientSecretController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientSecretController.php', 'PhabricatorOAuthClientTestController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientTestController.php', 'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientViewController.php', 'PhabricatorOAuthResponse' => 'applications/oauthserver/PhabricatorOAuthResponse.php', 'PhabricatorOAuthServer' => 'applications/oauthserver/PhabricatorOAuthServer.php', 'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php', 'PhabricatorOAuthServerApplication' => 'applications/oauthserver/application/PhabricatorOAuthServerApplication.php', 'PhabricatorOAuthServerAuthController' => 'applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php', 'PhabricatorOAuthServerAuthorizationCode' => 'applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php', 'PhabricatorOAuthServerAuthorizationsSettingsPanel' => 'applications/oauthserver/panel/PhabricatorOAuthServerAuthorizationsSettingsPanel.php', 'PhabricatorOAuthServerClient' => 'applications/oauthserver/storage/PhabricatorOAuthServerClient.php', 'PhabricatorOAuthServerClientAuthorizationPHIDType' => 'applications/oauthserver/phid/PhabricatorOAuthServerClientAuthorizationPHIDType.php', 'PhabricatorOAuthServerClientPHIDType' => 'applications/oauthserver/phid/PhabricatorOAuthServerClientPHIDType.php', 'PhabricatorOAuthServerClientQuery' => 'applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php', 'PhabricatorOAuthServerClientSearchEngine' => 'applications/oauthserver/query/PhabricatorOAuthServerClientSearchEngine.php', 'PhabricatorOAuthServerController' => 'applications/oauthserver/controller/PhabricatorOAuthServerController.php', 'PhabricatorOAuthServerCreateClientsCapability' => 'applications/oauthserver/capability/PhabricatorOAuthServerCreateClientsCapability.php', 'PhabricatorOAuthServerDAO' => 'applications/oauthserver/storage/PhabricatorOAuthServerDAO.php', 'PhabricatorOAuthServerEditEngine' => 'applications/oauthserver/editor/PhabricatorOAuthServerEditEngine.php', 'PhabricatorOAuthServerEditor' => 'applications/oauthserver/editor/PhabricatorOAuthServerEditor.php', 'PhabricatorOAuthServerSchemaSpec' => 'applications/oauthserver/query/PhabricatorOAuthServerSchemaSpec.php', 'PhabricatorOAuthServerScope' => 'applications/oauthserver/PhabricatorOAuthServerScope.php', 'PhabricatorOAuthServerTestCase' => 'applications/oauthserver/__tests__/PhabricatorOAuthServerTestCase.php', 'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/PhabricatorOAuthServerTokenController.php', 'PhabricatorOAuthServerTransaction' => 'applications/oauthserver/storage/PhabricatorOAuthServerTransaction.php', 'PhabricatorOAuthServerTransactionQuery' => 'applications/oauthserver/query/PhabricatorOAuthServerTransactionQuery.php', 'PhabricatorObjectGraph' => 'infrastructure/graph/PhabricatorObjectGraph.php', 'PhabricatorObjectHandle' => 'applications/phid/PhabricatorObjectHandle.php', 'PhabricatorObjectHasAsanaSubtaskEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasAsanaSubtaskEdgeType.php', 'PhabricatorObjectHasAsanaTaskEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasAsanaTaskEdgeType.php', 'PhabricatorObjectHasContributorEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasContributorEdgeType.php', 'PhabricatorObjectHasFileEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasFileEdgeType.php', 'PhabricatorObjectHasJiraIssueEdgeType' => 'applications/doorkeeper/edge/PhabricatorObjectHasJiraIssueEdgeType.php', 'PhabricatorObjectHasSubscriberEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasSubscriberEdgeType.php', 'PhabricatorObjectHasUnsubscriberEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasUnsubscriberEdgeType.php', 'PhabricatorObjectHasWatcherEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasWatcherEdgeType.php', 'PhabricatorObjectListQuery' => 'applications/phid/query/PhabricatorObjectListQuery.php', 'PhabricatorObjectListQueryTestCase' => 'applications/phid/query/__tests__/PhabricatorObjectListQueryTestCase.php', 'PhabricatorObjectMailReceiver' => 'applications/metamta/receiver/PhabricatorObjectMailReceiver.php', 'PhabricatorObjectMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php', 'PhabricatorObjectMentionedByObjectEdgeType' => 'applications/transactions/edges/PhabricatorObjectMentionedByObjectEdgeType.php', 'PhabricatorObjectMentionsObjectEdgeType' => 'applications/transactions/edges/PhabricatorObjectMentionsObjectEdgeType.php', 'PhabricatorObjectQuery' => 'applications/phid/query/PhabricatorObjectQuery.php', 'PhabricatorObjectRelationship' => 'applications/search/relationship/PhabricatorObjectRelationship.php', 'PhabricatorObjectRelationshipList' => 'applications/search/relationship/PhabricatorObjectRelationshipList.php', 'PhabricatorObjectRelationshipSource' => 'applications/search/relationship/PhabricatorObjectRelationshipSource.php', 'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php', 'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php', 'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php', 'PhabricatorOldWorldContentSource' => 'infrastructure/contentsource/PhabricatorOldWorldContentSource.php', 'PhabricatorOlderInlinesSetting' => 'applications/settings/setting/PhabricatorOlderInlinesSetting.php', 'PhabricatorOneTimeTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorOneTimeTriggerClock.php', 'PhabricatorOpcodeCacheSpec' => 'applications/cache/spec/PhabricatorOpcodeCacheSpec.php', 'PhabricatorOptionGroupSetting' => 'applications/settings/setting/PhabricatorOptionGroupSetting.php', 'PhabricatorOwnerPathQuery' => 'applications/owners/query/PhabricatorOwnerPathQuery.php', 'PhabricatorOwnersApplication' => 'applications/owners/application/PhabricatorOwnersApplication.php', 'PhabricatorOwnersArchiveController' => 'applications/owners/controller/PhabricatorOwnersArchiveController.php', 'PhabricatorOwnersConfigOptions' => 'applications/owners/config/PhabricatorOwnersConfigOptions.php', 'PhabricatorOwnersConfiguredCustomField' => 'applications/owners/customfield/PhabricatorOwnersConfiguredCustomField.php', 'PhabricatorOwnersController' => 'applications/owners/controller/PhabricatorOwnersController.php', 'PhabricatorOwnersCustomField' => 'applications/owners/customfield/PhabricatorOwnersCustomField.php', 'PhabricatorOwnersCustomFieldNumericIndex' => 'applications/owners/storage/PhabricatorOwnersCustomFieldNumericIndex.php', 'PhabricatorOwnersCustomFieldStorage' => 'applications/owners/storage/PhabricatorOwnersCustomFieldStorage.php', 'PhabricatorOwnersCustomFieldStringIndex' => 'applications/owners/storage/PhabricatorOwnersCustomFieldStringIndex.php', 'PhabricatorOwnersDAO' => 'applications/owners/storage/PhabricatorOwnersDAO.php', 'PhabricatorOwnersDefaultEditCapability' => 'applications/owners/capability/PhabricatorOwnersDefaultEditCapability.php', 'PhabricatorOwnersDefaultViewCapability' => 'applications/owners/capability/PhabricatorOwnersDefaultViewCapability.php', 'PhabricatorOwnersDetailController' => 'applications/owners/controller/PhabricatorOwnersDetailController.php', 'PhabricatorOwnersEditController' => 'applications/owners/controller/PhabricatorOwnersEditController.php', 'PhabricatorOwnersListController' => 'applications/owners/controller/PhabricatorOwnersListController.php', 'PhabricatorOwnersOwner' => 'applications/owners/storage/PhabricatorOwnersOwner.php', 'PhabricatorOwnersPackage' => 'applications/owners/storage/PhabricatorOwnersPackage.php', 'PhabricatorOwnersPackageAuditingTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageAuditingTransaction.php', 'PhabricatorOwnersPackageAutoreviewTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageAutoreviewTransaction.php', 'PhabricatorOwnersPackageDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php', 'PhabricatorOwnersPackageDescriptionTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageDescriptionTransaction.php', 'PhabricatorOwnersPackageDominionTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageDominionTransaction.php', 'PhabricatorOwnersPackageEditEngine' => 'applications/owners/editor/PhabricatorOwnersPackageEditEngine.php', 'PhabricatorOwnersPackageFulltextEngine' => 'applications/owners/query/PhabricatorOwnersPackageFulltextEngine.php', 'PhabricatorOwnersPackageFunctionDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php', 'PhabricatorOwnersPackageNameNgrams' => 'applications/owners/storage/PhabricatorOwnersPackageNameNgrams.php', 'PhabricatorOwnersPackageNameTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageNameTransaction.php', 'PhabricatorOwnersPackageOwnerDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageOwnerDatasource.php', 'PhabricatorOwnersPackageOwnersTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageOwnersTransaction.php', 'PhabricatorOwnersPackagePHIDType' => 'applications/owners/phid/PhabricatorOwnersPackagePHIDType.php', 'PhabricatorOwnersPackagePathsTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackagePathsTransaction.php', 'PhabricatorOwnersPackagePrimaryTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackagePrimaryTransaction.php', 'PhabricatorOwnersPackageQuery' => 'applications/owners/query/PhabricatorOwnersPackageQuery.php', 'PhabricatorOwnersPackageRemarkupRule' => 'applications/owners/remarkup/PhabricatorOwnersPackageRemarkupRule.php', 'PhabricatorOwnersPackageSearchEngine' => 'applications/owners/query/PhabricatorOwnersPackageSearchEngine.php', 'PhabricatorOwnersPackageStatusTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageStatusTransaction.php', 'PhabricatorOwnersPackageTestCase' => 'applications/owners/storage/__tests__/PhabricatorOwnersPackageTestCase.php', 'PhabricatorOwnersPackageTransaction' => 'applications/owners/storage/PhabricatorOwnersPackageTransaction.php', 'PhabricatorOwnersPackageTransactionEditor' => 'applications/owners/editor/PhabricatorOwnersPackageTransactionEditor.php', 'PhabricatorOwnersPackageTransactionQuery' => 'applications/owners/query/PhabricatorOwnersPackageTransactionQuery.php', 'PhabricatorOwnersPackageTransactionType' => 'applications/owners/xaction/PhabricatorOwnersPackageTransactionType.php', 'PhabricatorOwnersPath' => 'applications/owners/storage/PhabricatorOwnersPath.php', 'PhabricatorOwnersPathsController' => 'applications/owners/controller/PhabricatorOwnersPathsController.php', 'PhabricatorOwnersPathsSearchEngineAttachment' => 'applications/owners/engineextension/PhabricatorOwnersPathsSearchEngineAttachment.php', 'PhabricatorOwnersSchemaSpec' => 'applications/owners/storage/PhabricatorOwnersSchemaSpec.php', 'PhabricatorOwnersSearchField' => 'applications/owners/searchfield/PhabricatorOwnersSearchField.php', 'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php', 'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php', 'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php', 'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php', 'PhabricatorPHIDListEditField' => 'applications/transactions/editfield/PhabricatorPHIDListEditField.php', 'PhabricatorPHIDListEditType' => 'applications/transactions/edittype/PhabricatorPHIDListEditType.php', 'PhabricatorPHIDResolver' => 'applications/phid/resolver/PhabricatorPHIDResolver.php', 'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php', 'PhabricatorPHIDTypeTestCase' => 'applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php', 'PhabricatorPHIDsSearchField' => 'applications/search/field/PhabricatorPHIDsSearchField.php', 'PhabricatorPHPASTApplication' => 'applications/phpast/application/PhabricatorPHPASTApplication.php', 'PhabricatorPHPConfigSetupCheck' => 'applications/config/check/PhabricatorPHPConfigSetupCheck.php', 'PhabricatorPHPMailerConfigOptions' => 'applications/config/option/PhabricatorPHPMailerConfigOptions.php', 'PhabricatorPHPPreflightSetupCheck' => 'applications/config/check/PhabricatorPHPPreflightSetupCheck.php', 'PhabricatorPackagesApplication' => 'applications/packages/application/PhabricatorPackagesApplication.php', 'PhabricatorPackagesController' => 'applications/packages/controller/PhabricatorPackagesController.php', 'PhabricatorPackagesCreatePublisherCapability' => 'applications/packages/capability/PhabricatorPackagesCreatePublisherCapability.php', 'PhabricatorPackagesDAO' => 'applications/packages/storage/PhabricatorPackagesDAO.php', 'PhabricatorPackagesEditEngine' => 'applications/packages/editor/PhabricatorPackagesEditEngine.php', 'PhabricatorPackagesEditor' => 'applications/packages/editor/PhabricatorPackagesEditor.php', 'PhabricatorPackagesNgrams' => 'applications/packages/storage/PhabricatorPackagesNgrams.php', 'PhabricatorPackagesPackage' => 'applications/packages/storage/PhabricatorPackagesPackage.php', 'PhabricatorPackagesPackageController' => 'applications/packages/controller/PhabricatorPackagesPackageController.php', 'PhabricatorPackagesPackageDatasource' => 'applications/packages/typeahead/PhabricatorPackagesPackageDatasource.php', 'PhabricatorPackagesPackageDefaultEditCapability' => 'applications/packages/capability/PhabricatorPackagesPackageDefaultEditCapability.php', 'PhabricatorPackagesPackageDefaultViewCapability' => 'applications/packages/capability/PhabricatorPackagesPackageDefaultViewCapability.php', 'PhabricatorPackagesPackageEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPackageEditConduitAPIMethod.php', 'PhabricatorPackagesPackageEditController' => 'applications/packages/controller/PhabricatorPackagesPackageEditController.php', 'PhabricatorPackagesPackageEditEngine' => 'applications/packages/editor/PhabricatorPackagesPackageEditEngine.php', 'PhabricatorPackagesPackageEditor' => 'applications/packages/editor/PhabricatorPackagesPackageEditor.php', 'PhabricatorPackagesPackageKeyTransaction' => 'applications/packages/xaction/package/PhabricatorPackagesPackageKeyTransaction.php', 'PhabricatorPackagesPackageListController' => 'applications/packages/controller/PhabricatorPackagesPackageListController.php', 'PhabricatorPackagesPackageListView' => 'applications/packages/view/PhabricatorPackagesPackageListView.php', 'PhabricatorPackagesPackageNameNgrams' => 'applications/packages/storage/PhabricatorPackagesPackageNameNgrams.php', 'PhabricatorPackagesPackageNameTransaction' => 'applications/packages/xaction/package/PhabricatorPackagesPackageNameTransaction.php', 'PhabricatorPackagesPackagePHIDType' => 'applications/packages/phid/PhabricatorPackagesPackagePHIDType.php', 'PhabricatorPackagesPackagePublisherTransaction' => 'applications/packages/xaction/package/PhabricatorPackagesPackagePublisherTransaction.php', 'PhabricatorPackagesPackageQuery' => 'applications/packages/query/PhabricatorPackagesPackageQuery.php', 'PhabricatorPackagesPackageSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPackageSearchConduitAPIMethod.php', 'PhabricatorPackagesPackageSearchEngine' => 'applications/packages/query/PhabricatorPackagesPackageSearchEngine.php', 'PhabricatorPackagesPackageTransaction' => 'applications/packages/storage/PhabricatorPackagesPackageTransaction.php', 'PhabricatorPackagesPackageTransactionQuery' => 'applications/packages/query/PhabricatorPackagesPackageTransactionQuery.php', 'PhabricatorPackagesPackageTransactionType' => 'applications/packages/xaction/package/PhabricatorPackagesPackageTransactionType.php', 'PhabricatorPackagesPackageViewController' => 'applications/packages/controller/PhabricatorPackagesPackageViewController.php', 'PhabricatorPackagesPublisher' => 'applications/packages/storage/PhabricatorPackagesPublisher.php', 'PhabricatorPackagesPublisherController' => 'applications/packages/controller/PhabricatorPackagesPublisherController.php', 'PhabricatorPackagesPublisherDatasource' => 'applications/packages/typeahead/PhabricatorPackagesPublisherDatasource.php', 'PhabricatorPackagesPublisherDefaultEditCapability' => 'applications/packages/capability/PhabricatorPackagesPublisherDefaultEditCapability.php', 'PhabricatorPackagesPublisherEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPublisherEditConduitAPIMethod.php', 'PhabricatorPackagesPublisherEditController' => 'applications/packages/controller/PhabricatorPackagesPublisherEditController.php', 'PhabricatorPackagesPublisherEditEngine' => 'applications/packages/editor/PhabricatorPackagesPublisherEditEngine.php', 'PhabricatorPackagesPublisherEditor' => 'applications/packages/editor/PhabricatorPackagesPublisherEditor.php', 'PhabricatorPackagesPublisherKeyTransaction' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherKeyTransaction.php', 'PhabricatorPackagesPublisherListController' => 'applications/packages/controller/PhabricatorPackagesPublisherListController.php', 'PhabricatorPackagesPublisherListView' => 'applications/packages/view/PhabricatorPackagesPublisherListView.php', 'PhabricatorPackagesPublisherNameNgrams' => 'applications/packages/storage/PhabricatorPackagesPublisherNameNgrams.php', 'PhabricatorPackagesPublisherNameTransaction' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherNameTransaction.php', 'PhabricatorPackagesPublisherPHIDType' => 'applications/packages/phid/PhabricatorPackagesPublisherPHIDType.php', 'PhabricatorPackagesPublisherQuery' => 'applications/packages/query/PhabricatorPackagesPublisherQuery.php', 'PhabricatorPackagesPublisherSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPublisherSearchConduitAPIMethod.php', 'PhabricatorPackagesPublisherSearchEngine' => 'applications/packages/query/PhabricatorPackagesPublisherSearchEngine.php', 'PhabricatorPackagesPublisherTransaction' => 'applications/packages/storage/PhabricatorPackagesPublisherTransaction.php', 'PhabricatorPackagesPublisherTransactionQuery' => 'applications/packages/query/PhabricatorPackagesPublisherTransactionQuery.php', 'PhabricatorPackagesPublisherTransactionType' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherTransactionType.php', 'PhabricatorPackagesPublisherViewController' => 'applications/packages/controller/PhabricatorPackagesPublisherViewController.php', 'PhabricatorPackagesQuery' => 'applications/packages/query/PhabricatorPackagesQuery.php', 'PhabricatorPackagesSchemaSpec' => 'applications/packages/storage/PhabricatorPackagesSchemaSpec.php', 'PhabricatorPackagesTransactionType' => 'applications/packages/xaction/PhabricatorPackagesTransactionType.php', 'PhabricatorPackagesVersion' => 'applications/packages/storage/PhabricatorPackagesVersion.php', 'PhabricatorPackagesVersionController' => 'applications/packages/controller/PhabricatorPackagesVersionController.php', 'PhabricatorPackagesVersionEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesVersionEditConduitAPIMethod.php', 'PhabricatorPackagesVersionEditController' => 'applications/packages/controller/PhabricatorPackagesVersionEditController.php', 'PhabricatorPackagesVersionEditEngine' => 'applications/packages/editor/PhabricatorPackagesVersionEditEngine.php', 'PhabricatorPackagesVersionEditor' => 'applications/packages/editor/PhabricatorPackagesVersionEditor.php', 'PhabricatorPackagesVersionListController' => 'applications/packages/controller/PhabricatorPackagesVersionListController.php', 'PhabricatorPackagesVersionListView' => 'applications/packages/view/PhabricatorPackagesVersionListView.php', 'PhabricatorPackagesVersionNameNgrams' => 'applications/packages/storage/PhabricatorPackagesVersionNameNgrams.php', 'PhabricatorPackagesVersionNameTransaction' => 'applications/packages/xaction/version/PhabricatorPackagesVersionNameTransaction.php', 'PhabricatorPackagesVersionPHIDType' => 'applications/packages/phid/PhabricatorPackagesVersionPHIDType.php', 'PhabricatorPackagesVersionPackageTransaction' => 'applications/packages/xaction/version/PhabricatorPackagesVersionPackageTransaction.php', 'PhabricatorPackagesVersionQuery' => 'applications/packages/query/PhabricatorPackagesVersionQuery.php', 'PhabricatorPackagesVersionSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesVersionSearchConduitAPIMethod.php', 'PhabricatorPackagesVersionSearchEngine' => 'applications/packages/query/PhabricatorPackagesVersionSearchEngine.php', 'PhabricatorPackagesVersionTransaction' => 'applications/packages/storage/PhabricatorPackagesVersionTransaction.php', 'PhabricatorPackagesVersionTransactionQuery' => 'applications/packages/query/PhabricatorPackagesVersionTransactionQuery.php', 'PhabricatorPackagesVersionTransactionType' => 'applications/packages/xaction/version/PhabricatorPackagesVersionTransactionType.php', 'PhabricatorPackagesVersionViewController' => 'applications/packages/controller/PhabricatorPackagesVersionViewController.php', 'PhabricatorPackagesView' => 'applications/packages/view/PhabricatorPackagesView.php', 'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php', 'PhabricatorPassphraseApplication' => 'applications/passphrase/application/PhabricatorPassphraseApplication.php', 'PhabricatorPasswordAuthProvider' => 'applications/auth/provider/PhabricatorPasswordAuthProvider.php', 'PhabricatorPasswordHasher' => 'infrastructure/util/password/PhabricatorPasswordHasher.php', 'PhabricatorPasswordHasherTestCase' => 'infrastructure/util/password/__tests__/PhabricatorPasswordHasherTestCase.php', 'PhabricatorPasswordHasherUnavailableException' => 'infrastructure/util/password/PhabricatorPasswordHasherUnavailableException.php', 'PhabricatorPasswordSettingsPanel' => 'applications/settings/panel/PhabricatorPasswordSettingsPanel.php', 'PhabricatorPaste' => 'applications/paste/storage/PhabricatorPaste.php', 'PhabricatorPasteApplication' => 'applications/paste/application/PhabricatorPasteApplication.php', 'PhabricatorPasteArchiveController' => 'applications/paste/controller/PhabricatorPasteArchiveController.php', 'PhabricatorPasteConfigOptions' => 'applications/paste/config/PhabricatorPasteConfigOptions.php', 'PhabricatorPasteContentSearchEngineAttachment' => 'applications/paste/engineextension/PhabricatorPasteContentSearchEngineAttachment.php', 'PhabricatorPasteContentTransaction' => 'applications/paste/xaction/PhabricatorPasteContentTransaction.php', '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', 'PhabricatorPasteFilenameContextFreeGrammar' => 'applications/paste/lipsum/PhabricatorPasteFilenameContextFreeGrammar.php', 'PhabricatorPasteLanguageTransaction' => 'applications/paste/xaction/PhabricatorPasteLanguageTransaction.php', 'PhabricatorPasteListController' => 'applications/paste/controller/PhabricatorPasteListController.php', 'PhabricatorPastePastePHIDType' => 'applications/paste/phid/PhabricatorPastePastePHIDType.php', 'PhabricatorPasteQuery' => 'applications/paste/query/PhabricatorPasteQuery.php', 'PhabricatorPasteRawController' => 'applications/paste/controller/PhabricatorPasteRawController.php', 'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php', 'PhabricatorPasteSchemaSpec' => 'applications/paste/storage/PhabricatorPasteSchemaSpec.php', 'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php', 'PhabricatorPasteSnippet' => 'applications/paste/snippet/PhabricatorPasteSnippet.php', 'PhabricatorPasteStatusTransaction' => 'applications/paste/xaction/PhabricatorPasteStatusTransaction.php', 'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php', 'PhabricatorPasteTitleTransaction' => 'applications/paste/xaction/PhabricatorPasteTitleTransaction.php', 'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php', 'PhabricatorPasteTransactionComment' => 'applications/paste/storage/PhabricatorPasteTransactionComment.php', 'PhabricatorPasteTransactionQuery' => 'applications/paste/query/PhabricatorPasteTransactionQuery.php', 'PhabricatorPasteTransactionType' => 'applications/paste/xaction/PhabricatorPasteTransactionType.php', 'PhabricatorPasteViewController' => 'applications/paste/controller/PhabricatorPasteViewController.php', 'PhabricatorPathSetupCheck' => 'applications/config/check/PhabricatorPathSetupCheck.php', 'PhabricatorPeopleAnyOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleAnyOwnerDatasource.php', 'PhabricatorPeopleApplication' => 'applications/people/application/PhabricatorPeopleApplication.php', 'PhabricatorPeopleApproveController' => 'applications/people/controller/PhabricatorPeopleApproveController.php', 'PhabricatorPeopleController' => 'applications/people/controller/PhabricatorPeopleController.php', 'PhabricatorPeopleCreateController' => 'applications/people/controller/PhabricatorPeopleCreateController.php', 'PhabricatorPeopleCreateGuidanceContext' => 'applications/people/guidance/PhabricatorPeopleCreateGuidanceContext.php', 'PhabricatorPeopleDatasource' => 'applications/people/typeahead/PhabricatorPeopleDatasource.php', 'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php', - 'PhabricatorPeopleDetailsProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php', + 'PhabricatorPeopleDetailsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php', 'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php', 'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', 'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', 'PhabricatorPeopleIconSet' => 'applications/people/icon/PhabricatorPeopleIconSet.php', 'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php', 'PhabricatorPeopleInviteListController' => 'applications/people/controller/PhabricatorPeopleInviteListController.php', 'PhabricatorPeopleInviteSendController' => 'applications/people/controller/PhabricatorPeopleInviteSendController.php', 'PhabricatorPeopleLdapController' => 'applications/people/controller/PhabricatorPeopleLdapController.php', 'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php', 'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php', 'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleMainMenuBarExtension' => 'applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php', - 'PhabricatorPeopleManageProfilePanel' => 'applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php', + 'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php', 'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php', 'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php', 'PhabricatorPeopleOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleOwnerDatasource.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php', 'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php', - 'PhabricatorPeopleProfilePanelEngine' => 'applications/people/engine/PhabricatorPeopleProfilePanelEngine.php', + 'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php', 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', 'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php', 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php', 'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', 'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', 'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php', 'PhabricatorPeopleTransactionQuery' => 'applications/people/query/PhabricatorPeopleTransactionQuery.php', 'PhabricatorPeopleUserFunctionDatasource' => 'applications/people/typeahead/PhabricatorPeopleUserFunctionDatasource.php', 'PhabricatorPeopleUserPHIDType' => 'applications/people/phid/PhabricatorPeopleUserPHIDType.php', 'PhabricatorPeopleWelcomeController' => 'applications/people/controller/PhabricatorPeopleWelcomeController.php', 'PhabricatorPhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorPhabricatorAuthProvider.php', 'PhabricatorPhameApplication' => 'applications/phame/application/PhabricatorPhameApplication.php', 'PhabricatorPhameBlogPHIDType' => 'applications/phame/phid/PhabricatorPhameBlogPHIDType.php', 'PhabricatorPhamePostPHIDType' => 'applications/phame/phid/PhabricatorPhamePostPHIDType.php', 'PhabricatorPhluxApplication' => 'applications/phlux/application/PhabricatorPhluxApplication.php', 'PhabricatorPholioApplication' => 'applications/pholio/application/PhabricatorPholioApplication.php', 'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php', 'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php', 'PhabricatorPhortuneApplication' => 'applications/phortune/application/PhabricatorPhortuneApplication.php', 'PhabricatorPhortuneContentSource' => 'applications/phortune/contentsource/PhabricatorPhortuneContentSource.php', 'PhabricatorPhortuneManagementInvoiceWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php', 'PhabricatorPhortuneManagementWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementWorkflow.php', 'PhabricatorPhragmentApplication' => 'applications/phragment/application/PhabricatorPhragmentApplication.php', 'PhabricatorPhrequentApplication' => 'applications/phrequent/application/PhabricatorPhrequentApplication.php', 'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php', 'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php', 'PhabricatorPhurlApplication' => 'applications/phurl/application/PhabricatorPhurlApplication.php', 'PhabricatorPhurlConfigOptions' => 'applications/config/option/PhabricatorPhurlConfigOptions.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', 'PhabricatorPhurlShortURLController' => 'applications/phurl/controller/PhabricatorPhurlShortURLController.php', 'PhabricatorPhurlShortURLDefaultController' => 'applications/phurl/controller/PhabricatorPhurlShortURLDefaultController.php', 'PhabricatorPhurlURL' => 'applications/phurl/storage/PhabricatorPhurlURL.php', 'PhabricatorPhurlURLAccessController' => 'applications/phurl/controller/PhabricatorPhurlURLAccessController.php', 'PhabricatorPhurlURLCommentController' => 'applications/phurl/controller/PhabricatorPhurlURLCommentController.php', 'PhabricatorPhurlURLCreateCapability' => 'applications/phurl/capability/PhabricatorPhurlURLCreateCapability.php', 'PhabricatorPhurlURLEditConduitAPIMethod' => 'applications/phurl/conduit/PhabricatorPhurlURLEditConduitAPIMethod.php', 'PhabricatorPhurlURLEditController' => 'applications/phurl/controller/PhabricatorPhurlURLEditController.php', 'PhabricatorPhurlURLEditEngine' => 'applications/phurl/editor/PhabricatorPhurlURLEditEngine.php', 'PhabricatorPhurlURLEditor' => 'applications/phurl/editor/PhabricatorPhurlURLEditor.php', 'PhabricatorPhurlURLListController' => 'applications/phurl/controller/PhabricatorPhurlURLListController.php', 'PhabricatorPhurlURLMailReceiver' => 'applications/phurl/mail/PhabricatorPhurlURLMailReceiver.php', 'PhabricatorPhurlURLNameNgrams' => 'applications/phurl/storage/PhabricatorPhurlURLNameNgrams.php', 'PhabricatorPhurlURLPHIDType' => 'applications/phurl/phid/PhabricatorPhurlURLPHIDType.php', 'PhabricatorPhurlURLQuery' => 'applications/phurl/query/PhabricatorPhurlURLQuery.php', 'PhabricatorPhurlURLReplyHandler' => 'applications/phurl/mail/PhabricatorPhurlURLReplyHandler.php', 'PhabricatorPhurlURLSearchConduitAPIMethod' => 'applications/phurl/conduit/PhabricatorPhurlURLSearchConduitAPIMethod.php', 'PhabricatorPhurlURLSearchEngine' => 'applications/phurl/query/PhabricatorPhurlURLSearchEngine.php', 'PhabricatorPhurlURLTransaction' => 'applications/phurl/storage/PhabricatorPhurlURLTransaction.php', 'PhabricatorPhurlURLTransactionComment' => 'applications/phurl/storage/PhabricatorPhurlURLTransactionComment.php', 'PhabricatorPhurlURLTransactionQuery' => 'applications/phurl/query/PhabricatorPhurlURLTransactionQuery.php', 'PhabricatorPhurlURLViewController' => 'applications/phurl/controller/PhabricatorPhurlURLViewController.php', 'PhabricatorPinnedApplicationsSetting' => 'applications/settings/setting/PhabricatorPinnedApplicationsSetting.php', 'PhabricatorPirateEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorPirateEnglishTranslation.php', 'PhabricatorPlatformSite' => 'aphront/site/PhabricatorPlatformSite.php', 'PhabricatorPointsEditField' => 'applications/transactions/editfield/PhabricatorPointsEditField.php', 'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php', 'PhabricatorPolicy' => 'applications/policy/storage/PhabricatorPolicy.php', 'PhabricatorPolicyApplication' => 'applications/policy/application/PhabricatorPolicyApplication.php', 'PhabricatorPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorPolicyAwareQuery.php', 'PhabricatorPolicyAwareTestQuery' => 'applications/policy/__tests__/PhabricatorPolicyAwareTestQuery.php', 'PhabricatorPolicyCanEditCapability' => 'applications/policy/capability/PhabricatorPolicyCanEditCapability.php', 'PhabricatorPolicyCanJoinCapability' => 'applications/policy/capability/PhabricatorPolicyCanJoinCapability.php', 'PhabricatorPolicyCanViewCapability' => 'applications/policy/capability/PhabricatorPolicyCanViewCapability.php', 'PhabricatorPolicyCapability' => 'applications/policy/capability/PhabricatorPolicyCapability.php', 'PhabricatorPolicyCapabilityTestCase' => 'applications/policy/capability/__tests__/PhabricatorPolicyCapabilityTestCase.php', 'PhabricatorPolicyCodex' => 'applications/policy/codex/PhabricatorPolicyCodex.php', 'PhabricatorPolicyCodexInterface' => 'applications/policy/codex/PhabricatorPolicyCodexInterface.php', 'PhabricatorPolicyCodexRuleDescription' => 'applications/policy/codex/PhabricatorPolicyCodexRuleDescription.php', 'PhabricatorPolicyConfigOptions' => 'applications/policy/config/PhabricatorPolicyConfigOptions.php', 'PhabricatorPolicyConstants' => 'applications/policy/constants/PhabricatorPolicyConstants.php', 'PhabricatorPolicyController' => 'applications/policy/controller/PhabricatorPolicyController.php', 'PhabricatorPolicyDAO' => 'applications/policy/storage/PhabricatorPolicyDAO.php', 'PhabricatorPolicyDataTestCase' => 'applications/policy/__tests__/PhabricatorPolicyDataTestCase.php', 'PhabricatorPolicyEditController' => 'applications/policy/controller/PhabricatorPolicyEditController.php', 'PhabricatorPolicyEditEngineExtension' => 'applications/policy/editor/PhabricatorPolicyEditEngineExtension.php', 'PhabricatorPolicyEditField' => 'applications/transactions/editfield/PhabricatorPolicyEditField.php', 'PhabricatorPolicyException' => 'applications/policy/exception/PhabricatorPolicyException.php', 'PhabricatorPolicyExplainController' => 'applications/policy/controller/PhabricatorPolicyExplainController.php', 'PhabricatorPolicyFavoritesSetting' => 'applications/settings/setting/PhabricatorPolicyFavoritesSetting.php', 'PhabricatorPolicyFilter' => 'applications/policy/filter/PhabricatorPolicyFilter.php', 'PhabricatorPolicyInterface' => 'applications/policy/interface/PhabricatorPolicyInterface.php', 'PhabricatorPolicyManagementShowWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementShowWorkflow.php', 'PhabricatorPolicyManagementUnlockWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementUnlockWorkflow.php', 'PhabricatorPolicyManagementWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementWorkflow.php', 'PhabricatorPolicyPHIDTypePolicy' => 'applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php', 'PhabricatorPolicyQuery' => 'applications/policy/query/PhabricatorPolicyQuery.php', 'PhabricatorPolicyRequestExceptionHandler' => 'aphront/handler/PhabricatorPolicyRequestExceptionHandler.php', 'PhabricatorPolicyRule' => 'applications/policy/rule/PhabricatorPolicyRule.php', 'PhabricatorPolicySearchEngineExtension' => 'applications/policy/engineextension/PhabricatorPolicySearchEngineExtension.php', 'PhabricatorPolicyTestCase' => 'applications/policy/__tests__/PhabricatorPolicyTestCase.php', 'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php', 'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php', 'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php', 'PhabricatorProfileMenuCollapsedSetting' => 'applications/settings/setting/PhabricatorProfileMenuCollapsedSetting.php', - 'PhabricatorProfilePanel' => 'applications/search/profilepanel/PhabricatorProfilePanel.php', - 'PhabricatorProfilePanelConfiguration' => 'applications/search/storage/PhabricatorProfilePanelConfiguration.php', - 'PhabricatorProfilePanelConfigurationQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationQuery.php', - 'PhabricatorProfilePanelConfigurationTransaction' => 'applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php', - 'PhabricatorProfilePanelConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfilePanelConfigurationTransactionQuery.php', - 'PhabricatorProfilePanelEditEngine' => 'applications/search/editor/PhabricatorProfilePanelEditEngine.php', - 'PhabricatorProfilePanelEditor' => 'applications/search/editor/PhabricatorProfilePanelEditor.php', - 'PhabricatorProfilePanelEngine' => 'applications/search/engine/PhabricatorProfilePanelEngine.php', - 'PhabricatorProfilePanelIconSet' => 'applications/search/profilepanel/PhabricatorProfilePanelIconSet.php', - 'PhabricatorProfilePanelPHIDType' => 'applications/search/phidtype/PhabricatorProfilePanelPHIDType.php', + 'PhabricatorProfileMenuEditEngine' => 'applications/search/editor/PhabricatorProfileMenuEditEngine.php', + 'PhabricatorProfileMenuEditor' => 'applications/search/editor/PhabricatorProfileMenuEditor.php', + 'PhabricatorProfileMenuEngine' => 'applications/search/engine/PhabricatorProfileMenuEngine.php', + 'PhabricatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorProfileMenuItem.php', + 'PhabricatorProfileMenuItemConfiguration' => 'applications/search/storage/PhabricatorProfileMenuItemConfiguration.php', + 'PhabricatorProfileMenuItemConfigurationQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php', + 'PhabricatorProfileMenuItemConfigurationTransaction' => 'applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php', + 'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php', + 'PhabricatorProfileMenuItemIconSet' => 'applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php', + 'PhabricatorProfileMenuItemPHIDType' => 'applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php', 'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php', 'PhabricatorProjectAddHeraldAction' => 'applications/project/herald/PhabricatorProjectAddHeraldAction.php', 'PhabricatorProjectApplication' => 'applications/project/application/PhabricatorProjectApplication.php', 'PhabricatorProjectArchiveController' => 'applications/project/controller/PhabricatorProjectArchiveController.php', 'PhabricatorProjectBoardBackgroundController' => 'applications/project/controller/PhabricatorProjectBoardBackgroundController.php', 'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php', 'PhabricatorProjectBoardDisableController' => 'applications/project/controller/PhabricatorProjectBoardDisableController.php', 'PhabricatorProjectBoardImportController' => 'applications/project/controller/PhabricatorProjectBoardImportController.php', 'PhabricatorProjectBoardManageController' => 'applications/project/controller/PhabricatorProjectBoardManageController.php', 'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php', 'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php', 'PhabricatorProjectCardView' => 'applications/project/view/PhabricatorProjectCardView.php', 'PhabricatorProjectColorsConfigOptionType' => 'applications/project/config/PhabricatorProjectColorsConfigOptionType.php', 'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php', 'PhabricatorProjectColumnDetailController' => 'applications/project/controller/PhabricatorProjectColumnDetailController.php', 'PhabricatorProjectColumnEditController' => 'applications/project/controller/PhabricatorProjectColumnEditController.php', 'PhabricatorProjectColumnHideController' => 'applications/project/controller/PhabricatorProjectColumnHideController.php', 'PhabricatorProjectColumnPHIDType' => 'applications/project/phid/PhabricatorProjectColumnPHIDType.php', 'PhabricatorProjectColumnPosition' => 'applications/project/storage/PhabricatorProjectColumnPosition.php', 'PhabricatorProjectColumnPositionQuery' => 'applications/project/query/PhabricatorProjectColumnPositionQuery.php', 'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php', 'PhabricatorProjectColumnTransaction' => 'applications/project/storage/PhabricatorProjectColumnTransaction.php', 'PhabricatorProjectColumnTransactionEditor' => 'applications/project/editor/PhabricatorProjectColumnTransactionEditor.php', 'PhabricatorProjectColumnTransactionQuery' => 'applications/project/query/PhabricatorProjectColumnTransactionQuery.php', 'PhabricatorProjectConfigOptions' => 'applications/project/config/PhabricatorProjectConfigOptions.php', 'PhabricatorProjectConfiguredCustomField' => 'applications/project/customfield/PhabricatorProjectConfiguredCustomField.php', 'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php', 'PhabricatorProjectCoreTestCase' => 'applications/project/__tests__/PhabricatorProjectCoreTestCase.php', 'PhabricatorProjectCoverController' => 'applications/project/controller/PhabricatorProjectCoverController.php', 'PhabricatorProjectCustomField' => 'applications/project/customfield/PhabricatorProjectCustomField.php', 'PhabricatorProjectCustomFieldNumericIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldNumericIndex.php', 'PhabricatorProjectCustomFieldStorage' => 'applications/project/storage/PhabricatorProjectCustomFieldStorage.php', 'PhabricatorProjectCustomFieldStringIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldStringIndex.php', 'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php', 'PhabricatorProjectDatasource' => 'applications/project/typeahead/PhabricatorProjectDatasource.php', 'PhabricatorProjectDefaultController' => 'applications/project/controller/PhabricatorProjectDefaultController.php', 'PhabricatorProjectDescriptionField' => 'applications/project/customfield/PhabricatorProjectDescriptionField.php', - 'PhabricatorProjectDetailsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php', + 'PhabricatorProjectDetailsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php', 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectFulltextEngine' => 'applications/project/search/PhabricatorProjectFulltextEngine.php', 'PhabricatorProjectHeraldAction' => 'applications/project/herald/PhabricatorProjectHeraldAction.php', 'PhabricatorProjectHeraldAdapter' => 'applications/project/herald/PhabricatorProjectHeraldAdapter.php', 'PhabricatorProjectHeraldFieldGroup' => 'applications/project/herald/PhabricatorProjectHeraldFieldGroup.php', 'PhabricatorProjectHovercardEngineExtension' => 'applications/project/engineextension/PhabricatorProjectHovercardEngineExtension.php', 'PhabricatorProjectIconSet' => 'applications/project/icon/PhabricatorProjectIconSet.php', 'PhabricatorProjectIconsConfigOptionType' => 'applications/project/config/PhabricatorProjectIconsConfigOptionType.php', 'PhabricatorProjectInterface' => 'applications/project/interface/PhabricatorProjectInterface.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 'PhabricatorProjectListView' => 'applications/project/view/PhabricatorProjectListView.php', 'PhabricatorProjectLockController' => 'applications/project/controller/PhabricatorProjectLockController.php', 'PhabricatorProjectLogicalAncestorDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php', 'PhabricatorProjectLogicalDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalDatasource.php', 'PhabricatorProjectLogicalOrNotDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalOrNotDatasource.php', 'PhabricatorProjectLogicalUserDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalUserDatasource.php', 'PhabricatorProjectLogicalViewerDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalViewerDatasource.php', 'PhabricatorProjectManageController' => 'applications/project/controller/PhabricatorProjectManageController.php', - 'PhabricatorProjectManageProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php', + 'PhabricatorProjectManageProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php', 'PhabricatorProjectMaterializedMemberEdgeType' => 'applications/project/edge/PhabricatorProjectMaterializedMemberEdgeType.php', 'PhabricatorProjectMemberListView' => 'applications/project/view/PhabricatorProjectMemberListView.php', 'PhabricatorProjectMemberOfProjectEdgeType' => 'applications/project/edge/PhabricatorProjectMemberOfProjectEdgeType.php', 'PhabricatorProjectMembersAddController' => 'applications/project/controller/PhabricatorProjectMembersAddController.php', 'PhabricatorProjectMembersDatasource' => 'applications/project/typeahead/PhabricatorProjectMembersDatasource.php', 'PhabricatorProjectMembersPolicyRule' => 'applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php', - 'PhabricatorProjectMembersProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php', + 'PhabricatorProjectMembersProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php', 'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php', 'PhabricatorProjectMembersViewController' => 'applications/project/controller/PhabricatorProjectMembersViewController.php', + 'PhabricatorProjectMenuItemController' => 'applications/project/controller/PhabricatorProjectMenuItemController.php', 'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php', 'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php', 'PhabricatorProjectNoProjectsDatasource' => 'applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php', 'PhabricatorProjectObjectHasProjectEdgeType' => 'applications/project/edge/PhabricatorProjectObjectHasProjectEdgeType.php', 'PhabricatorProjectOrUserDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserDatasource.php', 'PhabricatorProjectOrUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectOrUserFunctionDatasource.php', 'PhabricatorProjectPHIDResolver' => 'applications/phid/resolver/PhabricatorProjectPHIDResolver.php', - 'PhabricatorProjectPanelController' => 'applications/project/controller/PhabricatorProjectPanelController.php', - 'PhabricatorProjectPointsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php', + 'PhabricatorProjectPointsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', - 'PhabricatorProjectProfilePanelEngine' => 'applications/project/engine/PhabricatorProjectProfilePanelEngine.php', + 'PhabricatorProjectProfileMenuEngine' => 'applications/project/engine/PhabricatorProjectProfileMenuEngine.php', + 'PhabricatorProjectProfileMenuItem' => 'applications/search/menuitem/PhabricatorProjectProfileMenuItem.php', 'PhabricatorProjectProjectHasMemberEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasMemberEdgeType.php', 'PhabricatorProjectProjectHasObjectEdgeType' => 'applications/project/edge/PhabricatorProjectProjectHasObjectEdgeType.php', 'PhabricatorProjectProjectPHIDType' => 'applications/project/phid/PhabricatorProjectProjectPHIDType.php', 'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php', 'PhabricatorProjectRemoveHeraldAction' => 'applications/project/herald/PhabricatorProjectRemoveHeraldAction.php', 'PhabricatorProjectSchemaSpec' => 'applications/project/storage/PhabricatorProjectSchemaSpec.php', 'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php', 'PhabricatorProjectSearchField' => 'applications/project/searchfield/PhabricatorProjectSearchField.php', 'PhabricatorProjectSilenceController' => 'applications/project/controller/PhabricatorProjectSilenceController.php', 'PhabricatorProjectSilencedEdgeType' => 'applications/project/edge/PhabricatorProjectSilencedEdgeType.php', 'PhabricatorProjectSlug' => 'applications/project/storage/PhabricatorProjectSlug.php', 'PhabricatorProjectStandardCustomField' => 'applications/project/customfield/PhabricatorProjectStandardCustomField.php', 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectSubprojectWarningController' => 'applications/project/controller/PhabricatorProjectSubprojectWarningController.php', 'PhabricatorProjectSubprojectsController' => 'applications/project/controller/PhabricatorProjectSubprojectsController.php', - 'PhabricatorProjectSubprojectsProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php', + 'PhabricatorProjectSubprojectsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php', 'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php', 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', 'PhabricatorProjectTransactionEditor' => 'applications/project/editor/PhabricatorProjectTransactionEditor.php', 'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php', 'PhabricatorProjectUIEventListener' => 'applications/project/events/PhabricatorProjectUIEventListener.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorProjectUserFunctionDatasource' => 'applications/project/typeahead/PhabricatorProjectUserFunctionDatasource.php', 'PhabricatorProjectUserListView' => 'applications/project/view/PhabricatorProjectUserListView.php', 'PhabricatorProjectViewController' => 'applications/project/controller/PhabricatorProjectViewController.php', 'PhabricatorProjectWatchController' => 'applications/project/controller/PhabricatorProjectWatchController.php', 'PhabricatorProjectWatcherListView' => 'applications/project/view/PhabricatorProjectWatcherListView.php', 'PhabricatorProjectWorkboardBackgroundColor' => 'applications/project/constants/PhabricatorProjectWorkboardBackgroundColor.php', - 'PhabricatorProjectWorkboardProfilePanel' => 'applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php', + 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', 'PhabricatorProjectsFulltextEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsFulltextEngineExtension.php', 'PhabricatorProjectsMembersSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsMembersSearchEngineAttachment.php', 'PhabricatorProjectsMembershipIndexEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMembershipIndexEngineExtension.php', 'PhabricatorProjectsPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsPolicyRule.php', 'PhabricatorProjectsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsSearchEngineAttachment.php', 'PhabricatorProjectsSearchEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsSearchEngineExtension.php', 'PhabricatorProjectsWatchersSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsWatchersSearchEngineAttachment.php', 'PhabricatorPronounSetting' => 'applications/settings/setting/PhabricatorPronounSetting.php', 'PhabricatorProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorProtocolAdapter.php', 'PhabricatorPygmentSetupCheck' => 'applications/config/check/PhabricatorPygmentSetupCheck.php', 'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php', 'PhabricatorQueryConstraint' => 'infrastructure/query/constraint/PhabricatorQueryConstraint.php', 'PhabricatorQueryOrderItem' => 'infrastructure/query/order/PhabricatorQueryOrderItem.php', 'PhabricatorQueryOrderTestCase' => 'infrastructure/query/order/__tests__/PhabricatorQueryOrderTestCase.php', 'PhabricatorQueryOrderVector' => 'infrastructure/query/order/PhabricatorQueryOrderVector.php', 'PhabricatorQuickActions' => 'applications/settings/quickmenu/PhabricatorQuickActions.php', 'PhabricatorRateLimitRequestExceptionHandler' => 'aphront/handler/PhabricatorRateLimitRequestExceptionHandler.php', 'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php', 'PhabricatorRecipientHasBadgeEdgeType' => 'applications/badges/edge/PhabricatorRecipientHasBadgeEdgeType.php', 'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php', 'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php', 'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php', 'PhabricatorReleephApplication' => 'applications/releeph/application/PhabricatorReleephApplication.php', 'PhabricatorReleephApplicationConfigOptions' => 'applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php', 'PhabricatorRemarkupControl' => 'view/form/control/PhabricatorRemarkupControl.php', 'PhabricatorRemarkupCowsayBlockInterpreter' => 'infrastructure/markup/interpreter/PhabricatorRemarkupCowsayBlockInterpreter.php', 'PhabricatorRemarkupCustomBlockRule' => 'infrastructure/markup/rule/PhabricatorRemarkupCustomBlockRule.php', 'PhabricatorRemarkupCustomInlineRule' => 'infrastructure/markup/rule/PhabricatorRemarkupCustomInlineRule.php', 'PhabricatorRemarkupEditField' => 'applications/transactions/editfield/PhabricatorRemarkupEditField.php', 'PhabricatorRemarkupFigletBlockInterpreter' => 'infrastructure/markup/interpreter/PhabricatorRemarkupFigletBlockInterpreter.php', 'PhabricatorRemarkupUIExample' => 'applications/uiexample/examples/PhabricatorRemarkupUIExample.php', 'PhabricatorRepositoriesSetupCheck' => 'applications/config/check/PhabricatorRepositoriesSetupCheck.php', 'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php', 'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/PhabricatorRepositoryAuditRequest.php', 'PhabricatorRepositoryBranch' => 'applications/repository/storage/PhabricatorRepositoryBranch.php', 'PhabricatorRepositoryCommit' => 'applications/repository/storage/PhabricatorRepositoryCommit.php', 'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php', 'PhabricatorRepositoryCommitData' => 'applications/repository/storage/PhabricatorRepositoryCommitData.php', 'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php', 'PhabricatorRepositoryCommitHint' => 'applications/repository/storage/PhabricatorRepositoryCommitHint.php', 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php', 'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php', 'PhabricatorRepositoryCommitPHIDType' => 'applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php', 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitParserWorker.php', 'PhabricatorRepositoryCommitRef' => 'applications/repository/engine/PhabricatorRepositoryCommitRef.php', 'PhabricatorRepositoryCommitTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php', 'PhabricatorRepositoryConfigOptions' => 'applications/repository/config/PhabricatorRepositoryConfigOptions.php', 'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php', 'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php', 'PhabricatorRepositoryEditor' => 'applications/repository/editor/PhabricatorRepositoryEditor.php', 'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryGitCommitMessageParserWorker.php', 'PhabricatorRepositoryGitLFSRef' => 'applications/repository/storage/PhabricatorRepositoryGitLFSRef.php', 'PhabricatorRepositoryGitLFSRefQuery' => 'applications/repository/query/PhabricatorRepositoryGitLFSRefQuery.php', 'PhabricatorRepositoryGraphCache' => 'applications/repository/graphcache/PhabricatorRepositoryGraphCache.php', 'PhabricatorRepositoryGraphStream' => 'applications/repository/daemon/PhabricatorRepositoryGraphStream.php', 'PhabricatorRepositoryManagementCacheWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementCacheWorkflow.php', 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementClusterizeWorkflow.php', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php', 'PhabricatorRepositoryManagementHintWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php', 'PhabricatorRepositoryManagementImportingWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementImportingWorkflow.php', 'PhabricatorRepositoryManagementListPathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListPathsWorkflow.php', 'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php', 'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementLookupUsersWorkflow.php', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkImportedWorkflow.php', 'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMarkReachableWorkflow.php', 'PhabricatorRepositoryManagementMirrorWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMirrorWorkflow.php', 'PhabricatorRepositoryManagementMovePathsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementMovePathsWorkflow.php', 'PhabricatorRepositoryManagementParentsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementParentsWorkflow.php', 'PhabricatorRepositoryManagementPullWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementPullWorkflow.php', 'PhabricatorRepositoryManagementRefsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementRefsWorkflow.php', 'PhabricatorRepositoryManagementReparseWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php', 'PhabricatorRepositoryManagementThawWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php', 'PhabricatorRepositoryManagementUpdateWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementUpdateWorkflow.php', 'PhabricatorRepositoryManagementWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementWorkflow.php', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryMercurialCommitChangeParserWorker.php', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryMercurialCommitMessageParserWorker.php', 'PhabricatorRepositoryMirror' => 'applications/repository/storage/PhabricatorRepositoryMirror.php', 'PhabricatorRepositoryMirrorEngine' => 'applications/repository/engine/PhabricatorRepositoryMirrorEngine.php', 'PhabricatorRepositoryOldRef' => 'applications/repository/storage/PhabricatorRepositoryOldRef.php', 'PhabricatorRepositoryParsedChange' => 'applications/repository/data/PhabricatorRepositoryParsedChange.php', 'PhabricatorRepositoryPullEngine' => 'applications/repository/engine/PhabricatorRepositoryPullEngine.php', 'PhabricatorRepositoryPullEvent' => 'applications/repository/storage/PhabricatorRepositoryPullEvent.php', 'PhabricatorRepositoryPullEventPHIDType' => 'applications/repository/phid/PhabricatorRepositoryPullEventPHIDType.php', 'PhabricatorRepositoryPullEventQuery' => 'applications/repository/query/PhabricatorRepositoryPullEventQuery.php', 'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php', 'PhabricatorRepositoryPushEvent' => 'applications/repository/storage/PhabricatorRepositoryPushEvent.php', 'PhabricatorRepositoryPushEventPHIDType' => 'applications/repository/phid/PhabricatorRepositoryPushEventPHIDType.php', 'PhabricatorRepositoryPushEventQuery' => 'applications/repository/query/PhabricatorRepositoryPushEventQuery.php', 'PhabricatorRepositoryPushLog' => 'applications/repository/storage/PhabricatorRepositoryPushLog.php', 'PhabricatorRepositoryPushLogPHIDType' => 'applications/repository/phid/PhabricatorRepositoryPushLogPHIDType.php', 'PhabricatorRepositoryPushLogQuery' => 'applications/repository/query/PhabricatorRepositoryPushLogQuery.php', 'PhabricatorRepositoryPushLogSearchEngine' => 'applications/repository/query/PhabricatorRepositoryPushLogSearchEngine.php', 'PhabricatorRepositoryPushMailWorker' => 'applications/repository/worker/PhabricatorRepositoryPushMailWorker.php', 'PhabricatorRepositoryPushReplyHandler' => 'applications/repository/mail/PhabricatorRepositoryPushReplyHandler.php', 'PhabricatorRepositoryQuery' => 'applications/repository/query/PhabricatorRepositoryQuery.php', 'PhabricatorRepositoryRefCursor' => 'applications/repository/storage/PhabricatorRepositoryRefCursor.php', 'PhabricatorRepositoryRefCursorPHIDType' => 'applications/repository/phid/PhabricatorRepositoryRefCursorPHIDType.php', 'PhabricatorRepositoryRefCursorQuery' => 'applications/repository/query/PhabricatorRepositoryRefCursorQuery.php', 'PhabricatorRepositoryRefEngine' => 'applications/repository/engine/PhabricatorRepositoryRefEngine.php', 'PhabricatorRepositoryRepositoryPHIDType' => 'applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php', 'PhabricatorRepositorySchemaSpec' => 'applications/repository/storage/PhabricatorRepositorySchemaSpec.php', 'PhabricatorRepositorySearchEngine' => 'applications/repository/query/PhabricatorRepositorySearchEngine.php', 'PhabricatorRepositoryStatusMessage' => 'applications/repository/storage/PhabricatorRepositoryStatusMessage.php', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php', 'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php', 'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php', 'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php', 'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php', 'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php', 'PhabricatorRepositoryURI' => 'applications/repository/storage/PhabricatorRepositoryURI.php', 'PhabricatorRepositoryURIIndex' => 'applications/repository/storage/PhabricatorRepositoryURIIndex.php', 'PhabricatorRepositoryURINormalizer' => 'applications/repository/data/PhabricatorRepositoryURINormalizer.php', 'PhabricatorRepositoryURINormalizerTestCase' => 'applications/repository/data/__tests__/PhabricatorRepositoryURINormalizerTestCase.php', 'PhabricatorRepositoryURIPHIDType' => 'applications/repository/phid/PhabricatorRepositoryURIPHIDType.php', 'PhabricatorRepositoryURIQuery' => 'applications/repository/query/PhabricatorRepositoryURIQuery.php', 'PhabricatorRepositoryURITestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryURITestCase.php', 'PhabricatorRepositoryURITransaction' => 'applications/repository/storage/PhabricatorRepositoryURITransaction.php', 'PhabricatorRepositoryURITransactionQuery' => 'applications/repository/query/PhabricatorRepositoryURITransactionQuery.php', 'PhabricatorRepositoryVCSPassword' => 'applications/repository/storage/PhabricatorRepositoryVCSPassword.php', 'PhabricatorRepositoryVersion' => 'applications/repository/constants/PhabricatorRepositoryVersion.php', 'PhabricatorRepositoryWorkingCopyVersion' => 'applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php', 'PhabricatorRequestExceptionHandler' => 'aphront/handler/PhabricatorRequestExceptionHandler.php', 'PhabricatorResourceSite' => 'aphront/site/PhabricatorResourceSite.php', 'PhabricatorRobotsController' => 'applications/system/controller/PhabricatorRobotsController.php', 'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php', 'PhabricatorSMS' => 'infrastructure/sms/storage/PhabricatorSMS.php', 'PhabricatorSMSConfigOptions' => 'applications/config/option/PhabricatorSMSConfigOptions.php', 'PhabricatorSMSDAO' => 'infrastructure/sms/storage/PhabricatorSMSDAO.php', 'PhabricatorSMSDemultiplexWorker' => 'infrastructure/sms/worker/PhabricatorSMSDemultiplexWorker.php', 'PhabricatorSMSImplementationAdapter' => 'infrastructure/sms/adapter/PhabricatorSMSImplementationAdapter.php', 'PhabricatorSMSImplementationTestBlackholeAdapter' => 'infrastructure/sms/adapter/PhabricatorSMSImplementationTestBlackholeAdapter.php', 'PhabricatorSMSImplementationTwilioAdapter' => 'infrastructure/sms/adapter/PhabricatorSMSImplementationTwilioAdapter.php', 'PhabricatorSMSManagementListOutboundWorkflow' => 'infrastructure/sms/management/PhabricatorSMSManagementListOutboundWorkflow.php', 'PhabricatorSMSManagementSendTestWorkflow' => 'infrastructure/sms/management/PhabricatorSMSManagementSendTestWorkflow.php', 'PhabricatorSMSManagementShowOutboundWorkflow' => 'infrastructure/sms/management/PhabricatorSMSManagementShowOutboundWorkflow.php', 'PhabricatorSMSManagementWorkflow' => 'infrastructure/sms/management/PhabricatorSMSManagementWorkflow.php', 'PhabricatorSMSSendWorker' => 'infrastructure/sms/worker/PhabricatorSMSSendWorker.php', 'PhabricatorSMSWorker' => 'infrastructure/sms/worker/PhabricatorSMSWorker.php', 'PhabricatorSQLPatchList' => 'infrastructure/storage/patch/PhabricatorSQLPatchList.php', 'PhabricatorSSHKeyGenerator' => 'infrastructure/util/PhabricatorSSHKeyGenerator.php', 'PhabricatorSSHKeysSettingsPanel' => 'applications/settings/panel/PhabricatorSSHKeysSettingsPanel.php', 'PhabricatorSSHLog' => 'infrastructure/log/PhabricatorSSHLog.php', 'PhabricatorSSHPassthruCommand' => 'infrastructure/ssh/PhabricatorSSHPassthruCommand.php', 'PhabricatorSSHPublicKeyInterface' => 'applications/auth/sshkey/PhabricatorSSHPublicKeyInterface.php', 'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php', 'PhabricatorSavedQuery' => 'applications/search/storage/PhabricatorSavedQuery.php', 'PhabricatorSavedQueryQuery' => 'applications/search/query/PhabricatorSavedQueryQuery.php', 'PhabricatorScheduleTaskTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorScheduleTaskTriggerAction.php', 'PhabricatorScopedEnv' => 'infrastructure/env/PhabricatorScopedEnv.php', 'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php', 'PhabricatorSearchApplication' => 'applications/search/application/PhabricatorSearchApplication.php', 'PhabricatorSearchApplicationSearchEngine' => 'applications/search/query/PhabricatorSearchApplicationSearchEngine.php', 'PhabricatorSearchApplicationStorageEnginePanel' => 'applications/search/applicationpanel/PhabricatorSearchApplicationStorageEnginePanel.php', 'PhabricatorSearchBaseController' => 'applications/search/controller/PhabricatorSearchBaseController.php', 'PhabricatorSearchCheckboxesField' => 'applications/search/field/PhabricatorSearchCheckboxesField.php', 'PhabricatorSearchConfigOptions' => 'applications/search/config/PhabricatorSearchConfigOptions.php', 'PhabricatorSearchController' => 'applications/search/controller/PhabricatorSearchController.php', 'PhabricatorSearchCustomFieldProxyField' => 'applications/search/field/PhabricatorSearchCustomFieldProxyField.php', 'PhabricatorSearchDAO' => 'applications/search/storage/PhabricatorSearchDAO.php', 'PhabricatorSearchDatasource' => 'applications/search/typeahead/PhabricatorSearchDatasource.php', 'PhabricatorSearchDatasourceField' => 'applications/search/field/PhabricatorSearchDatasourceField.php', 'PhabricatorSearchDateControlField' => 'applications/search/field/PhabricatorSearchDateControlField.php', 'PhabricatorSearchDateField' => 'applications/search/field/PhabricatorSearchDateField.php', 'PhabricatorSearchDeleteController' => 'applications/search/controller/PhabricatorSearchDeleteController.php', 'PhabricatorSearchDocument' => 'applications/search/storage/document/PhabricatorSearchDocument.php', 'PhabricatorSearchDocumentField' => 'applications/search/storage/document/PhabricatorSearchDocumentField.php', 'PhabricatorSearchDocumentFieldType' => 'applications/search/constants/PhabricatorSearchDocumentFieldType.php', 'PhabricatorSearchDocumentQuery' => 'applications/search/query/PhabricatorSearchDocumentQuery.php', 'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/PhabricatorSearchDocumentRelationship.php', 'PhabricatorSearchDocumentTypeDatasource' => 'applications/search/typeahead/PhabricatorSearchDocumentTypeDatasource.php', 'PhabricatorSearchEditController' => 'applications/search/controller/PhabricatorSearchEditController.php', 'PhabricatorSearchEngineAPIMethod' => 'applications/search/engine/PhabricatorSearchEngineAPIMethod.php', 'PhabricatorSearchEngineAttachment' => 'applications/search/engineextension/PhabricatorSearchEngineAttachment.php', 'PhabricatorSearchEngineExtension' => 'applications/search/engineextension/PhabricatorSearchEngineExtension.php', 'PhabricatorSearchEngineExtensionModule' => 'applications/search/engineextension/PhabricatorSearchEngineExtensionModule.php', 'PhabricatorSearchEngineTestCase' => 'applications/search/engine/__tests__/PhabricatorSearchEngineTestCase.php', 'PhabricatorSearchField' => 'applications/search/field/PhabricatorSearchField.php', 'PhabricatorSearchHovercardController' => 'applications/search/controller/PhabricatorSearchHovercardController.php', 'PhabricatorSearchIndexVersion' => 'applications/search/storage/PhabricatorSearchIndexVersion.php', 'PhabricatorSearchIndexVersionDestructionEngineExtension' => 'applications/search/engineextension/PhabricatorSearchIndexVersionDestructionEngineExtension.php', 'PhabricatorSearchManagementIndexWorkflow' => 'applications/search/management/PhabricatorSearchManagementIndexWorkflow.php', 'PhabricatorSearchManagementInitWorkflow' => 'applications/search/management/PhabricatorSearchManagementInitWorkflow.php', 'PhabricatorSearchManagementWorkflow' => 'applications/search/management/PhabricatorSearchManagementWorkflow.php', 'PhabricatorSearchNgrams' => 'applications/search/ngrams/PhabricatorSearchNgrams.php', 'PhabricatorSearchNgramsDestructionEngineExtension' => 'applications/search/engineextension/PhabricatorSearchNgramsDestructionEngineExtension.php', 'PhabricatorSearchOrderController' => 'applications/search/controller/PhabricatorSearchOrderController.php', 'PhabricatorSearchOrderField' => 'applications/search/field/PhabricatorSearchOrderField.php', 'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php', 'PhabricatorSearchRelationshipController' => 'applications/search/controller/PhabricatorSearchRelationshipController.php', 'PhabricatorSearchRelationshipSourceController' => 'applications/search/controller/PhabricatorSearchRelationshipSourceController.php', 'PhabricatorSearchResultBucket' => 'applications/search/buckets/PhabricatorSearchResultBucket.php', 'PhabricatorSearchResultBucketGroup' => 'applications/search/buckets/PhabricatorSearchResultBucketGroup.php', 'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php', 'PhabricatorSearchSchemaSpec' => 'applications/search/storage/PhabricatorSearchSchemaSpec.php', 'PhabricatorSearchScopeSetting' => 'applications/settings/setting/PhabricatorSearchScopeSetting.php', 'PhabricatorSearchSelectField' => 'applications/search/field/PhabricatorSearchSelectField.php', 'PhabricatorSearchStringListField' => 'applications/search/field/PhabricatorSearchStringListField.php', 'PhabricatorSearchSubscribersField' => 'applications/search/field/PhabricatorSearchSubscribersField.php', 'PhabricatorSearchTextField' => 'applications/search/field/PhabricatorSearchTextField.php', 'PhabricatorSearchThreeStateField' => 'applications/search/field/PhabricatorSearchThreeStateField.php', 'PhabricatorSearchTokenizerField' => 'applications/search/field/PhabricatorSearchTokenizerField.php', 'PhabricatorSearchWorker' => 'applications/search/worker/PhabricatorSearchWorker.php', 'PhabricatorSecurityConfigOptions' => 'applications/config/option/PhabricatorSecurityConfigOptions.php', 'PhabricatorSecuritySetupCheck' => 'applications/config/check/PhabricatorSecuritySetupCheck.php', 'PhabricatorSelectEditField' => 'applications/transactions/editfield/PhabricatorSelectEditField.php', 'PhabricatorSelectSetting' => 'applications/settings/setting/PhabricatorSelectSetting.php', 'PhabricatorSendGridConfigOptions' => 'applications/config/option/PhabricatorSendGridConfigOptions.php', 'PhabricatorSessionsSettingsPanel' => 'applications/settings/panel/PhabricatorSessionsSettingsPanel.php', 'PhabricatorSetting' => 'applications/settings/setting/PhabricatorSetting.php', 'PhabricatorSettingsAccountPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsAccountPanelGroup.php', 'PhabricatorSettingsAddEmailAction' => 'applications/settings/action/PhabricatorSettingsAddEmailAction.php', 'PhabricatorSettingsAdjustController' => 'applications/settings/controller/PhabricatorSettingsAdjustController.php', 'PhabricatorSettingsApplication' => 'applications/settings/application/PhabricatorSettingsApplication.php', 'PhabricatorSettingsApplicationsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsApplicationsPanelGroup.php', 'PhabricatorSettingsAuthenticationPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsAuthenticationPanelGroup.php', 'PhabricatorSettingsDeveloperPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsDeveloperPanelGroup.php', 'PhabricatorSettingsEditEngine' => 'applications/settings/editor/PhabricatorSettingsEditEngine.php', 'PhabricatorSettingsEmailPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsEmailPanelGroup.php', 'PhabricatorSettingsListController' => 'applications/settings/controller/PhabricatorSettingsListController.php', 'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php', 'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', 'PhabricatorSettingsMainMenuBarExtension' => 'applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php', 'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', 'PhabricatorSettingsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsPanelGroup.php', 'PhabricatorSettingsTimezoneController' => 'applications/settings/controller/PhabricatorSettingsTimezoneController.php', 'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', 'PhabricatorSetupCheckTestCase' => 'applications/config/check/__tests__/PhabricatorSetupCheckTestCase.php', 'PhabricatorSetupEngine' => 'applications/config/engine/PhabricatorSetupEngine.php', 'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php', 'PhabricatorSetupIssueUIExample' => 'applications/uiexample/examples/PhabricatorSetupIssueUIExample.php', 'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php', 'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php', 'PhabricatorShowFiletreeSetting' => 'applications/settings/setting/PhabricatorShowFiletreeSetting.php', 'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php', 'PhabricatorSite' => 'aphront/site/PhabricatorSite.php', 'PhabricatorSlackAuthProvider' => 'applications/auth/provider/PhabricatorSlackAuthProvider.php', 'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php', 'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php', 'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php', 'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php', 'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php', 'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/PhabricatorSlowvoteDAO.php', 'PhabricatorSlowvoteDefaultViewCapability' => 'applications/slowvote/capability/PhabricatorSlowvoteDefaultViewCapability.php', 'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php', 'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php', 'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php', 'PhabricatorSlowvoteMailReceiver' => 'applications/slowvote/mail/PhabricatorSlowvoteMailReceiver.php', 'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php', 'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php', 'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php', 'PhabricatorSlowvotePollPHIDType' => 'applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php', 'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php', 'PhabricatorSlowvoteReplyHandler' => 'applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php', 'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php', 'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php', 'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php', 'PhabricatorSlowvoteTransactionComment' => 'applications/slowvote/storage/PhabricatorSlowvoteTransactionComment.php', 'PhabricatorSlowvoteTransactionQuery' => 'applications/slowvote/query/PhabricatorSlowvoteTransactionQuery.php', 'PhabricatorSlowvoteVoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteVoteController.php', 'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php', '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', 'PhabricatorSpacesCapabilityDefaultEdit' => 'applications/spaces/capability/PhabricatorSpacesCapabilityDefaultEdit.php', 'PhabricatorSpacesCapabilityDefaultView' => 'applications/spaces/capability/PhabricatorSpacesCapabilityDefaultView.php', 'PhabricatorSpacesController' => 'applications/spaces/controller/PhabricatorSpacesController.php', 'PhabricatorSpacesDAO' => 'applications/spaces/storage/PhabricatorSpacesDAO.php', 'PhabricatorSpacesEditController' => 'applications/spaces/controller/PhabricatorSpacesEditController.php', 'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php', 'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php', 'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php', 'PhabricatorSpacesNamespaceDatasource' => 'applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php', 'PhabricatorSpacesNamespaceEditor' => 'applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php', 'PhabricatorSpacesNamespacePHIDType' => 'applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php', 'PhabricatorSpacesNamespaceQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceQuery.php', 'PhabricatorSpacesNamespaceSearchEngine' => 'applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php', 'PhabricatorSpacesNamespaceTransaction' => 'applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php', 'PhabricatorSpacesNamespaceTransactionQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceTransactionQuery.php', 'PhabricatorSpacesNoAccessController' => 'applications/spaces/controller/PhabricatorSpacesNoAccessController.php', 'PhabricatorSpacesRemarkupRule' => 'applications/spaces/remarkup/PhabricatorSpacesRemarkupRule.php', 'PhabricatorSpacesSchemaSpec' => 'applications/spaces/storage/PhabricatorSpacesSchemaSpec.php', 'PhabricatorSpacesSearchEngineExtension' => 'applications/spaces/engineextension/PhabricatorSpacesSearchEngineExtension.php', 'PhabricatorSpacesSearchField' => 'applications/spaces/searchfield/PhabricatorSpacesSearchField.php', 'PhabricatorSpacesTestCase' => 'applications/spaces/__tests__/PhabricatorSpacesTestCase.php', 'PhabricatorSpacesViewController' => 'applications/spaces/controller/PhabricatorSpacesViewController.php', 'PhabricatorStandardCustomField' => 'infrastructure/customfield/standard/PhabricatorStandardCustomField.php', 'PhabricatorStandardCustomFieldBlueprints' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldBlueprints.php', 'PhabricatorStandardCustomFieldBool' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php', 'PhabricatorStandardCustomFieldCredential' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php', 'PhabricatorStandardCustomFieldDatasource' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldDatasource.php', 'PhabricatorStandardCustomFieldDate' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php', 'PhabricatorStandardCustomFieldHeader' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php', 'PhabricatorStandardCustomFieldInt' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php', 'PhabricatorStandardCustomFieldInterface' => 'infrastructure/customfield/interface/PhabricatorStandardCustomFieldInterface.php', 'PhabricatorStandardCustomFieldLink' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldLink.php', 'PhabricatorStandardCustomFieldPHIDs' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php', 'PhabricatorStandardCustomFieldRemarkup' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php', 'PhabricatorStandardCustomFieldSelect' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php', 'PhabricatorStandardCustomFieldText' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldText.php', 'PhabricatorStandardCustomFieldTokenizer' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldTokenizer.php', 'PhabricatorStandardCustomFieldUsers' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php', 'PhabricatorStandardPageView' => 'view/page/PhabricatorStandardPageView.php', 'PhabricatorStandardSelectCustomFieldDatasource' => 'infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php', 'PhabricatorStaticEditField' => 'applications/transactions/editfield/PhabricatorStaticEditField.php', 'PhabricatorStatusController' => 'applications/system/controller/PhabricatorStatusController.php', 'PhabricatorStatusUIExample' => 'applications/uiexample/examples/PhabricatorStatusUIExample.php', 'PhabricatorStorageFixtureScopeGuard' => 'infrastructure/testing/fixture/PhabricatorStorageFixtureScopeGuard.php', 'PhabricatorStorageManagementAPI' => 'infrastructure/storage/management/PhabricatorStorageManagementAPI.php', 'PhabricatorStorageManagementAdjustWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementAdjustWorkflow.php', 'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php', 'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php', 'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php', 'PhabricatorStorageManagementPartitionWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementPartitionWorkflow.php', 'PhabricatorStorageManagementProbeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php', 'PhabricatorStorageManagementQuickstartWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php', 'PhabricatorStorageManagementRenamespaceWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php', 'PhabricatorStorageManagementShellWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php', 'PhabricatorStorageManagementStatusWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php', 'PhabricatorStorageManagementUpgradeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php', 'PhabricatorStorageManagementWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php', 'PhabricatorStoragePatch' => 'infrastructure/storage/management/PhabricatorStoragePatch.php', 'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php', 'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php', 'PhabricatorStreamingProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorStreamingProtocolAdapter.php', 'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php', 'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php', + 'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php', 'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php', 'PhabricatorSubscribedToObjectEdgeType' => 'applications/transactions/edges/PhabricatorSubscribedToObjectEdgeType.php', 'PhabricatorSubscribersEditField' => 'applications/transactions/editfield/PhabricatorSubscribersEditField.php', 'PhabricatorSubscribersQuery' => 'applications/subscriptions/query/PhabricatorSubscribersQuery.php', 'PhabricatorSubscriptionTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorSubscriptionTriggerClock.php', 'PhabricatorSubscriptionsAddSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsAddSelfHeraldAction.php', 'PhabricatorSubscriptionsAddSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsAddSubscribersHeraldAction.php', 'PhabricatorSubscriptionsApplication' => 'applications/subscriptions/application/PhabricatorSubscriptionsApplication.php', 'PhabricatorSubscriptionsCurtainExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsCurtainExtension.php', 'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php', 'PhabricatorSubscriptionsEditEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php', 'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php', 'PhabricatorSubscriptionsFulltextEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsFulltextEngineExtension.php', 'PhabricatorSubscriptionsHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php', 'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.php', 'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php', 'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php', 'PhabricatorSubscriptionsSearchEngineAttachment' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsSearchEngineAttachment.php', 'PhabricatorSubscriptionsSearchEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsSearchEngineExtension.php', 'PhabricatorSubscriptionsSubscribeEmailCommand' => 'applications/subscriptions/command/PhabricatorSubscriptionsSubscribeEmailCommand.php', 'PhabricatorSubscriptionsSubscribersPolicyRule' => 'applications/subscriptions/policyrule/PhabricatorSubscriptionsSubscribersPolicyRule.php', 'PhabricatorSubscriptionsTransactionController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php', 'PhabricatorSubscriptionsUIEventListener' => 'applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php', 'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php', 'PhabricatorSupportApplication' => 'applications/support/application/PhabricatorSupportApplication.php', 'PhabricatorSyntaxHighlighter' => 'infrastructure/markup/PhabricatorSyntaxHighlighter.php', 'PhabricatorSyntaxHighlightingConfigOptions' => 'applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php', 'PhabricatorSyntaxStyle' => 'infrastructure/syntax/PhabricatorSyntaxStyle.php', 'PhabricatorSystemAction' => 'applications/system/action/PhabricatorSystemAction.php', 'PhabricatorSystemActionEngine' => 'applications/system/engine/PhabricatorSystemActionEngine.php', 'PhabricatorSystemActionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemActionGarbageCollector.php', 'PhabricatorSystemActionLog' => 'applications/system/storage/PhabricatorSystemActionLog.php', 'PhabricatorSystemActionRateLimitException' => 'applications/system/exception/PhabricatorSystemActionRateLimitException.php', 'PhabricatorSystemApplication' => 'applications/system/application/PhabricatorSystemApplication.php', 'PhabricatorSystemDAO' => 'applications/system/storage/PhabricatorSystemDAO.php', 'PhabricatorSystemDestructionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemDestructionGarbageCollector.php', 'PhabricatorSystemDestructionLog' => 'applications/system/storage/PhabricatorSystemDestructionLog.php', 'PhabricatorSystemFaviconController' => 'applications/system/controller/PhabricatorSystemFaviconController.php', 'PhabricatorSystemReadOnlyController' => 'applications/system/controller/PhabricatorSystemReadOnlyController.php', 'PhabricatorSystemRemoveDestroyWorkflow' => 'applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php', 'PhabricatorSystemRemoveLogWorkflow' => 'applications/system/management/PhabricatorSystemRemoveLogWorkflow.php', 'PhabricatorSystemRemoveWorkflow' => 'applications/system/management/PhabricatorSystemRemoveWorkflow.php', 'PhabricatorSystemSelectEncodingController' => 'applications/system/controller/PhabricatorSystemSelectEncodingController.php', 'PhabricatorSystemSelectHighlightController' => 'applications/system/controller/PhabricatorSystemSelectHighlightController.php', 'PhabricatorTOTPAuthFactor' => 'applications/auth/factor/PhabricatorTOTPAuthFactor.php', 'PhabricatorTOTPAuthFactorTestCase' => 'applications/auth/factor/__tests__/PhabricatorTOTPAuthFactorTestCase.php', 'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php', 'PhabricatorTestApplication' => 'applications/base/controller/__tests__/PhabricatorTestApplication.php', 'PhabricatorTestCase' => 'infrastructure/testing/PhabricatorTestCase.php', 'PhabricatorTestController' => 'applications/base/controller/__tests__/PhabricatorTestController.php', 'PhabricatorTestDataGenerator' => 'applications/lipsum/generator/PhabricatorTestDataGenerator.php', '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', 'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php', 'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php', 'PhabricatorTimeTestCase' => 'infrastructure/time/__tests__/PhabricatorTimeTestCase.php', 'PhabricatorTimezoneIgnoreOffsetSetting' => 'applications/settings/setting/PhabricatorTimezoneIgnoreOffsetSetting.php', 'PhabricatorTimezoneSetting' => 'applications/settings/setting/PhabricatorTimezoneSetting.php', 'PhabricatorTimezoneSetupCheck' => 'applications/config/check/PhabricatorTimezoneSetupCheck.php', 'PhabricatorTitleGlyphsSetting' => 'applications/settings/setting/PhabricatorTitleGlyphsSetting.php', 'PhabricatorToken' => 'applications/tokens/storage/PhabricatorToken.php', 'PhabricatorTokenController' => 'applications/tokens/controller/PhabricatorTokenController.php', 'PhabricatorTokenCount' => 'applications/tokens/storage/PhabricatorTokenCount.php', 'PhabricatorTokenCountQuery' => 'applications/tokens/query/PhabricatorTokenCountQuery.php', 'PhabricatorTokenDAO' => 'applications/tokens/storage/PhabricatorTokenDAO.php', 'PhabricatorTokenDestructionEngineExtension' => 'applications/tokens/engineextension/PhabricatorTokenDestructionEngineExtension.php', 'PhabricatorTokenGiveController' => 'applications/tokens/controller/PhabricatorTokenGiveController.php', 'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php', 'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php', 'PhabricatorTokenGivenEditor' => 'applications/tokens/editor/PhabricatorTokenGivenEditor.php', 'PhabricatorTokenGivenFeedStory' => 'applications/tokens/feed/PhabricatorTokenGivenFeedStory.php', 'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php', 'PhabricatorTokenLeaderController' => 'applications/tokens/controller/PhabricatorTokenLeaderController.php', 'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php', 'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php', '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', 'PhabricatorTokensCurtainExtension' => 'applications/tokens/engineextension/PhabricatorTokensCurtainExtension.php', 'PhabricatorTokensSettingsPanel' => 'applications/settings/panel/PhabricatorTokensSettingsPanel.php', 'PhabricatorTokensToken' => 'applications/tokens/storage/PhabricatorTokensToken.php', 'PhabricatorTooltipUIExample' => 'applications/uiexample/examples/PhabricatorTooltipUIExample.php', 'PhabricatorTransactionChange' => 'applications/transactions/data/PhabricatorTransactionChange.php', 'PhabricatorTransactionRemarkupChange' => 'applications/transactions/data/PhabricatorTransactionRemarkupChange.php', 'PhabricatorTransactions' => 'applications/transactions/constants/PhabricatorTransactions.php', 'PhabricatorTransactionsApplication' => 'applications/transactions/application/PhabricatorTransactionsApplication.php', 'PhabricatorTransactionsDestructionEngineExtension' => 'applications/transactions/engineextension/PhabricatorTransactionsDestructionEngineExtension.php', 'PhabricatorTransactionsFulltextEngineExtension' => 'applications/transactions/engineextension/PhabricatorTransactionsFulltextEngineExtension.php', 'PhabricatorTransformedFile' => 'applications/files/storage/PhabricatorTransformedFile.php', 'PhabricatorTranslationSetting' => 'applications/settings/setting/PhabricatorTranslationSetting.php', 'PhabricatorTranslationsConfigOptions' => 'applications/config/option/PhabricatorTranslationsConfigOptions.php', 'PhabricatorTriggerAction' => 'infrastructure/daemon/workers/action/PhabricatorTriggerAction.php', 'PhabricatorTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorTriggerClock.php', 'PhabricatorTriggerClockTestCase' => 'infrastructure/daemon/workers/clock/__tests__/PhabricatorTriggerClockTestCase.php', 'PhabricatorTriggerDaemon' => 'infrastructure/daemon/workers/PhabricatorTriggerDaemon.php', 'PhabricatorTrivialTestCase' => 'infrastructure/testing/__tests__/PhabricatorTrivialTestCase.php', 'PhabricatorTwitchAuthProvider' => 'applications/auth/provider/PhabricatorTwitchAuthProvider.php', 'PhabricatorTwitterAuthProvider' => 'applications/auth/provider/PhabricatorTwitterAuthProvider.php', 'PhabricatorTypeaheadApplication' => 'applications/typeahead/application/PhabricatorTypeaheadApplication.php', 'PhabricatorTypeaheadCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php', 'PhabricatorTypeaheadDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php', 'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadDatasourceController.php', 'PhabricatorTypeaheadDatasourceTestCase' => 'applications/typeahead/datasource/__tests__/PhabricatorTypeaheadDatasourceTestCase.php', 'PhabricatorTypeaheadFunctionHelpController' => 'applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php', 'PhabricatorTypeaheadInvalidTokenException' => 'applications/typeahead/exception/PhabricatorTypeaheadInvalidTokenException.php', 'PhabricatorTypeaheadModularDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php', 'PhabricatorTypeaheadMonogramDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadMonogramDatasource.php', 'PhabricatorTypeaheadResult' => 'applications/typeahead/storage/PhabricatorTypeaheadResult.php', 'PhabricatorTypeaheadRuntimeCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadRuntimeCompositeDatasource.php', 'PhabricatorTypeaheadTokenView' => 'applications/typeahead/view/PhabricatorTypeaheadTokenView.php', 'PhabricatorUIConfigOptions' => 'applications/config/option/PhabricatorUIConfigOptions.php', 'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php', 'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/PhabricatorUIExampleRenderController.php', 'PhabricatorUIExamplesApplication' => 'applications/uiexample/application/PhabricatorUIExamplesApplication.php', 'PhabricatorUSEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php', 'PhabricatorUnifiedDiffsSetting' => 'applications/settings/setting/PhabricatorUnifiedDiffsSetting.php', 'PhabricatorUnitTestContentSource' => 'infrastructure/contentsource/PhabricatorUnitTestContentSource.php', 'PhabricatorUnitsTestCase' => 'view/__tests__/PhabricatorUnitsTestCase.php', 'PhabricatorUnknownContentSource' => 'infrastructure/contentsource/PhabricatorUnknownContentSource.php', 'PhabricatorUnsubscribedFromObjectEdgeType' => 'applications/transactions/edges/PhabricatorUnsubscribedFromObjectEdgeType.php', 'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php', 'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php', 'PhabricatorUserCache' => 'applications/people/storage/PhabricatorUserCache.php', 'PhabricatorUserCacheType' => 'applications/people/cache/PhabricatorUserCacheType.php', 'PhabricatorUserCardView' => 'applications/people/view/PhabricatorUserCardView.php', 'PhabricatorUserConfigOptions' => 'applications/people/config/PhabricatorUserConfigOptions.php', 'PhabricatorUserConfiguredCustomField' => 'applications/people/customfield/PhabricatorUserConfiguredCustomField.php', 'PhabricatorUserConfiguredCustomFieldStorage' => 'applications/people/storage/PhabricatorUserConfiguredCustomFieldStorage.php', 'PhabricatorUserCustomField' => 'applications/people/customfield/PhabricatorUserCustomField.php', 'PhabricatorUserCustomFieldNumericIndex' => 'applications/people/storage/PhabricatorUserCustomFieldNumericIndex.php', 'PhabricatorUserCustomFieldStringIndex' => 'applications/people/storage/PhabricatorUserCustomFieldStringIndex.php', 'PhabricatorUserDAO' => 'applications/people/storage/PhabricatorUserDAO.php', 'PhabricatorUserEditor' => 'applications/people/editor/PhabricatorUserEditor.php', 'PhabricatorUserEditorTestCase' => 'applications/people/editor/__tests__/PhabricatorUserEditorTestCase.php', 'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php', 'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php', 'PhabricatorUserFulltextEngine' => 'applications/people/search/PhabricatorUserFulltextEngine.php', 'PhabricatorUserIconField' => 'applications/people/customfield/PhabricatorUserIconField.php', 'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php', 'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php', 'PhabricatorUserMessageCountCacheType' => 'applications/people/cache/PhabricatorUserMessageCountCacheType.php', 'PhabricatorUserNotificationCountCacheType' => 'applications/people/cache/PhabricatorUserNotificationCountCacheType.php', 'PhabricatorUserPHIDResolver' => 'applications/phid/resolver/PhabricatorUserPHIDResolver.php', 'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php', 'PhabricatorUserPreferencesCacheType' => 'applications/people/cache/PhabricatorUserPreferencesCacheType.php', 'PhabricatorUserPreferencesEditor' => 'applications/settings/editor/PhabricatorUserPreferencesEditor.php', 'PhabricatorUserPreferencesPHIDType' => 'applications/settings/phid/PhabricatorUserPreferencesPHIDType.php', 'PhabricatorUserPreferencesQuery' => 'applications/settings/query/PhabricatorUserPreferencesQuery.php', 'PhabricatorUserPreferencesSearchEngine' => 'applications/settings/query/PhabricatorUserPreferencesSearchEngine.php', 'PhabricatorUserPreferencesTransaction' => 'applications/settings/storage/PhabricatorUserPreferencesTransaction.php', 'PhabricatorUserPreferencesTransactionQuery' => 'applications/settings/query/PhabricatorUserPreferencesTransactionQuery.php', 'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php', 'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php', 'PhabricatorUserProfileImageCacheType' => 'applications/people/cache/PhabricatorUserProfileImageCacheType.php', 'PhabricatorUserRealNameField' => 'applications/people/customfield/PhabricatorUserRealNameField.php', 'PhabricatorUserRolesField' => 'applications/people/customfield/PhabricatorUserRolesField.php', 'PhabricatorUserSchemaSpec' => 'applications/people/storage/PhabricatorUserSchemaSpec.php', 'PhabricatorUserSinceField' => 'applications/people/customfield/PhabricatorUserSinceField.php', 'PhabricatorUserStatusField' => 'applications/people/customfield/PhabricatorUserStatusField.php', '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/people/policyrule/PhabricatorUsersPolicyRule.php', 'PhabricatorUsersSearchField' => 'applications/people/searchfield/PhabricatorUsersSearchField.php', 'PhabricatorVCSResponse' => 'applications/repository/response/PhabricatorVCSResponse.php', 'PhabricatorVersionedDraft' => 'applications/draft/storage/PhabricatorVersionedDraft.php', 'PhabricatorVeryWowEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorVeryWowEnglishTranslation.php', 'PhabricatorViewerDatasource' => 'applications/people/typeahead/PhabricatorViewerDatasource.php', 'PhabricatorWatcherHasObjectEdgeType' => 'applications/transactions/edges/PhabricatorWatcherHasObjectEdgeType.php', 'PhabricatorWebContentSource' => 'infrastructure/contentsource/PhabricatorWebContentSource.php', 'PhabricatorWebServerSetupCheck' => 'applications/config/check/PhabricatorWebServerSetupCheck.php', 'PhabricatorWeekStartDaySetting' => 'applications/settings/setting/PhabricatorWeekStartDaySetting.php', 'PhabricatorWordPressAuthProvider' => 'applications/auth/provider/PhabricatorWordPressAuthProvider.php', 'PhabricatorWorker' => 'infrastructure/daemon/workers/PhabricatorWorker.php', 'PhabricatorWorkerActiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerActiveTask.php', 'PhabricatorWorkerActiveTaskQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerActiveTaskQuery.php', 'PhabricatorWorkerArchiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerArchiveTask.php', 'PhabricatorWorkerArchiveTaskQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php', 'PhabricatorWorkerBulkJob' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJob.php', 'PhabricatorWorkerBulkJobCreateWorker' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobCreateWorker.php', 'PhabricatorWorkerBulkJobEditor' => 'infrastructure/daemon/workers/editor/PhabricatorWorkerBulkJobEditor.php', 'PhabricatorWorkerBulkJobPHIDType' => 'infrastructure/daemon/workers/phid/PhabricatorWorkerBulkJobPHIDType.php', 'PhabricatorWorkerBulkJobQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobQuery.php', 'PhabricatorWorkerBulkJobSearchEngine' => 'infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobSearchEngine.php', 'PhabricatorWorkerBulkJobTaskWorker' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobTaskWorker.php', 'PhabricatorWorkerBulkJobTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerBulkJobTestCase.php', 'PhabricatorWorkerBulkJobTransaction' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerBulkJobTransaction.php', 'PhabricatorWorkerBulkJobTransactionQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerBulkJobTransactionQuery.php', 'PhabricatorWorkerBulkJobType' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobType.php', 'PhabricatorWorkerBulkJobWorker' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerBulkJobWorker.php', 'PhabricatorWorkerBulkTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerBulkTask.php', 'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerDAO.php', 'PhabricatorWorkerDestructionEngineExtension' => 'infrastructure/daemon/workers/engineextension/PhabricatorWorkerDestructionEngineExtension.php', 'PhabricatorWorkerLeaseQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php', 'PhabricatorWorkerManagementCancelWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementCancelWorkflow.php', 'PhabricatorWorkerManagementExecuteWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementExecuteWorkflow.php', 'PhabricatorWorkerManagementFloodWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementFloodWorkflow.php', 'PhabricatorWorkerManagementFreeWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementFreeWorkflow.php', 'PhabricatorWorkerManagementRetryWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementRetryWorkflow.php', 'PhabricatorWorkerManagementWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php', 'PhabricatorWorkerPermanentFailureException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerPermanentFailureException.php', 'PhabricatorWorkerSchemaSpec' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerSchemaSpec.php', 'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTask.php', 'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTaskData.php', 'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php', 'PhabricatorWorkerTaskQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerTaskQuery.php', 'PhabricatorWorkerTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php', 'PhabricatorWorkerTrigger' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTrigger.php', 'PhabricatorWorkerTriggerEvent' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTriggerEvent.php', 'PhabricatorWorkerTriggerManagementFireWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementFireWorkflow.php', 'PhabricatorWorkerTriggerManagementWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerTriggerManagementWorkflow.php', 'PhabricatorWorkerTriggerPHIDType' => 'infrastructure/daemon/workers/phid/PhabricatorWorkerTriggerPHIDType.php', 'PhabricatorWorkerTriggerQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php', 'PhabricatorWorkerYieldException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerYieldException.php', 'PhabricatorWorkingCopyDiscoveryTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyDiscoveryTestCase.php', 'PhabricatorWorkingCopyPullTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php', 'PhabricatorWorkingCopyTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php', 'PhabricatorXHPASTDAO' => 'applications/phpast/storage/PhabricatorXHPASTDAO.php', 'PhabricatorXHPASTParseTree' => 'applications/phpast/storage/PhabricatorXHPASTParseTree.php', 'PhabricatorXHPASTViewController' => 'applications/phpast/controller/PhabricatorXHPASTViewController.php', 'PhabricatorXHPASTViewFrameController' => 'applications/phpast/controller/PhabricatorXHPASTViewFrameController.php', 'PhabricatorXHPASTViewFramesetController' => 'applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php', 'PhabricatorXHPASTViewInputController' => 'applications/phpast/controller/PhabricatorXHPASTViewInputController.php', 'PhabricatorXHPASTViewPanelController' => 'applications/phpast/controller/PhabricatorXHPASTViewPanelController.php', 'PhabricatorXHPASTViewRunController' => 'applications/phpast/controller/PhabricatorXHPASTViewRunController.php', 'PhabricatorXHPASTViewStreamController' => 'applications/phpast/controller/PhabricatorXHPASTViewStreamController.php', 'PhabricatorXHPASTViewTreeController' => 'applications/phpast/controller/PhabricatorXHPASTViewTreeController.php', 'PhabricatorXHProfApplication' => 'applications/xhprof/application/PhabricatorXHProfApplication.php', 'PhabricatorXHProfController' => 'applications/xhprof/controller/PhabricatorXHProfController.php', 'PhabricatorXHProfDAO' => 'applications/xhprof/storage/PhabricatorXHProfDAO.php', 'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/PhabricatorXHProfProfileController.php', 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/PhabricatorXHProfProfileSymbolView.php', 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/PhabricatorXHProfProfileTopLevelView.php', 'PhabricatorXHProfProfileView' => 'applications/xhprof/view/PhabricatorXHProfProfileView.php', 'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php', 'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php', 'PhabricatorYoutubeRemarkupRule' => 'infrastructure/markup/rule/PhabricatorYoutubeRemarkupRule.php', 'Phame404Response' => 'applications/phame/site/Phame404Response.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', 'PhameBlog404Controller' => 'applications/phame/controller/blog/PhameBlog404Controller.php', 'PhameBlogArchiveController' => 'applications/phame/controller/blog/PhameBlogArchiveController.php', 'PhameBlogController' => 'applications/phame/controller/blog/PhameBlogController.php', 'PhameBlogCreateCapability' => 'applications/phame/capability/PhameBlogCreateCapability.php', 'PhameBlogDatasource' => 'applications/phame/typeahead/PhameBlogDatasource.php', 'PhameBlogEditConduitAPIMethod' => 'applications/phame/conduit/PhameBlogEditConduitAPIMethod.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogEditEngine' => 'applications/phame/editor/PhameBlogEditEngine.php', 'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php', 'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php', 'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php', 'PhameBlogHeaderPictureController' => 'applications/phame/controller/blog/PhameBlogHeaderPictureController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', 'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php', 'PhameBlogManageController' => 'applications/phame/controller/blog/PhameBlogManageController.php', 'PhameBlogProfilePictureController' => 'applications/phame/controller/blog/PhameBlogProfilePictureController.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogReplyHandler' => 'applications/phame/mail/PhameBlogReplyHandler.php', 'PhameBlogSearchConduitAPIMethod' => 'applications/phame/conduit/PhameBlogSearchConduitAPIMethod.php', 'PhameBlogSearchEngine' => 'applications/phame/query/PhameBlogSearchEngine.php', 'PhameBlogSite' => 'applications/phame/site/PhameBlogSite.php', 'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php', 'PhameBlogTransactionQuery' => 'applications/phame/query/PhameBlogTransactionQuery.php', 'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php', 'PhameConstants' => 'applications/phame/constants/PhameConstants.php', 'PhameController' => 'applications/phame/controller/PhameController.php', 'PhameDAO' => 'applications/phame/storage/PhameDAO.php', 'PhameDescriptionView' => 'applications/phame/view/PhameDescriptionView.php', 'PhameDraftListView' => 'applications/phame/view/PhameDraftListView.php', 'PhameHomeController' => 'applications/phame/controller/PhameHomeController.php', 'PhameLiveController' => 'applications/phame/controller/PhameLiveController.php', 'PhameNextPostView' => 'applications/phame/view/PhameNextPostView.php', 'PhamePost' => 'applications/phame/storage/PhamePost.php', 'PhamePostArchiveController' => 'applications/phame/controller/post/PhamePostArchiveController.php', 'PhamePostController' => 'applications/phame/controller/post/PhamePostController.php', 'PhamePostEditConduitAPIMethod' => 'applications/phame/conduit/PhamePostEditConduitAPIMethod.php', 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 'PhamePostEditEngine' => 'applications/phame/editor/PhamePostEditEngine.php', 'PhamePostEditor' => 'applications/phame/editor/PhamePostEditor.php', 'PhamePostFulltextEngine' => 'applications/phame/search/PhamePostFulltextEngine.php', 'PhamePostHeaderPictureController' => 'applications/phame/controller/post/PhamePostHeaderPictureController.php', 'PhamePostHistoryController' => 'applications/phame/controller/post/PhamePostHistoryController.php', 'PhamePostListController' => 'applications/phame/controller/post/PhamePostListController.php', 'PhamePostListView' => 'applications/phame/view/PhamePostListView.php', 'PhamePostMailReceiver' => 'applications/phame/mail/PhamePostMailReceiver.php', 'PhamePostMoveController' => 'applications/phame/controller/post/PhamePostMoveController.php', 'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 'PhamePostRemarkupRule' => 'applications/phame/remarkup/PhamePostRemarkupRule.php', 'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php', 'PhamePostSearchConduitAPIMethod' => 'applications/phame/conduit/PhamePostSearchConduitAPIMethod.php', 'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php', 'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php', 'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php', 'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', 'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php', 'PhameSite' => 'applications/phame/site/PhameSite.php', 'PhluxController' => 'applications/phlux/controller/PhluxController.php', 'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php', 'PhluxEditController' => 'applications/phlux/controller/PhluxEditController.php', 'PhluxListController' => 'applications/phlux/controller/PhluxListController.php', 'PhluxTransaction' => 'applications/phlux/storage/PhluxTransaction.php', 'PhluxTransactionQuery' => 'applications/phlux/query/PhluxTransactionQuery.php', 'PhluxVariable' => 'applications/phlux/storage/PhluxVariable.php', 'PhluxVariableEditor' => 'applications/phlux/editor/PhluxVariableEditor.php', 'PhluxVariablePHIDType' => 'applications/phlux/phid/PhluxVariablePHIDType.php', 'PhluxVariableQuery' => 'applications/phlux/query/PhluxVariableQuery.php', 'PhluxViewController' => 'applications/phlux/controller/PhluxViewController.php', 'PholioController' => 'applications/pholio/controller/PholioController.php', 'PholioDAO' => 'applications/pholio/storage/PholioDAO.php', 'PholioDefaultEditCapability' => 'applications/pholio/capability/PholioDefaultEditCapability.php', 'PholioDefaultViewCapability' => 'applications/pholio/capability/PholioDefaultViewCapability.php', 'PholioImage' => 'applications/pholio/storage/PholioImage.php', 'PholioImagePHIDType' => 'applications/pholio/phid/PholioImagePHIDType.php', 'PholioImageQuery' => 'applications/pholio/query/PholioImageQuery.php', 'PholioImageUploadController' => 'applications/pholio/controller/PholioImageUploadController.php', 'PholioInlineController' => 'applications/pholio/controller/PholioInlineController.php', 'PholioInlineListController' => 'applications/pholio/controller/PholioInlineListController.php', 'PholioMock' => 'applications/pholio/storage/PholioMock.php', 'PholioMockArchiveController' => 'applications/pholio/controller/PholioMockArchiveController.php', 'PholioMockAuthorHeraldField' => 'applications/pholio/herald/PholioMockAuthorHeraldField.php', 'PholioMockCommentController' => 'applications/pholio/controller/PholioMockCommentController.php', 'PholioMockDescriptionHeraldField' => 'applications/pholio/herald/PholioMockDescriptionHeraldField.php', 'PholioMockEditController' => 'applications/pholio/controller/PholioMockEditController.php', 'PholioMockEditor' => 'applications/pholio/editor/PholioMockEditor.php', 'PholioMockEmbedView' => 'applications/pholio/view/PholioMockEmbedView.php', 'PholioMockFulltextEngine' => 'applications/pholio/search/PholioMockFulltextEngine.php', 'PholioMockHasTaskEdgeType' => 'applications/pholio/edge/PholioMockHasTaskEdgeType.php', 'PholioMockHasTaskRelationship' => 'applications/pholio/relationships/PholioMockHasTaskRelationship.php', 'PholioMockHeraldField' => 'applications/pholio/herald/PholioMockHeraldField.php', 'PholioMockHeraldFieldGroup' => 'applications/pholio/herald/PholioMockHeraldFieldGroup.php', 'PholioMockImagesView' => 'applications/pholio/view/PholioMockImagesView.php', 'PholioMockListController' => 'applications/pholio/controller/PholioMockListController.php', 'PholioMockMailReceiver' => 'applications/pholio/mail/PholioMockMailReceiver.php', 'PholioMockNameHeraldField' => 'applications/pholio/herald/PholioMockNameHeraldField.php', 'PholioMockPHIDType' => 'applications/pholio/phid/PholioMockPHIDType.php', 'PholioMockQuery' => 'applications/pholio/query/PholioMockQuery.php', 'PholioMockRelationship' => 'applications/pholio/relationships/PholioMockRelationship.php', 'PholioMockRelationshipSource' => 'applications/search/relationship/PholioMockRelationshipSource.php', 'PholioMockSearchEngine' => 'applications/pholio/query/PholioMockSearchEngine.php', 'PholioMockThumbGridView' => 'applications/pholio/view/PholioMockThumbGridView.php', 'PholioMockViewController' => 'applications/pholio/controller/PholioMockViewController.php', 'PholioRemarkupRule' => 'applications/pholio/remarkup/PholioRemarkupRule.php', 'PholioReplyHandler' => 'applications/pholio/mail/PholioReplyHandler.php', 'PholioSchemaSpec' => 'applications/pholio/storage/PholioSchemaSpec.php', 'PholioTransaction' => 'applications/pholio/storage/PholioTransaction.php', 'PholioTransactionComment' => 'applications/pholio/storage/PholioTransactionComment.php', 'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php', 'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php', 'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php', 'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php', 'PhortuneAccountEditController' => 'applications/phortune/controller/PhortuneAccountEditController.php', 'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php', 'PhortuneAccountHasMemberEdgeType' => 'applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php', 'PhortuneAccountListController' => 'applications/phortune/controller/PhortuneAccountListController.php', 'PhortuneAccountPHIDType' => 'applications/phortune/phid/PhortuneAccountPHIDType.php', 'PhortuneAccountQuery' => 'applications/phortune/query/PhortuneAccountQuery.php', 'PhortuneAccountTransaction' => 'applications/phortune/storage/PhortuneAccountTransaction.php', 'PhortuneAccountTransactionQuery' => 'applications/phortune/query/PhortuneAccountTransactionQuery.php', 'PhortuneAccountViewController' => 'applications/phortune/controller/PhortuneAccountViewController.php', 'PhortuneAdHocCart' => 'applications/phortune/cart/PhortuneAdHocCart.php', 'PhortuneAdHocProduct' => 'applications/phortune/product/PhortuneAdHocProduct.php', 'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php', 'PhortuneCartAcceptController' => 'applications/phortune/controller/PhortuneCartAcceptController.php', 'PhortuneCartCancelController' => 'applications/phortune/controller/PhortuneCartCancelController.php', 'PhortuneCartCheckoutController' => 'applications/phortune/controller/PhortuneCartCheckoutController.php', 'PhortuneCartController' => 'applications/phortune/controller/PhortuneCartController.php', 'PhortuneCartEditor' => 'applications/phortune/editor/PhortuneCartEditor.php', 'PhortuneCartImplementation' => 'applications/phortune/cart/PhortuneCartImplementation.php', 'PhortuneCartListController' => 'applications/phortune/controller/PhortuneCartListController.php', 'PhortuneCartPHIDType' => 'applications/phortune/phid/PhortuneCartPHIDType.php', 'PhortuneCartQuery' => 'applications/phortune/query/PhortuneCartQuery.php', 'PhortuneCartReplyHandler' => 'applications/phortune/mail/PhortuneCartReplyHandler.php', 'PhortuneCartSearchEngine' => 'applications/phortune/query/PhortuneCartSearchEngine.php', 'PhortuneCartTransaction' => 'applications/phortune/storage/PhortuneCartTransaction.php', 'PhortuneCartTransactionQuery' => 'applications/phortune/query/PhortuneCartTransactionQuery.php', 'PhortuneCartUpdateController' => 'applications/phortune/controller/PhortuneCartUpdateController.php', 'PhortuneCartViewController' => 'applications/phortune/controller/PhortuneCartViewController.php', 'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php', 'PhortuneChargeListController' => 'applications/phortune/controller/PhortuneChargeListController.php', 'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php', 'PhortuneChargeQuery' => 'applications/phortune/query/PhortuneChargeQuery.php', 'PhortuneChargeSearchEngine' => 'applications/phortune/query/PhortuneChargeSearchEngine.php', 'PhortuneChargeTableView' => 'applications/phortune/view/PhortuneChargeTableView.php', 'PhortuneConstants' => 'applications/phortune/constants/PhortuneConstants.php', 'PhortuneController' => 'applications/phortune/controller/PhortuneController.php', 'PhortuneCreditCardForm' => 'applications/phortune/view/PhortuneCreditCardForm.php', 'PhortuneCurrency' => 'applications/phortune/currency/PhortuneCurrency.php', 'PhortuneCurrencySerializer' => 'applications/phortune/currency/PhortuneCurrencySerializer.php', 'PhortuneCurrencyTestCase' => 'applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php', 'PhortuneDAO' => 'applications/phortune/storage/PhortuneDAO.php', 'PhortuneErrCode' => 'applications/phortune/constants/PhortuneErrCode.php', 'PhortuneInvoiceView' => 'applications/phortune/view/PhortuneInvoiceView.php', 'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php', 'PhortuneMemberHasAccountEdgeType' => 'applications/phortune/edge/PhortuneMemberHasAccountEdgeType.php', 'PhortuneMemberHasMerchantEdgeType' => 'applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php', 'PhortuneMerchant' => 'applications/phortune/storage/PhortuneMerchant.php', 'PhortuneMerchantCapability' => 'applications/phortune/capability/PhortuneMerchantCapability.php', 'PhortuneMerchantController' => 'applications/phortune/controller/PhortuneMerchantController.php', 'PhortuneMerchantEditController' => 'applications/phortune/controller/PhortuneMerchantEditController.php', 'PhortuneMerchantEditEngine' => 'applications/phortune/editor/PhortuneMerchantEditEngine.php', 'PhortuneMerchantEditor' => 'applications/phortune/editor/PhortuneMerchantEditor.php', 'PhortuneMerchantHasMemberEdgeType' => 'applications/phortune/edge/PhortuneMerchantHasMemberEdgeType.php', 'PhortuneMerchantInvoiceCreateController' => 'applications/phortune/controller/PhortuneMerchantInvoiceCreateController.php', 'PhortuneMerchantListController' => 'applications/phortune/controller/PhortuneMerchantListController.php', 'PhortuneMerchantPHIDType' => 'applications/phortune/phid/PhortuneMerchantPHIDType.php', 'PhortuneMerchantPictureController' => 'applications/phortune/controller/PhortuneMerchantPictureController.php', 'PhortuneMerchantQuery' => 'applications/phortune/query/PhortuneMerchantQuery.php', 'PhortuneMerchantSearchEngine' => 'applications/phortune/query/PhortuneMerchantSearchEngine.php', 'PhortuneMerchantTransaction' => 'applications/phortune/storage/PhortuneMerchantTransaction.php', 'PhortuneMerchantTransactionQuery' => 'applications/phortune/query/PhortuneMerchantTransactionQuery.php', 'PhortuneMerchantViewController' => 'applications/phortune/controller/PhortuneMerchantViewController.php', 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 'PhortuneOrderTableView' => 'applications/phortune/view/PhortuneOrderTableView.php', 'PhortunePayPalPaymentProvider' => 'applications/phortune/provider/PhortunePayPalPaymentProvider.php', 'PhortunePaymentMethod' => 'applications/phortune/storage/PhortunePaymentMethod.php', 'PhortunePaymentMethodCreateController' => 'applications/phortune/controller/PhortunePaymentMethodCreateController.php', 'PhortunePaymentMethodDisableController' => 'applications/phortune/controller/PhortunePaymentMethodDisableController.php', 'PhortunePaymentMethodEditController' => 'applications/phortune/controller/PhortunePaymentMethodEditController.php', 'PhortunePaymentMethodPHIDType' => 'applications/phortune/phid/PhortunePaymentMethodPHIDType.php', 'PhortunePaymentMethodQuery' => 'applications/phortune/query/PhortunePaymentMethodQuery.php', 'PhortunePaymentProvider' => 'applications/phortune/provider/PhortunePaymentProvider.php', 'PhortunePaymentProviderConfig' => 'applications/phortune/storage/PhortunePaymentProviderConfig.php', 'PhortunePaymentProviderConfigEditor' => 'applications/phortune/editor/PhortunePaymentProviderConfigEditor.php', 'PhortunePaymentProviderConfigQuery' => 'applications/phortune/query/PhortunePaymentProviderConfigQuery.php', 'PhortunePaymentProviderConfigTransaction' => 'applications/phortune/storage/PhortunePaymentProviderConfigTransaction.php', 'PhortunePaymentProviderConfigTransactionQuery' => 'applications/phortune/query/PhortunePaymentProviderConfigTransactionQuery.php', 'PhortunePaymentProviderPHIDType' => 'applications/phortune/phid/PhortunePaymentProviderPHIDType.php', 'PhortunePaymentProviderTestCase' => 'applications/phortune/provider/__tests__/PhortunePaymentProviderTestCase.php', 'PhortuneProduct' => 'applications/phortune/storage/PhortuneProduct.php', 'PhortuneProductImplementation' => 'applications/phortune/product/PhortuneProductImplementation.php', 'PhortuneProductListController' => 'applications/phortune/controller/PhortuneProductListController.php', 'PhortuneProductPHIDType' => 'applications/phortune/phid/PhortuneProductPHIDType.php', 'PhortuneProductQuery' => 'applications/phortune/query/PhortuneProductQuery.php', 'PhortuneProductViewController' => 'applications/phortune/controller/PhortuneProductViewController.php', 'PhortuneProviderActionController' => 'applications/phortune/controller/PhortuneProviderActionController.php', 'PhortuneProviderDisableController' => 'applications/phortune/controller/PhortuneProviderDisableController.php', 'PhortuneProviderEditController' => 'applications/phortune/controller/PhortuneProviderEditController.php', 'PhortunePurchase' => 'applications/phortune/storage/PhortunePurchase.php', 'PhortunePurchasePHIDType' => 'applications/phortune/phid/PhortunePurchasePHIDType.php', 'PhortunePurchaseQuery' => 'applications/phortune/query/PhortunePurchaseQuery.php', 'PhortuneSchemaSpec' => 'applications/phortune/storage/PhortuneSchemaSpec.php', 'PhortuneStripePaymentProvider' => 'applications/phortune/provider/PhortuneStripePaymentProvider.php', 'PhortuneSubscription' => 'applications/phortune/storage/PhortuneSubscription.php', 'PhortuneSubscriptionCart' => 'applications/phortune/cart/PhortuneSubscriptionCart.php', 'PhortuneSubscriptionEditController' => 'applications/phortune/controller/PhortuneSubscriptionEditController.php', 'PhortuneSubscriptionImplementation' => 'applications/phortune/subscription/PhortuneSubscriptionImplementation.php', 'PhortuneSubscriptionListController' => 'applications/phortune/controller/PhortuneSubscriptionListController.php', 'PhortuneSubscriptionPHIDType' => 'applications/phortune/phid/PhortuneSubscriptionPHIDType.php', 'PhortuneSubscriptionProduct' => 'applications/phortune/product/PhortuneSubscriptionProduct.php', 'PhortuneSubscriptionQuery' => 'applications/phortune/query/PhortuneSubscriptionQuery.php', 'PhortuneSubscriptionSearchEngine' => 'applications/phortune/query/PhortuneSubscriptionSearchEngine.php', 'PhortuneSubscriptionTableView' => 'applications/phortune/view/PhortuneSubscriptionTableView.php', 'PhortuneSubscriptionViewController' => 'applications/phortune/controller/PhortuneSubscriptionViewController.php', 'PhortuneSubscriptionWorker' => 'applications/phortune/worker/PhortuneSubscriptionWorker.php', 'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php', 'PhortuneWePayPaymentProvider' => 'applications/phortune/provider/PhortuneWePayPaymentProvider.php', 'PhragmentBrowseController' => 'applications/phragment/controller/PhragmentBrowseController.php', 'PhragmentCanCreateCapability' => 'applications/phragment/capability/PhragmentCanCreateCapability.php', 'PhragmentConduitAPIMethod' => 'applications/phragment/conduit/PhragmentConduitAPIMethod.php', 'PhragmentController' => 'applications/phragment/controller/PhragmentController.php', 'PhragmentCreateController' => 'applications/phragment/controller/PhragmentCreateController.php', 'PhragmentDAO' => 'applications/phragment/storage/PhragmentDAO.php', 'PhragmentFragment' => 'applications/phragment/storage/PhragmentFragment.php', 'PhragmentFragmentPHIDType' => 'applications/phragment/phid/PhragmentFragmentPHIDType.php', 'PhragmentFragmentQuery' => 'applications/phragment/query/PhragmentFragmentQuery.php', 'PhragmentFragmentVersion' => 'applications/phragment/storage/PhragmentFragmentVersion.php', 'PhragmentFragmentVersionPHIDType' => 'applications/phragment/phid/PhragmentFragmentVersionPHIDType.php', 'PhragmentFragmentVersionQuery' => 'applications/phragment/query/PhragmentFragmentVersionQuery.php', 'PhragmentGetPatchConduitAPIMethod' => 'applications/phragment/conduit/PhragmentGetPatchConduitAPIMethod.php', 'PhragmentHistoryController' => 'applications/phragment/controller/PhragmentHistoryController.php', 'PhragmentPatchController' => 'applications/phragment/controller/PhragmentPatchController.php', 'PhragmentPatchUtil' => 'applications/phragment/util/PhragmentPatchUtil.php', 'PhragmentPolicyController' => 'applications/phragment/controller/PhragmentPolicyController.php', 'PhragmentQueryFragmentsConduitAPIMethod' => 'applications/phragment/conduit/PhragmentQueryFragmentsConduitAPIMethod.php', 'PhragmentRevertController' => 'applications/phragment/controller/PhragmentRevertController.php', 'PhragmentSchemaSpec' => 'applications/phragment/storage/PhragmentSchemaSpec.php', 'PhragmentSnapshot' => 'applications/phragment/storage/PhragmentSnapshot.php', 'PhragmentSnapshotChild' => 'applications/phragment/storage/PhragmentSnapshotChild.php', 'PhragmentSnapshotChildQuery' => 'applications/phragment/query/PhragmentSnapshotChildQuery.php', 'PhragmentSnapshotCreateController' => 'applications/phragment/controller/PhragmentSnapshotCreateController.php', 'PhragmentSnapshotDeleteController' => 'applications/phragment/controller/PhragmentSnapshotDeleteController.php', 'PhragmentSnapshotPHIDType' => 'applications/phragment/phid/PhragmentSnapshotPHIDType.php', 'PhragmentSnapshotPromoteController' => 'applications/phragment/controller/PhragmentSnapshotPromoteController.php', 'PhragmentSnapshotQuery' => 'applications/phragment/query/PhragmentSnapshotQuery.php', 'PhragmentSnapshotViewController' => 'applications/phragment/controller/PhragmentSnapshotViewController.php', 'PhragmentUpdateController' => 'applications/phragment/controller/PhragmentUpdateController.php', 'PhragmentVersionController' => 'applications/phragment/controller/PhragmentVersionController.php', 'PhragmentZIPController' => 'applications/phragment/controller/PhragmentZIPController.php', 'PhrequentConduitAPIMethod' => 'applications/phrequent/conduit/PhrequentConduitAPIMethod.php', 'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php', 'PhrequentCurtainExtension' => 'applications/phrequent/engineextension/PhrequentCurtainExtension.php', 'PhrequentDAO' => 'applications/phrequent/storage/PhrequentDAO.php', 'PhrequentListController' => 'applications/phrequent/controller/PhrequentListController.php', 'PhrequentPopConduitAPIMethod' => 'applications/phrequent/conduit/PhrequentPopConduitAPIMethod.php', 'PhrequentPushConduitAPIMethod' => 'applications/phrequent/conduit/PhrequentPushConduitAPIMethod.php', 'PhrequentSearchEngine' => 'applications/phrequent/query/PhrequentSearchEngine.php', 'PhrequentTimeBlock' => 'applications/phrequent/storage/PhrequentTimeBlock.php', 'PhrequentTimeBlockTestCase' => 'applications/phrequent/storage/__tests__/PhrequentTimeBlockTestCase.php', 'PhrequentTimeSlices' => 'applications/phrequent/storage/PhrequentTimeSlices.php', 'PhrequentTrackController' => 'applications/phrequent/controller/PhrequentTrackController.php', 'PhrequentTrackableInterface' => 'applications/phrequent/interface/PhrequentTrackableInterface.php', 'PhrequentTrackingConduitAPIMethod' => 'applications/phrequent/conduit/PhrequentTrackingConduitAPIMethod.php', 'PhrequentTrackingEditor' => 'applications/phrequent/editor/PhrequentTrackingEditor.php', 'PhrequentUIEventListener' => 'applications/phrequent/event/PhrequentUIEventListener.php', 'PhrequentUserTime' => 'applications/phrequent/storage/PhrequentUserTime.php', 'PhrequentUserTimeQuery' => 'applications/phrequent/query/PhrequentUserTimeQuery.php', 'PhrictionChangeType' => 'applications/phriction/constants/PhrictionChangeType.php', 'PhrictionConduitAPIMethod' => 'applications/phriction/conduit/PhrictionConduitAPIMethod.php', 'PhrictionConstants' => 'applications/phriction/constants/PhrictionConstants.php', 'PhrictionContent' => 'applications/phriction/storage/PhrictionContent.php', 'PhrictionController' => 'applications/phriction/controller/PhrictionController.php', 'PhrictionCreateConduitAPIMethod' => 'applications/phriction/conduit/PhrictionCreateConduitAPIMethod.php', 'PhrictionDAO' => 'applications/phriction/storage/PhrictionDAO.php', 'PhrictionDeleteController' => 'applications/phriction/controller/PhrictionDeleteController.php', 'PhrictionDiffController' => 'applications/phriction/controller/PhrictionDiffController.php', 'PhrictionDocument' => 'applications/phriction/storage/PhrictionDocument.php', 'PhrictionDocumentAuthorHeraldField' => 'applications/phriction/herald/PhrictionDocumentAuthorHeraldField.php', 'PhrictionDocumentContentHeraldField' => 'applications/phriction/herald/PhrictionDocumentContentHeraldField.php', 'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php', 'PhrictionDocumentFulltextEngine' => 'applications/phriction/search/PhrictionDocumentFulltextEngine.php', 'PhrictionDocumentHeraldAdapter' => 'applications/phriction/herald/PhrictionDocumentHeraldAdapter.php', 'PhrictionDocumentHeraldField' => 'applications/phriction/herald/PhrictionDocumentHeraldField.php', 'PhrictionDocumentHeraldFieldGroup' => 'applications/phriction/herald/PhrictionDocumentHeraldFieldGroup.php', 'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php', 'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php', 'PhrictionDocumentQuery' => 'applications/phriction/query/PhrictionDocumentQuery.php', 'PhrictionDocumentStatus' => 'applications/phriction/constants/PhrictionDocumentStatus.php', 'PhrictionDocumentTitleHeraldField' => 'applications/phriction/herald/PhrictionDocumentTitleHeraldField.php', 'PhrictionEditConduitAPIMethod' => 'applications/phriction/conduit/PhrictionEditConduitAPIMethod.php', 'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php', 'PhrictionHistoryConduitAPIMethod' => 'applications/phriction/conduit/PhrictionHistoryConduitAPIMethod.php', 'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php', 'PhrictionInfoConduitAPIMethod' => 'applications/phriction/conduit/PhrictionInfoConduitAPIMethod.php', 'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php', 'PhrictionMarkupPreviewController' => 'applications/phriction/controller/PhrictionMarkupPreviewController.php', 'PhrictionMoveController' => 'applications/phriction/controller/PhrictionMoveController.php', 'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php', 'PhrictionRemarkupRule' => 'applications/phriction/markup/PhrictionRemarkupRule.php', 'PhrictionReplyHandler' => 'applications/phriction/mail/PhrictionReplyHandler.php', 'PhrictionSchemaSpec' => 'applications/phriction/storage/PhrictionSchemaSpec.php', 'PhrictionSearchEngine' => 'applications/phriction/query/PhrictionSearchEngine.php', 'PhrictionTransaction' => 'applications/phriction/storage/PhrictionTransaction.php', 'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php', 'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php', 'PhrictionTransactionQuery' => 'applications/phriction/query/PhrictionTransactionQuery.php', 'PolicyLockOptionType' => 'applications/policy/config/PolicyLockOptionType.php', 'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', 'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', 'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php', 'PonderAnswerEditController' => 'applications/ponder/controller/PonderAnswerEditController.php', 'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php', 'PonderAnswerHistoryController' => 'applications/ponder/controller/PonderAnswerHistoryController.php', 'PonderAnswerMailReceiver' => 'applications/ponder/mail/PonderAnswerMailReceiver.php', 'PonderAnswerPHIDType' => 'applications/ponder/phid/PonderAnswerPHIDType.php', 'PonderAnswerQuery' => 'applications/ponder/query/PonderAnswerQuery.php', 'PonderAnswerReplyHandler' => 'applications/ponder/mail/PonderAnswerReplyHandler.php', 'PonderAnswerSaveController' => 'applications/ponder/controller/PonderAnswerSaveController.php', 'PonderAnswerStatus' => 'applications/ponder/constants/PonderAnswerStatus.php', 'PonderAnswerTransaction' => 'applications/ponder/storage/PonderAnswerTransaction.php', 'PonderAnswerTransactionComment' => 'applications/ponder/storage/PonderAnswerTransactionComment.php', 'PonderAnswerTransactionQuery' => 'applications/ponder/query/PonderAnswerTransactionQuery.php', 'PonderAnswerView' => 'applications/ponder/view/PonderAnswerView.php', 'PonderConstants' => 'applications/ponder/constants/PonderConstants.php', 'PonderController' => 'applications/ponder/controller/PonderController.php', 'PonderDAO' => 'applications/ponder/storage/PonderDAO.php', 'PonderDefaultViewCapability' => 'applications/ponder/capability/PonderDefaultViewCapability.php', 'PonderEditor' => 'applications/ponder/editor/PonderEditor.php', 'PonderFooterView' => 'applications/ponder/view/PonderFooterView.php', 'PonderModerateCapability' => 'applications/ponder/capability/PonderModerateCapability.php', 'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php', 'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php', 'PonderQuestionCreateMailReceiver' => 'applications/ponder/mail/PonderQuestionCreateMailReceiver.php', 'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php', 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 'PonderQuestionFulltextEngine' => 'applications/ponder/search/PonderQuestionFulltextEngine.php', 'PonderQuestionHistoryController' => 'applications/ponder/controller/PonderQuestionHistoryController.php', 'PonderQuestionListController' => 'applications/ponder/controller/PonderQuestionListController.php', 'PonderQuestionMailReceiver' => 'applications/ponder/mail/PonderQuestionMailReceiver.php', 'PonderQuestionPHIDType' => 'applications/ponder/phid/PonderQuestionPHIDType.php', 'PonderQuestionQuery' => 'applications/ponder/query/PonderQuestionQuery.php', 'PonderQuestionReplyHandler' => 'applications/ponder/mail/PonderQuestionReplyHandler.php', 'PonderQuestionSearchEngine' => 'applications/ponder/query/PonderQuestionSearchEngine.php', 'PonderQuestionStatus' => 'applications/ponder/constants/PonderQuestionStatus.php', 'PonderQuestionStatusController' => 'applications/ponder/controller/PonderQuestionStatusController.php', 'PonderQuestionTransaction' => 'applications/ponder/storage/PonderQuestionTransaction.php', 'PonderQuestionTransactionComment' => 'applications/ponder/storage/PonderQuestionTransactionComment.php', 'PonderQuestionTransactionQuery' => 'applications/ponder/query/PonderQuestionTransactionQuery.php', 'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php', 'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php', 'PonderSchemaSpec' => 'applications/ponder/storage/PonderSchemaSpec.php', 'ProjectAddProjectsEmailCommand' => 'applications/project/command/ProjectAddProjectsEmailCommand.php', 'ProjectBoardTaskCard' => 'applications/project/view/ProjectBoardTaskCard.php', 'ProjectCanLockProjectsCapability' => 'applications/project/capability/ProjectCanLockProjectsCapability.php', 'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php', 'ProjectCreateConduitAPIMethod' => 'applications/project/conduit/ProjectCreateConduitAPIMethod.php', 'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php', 'ProjectDefaultEditCapability' => 'applications/project/capability/ProjectDefaultEditCapability.php', 'ProjectDefaultJoinCapability' => 'applications/project/capability/ProjectDefaultJoinCapability.php', 'ProjectDefaultViewCapability' => 'applications/project/capability/ProjectDefaultViewCapability.php', 'ProjectEditConduitAPIMethod' => 'applications/project/conduit/ProjectEditConduitAPIMethod.php', 'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php', 'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php', 'ProjectRemarkupRuleTestCase' => 'applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php', 'ProjectReplyHandler' => 'applications/project/mail/ProjectReplyHandler.php', 'ProjectSearchConduitAPIMethod' => 'applications/project/conduit/ProjectSearchConduitAPIMethod.php', 'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php', 'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php', 'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php', 'ReleephBranchAccessController' => 'applications/releeph/controller/branch/ReleephBranchAccessController.php', 'ReleephBranchCommitFieldSpecification' => 'applications/releeph/field/specification/ReleephBranchCommitFieldSpecification.php', 'ReleephBranchController' => 'applications/releeph/controller/branch/ReleephBranchController.php', 'ReleephBranchCreateController' => 'applications/releeph/controller/branch/ReleephBranchCreateController.php', 'ReleephBranchEditController' => 'applications/releeph/controller/branch/ReleephBranchEditController.php', 'ReleephBranchEditor' => 'applications/releeph/editor/ReleephBranchEditor.php', 'ReleephBranchHistoryController' => 'applications/releeph/controller/branch/ReleephBranchHistoryController.php', 'ReleephBranchNamePreviewController' => 'applications/releeph/controller/branch/ReleephBranchNamePreviewController.php', 'ReleephBranchPHIDType' => 'applications/releeph/phid/ReleephBranchPHIDType.php', 'ReleephBranchPreviewView' => 'applications/releeph/view/branch/ReleephBranchPreviewView.php', 'ReleephBranchQuery' => 'applications/releeph/query/ReleephBranchQuery.php', 'ReleephBranchSearchEngine' => 'applications/releeph/query/ReleephBranchSearchEngine.php', 'ReleephBranchTemplate' => 'applications/releeph/view/branch/ReleephBranchTemplate.php', 'ReleephBranchTransaction' => 'applications/releeph/storage/ReleephBranchTransaction.php', 'ReleephBranchTransactionQuery' => 'applications/releeph/query/ReleephBranchTransactionQuery.php', 'ReleephBranchViewController' => 'applications/releeph/controller/branch/ReleephBranchViewController.php', 'ReleephCommitFinder' => 'applications/releeph/commitfinder/ReleephCommitFinder.php', 'ReleephCommitFinderException' => 'applications/releeph/commitfinder/ReleephCommitFinderException.php', 'ReleephCommitMessageFieldSpecification' => 'applications/releeph/field/specification/ReleephCommitMessageFieldSpecification.php', 'ReleephConduitAPIMethod' => 'applications/releeph/conduit/ReleephConduitAPIMethod.php', 'ReleephController' => 'applications/releeph/controller/ReleephController.php', 'ReleephDAO' => 'applications/releeph/storage/ReleephDAO.php', 'ReleephDefaultFieldSelector' => 'applications/releeph/field/selector/ReleephDefaultFieldSelector.php', 'ReleephDependsOnFieldSpecification' => 'applications/releeph/field/specification/ReleephDependsOnFieldSpecification.php', 'ReleephDiffChurnFieldSpecification' => 'applications/releeph/field/specification/ReleephDiffChurnFieldSpecification.php', 'ReleephDiffMessageFieldSpecification' => 'applications/releeph/field/specification/ReleephDiffMessageFieldSpecification.php', 'ReleephDiffSizeFieldSpecification' => 'applications/releeph/field/specification/ReleephDiffSizeFieldSpecification.php', 'ReleephFieldParseException' => 'applications/releeph/field/exception/ReleephFieldParseException.php', 'ReleephFieldSelector' => 'applications/releeph/field/selector/ReleephFieldSelector.php', 'ReleephFieldSpecification' => 'applications/releeph/field/specification/ReleephFieldSpecification.php', 'ReleephGetBranchesConduitAPIMethod' => 'applications/releeph/conduit/ReleephGetBranchesConduitAPIMethod.php', 'ReleephIntentFieldSpecification' => 'applications/releeph/field/specification/ReleephIntentFieldSpecification.php', 'ReleephLevelFieldSpecification' => 'applications/releeph/field/specification/ReleephLevelFieldSpecification.php', 'ReleephOriginalCommitFieldSpecification' => 'applications/releeph/field/specification/ReleephOriginalCommitFieldSpecification.php', 'ReleephProductActionController' => 'applications/releeph/controller/product/ReleephProductActionController.php', 'ReleephProductController' => 'applications/releeph/controller/product/ReleephProductController.php', 'ReleephProductCreateController' => 'applications/releeph/controller/product/ReleephProductCreateController.php', 'ReleephProductEditController' => 'applications/releeph/controller/product/ReleephProductEditController.php', 'ReleephProductEditor' => 'applications/releeph/editor/ReleephProductEditor.php', 'ReleephProductHistoryController' => 'applications/releeph/controller/product/ReleephProductHistoryController.php', 'ReleephProductListController' => 'applications/releeph/controller/product/ReleephProductListController.php', 'ReleephProductPHIDType' => 'applications/releeph/phid/ReleephProductPHIDType.php', 'ReleephProductQuery' => 'applications/releeph/query/ReleephProductQuery.php', 'ReleephProductSearchEngine' => 'applications/releeph/query/ReleephProductSearchEngine.php', 'ReleephProductTransaction' => 'applications/releeph/storage/ReleephProductTransaction.php', 'ReleephProductTransactionQuery' => 'applications/releeph/query/ReleephProductTransactionQuery.php', 'ReleephProductViewController' => 'applications/releeph/controller/product/ReleephProductViewController.php', 'ReleephProject' => 'applications/releeph/storage/ReleephProject.php', 'ReleephQueryBranchesConduitAPIMethod' => 'applications/releeph/conduit/ReleephQueryBranchesConduitAPIMethod.php', 'ReleephQueryProductsConduitAPIMethod' => 'applications/releeph/conduit/ReleephQueryProductsConduitAPIMethod.php', 'ReleephQueryRequestsConduitAPIMethod' => 'applications/releeph/conduit/ReleephQueryRequestsConduitAPIMethod.php', 'ReleephReasonFieldSpecification' => 'applications/releeph/field/specification/ReleephReasonFieldSpecification.php', 'ReleephRequest' => 'applications/releeph/storage/ReleephRequest.php', 'ReleephRequestActionController' => 'applications/releeph/controller/request/ReleephRequestActionController.php', 'ReleephRequestCommentController' => 'applications/releeph/controller/request/ReleephRequestCommentController.php', 'ReleephRequestConduitAPIMethod' => 'applications/releeph/conduit/ReleephRequestConduitAPIMethod.php', 'ReleephRequestController' => 'applications/releeph/controller/request/ReleephRequestController.php', 'ReleephRequestDifferentialCreateController' => 'applications/releeph/controller/request/ReleephRequestDifferentialCreateController.php', 'ReleephRequestEditController' => 'applications/releeph/controller/request/ReleephRequestEditController.php', 'ReleephRequestMailReceiver' => 'applications/releeph/mail/ReleephRequestMailReceiver.php', 'ReleephRequestPHIDType' => 'applications/releeph/phid/ReleephRequestPHIDType.php', 'ReleephRequestQuery' => 'applications/releeph/query/ReleephRequestQuery.php', 'ReleephRequestReplyHandler' => 'applications/releeph/mail/ReleephRequestReplyHandler.php', 'ReleephRequestSearchEngine' => 'applications/releeph/query/ReleephRequestSearchEngine.php', 'ReleephRequestStatus' => 'applications/releeph/constants/ReleephRequestStatus.php', 'ReleephRequestTransaction' => 'applications/releeph/storage/ReleephRequestTransaction.php', 'ReleephRequestTransactionComment' => 'applications/releeph/storage/ReleephRequestTransactionComment.php', 'ReleephRequestTransactionQuery' => 'applications/releeph/query/ReleephRequestTransactionQuery.php', 'ReleephRequestTransactionalEditor' => 'applications/releeph/editor/ReleephRequestTransactionalEditor.php', 'ReleephRequestTypeaheadControl' => 'applications/releeph/view/request/ReleephRequestTypeaheadControl.php', 'ReleephRequestTypeaheadController' => 'applications/releeph/controller/request/ReleephRequestTypeaheadController.php', 'ReleephRequestView' => 'applications/releeph/view/ReleephRequestView.php', 'ReleephRequestViewController' => 'applications/releeph/controller/request/ReleephRequestViewController.php', 'ReleephRequestorFieldSpecification' => 'applications/releeph/field/specification/ReleephRequestorFieldSpecification.php', 'ReleephRevisionFieldSpecification' => 'applications/releeph/field/specification/ReleephRevisionFieldSpecification.php', 'ReleephSeverityFieldSpecification' => 'applications/releeph/field/specification/ReleephSeverityFieldSpecification.php', 'ReleephSummaryFieldSpecification' => 'applications/releeph/field/specification/ReleephSummaryFieldSpecification.php', 'ReleephWorkCanPushConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkCanPushConduitAPIMethod.php', 'ReleephWorkGetAuthorInfoConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkGetAuthorInfoConduitAPIMethod.php', 'ReleephWorkGetBranchCommitMessageConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkGetBranchCommitMessageConduitAPIMethod.php', 'ReleephWorkGetBranchConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkGetBranchConduitAPIMethod.php', 'ReleephWorkGetCommitMessageConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkGetCommitMessageConduitAPIMethod.php', 'ReleephWorkNextRequestConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkNextRequestConduitAPIMethod.php', 'ReleephWorkRecordConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkRecordConduitAPIMethod.php', 'ReleephWorkRecordPickStatusConduitAPIMethod' => 'applications/releeph/conduit/work/ReleephWorkRecordPickStatusConduitAPIMethod.php', 'RemarkupProcessConduitAPIMethod' => 'applications/remarkup/conduit/RemarkupProcessConduitAPIMethod.php', 'RepositoryConduitAPIMethod' => 'applications/repository/conduit/RepositoryConduitAPIMethod.php', 'RepositoryQueryConduitAPIMethod' => 'applications/repository/conduit/RepositoryQueryConduitAPIMethod.php', 'ShellLogView' => 'applications/harbormaster/view/ShellLogView.php', 'SlowvoteConduitAPIMethod' => 'applications/slowvote/conduit/SlowvoteConduitAPIMethod.php', 'SlowvoteEmbedView' => 'applications/slowvote/view/SlowvoteEmbedView.php', 'SlowvoteInfoConduitAPIMethod' => 'applications/slowvote/conduit/SlowvoteInfoConduitAPIMethod.php', 'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php', 'SubscriptionListDialogBuilder' => 'applications/subscriptions/view/SubscriptionListDialogBuilder.php', 'SubscriptionListStringBuilder' => 'applications/subscriptions/view/SubscriptionListStringBuilder.php', 'TokenConduitAPIMethod' => 'applications/tokens/conduit/TokenConduitAPIMethod.php', 'TokenGiveConduitAPIMethod' => 'applications/tokens/conduit/TokenGiveConduitAPIMethod.php', 'TokenGivenConduitAPIMethod' => 'applications/tokens/conduit/TokenGivenConduitAPIMethod.php', 'TokenQueryConduitAPIMethod' => 'applications/tokens/conduit/TokenQueryConduitAPIMethod.php', 'UserConduitAPIMethod' => 'applications/people/conduit/UserConduitAPIMethod.php', 'UserDisableConduitAPIMethod' => 'applications/people/conduit/UserDisableConduitAPIMethod.php', 'UserEnableConduitAPIMethod' => 'applications/people/conduit/UserEnableConduitAPIMethod.php', 'UserFindConduitAPIMethod' => 'applications/people/conduit/UserFindConduitAPIMethod.php', 'UserQueryConduitAPIMethod' => 'applications/people/conduit/UserQueryConduitAPIMethod.php', 'UserSearchConduitAPIMethod' => 'applications/people/conduit/UserSearchConduitAPIMethod.php', 'UserWhoAmIConduitAPIMethod' => 'applications/people/conduit/UserWhoAmIConduitAPIMethod.php', ), 'function' => array( 'celerity_generate_unique_node_id' => 'applications/celerity/api.php', 'celerity_get_resource_uri' => 'applications/celerity/api.php', 'javelin_tag' => 'infrastructure/javelin/markup.php', 'phabricator_date' => 'view/viewutils.php', 'phabricator_datetime' => 'view/viewutils.php', 'phabricator_form' => 'infrastructure/javelin/markup.php', 'phabricator_format_local_time' => 'view/viewutils.php', 'phabricator_relative_date' => 'view/viewutils.php', 'phabricator_time' => 'view/viewutils.php', 'phid_get_subtype' => 'applications/phid/utils.php', 'phid_get_type' => 'applications/phid/utils.php', 'phid_group_by_type' => 'applications/phid/utils.php', 'require_celerity_resource' => 'applications/celerity/api.php', ), 'xmap' => array( 'AlmanacAddress' => 'Phobject', 'AlmanacBinding' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'AlmanacPropertyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorExtendedPolicyInterface', ), 'AlmanacBindingDisableController' => 'AlmanacServiceController', 'AlmanacBindingEditController' => 'AlmanacServiceController', 'AlmanacBindingEditor' => 'AlmanacEditor', 'AlmanacBindingPHIDType' => 'PhabricatorPHIDType', 'AlmanacBindingPropertyEditEngine' => 'AlmanacPropertyEditEngine', 'AlmanacBindingQuery' => 'AlmanacQuery', 'AlmanacBindingTableView' => 'AphrontView', 'AlmanacBindingTransaction' => 'AlmanacTransaction', 'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacBindingViewController' => 'AlmanacServiceController', 'AlmanacBindingsSearchEngineAttachment' => 'AlmanacSearchEngineAttachment', 'AlmanacCacheEngineExtension' => 'PhabricatorCacheEngineExtension', 'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType', 'AlmanacClusterRepositoryServiceType' => 'AlmanacClusterServiceType', 'AlmanacClusterServiceType' => 'AlmanacServiceType', 'AlmanacConsoleController' => 'AlmanacController', 'AlmanacController' => 'PhabricatorController', 'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability', 'AlmanacCreateNamespacesCapability' => 'PhabricatorPolicyCapability', 'AlmanacCreateNetworksCapability' => 'PhabricatorPolicyCapability', 'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability', 'AlmanacCustomServiceType' => 'AlmanacServiceType', 'AlmanacDAO' => 'PhabricatorLiskDAO', 'AlmanacDevice' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'PhabricatorSSHPublicKeyInterface', 'AlmanacPropertyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', 'PhabricatorConduitResultInterface', 'PhabricatorExtendedPolicyInterface', ), 'AlmanacDeviceController' => 'AlmanacController', 'AlmanacDeviceEditController' => 'AlmanacDeviceController', 'AlmanacDeviceEditEngine' => 'PhabricatorEditEngine', 'AlmanacDeviceEditor' => 'AlmanacEditor', 'AlmanacDeviceListController' => 'AlmanacDeviceController', 'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacDevicePHIDType' => 'PhabricatorPHIDType', 'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine', 'AlmanacDeviceQuery' => 'AlmanacQuery', 'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacDeviceTransaction' => 'AlmanacTransaction', 'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacDeviceViewController' => 'AlmanacDeviceController', 'AlmanacDrydockPoolServiceType' => 'AlmanacServiceType', 'AlmanacEditor' => 'PhabricatorApplicationTransactionEditor', 'AlmanacInterface' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorExtendedPolicyInterface', ), 'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource', 'AlmanacInterfaceDeleteController' => 'AlmanacDeviceController', 'AlmanacInterfaceEditController' => 'AlmanacDeviceController', 'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType', 'AlmanacInterfaceQuery' => 'AlmanacQuery', 'AlmanacInterfaceTableView' => 'AphrontView', 'AlmanacKeys' => 'Phobject', 'AlmanacManageClusterServicesCapability' => 'PhabricatorPolicyCapability', 'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow', 'AlmanacManagementTrustKeyWorkflow' => 'AlmanacManagementWorkflow', 'AlmanacManagementUntrustKeyWorkflow' => 'AlmanacManagementWorkflow', 'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow', 'AlmanacNames' => 'Phobject', 'AlmanacNamesTestCase' => 'PhabricatorTestCase', 'AlmanacNamespace' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'AlmanacPropertyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', ), 'AlmanacNamespaceController' => 'AlmanacController', 'AlmanacNamespaceEditController' => 'AlmanacNamespaceController', 'AlmanacNamespaceEditEngine' => 'PhabricatorEditEngine', 'AlmanacNamespaceEditor' => 'PhabricatorApplicationTransactionEditor', 'AlmanacNamespaceListController' => 'AlmanacNamespaceController', 'AlmanacNamespaceNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacNamespacePHIDType' => 'PhabricatorPHIDType', 'AlmanacNamespaceQuery' => 'AlmanacQuery', 'AlmanacNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacNamespaceTransaction' => 'PhabricatorApplicationTransaction', 'AlmanacNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacNamespaceViewController' => 'AlmanacNamespaceController', 'AlmanacNetwork' => array( 'AlmanacDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', ), 'AlmanacNetworkController' => 'AlmanacController', 'AlmanacNetworkEditController' => 'AlmanacNetworkController', 'AlmanacNetworkEditEngine' => 'PhabricatorEditEngine', 'AlmanacNetworkEditor' => 'PhabricatorApplicationTransactionEditor', 'AlmanacNetworkListController' => 'AlmanacNetworkController', 'AlmanacNetworkNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacNetworkPHIDType' => 'PhabricatorPHIDType', 'AlmanacNetworkQuery' => 'AlmanacQuery', 'AlmanacNetworkSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacNetworkTransaction' => 'PhabricatorApplicationTransaction', 'AlmanacNetworkTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacNetworkViewController' => 'AlmanacNetworkController', 'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'AlmanacPropertiesSearchEngineAttachment' => 'AlmanacSearchEngineAttachment', 'AlmanacProperty' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', ), 'AlmanacPropertyController' => 'AlmanacController', 'AlmanacPropertyDeleteController' => 'AlmanacPropertyController', 'AlmanacPropertyEditController' => 'AlmanacPropertyController', 'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine', 'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'AlmanacSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'AlmanacSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'AlmanacService' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'AlmanacPropertyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', 'PhabricatorConduitResultInterface', 'PhabricatorExtendedPolicyInterface', ), 'AlmanacServiceController' => 'AlmanacController', 'AlmanacServiceDatasource' => 'PhabricatorTypeaheadDatasource', 'AlmanacServiceEditController' => 'AlmanacServiceController', 'AlmanacServiceEditEngine' => 'PhabricatorEditEngine', 'AlmanacServiceEditor' => 'AlmanacEditor', 'AlmanacServiceListController' => 'AlmanacServiceController', 'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacServicePHIDType' => 'PhabricatorPHIDType', 'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine', 'AlmanacServiceQuery' => 'AlmanacQuery', 'AlmanacServiceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacServiceTransaction' => 'AlmanacTransaction', 'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacServiceType' => 'Phobject', 'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource', 'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase', 'AlmanacServiceViewController' => 'AlmanacServiceController', 'AlmanacTransaction' => 'PhabricatorApplicationTransaction', 'AphlictDropdownDataQuery' => 'Phobject', 'Aphront304Response' => 'AphrontResponse', 'Aphront400Response' => 'AphrontResponse', 'Aphront403Response' => 'AphrontHTMLResponse', 'Aphront404Response' => 'AphrontHTMLResponse', 'AphrontAjaxResponse' => 'AphrontResponse', 'AphrontApplicationConfiguration' => 'Phobject', 'AphrontBarView' => 'AphrontView', 'AphrontBoolHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontCalendarEventView' => 'AphrontView', 'AphrontController' => 'Phobject', 'AphrontCursorPagerView' => 'AphrontView', 'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration', 'AphrontDialogResponse' => 'AphrontResponse', 'AphrontDialogView' => array( 'AphrontView', 'AphrontResponseProducerInterface', ), 'AphrontEpochHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontException' => 'Exception', 'AphrontFileHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontFileResponse' => 'AphrontResponse', 'AphrontFormCheckboxControl' => 'AphrontFormControl', 'AphrontFormControl' => 'AphrontView', 'AphrontFormDateControl' => 'AphrontFormControl', 'AphrontFormDateControlValue' => 'Phobject', 'AphrontFormDividerControl' => 'AphrontFormControl', 'AphrontFormFileControl' => 'AphrontFormControl', 'AphrontFormHandlesControl' => 'AphrontFormControl', 'AphrontFormMarkupControl' => 'AphrontFormControl', 'AphrontFormPasswordControl' => 'AphrontFormControl', 'AphrontFormPolicyControl' => 'AphrontFormControl', 'AphrontFormRadioButtonControl' => 'AphrontFormControl', 'AphrontFormRecaptchaControl' => 'AphrontFormControl', 'AphrontFormSelectControl' => 'AphrontFormControl', 'AphrontFormStaticControl' => 'AphrontFormControl', 'AphrontFormSubmitControl' => 'AphrontFormControl', 'AphrontFormTextAreaControl' => 'AphrontFormControl', 'AphrontFormTextControl' => 'AphrontFormControl', 'AphrontFormTextWithSubmitControl' => 'AphrontFormControl', 'AphrontFormTokenizerControl' => 'AphrontFormControl', 'AphrontFormTypeaheadControl' => 'AphrontFormControl', 'AphrontFormView' => 'AphrontView', 'AphrontGlyphBarView' => 'AphrontBarView', 'AphrontHTMLResponse' => 'AphrontResponse', 'AphrontHTTPParameterType' => 'Phobject', 'AphrontHTTPProxyResponse' => 'AphrontResponse', 'AphrontHTTPSink' => 'Phobject', 'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase', 'AphrontIntHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink', 'AphrontJSONResponse' => 'AphrontResponse', 'AphrontJavelinView' => 'AphrontView', 'AphrontKeyboardShortcutsAvailableView' => 'AphrontView', 'AphrontListFilterView' => 'AphrontView', 'AphrontListHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontMalformedRequestException' => 'AphrontException', 'AphrontMoreView' => 'AphrontView', 'AphrontMultiColumnView' => 'AphrontView', 'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontNullView' => 'AphrontView', 'AphrontPHIDHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontPHIDListHTTPParameterType' => 'AphrontListHTTPParameterType', 'AphrontPHPHTTPSink' => 'AphrontHTTPSink', 'AphrontPageView' => 'AphrontView', 'AphrontPlainTextResponse' => 'AphrontResponse', 'AphrontProgressBarView' => 'AphrontBarView', 'AphrontProjectListHTTPParameterType' => 'AphrontListHTTPParameterType', 'AphrontProxyResponse' => array( 'AphrontResponse', 'AphrontResponseProducerInterface', ), 'AphrontRedirectResponse' => 'AphrontResponse', 'AphrontRedirectResponseTestCase' => 'PhabricatorTestCase', 'AphrontReloadResponse' => 'AphrontRedirectResponse', 'AphrontRequest' => 'Phobject', 'AphrontRequestExceptionHandler' => 'Phobject', 'AphrontRequestTestCase' => 'PhabricatorTestCase', 'AphrontResponse' => 'Phobject', 'AphrontRoutingMap' => 'Phobject', 'AphrontRoutingResult' => 'Phobject', 'AphrontSelectHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontSideNavFilterView' => 'AphrontView', 'AphrontSite' => 'Phobject', 'AphrontStackTraceView' => 'AphrontView', 'AphrontStandaloneHTMLResponse' => 'AphrontHTMLResponse', 'AphrontStringHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontStringListHTTPParameterType' => 'AphrontListHTTPParameterType', 'AphrontTableView' => 'AphrontView', 'AphrontTagView' => 'AphrontView', 'AphrontTokenizerTemplateView' => 'AphrontView', 'AphrontTypeaheadTemplateView' => 'AphrontView', 'AphrontUnhandledExceptionResponse' => 'AphrontStandaloneHTMLResponse', 'AphrontUserListHTTPParameterType' => 'AphrontListHTTPParameterType', 'AphrontView' => array( 'Phobject', 'PhutilSafeHTMLProducerInterface', ), 'AphrontWebpageResponse' => 'AphrontHTMLResponse', 'ArcanistConduitAPIMethod' => 'ConduitAPIMethod', 'AuditConduitAPIMethod' => 'ConduitAPIMethod', 'AuditQueryConduitAPIMethod' => 'AuditConduitAPIMethod', 'AuthManageProvidersCapability' => 'PhabricatorPolicyCapability', 'CalendarTimeUtil' => 'Phobject', 'CalendarTimeUtilTestCase' => 'PhabricatorTestCase', 'CelerityAPI' => 'Phobject', 'CelerityDefaultPostprocessor' => 'CelerityPostprocessor', 'CelerityHighContrastPostprocessor' => 'CelerityPostprocessor', 'CelerityLargeFontPostprocessor' => 'CelerityPostprocessor', 'CelerityManagementMapWorkflow' => 'CelerityManagementWorkflow', 'CelerityManagementSyntaxWorkflow' => 'CelerityManagementWorkflow', 'CelerityManagementWorkflow' => 'PhabricatorManagementWorkflow', 'CelerityPhabricatorResourceController' => 'CelerityResourceController', 'CelerityPhabricatorResources' => 'CelerityResourcesOnDisk', 'CelerityPhysicalResources' => 'CelerityResources', 'CelerityPhysicalResourcesTestCase' => 'PhabricatorTestCase', 'CelerityPostprocessor' => 'Phobject', 'CelerityPostprocessorTestCase' => 'PhabricatorTestCase', 'CelerityResourceController' => 'PhabricatorController', 'CelerityResourceGraph' => 'AbstractDirectedGraph', 'CelerityResourceMap' => 'Phobject', 'CelerityResourceMapGenerator' => 'Phobject', 'CelerityResourceTransformer' => 'Phobject', 'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase', 'CelerityResources' => 'Phobject', 'CelerityResourcesOnDisk' => 'CelerityPhysicalResources', 'CeleritySpriteGenerator' => 'Phobject', 'CelerityStaticResourceResponse' => 'Phobject', 'ChatLogConduitAPIMethod' => 'ConduitAPIMethod', 'ChatLogQueryConduitAPIMethod' => 'ChatLogConduitAPIMethod', 'ChatLogRecordConduitAPIMethod' => 'ChatLogConduitAPIMethod', 'ConduitAPIMethod' => array( 'Phobject', 'PhabricatorPolicyInterface', ), 'ConduitAPIMethodTestCase' => 'PhabricatorTestCase', 'ConduitAPIRequest' => 'Phobject', 'ConduitAPIResponse' => 'Phobject', 'ConduitApplicationNotInstalledException' => 'ConduitMethodNotFoundException', 'ConduitBoolParameterType' => 'ConduitParameterType', 'ConduitCall' => 'Phobject', 'ConduitCallTestCase' => 'PhabricatorTestCase', 'ConduitColumnsParameterType' => 'ConduitParameterType', 'ConduitConnectConduitAPIMethod' => 'ConduitAPIMethod', 'ConduitEpochParameterType' => 'ConduitParameterType', 'ConduitException' => 'Exception', 'ConduitGetCapabilitiesConduitAPIMethod' => 'ConduitAPIMethod', 'ConduitGetCertificateConduitAPIMethod' => 'ConduitAPIMethod', 'ConduitIntListParameterType' => 'ConduitListParameterType', 'ConduitIntParameterType' => 'ConduitParameterType', 'ConduitListParameterType' => 'ConduitParameterType', 'ConduitLogGarbageCollector' => 'PhabricatorGarbageCollector', 'ConduitMethodDoesNotExistException' => 'ConduitMethodNotFoundException', 'ConduitMethodNotFoundException' => 'ConduitException', 'ConduitPHIDListParameterType' => 'ConduitListParameterType', 'ConduitPHIDParameterType' => 'ConduitParameterType', 'ConduitParameterType' => 'Phobject', 'ConduitPingConduitAPIMethod' => 'ConduitAPIMethod', 'ConduitPointsParameterType' => 'ConduitParameterType', 'ConduitProjectListParameterType' => 'ConduitListParameterType', 'ConduitQueryConduitAPIMethod' => 'ConduitAPIMethod', 'ConduitResultSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'ConduitSSHWorkflow' => 'PhabricatorSSHWorkflow', 'ConduitStringListParameterType' => 'ConduitListParameterType', 'ConduitStringParameterType' => 'ConduitParameterType', 'ConduitTokenGarbageCollector' => 'PhabricatorGarbageCollector', 'ConduitUserListParameterType' => 'ConduitListParameterType', 'ConduitUserParameterType' => 'ConduitParameterType', 'ConduitWildParameterType' => 'ConduitParameterType', 'ConpherenceColumnViewController' => 'ConpherenceController', 'ConpherenceConduitAPIMethod' => 'ConduitAPIMethod', 'ConpherenceConfigOptions' => 'PhabricatorApplicationConfigOptions', 'ConpherenceConstants' => 'Phobject', 'ConpherenceController' => 'PhabricatorController', 'ConpherenceCreateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceDAO' => 'PhabricatorLiskDAO', 'ConpherenceDurableColumnView' => 'AphrontTagView', 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 'ConpherenceFulltextQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceIndex' => 'ConpherenceDAO', 'ConpherenceLayoutView' => 'AphrontTagView', 'ConpherenceListController' => 'ConpherenceController', 'ConpherenceMenuItemView' => 'AphrontTagView', 'ConpherenceNewRoomController' => 'ConpherenceController', 'ConpherenceNotificationPanelController' => 'ConpherenceController', 'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipantController' => 'ConpherenceController', 'ConpherenceParticipantCountQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipantView' => 'AphrontView', 'ConpherenceParticipationStatus' => 'ConpherenceConstants', 'ConpherenceQueryThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceQueryTransactionConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler', 'ConpherenceRoomListController' => 'ConpherenceController', 'ConpherenceRoomPictureController' => 'ConpherenceController', 'ConpherenceRoomTestCase' => 'ConpherenceTestCase', 'ConpherenceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ConpherenceTestCase' => 'PhabricatorTestCase', 'ConpherenceThread' => array( 'ConpherenceDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorMentionableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', ), 'ConpherenceThreadDatasource' => 'PhabricatorTypeaheadDatasource', 'ConpherenceThreadIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'ConpherenceThreadListView' => 'AphrontView', 'ConpherenceThreadMailReceiver' => 'PhabricatorObjectMailReceiver', 'ConpherenceThreadMembersPolicyRule' => 'PhabricatorPolicyRule', 'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ConpherenceThreadRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ConpherenceThreadSearchController' => 'ConpherenceController', 'ConpherenceThreadSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ConpherenceThreadTitleNgrams' => 'PhabricatorSearchNgrams', 'ConpherenceTransaction' => 'PhabricatorApplicationTransaction', 'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ConpherenceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ConpherenceTransactionRenderer' => 'Phobject', 'ConpherenceTransactionView' => 'AphrontView', 'ConpherenceUpdateActions' => 'ConpherenceConstants', 'ConpherenceUpdateController' => 'ConpherenceController', 'ConpherenceUpdateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceViewController' => 'ConpherenceController', 'DarkConsoleController' => 'PhabricatorController', 'DarkConsoleCore' => 'Phobject', 'DarkConsoleDataController' => 'PhabricatorController', 'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin', 'DarkConsoleErrorLogPluginAPI' => 'Phobject', 'DarkConsoleEventPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPluginAPI' => 'PhabricatorEventListener', 'DarkConsolePlugin' => 'Phobject', 'DarkConsoleRequestPlugin' => 'DarkConsolePlugin', 'DarkConsoleServicesPlugin' => 'DarkConsolePlugin', 'DarkConsoleStartupPlugin' => 'DarkConsolePlugin', 'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin', 'DarkConsoleXHProfPluginAPI' => 'Phobject', 'DifferentialAction' => 'Phobject', 'DifferentialActionEmailCommand' => 'MetaMTAEmailTransactionCommand', 'DifferentialAddCommentView' => 'AphrontView', 'DifferentialAdjustmentMapTestCase' => 'PhutilTestCase', 'DifferentialAffectedPath' => 'DifferentialDAO', - 'DifferentialApplyPatchField' => 'DifferentialCustomField', 'DifferentialAsanaRepresentationField' => 'DifferentialCustomField', + 'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialAuditorsField' => 'DifferentialStoredCustomField', - 'DifferentialAuthorField' => 'DifferentialCustomField', + 'DifferentialBlameRevisionCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialBlameRevisionField' => 'DifferentialStoredCustomField', 'DifferentialBlockHeraldAction' => 'HeraldAction', 'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialBranchField' => 'DifferentialCustomField', 'DifferentialChangeDetailMailView' => 'DifferentialMailView', 'DifferentialChangeHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialChangeType' => 'Phobject', 'DifferentialChangesSinceLastUpdateField' => 'DifferentialCustomField', 'DifferentialChangeset' => array( 'DifferentialDAO', 'PhabricatorPolicyInterface', ), 'DifferentialChangesetDetailView' => 'AphrontView', 'DifferentialChangesetFileTreeSideNavBuilder' => 'Phobject', 'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetListView' => 'AphrontView', 'DifferentialChangesetOneUpMailRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetOneUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetParser' => 'Phobject', 'DifferentialChangesetParserTestCase' => 'PhabricatorTestCase', 'DifferentialChangesetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialChangesetRenderer' => 'Phobject', 'DifferentialChangesetTestRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetViewController' => 'DifferentialController', - 'DifferentialChildRevisionsField' => 'DifferentialCustomField', 'DifferentialCloseConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCommentPreviewController' => 'DifferentialController', 'DifferentialCommentSaveController' => 'DifferentialController', + 'DifferentialCommitMessageCustomField' => 'DifferentialCommitMessageField', + 'DifferentialCommitMessageField' => 'Phobject', 'DifferentialCommitMessageParser' => 'Phobject', 'DifferentialCommitMessageParserTestCase' => 'PhabricatorTestCase', 'DifferentialCommitsField' => 'DifferentialCustomField', 'DifferentialConduitAPIMethod' => 'ConduitAPIMethod', - 'DifferentialConflictsField' => 'DifferentialCustomField', + 'DifferentialConflictsCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialController' => 'PhabricatorController', 'DifferentialCoreCustomField' => 'DifferentialCustomField', 'DifferentialCreateCommentConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateInlineConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateMailReceiver' => 'PhabricatorMailReceiver', 'DifferentialCreateRawDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCustomField' => 'PhabricatorCustomField', 'DifferentialCustomFieldDependsOnParser' => 'PhabricatorCustomFieldMonogramParser', 'DifferentialCustomFieldDependsOnParserTestCase' => 'PhabricatorTestCase', 'DifferentialCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'DifferentialCustomFieldRevertsParser' => 'PhabricatorCustomFieldMonogramParser', 'DifferentialCustomFieldRevertsParserTestCase' => 'PhabricatorTestCase', 'DifferentialCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'DifferentialCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'DifferentialDAO' => 'PhabricatorLiskDAO', 'DifferentialDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DifferentialDiff' => array( 'DifferentialDAO', 'PhabricatorPolicyInterface', 'HarbormasterBuildableInterface', 'HarbormasterCircleCIBuildableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'DifferentialDiffAffectedFilesHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffAuthorHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffAuthorProjectsHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffContentAddedHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffContentHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffContentRemovedHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffCreateController' => 'DifferentialController', 'DifferentialDiffEditor' => 'PhabricatorApplicationTransactionEditor', 'DifferentialDiffExtractionEngine' => 'Phobject', 'DifferentialDiffHeraldField' => 'HeraldField', 'DifferentialDiffHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', 'DifferentialDiffPHIDType' => 'PhabricatorPHIDType', 'DifferentialDiffProperty' => 'DifferentialDAO', 'DifferentialDiffQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialDiffRepositoryHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffRepositoryProjectsHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffTestCase' => 'PhutilTestCase', 'DifferentialDiffTransaction' => 'PhabricatorApplicationTransaction', 'DifferentialDiffTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DifferentialDraft' => 'DifferentialDAO', - 'DifferentialEditPolicyField' => 'DifferentialCoreCustomField', 'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialFieldParseException' => 'Exception', 'DifferentialFieldValidationException' => 'Exception', 'DifferentialFindConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetAllDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetCommitPathsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRawDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRevisionCommentsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetWorkingCopy' => 'Phobject', 'DifferentialGitHubLandingStrategy' => 'DifferentialLandingStrategy', - 'DifferentialGitSVNIDField' => 'DifferentialCustomField', + 'DifferentialGitSVNIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialHarbormasterField' => 'DifferentialCustomField', 'DifferentialHiddenComment' => 'DifferentialDAO', 'DifferentialHostField' => 'DifferentialCustomField', 'DifferentialHostedGitLandingStrategy' => 'DifferentialLandingStrategy', 'DifferentialHostedMercurialLandingStrategy' => 'DifferentialLandingStrategy', 'DifferentialHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DifferentialHunk' => array( 'DifferentialDAO', 'PhabricatorPolicyInterface', ), 'DifferentialHunkParser' => 'Phobject', 'DifferentialHunkParserTestCase' => 'PhabricatorTestCase', 'DifferentialHunkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialHunkTestCase' => 'PhutilTestCase', 'DifferentialInlineComment' => array( 'Phobject', 'PhabricatorInlineCommentInterface', ), 'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController', 'DifferentialInlineCommentMailView' => 'DifferentialMailView', 'DifferentialInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery', + 'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField', 'DifferentialLandingActionMenuEventListener' => 'PhabricatorEventListener', 'DifferentialLandingStrategy' => 'Phobject', 'DifferentialLegacyHunk' => 'DifferentialHunk', 'DifferentialLineAdjustmentMap' => 'Phobject', 'DifferentialLintField' => 'DifferentialHarbormasterField', 'DifferentialLintStatus' => 'Phobject', 'DifferentialLocalCommitsView' => 'AphrontView', 'DifferentialMailView' => 'Phobject', 'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField', 'DifferentialModernHunk' => 'DifferentialHunk', - 'DifferentialNextStepField' => 'DifferentialCustomField', - 'DifferentialParentRevisionsField' => 'DifferentialCustomField', 'DifferentialParseCacheGarbageCollector' => 'PhabricatorGarbageCollector', 'DifferentialParseCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialParseRenderTestCase' => 'PhabricatorTestCase', 'DifferentialPathField' => 'DifferentialCustomField', 'DifferentialProjectReviewersField' => 'DifferentialCustomField', - 'DifferentialProjectsField' => 'DifferentialCoreCustomField', 'DifferentialQueryConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialQueryDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialRawDiffRenderer' => 'Phobject', 'DifferentialReleephRequestFieldSpecification' => 'Phobject', 'DifferentialRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DifferentialReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'DifferentialRepositoryDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialRepositoryField' => 'DifferentialCoreCustomField', 'DifferentialRepositoryLookup' => 'Phobject', 'DifferentialRequiredSignaturesField' => 'DifferentialCoreCustomField', 'DifferentialResponsibleDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialResponsibleUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialResponsibleViewerFunctionDatasource' => 'PhabricatorTypeaheadDatasource', + 'DifferentialRevertPlanCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialRevertPlanField' => 'DifferentialStoredCustomField', - 'DifferentialReviewedByField' => 'DifferentialCoreCustomField', - 'DifferentialReviewer' => 'Phobject', + 'DifferentialReviewedByCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialReviewerForRevisionEdgeType' => 'PhabricatorEdgeType', + 'DifferentialReviewerProxy' => 'Phobject', 'DifferentialReviewerStatus' => 'Phobject', 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddSelfHeraldAction' => 'DifferentialReviewersHeraldAction', + 'DifferentialReviewersCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialReviewersField' => 'DifferentialCoreCustomField', 'DifferentialReviewersHeraldAction' => 'HeraldAction', 'DifferentialReviewersView' => 'AphrontView', 'DifferentialRevision' => array( 'DifferentialDAO', 'PhabricatorTokenReceiverInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorFlaggableInterface', 'PhrequentTrackableInterface', 'HarbormasterBuildableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorMentionableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorProjectInterface', 'PhabricatorFulltextInterface', 'PhabricatorConduitResultInterface', ), 'DifferentialRevisionAffectedFilesHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionAuthorHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionAuthorProjectsHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionCloseDetailsController' => 'DifferentialController', 'DifferentialRevisionContentAddedHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionContentHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionContentRemovedHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionControlSystem' => 'Phobject', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType', + 'DifferentialRevisionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DifferentialRevisionEditController' => 'DifferentialController', + 'DifferentialRevisionEditEngine' => 'PhabricatorEditEngine', 'DifferentialRevisionFulltextEngine' => 'PhabricatorFulltextEngine', 'DifferentialRevisionGraph' => 'PhabricatorObjectGraph', 'DifferentialRevisionHasChildRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHasCommitEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionHasCommitRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHasParentRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHasReviewerEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionHasTaskEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionHasTaskRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHeraldField' => 'HeraldField', 'DifferentialRevisionHeraldFieldGroup' => 'HeraldFieldGroup', - 'DifferentialRevisionIDField' => 'DifferentialCustomField', + 'DifferentialRevisionIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialRevisionLandController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListView' => 'AphrontView', 'DifferentialRevisionMailReceiver' => 'PhabricatorObjectMailReceiver', 'DifferentialRevisionOperationController' => 'DifferentialController', 'DifferentialRevisionPHIDType' => 'PhabricatorPHIDType', 'DifferentialRevisionPackageHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionPackageOwnerHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialRevisionRelationship' => 'PhabricatorObjectRelationship', 'DifferentialRevisionRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'DifferentialRevisionRepositoryHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionRepositoryProjectsHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionRepositoryTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionRequiredActionResultBucket' => 'DifferentialRevisionResultBucket', 'DifferentialRevisionResultBucket' => 'PhabricatorSearchResultBucket', 'DifferentialRevisionReviewersHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionReviewersTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DifferentialRevisionStatus' => 'Phobject', 'DifferentialRevisionSummaryHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionSummaryTransaction' => 'DifferentialRevisionTransactionType', + 'DifferentialRevisionTestPlanTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionTitleHeraldField' => 'DifferentialRevisionHeraldField', + 'DifferentialRevisionTitleTransaction' => 'DifferentialRevisionTransactionType', + 'DifferentialRevisionTransactionType' => 'PhabricatorModularTransactionType', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DifferentialSetDiffPropertyConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialStoredCustomField' => 'DifferentialCustomField', - 'DifferentialSubscribersField' => 'DifferentialCoreCustomField', + 'DifferentialSubscribersCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialSummaryCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialSummaryField' => 'DifferentialCoreCustomField', + 'DifferentialTagsCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTasksCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTestPlanCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanField' => 'DifferentialCoreCustomField', - 'DifferentialTitleField' => 'DifferentialCoreCustomField', - 'DifferentialTransaction' => 'PhabricatorApplicationTransaction', + 'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTransaction' => 'PhabricatorModularTransaction', 'DifferentialTransactionComment' => 'PhabricatorApplicationTransactionComment', 'DifferentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'DifferentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DifferentialTransactionView' => 'PhabricatorApplicationTransactionView', 'DifferentialUnitField' => 'DifferentialCustomField', 'DifferentialUnitStatus' => 'Phobject', 'DifferentialUnitTestResult' => 'Phobject', 'DifferentialUpdateRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', - 'DifferentialViewPolicyField' => 'DifferentialCoreCustomField', 'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionAuditorFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction', 'DiffusionAuditorsAddSelfHeraldAction' => 'DiffusionAuditorsHeraldAction', 'DiffusionAuditorsHeraldAction' => 'HeraldAction', 'DiffusionBlameConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBlameQuery' => 'DiffusionQuery', 'DiffusionBlockHeraldAction' => 'HeraldAction', 'DiffusionBranchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBranchTableController' => 'DiffusionController', 'DiffusionBranchTableView' => 'DiffusionView', 'DiffusionBrowseController' => 'DiffusionController', 'DiffusionBrowseQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBrowseResultSet' => 'Phobject', 'DiffusionBrowseTableView' => 'DiffusionView', 'DiffusionCacheEngineExtension' => 'PhabricatorCacheEngineExtension', 'DiffusionCachedResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionChangeController' => 'DiffusionController', 'DiffusionChangeHeraldFieldGroup' => 'HeraldFieldGroup', 'DiffusionCloneURIView' => 'AphrontView', 'DiffusionCommandEngine' => 'Phobject', 'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase', 'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitAuthorHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitBranchesController' => 'DiffusionController', 'DiffusionCommitBranchesHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitCommitterHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitController' => 'DiffusionController', 'DiffusionCommitDiffContentAddedHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDiffContentHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDiffContentRemovedHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDiffEnormousHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitEditController' => 'DiffusionController', 'DiffusionCommitFulltextEngine' => 'PhabricatorFulltextEngine', 'DiffusionCommitHasRevisionEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitHasRevisionRelationship' => 'DiffusionCommitRelationship', 'DiffusionCommitHasTaskEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitHasTaskRelationship' => 'DiffusionCommitRelationship', 'DiffusionCommitHash' => 'Phobject', 'DiffusionCommitHeraldField' => 'HeraldField', 'DiffusionCommitHeraldFieldGroup' => 'HeraldFieldGroup', 'DiffusionCommitHintQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DiffusionCommitHookEngine' => 'Phobject', 'DiffusionCommitHookRejectException' => 'Exception', 'DiffusionCommitMergeHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitMessageHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitPackageAuditHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitPackageHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitPackageOwnerHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitParentsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionCommitQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DiffusionCommitRef' => 'Phobject', 'DiffusionCommitRelationship' => 'PhabricatorObjectRelationship', 'DiffusionCommitRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'DiffusionCommitRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DiffusionCommitRemarkupRuleTestCase' => 'PhabricatorTestCase', 'DiffusionCommitRepositoryHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRepositoryProjectsHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevertedByCommitEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitRevertsCommitEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitReviewerHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionAcceptedHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionReviewersHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionSubscribersHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitTagsController' => 'DiffusionController', 'DiffusionCompareController' => 'DiffusionController', 'DiffusionConduitAPIMethod' => 'ConduitAPIMethod', 'DiffusionController' => 'PhabricatorController', 'DiffusionCreateCommentConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionCreateRepositoriesCapability' => 'PhabricatorPolicyCapability', 'DiffusionDaemonLockException' => 'Exception', 'DiffusionDefaultEditCapability' => 'PhabricatorPolicyCapability', 'DiffusionDefaultPushCapability' => 'PhabricatorPolicyCapability', 'DiffusionDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DiffusionDiffController' => 'DiffusionController', 'DiffusionDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', 'DiffusionDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DiffusionEmptyResultView' => 'DiffusionView', 'DiffusionExistsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionExternalController' => 'DiffusionController', 'DiffusionExternalSymbolQuery' => 'Phobject', 'DiffusionExternalSymbolsSource' => 'Phobject', 'DiffusionFileContentQuery' => 'DiffusionFileFutureQuery', 'DiffusionFileContentQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionFileFutureQuery' => 'DiffusionQuery', 'DiffusionFindSymbolsConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionGetLintMessagesConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionGetRecentCommitsByPathConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionGitBlameQuery' => 'DiffusionBlameQuery', 'DiffusionGitBranch' => 'Phobject', 'DiffusionGitBranchTestCase' => 'PhabricatorTestCase', 'DiffusionGitCommandEngine' => 'DiffusionCommandEngine', 'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionGitLFSAuthenticateWorkflow' => 'DiffusionGitSSHWorkflow', 'DiffusionGitLFSResponse' => 'AphrontResponse', 'DiffusionGitLFSTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionGitReceivePackSSHWorkflow' => 'DiffusionGitSSHWorkflow', 'DiffusionGitRequest' => 'DiffusionRequest', 'DiffusionGitResponse' => 'AphrontResponse', 'DiffusionGitSSHWorkflow' => array( 'DiffusionSSHWorkflow', 'DiffusionRepositoryClusterEngineLogInterface', ), 'DiffusionGitUploadPackSSHWorkflow' => 'DiffusionGitSSHWorkflow', 'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionHistoryTableView' => 'DiffusionView', 'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', 'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionLastModifiedController' => 'DiffusionController', 'DiffusionLastModifiedQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionLintController' => 'DiffusionController', 'DiffusionLintCountQuery' => 'PhabricatorQuery', 'DiffusionLintSaveRunner' => 'Phobject', 'DiffusionLocalRepositoryFilter' => 'Phobject', 'DiffusionLookSoonConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionLowLevelCommitFieldsQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelCommitQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelGitRefQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelMercurialBranchesQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelMercurialPathsQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelMercurialPathsQueryTests' => 'PhabricatorTestCase', 'DiffusionLowLevelParentsQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelQuery' => 'Phobject', 'DiffusionLowLevelResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionMercurialBlameQuery' => 'DiffusionBlameQuery', 'DiffusionMercurialCommandEngine' => 'DiffusionCommandEngine', 'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionMercurialRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionMercurialRequest' => 'DiffusionRequest', 'DiffusionMercurialResponse' => 'AphrontResponse', 'DiffusionMercurialSSHWorkflow' => 'DiffusionSSHWorkflow', 'DiffusionMercurialServeSSHWorkflow' => 'DiffusionMercurialSSHWorkflow', 'DiffusionMercurialWireClientSSHProtocolChannel' => 'PhutilProtocolChannel', 'DiffusionMercurialWireProtocol' => 'Phobject', 'DiffusionMercurialWireProtocolTests' => 'PhabricatorTestCase', 'DiffusionMercurialWireSSHTestCase' => 'PhabricatorTestCase', 'DiffusionMergedCommitsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionPathChange' => 'Phobject', 'DiffusionPathChangeQuery' => 'Phobject', 'DiffusionPathCompleteController' => 'DiffusionController', 'DiffusionPathIDQuery' => 'Phobject', 'DiffusionPathQuery' => 'Phobject', 'DiffusionPathQueryTestCase' => 'PhabricatorTestCase', 'DiffusionPathTreeController' => 'DiffusionController', 'DiffusionPathValidateController' => 'DiffusionController', 'DiffusionPhpExternalSymbolsSource' => 'DiffusionExternalSymbolsSource', 'DiffusionPreCommitContentAffectedFilesHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAuthorHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAuthorRawHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentBranchesHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentCommitterHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentCommitterRawHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffContentAddedHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffContentHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffContentRemovedHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffEnormousHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentHeraldField' => 'HeraldField', 'DiffusionPreCommitContentMergeHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentMessageHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPusherHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPusherIsCommitterHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPusherProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRepositoryHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRepositoryProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRevisionAcceptedHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRevisionHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRevisionReviewersHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRevisionSubscribersHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitRefChangeHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPreCommitRefHeraldField' => 'HeraldField', 'DiffusionPreCommitRefHeraldFieldGroup' => 'HeraldFieldGroup', 'DiffusionPreCommitRefNameHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPreCommitRefPusherHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPreCommitRefPusherProjectsHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPreCommitRefRepositoryHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPreCommitRefRepositoryProjectsHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPreCommitRefTypeHeraldField' => 'DiffusionPreCommitRefHeraldField', 'DiffusionPullEventGarbageCollector' => 'PhabricatorGarbageCollector', 'DiffusionPushCapability' => 'PhabricatorPolicyCapability', 'DiffusionPushEventViewController' => 'DiffusionPushLogController', 'DiffusionPushLogController' => 'DiffusionController', 'DiffusionPushLogListController' => 'DiffusionPushLogController', 'DiffusionPushLogListView' => 'AphrontView', 'DiffusionPythonExternalSymbolsSource' => 'DiffusionExternalSymbolsSource', 'DiffusionQuery' => 'PhabricatorQuery', 'DiffusionQueryCommitsConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionQueryConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionQueryPathsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionRawDiffQuery' => 'DiffusionFileFutureQuery', 'DiffusionRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionReadmeView' => 'DiffusionView', 'DiffusionRefDatasource' => 'PhabricatorTypeaheadDatasource', 'DiffusionRefNotFoundException' => 'Exception', 'DiffusionRefTableController' => 'DiffusionController', 'DiffusionRefsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionRenameHistoryQuery' => 'Phobject', 'DiffusionRepositoryActionsManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryAutomationManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryBasicsManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryBranchesManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryByIDRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DiffusionRepositoryClusterEngine' => 'Phobject', 'DiffusionRepositoryController' => 'DiffusionController', 'DiffusionRepositoryDatasource' => 'PhabricatorTypeaheadDatasource', 'DiffusionRepositoryDefaultController' => 'DiffusionController', 'DiffusionRepositoryDocumentationManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryEditActivateController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DiffusionRepositoryEditController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditDangerousController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditDeleteController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditEngine' => 'PhabricatorEditEngine', 'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryListController' => 'DiffusionController', 'DiffusionRepositoryManageController' => 'DiffusionController', 'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryManagementPanel' => 'Phobject', 'DiffusionRepositoryPath' => 'Phobject', 'DiffusionRepositoryPoliciesManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryRef' => 'Phobject', 'DiffusionRepositoryRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DiffusionRepositorySearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DiffusionRepositoryStagingManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryStatusManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryStorageManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositorySubversionManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositorySymbolsManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryTag' => 'Phobject', 'DiffusionRepositoryTestAutomationController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryURICredentialController' => 'DiffusionController', 'DiffusionRepositoryURIDisableController' => 'DiffusionController', 'DiffusionRepositoryURIEditController' => 'DiffusionController', 'DiffusionRepositoryURIViewController' => 'DiffusionController', 'DiffusionRepositoryURIsIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'DiffusionRepositoryURIsManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryURIsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'DiffusionRequest' => 'Phobject', 'DiffusionResolveRefsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionResolveUserQuery' => 'Phobject', 'DiffusionSSHWorkflow' => 'PhabricatorSSHWorkflow', 'DiffusionSearchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionServeController' => 'DiffusionController', 'DiffusionSetPasswordSettingsPanel' => 'PhabricatorSettingsPanel', 'DiffusionSetupException' => 'Exception', 'DiffusionSubversionCommandEngine' => 'DiffusionCommandEngine', 'DiffusionSubversionSSHWorkflow' => 'DiffusionSSHWorkflow', 'DiffusionSubversionServeSSHWorkflow' => 'DiffusionSubversionSSHWorkflow', 'DiffusionSubversionWireProtocol' => 'Phobject', 'DiffusionSubversionWireProtocolTestCase' => 'PhabricatorTestCase', 'DiffusionSvnBlameQuery' => 'DiffusionBlameQuery', 'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionSvnRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionSvnRequest' => 'DiffusionRequest', 'DiffusionSymbolController' => 'DiffusionController', 'DiffusionSymbolDatasource' => 'PhabricatorTypeaheadDatasource', 'DiffusionSymbolQuery' => 'PhabricatorOffsetPagedQuery', 'DiffusionTagListController' => 'DiffusionController', 'DiffusionTagListView' => 'DiffusionView', 'DiffusionTaggedRepositoriesFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionTagsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionURIEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DiffusionURIEditEngine' => 'PhabricatorEditEngine', 'DiffusionURIEditor' => 'PhabricatorApplicationTransactionEditor', 'DiffusionURITestCase' => 'PhutilTestCase', 'DiffusionUpdateCoverageConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionView' => 'AphrontView', 'DivinerArticleAtomizer' => 'DivinerAtomizer', 'DivinerAtom' => 'Phobject', 'DivinerAtomCache' => 'DivinerDiskCache', 'DivinerAtomController' => 'DivinerController', 'DivinerAtomListController' => 'DivinerController', 'DivinerAtomPHIDType' => 'PhabricatorPHIDType', 'DivinerAtomQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DivinerAtomRef' => 'Phobject', 'DivinerAtomSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DivinerAtomizeWorkflow' => 'DivinerWorkflow', 'DivinerAtomizer' => 'Phobject', 'DivinerBookController' => 'DivinerController', 'DivinerBookDatasource' => 'PhabricatorTypeaheadDatasource', 'DivinerBookEditController' => 'DivinerController', 'DivinerBookItemView' => 'AphrontTagView', 'DivinerBookPHIDType' => 'PhabricatorPHIDType', 'DivinerBookQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DivinerController' => 'PhabricatorController', 'DivinerDAO' => 'PhabricatorLiskDAO', 'DivinerDefaultEditCapability' => 'PhabricatorPolicyCapability', 'DivinerDefaultRenderer' => 'DivinerRenderer', 'DivinerDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DivinerDiskCache' => 'Phobject', 'DivinerFileAtomizer' => 'DivinerAtomizer', 'DivinerFindController' => 'DivinerController', 'DivinerGenerateWorkflow' => 'DivinerWorkflow', 'DivinerLiveAtom' => 'DivinerDAO', 'DivinerLiveBook' => array( 'DivinerDAO', 'PhabricatorPolicyInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFulltextInterface', ), 'DivinerLiveBookEditor' => 'PhabricatorApplicationTransactionEditor', 'DivinerLiveBookFulltextEngine' => 'PhabricatorFulltextEngine', 'DivinerLiveBookTransaction' => 'PhabricatorApplicationTransaction', 'DivinerLiveBookTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DivinerLivePublisher' => 'DivinerPublisher', 'DivinerLiveSymbol' => array( 'DivinerDAO', 'PhabricatorPolicyInterface', 'PhabricatorMarkupInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', ), 'DivinerLiveSymbolFulltextEngine' => 'PhabricatorFulltextEngine', 'DivinerMainController' => 'DivinerController', 'DivinerPHPAtomizer' => 'DivinerAtomizer', 'DivinerParameterTableView' => 'AphrontTagView', 'DivinerPublishCache' => 'DivinerDiskCache', 'DivinerPublisher' => 'Phobject', 'DivinerRenderer' => 'Phobject', 'DivinerReturnTableView' => 'AphrontTagView', 'DivinerSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DivinerSectionView' => 'AphrontTagView', 'DivinerStaticPublisher' => 'DivinerPublisher', 'DivinerSymbolRemarkupRule' => 'PhutilRemarkupRule', 'DivinerWorkflow' => 'PhabricatorManagementWorkflow', 'DoorkeeperAsanaFeedWorker' => 'DoorkeeperFeedWorker', 'DoorkeeperAsanaRemarkupRule' => 'DoorkeeperRemarkupRule', 'DoorkeeperBridge' => 'Phobject', 'DoorkeeperBridgeAsana' => 'DoorkeeperBridge', 'DoorkeeperBridgeGitHub' => 'DoorkeeperBridge', 'DoorkeeperBridgeGitHubIssue' => 'DoorkeeperBridgeGitHub', 'DoorkeeperBridgeGitHubUser' => 'DoorkeeperBridgeGitHub', 'DoorkeeperBridgeJIRA' => 'DoorkeeperBridge', 'DoorkeeperBridgeJIRATestCase' => 'PhabricatorTestCase', 'DoorkeeperBridgedObjectCurtainExtension' => 'PHUICurtainExtension', 'DoorkeeperDAO' => 'PhabricatorLiskDAO', 'DoorkeeperExternalObject' => array( 'DoorkeeperDAO', 'PhabricatorPolicyInterface', ), 'DoorkeeperExternalObjectPHIDType' => 'PhabricatorPHIDType', 'DoorkeeperExternalObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DoorkeeperFeedStoryPublisher' => 'Phobject', 'DoorkeeperFeedWorker' => 'FeedPushWorker', 'DoorkeeperImportEngine' => 'Phobject', 'DoorkeeperJIRAFeedWorker' => 'DoorkeeperFeedWorker', 'DoorkeeperJIRARemarkupRule' => 'DoorkeeperRemarkupRule', 'DoorkeeperMissingLinkException' => 'Exception', 'DoorkeeperObjectRef' => 'Phobject', 'DoorkeeperRemarkupRule' => 'PhutilRemarkupRule', 'DoorkeeperSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DoorkeeperTagView' => 'AphrontView', 'DoorkeeperTagsController' => 'PhabricatorController', 'DrydockAlmanacServiceHostBlueprintImplementation' => 'DrydockBlueprintImplementation', 'DrydockApacheWebrootInterface' => 'DrydockWebrootInterface', 'DrydockAuthorization' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', 'PhabricatorConduitResultInterface', ), 'DrydockAuthorizationAuthorizeController' => 'DrydockController', 'DrydockAuthorizationListController' => 'DrydockController', 'DrydockAuthorizationListView' => 'AphrontView', 'DrydockAuthorizationPHIDType' => 'PhabricatorPHIDType', 'DrydockAuthorizationQuery' => 'DrydockQuery', 'DrydockAuthorizationSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DrydockAuthorizationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockAuthorizationViewController' => 'DrydockController', 'DrydockBlueprint' => array( 'DrydockDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorNgramsInterface', 'PhabricatorProjectInterface', 'PhabricatorConduitResultInterface', ), 'DrydockBlueprintController' => 'DrydockController', 'DrydockBlueprintCoreCustomField' => array( 'DrydockBlueprintCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'DrydockBlueprintCustomField' => 'PhabricatorCustomField', 'DrydockBlueprintDatasource' => 'PhabricatorTypeaheadDatasource', 'DrydockBlueprintDisableController' => 'DrydockBlueprintController', 'DrydockBlueprintEditController' => 'DrydockBlueprintController', 'DrydockBlueprintEditEngine' => 'PhabricatorEditEngine', 'DrydockBlueprintEditor' => 'PhabricatorApplicationTransactionEditor', 'DrydockBlueprintImplementation' => 'Phobject', 'DrydockBlueprintImplementationTestCase' => 'PhabricatorTestCase', 'DrydockBlueprintListController' => 'DrydockBlueprintController', 'DrydockBlueprintNameNgrams' => 'PhabricatorSearchNgrams', 'DrydockBlueprintPHIDType' => 'PhabricatorPHIDType', 'DrydockBlueprintQuery' => 'DrydockQuery', 'DrydockBlueprintSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DrydockBlueprintSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockBlueprintTransaction' => 'PhabricatorApplicationTransaction', 'DrydockBlueprintTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DrydockBlueprintViewController' => 'DrydockBlueprintController', 'DrydockCommand' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), 'DrydockCommandError' => 'Phobject', 'DrydockCommandInterface' => 'DrydockInterface', 'DrydockCommandQuery' => 'DrydockQuery', 'DrydockConsoleController' => 'DrydockController', 'DrydockConstants' => 'Phobject', 'DrydockController' => 'PhabricatorController', 'DrydockCreateBlueprintsCapability' => 'PhabricatorPolicyCapability', 'DrydockDAO' => 'PhabricatorLiskDAO', 'DrydockDefaultEditCapability' => 'PhabricatorPolicyCapability', 'DrydockDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DrydockFilesystemInterface' => 'DrydockInterface', 'DrydockInterface' => 'Phobject', 'DrydockLandRepositoryOperation' => 'DrydockRepositoryOperationType', 'DrydockLease' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), 'DrydockLeaseAcquiredLogType' => 'DrydockLogType', 'DrydockLeaseActivatedLogType' => 'DrydockLogType', 'DrydockLeaseActivationFailureLogType' => 'DrydockLogType', 'DrydockLeaseActivationYieldLogType' => 'DrydockLogType', 'DrydockLeaseController' => 'DrydockController', 'DrydockLeaseDatasource' => 'PhabricatorTypeaheadDatasource', 'DrydockLeaseDestroyedLogType' => 'DrydockLogType', 'DrydockLeaseListController' => 'DrydockLeaseController', 'DrydockLeaseListView' => 'AphrontView', 'DrydockLeaseNoAuthorizationsLogType' => 'DrydockLogType', 'DrydockLeaseNoBlueprintsLogType' => 'DrydockLogType', 'DrydockLeasePHIDType' => 'PhabricatorPHIDType', 'DrydockLeaseQuery' => 'DrydockQuery', 'DrydockLeaseQueuedLogType' => 'DrydockLogType', 'DrydockLeaseReclaimLogType' => 'DrydockLogType', 'DrydockLeaseReleaseController' => 'DrydockLeaseController', 'DrydockLeaseReleasedLogType' => 'DrydockLogType', 'DrydockLeaseSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockLeaseStatus' => 'DrydockConstants', 'DrydockLeaseUpdateWorker' => 'DrydockWorker', 'DrydockLeaseViewController' => 'DrydockLeaseController', 'DrydockLeaseWaitingForResourcesLogType' => 'DrydockLogType', 'DrydockLog' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), 'DrydockLogController' => 'DrydockController', 'DrydockLogGarbageCollector' => 'PhabricatorGarbageCollector', 'DrydockLogListController' => 'DrydockLogController', 'DrydockLogListView' => 'AphrontView', 'DrydockLogQuery' => 'DrydockQuery', 'DrydockLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockLogType' => 'Phobject', 'DrydockManagementCommandWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReclaimWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReleaseLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReleaseResourceWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementUpdateLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementUpdateResourceWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementWorkflow' => 'PhabricatorManagementWorkflow', 'DrydockObjectAuthorizationView' => 'AphrontView', 'DrydockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DrydockRepositoryOperation' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), 'DrydockRepositoryOperationController' => 'DrydockController', 'DrydockRepositoryOperationDismissController' => 'DrydockRepositoryOperationController', 'DrydockRepositoryOperationListController' => 'DrydockRepositoryOperationController', 'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType', 'DrydockRepositoryOperationQuery' => 'DrydockQuery', 'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockRepositoryOperationStatusController' => 'DrydockRepositoryOperationController', 'DrydockRepositoryOperationStatusView' => 'AphrontView', 'DrydockRepositoryOperationType' => 'Phobject', 'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker', 'DrydockRepositoryOperationViewController' => 'DrydockRepositoryOperationController', 'DrydockResource' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), 'DrydockResourceActivationFailureLogType' => 'DrydockLogType', 'DrydockResourceActivationYieldLogType' => 'DrydockLogType', 'DrydockResourceController' => 'DrydockController', 'DrydockResourceDatasource' => 'PhabricatorTypeaheadDatasource', 'DrydockResourceListController' => 'DrydockResourceController', 'DrydockResourceListView' => 'AphrontView', 'DrydockResourcePHIDType' => 'PhabricatorPHIDType', 'DrydockResourceQuery' => 'DrydockQuery', 'DrydockResourceReclaimLogType' => 'DrydockLogType', 'DrydockResourceReleaseController' => 'DrydockResourceController', 'DrydockResourceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockResourceStatus' => 'DrydockConstants', 'DrydockResourceUpdateWorker' => 'DrydockWorker', 'DrydockResourceViewController' => 'DrydockResourceController', 'DrydockSFTPFilesystemInterface' => 'DrydockFilesystemInterface', 'DrydockSSHCommandInterface' => 'DrydockCommandInterface', 'DrydockSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DrydockSlotLock' => 'DrydockDAO', 'DrydockSlotLockException' => 'Exception', 'DrydockSlotLockFailureLogType' => 'DrydockLogType', 'DrydockTestRepositoryOperation' => 'DrydockRepositoryOperationType', 'DrydockWebrootInterface' => 'DrydockInterface', 'DrydockWorker' => 'PhabricatorWorker', 'DrydockWorkingCopyBlueprintImplementation' => 'DrydockBlueprintImplementation', 'FeedConduitAPIMethod' => 'ConduitAPIMethod', 'FeedPublishConduitAPIMethod' => 'FeedConduitAPIMethod', 'FeedPublisherHTTPWorker' => 'FeedPushWorker', 'FeedPublisherWorker' => 'FeedPushWorker', 'FeedPushWorker' => 'PhabricatorWorker', 'FeedQueryConduitAPIMethod' => 'FeedConduitAPIMethod', 'FeedStoryNotificationGarbageCollector' => 'PhabricatorGarbageCollector', 'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod', 'FileConduitAPIMethod' => 'ConduitAPIMethod', 'FileCreateMailReceiver' => 'PhabricatorMailReceiver', 'FileDownloadConduitAPIMethod' => 'FileConduitAPIMethod', 'FileInfoConduitAPIMethod' => 'FileConduitAPIMethod', 'FileMailReceiver' => 'PhabricatorObjectMailReceiver', 'FileQueryChunksConduitAPIMethod' => 'FileConduitAPIMethod', 'FileReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'FileTypeIcon' => 'Phobject', 'FileUploadChunkConduitAPIMethod' => 'FileConduitAPIMethod', 'FileUploadConduitAPIMethod' => 'FileConduitAPIMethod', 'FileUploadHashConduitAPIMethod' => 'FileConduitAPIMethod', 'FilesDefaultViewCapability' => 'PhabricatorPolicyCapability', 'FlagConduitAPIMethod' => 'ConduitAPIMethod', 'FlagDeleteConduitAPIMethod' => 'FlagConduitAPIMethod', 'FlagEditConduitAPIMethod' => 'FlagConduitAPIMethod', 'FlagQueryConduitAPIMethod' => 'FlagConduitAPIMethod', 'FundBacker' => array( 'FundDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'FundBackerCart' => 'PhortuneCartImplementation', 'FundBackerEditor' => 'PhabricatorApplicationTransactionEditor', 'FundBackerListController' => 'FundController', 'FundBackerPHIDType' => 'PhabricatorPHIDType', 'FundBackerProduct' => 'PhortuneProductImplementation', 'FundBackerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'FundBackerSearchEngine' => 'PhabricatorApplicationSearchEngine', 'FundBackerTransaction' => 'PhabricatorApplicationTransaction', 'FundBackerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'FundController' => 'PhabricatorController', 'FundCreateInitiativesCapability' => 'PhabricatorPolicyCapability', 'FundDAO' => 'PhabricatorLiskDAO', 'FundDefaultViewCapability' => 'PhabricatorPolicyCapability', 'FundInitiative' => array( 'FundDAO', 'PhabricatorPolicyInterface', 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorMentionableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', ), 'FundInitiativeBackController' => 'FundController', 'FundInitiativeCloseController' => 'FundController', 'FundInitiativeCommentController' => 'FundController', 'FundInitiativeEditController' => 'FundController', 'FundInitiativeEditor' => 'PhabricatorApplicationTransactionEditor', 'FundInitiativeFulltextEngine' => 'PhabricatorFulltextEngine', 'FundInitiativeListController' => 'FundController', 'FundInitiativePHIDType' => 'PhabricatorPHIDType', 'FundInitiativeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'FundInitiativeRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'FundInitiativeReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'FundInitiativeSearchEngine' => 'PhabricatorApplicationSearchEngine', 'FundInitiativeTransaction' => 'PhabricatorApplicationTransaction', 'FundInitiativeTransactionComment' => 'PhabricatorApplicationTransactionComment', 'FundInitiativeTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'FundInitiativeViewController' => 'FundController', 'FundSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HarbormasterArcLintBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterArcUnitBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterArtifact' => 'Phobject', 'HarbormasterAutotargetsTestCase' => 'PhabricatorTestCase', 'HarbormasterBuild' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorConduitResultInterface', ), 'HarbormasterBuildAbortedException' => 'Exception', 'HarbormasterBuildActionController' => 'HarbormasterController', 'HarbormasterBuildArcanistAutoplan' => 'HarbormasterBuildAutoplan', 'HarbormasterBuildArtifact' => array( 'HarbormasterDAO', 'PhabricatorPolicyInterface', ), 'HarbormasterBuildArtifactPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildArtifactQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildAutoplan' => 'Phobject', 'HarbormasterBuildCommand' => 'HarbormasterDAO', 'HarbormasterBuildDependencyDatasource' => 'PhabricatorTypeaheadDatasource', 'HarbormasterBuildEngine' => 'Phobject', 'HarbormasterBuildFailureException' => 'Exception', 'HarbormasterBuildGraph' => 'AbstractDirectedGraph', 'HarbormasterBuildInitiatorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'HarbormasterBuildLintMessage' => 'HarbormasterDAO', 'HarbormasterBuildListController' => 'HarbormasterController', 'HarbormasterBuildLog' => array( 'HarbormasterDAO', 'PhabricatorPolicyInterface', ), 'HarbormasterBuildLogChunk' => 'HarbormasterDAO', 'HarbormasterBuildLogChunkIterator' => 'PhutilBufferedIterator', 'HarbormasterBuildLogPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildMessage' => array( 'HarbormasterDAO', 'PhabricatorPolicyInterface', ), 'HarbormasterBuildMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildPlan' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorNgramsInterface', 'PhabricatorProjectInterface', ), 'HarbormasterBuildPlanDatasource' => 'PhabricatorTypeaheadDatasource', 'HarbormasterBuildPlanDefaultEditCapability' => 'PhabricatorPolicyCapability', 'HarbormasterBuildPlanDefaultViewCapability' => 'PhabricatorPolicyCapability', 'HarbormasterBuildPlanEditEngine' => 'PhabricatorEditEngine', 'HarbormasterBuildPlanEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildPlanNameNgrams' => 'PhabricatorSearchNgrams', 'HarbormasterBuildPlanPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildPlanQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildPlanSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HarbormasterBuildPlanTransaction' => 'PhabricatorApplicationTransaction', 'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildRequest' => 'Phobject', 'HarbormasterBuildSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'HarbormasterBuildSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HarbormasterBuildStatus' => 'Phobject', 'HarbormasterBuildStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'HarbormasterBuildStep' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorCustomFieldInterface', ), 'HarbormasterBuildStepCoreCustomField' => array( 'HarbormasterBuildStepCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'HarbormasterBuildStepCustomField' => 'PhabricatorCustomField', 'HarbormasterBuildStepEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildStepGroup' => 'Phobject', 'HarbormasterBuildStepImplementation' => 'Phobject', 'HarbormasterBuildStepImplementationTestCase' => 'PhabricatorTestCase', 'HarbormasterBuildStepPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildStepTransaction' => 'PhabricatorApplicationTransaction', 'HarbormasterBuildStepTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildTarget' => array( 'HarbormasterDAO', 'PhabricatorPolicyInterface', ), 'HarbormasterBuildTargetPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildTargetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildTransaction' => 'PhabricatorApplicationTransaction', 'HarbormasterBuildTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildUnitMessage' => 'HarbormasterDAO', 'HarbormasterBuildViewController' => 'HarbormasterController', 'HarbormasterBuildWorker' => 'HarbormasterWorker', 'HarbormasterBuildable' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'HarbormasterBuildableInterface', ), 'HarbormasterBuildableActionController' => 'HarbormasterController', 'HarbormasterBuildableListController' => 'HarbormasterController', 'HarbormasterBuildablePHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildableSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HarbormasterBuildableTransaction' => 'PhabricatorApplicationTransaction', 'HarbormasterBuildableTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildableTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildableViewController' => 'HarbormasterController', 'HarbormasterBuiltinBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterCircleCIBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterCircleCIHookController' => 'HarbormasterController', 'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod', 'HarbormasterController' => 'PhabricatorController', 'HarbormasterCreateArtifactConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterCreatePlansCapability' => 'PhabricatorPolicyCapability', 'HarbormasterDAO' => 'PhabricatorLiskDAO', 'HarbormasterDrydockBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterDrydockCommandBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterDrydockLeaseArtifact' => 'HarbormasterArtifact', 'HarbormasterExecFuture' => 'Future', 'HarbormasterExternalBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterFileArtifact' => 'HarbormasterArtifact', 'HarbormasterHTTPRequestBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterHostArtifact' => 'HarbormasterDrydockLeaseArtifact', 'HarbormasterLeaseWorkingCopyBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterLintMessagesController' => 'HarbormasterController', 'HarbormasterLintPropertyView' => 'AphrontView', 'HarbormasterManagementArchiveLogsWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementRestartWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementUpdateWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementWorkflow' => 'PhabricatorManagementWorkflow', 'HarbormasterMessageType' => 'Phobject', 'HarbormasterObject' => 'HarbormasterDAO', 'HarbormasterOtherBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterPlanController' => 'HarbormasterController', 'HarbormasterPlanDisableController' => 'HarbormasterPlanController', 'HarbormasterPlanEditController' => 'HarbormasterPlanController', 'HarbormasterPlanListController' => 'HarbormasterPlanController', 'HarbormasterPlanRunController' => 'HarbormasterPlanController', 'HarbormasterPlanViewController' => 'HarbormasterPlanController', 'HarbormasterPrototypeBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterPublishFragmentBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterQueryAutotargetsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterQueryBuildablesConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterQueryBuildsConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterQueryBuildsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'HarbormasterRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'HarbormasterRunBuildPlansHeraldAction' => 'HeraldAction', 'HarbormasterSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HarbormasterScratchTable' => 'HarbormasterDAO', 'HarbormasterSendMessageConduitAPIMethod' => 'HarbormasterConduitAPIMethod', 'HarbormasterSleepBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterStepAddController' => 'HarbormasterPlanController', 'HarbormasterStepDeleteController' => 'HarbormasterPlanController', 'HarbormasterStepEditController' => 'HarbormasterPlanController', 'HarbormasterStepViewController' => 'HarbormasterPlanController', 'HarbormasterTargetEngine' => 'Phobject', 'HarbormasterTargetWorker' => 'HarbormasterWorker', 'HarbormasterTestBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterThrowExceptionBuildStep' => 'HarbormasterBuildStepImplementation', 'HarbormasterUIEventListener' => 'PhabricatorEventListener', 'HarbormasterURIArtifact' => 'HarbormasterArtifact', 'HarbormasterUnitMessageListController' => 'HarbormasterController', 'HarbormasterUnitMessageViewController' => 'HarbormasterController', 'HarbormasterUnitPropertyView' => 'AphrontView', 'HarbormasterUnitStatus' => 'Phobject', 'HarbormasterUnitSummaryView' => 'AphrontView', 'HarbormasterUploadArtifactBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterWaitForPreviousBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterWorker' => 'PhabricatorWorker', 'HarbormasterWorkingCopyArtifact' => 'HarbormasterDrydockLeaseArtifact', 'HeraldAction' => 'Phobject', 'HeraldActionGroup' => 'HeraldGroup', 'HeraldActionRecord' => 'HeraldDAO', 'HeraldAdapter' => 'Phobject', 'HeraldAlwaysField' => 'HeraldField', 'HeraldAnotherRuleField' => 'HeraldField', 'HeraldApplicationActionGroup' => 'HeraldActionGroup', 'HeraldApplyTranscript' => 'Phobject', 'HeraldBasicFieldGroup' => 'HeraldFieldGroup', 'HeraldCommitAdapter' => array( 'HeraldAdapter', 'HarbormasterBuildableAdapterInterface', ), 'HeraldCondition' => 'HeraldDAO', 'HeraldConditionTranscript' => 'Phobject', 'HeraldContentSourceField' => 'HeraldField', 'HeraldController' => 'PhabricatorController', 'HeraldDAO' => 'PhabricatorLiskDAO', 'HeraldDifferentialAdapter' => 'HeraldAdapter', 'HeraldDifferentialDiffAdapter' => 'HeraldDifferentialAdapter', 'HeraldDifferentialRevisionAdapter' => array( 'HeraldDifferentialAdapter', 'HarbormasterBuildableAdapterInterface', ), 'HeraldDisableController' => 'HeraldController', 'HeraldDoNothingAction' => 'HeraldAction', 'HeraldEditFieldGroup' => 'HeraldFieldGroup', 'HeraldEffect' => 'Phobject', 'HeraldEmptyFieldValue' => 'HeraldFieldValue', 'HeraldEngine' => 'Phobject', 'HeraldExactProjectsField' => 'HeraldField', 'HeraldField' => 'Phobject', 'HeraldFieldGroup' => 'HeraldGroup', 'HeraldFieldTestCase' => 'PhutilTestCase', 'HeraldFieldValue' => 'Phobject', 'HeraldGroup' => 'Phobject', 'HeraldInvalidActionException' => 'Exception', 'HeraldInvalidConditionException' => 'Exception', 'HeraldManageGlobalRulesCapability' => 'PhabricatorPolicyCapability', 'HeraldManiphestTaskAdapter' => 'HeraldAdapter', 'HeraldNewController' => 'HeraldController', 'HeraldNewObjectField' => 'HeraldField', 'HeraldNotifyActionGroup' => 'HeraldActionGroup', 'HeraldObjectTranscript' => 'Phobject', 'HeraldPhameBlogAdapter' => 'HeraldAdapter', 'HeraldPhamePostAdapter' => 'HeraldAdapter', 'HeraldPholioMockAdapter' => 'HeraldAdapter', 'HeraldPonderQuestionAdapter' => 'HeraldAdapter', 'HeraldPreCommitAdapter' => 'HeraldAdapter', 'HeraldPreCommitContentAdapter' => 'HeraldPreCommitAdapter', 'HeraldPreCommitRefAdapter' => 'HeraldPreCommitAdapter', 'HeraldPreventActionGroup' => 'HeraldActionGroup', 'HeraldProjectsField' => 'HeraldField', 'HeraldRecursiveConditionsException' => 'Exception', 'HeraldRelatedFieldGroup' => 'HeraldFieldGroup', 'HeraldRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'HeraldRepetitionPolicyConfig' => 'Phobject', 'HeraldRule' => array( 'HeraldDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSubscribableInterface', ), 'HeraldRuleController' => 'HeraldController', 'HeraldRuleDatasource' => 'PhabricatorTypeaheadDatasource', 'HeraldRuleEditor' => 'PhabricatorApplicationTransactionEditor', 'HeraldRuleListController' => 'HeraldController', 'HeraldRulePHIDType' => 'PhabricatorPHIDType', 'HeraldRuleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HeraldRuleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HeraldRuleSerializer' => 'Phobject', 'HeraldRuleTestCase' => 'PhabricatorTestCase', 'HeraldRuleTransaction' => 'PhabricatorApplicationTransaction', 'HeraldRuleTransactionComment' => 'PhabricatorApplicationTransactionComment', 'HeraldRuleTranscript' => 'Phobject', 'HeraldRuleTypeConfig' => 'Phobject', 'HeraldRuleViewController' => 'HeraldController', 'HeraldSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HeraldSelectFieldValue' => 'HeraldFieldValue', 'HeraldSpaceField' => 'HeraldField', 'HeraldSubscribersField' => 'HeraldField', 'HeraldSupportActionGroup' => 'HeraldActionGroup', 'HeraldSupportFieldGroup' => 'HeraldFieldGroup', 'HeraldTestConsoleController' => 'HeraldController', 'HeraldTextFieldValue' => 'HeraldFieldValue', 'HeraldTokenizerFieldValue' => 'HeraldFieldValue', 'HeraldTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HeraldTranscript' => array( 'HeraldDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'HeraldTranscriptController' => 'HeraldController', 'HeraldTranscriptDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'HeraldTranscriptGarbageCollector' => 'PhabricatorGarbageCollector', 'HeraldTranscriptListController' => 'HeraldController', 'HeraldTranscriptPHIDType' => 'PhabricatorPHIDType', 'HeraldTranscriptQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HeraldTranscriptSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HeraldTranscriptTestCase' => 'PhabricatorTestCase', 'HeraldUtilityActionGroup' => 'HeraldActionGroup', 'Javelin' => 'Phobject', 'JavelinReactorUIExample' => 'PhabricatorUIExample', 'JavelinUIExample' => 'PhabricatorUIExample', 'JavelinViewExampleServerView' => 'AphrontView', 'JavelinViewUIExample' => 'PhabricatorUIExample', 'LegalpadController' => 'PhabricatorController', 'LegalpadCreateDocumentsCapability' => 'PhabricatorPolicyCapability', 'LegalpadDAO' => 'PhabricatorLiskDAO', 'LegalpadDefaultEditCapability' => 'PhabricatorPolicyCapability', 'LegalpadDefaultViewCapability' => 'PhabricatorPolicyCapability', 'LegalpadDocument' => array( 'LegalpadDAO', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'LegalpadDocumentBody' => array( 'LegalpadDAO', 'PhabricatorMarkupInterface', ), 'LegalpadDocumentCommentController' => 'LegalpadController', 'LegalpadDocumentDatasource' => 'PhabricatorTypeaheadDatasource', 'LegalpadDocumentDoneController' => 'LegalpadController', 'LegalpadDocumentEditController' => 'LegalpadController', 'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor', 'LegalpadDocumentListController' => 'LegalpadController', 'LegalpadDocumentManageController' => 'LegalpadController', 'LegalpadDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'LegalpadDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'LegalpadDocumentSignController' => 'LegalpadController', 'LegalpadDocumentSignature' => array( 'LegalpadDAO', 'PhabricatorPolicyInterface', ), 'LegalpadDocumentSignatureAddController' => 'LegalpadController', 'LegalpadDocumentSignatureListController' => 'LegalpadController', 'LegalpadDocumentSignatureQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentSignatureSearchEngine' => 'PhabricatorApplicationSearchEngine', 'LegalpadDocumentSignatureVerificationController' => 'LegalpadController', 'LegalpadDocumentSignatureViewController' => 'LegalpadController', 'LegalpadMailReceiver' => 'PhabricatorObjectMailReceiver', 'LegalpadObjectNeedsSignatureEdgeType' => 'PhabricatorEdgeType', 'LegalpadReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'LegalpadRequireSignatureHeraldAction' => 'HeraldAction', 'LegalpadSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'LegalpadSignatureNeededByObjectEdgeType' => 'PhabricatorEdgeType', 'LegalpadTransaction' => 'PhabricatorApplicationTransaction', 'LegalpadTransactionComment' => 'PhabricatorApplicationTransactionComment', 'LegalpadTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'LegalpadTransactionView' => 'PhabricatorApplicationTransactionView', 'LiskChunkTestCase' => 'PhabricatorTestCase', 'LiskDAO' => 'Phobject', 'LiskDAOSet' => 'Phobject', 'LiskDAOTestCase' => 'PhabricatorTestCase', 'LiskEphemeralObjectException' => 'Exception', 'LiskFixtureTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestDAO' => 'LiskDAO', 'LiskIsolationTestDAOException' => 'Exception', 'LiskMigrationIterator' => 'PhutilBufferedIterator', 'LiskRawMigrationIterator' => 'PhutilBufferedIterator', 'MacroConduitAPIMethod' => 'ConduitAPIMethod', 'MacroCreateMemeConduitAPIMethod' => 'MacroConduitAPIMethod', 'MacroQueryConduitAPIMethod' => 'MacroConduitAPIMethod', 'ManiphestAssignEmailCommand' => 'ManiphestEmailCommand', 'ManiphestAssigneeDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'ManiphestBatchEditController' => 'ManiphestController', 'ManiphestBulkEditCapability' => 'PhabricatorPolicyCapability', 'ManiphestClaimEmailCommand' => 'ManiphestEmailCommand', 'ManiphestCloseEmailCommand' => 'ManiphestEmailCommand', 'ManiphestConduitAPIMethod' => 'ConduitAPIMethod', 'ManiphestConfiguredCustomField' => array( 'ManiphestCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'ManiphestConstants' => 'Phobject', 'ManiphestController' => 'PhabricatorController', 'ManiphestCreateMailReceiver' => 'PhabricatorMailReceiver', 'ManiphestCreateTaskConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestCustomField' => 'PhabricatorCustomField', 'ManiphestCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'ManiphestCustomFieldStatusParser' => 'PhabricatorCustomFieldMonogramParser', 'ManiphestCustomFieldStatusParserTestCase' => 'PhabricatorTestCase', 'ManiphestCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'ManiphestCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestDefaultEditCapability' => 'PhabricatorPolicyCapability', 'ManiphestDefaultViewCapability' => 'PhabricatorPolicyCapability', 'ManiphestEditAssignCapability' => 'PhabricatorPolicyCapability', 'ManiphestEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'ManiphestEditEngine' => 'PhabricatorEditEngine', 'ManiphestEditPoliciesCapability' => 'PhabricatorPolicyCapability', 'ManiphestEditPriorityCapability' => 'PhabricatorPolicyCapability', 'ManiphestEditProjectsCapability' => 'PhabricatorPolicyCapability', 'ManiphestEditStatusCapability' => 'PhabricatorPolicyCapability', 'ManiphestEmailCommand' => 'MetaMTAEmailTransactionCommand', 'ManiphestExcelDefaultFormat' => 'ManiphestExcelFormat', 'ManiphestExcelFormat' => 'Phobject', 'ManiphestExcelFormatTestCase' => 'PhabricatorTestCase', 'ManiphestExportController' => 'ManiphestController', 'ManiphestGetTaskTransactionsConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestNameIndex' => 'ManiphestDAO', 'ManiphestPointsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestPriorityConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand', 'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'ManiphestQueryConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestQueryStatusesConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ManiphestReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'ManiphestReportController' => 'ManiphestController', 'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand', 'ManiphestSubpriorityController' => 'ManiphestController', 'ManiphestTask' => array( 'ManiphestDAO', 'PhabricatorSubscribableInterface', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorMentionableInterface', 'PhrequentTrackableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', 'DoorkeeperBridgedObjectInterface', ), 'ManiphestTaskAssignHeraldAction' => 'HeraldAction', 'ManiphestTaskAssignOtherHeraldAction' => 'ManiphestTaskAssignHeraldAction', 'ManiphestTaskAssignSelfHeraldAction' => 'ManiphestTaskAssignHeraldAction', 'ManiphestTaskAssigneeHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskAuthorHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskAuthorPolicyRule' => 'PhabricatorPolicyRule', 'ManiphestTaskCloseAsDuplicateRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskDependedOnByTaskEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskDependsOnTaskEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskDescriptionHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskDetailController' => 'ManiphestController', 'ManiphestTaskEditBulkJobType' => 'PhabricatorWorkerBulkJobType', 'ManiphestTaskEditController' => 'ManiphestController', 'ManiphestTaskFulltextEngine' => 'PhabricatorFulltextEngine', 'ManiphestTaskGraph' => 'PhabricatorObjectGraph', 'ManiphestTaskHasCommitEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskHasDuplicateTaskEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskHasMockEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskHasMockRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskHasParentRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskHasRevisionEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskHasRevisionRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskHasSubtaskRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskHeraldField' => 'HeraldField', 'ManiphestTaskHeraldFieldGroup' => 'HeraldFieldGroup', 'ManiphestTaskIsDuplicateOfTaskEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskListController' => 'ManiphestController', 'ManiphestTaskListHTTPParameterType' => 'AphrontListHTTPParameterType', 'ManiphestTaskListView' => 'ManiphestView', 'ManiphestTaskMailReceiver' => 'PhabricatorObjectMailReceiver', 'ManiphestTaskMergeInRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskOpenStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskPHIDResolver' => 'PhabricatorPHIDResolver', 'ManiphestTaskPHIDType' => 'PhabricatorPHIDType', 'ManiphestTaskPoints' => 'Phobject', 'ManiphestTaskPriority' => 'ManiphestConstants', 'ManiphestTaskPriorityDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskPriorityHeraldAction' => 'HeraldAction', 'ManiphestTaskPriorityHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ManiphestTaskRelationship' => 'PhabricatorObjectRelationship', 'ManiphestTaskRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'ManiphestTaskResultListView' => 'ManiphestView', 'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ManiphestTaskStatus' => 'ManiphestConstants', 'ManiphestTaskStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskStatusFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'ManiphestTaskStatusHeraldAction' => 'HeraldAction', 'ManiphestTaskStatusHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskStatusTestCase' => 'PhabricatorTestCase', 'ManiphestTaskTestCase' => 'PhabricatorTestCase', 'ManiphestTaskTitleHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTransaction' => 'PhabricatorApplicationTransaction', 'ManiphestTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ManiphestTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'ManiphestTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ManiphestUpdateConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestView' => 'AphrontView', 'MetaMTAEmailTransactionCommand' => 'Phobject', 'MetaMTAEmailTransactionCommandTestCase' => 'PhabricatorTestCase', 'MetaMTAMailReceivedGarbageCollector' => 'PhabricatorGarbageCollector', 'MetaMTAMailSentGarbageCollector' => 'PhabricatorGarbageCollector', 'MetaMTAReceivedMailStatus' => 'Phobject', 'MultimeterContext' => 'MultimeterDimension', 'MultimeterControl' => 'Phobject', 'MultimeterController' => 'PhabricatorController', 'MultimeterDAO' => 'PhabricatorLiskDAO', 'MultimeterDimension' => 'MultimeterDAO', 'MultimeterEvent' => 'MultimeterDAO', 'MultimeterEventGarbageCollector' => 'PhabricatorGarbageCollector', 'MultimeterHost' => 'MultimeterDimension', 'MultimeterLabel' => 'MultimeterDimension', 'MultimeterSampleController' => 'MultimeterController', 'MultimeterViewer' => 'MultimeterDimension', 'NuanceConduitAPIMethod' => 'ConduitAPIMethod', 'NuanceConsoleController' => 'NuanceController', 'NuanceContentSource' => 'PhabricatorContentSource', 'NuanceController' => 'PhabricatorController', 'NuanceDAO' => 'PhabricatorLiskDAO', 'NuanceGitHubEventItemType' => 'NuanceItemType', 'NuanceGitHubImportCursor' => 'NuanceImportCursor', 'NuanceGitHubIssuesImportCursor' => 'NuanceGitHubImportCursor', 'NuanceGitHubRawEvent' => 'Phobject', 'NuanceGitHubRawEventTestCase' => 'PhabricatorTestCase', 'NuanceGitHubRepositoryImportCursor' => 'NuanceGitHubImportCursor', 'NuanceGitHubRepositorySourceDefinition' => 'NuanceSourceDefinition', 'NuanceImportCursor' => 'Phobject', 'NuanceImportCursorData' => array( 'NuanceDAO', 'PhabricatorPolicyInterface', ), 'NuanceImportCursorDataQuery' => 'NuanceQuery', 'NuanceImportCursorPHIDType' => 'PhabricatorPHIDType', 'NuanceItem' => array( 'NuanceDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'NuanceItemActionController' => 'NuanceController', 'NuanceItemCommand' => array( 'NuanceDAO', 'PhabricatorPolicyInterface', ), 'NuanceItemCommandQuery' => 'NuanceQuery', 'NuanceItemController' => 'NuanceController', 'NuanceItemEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceItemListController' => 'NuanceItemController', 'NuanceItemManageController' => 'NuanceController', 'NuanceItemPHIDType' => 'PhabricatorPHIDType', 'NuanceItemQuery' => 'NuanceQuery', 'NuanceItemSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceItemTransaction' => 'NuanceTransaction', 'NuanceItemTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceItemTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceItemType' => 'Phobject', 'NuanceItemUpdateWorker' => 'NuanceWorker', 'NuanceItemViewController' => 'NuanceController', 'NuanceManagementImportWorkflow' => 'NuanceManagementWorkflow', 'NuanceManagementUpdateWorkflow' => 'NuanceManagementWorkflow', 'NuanceManagementWorkflow' => 'PhabricatorManagementWorkflow', 'NuancePhabricatorFormSourceDefinition' => 'NuanceSourceDefinition', 'NuanceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'NuanceQueue' => array( 'NuanceDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'NuanceQueueController' => 'NuanceController', 'NuanceQueueDatasource' => 'PhabricatorTypeaheadDatasource', 'NuanceQueueEditController' => 'NuanceQueueController', 'NuanceQueueEditEngine' => 'PhabricatorEditEngine', 'NuanceQueueEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceQueueListController' => 'NuanceQueueController', 'NuanceQueuePHIDType' => 'PhabricatorPHIDType', 'NuanceQueueQuery' => 'NuanceQuery', 'NuanceQueueSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceQueueTransaction' => 'NuanceTransaction', 'NuanceQueueTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceQueueTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceQueueViewController' => 'NuanceQueueController', 'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'NuanceSource' => array( 'NuanceDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorNgramsInterface', ), 'NuanceSourceActionController' => 'NuanceController', 'NuanceSourceController' => 'NuanceController', 'NuanceSourceDefaultEditCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceDefaultViewCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceDefinition' => 'Phobject', 'NuanceSourceDefinitionTestCase' => 'PhabricatorTestCase', 'NuanceSourceEditController' => 'NuanceSourceController', 'NuanceSourceEditEngine' => 'PhabricatorEditEngine', 'NuanceSourceEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceSourceListController' => 'NuanceSourceController', 'NuanceSourceManageCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceNameNgrams' => 'PhabricatorSearchNgrams', 'NuanceSourcePHIDType' => 'PhabricatorPHIDType', 'NuanceSourceQuery' => 'NuanceQuery', 'NuanceSourceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceSourceTransaction' => 'NuanceTransaction', 'NuanceSourceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceSourceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceSourceViewController' => 'NuanceSourceController', 'NuanceTransaction' => 'PhabricatorApplicationTransaction', 'NuanceWorker' => 'PhabricatorWorker', 'OwnersConduitAPIMethod' => 'ConduitAPIMethod', 'OwnersEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler', 'OwnersQueryConduitAPIMethod' => 'OwnersConduitAPIMethod', 'OwnersSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PHIDConduitAPIMethod' => 'ConduitAPIMethod', 'PHIDInfoConduitAPIMethod' => 'PHIDConduitAPIMethod', 'PHIDLookupConduitAPIMethod' => 'PHIDConduitAPIMethod', 'PHIDQueryConduitAPIMethod' => 'PHIDConduitAPIMethod', 'PHUI' => 'Phobject', 'PHUIActionPanelExample' => 'PhabricatorUIExample', 'PHUIActionPanelView' => 'AphrontTagView', 'PHUIApplicationMenuView' => 'Phobject', 'PHUIBadgeBoxView' => 'AphrontTagView', 'PHUIBadgeExample' => 'PhabricatorUIExample', 'PHUIBadgeMiniView' => 'AphrontTagView', 'PHUIBadgeView' => 'AphrontTagView', 'PHUIBigInfoView' => 'AphrontTagView', 'PHUIBoxExample' => 'PhabricatorUIExample', 'PHUIBoxView' => 'AphrontTagView', 'PHUIButtonBarExample' => 'PhabricatorUIExample', 'PHUIButtonBarView' => 'AphrontTagView', 'PHUIButtonExample' => 'PhabricatorUIExample', 'PHUIButtonView' => 'AphrontTagView', 'PHUICMSView' => 'AphrontTagView', 'PHUICalendarDayView' => 'AphrontView', 'PHUICalendarListView' => 'AphrontTagView', 'PHUICalendarMonthView' => 'AphrontView', 'PHUICalendarWeekView' => 'AphrontView', 'PHUICalendarWidgetView' => 'AphrontTagView', 'PHUIColorPalletteExample' => 'PhabricatorUIExample', 'PHUICrumbView' => 'AphrontView', 'PHUICrumbsView' => 'AphrontView', 'PHUICurtainExtension' => 'Phobject', 'PHUICurtainPanelView' => 'AphrontTagView', 'PHUICurtainView' => 'AphrontTagView', 'PHUIDiffGraphView' => 'Phobject', 'PHUIDiffGraphViewTestCase' => 'PhabricatorTestCase', 'PHUIDiffInlineCommentDetailView' => 'PHUIDiffInlineCommentView', 'PHUIDiffInlineCommentEditView' => 'PHUIDiffInlineCommentView', 'PHUIDiffInlineCommentRowScaffold' => 'AphrontView', 'PHUIDiffInlineCommentTableScaffold' => 'AphrontView', 'PHUIDiffInlineCommentUndoView' => 'PHUIDiffInlineCommentView', 'PHUIDiffInlineCommentView' => 'AphrontView', 'PHUIDiffOneUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 'PHUIDiffRevealIconView' => 'AphrontView', 'PHUIDiffTableOfContentsItemView' => 'AphrontView', 'PHUIDiffTableOfContentsListView' => 'AphrontView', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 'PHUIDocumentSummaryView' => 'AphrontTagView', 'PHUIDocumentViewPro' => 'AphrontTagView', 'PHUIFeedStoryExample' => 'PhabricatorUIExample', 'PHUIFeedStoryView' => 'AphrontView', 'PHUIFormDividerControl' => 'AphrontFormControl', 'PHUIFormFileControl' => 'AphrontFormControl', 'PHUIFormFreeformDateControl' => 'AphrontFormControl', 'PHUIFormIconSetControl' => 'AphrontFormControl', 'PHUIFormInsetView' => 'AphrontView', 'PHUIFormLayoutView' => 'AphrontView', 'PHUIFormNumberControl' => 'AphrontFormControl', 'PHUIHandleListView' => 'AphrontTagView', 'PHUIHandleTagListView' => 'AphrontTagView', 'PHUIHandleView' => 'AphrontView', 'PHUIHeadThingView' => 'AphrontTagView', 'PHUIHeaderView' => 'AphrontTagView', 'PHUIHovercardUIExample' => 'PhabricatorUIExample', 'PHUIHovercardView' => 'AphrontTagView', 'PHUIIconCircleView' => 'AphrontTagView', 'PHUIIconExample' => 'PhabricatorUIExample', 'PHUIIconView' => 'AphrontTagView', 'PHUIImageMaskExample' => 'PhabricatorUIExample', 'PHUIImageMaskView' => 'AphrontTagView', 'PHUIInfoExample' => 'PhabricatorUIExample', 'PHUIInfoPanelExample' => 'PhabricatorUIExample', 'PHUIInfoPanelView' => 'AphrontView', 'PHUIInfoView' => 'AphrontTagView', 'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase', 'PHUIInvisibleCharacterView' => 'AphrontView', 'PHUIListExample' => 'PhabricatorUIExample', 'PHUIListItemView' => 'AphrontTagView', 'PHUIListView' => 'AphrontTagView', 'PHUIListViewTestCase' => 'PhabricatorTestCase', 'PHUIMainMenuView' => 'AphrontView', 'PHUIObjectBoxView' => 'AphrontTagView', 'PHUIObjectItemListExample' => 'PhabricatorUIExample', 'PHUIObjectItemListView' => 'AphrontTagView', 'PHUIObjectItemView' => 'AphrontTagView', 'PHUIPagerView' => 'AphrontView', 'PHUIPinboardItemView' => 'AphrontView', 'PHUIPinboardView' => 'AphrontView', 'PHUIPolicySectionView' => 'AphrontTagView', 'PHUIPropertyGroupView' => 'AphrontTagView', 'PHUIPropertyListExample' => 'PhabricatorUIExample', 'PHUIPropertyListView' => 'AphrontView', 'PHUIRemarkupPreviewPanel' => 'AphrontTagView', 'PHUIRemarkupView' => 'AphrontView', 'PHUISegmentBarSegmentView' => 'AphrontTagView', 'PHUISegmentBarView' => 'AphrontTagView', 'PHUISpacesNamespaceContextView' => 'AphrontView', 'PHUIStatusItemView' => 'AphrontTagView', 'PHUIStatusListView' => 'AphrontTagView', 'PHUITabGroupView' => 'AphrontTagView', 'PHUITabView' => 'AphrontTagView', 'PHUITagExample' => 'PhabricatorUIExample', 'PHUITagView' => 'AphrontTagView', 'PHUITimelineEventView' => 'AphrontView', 'PHUITimelineExample' => 'PhabricatorUIExample', 'PHUITimelineView' => 'AphrontView', 'PHUITwoColumnView' => 'AphrontTagView', 'PHUITypeaheadExample' => 'PhabricatorUIExample', 'PHUIUserAvailabilityView' => 'AphrontTagView', 'PHUIWorkboardView' => 'AphrontTagView', 'PHUIWorkpanelView' => 'AphrontTagView', 'PassphraseAbstractKey' => 'Phobject', 'PassphraseConduitAPIMethod' => 'ConduitAPIMethod', 'PassphraseController' => 'PhabricatorController', 'PassphraseCredential' => array( 'PassphraseDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', 'PhabricatorFulltextInterface', ), 'PassphraseCredentialAuthorPolicyRule' => 'PhabricatorPolicyRule', 'PassphraseCredentialConduitController' => 'PassphraseController', 'PassphraseCredentialControl' => 'AphrontFormControl', 'PassphraseCredentialCreateController' => 'PassphraseController', 'PassphraseCredentialDestroyController' => 'PassphraseController', 'PassphraseCredentialEditController' => 'PassphraseController', 'PassphraseCredentialFulltextEngine' => 'PhabricatorFulltextEngine', 'PassphraseCredentialListController' => 'PassphraseController', 'PassphraseCredentialLockController' => 'PassphraseController', 'PassphraseCredentialPHIDType' => 'PhabricatorPHIDType', 'PassphraseCredentialPublicController' => 'PassphraseController', 'PassphraseCredentialQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PassphraseCredentialRevealController' => 'PassphraseController', 'PassphraseCredentialSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PassphraseCredentialTransaction' => 'PhabricatorApplicationTransaction', 'PassphraseCredentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PassphraseCredentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PassphraseCredentialType' => 'Phobject', 'PassphraseCredentialTypeTestCase' => 'PhabricatorTestCase', 'PassphraseCredentialViewController' => 'PassphraseController', 'PassphraseDAO' => 'PhabricatorLiskDAO', 'PassphraseDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PassphraseDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PassphraseNoteCredentialType' => 'PassphraseCredentialType', 'PassphrasePasswordCredentialType' => 'PassphraseCredentialType', 'PassphrasePasswordKey' => 'PassphraseAbstractKey', 'PassphraseQueryConduitAPIMethod' => 'PassphraseConduitAPIMethod', 'PassphraseRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PassphraseSSHGeneratedKeyCredentialType' => 'PassphraseSSHPrivateKeyCredentialType', 'PassphraseSSHKey' => 'PassphraseAbstractKey', 'PassphraseSSHPrivateKeyCredentialType' => 'PassphraseCredentialType', 'PassphraseSSHPrivateKeyFileCredentialType' => 'PassphraseSSHPrivateKeyCredentialType', 'PassphraseSSHPrivateKeyTextCredentialType' => 'PassphraseSSHPrivateKeyCredentialType', 'PassphraseSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PassphraseSecret' => 'PassphraseDAO', 'PassphraseTokenCredentialType' => 'PassphraseCredentialType', 'PasteConduitAPIMethod' => 'ConduitAPIMethod', 'PasteCreateConduitAPIMethod' => 'PasteConduitAPIMethod', 'PasteCreateMailReceiver' => 'PhabricatorMailReceiver', 'PasteDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PasteDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PasteEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PasteEmbedView' => 'AphrontView', 'PasteInfoConduitAPIMethod' => 'PasteConduitAPIMethod', 'PasteLanguageSelectDatasource' => 'PhabricatorTypeaheadDatasource', 'PasteMailReceiver' => 'PhabricatorObjectMailReceiver', 'PasteQueryConduitAPIMethod' => 'PasteConduitAPIMethod', 'PasteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PasteSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability', 'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability', 'PeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PeopleUserLogGarbageCollector' => 'PhabricatorGarbageCollector', 'Phabricator404Controller' => 'PhabricatorController', 'PhabricatorAWSConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAccessControlTestCase' => 'PhabricatorTestCase', 'PhabricatorAccessLog' => 'Phobject', 'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAccessibilitySetting' => 'PhabricatorSelectSetting', 'PhabricatorAccountSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorActionListView' => 'AphrontView', 'PhabricatorActionView' => 'AphrontView', 'PhabricatorActivitySettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorAdministratorsPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorAjaxRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorAlmanacApplication' => 'PhabricatorApplication', 'PhabricatorAmazonAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorAnchorView' => 'AphrontView', 'PhabricatorAphlictManagementDebugWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementRestartWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementStartWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementStatusWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementStopWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAphlictSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorAphrontBarUIExample' => 'PhabricatorUIExample', 'PhabricatorAphrontViewTestCase' => 'PhabricatorTestCase', 'PhabricatorAppSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorApplication' => array( 'Phobject', 'PhabricatorPolicyInterface', ), 'PhabricatorApplicationApplicationPHIDType' => 'PhabricatorPHIDType', 'PhabricatorApplicationConfigOptions' => 'Phobject', 'PhabricatorApplicationConfigurationPanel' => 'Phobject', 'PhabricatorApplicationConfigurationPanelTestCase' => 'PhabricatorTestCase', 'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView', 'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationLaunchView' => 'AphrontTagView', 'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController', - 'PhabricatorApplicationProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorApplicationSearchEngine' => 'Phobject', 'PhabricatorApplicationSearchEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorApplicationSearchResultView' => 'Phobject', 'PhabricatorApplicationStatusView' => 'AphrontView', 'PhabricatorApplicationTestCase' => 'PhabricatorTestCase', 'PhabricatorApplicationTransaction' => array( 'PhabricatorLiskDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorApplicationTransactionComment' => array( 'PhabricatorLiskDAO', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorApplicationTransactionCommentEditController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentEditor' => 'PhabricatorEditor', 'PhabricatorApplicationTransactionCommentHistoryController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationTransactionCommentQuoteController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentRawController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentRemoveController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentView' => 'AphrontView', 'PhabricatorApplicationTransactionController' => 'PhabricatorController', 'PhabricatorApplicationTransactionDetailController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionEditor' => 'PhabricatorEditor', 'PhabricatorApplicationTransactionFeedStory' => 'PhabricatorFeedStory', 'PhabricatorApplicationTransactionNoEffectException' => 'Exception', 'PhabricatorApplicationTransactionNoEffectResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionPublishWorker' => 'PhabricatorWorker', 'PhabricatorApplicationTransactionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationTransactionRemarkupPreviewController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorApplicationTransactionResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionShowOlderController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionStructureException' => 'Exception', 'PhabricatorApplicationTransactionTemplatedCommentQuery' => 'PhabricatorApplicationTransactionCommentQuery', 'PhabricatorApplicationTransactionTextDiffDetailView' => 'AphrontView', 'PhabricatorApplicationTransactionTransactionPHIDType' => 'PhabricatorPHIDType', 'PhabricatorApplicationTransactionValidationError' => 'Phobject', 'PhabricatorApplicationTransactionValidationException' => 'Exception', 'PhabricatorApplicationTransactionValidationResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionValueController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionView' => 'AphrontView', 'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationsApplication' => 'PhabricatorApplication', 'PhabricatorApplicationsController' => 'PhabricatorController', 'PhabricatorApplicationsListController' => 'PhabricatorApplicationsController', 'PhabricatorAsanaAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorAsanaConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAsanaSubtaskHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorAsanaTaskHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorAuditActionConstants' => 'Phobject', 'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController', 'PhabricatorAuditApplication' => 'PhabricatorApplication', 'PhabricatorAuditCommentEditor' => 'PhabricatorEditor', 'PhabricatorAuditCommitStatusConstants' => 'Phobject', 'PhabricatorAuditController' => 'PhabricatorController', 'PhabricatorAuditEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuditInlineComment' => array( 'Phobject', 'PhabricatorInlineCommentInterface', ), 'PhabricatorAuditListController' => 'PhabricatorAuditController', 'PhabricatorAuditListView' => 'AphrontView', 'PhabricatorAuditMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow', 'PhabricatorAuditManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuditPreviewController' => 'PhabricatorAuditController', 'PhabricatorAuditReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorAuditStatusConstants' => 'Phobject', 'PhabricatorAuditTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorAuditTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorAuditTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuditTransactionView' => 'PhabricatorApplicationTransactionView', 'PhabricatorAuthAccountView' => 'AphrontView', 'PhabricatorAuthApplication' => 'PhabricatorApplication', 'PhabricatorAuthAuthFactorPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthAuthProviderPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthConduitAPIMethod' => 'ConduitAPIMethod', 'PhabricatorAuthConfirmLinkController' => 'PhabricatorAuthController', 'PhabricatorAuthController' => 'PhabricatorController', 'PhabricatorAuthDAO' => 'PhabricatorLiskDAO', 'PhabricatorAuthDisableController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthDowngradeSessionController' => 'PhabricatorAuthController', 'PhabricatorAuthEditController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthFactor' => 'Phobject', 'PhabricatorAuthFactorConfig' => 'PhabricatorAuthDAO', 'PhabricatorAuthFactorTestCase' => 'PhabricatorTestCase', 'PhabricatorAuthFinishController' => 'PhabricatorAuthController', 'PhabricatorAuthHighSecurityRequiredException' => 'Exception', 'PhabricatorAuthHighSecurityToken' => 'Phobject', 'PhabricatorAuthInvite' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthInviteAccountException' => 'PhabricatorAuthInviteDialogException', 'PhabricatorAuthInviteAction' => 'Phobject', 'PhabricatorAuthInviteActionTableView' => 'AphrontView', 'PhabricatorAuthInviteController' => 'PhabricatorAuthController', 'PhabricatorAuthInviteDialogException' => 'PhabricatorAuthInviteException', 'PhabricatorAuthInviteEngine' => 'Phobject', 'PhabricatorAuthInviteException' => 'Exception', 'PhabricatorAuthInviteInvalidException' => 'PhabricatorAuthInviteDialogException', 'PhabricatorAuthInviteLoginException' => 'PhabricatorAuthInviteDialogException', 'PhabricatorAuthInvitePHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthInviteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthInviteRegisteredException' => 'PhabricatorAuthInviteException', 'PhabricatorAuthInviteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorAuthInviteTestCase' => 'PhabricatorTestCase', 'PhabricatorAuthInviteVerifyException' => 'PhabricatorAuthInviteDialogException', 'PhabricatorAuthInviteWorker' => 'PhabricatorWorker', 'PhabricatorAuthLinkController' => 'PhabricatorAuthController', 'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthLoginController' => 'PhabricatorAuthController', 'PhabricatorAuthLoginHandler' => 'Phobject', 'PhabricatorAuthLogoutConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorAuthManagementCachePKCS8Workflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementLDAPWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementListFactorsWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementRecoverWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementRefreshWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementStripWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUnlimitWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', 'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthOldOAuthRedirectController' => 'PhabricatorAuthController', 'PhabricatorAuthOneTimeLoginController' => 'PhabricatorAuthController', 'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorAuthPasswordResetTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorAuthProvider' => 'Phobject', 'PhabricatorAuthProviderConfig' => array( 'PhabricatorAuthDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthController', 'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthProvidersGuidanceContext' => 'PhabricatorGuidanceContext', 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'PhabricatorGuidanceEngineExtension', 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthRegisterController' => 'PhabricatorAuthController', 'PhabricatorAuthRevokeTokenController' => 'PhabricatorAuthController', 'PhabricatorAuthSSHKey' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorAuthSSHKeyController' => 'PhabricatorAuthController', 'PhabricatorAuthSSHKeyDeactivateController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyEditController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthSSHKeyGenerateController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyListController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthSSHKeyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthSSHKeyReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorAuthSSHKeySearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorAuthSSHKeyTableView' => 'AphrontView', 'PhabricatorAuthSSHKeyTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorAuthSSHKeyTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthSSHKeyViewController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHPublicKey' => 'Phobject', 'PhabricatorAuthSession' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthSessionEngine' => 'Phobject', 'PhabricatorAuthSessionEngineExtension' => 'Phobject', 'PhabricatorAuthSessionEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorAuthSessionGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorAuthSessionInfo' => 'Phobject', 'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorAuthStartController' => 'PhabricatorAuthController', 'PhabricatorAuthTOTPKeyTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorAuthTemporaryToken' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthTemporaryTokenGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorAuthTemporaryTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthTemporaryTokenType' => 'Phobject', 'PhabricatorAuthTemporaryTokenTypeModule' => 'PhabricatorConfigModule', 'PhabricatorAuthTerminateSessionController' => 'PhabricatorAuthController', 'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction', 'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController', 'PhabricatorAuthValidateController' => 'PhabricatorAuthController', 'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAutoEventListener' => 'PhabricatorEventListener', 'PhabricatorBadgeHasRecipientEdgeType' => 'PhabricatorEdgeType', 'PhabricatorBadgesApplication' => 'PhabricatorApplication', 'PhabricatorBadgesArchiveController' => 'PhabricatorBadgesController', 'PhabricatorBadgesAward' => array( 'PhabricatorBadgesDAO', 'PhabricatorDestructibleInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorBadgesAwardController' => 'PhabricatorBadgesController', 'PhabricatorBadgesAwardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorBadgesBadge' => array( 'PhabricatorBadgesDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorBadgesBadgeNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorBadgesCommentController' => 'PhabricatorBadgesController', 'PhabricatorBadgesController' => 'PhabricatorController', 'PhabricatorBadgesCreateCapability' => 'PhabricatorPolicyCapability', 'PhabricatorBadgesDAO' => 'PhabricatorLiskDAO', 'PhabricatorBadgesDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorBadgesDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorBadgesEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorBadgesEditController' => 'PhabricatorBadgesController', 'PhabricatorBadgesEditEngine' => 'PhabricatorEditEngine', 'PhabricatorBadgesEditRecipientsController' => 'PhabricatorBadgesController', 'PhabricatorBadgesEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorBadgesIconSet' => 'PhabricatorIconSet', 'PhabricatorBadgesListController' => 'PhabricatorBadgesController', 'PhabricatorBadgesMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorBadgesPHIDType' => 'PhabricatorPHIDType', 'PhabricatorBadgesQuality' => 'Phobject', 'PhabricatorBadgesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorBadgesRecipientsListView' => 'AphrontView', 'PhabricatorBadgesRemoveRecipientsController' => 'PhabricatorBadgesController', 'PhabricatorBadgesReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorBadgesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorBadgesSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorBadgesSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorBadgesTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorBadgesTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorBadgesTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorBadgesViewController' => 'PhabricatorBadgesController', 'PhabricatorBarePageUIExample' => 'PhabricatorUIExample', 'PhabricatorBarePageView' => 'AphrontPageView', 'PhabricatorBaseURISetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorBcryptPasswordHasher' => 'PhabricatorPasswordHasher', 'PhabricatorBinariesSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorBitbucketAuthProvider' => 'PhabricatorOAuth1AuthProvider', 'PhabricatorBoardLayoutEngine' => 'Phobject', 'PhabricatorBoardRenderingEngine' => 'Phobject', 'PhabricatorBoardResponseEngine' => 'Phobject', 'PhabricatorBoolEditField' => 'PhabricatorEditField', 'PhabricatorBot' => 'PhabricatorDaemon', 'PhabricatorBotChannel' => 'PhabricatorBotTarget', 'PhabricatorBotDebugLogHandler' => 'PhabricatorBotHandler', 'PhabricatorBotFeedNotificationHandler' => 'PhabricatorBotHandler', 'PhabricatorBotFlowdockProtocolAdapter' => 'PhabricatorStreamingProtocolAdapter', 'PhabricatorBotHandler' => 'Phobject', 'PhabricatorBotLogHandler' => 'PhabricatorBotHandler', 'PhabricatorBotMacroHandler' => 'PhabricatorBotHandler', 'PhabricatorBotMessage' => 'Phobject', 'PhabricatorBotObjectNameHandler' => 'PhabricatorBotHandler', 'PhabricatorBotSymbolHandler' => 'PhabricatorBotHandler', 'PhabricatorBotTarget' => 'Phobject', 'PhabricatorBotUser' => 'PhabricatorBotTarget', 'PhabricatorBotWhatsNewHandler' => 'PhabricatorBotHandler', 'PhabricatorBritishEnglishTranslation' => 'PhutilTranslation', 'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList', 'PhabricatorBulkContentSource' => 'PhabricatorContentSource', 'PhabricatorBusyUIExample' => 'PhabricatorUIExample', 'PhabricatorCacheDAO' => 'PhabricatorLiskDAO', 'PhabricatorCacheEngine' => 'Phobject', 'PhabricatorCacheEngineExtension' => 'Phobject', 'PhabricatorCacheGeneralGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorCacheManagementPurgeWorkflow' => 'PhabricatorCacheManagementWorkflow', 'PhabricatorCacheManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorCacheMarkupGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorCacheSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorCacheSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorCacheSpec' => 'Phobject', 'PhabricatorCacheTTLGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorCachedClassMapQuery' => 'Phobject', 'PhabricatorCaches' => 'Phobject', 'PhabricatorCachesTestCase' => 'PhabricatorTestCase', 'PhabricatorCalendarApplication' => 'PhabricatorApplication', 'PhabricatorCalendarController' => 'PhabricatorController', 'PhabricatorCalendarDAO' => 'PhabricatorLiskDAO', 'PhabricatorCalendarEvent' => array( 'PhabricatorCalendarDAO', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorPolicyCodexInterface', 'PhabricatorProjectInterface', 'PhabricatorMarkupInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorDestructibleInterface', 'PhabricatorMentionableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSpacesInterface', 'PhabricatorFulltextInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorCalendarEventAcceptTransaction' => 'PhabricatorCalendarEventReplyTransaction', 'PhabricatorCalendarEventAllDayTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventAvailabilityController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventCancelController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventCancelTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventDateTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventDeclineTransaction' => 'PhabricatorCalendarEventReplyTransaction', 'PhabricatorCalendarEventDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorCalendarEventDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorCalendarEventDescriptionTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventDragController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventEditEngine' => 'PhabricatorEditEngine', 'PhabricatorCalendarEventEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCalendarEventEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorCalendarEventEndDateTransaction' => 'PhabricatorCalendarEventDateTransaction', 'PhabricatorCalendarEventExportController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventForkTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventFrequencyTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorCalendarEventHeraldAdapter' => 'HeraldAdapter', 'PhabricatorCalendarEventHeraldField' => 'HeraldField', 'PhabricatorCalendarEventHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorCalendarEventHostPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorCalendarEventHostTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventIconTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventInviteTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventInvitee' => array( 'PhabricatorCalendarDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorCalendarEventInviteeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarEventInviteesPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorCalendarEventJoinController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEventMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorCalendarEventNameHeraldField' => 'PhabricatorCalendarEventHeraldField', 'PhabricatorCalendarEventNameTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventNotificationView' => 'Phobject', 'PhabricatorCalendarEventPHIDType' => 'PhabricatorPHIDType', 'PhabricatorCalendarEventPolicyCodex' => 'PhabricatorPolicyCodex', 'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarEventRSVPEmailCommand' => 'PhabricatorCalendarEventEmailCommand', 'PhabricatorCalendarEventRecurringTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventReplyTransaction' => 'PhabricatorCalendarEventTransactionType', 'PhabricatorCalendarEventSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorCalendarEventSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCalendarEventStartDateTransaction' => 'PhabricatorCalendarEventDateTransaction', 'PhabricatorCalendarEventTransaction' => 'PhabricatorModularTransaction', 'PhabricatorCalendarEventTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorCalendarEventTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorCalendarEventTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorCalendarEventUntilDateTransaction' => 'PhabricatorCalendarEventDateTransaction', 'PhabricatorCalendarEventViewController' => 'PhabricatorCalendarController', 'PhabricatorCalendarExport' => array( 'PhabricatorCalendarDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorCalendarExportDisableController' => 'PhabricatorCalendarController', 'PhabricatorCalendarExportDisableTransaction' => 'PhabricatorCalendarExportTransactionType', 'PhabricatorCalendarExportEditController' => 'PhabricatorCalendarController', 'PhabricatorCalendarExportEditEngine' => 'PhabricatorEditEngine', 'PhabricatorCalendarExportEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCalendarExportICSController' => 'PhabricatorCalendarController', 'PhabricatorCalendarExportListController' => 'PhabricatorCalendarController', 'PhabricatorCalendarExportModeTransaction' => 'PhabricatorCalendarExportTransactionType', 'PhabricatorCalendarExportNameTransaction' => 'PhabricatorCalendarExportTransactionType', 'PhabricatorCalendarExportPHIDType' => 'PhabricatorPHIDType', 'PhabricatorCalendarExportQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarExportQueryKeyTransaction' => 'PhabricatorCalendarExportTransactionType', 'PhabricatorCalendarExportSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCalendarExportTransaction' => 'PhabricatorModularTransaction', 'PhabricatorCalendarExportTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorCalendarExportTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorCalendarExportViewController' => 'PhabricatorCalendarController', 'PhabricatorCalendarExternalInvitee' => array( 'PhabricatorCalendarDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorCalendarExternalInviteePHIDType' => 'PhabricatorPHIDType', 'PhabricatorCalendarExternalInviteeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarICSFileImportEngine' => 'PhabricatorCalendarICSImportEngine', 'PhabricatorCalendarICSImportEngine' => 'PhabricatorCalendarImportEngine', 'PhabricatorCalendarICSURIImportEngine' => 'PhabricatorCalendarICSImportEngine', 'PhabricatorCalendarICSWriter' => 'Phobject', 'PhabricatorCalendarIconSet' => 'PhabricatorIconSet', 'PhabricatorCalendarImport' => array( 'PhabricatorCalendarDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorCalendarImportDefaultLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportDeleteController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportDeleteLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportDeleteTransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportDisableController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportDisableTransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportDropController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportDuplicateLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportEditController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportEditEngine' => 'PhabricatorEditEngine', 'PhabricatorCalendarImportEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCalendarImportEmptyLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportEngine' => 'Phobject', 'PhabricatorCalendarImportEpochLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportFetchLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportFrequencyLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportFrequencyTransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportICSFileTransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportICSLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportICSURITransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportICSWarningLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportIgnoredNodeLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportListController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportLog' => array( 'PhabricatorCalendarDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorCalendarImportLogListController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarImportLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCalendarImportLogType' => 'Phobject', 'PhabricatorCalendarImportLogView' => 'AphrontView', 'PhabricatorCalendarImportNameTransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportOriginalLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportOrphanLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportPHIDType' => 'PhabricatorPHIDType', 'PhabricatorCalendarImportQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCalendarImportQueueLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportReloadController' => 'PhabricatorCalendarController', 'PhabricatorCalendarImportReloadTransaction' => 'PhabricatorCalendarImportTransactionType', 'PhabricatorCalendarImportReloadWorker' => 'PhabricatorWorker', 'PhabricatorCalendarImportSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCalendarImportTransaction' => 'PhabricatorModularTransaction', 'PhabricatorCalendarImportTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorCalendarImportTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorCalendarImportTriggerLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportUpdateLogType' => 'PhabricatorCalendarImportLogType', 'PhabricatorCalendarImportViewController' => 'PhabricatorCalendarController', 'PhabricatorCalendarInviteeDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorCalendarInviteeUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorCalendarInviteeViewerFunctionDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorCalendarManagementNotifyWorkflow' => 'PhabricatorCalendarManagementWorkflow', 'PhabricatorCalendarManagementReloadWorkflow' => 'PhabricatorCalendarManagementWorkflow', 'PhabricatorCalendarManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorCalendarNotification' => 'PhabricatorCalendarDAO', 'PhabricatorCalendarNotificationEngine' => 'Phobject', 'PhabricatorCalendarRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorCalendarReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorCalendarSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorCampfireProtocolAdapter' => 'PhabricatorStreamingProtocolAdapter', 'PhabricatorCelerityApplication' => 'PhabricatorApplication', 'PhabricatorCelerityTestCase' => 'PhabricatorTestCase', 'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase', 'PhabricatorChangesetResponse' => 'AphrontProxyResponse', 'PhabricatorChatLogApplication' => 'PhabricatorApplication', 'PhabricatorChatLogChannel' => array( 'PhabricatorChatLogDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController', 'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController', 'PhabricatorChatLogChannelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorChatLogController' => 'PhabricatorController', 'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO', 'PhabricatorChatLogEvent' => array( 'PhabricatorChatLogDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorClusterConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorClusterDatabasesConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorClusterException' => 'Exception', 'PhabricatorClusterExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorClusterImpossibleWriteException' => 'PhabricatorClusterException', 'PhabricatorClusterImproperWriteException' => 'PhabricatorClusterException', 'PhabricatorClusterStrandedException' => 'PhabricatorClusterException', 'PhabricatorColumnsEditField' => 'PhabricatorPHIDListEditField', 'PhabricatorCommentEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorCommentEditField' => 'PhabricatorEditField', 'PhabricatorCommentEditType' => 'PhabricatorEditType', 'PhabricatorCommitBranchesField' => 'PhabricatorCommitCustomField', 'PhabricatorCommitCustomField' => 'PhabricatorCustomField', 'PhabricatorCommitMergedCommitsField' => 'PhabricatorCommitCustomField', 'PhabricatorCommitRepositoryField' => 'PhabricatorCommitCustomField', 'PhabricatorCommitSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCommitTagsField' => 'PhabricatorCommitCustomField', 'PhabricatorCommonPasswords' => 'Phobject', 'PhabricatorConduitAPIController' => 'PhabricatorConduitController', 'PhabricatorConduitApplication' => 'PhabricatorApplication', 'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 'PhabricatorConduitContentSource' => 'PhabricatorContentSource', 'PhabricatorConduitController' => 'PhabricatorController', 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 'PhabricatorConduitEditField' => 'PhabricatorEditField', 'PhabricatorConduitListController' => 'PhabricatorConduitController', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorConduitMethodCallLog' => array( 'PhabricatorConduitDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorConduitMethodQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConduitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorConduitResultInterface' => 'PhabricatorPHIDInterface', 'PhabricatorConduitSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorConduitSearchFieldSpecification' => 'Phobject', 'PhabricatorConduitTestCase' => 'PhabricatorTestCase', 'PhabricatorConduitToken' => array( 'PhabricatorConduitDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorConduitTokenController' => 'PhabricatorConduitController', 'PhabricatorConduitTokenEditController' => 'PhabricatorConduitController', 'PhabricatorConduitTokenHandshakeController' => 'PhabricatorConduitController', 'PhabricatorConduitTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConduitTokenTerminateController' => 'PhabricatorConduitController', 'PhabricatorConduitTokensSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorConfigAllController' => 'PhabricatorConfigController', 'PhabricatorConfigApplication' => 'PhabricatorApplication', 'PhabricatorConfigApplicationController' => 'PhabricatorConfigController', 'PhabricatorConfigCacheController' => 'PhabricatorConfigController', 'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigController', 'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigController', 'PhabricatorConfigClusterRepositoriesController' => 'PhabricatorConfigController', 'PhabricatorConfigCollectorsModule' => 'PhabricatorConfigModule', 'PhabricatorConfigColumnSchema' => 'PhabricatorConfigStorageSchema', 'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType', 'PhabricatorConfigConstants' => 'Phobject', 'PhabricatorConfigController' => 'PhabricatorController', 'PhabricatorConfigCoreSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorConfigDatabaseController' => 'PhabricatorConfigController', 'PhabricatorConfigDatabaseIssueController' => 'PhabricatorConfigDatabaseController', 'PhabricatorConfigDatabaseSchema' => 'PhabricatorConfigStorageSchema', 'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigDatabaseStatusController' => 'PhabricatorConfigDatabaseController', 'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource', 'PhabricatorConfigEdgeModule' => 'PhabricatorConfigModule', 'PhabricatorConfigEditController' => 'PhabricatorConfigController', 'PhabricatorConfigEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorConfigEntry' => array( 'PhabricatorConfigEntryDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorConfigEntryDAO' => 'PhabricatorLiskDAO', 'PhabricatorConfigEntryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigGroupConstants' => 'PhabricatorConfigConstants', 'PhabricatorConfigGroupController' => 'PhabricatorConfigController', 'PhabricatorConfigHTTPParameterTypesModule' => 'PhabricatorConfigModule', 'PhabricatorConfigHistoryController' => 'PhabricatorConfigController', 'PhabricatorConfigIgnoreController' => 'PhabricatorConfigController', 'PhabricatorConfigIssueListController' => 'PhabricatorConfigController', 'PhabricatorConfigIssuePanelController' => 'PhabricatorConfigController', 'PhabricatorConfigIssueViewController' => 'PhabricatorConfigController', 'PhabricatorConfigJSON' => 'Phobject', 'PhabricatorConfigJSONOptionType' => 'PhabricatorConfigOptionType', 'PhabricatorConfigKeySchema' => 'PhabricatorConfigStorageSchema', 'PhabricatorConfigListController' => 'PhabricatorConfigController', 'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementDoneWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementMigrateWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorConfigManualActivity' => 'PhabricatorConfigEntryDAO', 'PhabricatorConfigModule' => 'Phobject', 'PhabricatorConfigModuleController' => 'PhabricatorConfigController', 'PhabricatorConfigOption' => array( 'Phobject', 'PhabricatorMarkupInterface', ), 'PhabricatorConfigOptionType' => 'Phobject', 'PhabricatorConfigPHIDModule' => 'PhabricatorConfigModule', 'PhabricatorConfigPageView' => 'AphrontTagView', 'PhabricatorConfigProxySource' => 'PhabricatorConfigSource', 'PhabricatorConfigPurgeCacheController' => 'PhabricatorConfigController', 'PhabricatorConfigRequestExceptionHandlerModule' => 'PhabricatorConfigModule', 'PhabricatorConfigResponse' => 'AphrontStandaloneHTMLResponse', 'PhabricatorConfigSchemaQuery' => 'Phobject', 'PhabricatorConfigSchemaSpec' => 'Phobject', 'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema', 'PhabricatorConfigSetupCheckModule' => 'PhabricatorConfigModule', 'PhabricatorConfigSiteModule' => 'PhabricatorConfigModule', 'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigSource' => 'Phobject', 'PhabricatorConfigStackSource' => 'PhabricatorConfigSource', 'PhabricatorConfigStorageSchema' => 'Phobject', 'PhabricatorConfigTableSchema' => 'PhabricatorConfigStorageSchema', 'PhabricatorConfigTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorConfigValidationException' => 'Exception', 'PhabricatorConfigVersionController' => 'PhabricatorConfigController', 'PhabricatorConpherenceApplication' => 'PhabricatorApplication', 'PhabricatorConpherenceColumnMinimizeSetting' => 'PhabricatorInternalSetting', 'PhabricatorConpherenceColumnVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorConpherenceNotificationsSetting' => 'PhabricatorSelectSetting', 'PhabricatorConpherencePreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorConpherenceThreadPHIDType' => 'PhabricatorPHIDType', 'PhabricatorConpherenceWidgetVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorConsoleApplication' => 'PhabricatorApplication', 'PhabricatorConsoleContentSource' => 'PhabricatorContentSource', 'PhabricatorContentSource' => 'Phobject', 'PhabricatorContentSourceModule' => 'PhabricatorConfigModule', 'PhabricatorContentSourceView' => 'AphrontView', 'PhabricatorContributedToObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorController' => 'AphrontController', 'PhabricatorCookies' => 'Phobject', 'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorCoreCreateTransaction' => 'PhabricatorCoreTransactionType', 'PhabricatorCoreTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorCoreVoidTransaction' => 'PhabricatorModularTransactionType', 'PhabricatorCountdown' => array( 'PhabricatorCountdownDAO', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorSpacesInterface', 'PhabricatorProjectInterface', ), 'PhabricatorCountdownApplication' => 'PhabricatorApplication', 'PhabricatorCountdownController' => 'PhabricatorController', 'PhabricatorCountdownCountdownPHIDType' => 'PhabricatorPHIDType', 'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO', 'PhabricatorCountdownDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorCountdownDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditEngine' => 'PhabricatorEditEngine', 'PhabricatorCountdownEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCountdownListController' => 'PhabricatorCountdownController', 'PhabricatorCountdownMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorCountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCountdownRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorCountdownReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorCountdownSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorCountdownSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCountdownTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorCountdownTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorCountdownTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorCountdownView' => 'AphrontView', 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorCustomField' => 'Phobject', 'PhabricatorCustomFieldAttachment' => 'Phobject', 'PhabricatorCustomFieldConfigOptionType' => 'PhabricatorConfigOptionType', 'PhabricatorCustomFieldDataNotAvailableException' => 'Exception', 'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorCustomFieldEditField' => 'PhabricatorEditField', 'PhabricatorCustomFieldEditType' => 'PhabricatorEditType', 'PhabricatorCustomFieldFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorCustomFieldHeraldField' => 'HeraldField', 'PhabricatorCustomFieldHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorCustomFieldImplementationIncompleteException' => 'Exception', 'PhabricatorCustomFieldIndexStorage' => 'PhabricatorLiskDAO', 'PhabricatorCustomFieldList' => 'Phobject', 'PhabricatorCustomFieldMonogramParser' => 'Phobject', 'PhabricatorCustomFieldNotAttachedException' => 'Exception', 'PhabricatorCustomFieldNotProxyException' => 'Exception', 'PhabricatorCustomFieldNumericIndexStorage' => 'PhabricatorCustomFieldIndexStorage', 'PhabricatorCustomFieldSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorCustomFieldStorage' => 'PhabricatorLiskDAO', 'PhabricatorCustomFieldStorageQuery' => 'Phobject', 'PhabricatorCustomFieldStringIndexStorage' => 'PhabricatorCustomFieldIndexStorage', 'PhabricatorCustomLogoConfigType' => 'PhabricatorConfigOptionType', 'PhabricatorDaemon' => 'PhutilDaemon', 'PhabricatorDaemonBulkJobController' => 'PhabricatorDaemonController', 'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonBulkJobController', 'PhabricatorDaemonBulkJobMonitorController' => 'PhabricatorDaemonBulkJobController', 'PhabricatorDaemonBulkJobViewController' => 'PhabricatorDaemonBulkJobController', 'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController', 'PhabricatorDaemonContentSource' => 'PhabricatorContentSource', 'PhabricatorDaemonController' => 'PhabricatorController', 'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO', 'PhabricatorDaemonEventListener' => 'PhabricatorEventListener', 'PhabricatorDaemonLog' => array( 'PhabricatorDaemonDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO', 'PhabricatorDaemonLogEventGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorDaemonLogEventViewController' => 'PhabricatorDaemonController', 'PhabricatorDaemonLogEventsView' => 'AphrontView', 'PhabricatorDaemonLogGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController', 'PhabricatorDaemonLogListView' => 'AphrontView', 'PhabricatorDaemonLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController', 'PhabricatorDaemonManagementDebugWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementLaunchWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementListWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementLogWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementReloadWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementRestartWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementStartWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementStatusWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementStopWorkflow' => 'PhabricatorDaemonManagementWorkflow', 'PhabricatorDaemonManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorDaemonOverseerModule' => 'PhutilDaemonOverseerModule', 'PhabricatorDaemonReference' => 'Phobject', 'PhabricatorDaemonTaskGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorDaemonTasksTableView' => 'AphrontView', 'PhabricatorDaemonsApplication' => 'PhabricatorApplication', 'PhabricatorDaemonsSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorDailyRoutineTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorDarkConsoleSetting' => 'PhabricatorSelectSetting', 'PhabricatorDarkConsoleTabSetting' => 'PhabricatorInternalSetting', 'PhabricatorDarkConsoleVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorDashboard' => array( 'PhabricatorDashboardDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorProjectInterface', + 'PhabricatorNgramsInterface', ), 'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController', 'PhabricatorDashboardApplication' => 'PhabricatorApplication', 'PhabricatorDashboardArchiveController' => 'PhabricatorDashboardController', 'PhabricatorDashboardController' => 'PhabricatorController', 'PhabricatorDashboardCopyController' => 'PhabricatorDashboardController', 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'PhabricatorEdgeType', 'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType', + 'PhabricatorDashboardDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardIconSet' => 'PhabricatorIconSet', 'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO', 'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController', 'PhabricatorDashboardLayoutConfig' => 'Phobject', 'PhabricatorDashboardListController' => 'PhabricatorDashboardController', 'PhabricatorDashboardManageController' => 'PhabricatorDashboardController', 'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorDashboardPanel' => array( 'PhabricatorDashboardDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', + 'PhabricatorNgramsInterface', ), 'PhabricatorDashboardPanelArchiveController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelCoreCustomField' => array( 'PhabricatorDashboardPanelCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorDashboardPanelCustomField' => 'PhabricatorCustomField', + 'PhabricatorDashboardPanelDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorDashboardPanelEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelEditEngine' => 'PhabricatorEditEngine', 'PhabricatorDashboardPanelEditproController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelHasDashboardEdgeType' => 'PhabricatorEdgeType', 'PhabricatorDashboardPanelListController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardPanelNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorDashboardPanelPHIDType' => 'PhabricatorPHIDType', 'PhabricatorDashboardPanelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDashboardPanelRenderController' => 'PhabricatorDashboardController', 'PhabricatorDashboardPanelRenderingEngine' => 'Phobject', 'PhabricatorDashboardPanelSearchApplicationCustomField' => 'PhabricatorStandardCustomField', 'PhabricatorDashboardPanelSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorDashboardPanelSearchQueryCustomField' => 'PhabricatorStandardCustomField', 'PhabricatorDashboardPanelTabsCustomField' => 'PhabricatorStandardCustomField', 'PhabricatorDashboardPanelTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorDashboardPanelTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorDashboardPanelType' => 'Phobject', 'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController', + 'PhabricatorDashboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDashboardQueryPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorDashboardRemovePanelController' => 'PhabricatorDashboardController', 'PhabricatorDashboardRenderingEngine' => 'Phobject', 'PhabricatorDashboardSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorDashboardTabsPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardTextPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorDashboardTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorDashboardUninstallController' => 'PhabricatorDashboardController', 'PhabricatorDashboardViewController' => 'PhabricatorDashboardController', 'PhabricatorDataCacheSpec' => 'PhabricatorCacheSpec', 'PhabricatorDataNotAttachedException' => 'Exception', 'PhabricatorDatabaseHealthRecord' => 'Phobject', 'PhabricatorDatabaseRef' => 'Phobject', 'PhabricatorDatabaseRefParser' => 'Phobject', 'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorDatasourceEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorDatasourceEditType' => 'PhabricatorPHIDListEditType', 'PhabricatorDateFormatSetting' => 'PhabricatorSelectSetting', 'PhabricatorDateTimeSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDebugController' => 'PhabricatorController', 'PhabricatorDefaultRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorDefaultSyntaxStyle' => 'PhabricatorSyntaxStyle', 'PhabricatorDesktopNotificationsSetting' => 'PhabricatorInternalSetting', 'PhabricatorDesktopNotificationsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorDestructionEngine' => 'Phobject', 'PhabricatorDestructionEngineExtension' => 'Phobject', 'PhabricatorDestructionEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDeveloperPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDiffInlineCommentQuery' => 'PhabricatorApplicationTransactionCommentQuery', 'PhabricatorDiffPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDifferenceEngine' => 'Phobject', 'PhabricatorDifferentialApplication' => 'PhabricatorApplication', 'PhabricatorDifferentialAttachCommitWorkflow' => 'PhabricatorDifferentialManagementWorkflow', 'PhabricatorDifferentialConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDifferentialExtractWorkflow' => 'PhabricatorDifferentialManagementWorkflow', 'PhabricatorDifferentialManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorDifferentialRevisionTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorDiffusionApplication' => 'PhabricatorApplication', 'PhabricatorDiffusionBlameSetting' => 'PhabricatorInternalSetting', 'PhabricatorDiffusionConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDisplayPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDisqusAuthProvider' => 'PhabricatorOAuth2AuthProvider', - 'PhabricatorDividerProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorDividerEditField' => 'PhabricatorEditField', + 'PhabricatorDividerProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDivinerApplication' => 'PhabricatorApplication', 'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication', 'PhabricatorDraft' => 'PhabricatorDraftDAO', 'PhabricatorDraftDAO' => 'PhabricatorLiskDAO', 'PhabricatorDrydockApplication' => 'PhabricatorApplication', 'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants', 'PhabricatorEdgeConstants' => 'Phobject', 'PhabricatorEdgeCycleException' => 'Exception', 'PhabricatorEdgeEditType' => 'PhabricatorPHIDListEditType', 'PhabricatorEdgeEditor' => 'Phobject', 'PhabricatorEdgeGraph' => 'AbstractDirectedGraph', 'PhabricatorEdgeQuery' => 'PhabricatorQuery', 'PhabricatorEdgeTestCase' => 'PhabricatorTestCase', 'PhabricatorEdgeType' => 'Phobject', 'PhabricatorEdgeTypeTestCase' => 'PhabricatorTestCase', 'PhabricatorEdgesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorEditEngine' => array( 'Phobject', 'PhabricatorPolicyInterface', ), 'PhabricatorEditEngineAPIMethod' => 'ConduitAPIMethod', 'PhabricatorEditEngineColumnsCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineCommentAction' => 'Phobject', 'PhabricatorEditEngineConfiguration' => array( 'PhabricatorSearchDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorEditEngineConfigurationDefaultCreateController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationDefaultsController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationDisableController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorEditEngineConfigurationIsEditController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationLockController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType', 'PhabricatorEditEngineConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorEditEngineConfigurationReorderController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationSaveController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorEditEngineConfigurationSortController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineController' => 'PhabricatorApplicationTransactionController', 'PhabricatorEditEngineCreateQuickActions' => 'PhabricatorQuickActions', + 'PhabricatorEditEngineDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorEditEngineExtension' => 'Phobject', 'PhabricatorEditEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorEditEngineListController' => 'PhabricatorEditEngineController', 'PhabricatorEditEnginePointsCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorEditEngineSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorEditEngineSelectCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorEditEngineTokenizerCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditField' => 'Phobject', 'PhabricatorEditPage' => 'Phobject', 'PhabricatorEditType' => 'Phobject', 'PhabricatorEditor' => 'Phobject', 'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting', 'PhabricatorEditorSetting' => 'PhabricatorStringSetting', 'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', 'PhabricatorElasticSearchSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorEmailAddressesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorEmailContentSource' => 'PhabricatorContentSource', 'PhabricatorEmailDeliverySettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorEmailFormatSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailFormatSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorEmailLoginController' => 'PhabricatorAuthController', 'PhabricatorEmailNotificationsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailPreferencesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorEmailRePrefixSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailSelfActionsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailTagsSetting' => 'PhabricatorInternalSetting', 'PhabricatorEmailVarySubjectsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailVerificationController' => 'PhabricatorAuthController', 'PhabricatorEmbedFileRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorEmojiRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorEmojiTranslation' => 'PhutilTranslation', 'PhabricatorEmptyQueryException' => 'Exception', 'PhabricatorEnv' => 'Phobject', 'PhabricatorEnvTestCase' => 'PhabricatorTestCase', 'PhabricatorEpochEditField' => 'PhabricatorEditField', 'PhabricatorEvent' => 'PhutilEvent', 'PhabricatorEventEngine' => 'Phobject', 'PhabricatorEventListener' => 'PhutilEventListener', 'PhabricatorEventType' => 'PhutilEventType', 'PhabricatorExampleEventListener' => 'PhabricatorEventListener', 'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource', 'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorExtensionsSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorExternalAccount' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorExternalAccountsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorExtraConfigSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorFacebookAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorFactAggregate' => 'PhabricatorFactDAO', 'PhabricatorFactApplication' => 'PhabricatorApplication', 'PhabricatorFactChartController' => 'PhabricatorFactController', 'PhabricatorFactController' => 'PhabricatorController', 'PhabricatorFactCountEngine' => 'PhabricatorFactEngine', 'PhabricatorFactCursor' => 'PhabricatorFactDAO', 'PhabricatorFactDAO' => 'PhabricatorLiskDAO', 'PhabricatorFactDaemon' => 'PhabricatorDaemon', 'PhabricatorFactEngine' => 'Phobject', 'PhabricatorFactEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorFactHomeController' => 'PhabricatorFactController', 'PhabricatorFactLastUpdatedEngine' => 'PhabricatorFactEngine', 'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementListWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementStatusWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorFactRaw' => 'PhabricatorFactDAO', 'PhabricatorFactSimpleSpec' => 'PhabricatorFactSpec', 'PhabricatorFactSpec' => 'Phobject', 'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator', 'PhabricatorFaxContentSource' => 'PhabricatorContentSource', 'PhabricatorFeedApplication' => 'PhabricatorApplication', 'PhabricatorFeedBuilder' => 'Phobject', 'PhabricatorFeedConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFeedController' => 'PhabricatorController', 'PhabricatorFeedDAO' => 'PhabricatorLiskDAO', 'PhabricatorFeedDetailController' => 'PhabricatorFeedController', 'PhabricatorFeedListController' => 'PhabricatorFeedController', 'PhabricatorFeedManagementRepublishWorkflow' => 'PhabricatorFeedManagementWorkflow', 'PhabricatorFeedManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorFeedQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFeedSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorFeedStory' => array( 'Phobject', 'PhabricatorPolicyInterface', 'PhabricatorMarkupInterface', ), 'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryNotification' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryPublisher' => 'Phobject', 'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO', 'PhabricatorFile' => array( 'PhabricatorFileDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorFileAES256StorageFormat' => 'PhabricatorFileStorageFormat', 'PhabricatorFileBundleLoader' => 'Phobject', 'PhabricatorFileChunk' => array( 'PhabricatorFileDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorFileChunkIterator' => array( 'Phobject', 'Iterator', ), 'PhabricatorFileChunkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFileCommentController' => 'PhabricatorFileController', 'PhabricatorFileComposeController' => 'PhabricatorFileController', 'PhabricatorFileController' => 'PhabricatorController', 'PhabricatorFileDAO' => 'PhabricatorLiskDAO', 'PhabricatorFileDataController' => 'PhabricatorFileController', 'PhabricatorFileDeleteController' => 'PhabricatorFileController', 'PhabricatorFileDropUploadController' => 'PhabricatorFileController', 'PhabricatorFileEditController' => 'PhabricatorFileController', 'PhabricatorFileEditField' => 'PhabricatorEditField', 'PhabricatorFileEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorFileExternalRequest' => array( 'PhabricatorFileDAO', 'PhabricatorDestructibleInterface', ), 'PhabricatorFileExternalRequestGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorFileFilePHIDType' => 'PhabricatorPHIDType', 'PhabricatorFileHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorFileIconSetSelectController' => 'PhabricatorFileController', 'PhabricatorFileImageMacro' => array( 'PhabricatorFileDAO', 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorFileImageProxyController' => 'PhabricatorFileController', 'PhabricatorFileImageTransform' => 'PhabricatorFileTransform', 'PhabricatorFileInfoController' => 'PhabricatorFileController', 'PhabricatorFileLightboxController' => 'PhabricatorFileController', 'PhabricatorFileLinkView' => 'AphrontView', 'PhabricatorFileListController' => 'PhabricatorFileController', 'PhabricatorFileQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFileROT13StorageFormat' => 'PhabricatorFileStorageFormat', 'PhabricatorFileRawStorageFormat' => 'PhabricatorFileStorageFormat', 'PhabricatorFileSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorFileSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO', 'PhabricatorFileStorageConfigurationException' => 'Exception', 'PhabricatorFileStorageEngine' => 'Phobject', 'PhabricatorFileStorageEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorFileStorageFormat' => 'Phobject', 'PhabricatorFileStorageFormatTestCase' => 'PhabricatorTestCase', 'PhabricatorFileTemporaryGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorFileTestCase' => 'PhabricatorTestCase', 'PhabricatorFileTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorFileThumbnailTransform' => 'PhabricatorFileImageTransform', 'PhabricatorFileTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorFileTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorFileTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorFileTransform' => 'Phobject', 'PhabricatorFileTransformController' => 'PhabricatorFileController', 'PhabricatorFileTransformListController' => 'PhabricatorFileController', 'PhabricatorFileTransformTestCase' => 'PhabricatorTestCase', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadDialogController' => 'PhabricatorFileController', 'PhabricatorFileUploadException' => 'Exception', 'PhabricatorFileUploadSource' => 'Phobject', 'PhabricatorFileinfoSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorFilesApplication' => 'PhabricatorApplication', 'PhabricatorFilesApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel', 'PhabricatorFilesBuiltinFile' => 'Phobject', 'PhabricatorFilesComposeIconBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFilesManagementCatWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCompactWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCycleWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementEncodeWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementGenerateKeyWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementPurgeWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementRebuildWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorFilesOnDiskBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesOutboundRequestAction' => 'PhabricatorSystemAction', 'PhabricatorFiletreeVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorFlag' => array( 'PhabricatorFlagDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorFlagAddFlagHeraldAction' => 'HeraldAction', 'PhabricatorFlagColor' => 'PhabricatorFlagConstants', 'PhabricatorFlagConstants' => 'Phobject', 'PhabricatorFlagController' => 'PhabricatorController', 'PhabricatorFlagDAO' => 'PhabricatorLiskDAO', 'PhabricatorFlagDeleteController' => 'PhabricatorFlagController', 'PhabricatorFlagDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorFlagEditController' => 'PhabricatorFlagController', 'PhabricatorFlagListController' => 'PhabricatorFlagController', 'PhabricatorFlagQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFlagSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorFlagSelectControl' => 'AphrontFormControl', 'PhabricatorFlaggableInterface' => 'PhabricatorPHIDInterface', 'PhabricatorFlagsApplication' => 'PhabricatorApplication', 'PhabricatorFlagsUIEventListener' => 'PhabricatorEventListener', 'PhabricatorFulltextEngine' => 'Phobject', 'PhabricatorFulltextEngineExtension' => 'Phobject', 'PhabricatorFulltextEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorFulltextIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'PhabricatorFulltextStorageEngine' => 'Phobject', 'PhabricatorFundApplication' => 'PhabricatorApplication', 'PhabricatorGDSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorGarbageCollector' => 'Phobject', 'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow', 'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow', 'PhabricatorGarbageCollectorManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorGestureUIExample' => 'PhabricatorUIExample', 'PhabricatorGitGraphStream' => 'PhabricatorRepositoryGraphStream', 'PhabricatorGitHubAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorGlobalLock' => 'PhutilLock', 'PhabricatorGlobalUploadTargetView' => 'AphrontView', 'PhabricatorGoogleAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorGuidanceContext' => 'Phobject', 'PhabricatorGuidanceEngine' => 'Phobject', 'PhabricatorGuidanceEngineExtension' => 'Phobject', 'PhabricatorGuidanceMessage' => 'Phobject', 'PhabricatorGuideApplication' => 'PhabricatorApplication', 'PhabricatorGuideController' => 'PhabricatorController', 'PhabricatorGuideInstallModule' => 'PhabricatorGuideModule', 'PhabricatorGuideItemView' => 'Phobject', 'PhabricatorGuideListView' => 'AphrontView', 'PhabricatorGuideModule' => 'Phobject', 'PhabricatorGuideModuleController' => 'PhabricatorGuideController', 'PhabricatorGuideQuickStartModule' => 'PhabricatorGuideModule', 'PhabricatorHTTPParameterTypeTableView' => 'AphrontView', 'PhabricatorHandleList' => array( 'Phobject', 'Iterator', 'ArrayAccess', 'Countable', ), 'PhabricatorHandleObjectSelectorDataView' => 'Phobject', 'PhabricatorHandlePool' => 'Phobject', 'PhabricatorHandlePoolTestCase' => 'PhabricatorTestCase', 'PhabricatorHandleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorHandleRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorHandlesEditField' => 'PhabricatorPHIDListEditField', 'PhabricatorHarbormasterApplication' => 'PhabricatorApplication', 'PhabricatorHash' => 'Phobject', 'PhabricatorHashTestCase' => 'PhabricatorTestCase', 'PhabricatorHelpApplication' => 'PhabricatorApplication', 'PhabricatorHelpController' => 'PhabricatorController', 'PhabricatorHelpDocumentationController' => 'PhabricatorHelpController', 'PhabricatorHelpEditorProtocolController' => 'PhabricatorHelpController', 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', 'PhabricatorHelpMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorHeraldApplication' => 'PhabricatorApplication', 'PhabricatorHeraldContentSource' => 'PhabricatorContentSource', 'PhabricatorHighSecurityRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorHomeApplication' => 'PhabricatorApplication', 'PhabricatorHomeController' => 'PhabricatorController', 'PhabricatorHomeMainController' => 'PhabricatorHomeController', 'PhabricatorHomePreferencesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorHomeQuickCreateController' => 'PhabricatorHomeController', 'PhabricatorHovercardEngineExtension' => 'Phobject', 'PhabricatorHovercardEngineExtensionModule' => 'PhabricatorConfigModule', - 'PhabricatorHunksManagementMigrateWorkflow' => 'PhabricatorHunksManagementWorkflow', - 'PhabricatorHunksManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorIDsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorIDsSearchField' => 'PhabricatorSearchField', 'PhabricatorIRCProtocolAdapter' => 'PhabricatorProtocolAdapter', 'PhabricatorIconRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorIconSet' => 'Phobject', 'PhabricatorIconSetEditField' => 'PhabricatorEditField', 'PhabricatorIconSetIcon' => 'Phobject', 'PhabricatorImageMacroRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorImageRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorImageTransformer' => 'Phobject', 'PhabricatorImagemagickSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorInFlightErrorView' => 'AphrontView', 'PhabricatorIndexEngine' => 'Phobject', 'PhabricatorIndexEngineExtension' => 'Phobject', 'PhabricatorIndexEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase', 'PhabricatorInlineCommentController' => 'PhabricatorController', 'PhabricatorInlineCommentInterface' => 'PhabricatorMarkupInterface', 'PhabricatorInlineCommentPreviewController' => 'PhabricatorController', 'PhabricatorInlineSummaryView' => 'AphrontView', 'PhabricatorInstructionsEditField' => 'PhabricatorEditField', 'PhabricatorInternalSetting' => 'PhabricatorSetting', 'PhabricatorInternationalizationManagementExtractWorkflow' => 'PhabricatorInternationalizationManagementWorkflow', 'PhabricatorInternationalizationManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorInvalidConfigSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorIteratedMD5PasswordHasher' => 'PhabricatorPasswordHasher', 'PhabricatorIteratedMD5PasswordHasherTestCase' => 'PhabricatorTestCase', 'PhabricatorIteratorFileUploadSource' => 'PhabricatorFileUploadSource', 'PhabricatorJIRAAuthProvider' => 'PhabricatorOAuth1AuthProvider', 'PhabricatorJavelinLinter' => 'ArcanistLinter', 'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorJumpNavHandler' => 'Phobject', 'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache', 'PhabricatorKeyValueSerializingCacheProxy' => 'PhutilKeyValueCacheProxy', 'PhabricatorKeyboardRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorKeyring' => 'Phobject', 'PhabricatorKeyringConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider', 'PhabricatorLegalpadApplication' => 'PhabricatorApplication', 'PhabricatorLegalpadConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorLegalpadDocumentPHIDType' => 'PhabricatorPHIDType', 'PhabricatorLegalpadSignaturePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorLibraryTestCase' => 'PhutilLibraryTestCase', - 'PhabricatorLinkProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorLinkProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorLipsumArtist' => 'Phobject', 'PhabricatorLipsumContentSource' => 'PhabricatorContentSource', 'PhabricatorLipsumGenerateWorkflow' => 'PhabricatorLipsumManagementWorkflow', 'PhabricatorLipsumManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorLipsumMondrianArtist' => 'PhabricatorLipsumArtist', 'PhabricatorLiskDAO' => 'LiskDAO', 'PhabricatorLiskFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorLiskSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorLiskSerializer' => 'Phobject', 'PhabricatorListFilterUIExample' => 'PhabricatorUIExample', 'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase', 'PhabricatorLocaleScopeGuard' => 'Phobject', 'PhabricatorLocaleScopeGuardTestCase' => 'PhabricatorTestCase', 'PhabricatorLogTriggerAction' => 'PhabricatorTriggerAction', 'PhabricatorLogoutController' => 'PhabricatorAuthController', 'PhabricatorLunarPhasePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorMacroApplication' => 'PhabricatorApplication', 'PhabricatorMacroAudioController' => 'PhabricatorMacroController', 'PhabricatorMacroCommentController' => 'PhabricatorMacroController', 'PhabricatorMacroConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMacroController' => 'PhabricatorController', 'PhabricatorMacroDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorMacroDisableController' => 'PhabricatorMacroController', 'PhabricatorMacroEditController' => 'PhabricatorMacroController', 'PhabricatorMacroEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorMacroListController' => 'PhabricatorMacroController', 'PhabricatorMacroMacroPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMacroMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorMacroManageCapability' => 'PhabricatorPolicyCapability', 'PhabricatorMacroMemeController' => 'PhabricatorMacroController', 'PhabricatorMacroMemeDialogController' => 'PhabricatorMacroController', 'PhabricatorMacroQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMacroReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorMacroSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorMacroTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorMacroTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorMacroViewController' => 'PhabricatorMacroController', 'PhabricatorMailEmailHeraldField' => 'HeraldField', 'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorMailEmailSubjectHeraldField' => 'PhabricatorMailEmailHeraldField', 'PhabricatorMailImplementationAdapter' => 'Phobject', 'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', 'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementResendWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementSendTestWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter', 'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction', 'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction', 'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction', 'PhabricatorMailOutboundStatus' => 'Phobject', 'PhabricatorMailReceiver' => 'Phobject', 'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase', 'PhabricatorMailReplyHandler' => 'Phobject', 'PhabricatorMailRoutingRule' => 'Phobject', 'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorMailTarget' => 'Phobject', 'PhabricatorMailgunConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMainMenuBarExtension' => 'Phobject', 'PhabricatorMainMenuSearchView' => 'AphrontView', 'PhabricatorMainMenuView' => 'AphrontView', 'PhabricatorManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorManiphestApplication' => 'PhabricatorApplication', 'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorManualActivitySetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorMarkupCache' => 'PhabricatorCacheDAO', 'PhabricatorMarkupEngine' => 'Phobject', 'PhabricatorMarkupEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorMarkupOneOff' => array( 'Phobject', 'PhabricatorMarkupInterface', ), 'PhabricatorMarkupPreviewController' => 'PhabricatorController', 'PhabricatorMemeRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorMentionRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorMercurialGraphStream' => 'PhabricatorRepositoryGraphStream', 'PhabricatorMetaMTAActor' => 'Phobject', 'PhabricatorMetaMTAActorQuery' => 'PhabricatorQuery', 'PhabricatorMetaMTAApplication' => 'PhabricatorApplication', 'PhabricatorMetaMTAApplicationEmail' => array( 'PhabricatorMetaMTADAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', ), 'PhabricatorMetaMTAApplicationEmailDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorMetaMTAApplicationEmailEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorMetaMTAApplicationEmailHeraldField' => 'HeraldField', 'PhabricatorMetaMTAApplicationEmailPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMetaMTAApplicationEmailPanel' => 'PhabricatorApplicationConfigurationPanel', 'PhabricatorMetaMTAApplicationEmailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMetaMTAApplicationEmailTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorMetaMTAApplicationEmailTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorMetaMTAAttachment' => 'Phobject', 'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMetaMTAController' => 'PhabricatorController', 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', 'PhabricatorMetaMTAEmailBodyParser' => 'Phobject', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAEmailHeraldAction' => 'HeraldAction', 'PhabricatorMetaMTAEmailOthersHeraldAction' => 'PhabricatorMetaMTAEmailHeraldAction', 'PhabricatorMetaMTAEmailSelfHeraldAction' => 'PhabricatorMetaMTAEmailHeraldAction', 'PhabricatorMetaMTAErrorMailAction' => 'PhabricatorSystemAction', 'PhabricatorMetaMTAMail' => array( 'PhabricatorMetaMTADAO', 'PhabricatorPolicyInterface', ), 'PhabricatorMetaMTAMailBody' => 'Phobject', 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'PhabricatorEdgeType', 'PhabricatorMetaMTAMailListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMetaMTAMailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMetaMTAMailSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorMetaMTAMailSection' => 'Phobject', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailViewController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailableDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorMetaMTAMailableFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery', 'PhabricatorMetaMTAPermanentFailureException' => 'Exception', 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception', 'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTASchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAWorker' => 'PhabricatorWorker', 'PhabricatorMetronomicTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorModularTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorModularTransactionType' => 'Phobject', 'PhabricatorMonospacedFontSetting' => 'PhabricatorStringSetting', 'PhabricatorMonospacedTextareasSetting' => 'PhabricatorSelectSetting', - 'PhabricatorMotivatorProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorMotivatorProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorMultiColumnUIExample' => 'PhabricatorUIExample', 'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorMultimeterApplication' => 'PhabricatorApplication', 'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController', 'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorMySQLFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', 'PhabricatorMySQLSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorNamedQuery' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorNamedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorNavigationRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorNeverTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorNgramsIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'PhabricatorNotificationBuilder' => 'Phobject', 'PhabricatorNotificationClearController' => 'PhabricatorNotificationController', 'PhabricatorNotificationClient' => 'Phobject', 'PhabricatorNotificationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorNotificationController' => 'PhabricatorController', 'PhabricatorNotificationDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorNotificationIndividualController' => 'PhabricatorNotificationController', 'PhabricatorNotificationListController' => 'PhabricatorNotificationController', 'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController', 'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorNotificationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorNotificationServerRef' => 'Phobject', 'PhabricatorNotificationServersConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorNotificationStatusView' => 'AphrontTagView', 'PhabricatorNotificationTestController' => 'PhabricatorNotificationController', 'PhabricatorNotificationTestFeedStory' => 'PhabricatorFeedStory', 'PhabricatorNotificationUIExample' => 'PhabricatorUIExample', 'PhabricatorNotificationsApplication' => 'PhabricatorApplication', 'PhabricatorNuanceApplication' => 'PhabricatorApplication', 'PhabricatorOAuth1AuthProvider' => 'PhabricatorOAuthAuthProvider', 'PhabricatorOAuth1SecretTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorOAuth2AuthProvider' => 'PhabricatorOAuthAuthProvider', 'PhabricatorOAuthAuthProvider' => 'PhabricatorAuthProvider', 'PhabricatorOAuthClientAuthorization' => array( 'PhabricatorOAuthServerDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorOAuthClientAuthorizationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorOAuthClientController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthClientDisableController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthClientSecretController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthClientTestController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientController', 'PhabricatorOAuthResponse' => 'AphrontResponse', 'PhabricatorOAuthServer' => 'Phobject', 'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerApplication' => 'PhabricatorApplication', 'PhabricatorOAuthServerAuthController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthServerAuthorizationCode' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerAuthorizationsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorOAuthServerClient' => array( 'PhabricatorOAuthServerDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorOAuthServerClientAuthorizationPHIDType' => 'PhabricatorPHIDType', 'PhabricatorOAuthServerClientPHIDType' => 'PhabricatorPHIDType', 'PhabricatorOAuthServerClientQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorOAuthServerClientSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorOAuthServerController' => 'PhabricatorController', 'PhabricatorOAuthServerCreateClientsCapability' => 'PhabricatorPolicyCapability', 'PhabricatorOAuthServerDAO' => 'PhabricatorLiskDAO', 'PhabricatorOAuthServerEditEngine' => 'PhabricatorEditEngine', 'PhabricatorOAuthServerEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorOAuthServerSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorOAuthServerScope' => 'Phobject', 'PhabricatorOAuthServerTestCase' => 'PhabricatorTestCase', 'PhabricatorOAuthServerTokenController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthServerTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorOAuthServerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorObjectGraph' => 'AbstractDirectedGraph', 'PhabricatorObjectHandle' => array( 'Phobject', 'PhabricatorPolicyInterface', ), 'PhabricatorObjectHasAsanaSubtaskEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasAsanaTaskEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasContributorEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasFileEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasJiraIssueEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasSubscriberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasUnsubscriberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectHasWatcherEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectListQuery' => 'Phobject', 'PhabricatorObjectListQueryTestCase' => 'PhabricatorTestCase', 'PhabricatorObjectMailReceiver' => 'PhabricatorMailReceiver', 'PhabricatorObjectMailReceiverTestCase' => 'PhabricatorTestCase', 'PhabricatorObjectMentionedByObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectMentionsObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorObjectRelationship' => 'Phobject', 'PhabricatorObjectRelationshipList' => 'Phobject', 'PhabricatorObjectRelationshipSource' => 'Phobject', 'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorObjectSelectorDialog' => 'Phobject', 'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery', 'PhabricatorOldWorldContentSource' => 'PhabricatorContentSource', 'PhabricatorOlderInlinesSetting' => 'PhabricatorSelectSetting', 'PhabricatorOneTimeTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorOpcodeCacheSpec' => 'PhabricatorCacheSpec', 'PhabricatorOptionGroupSetting' => 'PhabricatorSetting', 'PhabricatorOwnerPathQuery' => 'Phobject', 'PhabricatorOwnersApplication' => 'PhabricatorApplication', 'PhabricatorOwnersArchiveController' => 'PhabricatorOwnersController', 'PhabricatorOwnersConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorOwnersConfiguredCustomField' => array( 'PhabricatorOwnersCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorOwnersController' => 'PhabricatorController', 'PhabricatorOwnersCustomField' => 'PhabricatorCustomField', 'PhabricatorOwnersCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'PhabricatorOwnersCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'PhabricatorOwnersCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO', 'PhabricatorOwnersDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorOwnersDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController', 'PhabricatorOwnersEditController' => 'PhabricatorOwnersController', 'PhabricatorOwnersListController' => 'PhabricatorOwnersController', 'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPackage' => array( 'PhabricatorOwnersDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorOwnersPackageAuditingTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageAutoreviewTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorOwnersPackageDescriptionTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageDominionTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageEditEngine' => 'PhabricatorEditEngine', 'PhabricatorOwnersPackageFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorOwnersPackageFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorOwnersPackageNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorOwnersPackageNameTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorOwnersPackageOwnersTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackagePHIDType' => 'PhabricatorPHIDType', 'PhabricatorOwnersPackagePathsTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackagePrimaryTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorOwnersPackageRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorOwnersPackageSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorOwnersPackageStatusTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageTestCase' => 'PhabricatorTestCase', 'PhabricatorOwnersPackageTransaction' => 'PhabricatorModularTransaction', 'PhabricatorOwnersPackageTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorOwnersPackageTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorOwnersPackageTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPathsController' => 'PhabricatorOwnersController', 'PhabricatorOwnersPathsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorOwnersSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorOwnersSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPHID' => 'Phobject', 'PhabricatorPHIDConstants' => 'Phobject', 'PhabricatorPHIDListEditField' => 'PhabricatorEditField', 'PhabricatorPHIDListEditType' => 'PhabricatorEditType', 'PhabricatorPHIDResolver' => 'Phobject', 'PhabricatorPHIDType' => 'Phobject', 'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase', 'PhabricatorPHIDsSearchField' => 'PhabricatorSearchField', 'PhabricatorPHPASTApplication' => 'PhabricatorApplication', 'PhabricatorPHPConfigSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorPHPMailerConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPHPPreflightSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorPackagesApplication' => 'PhabricatorApplication', 'PhabricatorPackagesController' => 'PhabricatorController', 'PhabricatorPackagesCreatePublisherCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPackagesDAO' => 'PhabricatorLiskDAO', 'PhabricatorPackagesEditEngine' => 'PhabricatorEditEngine', 'PhabricatorPackagesEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorPackagesNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorPackagesPackage' => array( 'PhabricatorPackagesDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSubscribableInterface', 'PhabricatorProjectInterface', 'PhabricatorConduitResultInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorPackagesPackageController' => 'PhabricatorPackagesController', 'PhabricatorPackagesPackageDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPackagesPackageDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPackagesPackageDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPackagesPackageEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorPackagesPackageEditController' => 'PhabricatorPackagesPackageController', 'PhabricatorPackagesPackageEditEngine' => 'PhabricatorPackagesEditEngine', 'PhabricatorPackagesPackageEditor' => 'PhabricatorPackagesEditor', 'PhabricatorPackagesPackageKeyTransaction' => 'PhabricatorPackagesPackageTransactionType', 'PhabricatorPackagesPackageListController' => 'PhabricatorPackagesPackageController', 'PhabricatorPackagesPackageListView' => 'PhabricatorPackagesView', 'PhabricatorPackagesPackageNameNgrams' => 'PhabricatorPackagesNgrams', 'PhabricatorPackagesPackageNameTransaction' => 'PhabricatorPackagesPackageTransactionType', 'PhabricatorPackagesPackagePHIDType' => 'PhabricatorPHIDType', 'PhabricatorPackagesPackagePublisherTransaction' => 'PhabricatorPackagesPackageTransactionType', 'PhabricatorPackagesPackageQuery' => 'PhabricatorPackagesQuery', 'PhabricatorPackagesPackageSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorPackagesPackageSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPackagesPackageTransaction' => 'PhabricatorModularTransaction', 'PhabricatorPackagesPackageTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPackagesPackageTransactionType' => 'PhabricatorPackagesTransactionType', 'PhabricatorPackagesPackageViewController' => 'PhabricatorPackagesPackageController', 'PhabricatorPackagesPublisher' => array( 'PhabricatorPackagesDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSubscribableInterface', 'PhabricatorProjectInterface', 'PhabricatorConduitResultInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorPackagesPublisherController' => 'PhabricatorPackagesController', 'PhabricatorPackagesPublisherDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPackagesPublisherDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPackagesPublisherEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorPackagesPublisherEditController' => 'PhabricatorPackagesPublisherController', 'PhabricatorPackagesPublisherEditEngine' => 'PhabricatorPackagesEditEngine', 'PhabricatorPackagesPublisherEditor' => 'PhabricatorPackagesEditor', 'PhabricatorPackagesPublisherKeyTransaction' => 'PhabricatorPackagesPublisherTransactionType', 'PhabricatorPackagesPublisherListController' => 'PhabricatorPackagesPublisherController', 'PhabricatorPackagesPublisherListView' => 'PhabricatorPackagesView', 'PhabricatorPackagesPublisherNameNgrams' => 'PhabricatorPackagesNgrams', 'PhabricatorPackagesPublisherNameTransaction' => 'PhabricatorPackagesPublisherTransactionType', 'PhabricatorPackagesPublisherPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPackagesPublisherQuery' => 'PhabricatorPackagesQuery', 'PhabricatorPackagesPublisherSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorPackagesPublisherSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPackagesPublisherTransaction' => 'PhabricatorModularTransaction', 'PhabricatorPackagesPublisherTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPackagesPublisherTransactionType' => 'PhabricatorPackagesTransactionType', 'PhabricatorPackagesPublisherViewController' => 'PhabricatorPackagesPublisherController', 'PhabricatorPackagesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPackagesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorPackagesTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorPackagesVersion' => array( 'PhabricatorPackagesDAO', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSubscribableInterface', 'PhabricatorProjectInterface', 'PhabricatorConduitResultInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorPackagesVersionController' => 'PhabricatorPackagesController', 'PhabricatorPackagesVersionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorPackagesVersionEditController' => 'PhabricatorPackagesVersionController', 'PhabricatorPackagesVersionEditEngine' => 'PhabricatorPackagesEditEngine', 'PhabricatorPackagesVersionEditor' => 'PhabricatorPackagesEditor', 'PhabricatorPackagesVersionListController' => 'PhabricatorPackagesVersionController', 'PhabricatorPackagesVersionListView' => 'PhabricatorPackagesView', 'PhabricatorPackagesVersionNameNgrams' => 'PhabricatorPackagesNgrams', 'PhabricatorPackagesVersionNameTransaction' => 'PhabricatorPackagesVersionTransactionType', 'PhabricatorPackagesVersionPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPackagesVersionPackageTransaction' => 'PhabricatorPackagesVersionTransactionType', 'PhabricatorPackagesVersionQuery' => 'PhabricatorPackagesQuery', 'PhabricatorPackagesVersionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorPackagesVersionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPackagesVersionTransaction' => 'PhabricatorModularTransaction', 'PhabricatorPackagesVersionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPackagesVersionTransactionType' => 'PhabricatorPackagesTransactionType', 'PhabricatorPackagesVersionViewController' => 'PhabricatorPackagesVersionController', 'PhabricatorPackagesView' => 'AphrontView', 'PhabricatorPagerUIExample' => 'PhabricatorUIExample', 'PhabricatorPassphraseApplication' => 'PhabricatorApplication', 'PhabricatorPasswordAuthProvider' => 'PhabricatorAuthProvider', 'PhabricatorPasswordHasher' => 'Phobject', 'PhabricatorPasswordHasherTestCase' => 'PhabricatorTestCase', 'PhabricatorPasswordHasherUnavailableException' => 'Exception', 'PhabricatorPasswordSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorPaste' => array( 'PhabricatorPasteDAO', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorMentionableInterface', 'PhabricatorPolicyInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorPasteApplication' => 'PhabricatorApplication', 'PhabricatorPasteArchiveController' => 'PhabricatorPasteController', 'PhabricatorPasteConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPasteContentSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorPasteContentTransaction' => 'PhabricatorPasteTransactionType', 'PhabricatorPasteController' => 'PhabricatorController', 'PhabricatorPasteDAO' => 'PhabricatorLiskDAO', 'PhabricatorPasteEditController' => 'PhabricatorPasteController', 'PhabricatorPasteEditEngine' => 'PhabricatorEditEngine', 'PhabricatorPasteEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorPasteFilenameContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorPasteLanguageTransaction' => 'PhabricatorPasteTransactionType', 'PhabricatorPasteListController' => 'PhabricatorPasteController', 'PhabricatorPastePastePHIDType' => 'PhabricatorPHIDType', 'PhabricatorPasteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPasteRawController' => 'PhabricatorPasteController', 'PhabricatorPasteRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorPasteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPasteSnippet' => 'Phobject', 'PhabricatorPasteStatusTransaction' => 'PhabricatorPasteTransactionType', 'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPasteTitleTransaction' => 'PhabricatorPasteTransactionType', 'PhabricatorPasteTransaction' => 'PhabricatorModularTransaction', 'PhabricatorPasteTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorPasteTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPasteTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorPasteViewController' => 'PhabricatorPasteController', 'PhabricatorPathSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorPeopleAnyOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleApplication' => 'PhabricatorApplication', 'PhabricatorPeopleApproveController' => 'PhabricatorPeopleController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleCreateController' => 'PhabricatorPeopleController', 'PhabricatorPeopleCreateGuidanceContext' => 'PhabricatorGuidanceContext', 'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController', - 'PhabricatorPeopleDetailsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorPeopleDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController', 'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', 'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPeopleIconSet' => 'PhabricatorIconSet', 'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController', 'PhabricatorPeopleInviteListController' => 'PhabricatorPeopleInviteController', 'PhabricatorPeopleInviteSendController' => 'PhabricatorPeopleInviteController', 'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', - 'PhabricatorPeopleManageProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleNewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController', - 'PhabricatorPeopleProfilePanelEngine' => 'PhabricatorProfilePanelEngine', + 'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', 'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPeopleTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPeopleUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeopleUserPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPeopleWelcomeController' => 'PhabricatorPeopleController', 'PhabricatorPhabricatorAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorPhameApplication' => 'PhabricatorApplication', 'PhabricatorPhameBlogPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhamePostPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhluxApplication' => 'PhabricatorApplication', 'PhabricatorPholioApplication' => 'PhabricatorApplication', 'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPhortuneApplication' => 'PhabricatorApplication', 'PhabricatorPhortuneContentSource' => 'PhabricatorContentSource', 'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow', 'PhabricatorPhortuneManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorPhragmentApplication' => 'PhabricatorApplication', 'PhabricatorPhrequentApplication' => 'PhabricatorApplication', 'PhabricatorPhrictionApplication' => 'PhabricatorApplication', 'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhurlApplication' => 'PhabricatorApplication', 'PhabricatorPhurlConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhurlController' => 'PhabricatorController', 'PhabricatorPhurlDAO' => 'PhabricatorLiskDAO', 'PhabricatorPhurlLinkRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorPhurlRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorPhurlSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorPhurlShortURLController' => 'PhabricatorPhurlController', 'PhabricatorPhurlShortURLDefaultController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURL' => array( 'PhabricatorPhurlDAO', 'PhabricatorPolicyInterface', 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorDestructibleInterface', 'PhabricatorMentionableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorPhurlURLAccessController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLCommentController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLCreateCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPhurlURLEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorPhurlURLEditController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLEditEngine' => 'PhabricatorEditEngine', 'PhabricatorPhurlURLEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorPhurlURLListController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorPhurlURLNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorPhurlURLPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhurlURLQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPhurlURLReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorPhurlURLSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorPhurlURLSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPhurlURLTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorPhurlURLTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorPhurlURLTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPhurlURLViewController' => 'PhabricatorPhurlController', 'PhabricatorPinnedApplicationsSetting' => 'PhabricatorInternalSetting', 'PhabricatorPirateEnglishTranslation' => 'PhutilTranslation', 'PhabricatorPlatformSite' => 'PhabricatorSite', 'PhabricatorPointsEditField' => 'PhabricatorEditField', 'PhabricatorPolicies' => 'PhabricatorPolicyConstants', 'PhabricatorPolicy' => array( 'PhabricatorPolicyDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorPolicyApplication' => 'PhabricatorApplication', 'PhabricatorPolicyAwareQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorPolicyAwareTestQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorPolicyCanEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPolicyCanJoinCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPolicyCanViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPolicyCapability' => 'Phobject', 'PhabricatorPolicyCapabilityTestCase' => 'PhabricatorTestCase', 'PhabricatorPolicyCodex' => 'Phobject', 'PhabricatorPolicyCodexRuleDescription' => 'Phobject', 'PhabricatorPolicyConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPolicyConstants' => 'Phobject', 'PhabricatorPolicyController' => 'PhabricatorController', 'PhabricatorPolicyDAO' => 'PhabricatorLiskDAO', 'PhabricatorPolicyDataTestCase' => 'PhabricatorTestCase', 'PhabricatorPolicyEditController' => 'PhabricatorPolicyController', 'PhabricatorPolicyEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorPolicyEditField' => 'PhabricatorEditField', 'PhabricatorPolicyException' => 'Exception', 'PhabricatorPolicyExplainController' => 'PhabricatorPolicyController', 'PhabricatorPolicyFavoritesSetting' => 'PhabricatorInternalSetting', 'PhabricatorPolicyFilter' => 'Phobject', 'PhabricatorPolicyInterface' => 'PhabricatorPHIDInterface', 'PhabricatorPolicyManagementShowWorkflow' => 'PhabricatorPolicyManagementWorkflow', 'PhabricatorPolicyManagementUnlockWorkflow' => 'PhabricatorPolicyManagementWorkflow', 'PhabricatorPolicyManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorPolicyPHIDTypePolicy' => 'PhabricatorPHIDType', 'PhabricatorPolicyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPolicyRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorPolicyRule' => 'Phobject', 'PhabricatorPolicySearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorPolicyTestCase' => 'PhabricatorTestCase', 'PhabricatorPolicyTestObject' => array( 'Phobject', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', ), 'PhabricatorPolicyType' => 'PhabricatorPolicyConstants', 'PhabricatorPonderApplication' => 'PhabricatorApplication', 'PhabricatorProfileMenuCollapsedSetting' => 'PhabricatorInternalSetting', - 'PhabricatorProfilePanel' => 'Phobject', - 'PhabricatorProfilePanelConfiguration' => array( + 'PhabricatorProfileMenuEditEngine' => 'PhabricatorEditEngine', + 'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor', + 'PhabricatorProfileMenuEngine' => 'Phobject', + 'PhabricatorProfileMenuItem' => 'Phobject', + 'PhabricatorProfileMenuItemConfiguration' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), - 'PhabricatorProfilePanelConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', - 'PhabricatorProfilePanelConfigurationTransaction' => 'PhabricatorApplicationTransaction', - 'PhabricatorProfilePanelConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', - 'PhabricatorProfilePanelEditEngine' => 'PhabricatorEditEngine', - 'PhabricatorProfilePanelEditor' => 'PhabricatorApplicationTransactionEditor', - 'PhabricatorProfilePanelEngine' => 'Phobject', - 'PhabricatorProfilePanelIconSet' => 'PhabricatorIconSet', - 'PhabricatorProfilePanelPHIDType' => 'PhabricatorPHIDType', + 'PhabricatorProfileMenuItemConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorProfileMenuItemConfigurationTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhabricatorProfileMenuItemIconSet' => 'PhabricatorIconSet', + 'PhabricatorProfileMenuItemPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProject' => array( 'PhabricatorProjectDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', 'PhabricatorConduitResultInterface', 'PhabricatorColumnProxyInterface', ), 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectApplication' => 'PhabricatorApplication', 'PhabricatorProjectArchiveController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardBackgroundController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardManageController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectCardView' => 'AphrontTagView', 'PhabricatorProjectColorsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorProjectColumn' => array( 'PhabricatorProjectDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorExtendedPolicyInterface', ), 'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectColumnHideController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectColumnPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProjectColumnPosition' => array( 'PhabricatorProjectDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorProjectColumnPositionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectColumnQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectColumnTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorProjectColumnTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProjectColumnTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProjectConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorProjectConfiguredCustomField' => array( 'PhabricatorProjectStandardCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorProjectController' => 'PhabricatorController', 'PhabricatorProjectCoreTestCase' => 'PhabricatorTestCase', 'PhabricatorProjectCoverController' => 'PhabricatorProjectController', 'PhabricatorProjectCustomField' => 'PhabricatorCustomField', 'PhabricatorProjectCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'PhabricatorProjectCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'PhabricatorProjectCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'PhabricatorProjectDAO' => 'PhabricatorLiskDAO', 'PhabricatorProjectDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectDefaultController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectDescriptionField' => 'PhabricatorProjectStandardCustomField', - 'PhabricatorProjectDetailsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectHeraldAction' => 'HeraldAction', 'PhabricatorProjectHeraldAdapter' => 'HeraldAdapter', 'PhabricatorProjectHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorProjectHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 'PhabricatorProjectIconsConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListView' => 'AphrontView', 'PhabricatorProjectLockController' => 'PhabricatorProjectController', 'PhabricatorProjectLogicalAncestorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalOrNotDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalViewerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectManageController' => 'PhabricatorProjectController', - 'PhabricatorProjectManageProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectMaterializedMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMemberListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMembersAddController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule', - 'PhabricatorProjectMembersProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectMembersProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersViewController' => 'PhabricatorProjectController', + 'PhabricatorProjectMenuItemController' => 'PhabricatorProjectController', 'PhabricatorProjectMoveController' => 'PhabricatorProjectController', 'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorProjectNoProjectsDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectObjectHasProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver', - 'PhabricatorProjectPanelController' => 'PhabricatorProjectController', - 'PhabricatorProjectPointsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectPointsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', - 'PhabricatorProjectProfilePanelEngine' => 'PhabricatorProfilePanelEngine', + 'PhabricatorProjectProfileMenuEngine' => 'PhabricatorProfileMenuEngine', + 'PhabricatorProjectProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectProjectHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectProjectPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectRemoveHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorProjectSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorProjectSilenceController' => 'PhabricatorProjectController', 'PhabricatorProjectSilencedEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectSlug' => 'PhabricatorProjectDAO', 'PhabricatorProjectStandardCustomField' => array( 'PhabricatorProjectCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorProjectStatus' => 'Phobject', 'PhabricatorProjectSubprojectWarningController' => 'PhabricatorProjectController', 'PhabricatorProjectSubprojectsController' => 'PhabricatorProjectController', - 'PhabricatorProjectSubprojectsProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectSubprojectsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectUserListView' => 'AphrontView', 'PhabricatorProjectViewController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController', 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject', - 'PhabricatorProjectWorkboardProfilePanel' => 'PhabricatorProfilePanel', + 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorProjectsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorProjectsWatchersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorPronounSetting' => 'PhabricatorSelectSetting', 'PhabricatorProtocolAdapter' => 'Phobject', 'PhabricatorPygmentSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorQuery' => 'Phobject', 'PhabricatorQueryConstraint' => 'Phobject', 'PhabricatorQueryOrderItem' => 'Phobject', 'PhabricatorQueryOrderTestCase' => 'PhabricatorTestCase', 'PhabricatorQueryOrderVector' => array( 'Phobject', 'Iterator', ), 'PhabricatorQuickActions' => 'Phobject', 'PhabricatorRateLimitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRecipientHasBadgeEdgeType' => 'PhabricatorEdgeType', 'PhabricatorRedirectController' => 'PhabricatorController', 'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController', 'PhabricatorRegistrationProfile' => 'Phobject', 'PhabricatorReleephApplication' => 'PhabricatorApplication', 'PhabricatorReleephApplicationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl', 'PhabricatorRemarkupCowsayBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 'PhabricatorRemarkupCustomBlockRule' => 'PhutilRemarkupBlockRule', 'PhabricatorRemarkupCustomInlineRule' => 'PhutilRemarkupRule', 'PhabricatorRemarkupEditField' => 'PhabricatorEditField', 'PhabricatorRemarkupFigletBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 'PhabricatorRemarkupUIExample' => 'PhabricatorUIExample', 'PhabricatorRepositoriesSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorRepository' => array( 'PhabricatorRepositoryDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorMarkupInterface', 'PhabricatorDestructibleInterface', 'PhabricatorProjectInterface', 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorRepositoryAuditRequest' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommit' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorProjectInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorSubscribableInterface', 'PhabricatorMentionableInterface', 'HarbormasterBuildableInterface', 'HarbormasterCircleCIBuildableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFulltextInterface', ), 'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitHint' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryCommitRef' => 'Phobject', 'PhabricatorRepositoryCommitTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorRepositoryEngine' => 'Phobject', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryGitLFSRef' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorRepositoryGitLFSRefQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryGraphCache' => 'Phobject', 'PhabricatorRepositoryGraphStream' => 'Phobject', 'PhabricatorRepositoryManagementCacheWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementClusterizeWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementHintWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementImportingWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementListPathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementLookupUsersWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMarkImportedWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMarkReachableWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMirrorWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementMovePathsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementParentsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementPullWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementRefsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementReparseWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementThawWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementUpdateWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryMirror' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryMirrorEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryOldRef' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryParsedChange' => 'Phobject', 'PhabricatorRepositoryPullEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryPullEvent' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryPullEventPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPullEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorDaemon', 'PhabricatorRepositoryPushEvent' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryPushEventPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPushEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPushLog' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryPushLogPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPushLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPushLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorRepositoryPushMailWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryPushReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryRefCursor' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryRefCursorPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryRefCursorQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryRefEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryRepositoryPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositorySchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorRepositoryStatusMessage' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorRepositoryType' => 'Phobject', 'PhabricatorRepositoryURI' => array( 'PhabricatorRepositoryDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorRepositoryURIIndex' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryURINormalizer' => 'Phobject', 'PhabricatorRepositoryURINormalizerTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryURIPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryURIQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryURITestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryURITransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorRepositoryURITransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorRepositoryVCSPassword' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryVersion' => 'Phobject', 'PhabricatorRepositoryWorkingCopyVersion' => 'PhabricatorRepositoryDAO', 'PhabricatorRequestExceptionHandler' => 'AphrontRequestExceptionHandler', 'PhabricatorResourceSite' => 'PhabricatorSite', 'PhabricatorRobotsController' => 'PhabricatorController', 'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorSMS' => 'PhabricatorSMSDAO', 'PhabricatorSMSConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSMSDAO' => 'PhabricatorLiskDAO', 'PhabricatorSMSDemultiplexWorker' => 'PhabricatorSMSWorker', 'PhabricatorSMSImplementationAdapter' => 'Phobject', 'PhabricatorSMSImplementationTestBlackholeAdapter' => 'PhabricatorSMSImplementationAdapter', 'PhabricatorSMSImplementationTwilioAdapter' => 'PhabricatorSMSImplementationAdapter', 'PhabricatorSMSManagementListOutboundWorkflow' => 'PhabricatorSMSManagementWorkflow', 'PhabricatorSMSManagementSendTestWorkflow' => 'PhabricatorSMSManagementWorkflow', 'PhabricatorSMSManagementShowOutboundWorkflow' => 'PhabricatorSMSManagementWorkflow', 'PhabricatorSMSManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorSMSSendWorker' => 'PhabricatorSMSWorker', 'PhabricatorSMSWorker' => 'PhabricatorWorker', 'PhabricatorSQLPatchList' => 'Phobject', 'PhabricatorSSHKeyGenerator' => 'Phobject', 'PhabricatorSSHKeysSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorSSHLog' => 'Phobject', 'PhabricatorSSHPassthruCommand' => 'Phobject', 'PhabricatorSSHWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorSavedQuery' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorSavedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction', 'PhabricatorScopedEnv' => 'Phobject', 'PhabricatorSearchAbstractDocument' => 'Phobject', 'PhabricatorSearchApplication' => 'PhabricatorApplication', 'PhabricatorSearchApplicationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSearchApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel', 'PhabricatorSearchBaseController' => 'PhabricatorController', 'PhabricatorSearchCheckboxesField' => 'PhabricatorSearchField', 'PhabricatorSearchConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchCustomFieldProxyField' => 'PhabricatorSearchField', 'PhabricatorSearchDAO' => 'PhabricatorLiskDAO', 'PhabricatorSearchDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorSearchDatasourceField' => 'PhabricatorSearchTokenizerField', 'PhabricatorSearchDateControlField' => 'PhabricatorSearchField', 'PhabricatorSearchDateField' => 'PhabricatorSearchField', 'PhabricatorSearchDeleteController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchDocument' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentFieldType' => 'Phobject', 'PhabricatorSearchDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentTypeDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorSearchEditController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchEngineAPIMethod' => 'ConduitAPIMethod', 'PhabricatorSearchEngineAttachment' => 'Phobject', 'PhabricatorSearchEngineExtension' => 'Phobject', 'PhabricatorSearchEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorSearchEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorSearchField' => 'Phobject', 'PhabricatorSearchHovercardController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchIndexVersion' => 'PhabricatorSearchDAO', 'PhabricatorSearchIndexVersionDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorSearchManagementIndexWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorSearchManagementInitWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorSearchManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorSearchNgrams' => 'PhabricatorSearchDAO', 'PhabricatorSearchNgramsDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorSearchOrderController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchOrderField' => 'PhabricatorSearchField', 'PhabricatorSearchRelationship' => 'Phobject', 'PhabricatorSearchRelationshipController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchRelationshipSourceController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchResultBucket' => 'Phobject', 'PhabricatorSearchResultBucketGroup' => 'Phobject', 'PhabricatorSearchResultView' => 'AphrontView', 'PhabricatorSearchSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSearchScopeSetting' => 'PhabricatorInternalSetting', 'PhabricatorSearchSelectField' => 'PhabricatorSearchField', 'PhabricatorSearchStringListField' => 'PhabricatorSearchField', 'PhabricatorSearchSubscribersField' => 'PhabricatorSearchTokenizerField', 'PhabricatorSearchTextField' => 'PhabricatorSearchField', 'PhabricatorSearchThreeStateField' => 'PhabricatorSearchField', 'PhabricatorSearchTokenizerField' => 'PhabricatorSearchField', 'PhabricatorSearchWorker' => 'PhabricatorWorker', 'PhabricatorSecurityConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSecuritySetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorSelectEditField' => 'PhabricatorEditField', 'PhabricatorSelectSetting' => 'PhabricatorSetting', 'PhabricatorSendGridConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSessionsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorSetting' => 'Phobject', 'PhabricatorSettingsAccountPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsAddEmailAction' => 'PhabricatorSystemAction', 'PhabricatorSettingsAdjustController' => 'PhabricatorController', 'PhabricatorSettingsApplication' => 'PhabricatorApplication', 'PhabricatorSettingsApplicationsPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsAuthenticationPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsDeveloperPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsEditEngine' => 'PhabricatorEditEngine', 'PhabricatorSettingsEmailPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsListController' => 'PhabricatorController', 'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsMainController' => 'PhabricatorController', 'PhabricatorSettingsMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorSettingsPanel' => 'Phobject', 'PhabricatorSettingsPanelGroup' => 'Phobject', 'PhabricatorSettingsTimezoneController' => 'PhabricatorController', 'PhabricatorSetupCheck' => 'Phobject', 'PhabricatorSetupCheckTestCase' => 'PhabricatorTestCase', 'PhabricatorSetupEngine' => 'Phobject', 'PhabricatorSetupIssue' => 'Phobject', 'PhabricatorSetupIssueUIExample' => 'PhabricatorUIExample', 'PhabricatorSetupIssueView' => 'AphrontView', 'PhabricatorShortSite' => 'PhabricatorSite', 'PhabricatorShowFiletreeSetting' => 'PhabricatorSelectSetting', 'PhabricatorSimpleEditType' => 'PhabricatorEditType', 'PhabricatorSite' => 'AphrontSite', 'PhabricatorSlackAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorSlowvoteApplication' => 'PhabricatorApplication', 'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteController' => 'PhabricatorController', 'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO', 'PhabricatorSlowvoteDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorSlowvoteEditController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvotePoll' => array( 'PhabricatorSlowvoteDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', ), 'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvotePollPHIDType' => 'PhabricatorPHIDType', 'PhabricatorSlowvoteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorSlowvoteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorSlowvoteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSlowvoteTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorSlowvoteTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorSlowvoteTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorSlowvoteVoteController' => 'PhabricatorSlowvoteController', 'PhabricatorSlug' => 'Phobject', 'PhabricatorSlugTestCase' => 'PhabricatorTestCase', 'PhabricatorSortTableUIExample' => 'PhabricatorUIExample', 'PhabricatorSourceCodeView' => 'AphrontView', 'PhabricatorSpaceEditField' => 'PhabricatorEditField', 'PhabricatorSpacesApplication' => 'PhabricatorApplication', 'PhabricatorSpacesArchiveController' => 'PhabricatorSpacesController', 'PhabricatorSpacesCapabilityCreateSpaces' => 'PhabricatorPolicyCapability', 'PhabricatorSpacesCapabilityDefaultEdit' => 'PhabricatorPolicyCapability', 'PhabricatorSpacesCapabilityDefaultView' => 'PhabricatorPolicyCapability', 'PhabricatorSpacesController' => 'PhabricatorController', 'PhabricatorSpacesDAO' => 'PhabricatorLiskDAO', 'PhabricatorSpacesEditController' => 'PhabricatorSpacesController', 'PhabricatorSpacesInterface' => 'PhabricatorPHIDInterface', 'PhabricatorSpacesListController' => 'PhabricatorSpacesController', 'PhabricatorSpacesNamespace' => array( 'PhabricatorSpacesDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorSpacesNamespaceDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorSpacesNamespaceEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorSpacesNamespacePHIDType' => 'PhabricatorPHIDType', 'PhabricatorSpacesNamespaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorSpacesNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorSpacesNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorSpacesNoAccessController' => 'PhabricatorSpacesController', 'PhabricatorSpacesRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorSpacesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSpacesSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorSpacesSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorSpacesTestCase' => 'PhabricatorTestCase', 'PhabricatorSpacesViewController' => 'PhabricatorSpacesController', 'PhabricatorStandardCustomField' => 'PhabricatorCustomField', 'PhabricatorStandardCustomFieldBlueprints' => 'PhabricatorStandardCustomFieldTokenizer', 'PhabricatorStandardCustomFieldBool' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldCredential' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldDatasource' => 'PhabricatorStandardCustomFieldTokenizer', 'PhabricatorStandardCustomFieldDate' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldHeader' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldInt' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldLink' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldPHIDs' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldRemarkup' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldSelect' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldText' => 'PhabricatorStandardCustomField', 'PhabricatorStandardCustomFieldTokenizer' => 'PhabricatorStandardCustomFieldPHIDs', 'PhabricatorStandardCustomFieldUsers' => 'PhabricatorStandardCustomFieldTokenizer', 'PhabricatorStandardPageView' => array( 'PhabricatorBarePageView', 'AphrontResponseProducerInterface', ), 'PhabricatorStandardSelectCustomFieldDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorStaticEditField' => 'PhabricatorEditField', 'PhabricatorStatusController' => 'PhabricatorController', 'PhabricatorStatusUIExample' => 'PhabricatorUIExample', 'PhabricatorStorageFixtureScopeGuard' => 'Phobject', 'PhabricatorStorageManagementAPI' => 'Phobject', 'PhabricatorStorageManagementAdjustWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementPartitionWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementProbeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementQuickstartWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementRenamespaceWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementShellWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorStoragePatch' => 'Phobject', 'PhabricatorStorageSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorStorageSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorStreamingProtocolAdapter' => 'PhabricatorProtocolAdapter', 'PhabricatorStringListEditField' => 'PhabricatorEditField', 'PhabricatorStringSetting' => 'PhabricatorSetting', + 'PhabricatorSubmitEditField' => 'PhabricatorEditField', 'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorSubscribersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', 'PhabricatorSubscriptionTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorSubscriptionsAddSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsAddSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsApplication' => 'PhabricatorApplication', 'PhabricatorSubscriptionsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorSubscriptionsEditController' => 'PhabricatorController', 'PhabricatorSubscriptionsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor', 'PhabricatorSubscriptionsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorSubscriptionsHeraldAction' => 'HeraldAction', 'PhabricatorSubscriptionsListController' => 'PhabricatorController', 'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorSubscriptionsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorSubscriptionsSubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorSubscriptionsSubscribersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorSubscriptionsTransactionController' => 'PhabricatorController', 'PhabricatorSubscriptionsUIEventListener' => 'PhabricatorEventListener', 'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorSupportApplication' => 'PhabricatorApplication', 'PhabricatorSyntaxHighlighter' => 'Phobject', 'PhabricatorSyntaxHighlightingConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSyntaxStyle' => 'Phobject', 'PhabricatorSystemAction' => 'Phobject', 'PhabricatorSystemActionEngine' => 'Phobject', 'PhabricatorSystemActionGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorSystemActionLog' => 'PhabricatorSystemDAO', 'PhabricatorSystemActionRateLimitException' => 'Exception', 'PhabricatorSystemApplication' => 'PhabricatorApplication', 'PhabricatorSystemDAO' => 'PhabricatorLiskDAO', 'PhabricatorSystemDestructionGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorSystemDestructionLog' => 'PhabricatorSystemDAO', 'PhabricatorSystemFaviconController' => 'PhabricatorController', 'PhabricatorSystemReadOnlyController' => 'PhabricatorController', 'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow', 'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow', 'PhabricatorSystemRemoveWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorSystemSelectEncodingController' => 'PhabricatorController', 'PhabricatorSystemSelectHighlightController' => 'PhabricatorController', 'PhabricatorTOTPAuthFactor' => 'PhabricatorAuthFactor', 'PhabricatorTOTPAuthFactorTestCase' => 'PhabricatorTestCase', 'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon', 'PhabricatorTestApplication' => 'PhabricatorApplication', 'PhabricatorTestCase' => 'PhutilTestCase', 'PhabricatorTestController' => 'PhabricatorController', 'PhabricatorTestDataGenerator' => 'Phobject', 'PhabricatorTestNoCycleEdgeType' => 'PhabricatorEdgeType', 'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorTestWorker' => 'PhabricatorWorker', 'PhabricatorTextAreaEditField' => 'PhabricatorEditField', 'PhabricatorTextEditField' => 'PhabricatorEditField', 'PhabricatorTime' => 'Phobject', 'PhabricatorTimeFormatSetting' => 'PhabricatorSelectSetting', 'PhabricatorTimeGuard' => 'Phobject', 'PhabricatorTimeTestCase' => 'PhabricatorTestCase', 'PhabricatorTimezoneIgnoreOffsetSetting' => 'PhabricatorInternalSetting', 'PhabricatorTimezoneSetting' => 'PhabricatorOptionGroupSetting', 'PhabricatorTimezoneSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorTitleGlyphsSetting' => 'PhabricatorSelectSetting', 'PhabricatorToken' => array( 'PhabricatorTokenDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorTokenController' => 'PhabricatorController', 'PhabricatorTokenCount' => 'PhabricatorTokenDAO', 'PhabricatorTokenCountQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorTokenDAO' => 'PhabricatorLiskDAO', 'PhabricatorTokenDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorTokenGiveController' => 'PhabricatorTokenController', 'PhabricatorTokenGiven' => array( 'PhabricatorTokenDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorTokenGivenController' => 'PhabricatorTokenController', 'PhabricatorTokenGivenEditor' => 'PhabricatorEditor', 'PhabricatorTokenGivenFeedStory' => 'PhabricatorFeedStory', 'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorTokenLeaderController' => 'PhabricatorTokenController', 'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorTokenReceiverQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorTokenTokenPHIDType' => 'PhabricatorPHIDType', 'PhabricatorTokenUIEventListener' => 'PhabricatorEventListener', 'PhabricatorTokenizerEditField' => 'PhabricatorPHIDListEditField', 'PhabricatorTokensApplication' => 'PhabricatorApplication', 'PhabricatorTokensCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorTokensSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorTokensToken' => array( 'PhabricatorTokenDAO', 'PhabricatorDestructibleInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorTooltipUIExample' => 'PhabricatorUIExample', 'PhabricatorTransactionChange' => 'Phobject', 'PhabricatorTransactionRemarkupChange' => 'PhabricatorTransactionChange', 'PhabricatorTransactions' => 'Phobject', 'PhabricatorTransactionsApplication' => 'PhabricatorApplication', 'PhabricatorTransactionsDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorTransactionsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorTransformedFile' => 'PhabricatorFileDAO', 'PhabricatorTranslationSetting' => 'PhabricatorOptionGroupSetting', 'PhabricatorTranslationsConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorTriggerAction' => 'Phobject', 'PhabricatorTriggerClock' => 'Phobject', 'PhabricatorTriggerClockTestCase' => 'PhabricatorTestCase', 'PhabricatorTriggerDaemon' => 'PhabricatorDaemon', 'PhabricatorTrivialTestCase' => 'PhabricatorTestCase', 'PhabricatorTwitchAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorTwitterAuthProvider' => 'PhabricatorOAuth1AuthProvider', 'PhabricatorTypeaheadApplication' => 'PhabricatorApplication', 'PhabricatorTypeaheadCompositeDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorTypeaheadDatasource' => 'Phobject', 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 'PhabricatorTypeaheadDatasourceTestCase' => 'PhabricatorTestCase', 'PhabricatorTypeaheadFunctionHelpController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadInvalidTokenException' => 'Exception', 'PhabricatorTypeaheadModularDatasourceController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadMonogramDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorTypeaheadResult' => 'Phobject', 'PhabricatorTypeaheadRuntimeCompositeDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorTypeaheadTokenView' => 'AphrontTagView', 'PhabricatorUIConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorUIExample' => 'Phobject', 'PhabricatorUIExampleRenderController' => 'PhabricatorController', 'PhabricatorUIExamplesApplication' => 'PhabricatorApplication', 'PhabricatorUSEnglishTranslation' => 'PhutilTranslation', 'PhabricatorUnifiedDiffsSetting' => 'PhabricatorSelectSetting', 'PhabricatorUnitTestContentSource' => 'PhabricatorContentSource', 'PhabricatorUnitsTestCase' => 'PhabricatorTestCase', 'PhabricatorUnknownContentSource' => 'PhabricatorContentSource', 'PhabricatorUnsubscribedFromObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorUser' => array( 'PhabricatorUserDAO', 'PhutilPerson', 'PhabricatorPolicyInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSSHPublicKeyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFulltextInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField', 'PhabricatorUserCache' => 'PhabricatorUserDAO', 'PhabricatorUserCacheType' => 'Phobject', 'PhabricatorUserCardView' => 'AphrontTagView', 'PhabricatorUserConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorUserConfiguredCustomField' => array( 'PhabricatorUserCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorUserConfiguredCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'PhabricatorUserCustomField' => 'PhabricatorCustomField', 'PhabricatorUserCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'PhabricatorUserCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 'PhabricatorUserEditor' => 'PhabricatorEditor', 'PhabricatorUserEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorUserEmail' => 'PhabricatorUserDAO', 'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase', 'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorUserIconField' => 'PhabricatorUserCustomField', 'PhabricatorUserLog' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorUserLogView' => 'AphrontView', 'PhabricatorUserMessageCountCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserNotificationCountCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorUserPreferences' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorUserPreferencesCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserPreferencesEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorUserPreferencesPHIDType' => 'PhabricatorPHIDType', 'PhabricatorUserPreferencesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorUserPreferencesSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorUserPreferencesTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorUserPreferencesTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorUserProfile' => 'PhabricatorUserDAO', 'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorUserProfileImageCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserRealNameField' => 'PhabricatorUserCustomField', 'PhabricatorUserRolesField' => 'PhabricatorUserCustomField', 'PhabricatorUserSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorUserSinceField' => 'PhabricatorUserCustomField', 'PhabricatorUserStatusField' => 'PhabricatorUserCustomField', 'PhabricatorUserTestCase' => 'PhabricatorTestCase', 'PhabricatorUserTitleField' => 'PhabricatorUserCustomField', 'PhabricatorUserTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorUsersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorUsersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorUsersSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorVCSResponse' => 'AphrontResponse', 'PhabricatorVersionedDraft' => 'PhabricatorDraftDAO', 'PhabricatorVeryWowEnglishTranslation' => 'PhutilTranslation', 'PhabricatorViewerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorWatcherHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorWebContentSource' => 'PhabricatorContentSource', 'PhabricatorWebServerSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorWeekStartDaySetting' => 'PhabricatorSelectSetting', 'PhabricatorWordPressAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorWorker' => 'Phobject', 'PhabricatorWorkerActiveTask' => 'PhabricatorWorkerTask', 'PhabricatorWorkerActiveTaskQuery' => 'PhabricatorWorkerTaskQuery', 'PhabricatorWorkerArchiveTask' => 'PhabricatorWorkerTask', 'PhabricatorWorkerArchiveTaskQuery' => 'PhabricatorWorkerTaskQuery', 'PhabricatorWorkerBulkJob' => array( 'PhabricatorWorkerDAO', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorWorkerBulkJobCreateWorker' => 'PhabricatorWorkerBulkJobWorker', 'PhabricatorWorkerBulkJobEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorWorkerBulkJobPHIDType' => 'PhabricatorPHIDType', 'PhabricatorWorkerBulkJobQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorWorkerBulkJobSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorWorkerBulkJobTaskWorker' => 'PhabricatorWorkerBulkJobWorker', 'PhabricatorWorkerBulkJobTestCase' => 'PhabricatorTestCase', 'PhabricatorWorkerBulkJobTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorWorkerBulkJobTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorWorkerBulkJobType' => 'Phobject', 'PhabricatorWorkerBulkJobWorker' => 'PhabricatorWorker', 'PhabricatorWorkerBulkTask' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO', 'PhabricatorWorkerDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorWorkerLeaseQuery' => 'PhabricatorQuery', 'PhabricatorWorkerManagementCancelWorkflow' => 'PhabricatorWorkerManagementWorkflow', 'PhabricatorWorkerManagementExecuteWorkflow' => 'PhabricatorWorkerManagementWorkflow', 'PhabricatorWorkerManagementFloodWorkflow' => 'PhabricatorWorkerManagementWorkflow', 'PhabricatorWorkerManagementFreeWorkflow' => 'PhabricatorWorkerManagementWorkflow', 'PhabricatorWorkerManagementRetryWorkflow' => 'PhabricatorWorkerManagementWorkflow', 'PhabricatorWorkerManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorWorkerPermanentFailureException' => 'Exception', 'PhabricatorWorkerSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController', 'PhabricatorWorkerTaskQuery' => 'PhabricatorQuery', 'PhabricatorWorkerTestCase' => 'PhabricatorTestCase', 'PhabricatorWorkerTrigger' => array( 'PhabricatorWorkerDAO', 'PhabricatorDestructibleInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorWorkerTriggerEvent' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTriggerManagementFireWorkflow' => 'PhabricatorWorkerTriggerManagementWorkflow', 'PhabricatorWorkerTriggerManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorWorkerTriggerPHIDType' => 'PhabricatorPHIDType', 'PhabricatorWorkerTriggerQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorWorkerYieldException' => 'Exception', 'PhabricatorWorkingCopyDiscoveryTestCase' => 'PhabricatorWorkingCopyTestCase', 'PhabricatorWorkingCopyPullTestCase' => 'PhabricatorWorkingCopyTestCase', 'PhabricatorWorkingCopyTestCase' => 'PhabricatorTestCase', 'PhabricatorXHPASTDAO' => 'PhabricatorLiskDAO', 'PhabricatorXHPASTParseTree' => 'PhabricatorXHPASTDAO', 'PhabricatorXHPASTViewController' => 'PhabricatorController', 'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHProfApplication' => 'PhabricatorApplication', 'PhabricatorXHProfController' => 'PhabricatorController', 'PhabricatorXHProfDAO' => 'PhabricatorLiskDAO', 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileView' => 'AphrontView', 'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO', 'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController', 'PhabricatorYoutubeRemarkupRule' => 'PhutilRemarkupRule', 'Phame404Response' => 'AphrontHTMLResponse', 'PhameBlog' => array( 'PhameDAO', 'PhabricatorPolicyInterface', 'PhabricatorMarkupInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', ), 'PhameBlog404Controller' => 'PhameLiveController', 'PhameBlogArchiveController' => 'PhameBlogController', 'PhameBlogController' => 'PhameController', 'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability', 'PhameBlogDatasource' => 'PhabricatorTypeaheadDatasource', 'PhameBlogEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhameBlogEditController' => 'PhameBlogController', 'PhameBlogEditEngine' => 'PhabricatorEditEngine', 'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor', 'PhameBlogFeedController' => 'PhameBlogController', 'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine', 'PhameBlogHeaderPictureController' => 'PhameBlogController', 'PhameBlogListController' => 'PhameBlogController', 'PhameBlogListView' => 'AphrontTagView', 'PhameBlogManageController' => 'PhameBlogController', 'PhameBlogProfilePictureController' => 'PhameBlogController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhameBlogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhameBlogSite' => 'PhameSite', 'PhameBlogTransaction' => 'PhabricatorApplicationTransaction', 'PhameBlogTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhameBlogViewController' => 'PhameLiveController', 'PhameConstants' => 'Phobject', 'PhameController' => 'PhabricatorController', 'PhameDAO' => 'PhabricatorLiskDAO', 'PhameDescriptionView' => 'AphrontTagView', 'PhameDraftListView' => 'AphrontTagView', 'PhameHomeController' => 'PhamePostController', 'PhameLiveController' => 'PhameController', 'PhameNextPostView' => 'AphrontTagView', 'PhamePost' => array( 'PhameDAO', 'PhabricatorPolicyInterface', 'PhabricatorMarkupInterface', 'PhabricatorFlaggableInterface', 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', ), 'PhamePostArchiveController' => 'PhamePostController', 'PhamePostController' => 'PhameController', 'PhamePostEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhamePostEditController' => 'PhamePostController', 'PhamePostEditEngine' => 'PhabricatorEditEngine', 'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor', 'PhamePostFulltextEngine' => 'PhabricatorFulltextEngine', 'PhamePostHeaderPictureController' => 'PhamePostController', 'PhamePostHistoryController' => 'PhamePostController', 'PhamePostListController' => 'PhamePostController', 'PhamePostListView' => 'AphrontTagView', 'PhamePostMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhamePostMoveController' => 'PhamePostController', 'PhamePostPublishController' => 'PhamePostController', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhamePostRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhamePostSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhamePostTransaction' => 'PhabricatorApplicationTransaction', 'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhamePostViewController' => 'PhameLiveController', 'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhameSite' => 'PhabricatorSite', 'PhluxController' => 'PhabricatorController', 'PhluxDAO' => 'PhabricatorLiskDAO', 'PhluxEditController' => 'PhluxController', 'PhluxListController' => 'PhluxController', 'PhluxTransaction' => 'PhabricatorApplicationTransaction', 'PhluxTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhluxVariable' => array( 'PhluxDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', ), 'PhluxVariableEditor' => 'PhabricatorApplicationTransactionEditor', 'PhluxVariablePHIDType' => 'PhabricatorPHIDType', 'PhluxVariableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhluxViewController' => 'PhluxController', 'PholioController' => 'PhabricatorController', 'PholioDAO' => 'PhabricatorLiskDAO', 'PholioDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PholioDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PholioImage' => array( 'PholioDAO', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', ), 'PholioImagePHIDType' => 'PhabricatorPHIDType', 'PholioImageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PholioImageUploadController' => 'PholioController', 'PholioInlineController' => 'PholioController', 'PholioInlineListController' => 'PholioController', 'PholioMock' => array( 'PholioDAO', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', 'PhabricatorMentionableInterface', 'PhabricatorFulltextInterface', ), 'PholioMockArchiveController' => 'PholioController', 'PholioMockAuthorHeraldField' => 'PholioMockHeraldField', 'PholioMockCommentController' => 'PholioController', 'PholioMockDescriptionHeraldField' => 'PholioMockHeraldField', 'PholioMockEditController' => 'PholioController', 'PholioMockEditor' => 'PhabricatorApplicationTransactionEditor', 'PholioMockEmbedView' => 'AphrontView', 'PholioMockFulltextEngine' => 'PhabricatorFulltextEngine', 'PholioMockHasTaskEdgeType' => 'PhabricatorEdgeType', 'PholioMockHasTaskRelationship' => 'PholioMockRelationship', 'PholioMockHeraldField' => 'HeraldField', 'PholioMockHeraldFieldGroup' => 'HeraldFieldGroup', 'PholioMockImagesView' => 'AphrontView', 'PholioMockListController' => 'PholioController', 'PholioMockMailReceiver' => 'PhabricatorObjectMailReceiver', 'PholioMockNameHeraldField' => 'PholioMockHeraldField', 'PholioMockPHIDType' => 'PhabricatorPHIDType', 'PholioMockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PholioMockRelationship' => 'PhabricatorObjectRelationship', 'PholioMockRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'PholioMockSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PholioMockThumbGridView' => 'AphrontView', 'PholioMockViewController' => 'PholioController', 'PholioRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PholioReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PholioSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PholioTransaction' => 'PhabricatorApplicationTransaction', 'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PholioTransactionView' => 'PhabricatorApplicationTransactionView', 'PholioUploadedImageView' => 'AphrontView', 'PhortuneAccount' => array( 'PhortuneDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhortuneAccountEditController' => 'PhortuneController', 'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortuneAccountHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhortuneAccountListController' => 'PhortuneController', 'PhortuneAccountPHIDType' => 'PhabricatorPHIDType', 'PhortuneAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneAccountTransaction' => 'PhabricatorApplicationTransaction', 'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhortuneAccountViewController' => 'PhortuneController', 'PhortuneAdHocCart' => 'PhortuneCartImplementation', 'PhortuneAdHocProduct' => 'PhortuneProductImplementation', 'PhortuneCart' => array( 'PhortuneDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhortuneCartAcceptController' => 'PhortuneCartController', 'PhortuneCartCancelController' => 'PhortuneCartController', 'PhortuneCartCheckoutController' => 'PhortuneCartController', 'PhortuneCartController' => 'PhortuneController', 'PhortuneCartEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortuneCartImplementation' => 'Phobject', 'PhortuneCartListController' => 'PhortuneController', 'PhortuneCartPHIDType' => 'PhabricatorPHIDType', 'PhortuneCartQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneCartReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhortuneCartSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneCartTransaction' => 'PhabricatorApplicationTransaction', 'PhortuneCartTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhortuneCartUpdateController' => 'PhortuneCartController', 'PhortuneCartViewController' => 'PhortuneCartController', 'PhortuneCharge' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', ), 'PhortuneChargeListController' => 'PhortuneController', 'PhortuneChargePHIDType' => 'PhabricatorPHIDType', 'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneChargeTableView' => 'AphrontView', 'PhortuneConstants' => 'Phobject', 'PhortuneController' => 'PhabricatorController', 'PhortuneCreditCardForm' => 'Phobject', 'PhortuneCurrency' => 'Phobject', 'PhortuneCurrencySerializer' => 'PhabricatorLiskSerializer', 'PhortuneCurrencyTestCase' => 'PhabricatorTestCase', 'PhortuneDAO' => 'PhabricatorLiskDAO', 'PhortuneErrCode' => 'PhortuneConstants', 'PhortuneInvoiceView' => 'AphrontTagView', 'PhortuneLandingController' => 'PhortuneController', 'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType', 'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType', 'PhortuneMerchant' => array( 'PhortuneDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhortuneMerchantCapability' => 'PhabricatorPolicyCapability', 'PhortuneMerchantController' => 'PhortuneController', 'PhortuneMerchantEditController' => 'PhortuneMerchantController', 'PhortuneMerchantEditEngine' => 'PhabricatorEditEngine', 'PhortuneMerchantEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortuneMerchantHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhortuneMerchantInvoiceCreateController' => 'PhortuneMerchantController', 'PhortuneMerchantListController' => 'PhortuneMerchantController', 'PhortuneMerchantPHIDType' => 'PhabricatorPHIDType', 'PhortuneMerchantPictureController' => 'PhortuneMerchantController', 'PhortuneMerchantQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneMerchantSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneMerchantTransaction' => 'PhabricatorApplicationTransaction', 'PhortuneMerchantTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhortuneMerchantViewController' => 'PhortuneMerchantController', 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 'PhortuneOrderTableView' => 'AphrontView', 'PhortunePayPalPaymentProvider' => 'PhortunePaymentProvider', 'PhortunePaymentMethod' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', ), 'PhortunePaymentMethodCreateController' => 'PhortuneController', 'PhortunePaymentMethodDisableController' => 'PhortuneController', 'PhortunePaymentMethodEditController' => 'PhortuneController', 'PhortunePaymentMethodPHIDType' => 'PhabricatorPHIDType', 'PhortunePaymentMethodQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortunePaymentProvider' => 'Phobject', 'PhortunePaymentProviderConfig' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhortunePaymentProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortunePaymentProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortunePaymentProviderConfigTransaction' => 'PhabricatorApplicationTransaction', 'PhortunePaymentProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhortunePaymentProviderPHIDType' => 'PhabricatorPHIDType', 'PhortunePaymentProviderTestCase' => 'PhabricatorTestCase', 'PhortuneProduct' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', ), 'PhortuneProductImplementation' => 'Phobject', 'PhortuneProductListController' => 'PhabricatorController', 'PhortuneProductPHIDType' => 'PhabricatorPHIDType', 'PhortuneProductQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneProductViewController' => 'PhortuneController', 'PhortuneProviderActionController' => 'PhortuneController', 'PhortuneProviderDisableController' => 'PhortuneMerchantController', 'PhortuneProviderEditController' => 'PhortuneMerchantController', 'PhortunePurchase' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', ), 'PhortunePurchasePHIDType' => 'PhabricatorPHIDType', 'PhortunePurchaseQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhortuneStripePaymentProvider' => 'PhortunePaymentProvider', 'PhortuneSubscription' => array( 'PhortuneDAO', 'PhabricatorPolicyInterface', ), 'PhortuneSubscriptionCart' => 'PhortuneCartImplementation', 'PhortuneSubscriptionEditController' => 'PhortuneController', 'PhortuneSubscriptionImplementation' => 'Phobject', 'PhortuneSubscriptionListController' => 'PhortuneController', 'PhortuneSubscriptionPHIDType' => 'PhabricatorPHIDType', 'PhortuneSubscriptionProduct' => 'PhortuneProductImplementation', 'PhortuneSubscriptionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneSubscriptionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneSubscriptionTableView' => 'AphrontView', 'PhortuneSubscriptionViewController' => 'PhortuneController', 'PhortuneSubscriptionWorker' => 'PhabricatorWorker', 'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider', 'PhortuneWePayPaymentProvider' => 'PhortunePaymentProvider', 'PhragmentBrowseController' => 'PhragmentController', 'PhragmentCanCreateCapability' => 'PhabricatorPolicyCapability', 'PhragmentConduitAPIMethod' => 'ConduitAPIMethod', 'PhragmentController' => 'PhabricatorController', 'PhragmentCreateController' => 'PhragmentController', 'PhragmentDAO' => 'PhabricatorLiskDAO', 'PhragmentFragment' => array( 'PhragmentDAO', 'PhabricatorPolicyInterface', ), 'PhragmentFragmentPHIDType' => 'PhabricatorPHIDType', 'PhragmentFragmentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhragmentFragmentVersion' => array( 'PhragmentDAO', 'PhabricatorPolicyInterface', ), 'PhragmentFragmentVersionPHIDType' => 'PhabricatorPHIDType', 'PhragmentFragmentVersionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhragmentGetPatchConduitAPIMethod' => 'PhragmentConduitAPIMethod', 'PhragmentHistoryController' => 'PhragmentController', 'PhragmentPatchController' => 'PhragmentController', 'PhragmentPatchUtil' => 'Phobject', 'PhragmentPolicyController' => 'PhragmentController', 'PhragmentQueryFragmentsConduitAPIMethod' => 'PhragmentConduitAPIMethod', 'PhragmentRevertController' => 'PhragmentController', 'PhragmentSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhragmentSnapshot' => array( 'PhragmentDAO', 'PhabricatorPolicyInterface', ), 'PhragmentSnapshotChild' => array( 'PhragmentDAO', 'PhabricatorPolicyInterface', ), 'PhragmentSnapshotChildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhragmentSnapshotCreateController' => 'PhragmentController', 'PhragmentSnapshotDeleteController' => 'PhragmentController', 'PhragmentSnapshotPHIDType' => 'PhabricatorPHIDType', 'PhragmentSnapshotPromoteController' => 'PhragmentController', 'PhragmentSnapshotQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhragmentSnapshotViewController' => 'PhragmentController', 'PhragmentUpdateController' => 'PhragmentController', 'PhragmentVersionController' => 'PhragmentController', 'PhragmentZIPController' => 'PhragmentController', 'PhrequentConduitAPIMethod' => 'ConduitAPIMethod', 'PhrequentController' => 'PhabricatorController', 'PhrequentCurtainExtension' => 'PHUICurtainExtension', 'PhrequentDAO' => 'PhabricatorLiskDAO', 'PhrequentListController' => 'PhrequentController', 'PhrequentPopConduitAPIMethod' => 'PhrequentConduitAPIMethod', 'PhrequentPushConduitAPIMethod' => 'PhrequentConduitAPIMethod', 'PhrequentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhrequentTimeBlock' => 'Phobject', 'PhrequentTimeBlockTestCase' => 'PhabricatorTestCase', 'PhrequentTimeSlices' => 'Phobject', 'PhrequentTrackController' => 'PhrequentController', 'PhrequentTrackingConduitAPIMethod' => 'PhrequentConduitAPIMethod', 'PhrequentTrackingEditor' => 'PhabricatorEditor', 'PhrequentUIEventListener' => 'PhabricatorEventListener', 'PhrequentUserTime' => array( 'PhrequentDAO', 'PhabricatorPolicyInterface', ), 'PhrequentUserTimeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhrictionChangeType' => 'PhrictionConstants', 'PhrictionConduitAPIMethod' => 'ConduitAPIMethod', 'PhrictionConstants' => 'Phobject', 'PhrictionContent' => array( 'PhrictionDAO', 'PhabricatorMarkupInterface', ), 'PhrictionController' => 'PhabricatorController', 'PhrictionCreateConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionDAO' => 'PhabricatorLiskDAO', 'PhrictionDeleteController' => 'PhrictionController', 'PhrictionDiffController' => 'PhrictionController', 'PhrictionDocument' => array( 'PhrictionDAO', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine', 'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter', 'PhrictionDocumentHeraldField' => 'HeraldField', 'PhrictionDocumentHeraldFieldGroup' => 'HeraldFieldGroup', 'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType', 'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhrictionDocumentStatus' => 'PhrictionConstants', 'PhrictionDocumentTitleHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionEditConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionEditController' => 'PhrictionController', 'PhrictionHistoryConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionHistoryController' => 'PhrictionController', 'PhrictionInfoConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionListController' => 'PhrictionController', 'PhrictionMarkupPreviewController' => 'PhabricatorController', 'PhrictionMoveController' => 'PhrictionController', 'PhrictionNewController' => 'PhrictionController', 'PhrictionRemarkupRule' => 'PhutilRemarkupRule', 'PhrictionReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhrictionSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhrictionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhrictionTransaction' => 'PhabricatorApplicationTransaction', 'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PolicyLockOptionType' => 'PhabricatorConfigJSONOptionType', 'PonderAddAnswerView' => 'AphrontView', 'PonderAnswer' => array( 'PonderDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorDestructibleInterface', ), 'PonderAnswerCommentController' => 'PonderController', 'PonderAnswerEditController' => 'PonderController', 'PonderAnswerEditor' => 'PonderEditor', 'PonderAnswerHistoryController' => 'PonderController', 'PonderAnswerMailReceiver' => 'PhabricatorObjectMailReceiver', 'PonderAnswerPHIDType' => 'PhabricatorPHIDType', 'PonderAnswerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PonderAnswerReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PonderAnswerSaveController' => 'PonderController', 'PonderAnswerStatus' => 'PonderConstants', 'PonderAnswerTransaction' => 'PhabricatorApplicationTransaction', 'PonderAnswerTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderAnswerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PonderAnswerView' => 'AphrontTagView', 'PonderConstants' => 'Phobject', 'PonderController' => 'PhabricatorController', 'PonderDAO' => 'PhabricatorLiskDAO', 'PonderDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PonderEditor' => 'PhabricatorApplicationTransactionEditor', 'PonderFooterView' => 'AphrontTagView', 'PonderModerateCapability' => 'PhabricatorPolicyCapability', 'PonderQuestion' => array( 'PonderDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorMarkupInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', 'PhabricatorFulltextInterface', ), 'PonderQuestionCommentController' => 'PonderController', 'PonderQuestionCreateMailReceiver' => 'PhabricatorMailReceiver', 'PonderQuestionEditController' => 'PonderController', 'PonderQuestionEditor' => 'PonderEditor', 'PonderQuestionFulltextEngine' => 'PhabricatorFulltextEngine', 'PonderQuestionHistoryController' => 'PonderController', 'PonderQuestionListController' => 'PonderController', 'PonderQuestionMailReceiver' => 'PhabricatorObjectMailReceiver', 'PonderQuestionPHIDType' => 'PhabricatorPHIDType', 'PonderQuestionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PonderQuestionReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PonderQuestionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PonderQuestionStatus' => 'PonderConstants', 'PonderQuestionStatusController' => 'PonderController', 'PonderQuestionTransaction' => 'PhabricatorApplicationTransaction', 'PonderQuestionTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderQuestionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PonderQuestionViewController' => 'PonderController', 'PonderRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PonderSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ProjectAddProjectsEmailCommand' => 'MetaMTAEmailTransactionCommand', 'ProjectBoardTaskCard' => 'Phobject', 'ProjectCanLockProjectsCapability' => 'PhabricatorPolicyCapability', 'ProjectConduitAPIMethod' => 'ConduitAPIMethod', 'ProjectCreateConduitAPIMethod' => 'ProjectConduitAPIMethod', 'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability', 'ProjectDefaultEditCapability' => 'PhabricatorPolicyCapability', 'ProjectDefaultJoinCapability' => 'PhabricatorPolicyCapability', 'ProjectDefaultViewCapability' => 'PhabricatorPolicyCapability', 'ProjectEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod', 'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ProjectRemarkupRuleTestCase' => 'PhabricatorTestCase', 'ProjectReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'ProjectSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'QueryFormattingTestCase' => 'PhabricatorTestCase', 'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification', 'ReleephBranch' => array( 'ReleephDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'ReleephBranchAccessController' => 'ReleephBranchController', 'ReleephBranchCommitFieldSpecification' => 'ReleephFieldSpecification', 'ReleephBranchController' => 'ReleephController', 'ReleephBranchCreateController' => 'ReleephProductController', 'ReleephBranchEditController' => 'ReleephBranchController', 'ReleephBranchEditor' => 'PhabricatorEditor', 'ReleephBranchHistoryController' => 'ReleephBranchController', 'ReleephBranchNamePreviewController' => 'ReleephController', 'ReleephBranchPHIDType' => 'PhabricatorPHIDType', 'ReleephBranchPreviewView' => 'AphrontFormControl', 'ReleephBranchQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ReleephBranchSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ReleephBranchTemplate' => 'Phobject', 'ReleephBranchTransaction' => 'PhabricatorApplicationTransaction', 'ReleephBranchTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ReleephBranchViewController' => 'ReleephBranchController', 'ReleephCommitFinder' => 'Phobject', 'ReleephCommitFinderException' => 'Exception', 'ReleephCommitMessageFieldSpecification' => 'ReleephFieldSpecification', 'ReleephConduitAPIMethod' => 'ConduitAPIMethod', 'ReleephController' => 'PhabricatorController', 'ReleephDAO' => 'PhabricatorLiskDAO', 'ReleephDefaultFieldSelector' => 'ReleephFieldSelector', 'ReleephDependsOnFieldSpecification' => 'ReleephFieldSpecification', 'ReleephDiffChurnFieldSpecification' => 'ReleephFieldSpecification', 'ReleephDiffMessageFieldSpecification' => 'ReleephFieldSpecification', 'ReleephDiffSizeFieldSpecification' => 'ReleephFieldSpecification', 'ReleephFieldParseException' => 'Exception', 'ReleephFieldSelector' => 'Phobject', 'ReleephFieldSpecification' => array( 'PhabricatorCustomField', 'PhabricatorMarkupInterface', ), 'ReleephGetBranchesConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephIntentFieldSpecification' => 'ReleephFieldSpecification', 'ReleephLevelFieldSpecification' => 'ReleephFieldSpecification', 'ReleephOriginalCommitFieldSpecification' => 'ReleephFieldSpecification', 'ReleephProductActionController' => 'ReleephProductController', 'ReleephProductController' => 'ReleephController', 'ReleephProductCreateController' => 'ReleephProductController', 'ReleephProductEditController' => 'ReleephProductController', 'ReleephProductEditor' => 'PhabricatorApplicationTransactionEditor', 'ReleephProductHistoryController' => 'ReleephProductController', 'ReleephProductListController' => 'ReleephController', 'ReleephProductPHIDType' => 'PhabricatorPHIDType', 'ReleephProductQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ReleephProductSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ReleephProductTransaction' => 'PhabricatorApplicationTransaction', 'ReleephProductTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ReleephProductViewController' => 'ReleephProductController', 'ReleephProject' => array( 'ReleephDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'ReleephQueryBranchesConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephQueryProductsConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephQueryRequestsConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephReasonFieldSpecification' => 'ReleephFieldSpecification', 'ReleephRequest' => array( 'ReleephDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorCustomFieldInterface', ), 'ReleephRequestActionController' => 'ReleephRequestController', 'ReleephRequestCommentController' => 'ReleephRequestController', 'ReleephRequestConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephRequestController' => 'ReleephController', 'ReleephRequestDifferentialCreateController' => 'ReleephController', 'ReleephRequestEditController' => 'ReleephBranchController', 'ReleephRequestMailReceiver' => 'PhabricatorObjectMailReceiver', 'ReleephRequestPHIDType' => 'PhabricatorPHIDType', 'ReleephRequestQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ReleephRequestReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'ReleephRequestSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ReleephRequestStatus' => 'Phobject', 'ReleephRequestTransaction' => 'PhabricatorApplicationTransaction', 'ReleephRequestTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ReleephRequestTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ReleephRequestTransactionalEditor' => 'PhabricatorApplicationTransactionEditor', 'ReleephRequestTypeaheadControl' => 'AphrontFormControl', 'ReleephRequestTypeaheadController' => 'PhabricatorTypeaheadDatasourceController', 'ReleephRequestView' => 'AphrontView', 'ReleephRequestViewController' => 'ReleephBranchController', 'ReleephRequestorFieldSpecification' => 'ReleephFieldSpecification', 'ReleephRevisionFieldSpecification' => 'ReleephFieldSpecification', 'ReleephSeverityFieldSpecification' => 'ReleephLevelFieldSpecification', 'ReleephSummaryFieldSpecification' => 'ReleephFieldSpecification', 'ReleephWorkCanPushConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkGetAuthorInfoConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkGetBranchCommitMessageConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkGetBranchConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkGetCommitMessageConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkNextRequestConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkRecordConduitAPIMethod' => 'ReleephConduitAPIMethod', 'ReleephWorkRecordPickStatusConduitAPIMethod' => 'ReleephConduitAPIMethod', 'RemarkupProcessConduitAPIMethod' => 'ConduitAPIMethod', 'RepositoryConduitAPIMethod' => 'ConduitAPIMethod', 'RepositoryQueryConduitAPIMethod' => 'RepositoryConduitAPIMethod', 'ShellLogView' => 'AphrontView', 'SlowvoteConduitAPIMethod' => 'ConduitAPIMethod', 'SlowvoteEmbedView' => 'AphrontView', 'SlowvoteInfoConduitAPIMethod' => 'SlowvoteConduitAPIMethod', 'SlowvoteRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'SubscriptionListDialogBuilder' => 'Phobject', 'SubscriptionListStringBuilder' => 'Phobject', 'TokenConduitAPIMethod' => 'ConduitAPIMethod', 'TokenGiveConduitAPIMethod' => 'TokenConduitAPIMethod', 'TokenGivenConduitAPIMethod' => 'TokenConduitAPIMethod', 'TokenQueryConduitAPIMethod' => 'TokenConduitAPIMethod', 'UserConduitAPIMethod' => 'ConduitAPIMethod', 'UserDisableConduitAPIMethod' => 'UserConduitAPIMethod', 'UserEnableConduitAPIMethod' => 'UserConduitAPIMethod', 'UserFindConduitAPIMethod' => 'UserConduitAPIMethod', 'UserQueryConduitAPIMethod' => 'UserConduitAPIMethod', 'UserSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'UserWhoAmIConduitAPIMethod' => 'UserConduitAPIMethod', ), )); diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php index aee2c63032..e7b3b85c63 100644 --- a/src/aphront/configuration/AphrontApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontApplicationConfiguration.php @@ -1,730 +1,719 @@ request = $request; return $this; } final public function getRequest() { return $this->request; } final public function getConsole() { return $this->console; } final public function setConsole($console) { $this->console = $console; return $this; } final public function setHost($host) { $this->host = $host; return $this; } final public function getHost() { return $this->host; } final public function setPath($path) { $this->path = $path; return $this; } final public function getPath() { return $this->path; } public function willBuildRequest() {} /** * @phutil-external-symbol class PhabricatorStartup */ public static function runHTTPRequest(AphrontHTTPSink $sink) { if (isset($_SERVER['HTTP_X_PHABRICATOR_SELFCHECK'])) { $response = self::newSelfCheckResponse(); return self::writeResponse($sink, $response); } PhabricatorStartup::beginStartupPhase('multimeter'); $multimeter = MultimeterControl::newInstance(); $multimeter->setEventContext(''); $multimeter->setEventViewer(''); // Build a no-op write guard for the setup phase. We'll replace this with a // real write guard later on, but we need to survive setup and build a // request object first. $write_guard = new AphrontWriteGuard('id'); PhabricatorStartup::beginStartupPhase('preflight'); $response = PhabricatorSetupCheck::willPreflightRequest(); if ($response) { return self::writeResponse($sink, $response); } PhabricatorStartup::beginStartupPhase('env.init'); try { PhabricatorEnv::initializeWebEnvironment(); $database_exception = null; } catch (PhabricatorClusterStrandedException $ex) { $database_exception = $ex; } if ($database_exception) { $issue = PhabricatorSetupIssue::newDatabaseConnectionIssue( $database_exception, true); $response = PhabricatorSetupCheck::newIssueResponse($issue); return self::writeResponse($sink, $response); } $multimeter->setSampleRate( PhabricatorEnv::getEnvConfig('debug.sample-rate')); $debug_time_limit = PhabricatorEnv::getEnvConfig('debug.time-limit'); if ($debug_time_limit) { PhabricatorStartup::setDebugTimeLimit($debug_time_limit); } // This is the earliest we can get away with this, we need env config first. PhabricatorStartup::beginStartupPhase('log.access'); PhabricatorAccessLog::init(); $access_log = PhabricatorAccessLog::getLog(); PhabricatorStartup::setAccessLog($access_log); $address = PhabricatorEnv::getRemoteAddress(); if ($address) { $address_string = $address->getAddress(); } else { $address_string = '-'; } $access_log->setData( array( 'R' => AphrontRequest::getHTTPHeader('Referer', '-'), 'r' => $address_string, 'M' => idx($_SERVER, 'REQUEST_METHOD', '-'), )); DarkConsoleXHProfPluginAPI::hookProfiler(); // We just activated the profiler, so we don't need to keep track of // startup phases anymore: it can take over from here. PhabricatorStartup::beginStartupPhase('startup.done'); DarkConsoleErrorLogPluginAPI::registerErrorHandler(); $response = PhabricatorSetupCheck::willProcessRequest(); if ($response) { return self::writeResponse($sink, $response); } $host = AphrontRequest::getHTTPHeader('Host'); $path = $_REQUEST['__path__']; switch ($host) { default: $config_key = 'aphront.default-application-configuration-class'; $application = PhabricatorEnv::newObjectFromConfig($config_key); break; } $application->setHost($host); $application->setPath($path); $application->willBuildRequest(); $request = $application->buildRequest(); // Now that we have a request, convert the write guard into one which // actually checks CSRF tokens. $write_guard->dispose(); $write_guard = new AphrontWriteGuard(array($request, 'validateCSRF')); // Build the server URI implied by the request headers. If an administrator // has not configured "phabricator.base-uri" yet, we'll use this to generate // links. $request_protocol = ($request->isHTTPS() ? 'https' : 'http'); $request_base_uri = "{$request_protocol}://{$host}/"; PhabricatorEnv::setRequestBaseURI($request_base_uri); $access_log->setData( array( 'U' => (string)$request->getRequestURI()->getPath(), )); $processing_exception = null; try { $response = $application->processRequest( $request, $access_log, $sink, $multimeter); $response_code = $response->getHTTPResponseCode(); } catch (Exception $ex) { $processing_exception = $ex; $response_code = 500; } $write_guard->dispose(); $access_log->setData( array( 'c' => $response_code, 'T' => PhabricatorStartup::getMicrosecondsSinceStart(), )); $multimeter->newEvent( MultimeterEvent::TYPE_REQUEST_TIME, $multimeter->getEventContext(), PhabricatorStartup::getMicrosecondsSinceStart()); $access_log->write(); $multimeter->saveEvents(); DarkConsoleXHProfPluginAPI::saveProfilerSample($access_log); // Add points to the rate limits for this request. if (isset($_SERVER['REMOTE_ADDR'])) { $user_ip = $_SERVER['REMOTE_ADDR']; // The base score for a request allows users to make 30 requests per // minute. $score = (1000 / 30); // If the user was logged in, let them make more requests. if ($request->getUser() && $request->getUser()->getPHID()) { $score = $score / 5; } PhabricatorStartup::addRateLimitScore($user_ip, $score); } if ($processing_exception) { throw $processing_exception; } } public function processRequest( AphrontRequest $request, PhutilDeferredLog $access_log, AphrontHTTPSink $sink, MultimeterControl $multimeter) { $this->setRequest($request); list($controller, $uri_data) = $this->buildController(); $controller_class = get_class($controller); $access_log->setData( array( 'C' => $controller_class, )); $multimeter->setEventContext('web.'.$controller_class); $request->setController($controller); $request->setURIMap($uri_data); $controller->setRequest($request); // If execution throws an exception and then trying to render that // exception throws another exception, we want to show the original // exception, as it is likely the root cause of the rendering exception. $original_exception = null; try { $response = $controller->willBeginExecution(); if ($request->getUser() && $request->getUser()->getPHID()) { $access_log->setData( array( 'u' => $request->getUser()->getUserName(), 'P' => $request->getUser()->getPHID(), )); $multimeter->setEventViewer('user.'.$request->getUser()->getPHID()); } if (!$response) { $controller->willProcessRequest($uri_data); $response = $controller->handleRequest($request); $this->validateControllerResponse($controller, $response); } } catch (Exception $ex) { $original_exception = $ex; $response = $this->handleException($ex); } try { $response = $this->produceResponse($request, $response); $response = $controller->willSendResponse($response); $response->setRequest($request); self::writeResponse($sink, $response); } catch (Exception $ex) { if ($original_exception) { throw $original_exception; } throw $ex; } return $response; } private static function writeResponse( AphrontHTTPSink $sink, AphrontResponse $response) { $unexpected_output = PhabricatorStartup::endOutputCapture(); if ($unexpected_output) { $unexpected_output = pht( "Unexpected output:\n\n%s", $unexpected_output); phlog($unexpected_output); if ($response instanceof AphrontWebpageResponse) { - echo phutil_tag( - 'div', - array( - 'style' => - 'background: #eeddff;'. - 'white-space: pre-wrap;'. - 'z-index: 200000;'. - 'position: relative;'. - 'padding: 8px;'. - 'font-family: monospace', - ), - $unexpected_output); + $response->setUnexpectedOutput($unexpected_output); } } $sink->writeResponse($response); } /* -( URI Routing )-------------------------------------------------------- */ /** * Build a controller to respond to the request. * * @return pair Controller and dictionary of request * parameters. * @task routing */ final private function buildController() { $request = $this->getRequest(); // If we're configured to operate in cluster mode, reject requests which // were not received on a cluster interface. // // For example, a host may have an internal address like "170.0.0.1", and // also have a public address like "51.23.95.16". Assuming the cluster // is configured on a range like "170.0.0.0/16", we want to reject the // requests received on the public interface. // // Ideally, nodes in a cluster should only be listening on internal // interfaces, but they may be configured in such a way that they also // listen on external interfaces, since this is easy to forget about or // get wrong. As a broad security measure, reject requests received on any // interfaces which aren't on the whitelist. $cluster_addresses = PhabricatorEnv::getEnvConfig('cluster.addresses'); if ($cluster_addresses) { $server_addr = idx($_SERVER, 'SERVER_ADDR'); if (!$server_addr) { if (php_sapi_name() == 'cli') { // This is a command line script (probably something like a unit // test) so it's fine that we don't have SERVER_ADDR defined. } else { throw new AphrontMalformedRequestException( pht('No %s', 'SERVER_ADDR'), pht( 'Phabricator is configured to operate in cluster mode, but '. '%s is not defined in the request context. Your webserver '. 'configuration needs to forward %s to PHP so Phabricator can '. 'reject requests received on external interfaces.', 'SERVER_ADDR', 'SERVER_ADDR')); } } else { if (!PhabricatorEnv::isClusterAddress($server_addr)) { throw new AphrontMalformedRequestException( pht('External Interface'), pht( 'Phabricator is configured in cluster mode and the address '. 'this request was received on ("%s") is not whitelisted as '. 'a cluster address.', $server_addr)); } } } $site = $this->buildSiteForRequest($request); if ($site->shouldRequireHTTPS()) { if (!$request->isHTTPS()) { // Don't redirect intracluster requests: doing so drops headers and // parameters, imposes a performance penalty, and indicates a // misconfiguration. if ($request->isProxiedClusterRequest()) { throw new AphrontMalformedRequestException( pht('HTTPS Required'), pht( 'This request reached a site which requires HTTPS, but the '. 'request is not marked as HTTPS.')); } $https_uri = $request->getRequestURI(); $https_uri->setDomain($request->getHost()); $https_uri->setProtocol('https'); // In this scenario, we'll be redirecting to HTTPS using an absolute // URI, so we need to permit an external redirect. return $this->buildRedirectController($https_uri, true); } } $maps = $site->getRoutingMaps(); $path = $request->getPath(); $result = $this->routePath($maps, $path); if ($result) { return $result; } // If we failed to match anything but don't have a trailing slash, try // to add a trailing slash and issue a redirect if that resolves. // NOTE: We only do this for GET, since redirects switch to GET and drop // data like POST parameters. if (!preg_match('@/$@', $path) && $request->isHTTPGet()) { $result = $this->routePath($maps, $path.'/'); if ($result) { $target_uri = $request->getAbsoluteRequestURI(); // We need to restore URI encoding because the webserver has // interpreted it. For example, this allows us to redirect a path // like `/tag/aa%20bb` to `/tag/aa%20bb/`, which may eventually be // resolved meaningfully by an application. $target_path = phutil_escape_uri($path.'/'); $target_uri->setPath($target_path); $target_uri = (string)$target_uri; return $this->buildRedirectController($target_uri, true); } } $result = $site->new404Controller($request); if ($result) { return array($result, array()); } return $this->build404Controller(); } /** * Map a specific path to the corresponding controller. For a description * of routing, see @{method:buildController}. * * @param list List of routing maps. * @param string Path to route. * @return pair Controller and dictionary of request * parameters. * @task routing */ private function routePath(array $maps, $path) { foreach ($maps as $map) { $result = $map->routePath($path); if ($result) { return array($result->getController(), $result->getURIData()); } } } private function buildSiteForRequest(AphrontRequest $request) { $sites = PhabricatorSite::getAllSites(); $site = null; foreach ($sites as $candidate) { $site = $candidate->newSiteForRequest($request); if ($site) { break; } } if (!$site) { $path = $request->getPath(); $host = $request->getHost(); throw new AphrontMalformedRequestException( pht('Site Not Found'), pht( 'This request asked for "%s" on host "%s", but no site is '. 'configured which can serve this request.', $path, $host), true); } $request->setSite($site); return $site; } /* -( Response Handling )-------------------------------------------------- */ /** * Tests if a response is of a valid type. * * @param wild Supposedly valid response. * @return bool True if the object is of a valid type. * @task response */ private function isValidResponseObject($response) { if ($response instanceof AphrontResponse) { return true; } if ($response instanceof AphrontResponseProducerInterface) { return true; } return false; } /** * Verifies that the return value from an @{class:AphrontController} is * of an allowed type. * * @param AphrontController Controller which returned the response. * @param wild Supposedly valid response. * @return void * @task response */ private function validateControllerResponse( AphrontController $controller, $response) { if ($this->isValidResponseObject($response)) { return; } throw new Exception( pht( 'Controller "%s" returned an invalid response from call to "%s". '. 'This method must return an object of class "%s", or an object '. 'which implements the "%s" interface.', get_class($controller), 'handleRequest()', 'AphrontResponse', 'AphrontResponseProducerInterface')); } /** * Verifies that the return value from an * @{class:AphrontResponseProducerInterface} is of an allowed type. * * @param AphrontResponseProducerInterface Object which produced * this response. * @param wild Supposedly valid response. * @return void * @task response */ private function validateProducerResponse( AphrontResponseProducerInterface $producer, $response) { if ($this->isValidResponseObject($response)) { return; } throw new Exception( pht( 'Producer "%s" returned an invalid response from call to "%s". '. 'This method must return an object of class "%s", or an object '. 'which implements the "%s" interface.', get_class($producer), 'produceAphrontResponse()', 'AphrontResponse', 'AphrontResponseProducerInterface')); } /** * Verifies that the return value from an * @{class:AphrontRequestExceptionHandler} is of an allowed type. * * @param AphrontRequestExceptionHandler Object which produced this * response. * @param wild Supposedly valid response. * @return void * @task response */ private function validateErrorHandlerResponse( AphrontRequestExceptionHandler $handler, $response) { if ($this->isValidResponseObject($response)) { return; } throw new Exception( pht( 'Exception handler "%s" returned an invalid response from call to '. '"%s". This method must return an object of class "%s", or an object '. 'which implements the "%s" interface.', get_class($handler), 'handleRequestException()', 'AphrontResponse', 'AphrontResponseProducerInterface')); } /** * Resolves a response object into an @{class:AphrontResponse}. * * Controllers are permitted to return actual responses of class * @{class:AphrontResponse}, or other objects which implement * @{interface:AphrontResponseProducerInterface} and can produce a response. * * If a controller returns a response producer, invoke it now and produce * the real response. * * @param AphrontRequest Request being handled. * @param AphrontResponse|AphrontResponseProducerInterface Response, or * response producer. * @return AphrontResponse Response after any required production. * @task response */ private function produceResponse(AphrontRequest $request, $response) { $original = $response; // Detect cycles on the exact same objects. It's still possible to produce // infinite responses as long as they're all unique, but we can only // reasonably detect cycles, not guarantee that response production halts. $seen = array(); while (true) { // NOTE: It is permissible for an object to be both a response and a // response producer. If so, being a producer is "stronger". This is // used by AphrontProxyResponse. // If this response is a valid response, hand over the request first. if ($response instanceof AphrontResponse) { $response->setRequest($request); } // If this isn't a producer, we're all done. if (!($response instanceof AphrontResponseProducerInterface)) { break; } $hash = spl_object_hash($response); if (isset($seen[$hash])) { throw new Exception( pht( 'Failure while producing response for object of class "%s": '. 'encountered production cycle (identical object, of class "%s", '. 'was produced twice).', get_class($original), get_class($response))); } $seen[$hash] = true; $new_response = $response->produceAphrontResponse(); $this->validateProducerResponse($response, $new_response); $response = $new_response; } return $response; } /* -( Error Handling )----------------------------------------------------- */ /** * Convert an exception which has escaped the controller into a response. * * This method delegates exception handling to available subclasses of * @{class:AphrontRequestExceptionHandler}. * * @param Exception Exception which needs to be handled. * @return wild Response or response producer, or null if no available * handler can produce a response. * @task exception */ private function handleException(Exception $ex) { $handlers = AphrontRequestExceptionHandler::getAllHandlers(); $request = $this->getRequest(); foreach ($handlers as $handler) { if ($handler->canHandleRequestException($request, $ex)) { $response = $handler->handleRequestException($request, $ex); $this->validateErrorHandlerResponse($handler, $response); return $response; } } throw $ex; } private static function newSelfCheckResponse() { $path = idx($_REQUEST, '__path__', ''); $query = idx($_SERVER, 'QUERY_STRING', ''); $pairs = id(new PhutilQueryStringParser()) ->parseQueryStringToPairList($query); $params = array(); foreach ($pairs as $v) { $params[] = array( 'name' => $v[0], 'value' => $v[1], ); } $result = array( 'path' => $path, 'params' => $params, 'user' => idx($_SERVER, 'PHP_AUTH_USER'), 'pass' => idx($_SERVER, 'PHP_AUTH_PW'), // This just makes sure that the response compresses well, so reasonable // algorithms should want to gzip or deflate it. 'filler' => str_repeat('Q', 1024 * 16), ); return id(new AphrontJSONResponse()) ->setAddJSONShield(false) ->setContent($result); } } diff --git a/src/aphront/response/AphrontWebpageResponse.php b/src/aphront/response/AphrontWebpageResponse.php index bda0d94244..de642f9b19 100644 --- a/src/aphront/response/AphrontWebpageResponse.php +++ b/src/aphront/response/AphrontWebpageResponse.php @@ -1,16 +1,48 @@ content = $content; return $this; } + public function setUnexpectedOutput($unexpected_output) { + $this->unexpectedOutput = $unexpected_output; + return $this; + } + + public function getUnexpectedOutput() { + return $this->unexpectedOutput; + } + public function buildResponseString() { - return hsprintf('%s', $this->content); + $unexpected_output = $this->getUnexpectedOutput(); + if (strlen($unexpected_output)) { + $style = array( + 'background: linear-gradient(180deg, #eeddff, #ddbbff);', + 'white-space: pre-wrap;', + 'z-index: 200000;', + 'position: relative;', + 'padding: 16px;', + 'font-family: monospace;', + 'text-shadow: 1px 1px 1px white;', + ); + + $unexpected_header = phutil_tag( + 'div', + array( + 'style' => implode(' ', $style), + ), + $unexpected_output); + } else { + $unexpected_header = ''; + } + + return hsprintf('%s%s', $unexpected_header, $this->content); } } diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 89a3c6cb7a..23a759d2aa 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -1,646 +1,646 @@ pht('Core Applications'), self::GROUP_UTILITIES => pht('Utilities'), self::GROUP_ADMIN => pht('Administration'), self::GROUP_DEVELOPER => pht('Developer Tools'), ); } /* -( Application Information )-------------------------------------------- */ abstract public function getName(); public function getShortDescription() { return pht('%s Application', $this->getName()); } final public function isInstalled() { if (!$this->canUninstall()) { return true; } $prototypes = PhabricatorEnv::getEnvConfig('phabricator.show-prototypes'); if (!$prototypes && $this->isPrototype()) { return false; } $uninstalled = PhabricatorEnv::getEnvConfig( 'phabricator.uninstalled-applications'); return empty($uninstalled[get_class($this)]); } public function isPrototype() { return false; } /** * Return `true` if this application should never appear in application lists * in the UI. Primarily intended for unit test applications or other * pseudo-applications. * * Few applications should be unlisted. For most applications, use * @{method:isLaunchable} to hide them from main launch views instead. * * @return bool True to remove application from UI lists. */ public function isUnlisted() { return false; } /** * Return `true` if this application is a normal application with a base * URI and a web interface. * * Launchable applications can be pinned to the home page, and show up in the * "Launcher" view of the Applications application. Making an application * unlauncahble prevents pinning and hides it from this view. * * Usually, an application should be marked unlaunchable if: * * - it is available on every page anyway (like search); or * - it does not have a web interface (like subscriptions); or * - it is still pre-release and being intentionally buried. * * To hide applications more completely, use @{method:isUnlisted}. * * @return bool True if the application is launchable. */ public function isLaunchable() { return true; } /** * Return `true` if this application should be pinned by default. * * Users who have not yet set preferences see a default list of applications. * * @param PhabricatorUser User viewing the pinned application list. * @return bool True if this application should be pinned by default. */ public function isPinnedByDefault(PhabricatorUser $viewer) { return false; } /** * Returns true if an application is first-party (developed by Phacility) * and false otherwise. * * @return bool True if this application is developed by Phacility. */ final public function isFirstParty() { $where = id(new ReflectionClass($this))->getFileName(); $root = phutil_get_library_root('phabricator'); if (!Filesystem::isDescendant($where, $root)) { return false; } if (Filesystem::isDescendant($where, $root.'/extensions')) { return false; } return true; } public function canUninstall() { return true; } final public function getPHID() { return 'PHID-APPS-'.get_class($this); } public function getTypeaheadURI() { return $this->isLaunchable() ? $this->getBaseURI() : null; } public function getBaseURI() { return null; } final public function getApplicationURI($path = '') { return $this->getBaseURI().ltrim($path, '/'); } public function getIcon() { return 'fa-puzzle-piece'; } public function getApplicationOrder() { return PHP_INT_MAX; } public function getApplicationGroup() { return self::GROUP_CORE; } public function getTitleGlyph() { return null; } final public function getHelpMenuItems(PhabricatorUser $viewer) { $items = array(); $articles = $this->getHelpDocumentationArticles($viewer); if ($articles) { $items[] = id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_LABEL) ->setName(pht('%s Documentation', $this->getName())); foreach ($articles as $article) { $item = id(new PHUIListItemView()) ->setName($article['name']) ->setIcon('fa-book') ->setHref($article['href']) ->setOpenInNewWindow(true); $items[] = $item; } } $command_specs = $this->getMailCommandObjects(); if ($command_specs) { $items[] = id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_LABEL) ->setName(pht('Email Help')); foreach ($command_specs as $key => $spec) { $object = $spec['object']; $class = get_class($this); $href = '/applications/mailcommands/'.$class.'/'.$key.'/'; $item = id(new PHUIListItemView()) ->setName($spec['name']) ->setIcon('fa-envelope-o') ->setHref($href) ->setOpenInNewWindow(true); $items[] = $item; } } return $items; } public function getHelpDocumentationArticles(PhabricatorUser $viewer) { return array(); } public function getOverview() { return null; } public function getEventListeners() { return array(); } public function getRemarkupRules() { return array(); } public function getQuicksandURIPatternBlacklist() { return array(); } public function getMailCommandObjects() { return array(); } /* -( URI Routing )-------------------------------------------------------- */ public function getRoutes() { return array(); } public function getResourceRoutes() { return array(); } /* -( Email Integration )-------------------------------------------------- */ public function supportsEmailIntegration() { return false; } final protected function getInboundEmailSupportLink() { return PhabricatorEnv::getDocLink('Configuring Inbound Email'); } public function getAppEmailBlurb() { throw new PhutilMethodNotImplementedException(); } /* -( Fact Integration )--------------------------------------------------- */ public function getFactObjectsForAnalysis() { return array(); } /* -( UI Integration )----------------------------------------------------- */ /** * Render status elements (like "3 Waiting Reviews") for application list * views. These provide a way to alert users to new or pending action items * in applications. * * @param PhabricatorUser Viewing user. * @return list Application status elements. * @task ui */ public function loadStatus(PhabricatorUser $user) { return array(); } /** * You can provide an optional piece of flavor text for the application. This * is currently rendered in application launch views if the application has no * status elements. * * @return string|null Flavor text. * @task ui */ public function getFlavorText() { return null; } /** * Build items for the main menu. * * @param PhabricatorUser The viewing user. * @param AphrontController The current controller. May be null for special * pages like 404, exception handlers, etc. * @return list List of menu items. * @task ui */ public function buildMainMenuItems( PhabricatorUser $user, PhabricatorController $controller = null) { return array(); } /** * Build extra items for the main menu. Generally, this is used to render * static dropdowns. * * @param PhabricatorUser The viewing user. * @param AphrontController The current controller. May be null for special * pages like 404, exception handlers, etc. * @return view List of menu items. * @task ui */ public function buildMainMenuExtraNodes( PhabricatorUser $viewer, PhabricatorController $controller = null) { return array(); } /* -( Application Management )--------------------------------------------- */ final public static function getByClass($class_name) { $selected = null; $applications = self::getAllApplications(); foreach ($applications as $application) { if (get_class($application) == $class_name) { $selected = $application; break; } } if (!$selected) { throw new Exception(pht("No application '%s'!", $class_name)); } return $selected; } final public static function getAllApplications() { static $applications; if ($applications === null) { $apps = id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) ->setSortMethod('getApplicationOrder') ->execute(); // Reorder the applications into "application order". Notably, this // ensures their event handlers register in application order. $apps = mgroup($apps, 'getApplicationGroup'); $group_order = array_keys(self::getApplicationGroups()); $apps = array_select_keys($apps, $group_order) + $apps; $apps = array_mergev($apps); $applications = $apps; } return $applications; } final public static function getAllInstalledApplications() { $all_applications = self::getAllApplications(); $apps = array(); foreach ($all_applications as $app) { if (!$app->isInstalled()) { continue; } $apps[] = $app; } return $apps; } /** * Determine if an application is installed, by application class name. * * To check if an application is installed //and// available to a particular * viewer, user @{method:isClassInstalledForViewer}. * * @param string Application class name. * @return bool True if the class is installed. * @task meta */ final public static function isClassInstalled($class) { return self::getByClass($class)->isInstalled(); } /** * Determine if an application is installed and available to a viewer, by * application class name. * * To check if an application is installed at all, use * @{method:isClassInstalled}. * * @param string Application class name. * @param PhabricatorUser Viewing user. * @return bool True if the class is installed for the viewer. * @task meta */ final public static function isClassInstalledForViewer( $class, PhabricatorUser $viewer) { if ($viewer->isOmnipotent()) { return true; } $cache = PhabricatorCaches::getRequestCache(); $viewer_phid = $viewer->getPHID(); $key = 'app.'.$class.'.installed.'.$viewer_phid; $result = $cache->getKey($key); if ($result === null) { if (!self::isClassInstalled($class)) { $result = false; } else { $application = self::getByClass($class); if (!$application->canUninstall()) { // If the application can not be uninstalled, always allow viewers // to see it. In particular, this allows logged-out viewers to see // Settings and load global default settings even if the install // does not allow public viewers. $result = true; } else { $result = PhabricatorPolicyFilter::hasCapability( $viewer, self::getByClass($class), PhabricatorPolicyCapability::CAN_VIEW); } } $cache->setKey($key, $result); } return $result; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array_merge( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ), array_keys($this->getCustomCapabilities())); } public function getPolicy($capability) { $default = $this->getCustomPolicySetting($capability); if ($default) { return $default; } switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return PhabricatorPolicies::getMostOpenPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return PhabricatorPolicies::POLICY_ADMIN; default: $spec = $this->getCustomCapabilitySpecification($capability); return idx($spec, 'default', PhabricatorPolicies::POLICY_USER); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } /* -( Policies )----------------------------------------------------------- */ protected function getCustomCapabilities() { return array(); } final private function getCustomPolicySetting($capability) { if (!$this->isCapabilityEditable($capability)) { return null; } $policy_locked = PhabricatorEnv::getEnvConfig('policy.locked'); if (isset($policy_locked[$capability])) { return $policy_locked[$capability]; } $config = PhabricatorEnv::getEnvConfig('phabricator.application-settings'); $app = idx($config, $this->getPHID()); if (!$app) { return null; } $policy = idx($app, 'policy'); if (!$policy) { return null; } return idx($policy, $capability); } final private function getCustomCapabilitySpecification($capability) { $custom = $this->getCustomCapabilities(); if (!isset($custom[$capability])) { throw new Exception(pht("Unknown capability '%s'!", $capability)); } return $custom[$capability]; } final public function getCapabilityLabel($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return pht('Can Use Application'); case PhabricatorPolicyCapability::CAN_EDIT: return pht('Can Configure Application'); } $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability); if ($capobj) { return $capobj->getCapabilityName(); } return null; } final public function isCapabilityEditable($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->canUninstall(); case PhabricatorPolicyCapability::CAN_EDIT: return false; default: $spec = $this->getCustomCapabilitySpecification($capability); return idx($spec, 'edit', true); } } final public function getCapabilityCaption($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: if (!$this->canUninstall()) { return pht( 'This application is required for Phabricator to operate, so all '. 'users must have access to it.'); } else { return null; } case PhabricatorPolicyCapability::CAN_EDIT: return null; default: $spec = $this->getCustomCapabilitySpecification($capability); return idx($spec, 'caption'); } } final public function getCapabilityTemplatePHIDType($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: case PhabricatorPolicyCapability::CAN_EDIT: return null; } $spec = $this->getCustomCapabilitySpecification($capability); return idx($spec, 'template'); } final public function getDefaultObjectTypePolicyMap() { $map = array(); foreach ($this->getCustomCapabilities() as $capability => $spec) { if (empty($spec['template'])) { continue; } if (empty($spec['capability'])) { continue; } $default = $this->getPolicy($capability); $map[$spec['template']][$spec['capability']] = $default; } return $map; } public function getApplicationSearchDocumentTypes() { return array(); } protected function getEditRoutePattern($base = null) { return $base.'(?:'. '(?P[0-9]\d*)/)?'. '(?:'. '(?:'. '(?Pparameters|nodefault|nocreate|nomanage|comment)/'. '|'. '(?:form/(?P[^/]+)/)?(?:page/(?P[^/]+)/)?'. ')'. ')?'; } protected function getQueryRoutePattern($base = null) { return $base.'(?:query/(?P[^/]+)/)?'; } - protected function getPanelRouting($controller) { + protected function getProfileMenuRouting($controller) { $edit_route = $this->getEditRoutePattern(); return array( - '(?Pview)/(?P[^/]+)/' => $controller, - '(?Phide)/(?P[^/]+)/' => $controller, - '(?Pdefault)/(?P[^/]+)/' => $controller, - '(?Pconfigure)/' => $controller, - '(?Preorder)/' => $controller, - '(?Pedit)/'.$edit_route => $controller, - '(?Pnew)/(?[^/]+)/'.$edit_route => $controller, - '(?Pbuiltin)/(?[^/]+)/'.$edit_route + '(?Pview)/(?P[^/]+)/' => $controller, + '(?Phide)/(?P[^/]+)/' => $controller, + '(?Pdefault)/(?P[^/]+)/' => $controller, + '(?Pconfigure)/' => $controller, + '(?Preorder)/' => $controller, + '(?Pedit)/'.$edit_route => $controller, + '(?Pnew)/(?[^/]+)/'.$edit_route => $controller, + '(?Pbuiltin)/(?[^/]+)/'.$edit_route => $controller, ); } } diff --git a/src/applications/config/controller/PhabricatorConfigVersionController.php b/src/applications/config/controller/PhabricatorConfigVersionController.php index 15877ddbd7..8f43192b3b 100644 --- a/src/applications/config/controller/PhabricatorConfigVersionController.php +++ b/src/applications/config/controller/PhabricatorConfigVersionController.php @@ -1,93 +1,220 @@ getViewer(); $title = pht('Version Information'); $crumbs = $this ->buildApplicationCrumbs() ->addTextCrumb($title) ->setBorder(true); $versions = $this->renderModuleStatus($viewer); $nav = $this->buildSideNavView(); $nav->selectFilter('version/'); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setProfileHeader(true); $content = id(new PhabricatorConfigPageView()) ->setHeader($header) ->setContent($versions); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setNavigation($nav) ->appendChild($content) ->addClass('white-background'); } public function renderModuleStatus($viewer) { $versions = $this->loadVersions($viewer); $version_property_list = id(new PHUIPropertyListView()); - foreach ($versions as $name => $version) { - $version_property_list->addProperty($name, $version); + foreach ($versions as $name => $info) { + $version = $info['version']; + + if ($info['branchpoint']) { + $display = pht( + '%s (branched from %s on %s)', + $version, + $info['branchpoint'], + $info['upstream']); + } else { + $display = $version; + } + + $version_property_list->addProperty($name, $display); } $phabricator_root = dirname(phutil_get_library_root('phabricator')); $version_path = $phabricator_root.'/conf/local/VERSION'; if (Filesystem::pathExists($version_path)) { $version_from_file = Filesystem::readFile($version_path); $version_property_list->addProperty( pht('Local Version'), $version_from_file); } return $version_property_list; } private function loadVersions(PhabricatorUser $viewer) { $specs = array( 'phabricator', 'arcanist', 'phutil', ); $all_libraries = PhutilBootloader::getInstance()->getAllLibraries(); // This puts the core libraries at the top: $other_libraries = array_diff($all_libraries, $specs); $specs = array_merge($specs, $other_libraries); - $futures = array(); + $log_futures = array(); + $remote_futures = array(); + foreach ($specs as $lib) { $root = dirname(phutil_get_library_root($lib)); - $futures[$lib] = - id(new ExecFuture('git log --format=%s -n 1 --', '%H %ct')) + + $log_command = csprintf( + 'git log --format=%s -n 1 --', + '%H %ct'); + + $remote_command = csprintf( + 'git remote -v'); + + $log_futures[$lib] = id(new ExecFuture('%C', $log_command)) + ->setCWD($root); + + $remote_futures[$lib] = id(new ExecFuture('%C', $remote_command)) ->setCWD($root); } + $all_futures = array_merge($log_futures, $remote_futures); + + id(new FutureIterator($all_futures)) + ->resolveAll(); + + // A repository may have a bunch of remotes, but we're only going to look + // for remotes we host to try to figure out where this repository branched. + $upstream_pattern = '(github\.com/phacility/|secure\.phabricator\.com/)'; + + $upstream_futures = array(); + $lib_upstreams = array(); + foreach ($specs as $lib) { + $remote_future = $remote_futures[$lib]; + + list($err, $stdout) = $remote_future->resolve(); + if ($err) { + // If this fails for whatever reason, just move on. + continue; + } + + // These look like this, with a tab separating the first two fields: + // remote-name http://remote.uri/ (push) + + $upstreams = array(); + + $remotes = phutil_split_lines($stdout, false); + foreach ($remotes as $remote) { + $remote_pattern = '/^([^\t]+)\t([^ ]+) \(([^)]+)\)\z/'; + $matches = null; + if (!preg_match($remote_pattern, $remote, $matches)) { + continue; + } + + // Remote URIs are either "push" or "fetch": we only care about "fetch" + // URIs. + $type = $matches[3]; + if ($type != 'fetch') { + continue; + } + + $uri = $matches[2]; + $is_upstream = preg_match($upstream_pattern, $uri); + if (!$is_upstream) { + continue; + } + + $name = $matches[1]; + $upstreams[$name] = $name; + } + + // If we have several suitable upstreams, try to pick the one named + // "origin", if it exists. Otherwise, just pick the first one. + if (isset($upstreams['origin'])) { + $upstream = $upstreams['origin']; + } else if ($upstreams) { + $upstream = head($upstreams); + } else { + $upstream = null; + } + + if (!$upstream) { + continue; + } + + $lib_upstreams[$lib] = $upstream; + + $merge_base_command = csprintf( + 'git merge-base HEAD %s/master --', + $upstream); + + $root = dirname(phutil_get_library_root($lib)); + + $upstream_futures[$lib] = id(new ExecFuture('%C', $merge_base_command)) + ->setCWD($root); + } + + if ($upstream_futures) { + id(new FutureIterator($upstream_futures)) + ->resolveAll(); + } + $results = array(); - foreach ($futures as $key => $future) { + foreach ($log_futures as $lib => $future) { list($err, $stdout) = $future->resolve(); if (!$err) { list($hash, $epoch) = explode(' ', $stdout); $version = pht('%s (%s)', $hash, phabricator_date($epoch, $viewer)); } else { $version = pht('Unknown'); } - $results[$key] = $version; + + $result = array( + 'version' => $version, + 'upstream' => null, + 'branchpoint' => null, + ); + + $upstream_future = idx($upstream_futures, $lib); + if ($upstream_future) { + list($err, $stdout) = $upstream_future->resolve(); + if (!$err) { + $branchpoint = trim($stdout); + if (strlen($branchpoint)) { + // We only list a branchpoint if it differs from HEAD. + if ($branchpoint != $hash) { + $result['upstream'] = $lib_upstreams[$lib]; + $result['branchpoint'] = trim($stdout); + } + } + } + } + + $results[$lib] = $result; } return $results; } } diff --git a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php index 45604f6872..806cd02db3 100644 --- a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php +++ b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php @@ -1,333 +1,323 @@ deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<deformat(pht(<<' - `real`: 'George Washington ' - `full`: 'gwashington (George Washington) ' The default is `full`. EODOC )); return array( $this->newOption( 'metamta.default-address', 'string', 'noreply@phabricator.example.com') ->setDescription(pht('Default "From" address.')), $this->newOption( 'metamta.domain', 'string', 'phabricator.example.com') ->setDescription(pht('Domain used to generate Message-IDs.')), $this->newOption( 'metamta.mail-adapter', 'class', 'PhabricatorMailImplementationPHPMailerLiteAdapter') ->setBaseClass('PhabricatorMailImplementationAdapter') ->setSummary(pht('Control how mail is sent.')) ->setDescription($adapter_description), $this->newOption( 'metamta.one-mail-per-recipient', 'bool', true) ->setLocked(true) ->setBoolOptions( array( pht('Send Mail To Each Recipient'), pht('Send Mail To All Recipients'), )) ->setSummary( pht( 'Controls whether Phabricator sends one email with multiple '. 'recipients in the "To:" line, or multiple emails, each with a '. 'single recipient in the "To:" line.')) ->setDescription($one_mail_per_recipient_desc), $this->newOption('metamta.can-send-as-user', 'bool', false) ->setBoolOptions( array( pht('Send as User Taking Action'), pht('Send as Phabricator'), )) ->setSummary( pht( 'Controls whether Phabricator sends email "From" users.')) ->setDescription($send_as_user_desc), $this->newOption( 'metamta.reply-handler-domain', 'string', null) ->setLocked(true) ->setDescription(pht('Domain used for reply email addresses.')) ->addExample('phabricator.example.com', ''), $this->newOption('metamta.herald.show-hints', 'bool', true) ->setBoolOptions( array( pht('Show Herald Hints'), pht('No Herald Hints'), )) ->setSummary(pht('Show hints about Herald rules in email.')) ->setDescription($herald_hints_description), $this->newOption('metamta.recipients.show-hints', 'bool', true) ->setBoolOptions( array( pht('Show Recipient Hints'), pht('No Recipient Hints'), )) ->setSummary(pht('Show "To:" and "Cc:" footer hints in email.')) ->setDescription($recipient_hints_description), $this->newOption('metamta.email-preferences', 'bool', true) ->setBoolOptions( array( pht('Show Email Preferences Link'), pht('No Email Preferences Link'), )) ->setSummary(pht('Show email preferences link in email.')) ->setDescription($email_preferences_description), $this->newOption('metamta.insecure-auth-with-reply-to', 'bool', false) ->setBoolOptions( array( pht('Allow Insecure Reply-To Auth'), pht('Disallow Reply-To Auth'), )) ->setSummary(pht('Trust "Reply-To" headers for authentication.')) ->setDescription($reply_to_description), $this->newOption('metamta.placeholder-to-recipient', 'string', null) ->setSummary(pht('Placeholder for mail with only CCs.')) ->setDescription($placeholder_description), $this->newOption('metamta.public-replies', 'bool', false) ->setBoolOptions( array( pht('Use Public Replies (Less Secure)'), pht('Use Private Replies (More Secure)'), )) ->setSummary( pht( 'Phabricator can use less-secure but mailing list friendly public '. 'reply addresses.')) ->setDescription($public_replies_description), $this->newOption('metamta.single-reply-handler-prefix', 'string', null) ->setSummary( pht('Allow Phabricator to use a single mailbox for all replies.')) ->setDescription($single_description), $this->newOption('metamta.user-address-format', 'enum', 'full') ->setEnumOptions( array( 'short' => 'short', 'real' => 'real', 'full' => 'full', )) ->setSummary(pht('Control how Phabricator renders user names in mail.')) ->setDescription($address_description) ->addExample('gwashington ', 'short') ->addExample('George Washington ', 'real') ->addExample( 'gwashington (George Washington) ', 'full'), $this->newOption('metamta.email-body-limit', 'int', 524288) ->setDescription( pht( 'You can set a limit for the maximum byte size of outbound mail. '. 'Mail which is larger than this limit will be truncated before '. 'being sent. This can be useful if your MTA rejects mail which '. 'exceeds some limit (this is reasonably common). Specify a value '. 'in bytes.')) ->setSummary(pht('Global cap for size of generated emails (bytes).')) ->addExample(524288, pht('Truncate at 512KB')) ->addExample(1048576, pht('Truncate at 1MB')), ); } } diff --git a/src/applications/dashboard/controller/PhabricatorDashboardEditController.php b/src/applications/dashboard/controller/PhabricatorDashboardEditController.php index 8438d0442b..a167c91188 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardEditController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardEditController.php @@ -1,362 +1,374 @@ getViewer(); $id = $request->getURIData('id'); if ($id) { $dashboard = id(new PhabricatorDashboardQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needPanels(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$dashboard) { return new Aphront404Response(); } $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( $dashboard->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); $v_projects = array_reverse($v_projects); $is_new = false; } else { if (!$request->getStr('edit')) { if ($request->isFormPost()) { switch ($request->getStr('template')) { case 'empty': break; default: return $this->processBuildTemplateRequest($request); } } else { return $this->processTemplateRequest($request); } } $dashboard = PhabricatorDashboard::initializeNewDashboard($viewer); $v_projects = array(); $is_new = true; } $crumbs = $this->buildApplicationCrumbs(); if ($is_new) { $title = pht('Create Dashboard'); $header_icon = 'fa-plus-square'; $button = pht('Create Dashboard'); $cancel_uri = $this->getApplicationURI(); $crumbs->addTextCrumb(pht('Create Dashboard')); } else { $id = $dashboard->getID(); $cancel_uri = $this->getApplicationURI('manage/'.$id.'/'); $title = pht('Edit Dashboard: %s', $dashboard->getName()); $header_icon = 'fa-pencil'; $button = pht('Save Changes'); $crumbs->addTextCrumb($dashboard->getName(), $cancel_uri); $crumbs->addTextCrumb(pht('Edit')); } $v_name = $dashboard->getName(); + $v_icon = $dashboard->getIcon(); $v_layout_mode = $dashboard->getLayoutConfigObject()->getLayoutMode(); $e_name = true; $validation_exception = null; if ($request->isFormPost() && $request->getStr('edit')) { $v_name = $request->getStr('name'); + $v_icon = $request->getStr('icon'); $v_layout_mode = $request->getStr('layout_mode'); $v_view_policy = $request->getStr('viewPolicy'); $v_edit_policy = $request->getStr('editPolicy'); $v_projects = $request->getArr('projects'); $xactions = array(); $type_name = PhabricatorDashboardTransaction::TYPE_NAME; + $type_icon = PhabricatorDashboardTransaction::TYPE_ICON; $type_layout_mode = PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE; $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY; $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType($type_name) ->setNewValue($v_name); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType($type_layout_mode) ->setNewValue($v_layout_mode); + $xactions[] = id(new PhabricatorDashboardTransaction()) + ->setTransactionType($type_icon) + ->setNewValue($v_icon); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType($type_view_policy) ->setNewValue($v_view_policy); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType($type_edit_policy) ->setNewValue($v_edit_policy); $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue('edge:type', $proj_edge_type) ->setNewValue(array('=' => array_fuse($v_projects))); try { $editor = id(new PhabricatorDashboardTransactionEditor()) ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->applyTransactions($dashboard, $xactions); $uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); return id(new AphrontRedirectResponse())->setURI($uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; $e_name = $validation_exception->getShortMessage($type_name); $dashboard->setViewPolicy($v_view_policy); $dashboard->setEditPolicy($v_edit_policy); } } $policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) ->setObject($dashboard) ->execute(); $layout_mode_options = PhabricatorDashboardLayoutConfig::getLayoutModeSelectOptions(); $form = id(new AphrontFormView()) ->setUser($viewer) ->addHiddenInput('edit', true) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Name')) ->setName('name') ->setValue($v_name) ->setError($e_name)) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Layout Mode')) ->setName('layout_mode') ->setValue($v_layout_mode) ->setOptions($layout_mode_options)) + ->appendChild( + id(new PHUIFormIconSetControl()) + ->setLabel(pht('Icon')) + ->setName('icon') + ->setIconSet(new PhabricatorDashboardIconSet()) + ->setValue($v_icon)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') ->setPolicyObject($dashboard) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicies($policies)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('editPolicy') ->setPolicyObject($dashboard) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicies($policies)); $form->appendControl( id(new AphrontFormTokenizerControl()) ->setLabel(pht('Tags')) ->setName('projects') ->setValue($v_projects) ->setDatasource(new PhabricatorProjectDatasource())); $form->appendChild( id(new AphrontFormSubmitControl()) ->setValue($button) ->addCancelButton($cancel_uri)); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Dashboard')) ->setForm($form) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setValidationException($validation_exception); $crumbs->setBorder(true); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon($header_icon); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter($box); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } private function processTemplateRequest(AphrontRequest $request) { $viewer = $request->getUser(); $template_control = id(new AphrontFormRadioButtonControl()) ->setName(pht('template')) ->setValue($request->getStr('template', 'empty')) ->addButton( 'empty', pht('Empty'), pht('Start with a blank canvas.')) ->addButton( 'simple', pht('Simple Template'), pht( 'Start with a simple dashboard with a welcome message, a feed of '. 'recent events, and a few starter panels.')); $form = id(new AphrontFormView()) ->setUser($viewer) ->appendRemarkupInstructions( pht('Choose a dashboard template to start with.')) ->appendChild($template_control); return $this->newDialog() ->setTitle(pht('Create Dashboard')) ->setWidth(AphrontDialogView::WIDTH_FORM) ->appendChild($form->buildLayoutView()) ->addCancelButton('/dashboard/') ->addSubmitButton(pht('Continue')); } private function processBuildTemplateRequest(AphrontRequest $request) { $viewer = $request->getUser(); $template = $request->getStr('template'); $bare_panel = PhabricatorDashboardPanel::initializeNewPanel($viewer); $panel_phids = array(); switch ($template) { case 'simple': $v_name = pht('New Simple Dashboard'); $welcome_panel = $this->newPanel( $request, $viewer, 'text', pht('Welcome'), array( 'text' => pht( "This is a simple template dashboard. You can edit this panel ". "to change this text and replace it with a welcome message, or ". "leave this placeholder text as-is to give your dashboard a ". "rustic, authentic feel.\n\n". "You can drag, remove, add, and edit panels to customize the ". "rest of this dashboard to show the information you want.\n\n". "To install this dashboard on the home page, use the ". "**Install Dashboard** action link above."), )); $panel_phids[] = $welcome_panel->getPHID(); $feed_panel = $this->newPanel( $request, $viewer, 'query', pht('Recent Activity'), array( 'class' => 'PhabricatorFeedSearchEngine', 'key' => 'all', )); $panel_phids[] = $feed_panel->getPHID(); $task_panel = $this->newPanel( $request, $viewer, 'query', pht('Open Tasks'), array( 'class' => 'ManiphestTaskSearchEngine', 'key' => 'open', )); $panel_phids[] = $task_panel->getPHID(); $commit_panel = $this->newPanel( $request, $viewer, 'query', pht('Recent Commits'), array( 'class' => 'PhabricatorCommitSearchEngine', 'key' => 'all', )); $panel_phids[] = $commit_panel->getPHID(); $mode_2_and_1 = PhabricatorDashboardLayoutConfig::MODE_THIRDS_AND_THIRD; $layout = id(new PhabricatorDashboardLayoutConfig()) ->setLayoutMode($mode_2_and_1) ->setPanelLocation(0, $welcome_panel->getPHID()) ->setPanelLocation(0, $task_panel->getPHID()) ->setPanelLocation(0, $commit_panel->getPHID()) ->setPanelLocation(1, $feed_panel->getPHID()); break; default: throw new Exception(pht('Unknown dashboard template %s!', $template)); } // Create the dashboard. $dashboard = PhabricatorDashboard::initializeNewDashboard($viewer) ->setLayoutConfigFromObject($layout); $xactions = array(); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType(PhabricatorDashboardTransaction::TYPE_NAME) ->setNewValue($v_name); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue( 'edge:type', PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST) ->setNewValue( array( '+' => array_fuse($panel_phids), )); $editor = id(new PhabricatorDashboardTransactionEditor()) ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->applyTransactions($dashboard, $xactions); $manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); return id(new AphrontRedirectResponse()) ->setURI($manage_uri); } private function newPanel( AphrontRequest $request, PhabricatorUser $viewer, $type, $name, array $properties) { $panel = PhabricatorDashboardPanel::initializeNewPanel($viewer) ->setPanelType($type) ->setProperties($properties); $xactions = array(); $xactions[] = id(new PhabricatorDashboardPanelTransaction()) ->setTransactionType(PhabricatorDashboardPanelTransaction::TYPE_NAME) ->setNewValue($name); $editor = id(new PhabricatorDashboardPanelTransactionEditor()) ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->applyTransactions($panel, $xactions); return $panel; } } diff --git a/src/applications/dashboard/controller/PhabricatorDashboardManageController.php b/src/applications/dashboard/controller/PhabricatorDashboardManageController.php index 4e31b2d2ae..9724db21f7 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardManageController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardManageController.php @@ -1,206 +1,206 @@ getViewer(); $id = $request->getURIData('id'); $dashboard_uri = $this->getApplicationURI('view/'.$id.'/'); // TODO: This UI should drop a lot of capabilities if the user can't // edit the dashboard, but we should still let them in for "Install" and // "View History". $dashboard = id(new PhabricatorDashboardQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needPanels(true) ->executeOne(); if (!$dashboard) { return new Aphront404Response(); } $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $dashboard, PhabricatorPolicyCapability::CAN_EDIT); $title = $dashboard->getName(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( pht('Dashboard %d', $dashboard->getID()), $dashboard_uri); $crumbs->addTextCrumb(pht('Manage')); $crumbs->setBorder(true); $header = $this->buildHeaderView($dashboard); $curtain = $this->buildCurtainview($dashboard); $properties = $this->buildPropertyView($dashboard); $timeline = $this->buildTransactionTimeline( $dashboard, new PhabricatorDashboardTransactionQuery()); $info_view = null; if (!$can_edit) { $no_edit = pht( 'You do not have permission to edit this dashboard. If you want to '. 'make changes, make a copy first.'); $info_view = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setErrors(array($no_edit)); } $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) ->setViewer($viewer) ->setDashboard($dashboard) ->setArrangeMode($can_edit) ->renderDashboard(); $dashboard_box = id(new PHUIBoxView()) ->addClass('dashboard-preview-box') ->appendChild($rendered_dashboard); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->setMainColumn(array( $info_view, $properties, $timeline, )) ->setFooter($dashboard_box); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } private function buildHeaderView(PhabricatorDashboard $dashboard) { $viewer = $this->getViewer(); $id = $dashboard->getID(); if ($dashboard->isArchived()) { $status_icon = 'fa-ban'; $status_color = 'dark'; } else { $status_icon = 'fa-check'; $status_color = 'bluegrey'; } $status_name = idx( PhabricatorDashboard::getStatusNameMap(), $dashboard->getStatus()); $button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('View Dashboard')) ->setIcon('fa-columns') ->setHref($this->getApplicationURI("view/{$id}/")); return id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($dashboard->getName()) ->setPolicyObject($dashboard) ->setStatus($status_icon, $status_color, $status_name) - ->setHeaderIcon('fa-dashboard') + ->setHeaderIcon($dashboard->getIcon()) ->addActionLink($button); } private function buildCurtainView(PhabricatorDashboard $dashboard) { $viewer = $this->getViewer(); $id = $dashboard->getID(); $curtain = $this->newCurtainView($dashboard); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $dashboard, PhabricatorPolicyCapability::CAN_EDIT); $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Dashboard')) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI("edit/{$id}/")) ->setDisabled(!$can_edit)); if ($dashboard->isArchived()) { $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Activate Dashboard')) ->setIcon('fa-check') ->setHref($this->getApplicationURI("archive/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow($can_edit)); } else { $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Archive Dashboard')) ->setIcon('fa-ban') ->setHref($this->getApplicationURI("archive/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow($can_edit)); } $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Copy Dashboard')) ->setIcon('fa-files-o') ->setHref($this->getApplicationURI("copy/{$id}/")) ->setWorkflow(true)); $installed_dashboard = id(new PhabricatorDashboardInstall()) ->loadOneWhere( 'objectPHID = %s AND applicationClass = %s', $viewer->getPHID(), 'PhabricatorHomeApplication'); if ($installed_dashboard && $installed_dashboard->getDashboardPHID() == $dashboard->getPHID()) { $title_install = pht('Uninstall Dashboard'); $href_install = "uninstall/{$id}/"; } else { $title_install = pht('Install Dashboard'); $href_install = "install/{$id}/"; } $curtain->addAction( id(new PhabricatorActionView()) ->setName($title_install) ->setIcon('fa-wrench') ->setHref($this->getApplicationURI($href_install)) ->setWorkflow(true)); return $curtain; } private function buildPropertyView(PhabricatorDashboard $dashboard) { $viewer = $this->getViewer(); $properties = id(new PHUIPropertyListView()) ->setUser($viewer); $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $viewer, $dashboard); $properties->addProperty( pht('Editable By'), $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); $properties->addProperty( pht('Panels'), $viewer->renderHandleList($dashboard->getPanelPHIDs())); return id(new PHUIObjectBoxView()) ->setHeaderText(pht('Details')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addPropertyList($properties); } } diff --git a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php index b85498c13c..787d1c63ee 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php @@ -1,443 +1,443 @@ getViewer(); $id = $request->getURIData('id'); // If the user is trying to create a panel directly on a dashboard, make // sure they have permission to see and edit the dashboard. $dashboard_id = $request->getInt('dashboardID'); $dashboard = null; if ($dashboard_id) { $dashboard = id(new PhabricatorDashboardQuery()) ->setViewer($viewer) ->withIDs(array($dashboard_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$dashboard) { return new Aphront404Response(); } $manage_uri = $this->getApplicationURI('manage/'.$dashboard_id.'/'); } if ($id) { $is_create = false; if ($dashboard) { $capabilities = array( PhabricatorPolicyCapability::CAN_VIEW, ); } else { $capabilities = array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } $panel = id(new PhabricatorDashboardPanelQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities($capabilities) ->executeOne(); if (!$panel) { return new Aphront404Response(); } if ($dashboard) { $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $panel, PhabricatorPolicyCapability::CAN_EDIT); if (!$can_edit) { if ($request->isFormPost() && $request->getBool('copy')) { $panel = $this->copyPanel( $request, $dashboard, $panel); } else { return $this->processPanelCloneRequest( $request, $dashboard, $panel); } } } } else { $is_create = true; $panel = PhabricatorDashboardPanel::initializeNewPanel($viewer); $types = PhabricatorDashboardPanelType::getAllPanelTypes(); $type = $request->getStr('type'); if (empty($types[$type])) { return $this->processPanelTypeRequest($request); } $panel->setPanelType($type); } if ($is_create) { $title = pht('Create New Panel'); $button = pht('Create Panel'); $header_icon = 'fa-plus-square'; if ($dashboard) { $cancel_uri = $manage_uri; } else { $cancel_uri = $this->getApplicationURI('panel/'); } } else { $title = pht('Edit Panel: %s', $panel->getName()); $button = pht('Save Panel'); $header_icon = 'fa-pencil'; if ($dashboard) { $cancel_uri = $manage_uri; } else { $cancel_uri = '/'.$panel->getMonogram(); } } $v_name = $panel->getName(); $e_name = true; $field_list = PhabricatorCustomField::getObjectFields( $panel, PhabricatorCustomField::ROLE_EDIT); $field_list ->setViewer($viewer) ->readFieldsFromStorage($panel); if ($is_create && !$request->isFormPost()) { $panel->requireImplementation()->initializeFieldsFromRequest( $panel, $field_list, $request); } $validation_exception = null; // NOTE: We require 'edit' to distinguish between the "Choose a Type" // and "Create a Panel" dialogs. if ($request->isFormPost() && $request->getBool('edit')) { $v_name = $request->getStr('name'); $v_view_policy = $request->getStr('viewPolicy'); $v_edit_policy = $request->getStr('editPolicy'); $type_name = PhabricatorDashboardPanelTransaction::TYPE_NAME; $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY; $xactions = array(); $xactions[] = id(new PhabricatorDashboardPanelTransaction()) ->setTransactionType($type_name) ->setNewValue($v_name); $xactions[] = id(new PhabricatorDashboardPanelTransaction()) ->setTransactionType($type_view_policy) ->setNewValue($v_view_policy); $xactions[] = id(new PhabricatorDashboardPanelTransaction()) ->setTransactionType($type_edit_policy) ->setNewValue($v_edit_policy); $field_xactions = $field_list->buildFieldTransactionsFromRequest( new PhabricatorDashboardPanelTransaction(), $request); $xactions = array_merge($xactions, $field_xactions); try { $editor = id(new PhabricatorDashboardPanelTransactionEditor()) ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->applyTransactions($panel, $xactions); // If we're creating a panel directly on a dashboard, add it now. if ($dashboard) { PhabricatorDashboardTransactionEditor::addPanelToDashboard( $viewer, PhabricatorContentSource::newFromRequest($request), $panel, $dashboard, $request->getInt('column', 0)); } if ($dashboard) { $done_uri = $manage_uri; } else { $done_uri = '/'.$panel->getMonogram(); } return id(new AphrontRedirectResponse())->setURI($done_uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; $e_name = $validation_exception->getShortMessage($type_name); $panel->setViewPolicy($v_view_policy); $panel->setEditPolicy($v_edit_policy); } } // NOTE: We're setting the submit URI explicitly because we need to edit // a different panel if we just cloned the original panel. if ($is_create) { $submit_uri = $this->getApplicationURI('panel/edit/'); } else { $submit_uri = $this->getApplicationURI('panel/edit/'.$panel->getID().'/'); } $policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) ->setObject($panel) ->execute(); $form = id(new AphrontFormView()) ->setUser($viewer) ->setAction($submit_uri) ->addHiddenInput('edit', true) ->addHiddenInput('dashboardID', $request->getInt('dashboardID')) ->addHiddenInput('column', $request->getInt('column')) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Name')) ->setName('name') ->setValue($v_name) ->setError($e_name)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') ->setPolicyObject($panel) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicies($policies)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('editPolicy') ->setPolicyObject($panel) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicies($policies)); $field_list->appendFieldsToForm($form); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( pht('Panels'), $this->getApplicationURI('panel/')); if ($is_create) { $crumbs->addTextCrumb(pht('New Panel')); $form->addHiddenInput('type', $panel->getPanelType()); } else { $crumbs->addTextCrumb( $panel->getMonogram(), '/'.$panel->getMonogram()); $crumbs->addTextCrumb(pht('Edit')); } $crumbs->setBorder(true); if ($request->isAjax()) { return $this->newDialog() ->setTitle($title) ->setSubmitURI($submit_uri) ->setWidth(AphrontDialogView::WIDTH_FORM) ->setValidationException($validation_exception) ->appendChild($form->buildLayoutView()) ->addCancelButton($cancel_uri) ->addSubmitButton($button); } else { $form ->appendChild( id(new AphrontFormSubmitControl()) ->setValue($button) ->addCancelButton($cancel_uri)); } $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Panel')) ->setValidationException($validation_exception) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon($header_icon); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter($box); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } private function processPanelTypeRequest(AphrontRequest $request) { $viewer = $request->getUser(); $types = PhabricatorDashboardPanelType::getAllPanelTypes(); $v_type = null; $errors = array(); if ($request->isFormPost()) { $v_type = $request->getStr('type'); if (!isset($types[$v_type])) { $errors[] = pht('You must select a type of panel to create.'); } } $cancel_uri = $this->getApplicationURI('panel/'); if (!$v_type) { $v_type = key($types); } $panel_types = id(new AphrontFormRadioButtonControl()) ->setName('type') ->setValue($v_type); foreach ($types as $key => $type) { $panel_types->addButton( $key, $type->getPanelTypeName(), $type->getPanelTypeDescription()); } $form = id(new AphrontFormView()) ->setUser($viewer) ->addHiddenInput('dashboardID', $request->getInt('dashboardID')) ->addHiddenInput('column', $request->getInt('column')) ->appendRemarkupInstructions( pht( 'Choose the type of dashboard panel to create:')) ->appendChild($panel_types); if ($request->isAjax()) { return $this->newDialog() ->setTitle(pht('Add New Panel')) ->setWidth(AphrontDialogView::WIDTH_FORM) ->setErrors($errors) ->appendChild($form->buildLayoutView()) ->addCancelbutton($cancel_uri) ->addSubmitButton(pht('Continue')); } else { $form->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Continue')) ->addCancelButton($cancel_uri)); } $title = pht('Create Dashboard Panel'); $header_icon = 'fa-plus-square'; $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb( pht('Panels'), $this->getApplicationURI('panel/')); $crumbs->addTextCrumb(pht('New Panel')); $crumbs->setBorder(true); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Panel')) ->setFormErrors($errors) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon($header_icon); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter($box); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } private function processPanelCloneRequest( AphrontRequest $request, PhabricatorDashboard $dashboard, PhabricatorDashboardPanel $panel) { $viewer = $request->getUser(); $manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); return $this->newDialog() ->setTitle(pht('Copy Panel?')) ->addHiddenInput('copy', true) ->addHiddenInput('dashboardID', $request->getInt('dashboardID')) ->addHiddenInput('column', $request->getInt('column')) ->appendParagraph( pht( 'You do not have permission to edit this dashboard panel, but you '. 'can make a copy and edit that instead. If you choose to copy the '. 'panel, the original will be replaced with the new copy on this '. 'dashboard.')) ->appendParagraph( pht( 'Do you want to make a copy of this panel?')) ->addCancelButton($manage_uri) ->addSubmitButton(pht('Copy Panel')); } private function copyPanel( AphrontRequest $request, PhabricatorDashboard $dashboard, PhabricatorDashboardPanel $panel) { $viewer = $request->getUser(); $copy = PhabricatorDashboardPanel::initializeNewPanel($viewer); - $copy = PhabricatorDashboardPanel::copyPanel($copy, $panel); + $copy = PhabricatorDashboardPanel::copyPanel($copy, $panel, $viewer); $copy->openTransaction(); $copy->save(); // TODO: This should record a transaction on the panel copy, too. $xactions = array(); $xactions[] = id(new PhabricatorDashboardTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue( 'edge:type', PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST) ->setNewValue( array( '+' => array( $copy->getPHID() => $copy->getPHID(), ), '-' => array( $panel->getPHID() => $panel->getPHID(), ), )); $layout_config = $dashboard->getLayoutConfigObject(); $layout_config->replacePanel($panel->getPHID(), $copy->getPHID()); $dashboard->setLayoutConfigFromObject($layout_config); $dashboard->save(); $editor = id(new PhabricatorDashboardTransactionEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($dashboard, $xactions); $copy->saveTransaction(); return $copy; } } diff --git a/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php b/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php index 48940dde60..c9be8bf013 100644 --- a/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php +++ b/src/applications/dashboard/editor/PhabricatorDashboardPanelEditEngine.php @@ -1,96 +1,100 @@ panelType = $panel_type; return $this; } public function getPanelType() { return $this->panelType; } public function isEngineConfigurable() { return false; } public function getEngineName() { return pht('Dashboard Panels'); } public function getSummaryHeader() { return pht('Edit Dashboard Panels'); } + protected function supportsSearch() { + return true; + } + public function getSummaryText() { return pht('This engine is used to modify dashboard panels.'); } public function getEngineApplicationClass() { - return 'PhabricatorSearchApplication'; + return 'PhabricatorDashboardApplication'; } protected function newEditableObject() { $viewer = $this->getViewer(); $panel = PhabricatorDashboardPanel::initializeNewPanel($viewer); if ($this->panelType) { $panel->setPanelType($this->panelType); } return $panel; } protected function newObjectQuery() { return new PhabricatorDashboardPanelQuery(); } protected function getObjectCreateTitleText($object) { return pht('Create Dashboard Panel'); } protected function getObjectCreateButtonText($object) { return pht('Create Panel'); } protected function getObjectEditTitleText($object) { return pht('Edit Panel: %s', $object->getName()); } protected function getObjectEditShortText($object) { return pht('Edit Panel'); } protected function getObjectCreateShortText() { return pht('Edit Panel'); } protected function getObjectName() { return pht('Dashboard Panel'); } protected function getObjectViewURI($object) { return $object->getURI(); } protected function buildCustomEditFields($object) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setDescription(pht('Name of the panel.')) ->setConduitDescription(pht('Rename the panel.')) ->setConduitTypeDescription(pht('New panel name.')) ->setTransactionType(PhabricatorDashboardPanelTransaction::TYPE_NAME) ->setIsRequired(true) ->setValue($object->getName()), ); } } diff --git a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php index 6cb7810d0b..792f6f9aa5 100644 --- a/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php +++ b/src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php @@ -1,171 +1,182 @@ setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue( 'edge:type', PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST) ->setNewValue( array( '+' => array( $panel->getPHID() => $panel->getPHID(), ), )); $layout_config = $dashboard->getLayoutConfigObject(); $layout_config->setPanelLocation($column, $panel->getPHID()); $dashboard->setLayoutConfigFromObject($layout_config); $editor = id(new PhabricatorDashboardTransactionEditor()) ->setActor($actor) ->setContentSource($content_source) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($dashboard, $xactions); } public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_EDGE; $types[] = PhabricatorDashboardTransaction::TYPE_NAME; + $types[] = PhabricatorDashboardTransaction::TYPE_ICON; $types[] = PhabricatorDashboardTransaction::TYPE_STATUS; $types[] = PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE; return $types; } protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorDashboardTransaction::TYPE_NAME: if ($this->getIsNewObject()) { return null; } return $object->getName(); + case PhabricatorDashboardTransaction::TYPE_ICON: + if ($this->getIsNewObject()) { + return null; + } + return $object->getIcon(); case PhabricatorDashboardTransaction::TYPE_STATUS: if ($this->getIsNewObject()) { return null; } return $object->getStatus(); case PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE: if ($this->getIsNewObject()) { return null; } $layout_config = $object->getLayoutConfigObject(); return $layout_config->getLayoutMode(); } return parent::getCustomTransactionOldValue($object, $xaction); } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorDashboardTransaction::TYPE_NAME: + case PhabricatorDashboardTransaction::TYPE_ICON: case PhabricatorDashboardTransaction::TYPE_STATUS: case PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE: return $xaction->getNewValue(); } return parent::getCustomTransactionNewValue($object, $xaction); } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorDashboardTransaction::TYPE_NAME: $object->setName($xaction->getNewValue()); return; + case PhabricatorDashboardTransaction::TYPE_ICON: + $object->setIcon($xaction->getNewValue()); + return; case PhabricatorDashboardTransaction::TYPE_STATUS: $object->setStatus($xaction->getNewValue()); return; case PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE: $old_layout = $object->getLayoutConfigObject(); $new_layout = clone $old_layout; $new_layout->setLayoutMode($xaction->getNewValue()); if ($old_layout->isMultiColumnLayout() != $new_layout->isMultiColumnLayout()) { $panel_phids = $object->getPanelPHIDs(); $new_locations = $new_layout->getDefaultPanelLocations(); foreach ($panel_phids as $panel_phid) { $new_locations[0][] = $panel_phid; } $new_layout->setPanelLocations($new_locations); } $object->setLayoutConfigFromObject($new_layout); return; } return parent::applyCustomInternalTransaction($object, $xaction); } protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorDashboardTransaction::TYPE_NAME: + case PhabricatorDashboardTransaction::TYPE_ICON: case PhabricatorDashboardTransaction::TYPE_STATUS: case PhabricatorDashboardTransaction::TYPE_LAYOUT_MODE: return; } return parent::applyCustomExternalTransaction($object, $xaction); } protected function validateTransaction( PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorDashboardTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField( $object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError( $type, pht('Required'), pht('Dashboard name is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; } return $errors; } } diff --git a/src/applications/dashboard/icon/PhabricatorDashboardIconSet.php b/src/applications/dashboard/icon/PhabricatorDashboardIconSet.php new file mode 100644 index 0000000000..1bd12609b7 --- /dev/null +++ b/src/applications/dashboard/icon/PhabricatorDashboardIconSet.php @@ -0,0 +1,45 @@ + pht('Home'), + 'fa-th-large' => pht('Blocks'), + 'fa-columns' => pht('Columns'), + 'fa-bookmark' => pht('Page Saver'), + + 'fa-book' => pht('Knowledge'), + 'fa-bomb' => pht('Kaboom'), + 'fa-pie-chart' => pht('Apple Blueberry'), + 'fa-bar-chart' => pht('Serious Business'), + + 'fa-bell' => pht('Ding Ding'), + 'fa-credit-card' => pht('Plastic Debt'), + 'fa-code' => pht('PHP is Life'), + 'fa-sticky-note' => pht('To Self'), + + 'fa-newspaper-o' => pht('Stay Woke'), + 'fa-server' => pht('Metallica'), + 'fa-hashtag' => pht('Corned Beef'), + 'fa-group' => pht('Triplets'), + ); + + $icons = array(); + foreach ($map as $key => $label) { + $icons[] = id(new PhabricatorIconSetIcon()) + ->setKey($key) + ->setLabel($label); + } + + return $icons; + } + +} diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php index 3a6589a32c..ac72c9ce6f 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php @@ -1,85 +1,108 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withArchived($archived) { $this->archived = $archived; return $this; } public function withPanelTypes(array $types) { $this->panelTypes = $types; return $this; } + public function withAuthorPHIDs(array $authors) { + $this->authorPHIDs = $authors; + return $this; + } + + public function withNameNgrams($ngrams) { + return $this->withNgramsConstraint( + id(new PhabricatorDashboardPanelNgrams()), + $ngrams); + } + protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } public function newResultObject() { // TODO: If we don't do this, SearchEngine explodes when trying to // enumerate custom fields. For now, just give the panel a default panel // type so custom fields work. In the long run, we may want to find a // cleaner or more general approach for this. $text_type = id(new PhabricatorDashboardTextPanelType()) ->getPanelTypeKey(); return id(new PhabricatorDashboardPanel()) ->setPanelType($text_type); } protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->ids !== null) { $where[] = qsprintf( $conn, 'id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn, 'phid IN (%Ls)', $this->phids); } if ($this->archived !== null) { $where[] = qsprintf( $conn, 'isArchived = %d', (int)$this->archived); } if ($this->panelTypes !== null) { $where[] = qsprintf( $conn, 'panelType IN (%Ls)', $this->panelTypes); } + if ($this->authorPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'authorPHID IN (%Ls)', + $this->authorPHIDs); + } + return $where; } public function getQueryApplicationClass() { return 'PhabricatorDashboardApplication'; } + protected function getPrimaryTableAlias() { + return 'dashboard_panel'; + } + } diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php index 113ed8ff94..89e77997d8 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php @@ -1,125 +1,154 @@ newQuery(); if ($map['status']) { switch ($map['status']) { case 'active': $query->withArchived(false); break; case 'archived': $query->withArchived(true); break; default: break; } } if ($map['paneltype']) { $query->withPanelTypes(array($map['paneltype'])); } + if ($map['authorPHIDs']) { + $query->withAuthorPHIDs($map['authorPHIDs']); + } + + if ($map['name'] !== null) { + $query->withNameNgrams($map['name']); + } + return $query; } protected function buildCustomSearchFields() { return array( + id(new PhabricatorSearchTextField()) + ->setLabel(pht('Name Contains')) + ->setKey('name') + ->setDescription(pht('Search for panels by name substring.')), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Authored By')) + ->setKey('authorPHIDs') + ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()), id(new PhabricatorSearchSelectField()) ->setKey('status') ->setLabel(pht('Status')) ->setOptions( id(new PhabricatorDashboardPanel()) ->getStatuses()), id(new PhabricatorSearchSelectField()) ->setKey('paneltype') ->setLabel(pht('Panel Type')) ->setOptions( id(new PhabricatorDashboardPanel()) ->getPanelTypes()), ); } protected function getURI($path) { return '/dashboard/panel/'.$path; } protected function getBuiltinQueryNames() { - return array( - 'active' => pht('Active Panels'), - 'all' => pht('All Panels'), - ); + $names = array(); + + if ($this->requireViewer()->isLoggedIn()) { + $names['authored'] = pht('Authored'); + } + + $names['active'] = pht('Active Panels'); + $names['all'] = pht('All Panels'); + + return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); + $viewer = $this->requireViewer(); switch ($query_key) { case 'active': return $query->setParameter('status', 'active'); + case 'authored': + return $query->setParameter( + 'authorPHIDs', + array( + $viewer->getPHID(), + )); case 'all': return $query; } return parent::buildSavedQueryFromBuiltin($query_key); } protected function renderResultList( array $panels, PhabricatorSavedQuery $query, array $handles) { $viewer = $this->requireViewer(); $list = new PHUIObjectItemListView(); $list->setUser($viewer); foreach ($panels as $panel) { $item = id(new PHUIObjectItemView()) ->setObjectName($panel->getMonogram()) ->setHeader($panel->getName()) ->setHref('/'.$panel->getMonogram()) ->setObject($panel); $impl = $panel->getImplementation(); if ($impl) { $type_text = $impl->getPanelTypeName(); } else { $type_text = nonempty($panel->getPanelType(), pht('Unknown Type')); } $item->addAttribute($type_text); $properties = $panel->getProperties(); $class = idx($properties, 'class'); $item->addAttribute($class); if ($panel->getIsArchived()) { $item->setDisabled(true); } $list->addItem($item); } $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); $result->setNoDataString(pht('No panels found.')); return $result; } } diff --git a/src/applications/dashboard/query/PhabricatorDashboardQuery.php b/src/applications/dashboard/query/PhabricatorDashboardQuery.php index 55cd447c7a..a54cfbc47c 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardQuery.php +++ b/src/applications/dashboard/query/PhabricatorDashboardQuery.php @@ -1,131 +1,154 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withStatuses(array $statuses) { $this->statuses = $statuses; return $this; } + public function withAuthorPHIDs(array $authors) { + $this->authorPHIDs = $authors; + return $this; + } + public function needPanels($need_panels) { $this->needPanels = $need_panels; return $this; } public function needProjects($need_projects) { $this->needProjects = $need_projects; return $this; } + public function withNameNgrams($ngrams) { + return $this->withNgramsConstraint( + id(new PhabricatorDashboardNgrams()), + $ngrams); + } + protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } public function newResultObject() { return new PhabricatorDashboard(); } protected function didFilterPage(array $dashboards) { $phids = mpull($dashboards, 'getPHID'); if ($this->needPanels) { $edge_query = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs($phids) ->withEdgeTypes( array( PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST, )); $edge_query->execute(); $panel_phids = $edge_query->getDestinationPHIDs(); if ($panel_phids) { $panels = id(new PhabricatorDashboardPanelQuery()) ->setParentQuery($this) ->setViewer($this->getViewer()) ->withPHIDs($panel_phids) ->execute(); $panels = mpull($panels, null, 'getPHID'); } else { $panels = array(); } foreach ($dashboards as $dashboard) { $dashboard_phids = $edge_query->getDestinationPHIDs( array($dashboard->getPHID())); $dashboard_panels = array_select_keys($panels, $dashboard_phids); $dashboard->attachPanelPHIDs($dashboard_phids); $dashboard->attachPanels($dashboard_panels); } } if ($this->needProjects) { $edge_query = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs($phids) ->withEdgeTypes( array( PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, )); $edge_query->execute(); foreach ($dashboards as $dashboard) { $project_phids = $edge_query->getDestinationPHIDs( array($dashboard->getPHID())); $dashboard->attachProjectPHIDs($project_phids); } } return $dashboards; } protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->ids !== null) { $where[] = qsprintf( $conn, 'id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn, 'phid IN (%Ls)', $this->phids); } if ($this->statuses !== null) { $where[] = qsprintf( $conn, 'status IN (%Ls)', $this->statuses); } + if ($this->authorPHIDs !== null) { + $where[] = qsprintf( + $conn, + 'authorPHID IN (%Ls)', + $this->authorPHIDs); + } + return $where; } public function getQueryApplicationClass() { return 'PhabricatorDashboardApplication'; } + protected function getPrimaryTableAlias() { + return 'dashboard'; + } + } diff --git a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php index 26c71c1bab..c6c6ab1233 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php +++ b/src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php @@ -1,197 +1,226 @@ needProjects(true); } protected function buildCustomSearchFields() { return array( + id(new PhabricatorSearchTextField()) + ->setLabel(pht('Name Contains')) + ->setKey('name') + ->setDescription(pht('Search for dashboards by name substring.')), + id(new PhabricatorSearchDatasourceField()) + ->setLabel(pht('Authored By')) + ->setKey('authorPHIDs') + ->setDatasource(new PhabricatorPeopleUserFunctionDatasource()), id(new PhabricatorSearchCheckboxesField()) ->setKey('statuses') ->setLabel(pht('Status')) ->setOptions(PhabricatorDashboard::getStatusNameMap()), ); } protected function getURI($path) { return '/dashboard/'.$path; } protected function getBuiltinQueryNames() { - return array( - 'open' => pht('Active Dashboards'), - 'all' => pht('All Dashboards'), - ); + $names = array(); + + if ($this->requireViewer()->isLoggedIn()) { + $names['authored'] = pht('Authored'); + } + + $names['open'] = pht('Active Dashboards'); + $names['all'] = pht('All Dashboards'); + + return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); + $viewer = $this->requireViewer(); switch ($query_key) { case 'all': return $query; + case 'authored': + return $query->setParameter( + 'authorPHIDs', + array( + $viewer->getPHID(), + )); case 'open': return $query->setParameter( 'statuses', array( PhabricatorDashboard::STATUS_ACTIVE, )); } return parent::buildSavedQueryFromBuiltin($query_key); } protected function buildQueryFromParameters(array $map) { $query = $this->newQuery(); if ($map['statuses']) { $query->withStatuses($map['statuses']); } + if ($map['authorPHIDs']) { + $query->withAuthorPHIDs($map['authorPHIDs']); + } + + if ($map['name'] !== null) { + $query->withNameNgrams($map['name']); + } + return $query; } protected function renderResultList( array $dashboards, PhabricatorSavedQuery $query, array $handles) { $dashboards = mpull($dashboards, null, 'getPHID'); $viewer = $this->requireViewer(); if ($dashboards) { $installs = id(new PhabricatorDashboardInstall()) ->loadAllWhere( 'objectPHID IN (%Ls) AND dashboardPHID IN (%Ls)', array( PhabricatorHomeApplication::DASHBOARD_DEFAULT, $viewer->getPHID(), ), array_keys($dashboards)); $installs = mpull($installs, null, 'getDashboardPHID'); } else { $installs = array(); } $proj_phids = array(); foreach ($dashboards as $dashboard) { foreach ($dashboard->getProjectPHIDs() as $project_phid) { $proj_phids[] = $project_phid; } } $proj_handles = id(new PhabricatorHandleQuery()) ->setViewer($viewer) ->withPHIDs($proj_phids) ->execute(); $list = new PHUIObjectItemListView(); $list->setUser($viewer); $list->initBehavior('phabricator-tooltips', array()); $list->requireResource('aphront-tooltip-css'); foreach ($dashboards as $dashboard_phid => $dashboard) { $id = $dashboard->getID(); $item = id(new PHUIObjectItemView()) ->setObjectName(pht('Dashboard %d', $id)) ->setHeader($dashboard->getName()) ->setHref($this->getApplicationURI("view/{$id}/")) ->setObject($dashboard); if (isset($installs[$dashboard_phid])) { $install = $installs[$dashboard_phid]; if ($install->getObjectPHID() == $viewer->getPHID()) { $attrs = array( 'tip' => pht( 'This dashboard is installed to your personal homepage.'), ); $item->addIcon('fa-user', pht('Installed'), $attrs); } else { $attrs = array( 'tip' => pht( 'This dashboard is the default homepage for all users.'), ); $item->addIcon('fa-globe', pht('Installed'), $attrs); } } $project_handles = array_select_keys( $proj_handles, $dashboard->getProjectPHIDs()); $item->addAttribute( id(new PHUIHandleTagListView()) ->setLimit(4) ->setNoDataString(pht('No Projects')) ->setSlim(true) ->setHandles($project_handles)); if ($dashboard->isArchived()) { $item->setDisabled(true); } $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $dashboard, PhabricatorPolicyCapability::CAN_EDIT); $href_view = $this->getApplicationURI("manage/{$id}/"); $item->addAction( id(new PHUIListItemView()) ->setName(pht('Manage')) ->setIcon('fa-th') ->setHref($href_view)); $href_edit = $this->getApplicationURI("edit/{$id}/"); $item->addAction( id(new PHUIListItemView()) ->setName(pht('Edit')) ->setIcon('fa-pencil') ->setHref($href_edit) ->setDisabled(!$can_edit)); $list->addItem($item); } $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); $result->setNoDataString(pht('No dashboards found.')); return $result; } protected function getNewUserBody() { $create_button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Create a Dashboard')) ->setHref('/dashboard/create/') ->setColor(PHUIButtonView::GREEN); $icon = $this->getApplication()->getIcon(); $app_name = $this->getApplication()->getName(); $view = id(new PHUIBigInfoView()) ->setIcon($icon) ->setTitle(pht('Welcome to %s', $app_name)) ->setDescription( pht('Customize your homepage with different panels and '. 'search queries.')) ->addAction($create_button); return $view; } } diff --git a/src/applications/dashboard/storage/PhabricatorDashboard.php b/src/applications/dashboard/storage/PhabricatorDashboard.php index 2930ca7674..fb50cba692 100644 --- a/src/applications/dashboard/storage/PhabricatorDashboard.php +++ b/src/applications/dashboard/storage/PhabricatorDashboard.php @@ -1,183 +1,204 @@ setName('') + ->setIcon('fa-dashboard') ->setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setEditPolicy($actor->getPHID()) ->setStatus(self::STATUS_ACTIVE) + ->setAuthorPHID($actor->getPHID()) ->attachPanels(array()) ->attachPanelPHIDs(array()); } public static function getStatusNameMap() { return array( self::STATUS_ACTIVE => pht('Active'), self::STATUS_ARCHIVED => pht('Archived'), ); } public static function copyDashboard( PhabricatorDashboard $dst, PhabricatorDashboard $src) { $dst->name = $src->name; $dst->layoutConfig = $src->layoutConfig; return $dst; } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'layoutConfig' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'name' => 'text255', + 'name' => 'sort255', 'status' => 'text32', + 'icon' => 'text32', + 'authorPHID' => 'phid', ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorDashboardDashboardPHIDType::TYPECONST); } public function getLayoutConfigObject() { return PhabricatorDashboardLayoutConfig::newFromDictionary( $this->getLayoutConfig()); } public function setLayoutConfigFromObject( PhabricatorDashboardLayoutConfig $object) { $this->setLayoutConfig($object->toDictionary()); return $this; } public function getProjectPHIDs() { return $this->assertAttached($this->edgeProjectPHIDs); } public function attachProjectPHIDs(array $phids) { $this->edgeProjectPHIDs = $phids; return $this; } public function attachPanelPHIDs(array $phids) { $this->panelPHIDs = $phids; return $this; } public function getPanelPHIDs() { return $this->assertAttached($this->panelPHIDs); } public function attachPanels(array $panels) { assert_instances_of($panels, 'PhabricatorDashboardPanel'); $this->panels = $panels; return $this; } public function getPanels() { return $this->assertAttached($this->panels); } public function isArchived() { return ($this->getStatus() == self::STATUS_ARCHIVED); } + public function getViewURI() { + return '/dashboard/view/'.$this->getID().'/'; + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorDashboardTransactionEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new PhabricatorDashboardTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); $installs = id(new PhabricatorDashboardInstall())->loadAllWhere( 'dashboardPHID = %s', $this->getPHID()); foreach ($installs as $install) { $install->delete(); } $this->delete(); $this->saveTransaction(); } +/* -( PhabricatorNgramInterface )------------------------------------------ */ + + + public function newNgrams() { + return array( + id(new PhabricatorDashboardNgrams()) + ->setValue($this->getName()), + ); + } + } diff --git a/src/applications/dashboard/storage/PhabricatorDashboardNgrams.php b/src/applications/dashboard/storage/PhabricatorDashboardNgrams.php new file mode 100644 index 0000000000..7884ec43f9 --- /dev/null +++ b/src/applications/dashboard/storage/PhabricatorDashboardNgrams.php @@ -0,0 +1,18 @@ +setName('') + ->setAuthorPHID($actor->getPHID()) ->setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setEditPolicy($actor->getPHID()); } public static function copyPanel( PhabricatorDashboardPanel $dst, - PhabricatorDashboardPanel $src) { + PhabricatorDashboardPanel $src, + PhabricatorUser $user) { $dst->name = $src->name; $dst->panelType = $src->panelType; $dst->properties = $src->properties; + $dst->authorPHID = $user->getPHID(); return $dst; } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'name' => 'text255', + 'name' => 'sort255', 'panelType' => 'text64', + 'authorPHID' => 'phid', 'isArchived' => 'bool', ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorDashboardPanelPHIDType::TYPECONST); } public function getProperty($key, $default = null) { return idx($this->properties, $key, $default); } public function setProperty($key, $value) { $this->properties[$key] = $value; return $this; } public function getMonogram() { return 'W'.$this->getID(); } public function getURI() { return '/'.$this->getMonogram(); } public function getPanelTypes() { $panel_types = PhabricatorDashboardPanelType::getAllPanelTypes(); $panel_types = mpull($panel_types, 'getPanelTypeName', 'getPanelTypeKey'); asort($panel_types); $panel_types = (array('' => pht('(All Types)')) + $panel_types); return $panel_types; } public function getStatuses() { $statuses = array( '' => pht('(All Panels)'), 'active' => pht('Active Panels'), 'archived' => pht('Archived Panels'), ); return $statuses; } public function getImplementation() { return idx( PhabricatorDashboardPanelType::getAllPanelTypes(), $this->getPanelType()); } public function requireImplementation() { $impl = $this->getImplementation(); if (!$impl) { throw new Exception( pht( 'Attempting to use a panel in a way that requires an '. 'implementation, but the panel implementation ("%s") is unknown to '. 'Phabricator.', $this->getPanelType())); } return $impl; } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorDashboardPanelTransactionEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new PhabricatorDashboardPanelTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } /* -( PhabricatorCustomFieldInterface )------------------------------------ */ public function getCustomFieldSpecificationForRole($role) { return array(); } public function getCustomFieldBaseClass() { return 'PhabricatorDashboardPanelCustomField'; } public function getCustomFields() { return $this->assertAttached($this->customFields); } public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) { $this->customFields = $fields; return $this; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); $this->delete(); $this->saveTransaction(); } + +/* -( PhabricatorNgramInterface )------------------------------------------ */ + + + public function newNgrams() { + return array( + id(new PhabricatorDashboardPanelNgrams()) + ->setValue($this->getName()), + ); + } + } diff --git a/src/applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php b/src/applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php new file mode 100644 index 0000000000..536da8b751 --- /dev/null +++ b/src/applications/dashboard/storage/PhabricatorDashboardPanelNgrams.php @@ -0,0 +1,18 @@ +getAuthorPHID(); $object_phid = $this->getObjectPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $author_link = $this->renderHandleLink($author_phid); $type = $this->getTransactionType(); switch ($type) { case self::TYPE_NAME: if (!strlen($old)) { return pht( '%s created this dashboard.', $author_link); } else { return pht( '%s renamed this dashboard from "%s" to "%s".', $author_link, $old, $new); } break; + case self::TYPE_ICON: + if (!strlen($old)) { + return pht( + '%s set the dashboard icon.', + $author_link); + } else { + return pht( + '%s changed this dashboard icon from "%s" to "%s".', + $author_link, + $old, + $new); + } + break; case self::TYPE_STATUS: if ($new == PhabricatorDashboard::STATUS_ACTIVE) { return pht( '%s activated this dashboard', $author_link); } else { return pht( '%s archived this dashboard', $author_link); } break; } return parent::getTitle(); } public function getTitleForFeed() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $author_link = $this->renderHandleLink($author_phid); $object_link = $this->renderHandleLink($object_phid); $type = $this->getTransactionType(); switch ($type) { case self::TYPE_NAME: if (!strlen($old)) { return pht( '%s created dashboard %s.', $author_link, $object_link); } else { return pht( '%s renamed dashboard %s from "%s" to "%s".', $author_link, $object_link, $old, $new); } break; + case self::TYPE_ICON: + if (!strlen($old)) { + return pht( + '%s set dashboard icon for %s.', + $author_link, + $object_link); + } else { + return pht( + '%s set the dashboard icon on %s from "%s" to "%s".', + $author_link, + $object_link, + $old, + $new); + } + break; case self::TYPE_STATUS: if ($new == PhabricatorDashboard::STATUS_ACTIVE) { return pht( '%s activated dashboard %s.', $author_link, $object_link); } else { return pht( '%s archived dashboard %s.', $author_link, $object_link); } break; } return parent::getTitleForFeed(); } public function getColor() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_NAME: if (!strlen($old)) { return PhabricatorTransactions::COLOR_GREEN; } break; case self::TYPE_STATUS: if ($new == PhabricatorDashboard::STATUS_ACTIVE) { return PhabricatorTransactions::COLOR_GREEN; } else { return PhabricatorTransactions::COLOR_INDIGO; } break; } return parent::getColor(); } public function getIcon() { $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_NAME: return 'fa-pencil'; break; case self::TYPE_STATUS: if ($new == PhabricatorDashboard::STATUS_ACTIVE) { return 'fa-check'; } else { return 'fa-ban'; } break; case self::TYPE_LAYOUT_MODE: return 'fa-columns'; break; } return parent::getIcon(); } public function shouldHide() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_LAYOUT_MODE: return true; } return parent::shouldHide(); } } diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php new file mode 100644 index 0000000000..a1c0399624 --- /dev/null +++ b/src/applications/dashboard/typeahead/PhabricatorDashboardDatasource.php @@ -0,0 +1,39 @@ +executeQuery($query); + $results = array(); + foreach ($dashboards as $dashboard) { + $result = id(new PhabricatorTypeaheadResult()) + ->setName($dashboard->getName()) + ->setPHID($dashboard->getPHID()) + ->addAttribute(pht('Dashboard')); + + if ($dashboard->isArchived()) { + $result->setClosed(pht('Archived')); + } + + $results[] = $result; + } + + return $this->filterResultsAgainstTokens($results); + } + +} diff --git a/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php new file mode 100644 index 0000000000..35c8c5c212 --- /dev/null +++ b/src/applications/dashboard/typeahead/PhabricatorDashboardPanelDatasource.php @@ -0,0 +1,46 @@ +executeQuery($query); + $results = array(); + foreach ($panels as $panel) { + $impl = $panel->getImplementation(); + if ($impl) { + $type_text = $impl->getPanelTypeName(); + } else { + $type_text = nonempty($panel->getPanelType(), pht('Unknown Type')); + } + + $result = id(new PhabricatorTypeaheadResult()) + ->setName($panel->getName()) + ->setPHID($panel->getPHID()) + ->addAttribute($type_text); + + if ($panel->getIsArchived()) { + $result->setClosed(pht('Archived')); + } + + $results[] = $result; + } + + return $this->filterResultsAgainstTokens($results); + } + +} diff --git a/src/applications/differential/application/PhabricatorDifferentialApplication.php b/src/applications/differential/application/PhabricatorDifferentialApplication.php index 589dfe239d..b5a3ea95dc 100644 --- a/src/applications/differential/application/PhabricatorDifferentialApplication.php +++ b/src/applications/differential/application/PhabricatorDifferentialApplication.php @@ -1,226 +1,228 @@ pht('Differential User Guide'), 'href' => PhabricatorEnv::getDoclink('Differential User Guide'), ), ); } public function getFactObjectsForAnalysis() { return array( new DifferentialRevision(), ); } public function getTitleGlyph() { return "\xE2\x9A\x99"; } public function getEventListeners() { return array( new DifferentialLandingActionMenuEventListener(), ); } public function getOverview() { return pht( 'Differential is a **code review application** which allows '. 'engineers to review, discuss and approve changes to software.'); } public function getRoutes() { return array( '/D(?P[1-9]\d*)' => 'DifferentialRevisionViewController', '/differential/' => array( '(?:query/(?P[^/]+)/)?' => 'DifferentialRevisionListController', 'diff/' => array( '(?P[1-9]\d*)/' => 'DifferentialDiffViewController', 'create/' => 'DifferentialDiffCreateController', ), 'changeset/' => 'DifferentialChangesetViewController', 'revision/' => array( - 'edit/(?:(?P[1-9]\d*)/)?' + $this->getEditRoutePattern('edit/') + => 'DifferentialRevisionEditController', + $this->getEditRoutePattern('attach/(?P[^/]+)/to/') => 'DifferentialRevisionEditController', 'land/(?:(?P[1-9]\d*))/(?P[^/]+)/' => 'DifferentialRevisionLandController', 'closedetails/(?P[^/]+)/' => 'DifferentialRevisionCloseDetailsController', 'update/(?P[1-9]\d*)/' => 'DifferentialDiffCreateController', 'operation/(?P[1-9]\d*)/' => 'DifferentialRevisionOperationController', ), 'comment/' => array( 'preview/(?P[1-9]\d*)/' => 'DifferentialCommentPreviewController', 'save/(?P[1-9]\d*)/' => 'DifferentialCommentSaveController', 'inline/' => array( 'preview/(?P[1-9]\d*)/' => 'DifferentialInlineCommentPreviewController', 'edit/(?P[1-9]\d*)/' => 'DifferentialInlineCommentEditController', ), ), 'preview/' => 'PhabricatorMarkupPreviewController', ), ); } public function getApplicationOrder() { return 0.100; } public function getRemarkupRules() { return array( new DifferentialRemarkupRule(), ); } public static function loadNeedAttentionRevisions(PhabricatorUser $viewer) { if (!$viewer->isLoggedIn()) { return array(); } $viewer_phid = $viewer->getPHID(); $responsible_phids = id(new DifferentialResponsibleDatasource()) ->setViewer($viewer) ->evaluateTokens(array($viewer_phid)); $revision_query = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withStatus(DifferentialRevisionQuery::STATUS_OPEN) ->withResponsibleUsers($responsible_phids) ->needReviewerStatus(true) ->needRelationships(true) ->needFlags(true) ->needDrafts(true) ->setLimit(self::MAX_STATUS_ITEMS); $revisions = $revision_query->execute(); $query = id(new PhabricatorSavedQuery()) ->attachParameterMap( array( 'responsiblePHIDs' => $responsible_phids, )); $groups = id(new DifferentialRevisionRequiredActionResultBucket()) ->setViewer($viewer) ->newResultGroups($query, $revisions); $include = array(); foreach ($groups as $group) { switch ($group->getKey()) { case DifferentialRevisionRequiredActionResultBucket::KEY_MUSTREVIEW: case DifferentialRevisionRequiredActionResultBucket::KEY_SHOULDREVIEW: foreach ($group->getObjects() as $object) { $include[] = $object; } break; default: break; } } return $include; } public function loadStatus(PhabricatorUser $user) { $revisions = self::loadNeedAttentionRevisions($user); $limit = self::MAX_STATUS_ITEMS; if (count($revisions) >= $limit) { $display_count = ($limit - 1); $display_label = pht( '%s+ Active Review(s)', new PhutilNumber($display_count)); } else { $display_count = count($revisions); $display_label = pht( '%s Review(s) Need Attention', new PhutilNumber($display_count)); } $status = array(); $status[] = id(new PhabricatorApplicationStatusView()) ->setType(PhabricatorApplicationStatusView::TYPE_WARNING) ->setText($display_label) ->setCount($display_count); return $status; } public function supportsEmailIntegration() { return true; } public function getAppEmailBlurb() { return pht( 'Send email to these addresses to create revisions. The body of the '. 'message and / or one or more attachments should be the output of a '. '"diff" command. %s', phutil_tag( 'a', array( 'href' => $this->getInboundEmailSupportLink(), ), pht('Learn More'))); } protected function getCustomCapabilities() { return array( DifferentialDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created revisions.'), 'template' => DifferentialRevisionPHIDType::TYPECONST, 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ); } public function getMailCommandObjects() { return array( 'revision' => array( 'name' => pht('Email Commands: Revisions'), 'header' => pht('Interacting with Differential Revisions'), 'object' => new DifferentialRevision(), 'summary' => pht( 'This page documents the commands you can use to interact with '. 'revisions in Differential.'), ), ); } public function getApplicationSearchDocumentTypes() { return array( DifferentialRevisionPHIDType::TYPECONST, ); } } diff --git a/src/applications/differential/conduit/DifferentialConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialConduitAPIMethod.php index fdcf4395dd..34843b5609 100644 --- a/src/applications/differential/conduit/DifferentialConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialConduitAPIMethod.php @@ -1,222 +1,195 @@ getID().'/'; $uri = PhabricatorEnv::getProductionURI($uri); return array( 'id' => $diff->getID(), 'phid' => $diff->getPHID(), 'uri' => $uri, ); } protected function buildInlineInfoDictionary( DifferentialInlineComment $inline, DifferentialChangeset $changeset = null) { $file_path = null; $diff_id = null; if ($changeset) { $file_path = $inline->getIsNewFile() ? $changeset->getFilename() : $changeset->getOldFile(); $diff_id = $changeset->getDiffID(); } return array( 'id' => $inline->getID(), 'authorPHID' => $inline->getAuthorPHID(), 'filePath' => $file_path, 'isNewFile' => $inline->getIsNewFile(), 'lineNumber' => $inline->getLineNumber(), 'lineLength' => $inline->getLineLength(), 'diffID' => $diff_id, 'content' => $inline->getContent(), ); } protected function applyFieldEdit( ConduitAPIRequest $request, DifferentialRevision $revision, DifferentialDiff $diff, array $fields, $message) { $viewer = $request->getUser(); - $field_list = PhabricatorCustomField::getObjectFields( - $revision, - DifferentialCustomField::ROLE_COMMITMESSAGEEDIT); - - $field_list - ->setViewer($viewer) - ->readFieldsFromStorage($revision); - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); + // We're going to build the body of a "differential.revision.edit" API + // request, then just call that code directly. $xactions = array(); + $xactions[] = array( + 'type' => DifferentialRevisionEditEngine::KEY_UPDATE, + 'value' => $diff->getPHID(), + ); - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) - ->setNewValue($diff->getPHID()); - + $field_map = DifferentialCommitMessageField::newEnabledFields($viewer); $values = $request->getValue('fields', array()); foreach ($values as $key => $value) { $field = idx($field_map, $key); if (!$field) { // NOTE: We're just ignoring fields we don't know about. This isn't // ideal, but the way the workflow currently works involves us getting // several read-only fields, like the revision ID field, which we should // just skip. continue; } - $role = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS; - if (!$field->shouldEnableForRole($role)) { - continue; - } - - // TODO: This is fairly similar to PhabricatorCustomField's - // buildFieldTransactionsFromRequest() method, but that's currently not - // easy to reuse. - - $transaction_type = $field->getApplicationTransactionType(); - $xaction = id(new DifferentialTransaction()) - ->setTransactionType($transaction_type); - - if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { - // For TYPE_CUSTOMFIELD transactions only, we provide the old value - // as an input. - $old_value = $field->getOldValueForApplicationTransactions(); - $xaction->setOldValue($old_value); - } - // The transaction itself will be validated so this is somewhat // redundant, but this validator will sometimes give us a better error // message or a better reaction to a bad value type. - $field->validateCommitMessageValue($value); - $field->readValueFromCommitMessage($value); + $value = $field->readFieldValueFromConduit($value); - $xaction - ->setNewValue($field->getNewValueForApplicationTransactions()); - - if ($transaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { - // For TYPE_CUSTOMFIELD transactions, add the field key in metadata. - $xaction->setMetadataValue('customfield:key', $field->getFieldKey()); - } - - $metadata = $field->getApplicationTransactionMetadata(); - foreach ($metadata as $meta_key => $meta_value) { - $xaction->setMetadataValue($meta_key, $meta_value); + foreach ($field->getFieldTransactions($value) as $xaction) { + $xactions[] = $xaction; } - - $xactions[] = $xaction; } $message = $request->getValue('message'); if (strlen($message)) { - // This is a little awkward, and should maybe move inside the transaction - // editor. It largely exists for legacy reasons. + // This is a little awkward, and should move elsewhere or be removed. It + // largely exists for legacy reasons. See some discussion in T7899. $first_line = head(phutil_split_lines($message, false)); + + $first_line = id(new PhutilUTF8StringTruncator()) + ->setMaximumBytes(250) + ->setMaximumGlyphs(80) + ->truncateString($first_line); + $diff->setDescription($first_line); $diff->save(); - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) - ->attachComment( - id(new DifferentialTransactionComment()) - ->setContent($message)); + $xactions[] = array( + 'type' => PhabricatorCommentEditEngineExtension::EDITKEY, + 'value' => $message, + ); } - $editor = id(new DifferentialTransactionEditor()) - ->setActor($viewer) - ->setContentSource($request->newContentSource()) - ->setContinueOnNoEffect(true) - ->setContinueOnMissingFields(true); + $method = 'differential.revision.edit'; + $params = array( + 'transactions' => $xactions, + ); - $editor->applyTransactions($revision, $xactions); + if ($revision->getID()) { + $params['objectIdentifier'] = $revision->getID(); + } + + return id(new ConduitCall($method, $params, $strict = true)) + ->setUser($viewer) + ->execute(); } protected function loadCustomFieldsForRevisions( PhabricatorUser $viewer, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); if (!$revisions) { return array(); } $field_lists = array(); foreach ($revisions as $revision) { $revision_phid = $revision->getPHID(); $field_list = PhabricatorCustomField::getObjectFields( $revision, PhabricatorCustomField::ROLE_CONDUIT); $field_list ->setViewer($viewer) ->readFieldsFromObject($revision); $field_lists[$revision_phid] = $field_list; } $all_fields = array(); foreach ($field_lists as $field_list) { foreach ($field_list->getFields() as $field) { $all_fields[] = $field; } } id(new PhabricatorCustomFieldStorageQuery()) ->addFields($all_fields) ->execute(); $results = array(); foreach ($field_lists as $revision_phid => $field_list) { $results[$revision_phid] = array(); foreach ($field_list->getFields() as $field) { $field_key = $field->getFieldKeyForConduit(); $value = $field->getConduitDictionaryValue(); $results[$revision_phid][$field_key] = $value; } } // For compatibility, fill in these "custom fields" by querying for them // efficiently. See T11404 for discussion. $legacy_edge_map = array( 'phabricator:projects' => PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, 'phabricator:depends-on' => DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST, ); $query = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(array_keys($results)) ->withEdgeTypes($legacy_edge_map); $query->execute(); foreach ($results as $revision_phid => $dict) { foreach ($legacy_edge_map as $edge_key => $edge_type) { $phid_list = $query->getDestinationPHIDs( array($revision_phid), array($edge_type)); $results[$revision_phid][$edge_key] = $phid_list; } } return $results; } } diff --git a/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php index 95b4309c70..371d57cd9c 100644 --- a/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialCreateRevisionConduitAPIMethod.php @@ -1,61 +1,63 @@ 'ignored', 'diffid' => 'required diffid', 'fields' => 'required dict', ); } protected function defineReturnType() { return 'nonempty dict'; } protected function defineErrorTypes() { return array( 'ERR_BAD_DIFF' => pht('Bad diff ID.'), ); } protected function execute(ConduitAPIRequest $request) { $viewer = $request->getUser(); $diff = id(new DifferentialDiffQuery()) ->setViewer($viewer) ->withIDs(array($request->getValue('diffid'))) ->executeOne(); if (!$diff) { throw new ConduitException('ERR_BAD_DIFF'); } $revision = DifferentialRevision::initializeNewRevision($viewer); $revision->attachReviewerStatus(array()); - $this->applyFieldEdit( + $result = $this->applyFieldEdit( $request, $revision, $diff, $request->getValue('fields', array()), $message = null); + $revision_id = $result['object']['id']; + return array( - 'revisionid' => $revision->getID(), - 'uri' => PhabricatorEnv::getURI('/D'.$revision->getID()), + 'revisionid' => $revision_id, + 'uri' => PhabricatorEnv::getURI('/D'.$revision_id), ); } } diff --git a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php index 288a8c4ca9..2c5c936679 100644 --- a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php @@ -1,198 +1,166 @@ 'optional revision_id', 'fields' => 'optional dict', 'edit' => 'optional '.$this->formatStringConstants($edit_types), ); } protected function defineReturnType() { return 'nonempty string'; } protected function defineErrorTypes() { return array( 'ERR_NOT_FOUND' => pht('Revision was not found.'), ); } protected function execute(ConduitAPIRequest $request) { $id = $request->getValue('revision_id'); $viewer = $request->getUser(); if ($id) { $revision = id(new DifferentialRevisionQuery()) ->withIDs(array($id)) ->setViewer($viewer) ->needReviewerStatus(true) ->needActiveDiffs(true) ->executeOne(); if (!$revision) { throw new ConduitException('ERR_NOT_FOUND'); } } else { $revision = DifferentialRevision::initializeNewRevision($viewer); - $revision->attachReviewerStatus(array()); - $revision->attachActiveDiff(null); } - $is_edit = $request->getValue('edit'); - $is_create = ($is_edit == 'create'); + // There are three modes here: "edit", "create", and "read" (which has + // no value for the "edit" parameter). - $field_list = PhabricatorCustomField::getObjectFields( - $revision, - ($is_edit - ? DifferentialCustomField::ROLE_COMMITMESSAGEEDIT - : DifferentialCustomField::ROLE_COMMITMESSAGE)); + // In edit or create mode, we hide read-only fields. In create mode, we + // show "Field:" templates for some fields even if they are empty. + $edit_mode = $request->getValue('edit'); - $field_list - ->setViewer($viewer) - ->readFieldsFromStorage($revision); + $is_any_edit = (bool)strlen($edit_mode); + $is_create = ($edit_mode == 'create'); - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); + $field_list = DifferentialCommitMessageField::newEnabledFields($viewer); - if ($is_edit) { - $fields = $request->getValue('fields', array()); - foreach ($fields as $field => $value) { - $custom_field = idx($field_map, $field); - if (!$custom_field) { - // Just ignore this, these workflows don't make strong distictions - // about field editability on the client side. - continue; - } - if ($is_create || - $custom_field->shouldOverwriteWhenCommitMessageIsEdited()) { - $custom_field->readValueFromCommitMessage($value); + $custom_storage = $this->loadCustomFieldStorage($viewer, $revision); + foreach ($field_list as $field) { + $field->setCustomFieldStorage($custom_storage); + } + + // If we're editing the message, remove fields like "Conflicts" and + // "git-svn-id" which should not be presented to the user for editing. + if ($is_any_edit) { + foreach ($field_list as $field_key => $field) { + if (!$field->isFieldEditable()) { + unset($field_list[$field_key]); } } } - $phids = array(); - foreach ($field_list->getFields() as $key => $field) { - $field_phids = $field->getRequiredHandlePHIDsForCommitMessage(); - if (!is_array($field_phids)) { - throw new Exception( - pht( - 'Custom field "%s" was expected to return an array of handle '. - 'PHIDs required for commit message rendering, but returned "%s" '. - 'instead.', - $field->getFieldKey(), - gettype($field_phids))); + $overrides = $request->getValue('fields', array()); + + $value_map = array(); + foreach ($field_list as $field_key => $field) { + if (array_key_exists($field_key, $overrides)) { + $field_value = $overrides[$field_key]; + } else { + $field_value = $field->readFieldValueFromObject($revision); } - $phids[$key] = $field_phids; - } - $all_phids = array_mergev($phids); - if ($all_phids) { - $all_handles = id(new PhabricatorHandleQuery()) - ->setViewer($viewer) - ->withPHIDs($all_phids) - ->execute(); - } else { - $all_handles = array(); + // We're calling this method on the value no matter where we got it + // from, so we hit the same validation logic for values which came over + // the wire and which we generated. + $field_value = $field->readFieldValueFromConduit($field_value); + + $value_map[$field_key] = $field_value; } - $key_title = id(new DifferentialTitleField())->getFieldKey(); - $default_title = DifferentialTitleField::getDefaultTitle(); + $key_title = DifferentialTitleCommitMessageField::FIELDKEY; $commit_message = array(); - foreach ($field_list->getFields() as $key => $field) { - $handles = array_select_keys($all_handles, $phids[$key]); + foreach ($field_list as $field_key => $field) { + $label = $field->getFieldName(); + $wire_value = $value_map[$field_key]; + $value = $field->renderFieldValue($wire_value); - $label = $field->renderCommitMessageLabel(); - $value = $field->renderCommitMessageValue($handles); + $is_template = ($is_create && $field->isTemplateField()); if (!is_string($value) && !is_null($value)) { throw new Exception( pht( - 'Custom field "%s" was expected to render a string or null value, '. - 'but rendered a "%s" instead.', + 'Commit message field "%s" was expected to render a string or '. + 'null value, but rendered a "%s" instead.', $field->getFieldKey(), gettype($value))); } - $is_title = ($key == $key_title); + $is_title = ($field_key == $key_title); if (!strlen($value)) { - if ($is_title) { - $commit_message[] = $default_title; - } else { - if ($is_edit && $field->shouldAppearInCommitMessageTemplate()) { - $commit_message[] = $label.': '; - } + if ($is_template) { + $commit_message[] = $label.': '; } } else { if ($is_title) { $commit_message[] = $value; } else { $value = str_replace( array("\r\n", "\r"), array("\n", "\n"), $value); if (strpos($value, "\n") !== false || substr($value, 0, 2) === ' ') { $commit_message[] = "{$label}:\n{$value}"; } else { $commit_message[] = "{$label}: {$value}"; } } } } - if ($is_edit) { - $tip = $this->getProTip($field_list); - if ($tip !== null) { - $commit_message[] = "\n".$tip; - } - } - - $commit_message = implode("\n\n", $commit_message); - - return $commit_message; + return implode("\n\n", $commit_message); } - private function getProTip() { - // Any field can provide tips, whether it normally appears on commit - // messages or not. - $field_list = PhabricatorCustomField::getObjectFields( - new DifferentialRevision(), - PhabricatorCustomField::ROLE_DEFAULT); - - $tips = array(); - foreach ($field_list->getFields() as $key => $field) { - $tips[] = $field->getProTips(); - } - $tips = array_mergev($tips); - - if (!$tips) { - return null; - } - - shuffle($tips); - - $tip = pht('Tip: %s', head($tips)); - $tip = wordwrap($tip, 78, "\n", true); + private function loadCustomFieldStorage( + PhabricatorUser $viewer, + DifferentialRevision $revision) { + $custom_field_list = PhabricatorCustomField::getObjectFields( + $revision, + DifferentialCustomField::ROLE_COMMITMESSAGE); + $custom_field_list + ->setViewer($viewer) + ->readFieldsFromStorage($revision); - $lines = explode("\n", $tip); - foreach ($lines as $key => $line) { - $lines[$key] = '# '.$line; + $custom_field_map = array(); + foreach ($custom_field_list->getFields() as $custom_field) { + if (!$custom_field->shouldUseStorage()) { + continue; + } + $custom_field_key = $custom_field->getFieldKey(); + $custom_field_value = $custom_field->getValueForStorage(); + $custom_field_map[$custom_field_key] = $custom_field_value; } - return implode("\n", $lines); + return $custom_field_map; } + } diff --git a/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php index dc29ff07a9..59401862f0 100644 --- a/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php @@ -1,105 +1,55 @@ 'required string', 'partial' => 'optional bool', ); } protected function defineReturnType() { return 'nonempty dict'; } protected function execute(ConduitAPIRequest $request) { - $viewer = $request->getUser(); - $corpus = $request->getValue('corpus'); - $is_partial = $request->getValue('partial'); - - $field_list = PhabricatorCustomField::getObjectFields( - new DifferentialRevision(), - DifferentialCustomField::ROLE_COMMITMESSAGE); - $field_list->setViewer($viewer); - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); - - $corpus_map = $this->parseCommitMessage($corpus); - - $values = array(); - foreach ($corpus_map as $field_key => $text_value) { - $field = idx($field_map, $field_key); + $viewer = $this->getViewer(); - if (!$field) { - throw new Exception( - pht( - 'Parser emitted text value for field key "%s", but no such '. - 'field exists.', - $field_key)); - } + $parser = DifferentialCommitMessageParser::newStandardParser($viewer); - try { - $values[$field_key] = $field->parseValueFromCommitMessage($text_value); - } catch (DifferentialFieldParseException $ex) { - $this->errors[] = pht( - 'Error parsing field "%s": %s', - $field->renderCommitMessageLabel(), - $ex->getMessage()); - } + $is_partial = $request->getValue('partial'); + if ($is_partial) { + $parser->setRaiseMissingFieldErrors(false); } - if (!$is_partial) { - foreach ($field_map as $key => $field) { - try { - $field->validateCommitMessageValue(idx($values, $key)); - } catch (DifferentialFieldValidationException $ex) { - $this->errors[] = pht( - 'Invalid or missing field "%s": %s', - $field->renderCommitMessageLabel(), - $ex->getMessage()); - } - } - } + $corpus = $request->getValue('corpus'); + $field_map = $parser->parseFields($corpus); + + $errors = $parser->getErrors(); - // grab some extra information about the Differential Revision: field... - $revision_id_field = new DifferentialRevisionIDField(); $revision_id_value = idx( - $corpus_map, - $revision_id_field->getFieldKeyForConduit()); + $field_map, + DifferentialRevisionIDCommitMessageField::FIELDKEY); $revision_id_valid_domain = PhabricatorEnv::getProductionURI(''); return array( - 'errors' => $this->errors, - 'fields' => $values, + 'errors' => $errors, + 'fields' => $field_map, 'revisionIDFieldInfo' => array( 'value' => $revision_id_value, 'validDomain' => $revision_id_valid_domain, ), ); } - private function parseCommitMessage($corpus) { - $viewer = $this->getViewer(); - $parser = DifferentialCommitMessageParser::newStandardParser($viewer); - $result = $parser->parseCorpus($corpus); - - $this->errors = array(); - foreach ($parser->getErrors() as $error) { - $this->errors[] = $error; - } - - return $result; - } - } diff --git a/src/applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php new file mode 100644 index 0000000000..cb7c7e2e93 --- /dev/null +++ b/src/applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php @@ -0,0 +1,18 @@ +getFieldKey()] = array( 'disabled' => $field->shouldDisableByDefault(), ); } $inline_description = $this->deformat( pht(<<newOption( 'differential.fields', $custom_field_type, $default_fields) ->setCustomData( id(new DifferentialRevision())->getCustomFieldBaseClass()) ->setDescription( pht( "Select and reorder revision fields.\n\n". "NOTE: This feature is under active development and subject ". "to change.")), $this->newOption( 'differential.whitespace-matters', 'list', array( '/\.py$/', '/\.l?hs$/', )) ->setDescription( pht( "List of file regexps where whitespace is meaningful and should ". "not use 'ignore-all' by default")), $this->newOption('differential.require-test-plan-field', 'bool', true) ->setBoolOptions( array( pht("Require 'Test Plan' field"), pht("Make 'Test Plan' field optional"), )) ->setSummary(pht('Require "Test Plan" field?')) ->setDescription( pht( "Differential has a required 'Test Plan' field by default. You ". "can make it optional by setting this to false. You can also ". "completely remove it above, if you prefer.")), $this->newOption('differential.enable-email-accept', 'bool', false) ->setBoolOptions( array( pht('Enable Email "!accept" Action'), pht('Disable Email "!accept" Action'), )) ->setSummary(pht('Enable or disable "!accept" action via email.')) ->setDescription( pht( 'If inbound email is configured, users can interact with '. 'revisions by using "!actions" in email replies (for example, '. '"!resign" or "!rethink"). However, by default, users may not '. '"!accept" revisions via email: email authentication can be '. 'configured to be very weak, and email "!accept" is kind of '. 'sketchy and implies the revision may not actually be receiving '. 'thorough review. You can enable "!accept" by setting this '. 'option to true.')), $this->newOption('differential.generated-paths', 'list', array()) ->setSummary(pht('File regexps to treat as automatically generated.')) ->setDescription( pht( 'List of file regexps that should be treated as if they are '. 'generated by an automatic process, and thus be hidden by '. 'default in Differential.'. "\n\n". 'NOTE: This property is cached, so you will need to purge the '. 'cache after making changes if you want the new configuration '. 'to affect existing revisions. For instructions, see '. '**[[ %s | Managing Caches ]]** in the documentation.', $caches_href)) ->addExample("/config\.h$/\n#(^|/)autobuilt/#", pht('Valid Setting')), $this->newOption('differential.sticky-accept', 'bool', true) ->setBoolOptions( array( pht('Accepts persist across updates'), pht('Accepts are reset by updates'), )) ->setSummary( pht('Should "Accepted" revisions remain "Accepted" after updates?')) ->setDescription( pht( 'Normally, when revisions that have been "Accepted" are updated, '. 'they remain "Accepted". This allows reviewers to suggest minor '. 'alterations when accepting, and encourages authors to update '. 'if they make minor changes in response to this feedback.'. "\n\n". 'If you want updates to always require re-review, you can disable '. 'the "stickiness" of the "Accepted" status with this option. '. 'This may make the process for minor changes much more burdensome '. 'to both authors and reviewers.')), $this->newOption('differential.allow-self-accept', 'bool', false) ->setBoolOptions( array( pht('Allow self-accept'), pht('Disallow self-accept'), )) ->setSummary(pht('Allows users to accept their own revisions.')) ->setDescription( pht( "If you set this to true, users can accept their own revisions. ". "This action is disabled by default because it's most likely not ". "a behavior you want, but it proves useful if you are working ". "alone on a project and want to make use of all of ". "differential's features.")), $this->newOption('differential.always-allow-close', 'bool', false) ->setBoolOptions( array( pht('Allow any user'), pht('Restrict to submitter'), )) ->setSummary(pht('Allows any user to close accepted revisions.')) ->setDescription( pht( 'If you set this to true, any user can close any revision so '. 'long as it has been accepted. This can be useful depending on '. 'your development model. For example, github-style pull requests '. 'where the reviewer is often the actual committer can benefit '. 'from turning this option to true. If false, only the submitter '. 'can close a revision.')), $this->newOption('differential.always-allow-abandon', 'bool', false) ->setBoolOptions( array( pht('Allow any user'), pht('Restrict to submitter'), )) ->setSummary(pht('Allows any user to abandon revisions.')) ->setDescription( pht( 'If you set this to true, any user can abandon any revision. If '. 'false, only the submitter can abandon a revision.')), $this->newOption('differential.allow-reopen', 'bool', false) ->setBoolOptions( array( pht('Enable reopen'), pht('Disable reopen'), )) ->setSummary(pht('Allows any user to reopen a closed revision.')) ->setDescription( pht( 'If you set this to true, any user can reopen a revision so '. 'long as it has been closed. This can be useful if a revision '. 'is accidentally closed or if a developer changes his or her '. 'mind after closing a revision. If it is false, reopening '. 'is not allowed.')), $this->newOption('differential.close-on-accept', 'bool', false) ->setBoolOptions( array( pht('Treat Accepted Revisions as "Closed"'), pht('Treat Accepted Revisions as "Open"'), )) ->setSummary(pht('Allows "Accepted" to act as a closed status.')) ->setDescription( pht( 'Normally, Differential revisions remain on the dashboard when '. 'they are "Accepted", and the author then commits the changes '. 'to "Close" the revision and move it off the dashboard.'. "\n\n". 'If you have an unusual workflow where Differential is used for '. 'post-commit review (normally called "Audit", elsewhere in '. 'Phabricator), you can set this flag to treat the "Accepted" '. 'state as a "Closed" state and end the review workflow early.'. "\n\n". 'This sort of workflow is very unusual. Very few installs should '. 'need to change this option.')), $this->newOption( 'metamta.differential.subject-prefix', 'string', '[Differential]') ->setDescription(pht('Subject prefix for Differential mail.')), $this->newOption( 'metamta.differential.attach-patches', 'bool', false) ->setBoolOptions( array( pht('Attach Patches'), pht('Do Not Attach Patches'), )) ->setSummary(pht('Attach patches to email, as text attachments.')) ->setDescription( pht( 'If you set this to true, Phabricator will attach patches to '. 'Differential mail (as text attachments). This will not work if '. 'you are using SendGrid as your mail adapter.')), $this->newOption( 'metamta.differential.inline-patches', 'int', 0) ->setSummary(pht('Inline patches in email, as body text.')) ->setDescription($inline_description), $this->newOption( 'metamta.differential.patch-format', 'enum', 'unified') ->setDescription( pht('Format for inlined or attached patches.')) ->setEnumOptions( array('unified' => 'unified', 'git' => 'git')), ); } } diff --git a/src/applications/differential/controller/DifferentialCommentSaveController.php b/src/applications/differential/controller/DifferentialCommentSaveController.php index 831d7c90c8..87376bf6d5 100644 --- a/src/applications/differential/controller/DifferentialCommentSaveController.php +++ b/src/applications/differential/controller/DifferentialCommentSaveController.php @@ -1,143 +1,143 @@ getViewer(); $id = $request->getURIData('id'); if (!$request->isFormPost()) { return new Aphront400Response(); } $revision = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needReviewerStatus(true) ->needReviewerAuthority(true) ->executeOne(); if (!$revision) { return new Aphront404Response(); } $type_action = DifferentialTransaction::TYPE_ACTION; $type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS; $type_edge = PhabricatorTransactions::TYPE_EDGE; $type_comment = PhabricatorTransactions::TYPE_COMMENT; $type_inline = DifferentialTransaction::TYPE_INLINE; $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; $xactions = array(); $action = $request->getStr('action'); switch ($action) { case DifferentialAction::ACTION_COMMENT: case DifferentialAction::ACTION_ADDREVIEWERS: case DifferentialAction::ACTION_ADDCCS: // These transaction types have no direct effect, they just // accompany other transaction types which can have an effect. break; default: $xactions[] = id(new DifferentialTransaction()) ->setTransactionType($type_action) ->setNewValue($request->getStr('action')); break; } $ccs = $request->getArr('ccs'); if ($ccs) { $xactions[] = id(new DifferentialTransaction()) ->setTransactionType($type_subscribers) ->setNewValue(array('+' => $ccs)); } $current_reviewers = mpull( $revision->getReviewerStatus(), null, 'getReviewerPHID'); $reviewer_edges = array(); $add_reviewers = $request->getArr('reviewers'); foreach ($add_reviewers as $reviewer_phid) { if (isset($current_reviewers[$reviewer_phid])) { continue; } - $reviewer = new DifferentialReviewer( + $reviewer = new DifferentialReviewerProxy( $reviewer_phid, array( 'status' => DifferentialReviewerStatus::STATUS_ADDED, )); $reviewer_edges[$reviewer_phid] = array( 'data' => $reviewer->getEdgeData(), ); } if ($add_reviewers) { $xactions[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_reviewer) ->setNewValue(array('+' => $reviewer_edges)); } $inlines = DifferentialTransactionQuery::loadUnsubmittedInlineComments( $viewer, $revision); foreach ($inlines as $inline) { $xactions[] = id(new DifferentialTransaction()) ->setTransactionType($type_inline) ->attachComment($inline); } // NOTE: If there are no other transactions, add an empty comment // transaction so that we'll raise a more user-friendly error message, // to the effect of "you can not post an empty comment". $no_xactions = !$xactions; $comment = $request->getStr('comment'); if (strlen($comment) || $no_xactions) { $xactions[] = id(new DifferentialTransaction()) ->setTransactionType($type_comment) ->attachComment( id(new DifferentialTransactionComment()) ->setRevisionPHID($revision->getPHID()) ->setContent($comment)); } $editor = id(new DifferentialTransactionEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect($request->isContinueRequest()); $revision_uri = '/D'.$revision->getID(); try { $editor->applyTransactions($revision, $xactions); } catch (PhabricatorApplicationTransactionNoEffectException $ex) { return id(new PhabricatorApplicationTransactionNoEffectResponse()) ->setCancelURI($revision_uri) ->setException($ex); } catch (PhabricatorApplicationTransactionValidationException $ex) { return id(new PhabricatorApplicationTransactionValidationResponse()) ->setCancelURI($revision_uri) ->setException($ex); } $user = $request->getUser(); $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-'.$revision->getID()); if ($draft) { $draft->delete(); } DifferentialDraft::deleteAllDrafts($user->getPHID(), $revision->getPHID()); return id(new AphrontRedirectResponse()) ->setURI('/D'.$revision->getID()); } } diff --git a/src/applications/differential/controller/DifferentialDiffViewController.php b/src/applications/differential/controller/DifferentialDiffViewController.php index b2c497f6ac..dae65bb200 100644 --- a/src/applications/differential/controller/DifferentialDiffViewController.php +++ b/src/applications/differential/controller/DifferentialDiffViewController.php @@ -1,206 +1,214 @@ getViewer(); $id = $request->getURIData('id'); $diff = id(new DifferentialDiffQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$diff) { return new Aphront404Response(); } if ($diff->getRevisionID()) { return id(new AphrontRedirectResponse()) ->setURI('/D'.$diff->getRevisionID().'?id='.$diff->getID()); } + if ($request->isFormPost()) { + $diff_id = $diff->getID(); + $revision_id = $request->getInt('revisionID'); + if ($revision_id) { + $attach_uri = "/revision/attach/{$diff_id}/to/{$revision_id}/"; + } else { + $attach_uri = "/revision/attach/{$diff_id}/to/"; + } + $attach_uri = $this->getApplicationURI($attach_uri); + + return id(new AphrontRedirectResponse()) + ->setURI($attach_uri); + } + $diff_phid = $diff->getPHID(); $buildables = id(new HarbormasterBuildableQuery()) ->setViewer($viewer) ->withBuildablePHIDs(array($diff_phid)) ->withManualBuildables(false) ->needBuilds(true) ->needTargets(true) ->execute(); $buildables = mpull($buildables, null, 'getBuildablePHID'); $diff->attachBuildable(idx($buildables, $diff_phid)); // TODO: implement optgroup support in AphrontFormSelectControl? $select = array(); $select[] = hsprintf('', pht('Create New Revision')); $select[] = phutil_tag( 'option', array('value' => ''), pht('Create a new Revision...')); $select[] = hsprintf(''); $selected_id = $request->getInt('revisionID'); $revisions = $this->loadSelectableRevisions($viewer, $selected_id); if ($revisions) { $select[] = hsprintf( '', pht('Update Existing Revision')); foreach ($revisions as $revision) { if ($selected_id == $revision->getID()) { $selected = 'selected'; } else { $selected = null; } $select[] = phutil_tag( 'option', array( 'value' => $revision->getID(), 'selected' => $selected, ), id(new PhutilUTF8StringTruncator()) ->setMaximumGlyphs(128) ->truncateString( 'D'.$revision->getID().' '.$revision->getTitle())); } $select[] = hsprintf(''); } $select = phutil_tag( 'select', array('name' => 'revisionID'), $select); $form = id(new AphrontFormView()) - ->setUser($request->getUser()) - ->setAction('/differential/revision/edit/') - ->addHiddenInput('diffID', $diff->getID()) - ->addHiddenInput('viaDiffView', 1) - ->addHiddenInput( - id(new DifferentialRepositoryField())->getFieldKey(), - $diff->getRepositoryPHID()) + ->setViewer($viewer) ->appendRemarkupInstructions( pht( 'Review the diff for correctness. When you are satisfied, either '. '**create a new revision** or **update an existing revision**.')) ->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Attach To')) ->setValue($select)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Continue'))); $props = id(new DifferentialDiffProperty())->loadAllWhere( - 'diffID = %d', + 'diffID = %d', $diff->getID()); $props = mpull($props, 'getData', 'getName'); $property_head = id(new PHUIHeaderView()) ->setHeader(pht('Properties')); $property_view = new PHUIPropertyListView(); $changesets = $diff->loadChangesets(); $changesets = msort($changesets, 'getSortKey'); $table_of_contents = $this->buildTableOfContents( $changesets, $changesets, $diff->loadCoverageMap($viewer)); $refs = array(); foreach ($changesets as $changeset) { $refs[$changeset->getID()] = $changeset->getID(); } $details = id(new DifferentialChangesetListView()) ->setChangesets($changesets) ->setVisibleChangesets($changesets) ->setRenderingReferences($refs) ->setStandaloneURI('/differential/changeset/') ->setDiff($diff) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setTitle(pht('Diff %d', $diff->getID())) ->setUser($request->getUser()); $title = pht('Diff %d', $diff->getID()); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title); $crumbs->setBorder(true); $header = id(new PHUIHeaderView()) ->setHeader($title); $prop_box = id(new PHUIObjectBoxView()) ->setHeader($property_head) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addPropertyList($property_view) ->setForm($form); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setMainColumn(array( )) ->setFooter(array( $prop_box, $table_of_contents, $details, )); $page = $this->newPage() ->setTitle(pht('Diff View')) ->setCrumbs($crumbs) ->appendChild($view); return $page; } private function loadSelectableRevisions( PhabricatorUser $viewer, $selected_id) { $revisions = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withAuthors(array($viewer->getPHID())) ->withStatus(DifferentialRevisionQuery::STATUS_OPEN) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->execute(); $revisions = mpull($revisions, null, 'getID'); // If a specific revision is selected (for example, because the user is // following the "Update Diff" workflow), but not present in the dropdown, // try to add it to the dropdown even if it is closed. This allows the // workflow to be used to update abandoned revisions. if ($selected_id) { if (empty($revisions[$selected_id])) { $selected = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withAuthors(array($viewer->getPHID())) ->withIDs(array($selected_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->execute(); $revisions = mpull($selected, null, 'getID') + $revisions; } } return $revisions; } } diff --git a/src/applications/differential/controller/DifferentialRevisionEditController.php b/src/applications/differential/controller/DifferentialRevisionEditController.php index eb3aa08521..48fea82f7c 100644 --- a/src/applications/differential/controller/DifferentialRevisionEditController.php +++ b/src/applications/differential/controller/DifferentialRevisionEditController.php @@ -1,214 +1,56 @@ getViewer(); - $id = $request->getURIData('id'); - if (!$id) { - $id = $request->getInt('revisionID'); - } - - if ($id) { - $revision = id(new DifferentialRevisionQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->needRelationships(true) - ->needReviewerStatus(true) - ->needActiveDiffs(true) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$revision) { - return new Aphront404Response(); - } - } else { - $revision = DifferentialRevision::initializeNewRevision($viewer); - $revision->attachReviewerStatus(array()); - } + // If we have a Diff ID, this is an "/attach/123/to/456/" action. The + // user just created a diff and is trying to use it to create or update + // a revision. + $diff_id = $request->getURIData('diffID'); - $diff_id = $request->getInt('diffID'); if ($diff_id) { $diff = id(new DifferentialDiffQuery()) ->setViewer($viewer) ->withIDs(array($diff_id)) ->executeOne(); if (!$diff) { return new Aphront404Response(); } + if ($diff->getRevisionID()) { - // TODO: Redirect? - throw new Exception( - pht('This diff is already attached to a revision!')); + $revision = $diff->getRevision(); + return $this->newDialog() + ->setTitle(pht('Diff Already Attached')) + ->appendParagraph( + pht( + 'This diff is already attached to a revision.')) + ->addCancelButton($revision->getURI(), pht('Continue')); } } else { $diff = null; } - if (!$diff) { - if (!$revision->getID()) { - throw new Exception( - pht('You can not create a new revision without a diff!')); - } - } else { - // TODO: It would be nice to show the diff being attached in the UI. - } - - $field_list = PhabricatorCustomField::getObjectFields( - $revision, - PhabricatorCustomField::ROLE_EDIT); - $field_list - ->setViewer($viewer) - ->readFieldsFromStorage($revision); - - if ($request->getStr('viaDiffView') && $diff) { - $repo_key = id(new DifferentialRepositoryField())->getFieldKey(); - $repository_field = idx( - $field_list->getFields(), - $repo_key); - if ($repository_field) { - $repository_field->setValue($request->getStr($repo_key)); - } - $view_policy_key = id(new DifferentialViewPolicyField())->getFieldKey(); - $view_policy_field = idx( - $field_list->getFields(), - $view_policy_key); - if ($view_policy_field) { - $view_policy_field->setValue($diff->getViewPolicy()); - } + $revision_id = $request->getURIData('id'); + if (!$diff && !$revision_id) { + return $this->newDialog() + ->setTitle(pht('Diff Required')) + ->appendParagraph( + pht( + 'You can not create a revision without a diff.')) + ->addCancelButton($this->getApplicationURI()); } - $validation_exception = null; - if ($request->isFormPost() && !$request->getStr('viaDiffView')) { - - $editor = id(new DifferentialTransactionEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - $xactions = $field_list->buildFieldTransactionsFromRequest( - new DifferentialTransaction(), - $request); - - if ($diff) { - $repository_phid = null; - $repository_tokenizer = $request->getArr( - id(new DifferentialRepositoryField())->getFieldKey()); - if ($repository_tokenizer) { - $repository_phid = reset($repository_tokenizer); - } - - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) - ->setNewValue($diff->getPHID()); - - $editor->setRepositoryPHIDOverride($repository_phid); - } - - $comments = $request->getStr('comments'); - if (strlen($comments)) { - $xactions[] = id(new DifferentialTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) - ->attachComment( - id(new DifferentialTransactionComment()) - ->setContent($comments)); - } + $engine = id(new DifferentialRevisionEditEngine()) + ->setController($this); - try { - $editor->applyTransactions($revision, $xactions); - $revision_uri = '/D'.$revision->getID(); - return id(new AphrontRedirectResponse())->setURI($revision_uri); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - } - } - - - $form = new AphrontFormView(); - $form->setUser($request->getUser()); if ($diff) { - $form->addHiddenInput('diffID', $diff->getID()); - } - - if ($revision->getID()) { - $form->setAction('/differential/revision/edit/'.$revision->getID().'/'); - } else { - $form->setAction('/differential/revision/edit/'); - } - - if ($diff && $revision->getID()) { - $form - ->appendChild( - id(new AphrontFormTextAreaControl()) - ->setLabel(pht('Comments')) - ->setName('comments') - ->setCaption(pht("Explain what's new in this diff.")) - ->setValue($request->getStr('comments'))) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Save'))) - ->appendChild( - id(new AphrontFormDividerControl())); + $engine->setDiff($diff); } - $field_list->appendFieldsToForm($form); - - $submit = id(new AphrontFormSubmitControl()) - ->setValue('Save'); - if ($diff) { - $submit->addCancelButton('/differential/diff/'.$diff->getID().'/'); - } else { - $submit->addCancelButton('/D'.$revision->getID()); - } - - $form->appendChild($submit); - - $crumbs = $this->buildApplicationCrumbs(); - if ($revision->getID()) { - if ($diff) { - $header_icon = 'fa-upload'; - $title = pht('Update Revision'); - $crumbs->addTextCrumb( - 'D'.$revision->getID(), - '/differential/diff/'.$diff->getID().'/'); - } else { - $header_icon = 'fa-pencil'; - $title = pht('Edit Revision: %s', $revision->getTitle()); - $crumbs->addTextCrumb( - 'D'.$revision->getID(), - '/D'.$revision->getID()); - } - } else { - $header_icon = 'fa-plus-square'; - $title = pht('Create New Differential Revision'); - } - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText('Revision') - ->setValidationException($validation_exception) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($form); - - $crumbs->addTextCrumb($title); - $crumbs->setBorder(true); - - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon($header_icon); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter($form_box); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); + return $engine->buildResponse(); } } diff --git a/src/applications/differential/customfield/DifferentialApplyPatchField.php b/src/applications/differential/customfield/DifferentialApplyPatchField.php deleted file mode 100644 index 24665b7f5c..0000000000 --- a/src/applications/differential/customfield/DifferentialApplyPatchField.php +++ /dev/null @@ -1,32 +0,0 @@ -getFieldName(); - } - - public function renderPropertyViewValue(array $handles) { - $mono = $this->getObject()->getMonogram(); - - return phutil_tag('tt', array(), "arc patch {$mono}"); - } - -} diff --git a/src/applications/differential/customfield/DifferentialAuditorsField.php b/src/applications/differential/customfield/DifferentialAuditorsField.php index d84fe0eda8..544f238458 100644 --- a/src/applications/differential/customfield/DifferentialAuditorsField.php +++ b/src/applications/differential/customfield/DifferentialAuditorsField.php @@ -1,60 +1,55 @@ getValue()); + return phutil_json_encode($this->getValue()); } public function setValueFromStorage($value) { try { $this->setValue(phutil_json_decode($value)); } catch (PhutilJSONParserException $ex) { $this->setValue(array()); } return $this; } - public function shouldAppearInCommitMessage() { - return true; + public function canDisableField() { + return false; } - public function shouldAllowEditInCommitMessage() { + public function shouldAppearInEditEngine() { return true; } - public function canDisableField() { - return false; + public function shouldAppearInCommitMessage() { + return true; } - public function getRequiredHandlePHIDsForCommitMessage() { - return nonempty($this->getValue(), array()); + public function shouldAppearInConduitTransactions() { + return true; } - public function parseCommitMessageValue($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - )); + protected function newConduitEditParameterType() { + return new ConduitPHIDListParameterType(); } - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); + public function shouldAppearInApplicationTransactions() { + return true; } } diff --git a/src/applications/differential/customfield/DifferentialAuthorField.php b/src/applications/differential/customfield/DifferentialAuthorField.php deleted file mode 100644 index fbd74dd2ab..0000000000 --- a/src/applications/differential/customfield/DifferentialAuthorField.php +++ /dev/null @@ -1,38 +0,0 @@ -getFieldName(); - } - - public function getRequiredHandlePHIDsForPropertyView() { - return array($this->getObject()->getAuthorPHID()); - } - - public function renderPropertyViewValue(array $handles) { - return $handles[$this->getObject()->getAuthorPHID()]->renderHovercardLink(); - } - -} diff --git a/src/applications/differential/customfield/DifferentialBlameRevisionField.php b/src/applications/differential/customfield/DifferentialBlameRevisionField.php index ba2220ae30..b2d8872225 100644 --- a/src/applications/differential/customfield/DifferentialBlameRevisionField.php +++ b/src/applications/differential/customfield/DifferentialBlameRevisionField.php @@ -1,117 +1,110 @@ getFieldName(); } public function renderPropertyViewValue(array $handles) { + if (!strlen($this->getValue())) { + return null; + } + return $this->getValue(); } public function shouldAppearInEditView() { return true; } public function shouldAppearInApplicationTransactions() { return true; } public function getOldValueForApplicationTransactions() { return $this->getValue(); } public function getNewValueForApplicationTransactions() { return $this->getValue(); } public function readValueFromRequest(AphrontRequest $request) { $this->setValue($request->getStr($this->getFieldKey())); } public function renderEditControl(array $handles) { return id(new AphrontFormTextControl()) ->setName($this->getFieldKey()) ->setValue($this->getValue()) ->setLabel($this->getFieldName()); } public function getApplicationTransactionTitle( PhabricatorApplicationTransaction $xaction) { $author_phid = $xaction->getAuthorPHID(); $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); return pht( '%s updated the blame revision for this revision.', $xaction->renderHandleLink($author_phid)); } public function getApplicationTransactionTitleForFeed( PhabricatorApplicationTransaction $xaction) { $object_phid = $xaction->getObjectPHID(); $author_phid = $xaction->getAuthorPHID(); $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); return pht( '%s updated the blame revision for %s.', $xaction->renderHandleLink($author_phid), $xaction->renderHandleLink($object_phid)); } public function shouldAppearInCommitMessage() { return true; } - public function shouldAllowEditInCommitMessage() { + public function shouldAppearInConduitDictionary() { return true; } - public function shouldOverwriteWhenCommitMessageIsEdited() { + public function shouldAppearInConduitTransactions() { return true; } - public function getCommitMessageLabels() { - return array( - 'Blame Revision', - 'Blame Rev', - ); - } - - public function renderCommitMessageValue(array $handles) { - return $this->getValue(); - } - - public function shouldAppearInConduitDictionary() { - return true; + protected function newConduitEditParameterType() { + return new ConduitStringParameterType(); } } diff --git a/src/applications/differential/customfield/DifferentialChildRevisionsField.php b/src/applications/differential/customfield/DifferentialChildRevisionsField.php deleted file mode 100644 index 1d9406a448..0000000000 --- a/src/applications/differential/customfield/DifferentialChildRevisionsField.php +++ /dev/null @@ -1,22 +0,0 @@ -setFieldError(null); $errors = parent::validateApplicationTransactions( $editor, $type, $xactions); $transaction = null; foreach ($xactions as $xaction) { $value = $xaction->getNewValue(); if ($this->isCoreFieldRequired()) { if ($this->isCoreFieldValueEmpty($value)) { $error = new PhabricatorApplicationTransactionValidationError( $type, pht('Required'), $this->getCoreFieldRequiredErrorString(), $xaction); $error->setIsMissingFieldError(true); $errors[] = $error; $this->setFieldError(pht('Required')); continue; } } if (is_string($value)) { $parser = $this->getFieldParser(); $result = $parser->parseCorpus($value); unset($result['__title__']); unset($result['__summary__']); if ($result) { $error = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), pht( 'The value you have entered in "%s" can not be parsed '. 'unambiguously when rendered in a commit message. Edit the '. 'message so that keywords like "Summary:" and "Test Plan:" do '. 'not appear at the beginning of lines. Parsed keys: %s.', $this->getFieldName(), implode(', ', array_keys($result))), $xaction); $errors[] = $error; $this->setFieldError(pht('Invalid')); continue; } } } return $errors; } private function getFieldParser() { if (!$this->fieldParser) { $viewer = $this->getViewer(); $parser = DifferentialCommitMessageParser::newStandardParser($viewer); // Set custom title and summary keys so we can detect the presence of // "Summary:" in, e.g., a test plan. $parser->setTitleKey('__title__'); $parser->setSummaryKey('__summary__'); $this->fieldParser = $parser; } return $this->fieldParser; } public function canDisableField() { return false; } public function shouldAppearInApplicationTransactions() { return true; } - public function shouldAppearInEditView() { - return true; - } - public function readValueFromObject(PhabricatorCustomFieldInterface $object) { if ($this->isCoreFieldRequired()) { $this->setFieldError(true); } $this->setValue($this->readValueFromRevision($object)); } public function getOldValueForApplicationTransactions() { return $this->readValueFromRevision($this->getObject()); } public function getNewValueForApplicationTransactions() { return $this->getValue(); } public function applyApplicationTransactionInternalEffects( PhabricatorApplicationTransaction $xaction) { $this->writeValueToRevision($this->getObject(), $xaction->getNewValue()); } public function setFieldError($field_error) { $this->fieldError = $field_error; return $this; } public function getFieldError() { return $this->fieldError; } public function setValue($value) { $this->value = $value; return $this; } public function getValue() { return $this->value; } public function readValueFromCommitMessage($value) { $this->setValue($value); return $this; } public function renderCommitMessageValue(array $handles) { return $this->getValue(); } public function getConduitDictionaryValue() { return $this->getValue(); } } diff --git a/src/applications/differential/customfield/DifferentialCustomField.php b/src/applications/differential/customfield/DifferentialCustomField.php index d0980736c4..f210dd0f63 100644 --- a/src/applications/differential/customfield/DifferentialCustomField.php +++ b/src/applications/differential/customfield/DifferentialCustomField.php @@ -1,263 +1,268 @@ getFieldKey(); } + // TODO: As above. + public function getModernFieldKey() { + return $this->getFieldKeyForConduit(); + } + public function shouldEnableForRole($role) { switch ($role) { case self::ROLE_COMMITMESSAGE: return $this->shouldAppearInCommitMessage(); case self::ROLE_COMMITMESSAGEEDIT: return $this->shouldAppearInCommitMessage() && $this->shouldAllowEditInCommitMessage(); } return parent::shouldEnableForRole($role); } protected function parseObjectList( $value, array $types, $allow_partial = false, array $suffixes = array()) { return id(new PhabricatorObjectListQuery()) ->setViewer($this->getViewer()) ->setAllowedTypes($types) ->setObjectList($value) ->setAllowPartialResults($allow_partial) ->setSuffixes($suffixes) ->execute(); } protected function renderObjectList( array $handles, array $suffixes = array()) { if (!$handles) { return null; } $out = array(); foreach ($handles as $handle) { $phid = $handle->getPHID(); if ($handle->getPolicyFiltered()) { $token = $phid; } else if ($handle->isComplete()) { $token = $handle->getCommandLineObjectName(); } $suffix = idx($suffixes, $phid); $token = $token.$suffix; $out[] = $token; } return implode(', ', $out); } public function getWarningsForDetailView() { if ($this->getProxy()) { return $this->getProxy()->getWarningsForDetailView(); } return array(); } public function getRequiredHandlePHIDsForRevisionHeaderWarnings() { return array(); } public function getWarningsForRevisionHeader(array $handles) { return array(); } /* -( Integration with Commit Messages )----------------------------------- */ /** * @task commitmessage */ public function shouldAppearInCommitMessage() { if ($this->getProxy()) { return $this->getProxy()->shouldAppearInCommitMessage(); } return false; } /** * @task commitmessage */ public function shouldAppearInCommitMessageTemplate() { if ($this->getProxy()) { return $this->getProxy()->shouldAppearInCommitMessageTemplate(); } return false; } /** * @task commitmessage */ public function shouldAllowEditInCommitMessage() { if ($this->getProxy()) { return $this->getProxy()->shouldAllowEditInCommitMessage(); } return true; } /** * @task commitmessage */ public function getProTips() { if ($this->getProxy()) { return $this->getProxy()->getProTips(); } return array(); } /** * @task commitmessage */ public function getCommitMessageLabels() { if ($this->getProxy()) { return $this->getProxy()->getCommitMessageLabels(); } return array($this->renderCommitMessageLabel()); } /** * @task commitmessage */ public function parseValueFromCommitMessage($value) { if ($this->getProxy()) { return $this->getProxy()->parseValueFromCommitMessage($value); } return $value; } /** * @task commitmessage */ public function readValueFromCommitMessage($value) { if ($this->getProxy()) { $this->getProxy()->readValueFromCommitMessage($value); return $this; } return $this; } /** * @task commitmessage */ public function shouldOverwriteWhenCommitMessageIsEdited() { if ($this->getProxy()) { return $this->getProxy()->shouldOverwriteWhenCommitMessageIsEdited(); } return false; } /** * @task commitmessage */ public function getRequiredHandlePHIDsForCommitMessage() { if ($this->getProxy()) { return $this->getProxy()->getRequiredHandlePHIDsForCommitMessage(); } return array(); } /** * @task commitmessage */ public function renderCommitMessageLabel() { if ($this->getProxy()) { return $this->getProxy()->renderCommitMessageLabel(); } return $this->getFieldName(); } /** * @task commitmessage */ public function renderCommitMessageValue(array $handles) { if ($this->getProxy()) { return $this->getProxy()->renderCommitMessageValue($handles); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * @task commitmessage */ public function validateCommitMessageValue($value) { if ($this->getProxy()) { return $this->getProxy()->validateCommitMessageValue($value); } return; } /* -( Integration with Diff Properties )----------------------------------- */ /** * @task diff */ public function shouldAppearInDiffPropertyView() { if ($this->getProxy()) { return $this->getProxy()->shouldAppearInDiffPropertyView(); } return false; } /** * @task diff */ public function renderDiffPropertyViewLabel(DifferentialDiff $diff) { if ($this->proxy) { return $this->proxy->renderDiffPropertyViewLabel($diff); } return $this->getFieldName(); } /** * @task diff */ public function renderDiffPropertyViewValue(DifferentialDiff $diff) { if ($this->proxy) { return $this->proxy->renderDiffPropertyViewValue($diff); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } } diff --git a/src/applications/differential/customfield/DifferentialEditPolicyField.php b/src/applications/differential/customfield/DifferentialEditPolicyField.php deleted file mode 100644 index 8175fa2b5b..0000000000 --- a/src/applications/differential/customfield/DifferentialEditPolicyField.php +++ /dev/null @@ -1,50 +0,0 @@ -getEditPolicy(); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - $viewer = $this->getViewer(); - $revision = $this->getObject(); - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($revision) - ->execute(); - - return id(new AphrontFormPolicyControl()) - ->setUser($viewer) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicyObject($revision) - ->setPolicies($policies) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDIT_POLICY; - } - -} diff --git a/src/applications/differential/customfield/DifferentialGitSVNIDField.php b/src/applications/differential/customfield/DifferentialGitSVNIDField.php deleted file mode 100644 index de45c54c7f..0000000000 --- a/src/applications/differential/customfield/DifferentialGitSVNIDField.php +++ /dev/null @@ -1,45 +0,0 @@ -getValue()); } public function setValueFromStorage($value) { try { $this->setValue(phutil_json_decode($value)); } catch (PhutilJSONParserException $ex) { $this->setValue(array()); } return $this; } public function getFieldName() { return pht('JIRA Issues'); } public function getFieldDescription() { return pht('Lists associated JIRA issues.'); } public function shouldAppearInPropertyView() { return true; } public function renderPropertyViewLabel() { return $this->getFieldName(); } public function renderPropertyViewValue(array $handles) { $xobjs = $this->loadDoorkeeperExternalObjects($this->getValue()); if (!$xobjs) { return null; } $links = array(); foreach ($xobjs as $xobj) { $links[] = id(new DoorkeeperTagView()) ->setExternalObject($xobj); } return phutil_implode_html(phutil_tag('br'), $links); } private function buildDoorkeeperRefs($value) { $provider = PhabricatorJIRAAuthProvider::getJIRAProvider(); $refs = array(); if ($value) { foreach ($value as $jira_key) { $refs[] = id(new DoorkeeperObjectRef()) ->setApplicationType(DoorkeeperBridgeJIRA::APPTYPE_JIRA) ->setApplicationDomain($provider->getProviderDomain()) ->setObjectType(DoorkeeperBridgeJIRA::OBJTYPE_ISSUE) ->setObjectID($jira_key); } } return $refs; } private function loadDoorkeeperExternalObjects($value) { $refs = $this->buildDoorkeeperRefs($value); if (!$refs) { return array(); } $xobjs = id(new DoorkeeperExternalObjectQuery()) ->setViewer($this->getViewer()) ->withObjectKeys(mpull($refs, 'getObjectKey')) ->execute(); return $xobjs; } public function shouldAppearInEditView() { return PhabricatorJIRAAuthProvider::getJIRAProvider(); } public function shouldAppearInApplicationTransactions() { return PhabricatorJIRAAuthProvider::getJIRAProvider(); } public function readValueFromRequest(AphrontRequest $request) { $this->setValue($request->getStrList($this->getFieldKey())); return $this; } public function renderEditControl(array $handles) { return id(new AphrontFormTextControl()) ->setLabel(pht('JIRA Issues')) ->setCaption( pht('Example: %s', phutil_tag('tt', array(), 'JIS-3, JIS-9'))) ->setName($this->getFieldKey()) ->setValue(implode(', ', nonempty($this->getValue(), array()))) ->setError($this->error); } public function getOldValueForApplicationTransactions() { return array_unique(nonempty($this->getValue(), array())); } public function getNewValueForApplicationTransactions() { return array_unique(nonempty($this->getValue(), array())); } public function validateApplicationTransactions( PhabricatorApplicationTransactionEditor $editor, $type, array $xactions) { $this->error = null; $errors = parent::validateApplicationTransactions( $editor, $type, $xactions); $transaction = null; foreach ($xactions as $xaction) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $add = array_diff($new, $old); if (!$add) { continue; } // Only check that the actor can see newly added JIRA refs. You're // allowed to remove refs or make no-op changes even if you aren't // linked to JIRA. try { $refs = id(new DoorkeeperImportEngine()) ->setViewer($this->getViewer()) ->setRefs($this->buildDoorkeeperRefs($add)) ->setThrowOnMissingLink(true) ->execute(); } catch (DoorkeeperMissingLinkException $ex) { $this->error = pht('Not Linked'); $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Not Linked'), pht( 'You can not add JIRA issues (%s) to this revision because your '. 'Phabricator account is not linked to a JIRA account.', implode(', ', $add)), $xaction); continue; } $bad = array(); foreach ($refs as $ref) { if (!$ref->getIsVisible()) { $bad[] = $ref->getObjectID(); } } if ($bad) { $bad = implode(', ', $bad); $this->error = pht('Invalid'); $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), pht( 'Some JIRA issues could not be loaded. They may not exist, or '. 'you may not have permission to view them: %s', $bad), $xaction); } } return $errors; } public function getApplicationTransactionTitle( PhabricatorApplicationTransaction $xaction) { $old = $xaction->getOldValue(); if (!is_array($old)) { $old = array(); } $new = $xaction->getNewValue(); if (!is_array($new)) { $new = array(); } $add = array_diff($new, $old); $rem = array_diff($old, $new); $author_phid = $xaction->getAuthorPHID(); if ($add && $rem) { return pht( '%s updated JIRA issue(s): added %d %s; removed %d %s.', $xaction->renderHandleLink($author_phid), phutil_count($add), implode(', ', $add), phutil_count($rem), implode(', ', $rem)); } else if ($add) { return pht( '%s added %d JIRA issue(s): %s.', $xaction->renderHandleLink($author_phid), phutil_count($add), implode(', ', $add)); } else if ($rem) { return pht( '%s removed %d JIRA issue(s): %s.', $xaction->renderHandleLink($author_phid), phutil_count($rem), implode(', ', $rem)); } return parent::getApplicationTransactionTitle($xaction); } public function applyApplicationTransactionExternalEffects( PhabricatorApplicationTransaction $xaction) { // Update the CustomField storage. parent::applyApplicationTransactionExternalEffects($xaction); // Now, synchronize the Doorkeeper edges. $revision = $this->getObject(); $revision_phid = $revision->getPHID(); $edge_type = PhabricatorJiraIssueHasObjectEdgeType::EDGECONST; $xobjs = $this->loadDoorkeeperExternalObjects($xaction->getNewValue()); $edge_dsts = mpull($xobjs, 'getPHID'); $edges = PhabricatorEdgeQuery::loadDestinationPHIDs( $revision_phid, $edge_type); $editor = new PhabricatorEdgeEditor(); foreach (array_diff($edges, $edge_dsts) as $rem_edge) { $editor->removeEdge($revision_phid, $edge_type, $rem_edge); } foreach (array_diff($edge_dsts, $edges) as $add_edge) { $editor->addEdge($revision_phid, $edge_type, $add_edge); } $editor->save(); } public function shouldAppearInCommitMessage() { return true; } public function shouldAppearInCommitMessageTemplate() { return true; } public function getCommitMessageLabels() { return array( 'JIRA', 'JIRA Issues', 'JIRA Issue', ); } public function parseValueFromCommitMessage($value) { return preg_split('/[\s,]+/', $value, $limit = -1, PREG_SPLIT_NO_EMPTY); } public function readValueFromCommitMessage($value) { $this->setValue($value); return $this; } - - public function renderCommitMessageValue(array $handles) { $value = $this->getValue(); if (!$value) { return null; } return implode(', ', $value); } public function shouldAppearInConduitDictionary() { return true; } + public function shouldAppearInConduitTransactions() { + return true; + } + + protected function newConduitEditParameterType() { + return new ConduitStringListParameterType(); + } } diff --git a/src/applications/differential/customfield/DifferentialManiphestTasksField.php b/src/applications/differential/customfield/DifferentialManiphestTasksField.php index 56803f60c3..8e70f1da4d 100644 --- a/src/applications/differential/customfield/DifferentialManiphestTasksField.php +++ b/src/applications/differential/customfield/DifferentialManiphestTasksField.php @@ -1,115 +1,48 @@ getFieldName(); } protected function readValueFromRevision(DifferentialRevision $revision) { if (!$revision->getPHID()) { return array(); } return PhabricatorEdgeQuery::loadDestinationPHIDs( $revision->getPHID(), DifferentialRevisionHasTaskEdgeType::EDGECONST); } - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDGE; - } - - public function getApplicationTransactionMetadata() { - return array( - 'edge:type' => DifferentialRevisionHasTaskEdgeType::EDGECONST, - ); - } - - public function getNewValueForApplicationTransactions() { - $edges = array(); - foreach ($this->getValue() as $phid) { - $edges[$phid] = $phid; - } - - return array('=' => $edges); - } - public function getRequiredHandlePHIDsForPropertyView() { return $this->getValue(); } public function renderPropertyViewValue(array $handles) { return $this->renderHandleList($handles); } - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Maniphest Task', - 'Maniphest Tasks', - ); - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - ManiphestTaskPHIDType::TYPECONST, - )); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getRequiredHandlePHIDsForPropertyView(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - - public function getProTips() { - return array( - pht( - 'Write "%s" in your summary to automatically close the '. - 'corresponding task when this change lands.', - 'Fixes T123'), - ); - } - } diff --git a/src/applications/differential/customfield/DifferentialNextStepField.php b/src/applications/differential/customfield/DifferentialNextStepField.php deleted file mode 100644 index bf0ed5972d..0000000000 --- a/src/applications/differential/customfield/DifferentialNextStepField.php +++ /dev/null @@ -1,65 +0,0 @@ -getFieldName(); - } - - public function renderPropertyViewValue(array $handles) { - $revision = $this->getObject(); - $diff = $revision->getActiveDiff(); - - $status = $revision->getStatus(); - if ($status != ArcanistDifferentialRevisionStatus::ACCEPTED) { - return null; - } - - $local_vcs = $diff->getSourceControlSystem(); - switch ($local_vcs) { - case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: - $bookmark = $diff->getBookmark(); - if (strlen($bookmark)) { - $next_step = csprintf('arc land %R', $bookmark); - } else { - $next_step = csprintf('arc land'); - } - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: - $branch = $diff->getBranch(); - if (strlen($branch)) { - $next_step = csprintf('arc land %R', $branch); - } else { - $next_step = csprintf('arc land'); - } - break; - case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: - $next_step = csprintf('arc commit'); - break; - default: - return null; - } - - $next_step = phutil_tag('tt', array(), (string)$next_step); - - return $next_step; - } - -} diff --git a/src/applications/differential/customfield/DifferentialParentRevisionsField.php b/src/applications/differential/customfield/DifferentialParentRevisionsField.php deleted file mode 100644 index 5dbc99dd6f..0000000000 --- a/src/applications/differential/customfield/DifferentialParentRevisionsField.php +++ /dev/null @@ -1,44 +0,0 @@ -getObject()->getPHID(), - DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST); - } - -} diff --git a/src/applications/differential/customfield/DifferentialProjectReviewersField.php b/src/applications/differential/customfield/DifferentialProjectReviewersField.php index c900f72659..87ea0c34a3 100644 --- a/src/applications/differential/customfield/DifferentialProjectReviewersField.php +++ b/src/applications/differential/customfield/DifferentialProjectReviewersField.php @@ -1,69 +1,60 @@ getFieldName(); } public function getRequiredHandlePHIDsForPropertyView() { return mpull($this->getProjectReviewers(), 'getReviewerPHID'); } public function renderPropertyViewValue(array $handles) { $reviewers = $this->getProjectReviewers(); if (!$reviewers) { return null; } $view = id(new DifferentialReviewersView()) ->setUser($this->getViewer()) ->setReviewers($reviewers) ->setHandles($handles); // TODO: Active diff stuff. return $view; } private function getProjectReviewers() { $reviewers = array(); foreach ($this->getObject()->getReviewerStatus() as $reviewer) { if (!$reviewer->isUser()) { $reviewers[] = $reviewer; } } return $reviewers; } - public function getProTips() { - return array( - pht( - 'You can add a project as a subscriber or reviewer by writing '. - '"%s" in the appropriate field.', - '#projectname'), - ); - } - } diff --git a/src/applications/differential/customfield/DifferentialProjectsField.php b/src/applications/differential/customfield/DifferentialProjectsField.php deleted file mode 100644 index 425e30e132..0000000000 --- a/src/applications/differential/customfield/DifferentialProjectsField.php +++ /dev/null @@ -1,114 +0,0 @@ -getPHID()) { - return array(); - } - - $projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $revision->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $projects = array_reverse($projects); - - return $projects; - } - - public function getNewValueForApplicationTransactions() { - return array('=' => array_fuse($this->getValue())); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getArr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new PhabricatorProjectDatasource()) - ->setValue($this->getValue()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDGE; - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Tags', - 'Project', - 'Projects', - ); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getValue(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - - public function shouldAppearInConduitDictionary() { - // To improve performance, we exclude this field from Conduit results. - // See T11404 for discussion. In modern "differential.revision.search", - // this information is available efficiently as an attachment. - return false; - } - - public function getApplicationTransactionMetadata() { - return array( - 'edge:type' => PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, - ); - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorProjectProjectPHIDType::TYPECONST, - )); - } - -} diff --git a/src/applications/differential/customfield/DifferentialRepositoryField.php b/src/applications/differential/customfield/DifferentialRepositoryField.php index 7f39d25823..1d403d160a 100644 --- a/src/applications/differential/customfield/DifferentialRepositoryField.php +++ b/src/applications/differential/customfield/DifferentialRepositoryField.php @@ -1,167 +1,66 @@ getRepositoryPHID(); } - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setRepositoryPHID($value); - } - - public function readValueFromRequest(AphrontRequest $request) { - $phids = $request->getArr($this->getFieldKey()); - $first = head($phids); - $this->setValue(nonempty($first, null)); - } - - public function renderEditControl(array $handles) { - if ($this->getValue()) { - $value = array($this->getValue()); - } else { - $value = array(); - } - - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new DiffusionRepositoryDatasource()) - ->setValue($value) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()) - ->setLimit(1); - } - - public function getApplicationTransactionRequiredHandlePHIDs( - PhabricatorApplicationTransaction $xaction) { - - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - $phids = array(); - if ($old) { - $phids[] = $old; - } - if ($new) { - $phids[] = $new; - } - - return $phids; - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if ($old && $new) { - return pht( - '%s changed the repository for this revision from %s to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($old), - $xaction->renderHandleLink($new)); - } else if ($new) { - return pht( - '%s set the repository for this revision to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($new)); - } else { - return pht( - '%s removed %s as the repository for this revision.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($old)); - } - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if ($old && $new) { - return pht( - '%s updated the repository for %s from %s to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $xaction->renderHandleLink($old), - $xaction->renderHandleLink($new)); - } else if ($new) { - return pht( - '%s set the repository for %s to %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $xaction->renderHandleLink($new)); - } else { - return pht( - '%s removed the repository for %s. (Repository was %s.)', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $xaction->renderHandleLink($old)); - } - } - public function shouldAppearInPropertyView() { return true; } public function renderPropertyViewValue(array $handles) { return null; } public function shouldAppearInDiffPropertyView() { return true; } public function renderDiffPropertyViewLabel(DifferentialDiff $diff) { return $this->getFieldName(); } public function renderDiffPropertyViewValue(DifferentialDiff $diff) { if (!$diff->getRepositoryPHID()) { return null; } return $this->getViewer()->renderHandle($diff->getRepositoryPHID()); } public function shouldAppearInTransactionMail() { return true; } public function updateTransactionMailBody( PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions) { $repository = $this->getObject()->getRepository(); if ($repository === null) { return; } $body->addTextSection( pht('REPOSITORY'), $repository->getMonogram().' '.$repository->getName()); } } diff --git a/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php b/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php index 2408daa27c..421c129fdb 100644 --- a/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php +++ b/src/applications/differential/customfield/DifferentialRequiredSignaturesField.php @@ -1,145 +1,141 @@ getPHID()) { return array(); } $phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $revision->getPHID(), LegalpadObjectNeedsSignatureEdgeType::EDGECONST); if ($phids) { // NOTE: We're bypassing permissions to pull these. We have to expose // some information about signature status in order to implement this // field meaningfully (otherwise, we could not tell reviewers that they // can't accept the revision yet), but that's OK because the only way to // require signatures is with a "Global" Herald rule, which requires a // high level of access. $signatures = id(new LegalpadDocumentSignatureQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withDocumentPHIDs($phids) ->withSignerPHIDs(array($revision->getAuthorPHID())) ->execute(); $signatures = mpull($signatures, null, 'getDocumentPHID'); $phids = array_fuse($phids); foreach ($phids as $phid) { $phids[$phid] = isset($signatures[$phid]); } } return $phids; } public function getRequiredHandlePHIDsForPropertyView() { return array_keys($this->getValue()); } public function renderPropertyViewValue(array $handles) { if (!$handles) { return null; } $author_phid = $this->getObject()->getAuthorPHID(); $viewer_phid = $this->getViewer()->getPHID(); $viewer_is_author = ($author_phid == $viewer_phid); $view = new PHUIStatusListView(); foreach ($handles as $handle) { $item = id(new PHUIStatusItemView()) ->setTarget($handle->renderLink()); // NOTE: If the viewer isn't the author, we just show generic document // icons, because the granular information isn't very useful and there // is no need to disclose it. // If the viewer is the author, we show exactly what they need to sign. if (!$viewer_is_author) { $item->setIcon('fa-file-text-o bluegrey'); } else { if (idx($this->getValue(), $handle->getPHID())) { $item->setIcon('fa-check-square-o green'); } else { $item->setIcon('fa-times red'); } } $view->addItem($item); } return $view; } public function getWarningsForDetailView() { if (!$this->haveAnyUnsignedDocuments()) { return array(); } return array( pht( 'The author of this revision has not signed all the required '. 'legal documents. The revision can not be accepted until the '. 'documents are signed.'), ); } private function haveAnyUnsignedDocuments() { foreach ($this->getValue() as $phid => $signed) { if (!$signed) { return true; } } return false; } public function getWarningsForRevisionHeader(array $handles) { if (!$this->haveAnyUnsignedDocuments()) { return array(); } return array( pht( 'This revision can not be accepted until the required legal '. 'agreements have been signed.'), ); } } diff --git a/src/applications/differential/customfield/DifferentialRevertPlanField.php b/src/applications/differential/customfield/DifferentialRevertPlanField.php index 646116c74e..0fd5531426 100644 --- a/src/applications/differential/customfield/DifferentialRevertPlanField.php +++ b/src/applications/differential/customfield/DifferentialRevertPlanField.php @@ -1,145 +1,153 @@ getFieldName(); } public function getStyleForPropertyView() { return 'block'; } public function getIconForPropertyView() { return PHUIPropertyListView::ICON_TESTPLAN; } public function renderPropertyViewValue(array $handles) { if (!strlen($this->getValue())) { return null; } return new PHUIRemarkupView($this->getViewer(), $this->getValue()); } public function shouldAppearInGlobalSearch() { return true; } public function updateAbstractDocument( PhabricatorSearchAbstractDocument $document) { if (strlen($this->getValue())) { $document->addField('rvrt', $this->getValue()); } } public function shouldAppearInEditView() { return true; } public function shouldAppearInApplicationTransactions() { return true; } public function getOldValueForApplicationTransactions() { return $this->getValue(); } public function getNewValueForApplicationTransactions() { return $this->getValue(); } public function readValueFromRequest(AphrontRequest $request) { $this->setValue($request->getStr($this->getFieldKey())); } public function renderEditControl(array $handles) { return id(new PhabricatorRemarkupControl()) ->setUser($this->getViewer()) ->setName($this->getFieldKey()) ->setValue($this->getValue()) ->setLabel($this->getFieldName()); } public function getApplicationTransactionTitle( PhabricatorApplicationTransaction $xaction) { $author_phid = $xaction->getAuthorPHID(); $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); return pht( '%s updated the revert plan for this revision.', $xaction->renderHandleLink($author_phid)); } public function getApplicationTransactionTitleForFeed( PhabricatorApplicationTransaction $xaction) { $object_phid = $xaction->getObjectPHID(); $author_phid = $xaction->getAuthorPHID(); $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); return pht( '%s updated the revert plan for %s.', $xaction->renderHandleLink($author_phid), $xaction->renderHandleLink($object_phid)); } public function getApplicationTransactionHasChangeDetails( PhabricatorApplicationTransaction $xaction) { return true; } public function getApplicationTransactionChangeDetails( PhabricatorApplicationTransaction $xaction, PhabricatorUser $viewer) { return $xaction->renderTextCorpusChangeDetails( $viewer, $xaction->getOldValue(), $xaction->getNewValue()); } public function getApplicationTransactionRemarkupBlocks( PhabricatorApplicationTransaction $xaction) { return array($xaction->getNewValue()); } public function shouldAppearInCommitMessage() { return true; } public function renderCommitMessageValue(array $handles) { return $this->getValue(); } public function shouldAppearInConduitDictionary() { return true; } + public function shouldAppearInConduitTransactions() { + return true; + } + + protected function newConduitEditParameterType() { + return new ConduitStringParameterType(); + } + } diff --git a/src/applications/differential/customfield/DifferentialReviewedByField.php b/src/applications/differential/customfield/DifferentialReviewedByField.php deleted file mode 100644 index 6f49c80fef..0000000000 --- a/src/applications/differential/customfield/DifferentialReviewedByField.php +++ /dev/null @@ -1,72 +0,0 @@ -getReviewerStatus() as $reviewer) { - switch ($reviewer->getStatus()) { - case DifferentialReviewerStatus::STATUS_ACCEPTED: - case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER: - $phids[] = $reviewer->getReviewerPHID(); - break; - } - } - - return $phids; - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - ), - $allow_partial = true); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getValue(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - -} diff --git a/src/applications/differential/customfield/DifferentialReviewersField.php b/src/applications/differential/customfield/DifferentialReviewersField.php index 41a4cf8f26..ad96a22b88 100644 --- a/src/applications/differential/customfield/DifferentialReviewersField.php +++ b/src/applications/differential/customfield/DifferentialReviewersField.php @@ -1,331 +1,92 @@ getReviewerStatus(); } - public function getNewValueForApplicationTransactions() { - $specs = array(); - foreach ($this->getValue() as $reviewer) { - $specs[$reviewer->getReviewerPHID()] = array( - 'data' => $reviewer->getEdgeData(), - ); - } - - return array('=' => $specs); - } - - public function readValueFromRequest(AphrontRequest $request) { - $datasource = id(new DifferentialBlockingReviewerDatasource()) - ->setViewer($request->getViewer()); - - $new_phids = $request->getArr($this->getFieldKey()); - $new_phids = $datasource->evaluateTokens($new_phids); - - $reviewers = array(); - foreach ($new_phids as $spec) { - if (!is_array($spec)) { - $reviewers[$spec] = DifferentialReviewerStatus::STATUS_ADDED; - } else { - $reviewers[$spec['phid']] = $spec['type']; - } - } - - $this->updateReviewers($this->getValue(), $reviewers); - } - - private function updateReviewers(array $old_reviewers, array $new_map) { - // Compute a new set of reviewer objects. We're going to respect the new - // reviewer order, add or remove any new or missing reviewers, and respect - // any blocking or unblocking changes. For reviewers who were there before - // and are still there, we're going to keep the old value because it - // may be something like "Accept", "Reject", etc. - - $old_map = mpull($old_reviewers, 'getStatus', 'getReviewerPHID'); - $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; - - $new_reviewers = array(); - foreach ($new_map as $phid => $new) { - $old = idx($old_map, $phid); - - // If we have an old status and this didn't make the reviewer blocking - // or nonblocking, just retain the old status. This makes sure we don't - // throw away rejects, accepts, etc. - if ($old) { - $is_block = ($old !== $status_blocking && $new === $status_blocking); - $is_unblock = ($old === $status_blocking && $new !== $status_blocking); - if (!$is_block && !$is_unblock) { - $new_reviewers[$phid] = $old; - continue; - } - } - - $new_reviewers[$phid] = $new; - } - - foreach ($new_reviewers as $phid => $status) { - $new_reviewers[$phid] = new DifferentialReviewer( - $phid, - array( - 'status' => $status, - )); - } - - $this->setValue($new_reviewers); - } - - public function renderEditControl(array $handles) { - $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; - - $value = array(); - foreach ($this->getValue() as $reviewer) { - $phid = $reviewer->getReviewerPHID(); - if ($reviewer->getStatus() == $status_blocking) { - $value[] = 'blocking('.$phid.')'; - } else { - $value[] = $phid; - } - } - - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new DifferentialReviewerDatasource()) - ->setValue($value) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_EDGE; - } - - public function getApplicationTransactionMetadata() { - return array( - 'edge:type' => DifferentialRevisionHasReviewerEdgeType::EDGECONST, - ); - } - public function shouldAppearInPropertyView() { return true; } public function renderPropertyViewLabel() { return $this->getFieldName(); } public function getRequiredHandlePHIDsForPropertyView() { return mpull($this->getUserReviewers(), 'getReviewerPHID'); } public function renderPropertyViewValue(array $handles) { $reviewers = $this->getUserReviewers(); if (!$reviewers) { return phutil_tag('em', array(), pht('None')); } $view = id(new DifferentialReviewersView()) ->setUser($this->getViewer()) ->setReviewers($reviewers) ->setHandles($handles); // TODO: Active diff stuff. return $view; } private function getUserReviewers() { $reviewers = array(); foreach ($this->getObject()->getReviewerStatus() as $reviewer) { if ($reviewer->isUser()) { $reviewers[] = $reviewer; } } return $reviewers; } - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Reviewer', - 'Reviewers', - ); - } - - public function parseValueFromCommitMessage($value) { - $results = $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - PhabricatorOwnersPackagePHIDType::TYPECONST, - ), - false, - array('!')); - - return $this->flattenReviewers($results); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return mpull($this->getValue(), 'getReviewerPHID'); - } - - public function readValueFromCommitMessage($value) { - $value = $this->inflateReviewers($value); - - $reviewers = array(); - foreach ($value as $spec) { - $phid = $spec['phid']; - - $is_blocking = isset($spec['suffixes']['!']); - if ($is_blocking) { - $status = DifferentialReviewerStatus::STATUS_BLOCKING; - } else { - $status = DifferentialReviewerStatus::STATUS_ADDED; - } - - $reviewers[$phid] = $status; - } - - $this->updateReviewers( - $this->getObject()->getReviewerStatus(), - $reviewers); - - return $this; - } - - public function renderCommitMessageValue(array $handles) { - $suffixes = array(); - - $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; - - foreach ($this->getValue() as $reviewer) { - if ($reviewer->getStatus() == $status_blocking) { - $phid = $reviewer->getReviewerPHID(); - $suffixes[$phid] = '!'; - } - } - - return $this->renderObjectList($handles, $suffixes); - } - - public function validateCommitMessageValue($value) { - if (!$value) { - return; - } - - $author_phid = $this->getObject()->getAuthorPHID(); - - $config_self_accept_key = 'differential.allow-self-accept'; - $allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key); - - $value = $this->inflateReviewers($value); - foreach ($value as $spec) { - $phid = $spec['phid']; - - if (($phid == $author_phid) && !$allow_self_accept) { - throw new DifferentialFieldValidationException( - pht('The author of a revision can not be a reviewer.')); - } - } - } - public function getRequiredHandlePHIDsForRevisionHeaderWarnings() { return mpull($this->getValue(), 'getReviewerPHID'); } public function getWarningsForRevisionHeader(array $handles) { $revision = $this->getObject(); $status_needs_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW; if ($revision->getStatus() != $status_needs_review) { return array(); } foreach ($this->getValue() as $reviewer) { if (!$handles[$reviewer->getReviewerPHID()]->isDisabled()) { return array(); } } $warnings = array(); if ($this->getValue()) { $warnings[] = pht( 'This revision needs review, but all specified reviewers are '. 'disabled or inactive.'); } else { $warnings[] = pht( 'This revision needs review, but there are no reviewers specified.'); } return $warnings; } - public function getProTips() { - return array( - pht( - 'You can mark a reviewer as blocking by adding an exclamation '. - 'mark ("!") after their name.'), - ); - } - - private function flattenReviewers(array $values) { - // NOTE: For now, `arc` relies on this field returning only scalars, so we - // need to reduce the results into scalars. See T10981. - $result = array(); - - foreach ($values as $value) { - $result[] = $value['phid'].implode('', array_keys($value['suffixes'])); - } - - return $result; - } - - private function inflateReviewers(array $values) { - $result = array(); - - foreach ($values as $value) { - if (substr($value, -1) == '!') { - $value = substr($value, 0, -1); - $suffixes = array('!' => '!'); - } else { - $suffixes = array(); - } - - $result[] = array( - 'phid' => $value, - 'suffixes' => $suffixes, - ); - } - - return $result; - } - } diff --git a/src/applications/differential/customfield/DifferentialSubscribersField.php b/src/applications/differential/customfield/DifferentialSubscribersField.php deleted file mode 100644 index b8423e9879..0000000000 --- a/src/applications/differential/customfield/DifferentialSubscribersField.php +++ /dev/null @@ -1,93 +0,0 @@ -getPHID()) { - return array(); - } - - return PhabricatorSubscribersQuery::loadSubscribersForPHID( - $revision->getPHID()); - } - - public function getNewValueForApplicationTransactions() { - return array('=' => $this->getValue()); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getArr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new AphrontFormTokenizerControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setDatasource(new PhabricatorMetaMTAMailableDatasource()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_SUBSCRIBERS; - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAllowEditInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'CC', - 'CCs', - 'Subscriber', - 'Subscribers', - ); - } - - public function parseValueFromCommitMessage($value) { - return $this->parseObjectList( - $value, - array( - PhabricatorPeopleUserPHIDType::TYPECONST, - PhabricatorProjectProjectPHIDType::TYPECONST, - PhabricatorOwnersPackagePHIDType::TYPECONST, - )); - } - - public function getRequiredHandlePHIDsForCommitMessage() { - return $this->getValue(); - } - - public function renderCommitMessageValue(array $handles) { - return $this->renderObjectList($handles); - } - -} diff --git a/src/applications/differential/customfield/DifferentialSummaryField.php b/src/applications/differential/customfield/DifferentialSummaryField.php index 5052e238e0..a11bebca6e 100644 --- a/src/applications/differential/customfield/DifferentialSummaryField.php +++ b/src/applications/differential/customfield/DifferentialSummaryField.php @@ -1,166 +1,82 @@ getID()) { return null; } return $revision->getSummary(); } - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setSummary($value); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new PhabricatorRemarkupControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the summary for this revision.', - $xaction->renderHandleLink($author_phid)); - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the summary for %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid)); - } - - public function getApplicationTransactionHasChangeDetails( - PhabricatorApplicationTransaction $xaction) { - return true; - } - - public function getApplicationTransactionChangeDetails( - PhabricatorApplicationTransaction $xaction, - PhabricatorUser $viewer) { - return $xaction->renderTextCorpusChangeDetails( - $viewer, - $xaction->getOldValue(), - $xaction->getNewValue()); - } - - public function shouldHideInApplicationTransactions( - PhabricatorApplicationTransaction $xaction) { - return ($xaction->getOldValue() === null); - } - public function shouldAppearInGlobalSearch() { return true; } public function updateAbstractDocument( PhabricatorSearchAbstractDocument $document) { if (strlen($this->getValue())) { $document->addField('body', $this->getValue()); } } public function shouldAppearInPropertyView() { return true; } public function renderPropertyViewLabel() { return $this->getFieldName(); } public function getStyleForPropertyView() { return 'block'; } public function getIconForPropertyView() { return PHUIPropertyListView::ICON_SUMMARY; } public function renderPropertyViewValue(array $handles) { if (!strlen($this->getValue())) { return null; } return new PHUIRemarkupView($this->getViewer(), $this->getValue()); } - public function getApplicationTransactionRemarkupBlocks( - PhabricatorApplicationTransaction $xaction) { - return array($xaction->getNewValue()); - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - public function shouldAppearInTransactionMail() { return true; } public function updateTransactionMailBody( PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions) { if (!$editor->getIsNewObject()) { return; } $summary = $this->getValue(); if (!strlen(trim($summary))) { return; } $body->addRemarkupSection(pht('REVISION SUMMARY'), $summary); } } diff --git a/src/applications/differential/customfield/DifferentialTestPlanField.php b/src/applications/differential/customfield/DifferentialTestPlanField.php index 6a1029dba4..c774e81a08 100644 --- a/src/applications/differential/customfield/DifferentialTestPlanField.php +++ b/src/applications/differential/customfield/DifferentialTestPlanField.php @@ -1,197 +1,87 @@ getID()) { return null; } return $revision->getTestPlan(); } - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setTestPlan($value); - } - - protected function isCoreFieldRequired() { - return PhabricatorEnv::getEnvConfig('differential.require-test-plan-field'); - } - public function canDisableField() { return true; } - protected function getCoreFieldRequiredErrorString() { - return pht( - 'You must provide a test plan. Describe the actions you performed '. - 'to verify the behavior of this change.'); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - return id(new PhabricatorRemarkupControl()) - ->setUser($this->getViewer()) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the test plan for this revision.', - $xaction->renderHandleLink($author_phid)); - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - return pht( - '%s updated the test plan for %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid)); - } - - public function getApplicationTransactionHasChangeDetails( - PhabricatorApplicationTransaction $xaction) { - return true; - } - - public function getApplicationTransactionChangeDetails( - PhabricatorApplicationTransaction $xaction, - PhabricatorUser $viewer) { - return $xaction->renderTextCorpusChangeDetails( - $viewer, - $xaction->getOldValue(), - $xaction->getNewValue()); - } - - public function shouldHideInApplicationTransactions( - PhabricatorApplicationTransaction $xaction) { - return ($xaction->getOldValue() === null); - } - public function shouldAppearInGlobalSearch() { return true; } public function updateAbstractDocument( PhabricatorSearchAbstractDocument $document) { if (strlen($this->getValue())) { $document->addField('plan', $this->getValue()); } } public function shouldAppearInPropertyView() { return true; } public function renderPropertyViewLabel() { return $this->getFieldName(); } public function getStyleForPropertyView() { return 'block'; } public function getIconForPropertyView() { return PHUIPropertyListView::ICON_TESTPLAN; } public function renderPropertyViewValue(array $handles) { if (!strlen($this->getValue())) { return null; } return new PHUIRemarkupView($this->getViewer(), $this->getValue()); } - public function getApplicationTransactionRemarkupBlocks( - PhabricatorApplicationTransaction $xaction) { - return array($xaction->getNewValue()); - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldAppearInCommitMessageTemplate() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function getCommitMessageLabels() { - return array( - 'Test Plan', - 'Testplan', - 'Tested', - 'Tests', - ); - } - - public function validateCommitMessageValue($value) { - if (!strlen($value) && $this->isCoreFieldRequired()) { - throw new DifferentialFieldValidationException( - $this->getCoreFieldRequiredErrorString()); - } - } - public function shouldAppearInTransactionMail() { return true; } public function updateTransactionMailBody( PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions) { if (!$editor->getIsNewObject()) { return; } $test_plan = $this->getValue(); if (!strlen(trim($test_plan))) { return; } $body->addRemarkupSection(pht('TEST PLAN'), $test_plan); } } diff --git a/src/applications/differential/customfield/DifferentialTitleField.php b/src/applications/differential/customfield/DifferentialTitleField.php deleted file mode 100644 index 82d6ddc1f3..0000000000 --- a/src/applications/differential/customfield/DifferentialTitleField.php +++ /dev/null @@ -1,125 +0,0 @@ ->'); - } - - protected function readValueFromRevision( - DifferentialRevision $revision) { - return $revision->getTitle(); - } - - protected function writeValueToRevision( - DifferentialRevision $revision, - $value) { - $revision->setTitle($value); - } - - protected function getCoreFieldRequiredErrorString() { - return pht('You must choose a title for this revision.'); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - protected function isCoreFieldRequired() { - return true; - } - - public function renderEditControl(array $handles) { - return id(new AphrontFormTextAreaControl()) - ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()) - ->setLabel($this->getFieldName()); - } - - public function getApplicationTransactionTitle( - PhabricatorApplicationTransaction $xaction) { - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if (strlen($old)) { - return pht( - '%s retitled this revision from "%s" to "%s".', - $xaction->renderHandleLink($author_phid), - $old, - $new); - } else { - return pht( - '%s created this revision.', - $xaction->renderHandleLink($author_phid)); - } - } - - public function getApplicationTransactionTitleForFeed( - PhabricatorApplicationTransaction $xaction) { - - $object_phid = $xaction->getObjectPHID(); - $author_phid = $xaction->getAuthorPHID(); - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - if (strlen($old)) { - return pht( - '%s retitled %s, from "%s" to "%s".', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid), - $old, - $new); - } else { - return pht( - '%s created %s.', - $xaction->renderHandleLink($author_phid), - $xaction->renderHandleLink($object_phid)); - } - } - - public function shouldAppearInCommitMessage() { - return true; - } - - public function shouldOverwriteWhenCommitMessageIsEdited() { - return true; - } - - public function validateCommitMessageValue($value) { - if (!strlen($value)) { - throw new DifferentialFieldValidationException( - pht( - 'You must provide a revision title in the first line '. - 'of your commit message.')); - } - - if (preg_match('/^<<.*>>$/', $value)) { - throw new DifferentialFieldValidationException( - pht( - 'Replace the line "%s" with a human-readable revision title which '. - 'describes the changes you are making.', - self::getDefaultTitle())); - } - } - -} diff --git a/src/applications/differential/customfield/DifferentialViewPolicyField.php b/src/applications/differential/customfield/DifferentialViewPolicyField.php deleted file mode 100644 index 9b17413fcf..0000000000 --- a/src/applications/differential/customfield/DifferentialViewPolicyField.php +++ /dev/null @@ -1,50 +0,0 @@ -getViewPolicy(); - } - - public function readValueFromRequest(AphrontRequest $request) { - $this->setValue($request->getStr($this->getFieldKey())); - } - - public function renderEditControl(array $handles) { - $viewer = $this->getViewer(); - $revision = $this->getObject(); - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($revision) - ->execute(); - - return id(new AphrontFormPolicyControl()) - ->setUser($viewer) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicyObject($revision) - ->setPolicies($policies) - ->setName($this->getFieldKey()) - ->setValue($this->getValue()) - ->setError($this->getFieldError()); - } - - public function getApplicationTransactionType() { - return PhabricatorTransactions::TYPE_VIEW_POLICY; - } - -} diff --git a/src/applications/differential/editor/DifferentialRevisionEditEngine.php b/src/applications/differential/editor/DifferentialRevisionEditEngine.php new file mode 100644 index 0000000000..8e15238661 --- /dev/null +++ b/src/applications/differential/editor/DifferentialRevisionEditEngine.php @@ -0,0 +1,222 @@ +getViewer(); + return DifferentialRevision::initializeNewRevision($viewer); + } + + protected function newObjectQuery() { + return id(new DifferentialRevisionQuery()) + ->needActiveDiffs(true) + ->needReviewerStatus(true); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Revision'); + } + + protected function getObjectEditTitleText($object) { + $monogram = $object->getMonogram(); + $title = $object->getTitle(); + + $diff = $this->getDiff(); + if ($diff) { + return pht('Update Revision %s: %s', $monogram, $title); + } else { + return pht('Edit Revision %s: %s', $monogram, $title); + } + } + + protected function getObjectEditShortText($object) { + return $object->getMonogram(); + } + + protected function getObjectCreateShortText() { + return pht('Create Revision'); + } + + protected function getObjectName() { + return pht('Revision'); + } + + protected function getObjectViewURI($object) { + return $object->getURI(); + } + + public function setDiff(DifferentialDiff $diff) { + $this->diff = $diff; + return $this; + } + + public function getDiff() { + return $this->diff; + } + + protected function buildCustomEditFields($object) { + + $plan_required = PhabricatorEnv::getEnvConfig( + 'differential.require-test-plan-field'); + $plan_enabled = $this->isCustomFieldEnabled( + $object, + 'differential:test-plan'); + + $diff = $this->getDiff(); + if ($diff) { + $diff_phid = $diff->getPHID(); + } else { + $diff_phid = null; + } + + $is_create = $this->getIsCreate(); + $is_update = ($diff && !$is_create); + + $fields = array(); + + $fields[] = id(new PhabricatorHandlesEditField()) + ->setKey(self::KEY_UPDATE) + ->setLabel(pht('Update Diff')) + ->setDescription(pht('New diff to create or update the revision with.')) + ->setConduitDescription(pht('Create or update a revision with a diff.')) + ->setConduitTypeDescription(pht('PHID of the diff.')) + ->setTransactionType(DifferentialTransaction::TYPE_UPDATE) + ->setHandleParameterType(new AphrontPHIDListHTTPParameterType()) + ->setSingleValue($diff_phid) + ->setIsConduitOnly(!$diff) + ->setIsReorderable(false) + ->setIsDefaultable(false) + ->setIsInvisible(true) + ->setIsLockable(false); + + if ($is_update) { + $fields[] = id(new PhabricatorInstructionsEditField()) + ->setKey('update.help') + ->setValue(pht('Describe the updates you have made to the diff.')); + $fields[] = id(new PhabricatorCommentEditField()) + ->setKey('update.comment') + ->setLabel(pht('Comment')) + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) + ->setIsWebOnly(true) + ->setDescription(pht('Comments providing context for the update.')); + $fields[] = id(new PhabricatorSubmitEditField()) + ->setKey('update.submit') + ->setValue($this->getObjectEditButtonText($object)); + $fields[] = id(new PhabricatorDividerEditField()) + ->setKey('update.note'); + } + + $fields[] = id(new PhabricatorTextEditField()) + ->setKey(DifferentialRevisionTitleTransaction::EDITKEY) + ->setLabel(pht('Title')) + ->setIsRequired(true) + ->setTransactionType( + DifferentialRevisionTitleTransaction::TRANSACTIONTYPE) + ->setDescription(pht('The title of the revision.')) + ->setConduitDescription(pht('Retitle the revision.')) + ->setConduitTypeDescription(pht('New revision title.')) + ->setValue($object->getTitle()); + + $fields[] = id(new PhabricatorRemarkupEditField()) + ->setKey(DifferentialRevisionSummaryTransaction::EDITKEY) + ->setLabel(pht('Summary')) + ->setTransactionType( + DifferentialRevisionSummaryTransaction::TRANSACTIONTYPE) + ->setDescription(pht('The summary of the revision.')) + ->setConduitDescription(pht('Change the revision summary.')) + ->setConduitTypeDescription(pht('New revision summary.')) + ->setValue($object->getSummary()); + + if ($plan_enabled) { + $fields[] = id(new PhabricatorRemarkupEditField()) + ->setKey(DifferentialRevisionTestPlanTransaction::EDITKEY) + ->setLabel(pht('Test Plan')) + ->setIsRequired($plan_required) + ->setTransactionType( + DifferentialRevisionTestPlanTransaction::TRANSACTIONTYPE) + ->setDescription( + pht('Actions performed to verify the behavior of the change.')) + ->setConduitDescription(pht('Update the revision test plan.')) + ->setConduitTypeDescription(pht('New test plan.')) + ->setValue($object->getTestPlan()); + } + + $fields[] = id(new PhabricatorDatasourceEditField()) + ->setKey(DifferentialRevisionReviewersTransaction::EDITKEY) + ->setLabel(pht('Reviewers')) + ->setDatasource(new DifferentialReviewerDatasource()) + ->setUseEdgeTransactions(true) + ->setTransactionType( + DifferentialRevisionReviewersTransaction::TRANSACTIONTYPE) + ->setDescription(pht('Reviewers for this revision.')) + ->setConduitDescription(pht('Change the reviewers for this revision.')) + ->setConduitTypeDescription(pht('New reviewers.')) + ->setValue($object->getReviewerPHIDsForEdit()); + + $fields[] = id(new PhabricatorDatasourceEditField()) + ->setKey('repositoryPHID') + ->setLabel(pht('Repository')) + ->setDatasource(new DiffusionRepositoryDatasource()) + ->setTransactionType( + DifferentialRevisionRepositoryTransaction::TRANSACTIONTYPE) + ->setDescription(pht('The repository the revision belongs to.')) + ->setConduitDescription(pht('Change the repository for this revision.')) + ->setConduitTypeDescription(pht('New repository.')) + ->setSingleValue($object->getRepositoryPHID()); + + // This is a little flimsy, but allows "Maniphest Tasks: ..." to continue + // working properly in commit messages until we fully sort out T5873. + $fields[] = id(new PhabricatorHandlesEditField()) + ->setKey('tasks') + ->setUseEdgeTransactions(true) + ->setIsConduitOnly(true) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue( + 'edge:type', + DifferentialRevisionHasTaskEdgeType::EDGECONST) + ->setDescription(pht('Tasks associated with this revision.')) + ->setConduitDescription(pht('Change associated tasks.')) + ->setConduitTypeDescription(pht('List of tasks.')) + ->setValue(array()); + + return $fields; + } + + private function isCustomFieldEnabled(DifferentialRevision $revision, $key) { + $field_list = PhabricatorCustomField::getObjectFields( + $revision, + PhabricatorCustomField::ROLE_VIEW); + + $fields = $field_list->getFields(); + return isset($fields[$key]); + } + +} diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php index b4828494c0..f1bed835d9 100644 --- a/src/applications/differential/editor/DifferentialTransactionEditor.php +++ b/src/applications/differential/editor/DifferentialTransactionEditor.php @@ -1,1925 +1,1925 @@ getTransactionType() == $type_update) { return $xaction; } } return null; } public function setIsCloseByCommit($is_close_by_commit) { $this->isCloseByCommit = $is_close_by_commit; return $this; } public function getIsCloseByCommit() { return $this->isCloseByCommit; } public function setChangedPriorToCommitURI($uri) { $this->changedPriorToCommitURI = $uri; return $this; } public function getChangedPriorToCommitURI() { return $this->changedPriorToCommitURI; } public function setRepositoryPHIDOverride($phid_or_null) { $this->repositoryPHIDOverride = $phid_or_null; return $this; } public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = DifferentialTransaction::TYPE_ACTION; $types[] = DifferentialTransaction::TYPE_INLINE; $types[] = DifferentialTransaction::TYPE_STATUS; $types[] = DifferentialTransaction::TYPE_UPDATE; return $types; } protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_ACTION: return null; case DifferentialTransaction::TYPE_INLINE: return null; case DifferentialTransaction::TYPE_UPDATE: if ($this->getIsNewObject()) { return null; } else { return $object->getActiveDiff()->getPHID(); } } return parent::getCustomTransactionOldValue($object, $xaction); } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_ACTION: case DifferentialTransaction::TYPE_UPDATE: return $xaction->getNewValue(); case DifferentialTransaction::TYPE_INLINE: return null; } return parent::getCustomTransactionNewValue($object, $xaction); } protected function transactionHasEffect( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $actor_phid = $this->getActingAsPHID(); switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_INLINE: return $xaction->hasComment(); case DifferentialTransaction::TYPE_ACTION: $status_closed = ArcanistDifferentialRevisionStatus::CLOSED; $status_abandoned = ArcanistDifferentialRevisionStatus::ABANDONED; $status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW; $status_revision = ArcanistDifferentialRevisionStatus::NEEDS_REVISION; $status_plan = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED; $action_type = $xaction->getNewValue(); switch ($action_type) { case DifferentialAction::ACTION_ACCEPT: case DifferentialAction::ACTION_REJECT: if ($action_type == DifferentialAction::ACTION_ACCEPT) { $new_status = DifferentialReviewerStatus::STATUS_ACCEPTED; } else { $new_status = DifferentialReviewerStatus::STATUS_REJECTED; } $actor = $this->getActor(); // These transactions can cause effects in two ways: by altering the // status of an existing reviewer; or by adding the actor as a new // reviewer. $will_add_reviewer = true; foreach ($object->getReviewerStatus() as $reviewer) { if ($reviewer->hasAuthority($actor)) { if ($reviewer->getStatus() != $new_status) { return true; } } if ($reviewer->getReviewerPHID() == $actor_phid) { $will_add_reviwer = false; } } return $will_add_reviewer; case DifferentialAction::ACTION_CLOSE: return ($object->getStatus() != $status_closed); case DifferentialAction::ACTION_ABANDON: return ($object->getStatus() != $status_abandoned); case DifferentialAction::ACTION_RECLAIM: return ($object->getStatus() == $status_abandoned); case DifferentialAction::ACTION_REOPEN: return ($object->getStatus() == $status_closed); case DifferentialAction::ACTION_RETHINK: return ($object->getStatus() != $status_plan); case DifferentialAction::ACTION_REQUEST: return ($object->getStatus() != $status_review); case DifferentialAction::ACTION_RESIGN: foreach ($object->getReviewerStatus() as $reviewer) { if ($reviewer->getReviewerPHID() == $actor_phid) { return true; } } return false; case DifferentialAction::ACTION_CLAIM: return ($actor_phid != $object->getAuthorPHID()); } } return parent::transactionHasEffect($object, $xaction); } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW; $status_revision = ArcanistDifferentialRevisionStatus::NEEDS_REVISION; $status_plan = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED; $status_abandoned = ArcanistDifferentialRevisionStatus::ABANDONED; $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_INLINE: return; case DifferentialTransaction::TYPE_UPDATE: if (!$this->getIsCloseByCommit()) { switch ($object->getStatus()) { case $status_revision: case $status_plan: case $status_abandoned: $object->setStatus($status_review); break; } } $diff = $this->requireDiff($xaction->getNewValue()); $object->setLineCount($diff->getLineCount()); if ($this->repositoryPHIDOverride !== false) { $object->setRepositoryPHID($this->repositoryPHIDOverride); } else { $object->setRepositoryPHID($diff->getRepositoryPHID()); } $object->attachActiveDiff($diff); // TODO: Update the `diffPHID` once we add that. return; case DifferentialTransaction::TYPE_ACTION: switch ($xaction->getNewValue()) { case DifferentialAction::ACTION_RESIGN: case DifferentialAction::ACTION_ACCEPT: case DifferentialAction::ACTION_REJECT: // These have no direct effects, and affect review status only // indirectly by altering reviewers with TYPE_EDGE transactions. return; case DifferentialAction::ACTION_ABANDON: $object->setStatus(ArcanistDifferentialRevisionStatus::ABANDONED); return; case DifferentialAction::ACTION_RETHINK: $object->setStatus($status_plan); return; case DifferentialAction::ACTION_RECLAIM: $object->setStatus($status_review); return; case DifferentialAction::ACTION_REOPEN: $object->setStatus($status_review); return; case DifferentialAction::ACTION_REQUEST: $object->setStatus($status_review); return; case DifferentialAction::ACTION_CLOSE: $old_status = $object->getStatus(); $object->setStatus(ArcanistDifferentialRevisionStatus::CLOSED); $was_accepted = ($old_status == $status_accepted); $object->setProperty( DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED, $was_accepted); return; case DifferentialAction::ACTION_CLAIM: $object->setAuthorPHID($this->getActingAsPHID()); return; default: throw new Exception( pht( 'Differential action "%s" is not a valid action!', $xaction->getNewValue())); } break; } return parent::applyCustomInternalTransaction($object, $xaction); } protected function expandTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $results = parent::expandTransaction($object, $xaction); $actor = $this->getActor(); $actor_phid = $this->getActingAsPHID(); $type_edge = PhabricatorTransactions::TYPE_EDGE; $status_plan = ArcanistDifferentialRevisionStatus::CHANGES_PLANNED; $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; $edge_ref_task = DifferentialRevisionHasTaskEdgeType::EDGECONST; $is_sticky_accept = PhabricatorEnv::getEnvConfig( 'differential.sticky-accept'); $downgrade_rejects = false; $downgrade_accepts = false; if ($this->getIsCloseByCommit()) { // Never downgrade reviewers when we're closing a revision after a // commit. } else { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_UPDATE: $downgrade_rejects = true; if (!$is_sticky_accept) { // If "sticky accept" is disabled, also downgrade the accepts. $downgrade_accepts = true; } break; case DifferentialTransaction::TYPE_ACTION: switch ($xaction->getNewValue()) { case DifferentialAction::ACTION_REQUEST: $downgrade_rejects = true; if ((!$is_sticky_accept) || ($object->getStatus() != $status_plan)) { // If the old state isn't "changes planned", downgrade the // accepts. This exception allows an accepted revision to // go through Plan Changes -> Request Review to return to // "accepted" if the author didn't update the revision. $downgrade_accepts = true; } break; } break; } } $new_accept = DifferentialReviewerStatus::STATUS_ACCEPTED; $new_reject = DifferentialReviewerStatus::STATUS_REJECTED; $old_accept = DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER; $old_reject = DifferentialReviewerStatus::STATUS_REJECTED_OLDER; if ($downgrade_rejects || $downgrade_accepts) { // When a revision is updated, change all "reject" to "rejected older // revision". This means we won't immediately push the update back into // "needs review", but outstanding rejects will still block it from // moving to "accepted". // We also do this for "Request Review", even though the diff is not // updated directly. Essentially, this acts like an update which doesn't // actually change the diff text. $edits = array(); foreach ($object->getReviewerStatus() as $reviewer) { if ($downgrade_rejects) { if ($reviewer->getStatus() == $new_reject) { $edits[$reviewer->getReviewerPHID()] = array( 'data' => array( 'status' => $old_reject, ), ); } } if ($downgrade_accepts) { if ($reviewer->getStatus() == $new_accept) { $edits[$reviewer->getReviewerPHID()] = array( 'data' => array( 'status' => $old_accept, ), ); } } } if ($edits) { $results[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_reviewer) ->setIgnoreOnNoEffect(true) ->setNewValue(array('+' => $edits)); } } switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_UPDATE: if ($this->getIsCloseByCommit()) { // Don't bother with any of this if this update is a side effect of // commit detection. break; } // When a revision is updated and the diff comes from a branch named // "T123" or similar, automatically associate the commit with the // task that the branch names. $maniphest = 'PhabricatorManiphestApplication'; if (PhabricatorApplication::isClassInstalled($maniphest)) { $diff = $this->requireDiff($xaction->getNewValue()); $branch = $diff->getBranch(); // No "$", to allow for branches like T123_demo. $match = null; if (preg_match('/^T(\d+)/i', $branch, $match)) { $task_id = $match[1]; $tasks = id(new ManiphestTaskQuery()) ->setViewer($this->getActor()) ->withIDs(array($task_id)) ->execute(); if ($tasks) { $task = head($tasks); $task_phid = $task->getPHID(); $results[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_ref_task) ->setIgnoreOnNoEffect(true) ->setNewValue(array('+' => array($task_phid => $task_phid))); } } } break; case PhabricatorTransactions::TYPE_COMMENT: // When a user leaves a comment, upgrade their reviewer status from // "added" to "commented" if they're also a reviewer. We may further // upgrade this based on other actions in the transaction group. $status_added = DifferentialReviewerStatus::STATUS_ADDED; $status_commented = DifferentialReviewerStatus::STATUS_COMMENTED; $data = array( 'status' => $status_commented, ); $edits = array(); foreach ($object->getReviewerStatus() as $reviewer) { if ($reviewer->getReviewerPHID() == $actor_phid) { if ($reviewer->getStatus() == $status_added) { $edits[$actor_phid] = array( 'data' => $data, ); } } } if ($edits) { $results[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_reviewer) ->setIgnoreOnNoEffect(true) ->setNewValue(array('+' => $edits)); } break; case DifferentialTransaction::TYPE_ACTION: $action_type = $xaction->getNewValue(); switch ($action_type) { case DifferentialAction::ACTION_ACCEPT: case DifferentialAction::ACTION_REJECT: if ($action_type == DifferentialAction::ACTION_ACCEPT) { $data = array( 'status' => DifferentialReviewerStatus::STATUS_ACCEPTED, ); } else { $data = array( 'status' => DifferentialReviewerStatus::STATUS_REJECTED, ); } $edits = array(); foreach ($object->getReviewerStatus() as $reviewer) { if ($reviewer->hasAuthority($actor)) { $edits[$reviewer->getReviewerPHID()] = array( 'data' => $data, ); } } // Also either update or add the actor themselves as a reviewer. $edits[$actor_phid] = array( 'data' => $data, ); $results[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_reviewer) ->setIgnoreOnNoEffect(true) ->setNewValue(array('+' => $edits)); break; case DifferentialAction::ACTION_CLAIM: // If the user is commandeering, add the previous owner as a // reviewer and remove the actor. $edits = array( '-' => array( $actor_phid => $actor_phid, ), ); $owner_phid = $object->getAuthorPHID(); if ($owner_phid) { - $reviewer = new DifferentialReviewer( + $reviewer = new DifferentialReviewerProxy( $owner_phid, array( 'status' => DifferentialReviewerStatus::STATUS_ADDED, )); $edits['+'] = array( $owner_phid => array( 'data' => $reviewer->getEdgeData(), ), ); } // NOTE: We're setting setIsCommandeerSideEffect() on this because // normally you can't add a revision's author as a reviewer, but // this action swaps them after validation executes. $results[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_reviewer) ->setIgnoreOnNoEffect(true) ->setIsCommandeerSideEffect(true) ->setNewValue($edits); break; case DifferentialAction::ACTION_RESIGN: // If the user is resigning, add a separate reviewer edit // transaction which removes them as a reviewer. $results[] = id(new DifferentialTransaction()) ->setTransactionType($type_edge) ->setMetadataValue('edge:type', $edge_reviewer) ->setIgnoreOnNoEffect(true) ->setNewValue( array( '-' => array( $actor_phid => $actor_phid, ), )); break; } break; } if (!$this->didExpandInlineState) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: case DifferentialTransaction::TYPE_ACTION: case DifferentialTransaction::TYPE_UPDATE: case DifferentialTransaction::TYPE_INLINE: $this->didExpandInlineState = true; $actor_phid = $this->getActingAsPHID(); $actor_is_author = ($object->getAuthorPHID() == $actor_phid); if (!$actor_is_author) { break; } $state_map = PhabricatorTransactions::getInlineStateMap(); $inlines = id(new DifferentialDiffInlineCommentQuery()) ->setViewer($this->getActor()) ->withRevisionPHIDs(array($object->getPHID())) ->withFixedStates(array_keys($state_map)) ->execute(); if (!$inlines) { break; } $old_value = mpull($inlines, 'getFixedState', 'getPHID'); $new_value = array(); foreach ($old_value as $key => $state) { $new_value[$key] = $state_map[$state]; } $results[] = id(new DifferentialTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_INLINESTATE) ->setIgnoreOnNoEffect(true) ->setOldValue($old_value) ->setNewValue($new_value); break; } } return $results; } protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_ACTION: return; case DifferentialTransaction::TYPE_INLINE: $reply = $xaction->getComment()->getReplyToComment(); if ($reply && !$reply->getHasReplies()) { $reply->setHasReplies(1)->save(); } return; case DifferentialTransaction::TYPE_UPDATE: // Now that we're inside the transaction, do a final check. $diff = $this->requireDiff($xaction->getNewValue()); // TODO: It would be slightly cleaner to just revalidate this // transaction somehow using the same validation code, but that's // not easy to do at the moment. $revision_id = $diff->getRevisionID(); if ($revision_id && ($revision_id != $object->getID())) { throw new Exception( pht( 'Diff is already attached to another revision. You lost '. 'a race?')); } // TODO: This can race with diff updates, particularly those from // Harbormaster. See discussion in T8650. $diff->setRevisionID($object->getID()); $diff->save(); // Update Harbormaster to set the containerPHID correctly for any // existing buildables. We may otherwise have buildables stuck with // the old (`null`) container. // TODO: This is a bit iffy, maybe we can find a cleaner approach? // In particular, this could (rarely) be overwritten by Harbormaster // workers. $table = new HarbormasterBuildable(); $conn_w = $table->establishConnection('w'); queryfx( $conn_w, 'UPDATE %T SET containerPHID = %s WHERE buildablePHID = %s', $table->getTableName(), $object->getPHID(), $diff->getPHID()); return; } return parent::applyCustomExternalTransaction($object, $xaction); } protected function applyBuiltinExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_INLINESTATE: $table = new DifferentialTransactionComment(); $conn_w = $table->establishConnection('w'); foreach ($xaction->getNewValue() as $phid => $state) { queryfx( $conn_w, 'UPDATE %T SET fixedState = %s WHERE phid = %s', $table->getTableName(), $state, $phid); } break; } return parent::applyBuiltinExternalTransaction($object, $xaction); } protected function mergeEdgeData($type, array $u, array $v) { $result = parent::mergeEdgeData($type, $u, $v); switch ($type) { case DifferentialRevisionHasReviewerEdgeType::EDGECONST: // When the same reviewer has their status updated by multiple // transactions, we want the strongest status to win. An example of // this is when a user adds a comment and also accepts a revision which // they are a reviewer on. The comment creates a "commented" status, // while the accept creates an "accepted" status. Since accept is // stronger, it should win and persist. $u_status = idx($u, 'status'); $v_status = idx($v, 'status'); $u_str = DifferentialReviewerStatus::getStatusStrength($u_status); $v_str = DifferentialReviewerStatus::getStatusStrength($v_status); if ($u_str > $v_str) { $result['status'] = $u_status; } else { $result['status'] = $v_status; } break; } return $result; } protected function applyFinalEffects( PhabricatorLiskDAO $object, array $xactions) { // Load the most up-to-date version of the revision and its reviewers, // so we don't need to try to deduce the state of reviewers by examining // all the changes made by the transactions. Then, update the reviewers // on the object to make sure we're acting on the current reviewer set // (and, for example, sending mail to the right people). $new_revision = id(new DifferentialRevisionQuery()) ->setViewer($this->getActor()) ->needReviewerStatus(true) ->needActiveDiffs(true) ->withIDs(array($object->getID())) ->executeOne(); if (!$new_revision) { throw new Exception( pht('Failed to load revision from transaction finalization.')); } $object->attachReviewerStatus($new_revision->getReviewerStatus()); $object->attachActiveDiff($new_revision->getActiveDiff()); $object->attachRepository($new_revision->getRepository()); foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_UPDATE: $diff = $this->requireDiff($xaction->getNewValue(), true); // Update these denormalized index tables when we attach a new // diff to a revision. $this->updateRevisionHashTable($object, $diff); $this->updateAffectedPathTable($object, $diff); break; } } $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; $status_revision = ArcanistDifferentialRevisionStatus::NEEDS_REVISION; $status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW; $old_status = $object->getStatus(); switch ($old_status) { case $status_accepted: case $status_revision: case $status_review: // Try to move a revision to "accepted". We look for: // // - at least one accepting reviewer who is a user; and // - no rejects; and // - no rejects of older diffs; and // - no blocking reviewers. $has_accepting_user = false; $has_rejecting_reviewer = false; $has_rejecting_older_reviewer = false; $has_blocking_reviewer = false; foreach ($object->getReviewerStatus() as $reviewer) { $reviewer_status = $reviewer->getStatus(); switch ($reviewer_status) { case DifferentialReviewerStatus::STATUS_REJECTED: $has_rejecting_reviewer = true; break; case DifferentialReviewerStatus::STATUS_REJECTED_OLDER: $has_rejecting_older_reviewer = true; break; case DifferentialReviewerStatus::STATUS_BLOCKING: $has_blocking_reviewer = true; break; case DifferentialReviewerStatus::STATUS_ACCEPTED: if ($reviewer->isUser()) { $has_accepting_user = true; } break; } } $new_status = null; if ($has_accepting_user && !$has_rejecting_reviewer && !$has_rejecting_older_reviewer && !$has_blocking_reviewer) { $new_status = $status_accepted; } else if ($has_rejecting_reviewer) { // This isn't accepted, and there's at least one rejecting reviewer, // so the revision needs changes. This usually happens after a // "reject". $new_status = $status_revision; } else if ($old_status == $status_accepted) { // This revision was accepted, but it no longer satisfies the // conditions for acceptance. This usually happens after an accepting // reviewer resigns or is removed. $new_status = $status_review; } if ($new_status !== null && ($new_status != $old_status)) { $xaction = id(new DifferentialTransaction()) ->setTransactionType(DifferentialTransaction::TYPE_STATUS) ->setOldValue($old_status) ->setNewValue($new_status); $xaction = $this->populateTransaction($object, $xaction)->save(); $xactions[] = $xaction; $object->setStatus($new_status)->save(); } break; default: // Revisions can't transition out of other statuses (like closed or // abandoned) as a side effect of reviewer status changes. break; } return $xactions; } protected function validateTransaction( PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); $config_self_accept_key = 'differential.allow-self-accept'; $allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key); foreach ($xactions as $xaction) { switch ($type) { case PhabricatorTransactions::TYPE_EDGE: switch ($xaction->getMetadataValue('edge:type')) { case DifferentialRevisionHasReviewerEdgeType::EDGECONST: // Prevent the author from becoming a reviewer. // NOTE: This is pretty gross, but this restriction is unusual. // If we end up with too much more of this, we should try to clean // this up -- maybe by moving validation to after transactions // are adjusted (so we can just examine the final value) or adding // a second phase there? $author_phid = $object->getAuthorPHID(); $new = $xaction->getNewValue(); $add = idx($new, '+', array()); $eq = idx($new, '=', array()); $phids = array_keys($add + $eq); foreach ($phids as $phid) { if (($phid == $author_phid) && !$allow_self_accept && !$xaction->getIsCommandeerSideEffect()) { $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), pht('The author of a revision can not be a reviewer.'), $xaction); } } break; } break; case DifferentialTransaction::TYPE_UPDATE: $diff = $this->loadDiff($xaction->getNewValue()); if (!$diff) { $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), pht('The specified diff does not exist.'), $xaction); } else if (($diff->getRevisionID()) && ($diff->getRevisionID() != $object->getID())) { $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), pht( 'You can not update this revision to the specified diff, '. 'because the diff is already attached to another revision.'), $xaction); } break; case DifferentialTransaction::TYPE_ACTION: $error = $this->validateDifferentialAction( $object, $type, $xaction, $xaction->getNewValue()); if ($error) { $errors[] = new PhabricatorApplicationTransactionValidationError( $type, pht('Invalid'), $error, $xaction); } break; } } return $errors; } private function validateDifferentialAction( DifferentialRevision $revision, $type, DifferentialTransaction $xaction, $action) { $author_phid = $revision->getAuthorPHID(); $actor_phid = $this->getActingAsPHID(); $actor_is_author = ($author_phid == $actor_phid); $config_abandon_key = 'differential.always-allow-abandon'; $always_allow_abandon = PhabricatorEnv::getEnvConfig($config_abandon_key); $config_close_key = 'differential.always-allow-close'; $always_allow_close = PhabricatorEnv::getEnvConfig($config_close_key); $config_reopen_key = 'differential.allow-reopen'; $allow_reopen = PhabricatorEnv::getEnvConfig($config_reopen_key); $config_self_accept_key = 'differential.allow-self-accept'; $allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key); $revision_status = $revision->getStatus(); $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; $status_abandoned = ArcanistDifferentialRevisionStatus::ABANDONED; $status_closed = ArcanistDifferentialRevisionStatus::CLOSED; switch ($action) { case DifferentialAction::ACTION_ACCEPT: if ($actor_is_author && !$allow_self_accept) { return pht( 'You can not accept this revision because you are the owner.'); } if ($revision_status == $status_abandoned) { return pht( 'You can not accept this revision because it has been '. 'abandoned.'); } if ($revision_status == $status_closed) { return pht( 'You can not accept this revision because it has already been '. 'closed.'); } // TODO: It would be nice to make this generic at some point. $signatures = DifferentialRequiredSignaturesField::loadForRevision( $revision); foreach ($signatures as $phid => $signed) { if (!$signed) { return pht( 'You can not accept this revision because the author has '. 'not signed all of the required legal documents.'); } } break; case DifferentialAction::ACTION_REJECT: if ($actor_is_author) { return pht('You can not request changes to your own revision.'); } if ($revision_status == $status_abandoned) { return pht( 'You can not request changes to this revision because it has been '. 'abandoned.'); } if ($revision_status == $status_closed) { return pht( 'You can not request changes to this revision because it has '. 'already been closed.'); } break; case DifferentialAction::ACTION_RESIGN: // You can always resign from a revision if you're a reviewer. If you // aren't, this is a no-op rather than invalid. break; case DifferentialAction::ACTION_CLAIM: // You can claim a revision if you're not the owner. If you are, this // is a no-op rather than invalid. if ($revision_status == $status_closed) { return pht( 'You can not commandeer this revision because it has already been '. 'closed.'); } break; case DifferentialAction::ACTION_ABANDON: if (!$actor_is_author && !$always_allow_abandon) { return pht( 'You can not abandon this revision because you do not own it. '. 'You can only abandon revisions you own.'); } if ($revision_status == $status_closed) { return pht( 'You can not abandon this revision because it has already been '. 'closed.'); } // NOTE: Abandons of already-abandoned revisions are treated as no-op // instead of invalid. Other abandons are OK. break; case DifferentialAction::ACTION_RECLAIM: if (!$actor_is_author) { return pht( 'You can not reclaim this revision because you do not own '. 'it. You can only reclaim revisions you own.'); } if ($revision_status == $status_closed) { return pht( 'You can not reclaim this revision because it has already been '. 'closed.'); } // NOTE: Reclaims of other non-abandoned revisions are treated as no-op // instead of invalid. break; case DifferentialAction::ACTION_REOPEN: if (!$allow_reopen) { return pht( 'The reopen action is not enabled on this Phabricator install. '. 'Adjust your configuration to enable it.'); } // NOTE: If the revision is not closed, this is caught as a no-op // instead of an invalid transaction. break; case DifferentialAction::ACTION_RETHINK: if (!$actor_is_author) { return pht( 'You can not plan changes to this revision because you do not '. 'own it. To plan changes to a revision, you must be its owner.'); } switch ($revision_status) { case ArcanistDifferentialRevisionStatus::ACCEPTED: case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: // These are OK. break; case ArcanistDifferentialRevisionStatus::CHANGES_PLANNED: // Let this through, it's a no-op. break; case ArcanistDifferentialRevisionStatus::ABANDONED: return pht( 'You can not plan changes to this revision because it has '. 'been abandoned.'); case ArcanistDifferentialRevisionStatus::CLOSED: return pht( 'You can not plan changes to this revision because it has '. 'already been closed.'); default: throw new Exception( pht( 'Encountered unexpected revision status ("%s") when '. 'validating "%s" action.', $revision_status, $action)); } break; case DifferentialAction::ACTION_REQUEST: if (!$actor_is_author) { return pht( 'You can not request review of this revision because you do '. 'not own it. To request review of a revision, you must be its '. 'owner.'); } switch ($revision_status) { case ArcanistDifferentialRevisionStatus::ACCEPTED: case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: case ArcanistDifferentialRevisionStatus::CHANGES_PLANNED: // These are OK. break; case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: // This will be caught as "no effect" later on. break; case ArcanistDifferentialRevisionStatus::ABANDONED: return pht( 'You can not request review of this revision because it has '. 'been abandoned. Instead, reclaim it.'); case ArcanistDifferentialRevisionStatus::CLOSED: return pht( 'You can not request review of this revision because it has '. 'already been closed.'); default: throw new Exception( pht( 'Encountered unexpected revision status ("%s") when '. 'validating "%s" action.', $revision_status, $action)); } break; case DifferentialAction::ACTION_CLOSE: // We force revisions closed when we discover a corresponding commit. // In this case, revisions are allowed to transition to closed from // any state. This is an automated action taken by the daemons. if (!$this->getIsCloseByCommit()) { if (!$actor_is_author && !$always_allow_close) { return pht( 'You can not close this revision because you do not own it. To '. 'close a revision, you must be its owner.'); } if ($revision_status != $status_accepted) { return pht( 'You can not close this revision because it has not been '. 'accepted. You can only close accepted revisions.'); } } break; } return null; } protected function sortTransactions(array $xactions) { $xactions = parent::sortTransactions($xactions); $head = array(); $tail = array(); foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); if ($type == DifferentialTransaction::TYPE_INLINE) { $tail[] = $xaction; } else { $head[] = $xaction; } } return array_values(array_merge($head, $tail)); } protected function requireCapabilities( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) {} return parent::requireCapabilities($object, $xaction); } protected function shouldPublishFeedStory( PhabricatorLiskDAO $object, array $xactions) { return true; } protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { return true; } protected function getMailTo(PhabricatorLiskDAO $object) { $phids = array(); $phids[] = $object->getAuthorPHID(); foreach ($object->getReviewerStatus() as $reviewer) { $phids[] = $reviewer->getReviewerPHID(); } return $phids; } protected function getMailAction( PhabricatorLiskDAO $object, array $xactions) { $action = parent::getMailAction($object, $xactions); $strongest = $this->getStrongestAction($object, $xactions); switch ($strongest->getTransactionType()) { case DifferentialTransaction::TYPE_UPDATE: $count = new PhutilNumber($object->getLineCount()); $action = pht('%s, %s line(s)', $action, $count); break; } return $action; } protected function getMailSubjectPrefix() { return PhabricatorEnv::getEnvConfig('metamta.differential.subject-prefix'); } protected function getMailThreadID(PhabricatorLiskDAO $object) { // This is nonstandard, but retains threading with older messages. $phid = $object->getPHID(); return "differential-rev-{$phid}-req"; } protected function buildReplyHandler(PhabricatorLiskDAO $object) { return id(new DifferentialReplyHandler()) ->setMailReceiver($object); } protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $title = $object->getTitle(); $original_title = $object->getOriginalTitle(); $subject = "D{$id}: {$title}"; $thread_topic = "D{$id}: {$original_title}"; return id(new PhabricatorMetaMTAMail()) ->setSubject($subject) ->addHeader('Thread-Topic', $thread_topic); } protected function buildMailBody( PhabricatorLiskDAO $object, array $xactions) { $body = new PhabricatorMetaMTAMailBody(); $body->setViewer($this->requireActor()); $revision_uri = PhabricatorEnv::getProductionURI('/D'.$object->getID()); $this->addHeadersAndCommentsToMailBody( $body, $xactions, pht('View Revision'), $revision_uri); $type_inline = DifferentialTransaction::TYPE_INLINE; $inlines = array(); foreach ($xactions as $xaction) { if ($xaction->getTransactionType() == $type_inline) { $inlines[] = $xaction; } } if ($inlines) { $this->appendInlineCommentsForMail($object, $inlines, $body); } $changed_uri = $this->getChangedPriorToCommitURI(); if ($changed_uri) { $body->addLinkSection( pht('CHANGED PRIOR TO COMMIT'), $changed_uri); } $this->addCustomFieldsToMailBody($body, $object, $xactions); $body->addLinkSection( pht('REVISION DETAIL'), $revision_uri); $update_xaction = null; foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_UPDATE: $update_xaction = $xaction; break; } } if ($update_xaction) { $diff = $this->requireDiff($update_xaction->getNewValue(), true); $body->addTextSection( pht('AFFECTED FILES'), $this->renderAffectedFilesForMail($diff)); $config_key_inline = 'metamta.differential.inline-patches'; $config_inline = PhabricatorEnv::getEnvConfig($config_key_inline); $config_key_attach = 'metamta.differential.attach-patches'; $config_attach = PhabricatorEnv::getEnvConfig($config_key_attach); if ($config_inline || $config_attach) { $body_limit = PhabricatorEnv::getEnvConfig('metamta.email-body-limit'); $patch = $this->buildPatchForMail($diff); if ($config_inline) { $lines = substr_count($patch, "\n"); $bytes = strlen($patch); // Limit the patch size to the smaller of 256 bytes per line or // the mail body limit. This prevents degenerate behavior for patches // with one line that is 10MB long. See T11748. $byte_limits = array(); $byte_limits[] = (256 * $config_inline); $byte_limits[] = $body_limit; $byte_limit = min($byte_limits); $lines_ok = ($lines <= $config_inline); $bytes_ok = ($bytes <= $byte_limit); if ($lines_ok && $bytes_ok) { $this->appendChangeDetailsForMail($object, $diff, $patch, $body); } else { // TODO: Provide a helpful message about the patch being too // large or lengthy here. } } if ($config_attach) { $name = pht('D%s.%s.patch', $object->getID(), $diff->getID()); $mime_type = 'text/x-patch; charset=utf-8'; $body->addAttachment( new PhabricatorMetaMTAAttachment($patch, $name, $mime_type)); } } } return $body; } public function getMailTagsMap() { return array( DifferentialTransaction::MAILTAG_REVIEW_REQUEST => pht('A revision is created.'), DifferentialTransaction::MAILTAG_UPDATED => pht('A revision is updated.'), DifferentialTransaction::MAILTAG_COMMENT => pht('Someone comments on a revision.'), DifferentialTransaction::MAILTAG_CLOSED => pht('A revision is closed.'), DifferentialTransaction::MAILTAG_REVIEWERS => pht("A revision's reviewers change."), DifferentialTransaction::MAILTAG_CC => pht("A revision's CCs change."), DifferentialTransaction::MAILTAG_OTHER => pht('Other revision activity not listed above occurs.'), ); } protected function supportsSearch() { return true; } protected function expandCustomRemarkupBlockTransactions( PhabricatorLiskDAO $object, array $xactions, array $changes, PhutilMarkupEngine $engine) { $flat_blocks = mpull($changes, 'getNewValue'); $huge_block = implode("\n\n", $flat_blocks); $task_map = array(); $task_refs = id(new ManiphestCustomFieldStatusParser()) ->parseCorpus($huge_block); foreach ($task_refs as $match) { foreach ($match['monograms'] as $monogram) { $task_id = (int)trim($monogram, 'tT'); $task_map[$task_id] = true; } } $rev_map = array(); $rev_refs = id(new DifferentialCustomFieldDependsOnParser()) ->parseCorpus($huge_block); foreach ($rev_refs as $match) { foreach ($match['monograms'] as $monogram) { $rev_id = (int)trim($monogram, 'dD'); $rev_map[$rev_id] = true; } } $edges = array(); $task_phids = array(); $rev_phids = array(); if ($task_map) { $tasks = id(new ManiphestTaskQuery()) ->setViewer($this->getActor()) ->withIDs(array_keys($task_map)) ->execute(); if ($tasks) { $task_phids = mpull($tasks, 'getPHID', 'getPHID'); $edge_related = DifferentialRevisionHasTaskEdgeType::EDGECONST; $edges[$edge_related] = $task_phids; } } if ($rev_map) { $revs = id(new DifferentialRevisionQuery()) ->setViewer($this->getActor()) ->withIDs(array_keys($rev_map)) ->execute(); $rev_phids = mpull($revs, 'getPHID', 'getPHID'); // NOTE: Skip any write attempts if a user cleverly implies a revision // depends upon itself. unset($rev_phids[$object->getPHID()]); if ($revs) { $depends = DifferentialRevisionDependsOnRevisionEdgeType::EDGECONST; $edges[$depends] = $rev_phids; } } $this->setUnmentionablePHIDMap(array_merge($task_phids, $rev_phids)); $result = array(); foreach ($edges as $type => $specs) { $result[] = id(new DifferentialTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue('edge:type', $type) ->setNewValue(array('+' => $specs)); } return $result; } private function appendInlineCommentsForMail( PhabricatorLiskDAO $object, array $inlines, PhabricatorMetaMTAMailBody $body) { $section = id(new DifferentialInlineCommentMailView()) ->setViewer($this->getActor()) ->setInlines($inlines) ->buildMailSection(); $header = pht('INLINE COMMENTS'); $section_text = "\n".$section->getPlaintext(); $style = array( 'margin: 6px 0 12px 0;', ); $section_html = phutil_tag( 'div', array( 'style' => implode(' ', $style), ), $section->getHTML()); $body->addPlaintextSection($header, $section_text, false); $body->addHTMLSection($header, $section_html); } private function appendChangeDetailsForMail( PhabricatorLiskDAO $object, DifferentialDiff $diff, $patch, PhabricatorMetaMTAMailBody $body) { $section = id(new DifferentialChangeDetailMailView()) ->setViewer($this->getActor()) ->setDiff($diff) ->setPatch($patch) ->buildMailSection(); $header = pht('CHANGE DETAILS'); $section_text = "\n".$section->getPlaintext(); $style = array( 'margin: 6px 0 12px 0;', ); $section_html = phutil_tag( 'div', array( 'style' => implode(' ', $style), ), $section->getHTML()); $body->addPlaintextSection($header, $section_text, false); $body->addHTMLSection($header, $section_html); } private function loadDiff($phid, $need_changesets = false) { $query = id(new DifferentialDiffQuery()) ->withPHIDs(array($phid)) ->setViewer($this->getActor()); if ($need_changesets) { $query->needChangesets(true); } return $query->executeOne(); } private function requireDiff($phid, $need_changesets = false) { $diff = $this->loadDiff($phid, $need_changesets); if (!$diff) { throw new Exception(pht('Diff "%s" does not exist!', $phid)); } return $diff; } /* -( Herald Integration )------------------------------------------------- */ protected function shouldApplyHeraldRules( PhabricatorLiskDAO $object, array $xactions) { if ($this->getIsNewObject()) { return true; } foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case DifferentialTransaction::TYPE_UPDATE: if (!$this->getIsCloseByCommit()) { return true; } break; case DifferentialTransaction::TYPE_ACTION: switch ($xaction->getNewValue()) { case DifferentialAction::ACTION_CLAIM: // When users commandeer revisions, we may need to trigger // signatures or author-based rules. return true; } break; } } return parent::shouldApplyHeraldRules($object, $xactions); } protected function didApplyHeraldRules( PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript) { $repository = $object->getRepository(); if (!$repository) { return array(); } if (!$this->affectedPaths) { return array(); } $packages = PhabricatorOwnersPackage::loadAffectedPackages( $repository, $this->affectedPaths); if (!$packages) { return array(); } // Remove packages that the revision author is an owner of. If you own // code, you don't need another owner to review it. $authority = id(new PhabricatorOwnersPackageQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs(mpull($packages, 'getPHID')) ->withAuthorityPHIDs(array($object->getAuthorPHID())) ->execute(); $authority = mpull($authority, null, 'getPHID'); foreach ($packages as $key => $package) { $package_phid = $package->getPHID(); if (isset($authority[$package_phid])) { unset($packages[$key]); continue; } } if (!$packages) { return array(); } $auto_subscribe = array(); $auto_review = array(); $auto_block = array(); foreach ($packages as $package) { switch ($package->getAutoReview()) { case PhabricatorOwnersPackage::AUTOREVIEW_SUBSCRIBE: $auto_subscribe[] = $package; break; case PhabricatorOwnersPackage::AUTOREVIEW_REVIEW: $auto_review[] = $package; break; case PhabricatorOwnersPackage::AUTOREVIEW_BLOCK: $auto_block[] = $package; break; case PhabricatorOwnersPackage::AUTOREVIEW_NONE: default: break; } } $owners_phid = id(new PhabricatorOwnersApplication()) ->getPHID(); $xactions = array(); if ($auto_subscribe) { $xactions[] = $object->getApplicationTransactionTemplate() ->setAuthorPHID($owners_phid) ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) ->setNewValue( array( '+' => mpull($auto_subscribe, 'getPHID'), )); } $specs = array( array($auto_review, false), array($auto_block, true), ); foreach ($specs as $spec) { list($reviewers, $blocking) = $spec; if (!$reviewers) { continue; } $phids = mpull($reviewers, 'getPHID'); $xaction = $this->newAutoReviewTransaction($object, $phids, $blocking); if ($xaction) { $xactions[] = $xaction; } } return $xactions; } private function newAutoReviewTransaction( PhabricatorLiskDAO $object, array $phids, $is_blocking) { // TODO: This is substantially similar to DifferentialReviewersHeraldAction // and both are needlessly complex. This logic should live in the normal // transaction application pipeline. See T10967. $reviewers = $object->getReviewerStatus(); $reviewers = mpull($reviewers, null, 'getReviewerPHID'); if ($is_blocking) { $new_status = DifferentialReviewerStatus::STATUS_BLOCKING; } else { $new_status = DifferentialReviewerStatus::STATUS_ADDED; } $new_strength = DifferentialReviewerStatus::getStatusStrength( $new_status); $current = array(); foreach ($phids as $phid) { if (!isset($reviewers[$phid])) { continue; } // If we're applying a stronger status (usually, upgrading a reviewer // into a blocking reviewer), skip this check so we apply the change. $old_strength = DifferentialReviewerStatus::getStatusStrength( $reviewers[$phid]->getStatus()); if ($old_strength <= $new_strength) { continue; } $current[] = $phid; } $phids = array_diff($phids, $current); if (!$phids) { return null; } $phids = array_fuse($phids); $value = array(); foreach ($phids as $phid) { $value[$phid] = array( 'data' => array( 'status' => $new_status, ), ); } $edgetype_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; $owners_phid = id(new PhabricatorOwnersApplication()) ->getPHID(); return $object->getApplicationTransactionTemplate() ->setAuthorPHID($owners_phid) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue('edge:type', $edgetype_reviewer) ->setNewValue( array( '+' => $value, )); } protected function buildHeraldAdapter( PhabricatorLiskDAO $object, array $xactions) { $revision = id(new DifferentialRevisionQuery()) ->setViewer($this->getActor()) ->withPHIDs(array($object->getPHID())) ->needActiveDiffs(true) ->needReviewerStatus(true) ->executeOne(); if (!$revision) { throw new Exception( pht('Failed to load revision for Herald adapter construction!')); } $adapter = HeraldDifferentialRevisionAdapter::newLegacyAdapter( $revision, $revision->getActiveDiff()); return $adapter; } /** * Update the table which links Differential revisions to paths they affect, * so Diffusion can efficiently find pending revisions for a given file. */ private function updateAffectedPathTable( DifferentialRevision $revision, DifferentialDiff $diff) { $repository = $revision->getRepository(); if (!$repository) { // The repository where the code lives is untracked. return; } $path_prefix = null; $local_root = $diff->getSourceControlPath(); if ($local_root) { // We're in a working copy which supports subdirectory checkouts (e.g., // SVN) so we need to figure out what prefix we should add to each path // (e.g., trunk/projects/example/) to get the absolute path from the // root of the repository. DVCS systems like Git and Mercurial are not // affected. // Normalize both paths and check if the repository root is a prefix of // the local root. If so, throw it away. Note that this correctly handles // the case where the remote path is "/". $local_root = id(new PhutilURI($local_root))->getPath(); $local_root = rtrim($local_root, '/'); $repo_root = id(new PhutilURI($repository->getRemoteURI()))->getPath(); $repo_root = rtrim($repo_root, '/'); if (!strncmp($repo_root, $local_root, strlen($repo_root))) { $path_prefix = substr($local_root, strlen($repo_root)); } } $changesets = $diff->getChangesets(); $paths = array(); foreach ($changesets as $changeset) { $paths[] = $path_prefix.'/'.$changeset->getFilename(); } // Save the affected paths; we'll use them later to query Owners. This // uses the un-expanded paths. $this->affectedPaths = $paths; // Mark this as also touching all parent paths, so you can see all pending // changes to any file within a directory. $all_paths = array(); foreach ($paths as $local) { foreach (DiffusionPathIDQuery::expandPathToRoot($local) as $path) { $all_paths[$path] = true; } } $all_paths = array_keys($all_paths); $path_ids = PhabricatorRepositoryCommitChangeParserWorker::lookupOrCreatePaths( $all_paths); $table = new DifferentialAffectedPath(); $conn_w = $table->establishConnection('w'); $sql = array(); foreach ($path_ids as $path_id) { $sql[] = qsprintf( $conn_w, '(%d, %d, %d, %d)', $repository->getID(), $path_id, time(), $revision->getID()); } queryfx( $conn_w, 'DELETE FROM %T WHERE revisionID = %d', $table->getTableName(), $revision->getID()); foreach (array_chunk($sql, 256) as $chunk) { queryfx( $conn_w, 'INSERT INTO %T (repositoryID, pathID, epoch, revisionID) VALUES %Q', $table->getTableName(), implode(', ', $chunk)); } } /** * Update the table connecting revisions to DVCS local hashes, so we can * identify revisions by commit/tree hashes. */ private function updateRevisionHashTable( DifferentialRevision $revision, DifferentialDiff $diff) { $vcs = $diff->getSourceControlSystem(); if ($vcs == DifferentialRevisionControlSystem::SVN) { // Subversion has no local commit or tree hash information, so we don't // have to do anything. return; } $property = id(new DifferentialDiffProperty())->loadOneWhere( 'diffID = %d AND name = %s', $diff->getID(), 'local:commits'); if (!$property) { return; } $hashes = array(); $data = $property->getData(); switch ($vcs) { case DifferentialRevisionControlSystem::GIT: foreach ($data as $commit) { $hashes[] = array( ArcanistDifferentialRevisionHash::HASH_GIT_COMMIT, $commit['commit'], ); $hashes[] = array( ArcanistDifferentialRevisionHash::HASH_GIT_TREE, $commit['tree'], ); } break; case DifferentialRevisionControlSystem::MERCURIAL: foreach ($data as $commit) { $hashes[] = array( ArcanistDifferentialRevisionHash::HASH_MERCURIAL_COMMIT, $commit['rev'], ); } break; } $conn_w = $revision->establishConnection('w'); $sql = array(); foreach ($hashes as $info) { list($type, $hash) = $info; $sql[] = qsprintf( $conn_w, '(%d, %s, %s)', $revision->getID(), $type, $hash); } queryfx( $conn_w, 'DELETE FROM %T WHERE revisionID = %d', ArcanistDifferentialRevisionHash::TABLE_NAME, $revision->getID()); if ($sql) { queryfx( $conn_w, 'INSERT INTO %T (revisionID, type, hash) VALUES %Q', ArcanistDifferentialRevisionHash::TABLE_NAME, implode(', ', $sql)); } } private function renderAffectedFilesForMail(DifferentialDiff $diff) { $changesets = $diff->getChangesets(); $filenames = mpull($changesets, 'getDisplayFilename'); sort($filenames); $count = count($filenames); $max = 250; if ($count > $max) { $filenames = array_slice($filenames, 0, $max); $filenames[] = pht('(%d more files...)', ($count - $max)); } return implode("\n", $filenames); } private function renderPatchHTMLForMail($patch) { return phutil_tag('pre', array('style' => 'font-family: monospace;'), $patch); } private function buildPatchForMail(DifferentialDiff $diff) { $format = PhabricatorEnv::getEnvConfig('metamta.differential.patch-format'); return id(new DifferentialRawDiffRenderer()) ->setViewer($this->getActor()) ->setFormat($format) ->setChangesets($diff->getChangesets()) ->buildPatch(); } protected function willPublish(PhabricatorLiskDAO $object, array $xactions) { // Reload to pick up the active diff and reviewer status. return id(new DifferentialRevisionQuery()) ->setViewer($this->getActor()) ->needReviewerStatus(true) ->needActiveDiffs(true) ->withIDs(array($object->getID())) ->executeOne(); } protected function getCustomWorkerState() { return array( 'changedPriorToCommitURI' => $this->changedPriorToCommitURI, ); } protected function loadCustomWorkerState(array $state) { $this->changedPriorToCommitURI = idx($state, 'changedPriorToCommitURI'); return $this; } } diff --git a/src/applications/differential/field/DifferentialAuditorsCommitMessageField.php b/src/applications/differential/field/DifferentialAuditorsCommitMessageField.php new file mode 100644 index 0000000000..94f629e557 --- /dev/null +++ b/src/applications/differential/field/DifferentialAuditorsCommitMessageField.php @@ -0,0 +1,45 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + )); + } + + public function getCustomFieldKey() { + return 'phabricator:auditors'; + } + + public function isFieldEditable() { + return true; + } + + public function isTemplateField() { + return false; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + protected function readFieldValueFromCustomFieldStorage($value) { + return $this->readJSONFieldValueFromCustomFieldStorage($value, array()); + } + +} diff --git a/src/applications/differential/field/DifferentialBlameRevisionCommitMessageField.php b/src/applications/differential/field/DifferentialBlameRevisionCommitMessageField.php new file mode 100644 index 0000000000..feb17b16c9 --- /dev/null +++ b/src/applications/differential/field/DifferentialBlameRevisionCommitMessageField.php @@ -0,0 +1,22 @@ +getCustomFieldKey(); + return 100000 + $this->getCustomFieldOrder($custom_key); + } + + public function isFieldEnabled() { + $custom_key = $this->getCustomFieldKey(); + return $this->isCustomFieldEnabled($custom_key); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + $custom_key = $this->getCustomFieldKey(); + $value = $this->readCustomFieldValue($revision, $custom_key); + return $value; + } + + protected function readFieldValueFromCustomFieldStorage($value) { + return $value; + } + + protected function readJSONFieldValueFromCustomFieldStorage( + $value, + $default) { + try { + return phutil_json_decode($value); + } catch (PhutilJSONParserException $ex) { + return $default; + } + } + + protected function readCustomFieldValue( + DifferentialRevision $revision, + $key) { + $value = idx($this->getCustomFieldStorage(), $key); + return $this->readFieldValueFromCustomFieldStorage($value); + } + + protected function getCustomFieldOrder($key) { + $field_list = PhabricatorCustomField::getObjectFields( + new DifferentialRevision(), + DifferentialCustomField::ROLE_COMMITMESSAGE); + + $fields = $field_list->getFields(); + + $idx = 0; + foreach ($fields as $field_key => $value) { + if ($key === $field_key) { + return $idx; + } + $idx++; + } + + return $idx; + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => $this->getCommitMessageFieldKey(), + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialCommitMessageField.php b/src/applications/differential/field/DifferentialCommitMessageField.php new file mode 100644 index 0000000000..ebe10bcf88 --- /dev/null +++ b/src/applications/differential/field/DifferentialCommitMessageField.php @@ -0,0 +1,191 @@ +viewer = $viewer; + return $this; + } + + final public function getViewer() { + return $this->viewer; + } + + final public function setCustomFieldStorage(array $custom_field_storage) { + $this->customFieldStorage = $custom_field_storage; + return $this; + } + + final public function getCustomFieldStorage() { + return $this->customFieldStorage; + } + + abstract public function getFieldName(); + abstract public function getFieldOrder(); + + public function isFieldEnabled() { + return true; + } + + public function getFieldAliases() { + return array(); + } + + public function validateFieldValue($value) { + return; + } + + public function parseFieldValue($value) { + return $value; + } + + public function isFieldEditable() { + return true; + } + + public function isTemplateField() { + return true; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringFieldValueFromConduit($value); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + return null; + } + + public function renderFieldValue($value) { + if (!strlen($value)) { + return null; + } + + return $value; + } + + public function getFieldTransactions($value) { + if (!$this->isFieldEditable()) { + return array(); + } + throw new PhutilMethodNotImplementedException(); + } + + final public function getCommitMessageFieldKey() { + return $this->getPhobjectClassConstant('FIELDKEY', 64); + } + + final public static function newEnabledFields(PhabricatorUser $viewer) { + $fields = self::getAllFields(); + + $results = array(); + foreach ($fields as $key => $field) { + $field = clone $field; + $field->setViewer($viewer); + if ($field->isFieldEnabled()) { + $results[$key] = $field; + } + } + + return $results; + } + + final public static function getAllFields() { + return id(new PhutilClassMapQuery()) + ->setAncestorClass(__CLASS__) + ->setUniqueMethod('getCommitMessageFieldKey') + ->setSortMethod('getFieldOrder') + ->execute(); + } + + protected function raiseParseException($message) { + throw new DifferentialFieldParseException($message); + } + + protected function raiseValidationException($message) { + throw new DifferentialFieldValidationException($message); + } + + protected function parseObjectList( + $value, + array $types, + $allow_partial = false, + array $suffixes = array()) { + return id(new PhabricatorObjectListQuery()) + ->setViewer($this->getViewer()) + ->setAllowedTypes($types) + ->setObjectList($value) + ->setAllowPartialResults($allow_partial) + ->setSuffixes($suffixes) + ->execute(); + } + + protected function renderHandleList(array $phids, array $suffixes = array()) { + if (!$phids) { + return null; + } + + $handles = $this->getViewer()->loadHandles($phids); + + $out = array(); + foreach ($handles as $handle) { + $phid = $handle->getPHID(); + + if ($handle->getPolicyFiltered()) { + $token = $phid; + } else if ($handle->isComplete()) { + $token = $handle->getCommandLineObjectName(); + } + + $suffix = idx($suffixes, $phid); + $token = $token.$suffix; + + $out[] = $token; + } + + return implode(', ', $out); + } + + protected function readStringFieldValueFromConduit($value) { + if ($value === null) { + return $value; + } + + if (!is_string($value)) { + throw new Exception( + pht( + 'Field "%s" expects a string value, but received a value of type '. + '"%s".', + $this->getCommitMessageFieldKey(), + gettype($value))); + } + + return $value; + } + + protected function readStringListFieldValueFromConduit($value) { + if (!is_array($value)) { + throw new Exception( + pht( + 'Field "%s" expects a list of strings, but received a value of type '. + '"%s".', + $this->getCommitMessageFieldKey(), + gettype($value))); + } + + return $value; + } + + protected function isCustomFieldEnabled($key) { + $field_list = PhabricatorCustomField::getObjectFields( + new DifferentialRevision(), + DifferentialCustomField::ROLE_DEFAULT); + + $fields = $field_list->getFields(); + return isset($fields[$key]); + } + +} diff --git a/src/applications/differential/field/DifferentialConflictsCommitMessageField.php b/src/applications/differential/field/DifferentialConflictsCommitMessageField.php new file mode 100644 index 0000000000..5a4c281157 --- /dev/null +++ b/src/applications/differential/field/DifferentialConflictsCommitMessageField.php @@ -0,0 +1,24 @@ +readJSONFieldValueFromCustomFieldStorage($value, array()); + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + if (!$value) { + return null; + } + + return implode(', ', $value); + } + +} diff --git a/src/applications/differential/field/DifferentialRevertPlanCommitMessageField.php b/src/applications/differential/field/DifferentialRevertPlanCommitMessageField.php new file mode 100644 index 0000000000..0a813130f9 --- /dev/null +++ b/src/applications/differential/field/DifferentialRevertPlanCommitMessageField.php @@ -0,0 +1,16 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + ), + $allow_partial = true); + } + + public function isFieldEditable() { + return false; + } + + public function isTemplateField() { + return false; + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $phids = array(); + foreach ($revision->getReviewerStatus() as $reviewer) { + switch ($reviewer->getStatus()) { + case DifferentialReviewerStatus::STATUS_ACCEPTED: + case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER: + $phids[] = $reviewer->getReviewerPHID(); + break; + } + } + + return $phids; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + +} diff --git a/src/applications/differential/field/DifferentialReviewersCommitMessageField.php b/src/applications/differential/field/DifferentialReviewersCommitMessageField.php new file mode 100644 index 0000000000..0f110b6e3a --- /dev/null +++ b/src/applications/differential/field/DifferentialReviewersCommitMessageField.php @@ -0,0 +1,136 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + PhabricatorOwnersPackagePHIDType::TYPECONST, + ), + false, + array('!')); + + return $this->flattenReviewers($results); + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + + $results = array(); + foreach ($revision->getReviewerStatus() as $reviewer) { + if ($reviewer->getStatus() == $status_blocking) { + $suffixes = array('!' => '!'); + } else { + $suffixes = array(); + } + + $results[] = array( + 'phid' => $reviewer->getReviewerPHID(), + 'suffixes' => $suffixes, + ); + } + + return $this->flattenReviewers($results); + } + + public function renderFieldValue($value) { + $value = $this->inflateReviewers($value); + + $phid_list = array(); + $suffix_map = array(); + foreach ($value as $reviewer) { + $phid = $reviewer['phid']; + $phid_list[] = $phid; + if (isset($reviewer['suffixes']['!'])) { + $suffix_map[$phid] = '!'; + } + } + + return $this->renderHandleList($phid_list, $suffix_map); + } + + public function getFieldTransactions($value) { + $value = $this->inflateReviewers($value); + + $reviewer_list = array(); + foreach ($value as $reviewer) { + $phid = $reviewer['phid']; + if (isset($reviewer['suffixes']['!'])) { + $reviewer_list[] = 'blocking('.$phid.')'; + } else { + $reviewer_list[] = $phid; + } + } + + $xaction_key = DifferentialRevisionReviewersTransaction::EDITKEY; + $xaction_type = "{$xaction_key}.set"; + + return array( + array( + 'type' => $xaction_type, + 'value' => $reviewer_list, + ), + ); + } + + private function flattenReviewers(array $values) { + // NOTE: For now, `arc` relies on this field returning only scalars, so we + // need to reduce the results into scalars. See T10981. + $result = array(); + + foreach ($values as $value) { + $result[] = $value['phid'].implode('', array_keys($value['suffixes'])); + } + + return $result; + } + + private function inflateReviewers(array $values) { + $result = array(); + + foreach ($values as $value) { + if (substr($value, -1) == '!') { + $value = substr($value, 0, -1); + $suffixes = array('!' => '!'); + } else { + $suffixes = array(); + } + + $result[] = array( + 'phid' => $value, + 'suffixes' => $suffixes, + ); + } + + return $result; + } + +} diff --git a/src/applications/differential/customfield/DifferentialRevisionIDField.php b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php similarity index 60% rename from src/applications/differential/customfield/DifferentialRevisionIDField.php rename to src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php index 9d23cf7658..1c4a2c9d60 100644 --- a/src/applications/differential/customfield/DifferentialRevisionIDField.php +++ b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php @@ -1,85 +1,83 @@ revisionID, $this->getObject()->getID()); - if (!$id) { - return null; - } - return PhabricatorEnv::getProductionURI('/D'.$id); - } - - public function readValueFromCommitMessage($value) { - $this->revisionID = $value; - } - private static function parseRevisionIDFromURI($uri_string) { $uri = new PhutilURI($uri_string); $path = $uri->getPath(); $matches = null; if (preg_match('#^/D(\d+)$#', $path, $matches)) { $id = (int)$matches[1]; $prod_uri = new PhutilURI(PhabricatorEnv::getProductionURI('/D'.$id)); // Make sure the URI is the same as our URI. Basically, we want to ignore // commits from other Phabricator installs. if ($uri->getDomain() == $prod_uri->getDomain()) { return $id; } $allowed_uris = PhabricatorEnv::getAllowedURIs('/D'.$id); foreach ($allowed_uris as $allowed_uri) { if ($uri_string == $allowed_uri) { return $id; } } } return null; } + public function readFieldValueFromObject(DifferentialRevision $revision) { + return $revision->getID(); + } + + public function readFieldValueFromConduit($value) { + if (is_int($value)) { + $value = (string)$value; + } + return $this->readStringFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + if (!strlen($value)) { + return null; + } + + return PhabricatorEnv::getProductionURI('/D'.$value); + } + + public function getFieldTransactions($value) { + return array(); + } + } diff --git a/src/applications/differential/field/DifferentialSubscribersCommitMessageField.php b/src/applications/differential/field/DifferentialSubscribersCommitMessageField.php new file mode 100644 index 0000000000..12d36e4381 --- /dev/null +++ b/src/applications/differential/field/DifferentialSubscribersCommitMessageField.php @@ -0,0 +1,60 @@ +parseObjectList( + $value, + array( + PhabricatorPeopleUserPHIDType::TYPECONST, + PhabricatorProjectProjectPHIDType::TYPECONST, + PhabricatorOwnersPackagePHIDType::TYPECONST, + )); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + return PhabricatorSubscribersQuery::loadSubscribersForPHID( + $revision->getPHID()); + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => PhabricatorSubscriptionsEditEngineExtension::EDITKEY_SET, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialSummaryCommitMessageField.php b/src/applications/differential/field/DifferentialSummaryCommitMessageField.php new file mode 100644 index 0000000000..6b57942470 --- /dev/null +++ b/src/applications/differential/field/DifferentialSummaryCommitMessageField.php @@ -0,0 +1,29 @@ +getSummary(); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => DifferentialRevisionSummaryTransaction::EDITKEY, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialTagsCommitMessageField.php b/src/applications/differential/field/DifferentialTagsCommitMessageField.php new file mode 100644 index 0000000000..fc6267f1ce --- /dev/null +++ b/src/applications/differential/field/DifferentialTagsCommitMessageField.php @@ -0,0 +1,66 @@ +parseObjectList( + $value, + array( + PhabricatorProjectProjectPHIDType::TYPECONST, + )); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $projects = PhabricatorEdgeQuery::loadDestinationPHIDs( + $revision->getPHID(), + PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); + $projects = array_reverse($projects); + + return $projects; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => PhabricatorProjectsEditEngineExtension::EDITKEY_SET, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialTasksCommitMessageField.php b/src/applications/differential/field/DifferentialTasksCommitMessageField.php new file mode 100644 index 0000000000..eea0afef8d --- /dev/null +++ b/src/applications/differential/field/DifferentialTasksCommitMessageField.php @@ -0,0 +1,65 @@ +parseObjectList( + $value, + array( + ManiphestTaskPHIDType::TYPECONST, + )); + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + if (!$revision->getPHID()) { + return array(); + } + + $projects = PhabricatorEdgeQuery::loadDestinationPHIDs( + $revision->getPHID(), + DifferentialRevisionHasTaskEdgeType::EDGECONST); + $projects = array_reverse($projects); + + return $projects; + } + + public function readFieldValueFromConduit($value) { + return $this->readStringListFieldValueFromConduit($value); + } + + public function renderFieldValue($value) { + return $this->renderHandleList($value); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => 'tasks.set', + 'value' => $value, + ), + ); + } +} diff --git a/src/applications/differential/field/DifferentialTestPlanCommitMessageField.php b/src/applications/differential/field/DifferentialTestPlanCommitMessageField.php new file mode 100644 index 0000000000..a477a9036e --- /dev/null +++ b/src/applications/differential/field/DifferentialTestPlanCommitMessageField.php @@ -0,0 +1,53 @@ +isCustomFieldEnabled('differential:test-plan'); + } + + public function validateFieldValue($value) { + $is_required = PhabricatorEnv::getEnvConfig( + 'differential.require-test-plan-field'); + + if ($is_required && !strlen($value)) { + $this->raiseValidationException( + pht( + 'You must provide a test plan. Describe the actions you performed '. + 'to verify the behavior of this change.')); + } + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + return $revision->getTestPlan(); + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => DifferentialRevisionTestPlanTransaction::EDITKEY, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/field/DifferentialTitleCommitMessageField.php b/src/applications/differential/field/DifferentialTitleCommitMessageField.php new file mode 100644 index 0000000000..6b39796f3a --- /dev/null +++ b/src/applications/differential/field/DifferentialTitleCommitMessageField.php @@ -0,0 +1,59 @@ +'); + } + + public function parseFieldValue($value) { + if ($value === self::getDefaultTitle()) { + $this->raiseParseException( + pht( + 'Replace the default title line with a human-readable revision '. + 'title which describes the changes you are making.')); + } + + return parent::parseFieldValue($value); + } + + public function validateFieldValue($value) { + if (!strlen($value)) { + $this->raiseValidationException( + pht( + 'You must provide a revision title in the first line '. + 'of your commit message.')); + } + } + + public function readFieldValueFromObject(DifferentialRevision $revision) { + $value = $revision->getTitle(); + + if (!strlen($value)) { + return self::getDefaultTitle(); + } + + return $value; + } + + public function getFieldTransactions($value) { + return array( + array( + 'type' => DifferentialRevisionTitleTransaction::EDITKEY, + 'value' => $value, + ), + ); + } + +} diff --git a/src/applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php b/src/applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php deleted file mode 100644 index 90c0be1717..0000000000 --- a/src/applications/differential/management/PhabricatorHunksManagementMigrateWorkflow.php +++ /dev/null @@ -1,60 +0,0 @@ -setName('migrate') - ->setExamples('**migrate**') - ->setSynopsis(pht('Migrate hunks to modern storage.')) - ->setArguments(array()); - } - - public function execute(PhutilArgumentParser $args) { - $saw_any_rows = false; - $console = PhutilConsole::getConsole(); - - $table = new DifferentialLegacyHunk(); - foreach (new LiskMigrationIterator($table) as $hunk) { - $saw_any_rows = true; - - $id = $hunk->getID(); - $console->writeOut("%s\n", pht('Migrating hunk %d...', $id)); - - $new_hunk = id(new DifferentialModernHunk()) - ->setChangesetID($hunk->getChangesetID()) - ->setOldOffset($hunk->getOldOffset()) - ->setOldLen($hunk->getOldLen()) - ->setNewOffset($hunk->getNewOffset()) - ->setNewLen($hunk->getNewLen()) - ->setChanges($hunk->getChanges()) - ->setDateCreated($hunk->getDateCreated()) - ->setDateModified($hunk->getDateModified()); - - $hunk->openTransaction(); - $new_hunk->save(); - $hunk->delete(); - $hunk->saveTransaction(); - - $old_len = strlen($hunk->getChanges()); - $new_len = strlen($new_hunk->getData()); - if ($old_len) { - $diff_len = ($old_len - $new_len); - $console->writeOut( - "%s\n", - pht( - 'Saved %s bytes (%s).', - new PhutilNumber($diff_len), - sprintf('%.1f%%', 100 * ($diff_len / $old_len)))); - } - } - - if ($saw_any_rows) { - $console->writeOut("%s\n", pht('Done.')); - } else { - $console->writeOut("%s\n", pht('No rows to migrate.')); - } - } - -} diff --git a/src/applications/differential/management/PhabricatorHunksManagementWorkflow.php b/src/applications/differential/management/PhabricatorHunksManagementWorkflow.php deleted file mode 100644 index a56a5f88e7..0000000000 --- a/src/applications/differential/management/PhabricatorHunksManagementWorkflow.php +++ /dev/null @@ -1,4 +0,0 @@ -setLabelMap($label_map) * ->setTitleKey($key_title) * ->setSummaryKey($key_summary); * * $fields = $parser->parseCorpus($corpus); * $errors = $parser->getErrors(); * * This is used by Differential to parse messages entered from the command line. * * @task config Configuring the Parser * @task parse Parsing Messages * @task support Support Methods * @task internal Internals */ final class DifferentialCommitMessageParser extends Phobject { + private $viewer; private $labelMap; private $titleKey; private $summaryKey; private $errors; - + private $commitMessageFields; + private $raiseMissingFieldErrors = true; public static function newStandardParser(PhabricatorUser $viewer) { + $key_title = DifferentialTitleCommitMessageField::FIELDKEY; + $key_summary = DifferentialSummaryCommitMessageField::FIELDKEY; - $key_title = id(new DifferentialTitleField())->getFieldKeyForConduit(); - $key_summary = id(new DifferentialSummaryField())->getFieldKeyForConduit(); - - $field_list = PhabricatorCustomField::getObjectFields( - new DifferentialRevision(), - DifferentialCustomField::ROLE_COMMITMESSAGE); - $field_list->setViewer($viewer); - - $label_map = array(); - - foreach ($field_list->getFields() as $field) { - $labels = $field->getCommitMessageLabels(); - $key = $field->getFieldKeyForConduit(); - - foreach ($labels as $label) { - $normal_label = self::normalizeFieldLabel( - $label); - if (!empty($label_map[$normal_label])) { - throw new Exception( - pht( - 'Field label "%s" is parsed by two custom fields: "%s" and '. - '"%s". Each label must be parsed by only one field.', - $label, - $key, - $label_map[$normal_label])); - } - $label_map[$normal_label] = $key; - } - } + $field_list = DifferentialCommitMessageField::newEnabledFields($viewer); return id(new self()) - ->setLabelMap($label_map) + ->setViewer($viewer) + ->setCommitMessageFields($field_list) ->setTitleKey($key_title) ->setSummaryKey($key_summary); } /* -( Configuring the Parser )--------------------------------------------- */ + /** + * @task config + */ + public function setViewer(PhabricatorUser $viewer) { + $this->viewer = $viewer; + return $this; + } + + + /** + * @task config + */ + public function getViewer() { + return $this->viewer; + } + + + /** + * @task config + */ + public function setCommitMessageFields($fields) { + assert_instances_of($fields, 'DifferentialCommitMessageField'); + $fields = mpull($fields, null, 'getCommitMessageFieldKey'); + $this->commitMessageFields = $fields; + return $this; + } + + + /** + * @task config + */ + public function getCommitMessageFields() { + return $this->commitMessageFields; + } + + + /** + * @task config + */ + public function setRaiseMissingFieldErrors($raise) { + $this->raiseMissingFieldErrors = $raise; + return $this; + } + + + /** + * @task config + */ + public function getRaiseMissingFieldErrors() { + return $this->raiseMissingFieldErrors; + } + + /** * @task config */ public function setLabelMap(array $label_map) { $this->labelMap = $label_map; return $this; } /** * @task config */ public function setTitleKey($title_key) { $this->titleKey = $title_key; return $this; } /** * @task config */ public function setSummaryKey($summary_key) { $this->summaryKey = $summary_key; return $this; } /* -( Parsing Messages )--------------------------------------------------- */ /** * @task parse */ public function parseCorpus($corpus) { $this->errors = array(); - $label_map = $this->labelMap; + $label_map = $this->getLabelMap(); $key_title = $this->titleKey; $key_summary = $this->summaryKey; if (!$key_title || !$key_summary || ($label_map === null)) { throw new Exception( pht( 'Expected %s, %s and %s to be set before parsing a corpus.', 'labelMap', 'summaryKey', 'titleKey')); } $label_regexp = $this->buildLabelRegexp($label_map); // NOTE: We're special casing things here to make the "Title:" label // optional in the message. $field = $key_title; $seen = array(); $lines = explode("\n", trim($corpus)); $field_map = array(); foreach ($lines as $key => $line) { $match = null; if (preg_match($label_regexp, $line, $match)) { $lines[$key] = trim($match['text']); $field = $label_map[self::normalizeFieldLabel($match['field'])]; if (!empty($seen[$field])) { $this->errors[] = pht( 'Field "%s" occurs twice in commit message!', $field); } $seen[$field] = true; } $field_map[$key] = $field; } $fields = array(); foreach ($lines as $key => $line) { $fields[$field_map[$key]][] = $line; } // This is a piece of special-cased magic which allows you to omit the // field labels for "title" and "summary". If the user enters a large block // of text at the beginning of the commit message with an empty line in it, // treat everything before the blank line as "title" and everything after // as "summary". if (isset($fields[$key_title]) && empty($fields[$key_summary])) { $lines = $fields[$key_title]; for ($ii = 0; $ii < count($lines); $ii++) { if (strlen(trim($lines[$ii])) == 0) { break; } } if ($ii != count($lines)) { $fields[$key_title] = array_slice($lines, 0, $ii); $summary = array_slice($lines, $ii); if (strlen(trim(implode("\n", $summary)))) { $fields[$key_summary] = $summary; } } } // Implode all the lines back into chunks of text. foreach ($fields as $name => $lines) { $data = rtrim(implode("\n", $lines)); $data = ltrim($data, "\n"); $fields[$name] = $data; } // This is another piece of special-cased magic which allows you to // enter a ridiculously long title, or just type a big block of stream // of consciousness text, and have some sort of reasonable result conjured // from it. if (isset($fields[$key_title])) { $terminal = '...'; $title = $fields[$key_title]; $short = id(new PhutilUTF8StringTruncator()) ->setMaximumBytes(250) ->setTerminator($terminal) ->truncateString($title); if ($short != $title) { // If we shortened the title, split the rest into the summary, so // we end up with a title like: // // Title title tile title title... // // ...and a summary like: // // ...title title title. // // Summary summary summary summary. $summary = idx($fields, $key_summary, ''); $offset = strlen($short) - strlen($terminal); $remainder = ltrim(substr($fields[$key_title], $offset)); $summary = '...'.$remainder."\n\n".$summary; $summary = rtrim($summary, "\n"); $fields[$key_title] = $short; $fields[$key_summary] = $summary; } } return $fields; } + /** + * @task parse + */ + public function parseFields($corpus) { + $viewer = $this->getViewer(); + $text_map = $this->parseCorpus($corpus); + + $field_map = $this->getCommitMessageFields(); + + $result_map = array(); + foreach ($text_map as $field_key => $text_value) { + $field = idx($field_map, $field_key); + if (!$field) { + // This is a strict error, since we only parse fields which we have + // been told are valid. The caller probably handed us an invalid label + // map. + throw new Exception( + pht( + 'Parser emitted a field with key "%s", but no corresponding '. + 'field definition exists.', + $field_key)); + } + + try { + $result = $field->parseFieldValue($text_value); + $result_map[$field_key] = $result; + } catch (DifferentialFieldParseException $ex) { + $this->errors[] = pht( + 'Error parsing field "%s": %s', + $field->getFieldName(), + $ex->getMessage()); + } + } + + if ($this->getRaiseMissingFieldErrors()) { + foreach ($field_map as $key => $field) { + try { + $field->validateFieldValue(idx($result_map, $key)); + } catch (DifferentialFieldValidationException $ex) { + $this->errors[] = pht( + 'Invalid or missing field "%s": %s', + $field->getFieldName(), + $ex->getMessage()); + } + } + } + + return $result_map; + } + + /** * @task parse */ public function getErrors() { return $this->errors; } /* -( Support Methods )---------------------------------------------------- */ /** * @task support */ public static function normalizeFieldLabel($label) { return phutil_utf8_strtolower($label); } /* -( Internals )---------------------------------------------------------- */ + private function getLabelMap() { + if ($this->labelMap === null) { + $field_list = $this->getCommitMessageFields(); + + $label_map = array(); + foreach ($field_list as $field_key => $field) { + $labels = $field->getFieldAliases(); + $labels[] = $field->getFieldName(); + + foreach ($labels as $label) { + $normal_label = self::normalizeFieldLabel($label); + if (!empty($label_map[$normal_label])) { + throw new Exception( + pht( + 'Field label "%s" is parsed by two custom fields: "%s" and '. + '"%s". Each label must be parsed by only one field.', + $label, + $field_key, + $label_map[$normal_label])); + } + + $label_map[$normal_label] = $field_key; + } + } + + $this->labelMap = $label_map; + } + + return $this->labelMap; + } + + /** * @task internal */ private function buildLabelRegexp(array $label_map) { $field_labels = array_keys($label_map); foreach ($field_labels as $key => $label) { $field_labels[$key] = preg_quote($label, '/'); } $field_labels = implode('|', $field_labels); $field_pattern = '/^(?P'.$field_labels.'):(?P.*)$/i'; return $field_pattern; } } diff --git a/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php b/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php index 669cfed220..320445fd0d 100644 --- a/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php +++ b/src/applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php @@ -1,59 +1,89 @@ setLabelMap($fields) ->setTitleKey('title') ->setSummaryKey('summary'); $result_output = $parser->parseCorpus($message); $result_errors = $parser->getErrors(); $this->assertEqual($output, $result_output); $this->assertEqual($errors, $result_errors); } } + + public function testDifferentialCommitMessageFieldParser() { + $message = << + 'This is the title.', + DifferentialSummaryCommitMessageField::FIELDKEY => + 'This is the summary.', + ); + + $parser = id(new DifferentialCommitMessageParser()) + ->setCommitMessageFields($fields) + ->setTitleKey(DifferentialTitleCommitMessageField::FIELDKEY) + ->setSummaryKey(DifferentialSummaryCommitMessageField::FIELDKEY); + + $actual = $parser->parseFields($message); + + $this->assertEqual($expect, $actual); + } + public function testDifferentialCommitMessageParserNormalization() { $map = array( 'Test Plan' => 'test plan', 'REVIEWERS' => 'reviewers', 'sUmmArY' => 'summary', ); foreach ($map as $input => $expect) { $this->assertEqual( $expect, DifferentialCommitMessageParser::normalizeFieldLabel($input), pht('Field normalization of label "%s".', $input)); } } } diff --git a/src/applications/differential/query/DifferentialHunkQuery.php b/src/applications/differential/query/DifferentialHunkQuery.php index 09beb0b6f7..c8e35cb607 100644 --- a/src/applications/differential/query/DifferentialHunkQuery.php +++ b/src/applications/differential/query/DifferentialHunkQuery.php @@ -1,122 +1,108 @@ changesets = $changesets; return $this; } public function needAttachToChangesets($attach) { $this->shouldAttachToChangesets = $attach; return $this; } protected function willExecute() { // If we fail to load any hunks at all (for example, because all of // the requested changesets are directories or empty files and have no // hunks) we'll never call didFilterPage(), and thus never have an // opportunity to attach hunks. Attach empty hunk lists now so that we // end up with the right result. if ($this->shouldAttachToChangesets) { foreach ($this->changesets as $changeset) { $changeset->attachHunks(array()); } } } protected function loadPage() { $all_results = array(); // Load modern hunks. $table = new DifferentialModernHunk(); $conn_r = $table->establishConnection('r'); $modern_data = queryfx_all( $conn_r, 'SELECT * FROM %T %Q %Q %Q', $table->getTableName(), $this->buildWhereClause($conn_r), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r)); $modern_results = $table->loadAllFromArray($modern_data); - - // Now, load legacy hunks. - $table = new DifferentialLegacyHunk(); - $conn_r = $table->establishConnection('r'); - - $legacy_data = queryfx_all( - $conn_r, - 'SELECT * FROM %T %Q %Q %Q', - $table->getTableName(), - $this->buildWhereClause($conn_r), - $this->buildOrderClause($conn_r), - $this->buildLimitClause($conn_r)); - $legacy_results = $table->loadAllFromArray($legacy_data); - // Strip all the IDs off since they're not unique and nothing should be // using them. - return array_values(array_merge($legacy_results, $modern_results)); + return array_values($modern_results); } protected function willFilterPage(array $hunks) { $changesets = mpull($this->changesets, null, 'getID'); foreach ($hunks as $key => $hunk) { $changeset = idx($changesets, $hunk->getChangesetID()); if (!$changeset) { unset($hunks[$key]); } $hunk->attachChangeset($changeset); } return $hunks; } protected function didFilterPage(array $hunks) { if ($this->shouldAttachToChangesets) { $hunk_groups = mgroup($hunks, 'getChangesetID'); foreach ($this->changesets as $changeset) { $hunks = idx($hunk_groups, $changeset->getID(), array()); $changeset->attachHunks($hunks); } } return $hunks; } protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { $where = array(); if (!$this->changesets) { throw new Exception( pht( 'You must load hunks via changesets, with %s!', 'withChangesets()')); } $where[] = qsprintf( $conn_r, 'changesetID IN (%Ld)', mpull($this->changesets, 'getID')); $where[] = $this->buildPagingClause($conn_r); return $this->formatWhereClause($where); } public function getQueryApplicationClass() { return 'PhabricatorDifferentialApplication'; } protected function getDefaultOrderVector() { // TODO: Do we need this? return array('-id'); } } diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php index f36a686eb5..6dd690d179 100644 --- a/src/applications/differential/query/DifferentialRevisionQuery.php +++ b/src/applications/differential/query/DifferentialRevisionQuery.php @@ -1,1112 +1,1114 @@ withStatus(DifferentialRevisionQuery::STATUS_OPEN) * ->execute(); * * @task config Query Configuration * @task exec Query Execution * @task internal Internals */ final class DifferentialRevisionQuery extends PhabricatorCursorPagedPolicyAwareQuery { private $pathIDs = array(); private $status = 'status-any'; const STATUS_ANY = 'status-any'; const STATUS_OPEN = 'status-open'; const STATUS_ACCEPTED = 'status-accepted'; const STATUS_NEEDS_REVIEW = 'status-needs-review'; const STATUS_NEEDS_REVISION = 'status-needs-revision'; const STATUS_CLOSED = 'status-closed'; const STATUS_ABANDONED = 'status-abandoned'; private $authors = array(); private $draftAuthors = array(); private $ccs = array(); private $reviewers = array(); private $revIDs = array(); private $commitHashes = array(); private $commitPHIDs = array(); private $phids = array(); private $responsibles = array(); private $branches = array(); private $repositoryPHIDs; private $updatedEpochMin; private $updatedEpochMax; const ORDER_MODIFIED = 'order-modified'; const ORDER_CREATED = 'order-created'; private $needRelationships = false; private $needActiveDiffs = false; private $needDiffIDs = false; private $needCommitPHIDs = false; private $needHashes = false; private $needReviewerStatus = false; private $needReviewerAuthority; private $needDrafts; private $needFlags; private $buildingGlobalOrder; /* -( Query Configuration )------------------------------------------------ */ /** * Filter results to revisions which affect a Diffusion path ID in a given * repository. You can call this multiple times to select revisions for * several paths. * * @param int Diffusion repository ID. * @param int Diffusion path ID. * @return this * @task config */ public function withPath($repository_id, $path_id) { $this->pathIDs[] = array( 'repositoryID' => $repository_id, 'pathID' => $path_id, ); return $this; } /** * Filter results to revisions authored by one of the given PHIDs. Calling * this function will clear anything set by previous calls to * @{method:withAuthors}. * * @param array List of PHIDs of authors * @return this * @task config */ public function withAuthors(array $author_phids) { $this->authors = $author_phids; return $this; } /** * Filter results to revisions which CC one of the listed people. Calling this * function will clear anything set by previous calls to @{method:withCCs}. * * @param array List of PHIDs of subscribers. * @return this * @task config */ public function withCCs(array $cc_phids) { $this->ccs = $cc_phids; return $this; } /** * Filter results to revisions that have one of the provided PHIDs as * reviewers. Calling this function will clear anything set by previous calls * to @{method:withReviewers}. * * @param array List of PHIDs of reviewers * @return this * @task config */ public function withReviewers(array $reviewer_phids) { $this->reviewers = $reviewer_phids; return $this; } /** * Filter results to revisions that have one of the provided commit hashes. * Calling this function will clear anything set by previous calls to * @{method:withCommitHashes}. * * @param array List of pairs * @return this * @task config */ public function withCommitHashes(array $commit_hashes) { $this->commitHashes = $commit_hashes; return $this; } /** * Filter results to revisions that have one of the provided PHIDs as * commits. Calling this function will clear anything set by previous calls * to @{method:withCommitPHIDs}. * * @param array List of PHIDs of commits * @return this * @task config */ public function withCommitPHIDs(array $commit_phids) { $this->commitPHIDs = $commit_phids; return $this; } /** * Filter results to revisions with a given status. Provide a class constant, * such as `DifferentialRevisionQuery::STATUS_OPEN`. * * @param const Class STATUS constant, like STATUS_OPEN. * @return this * @task config */ public function withStatus($status_constant) { $this->status = $status_constant; return $this; } /** * Filter results to revisions on given branches. * * @param list List of branch names. * @return this * @task config */ public function withBranches(array $branches) { $this->branches = $branches; return $this; } /** * Filter results to only return revisions whose ids are in the given set. * * @param array List of revision ids * @return this * @task config */ public function withIDs(array $ids) { $this->revIDs = $ids; return $this; } /** * Filter results to only return revisions whose PHIDs are in the given set. * * @param array List of revision PHIDs * @return this * @task config */ public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } /** * Given a set of users, filter results to return only revisions they are * responsible for (i.e., they are either authors or reviewers). * * @param array List of user PHIDs. * @return this * @task config */ public function withResponsibleUsers(array $responsible_phids) { $this->responsibles = $responsible_phids; return $this; } public function withRepositoryPHIDs(array $repository_phids) { $this->repositoryPHIDs = $repository_phids; return $this; } public function withUpdatedEpochBetween($min, $max) { $this->updatedEpochMin = $min; $this->updatedEpochMax = $max; return $this; } /** * Set whether or not the query will load and attach relationships. * * @param bool True to load and attach relationships. * @return this * @task config */ public function needRelationships($need_relationships) { $this->needRelationships = $need_relationships; return $this; } /** * Set whether or not the query should load the active diff for each * revision. * * @param bool True to load and attach diffs. * @return this * @task config */ public function needActiveDiffs($need_active_diffs) { $this->needActiveDiffs = $need_active_diffs; return $this; } /** * Set whether or not the query should load the associated commit PHIDs for * each revision. * * @param bool True to load and attach diffs. * @return this * @task config */ public function needCommitPHIDs($need_commit_phids) { $this->needCommitPHIDs = $need_commit_phids; return $this; } /** * Set whether or not the query should load associated diff IDs for each * revision. * * @param bool True to load and attach diff IDs. * @return this * @task config */ public function needDiffIDs($need_diff_ids) { $this->needDiffIDs = $need_diff_ids; return $this; } /** * Set whether or not the query should load associated commit hashes for each * revision. * * @param bool True to load and attach commit hashes. * @return this * @task config */ public function needHashes($need_hashes) { $this->needHashes = $need_hashes; return $this; } /** * Set whether or not the query should load associated reviewer status. * * @param bool True to load and attach reviewers. * @return this * @task config */ public function needReviewerStatus($need_reviewer_status) { $this->needReviewerStatus = $need_reviewer_status; return $this; } /** * Request information about the viewer's authority to act on behalf of each * reviewer. In particular, they have authority to act on behalf of projects * they are a member of. * * @param bool True to load and attach authority. * @return this * @task config */ public function needReviewerAuthority($need_reviewer_authority) { $this->needReviewerAuthority = $need_reviewer_authority; return $this; } public function needFlags($need_flags) { $this->needFlags = $need_flags; return $this; } public function needDrafts($need_drafts) { $this->needDrafts = $need_drafts; return $this; } /* -( Query Execution )---------------------------------------------------- */ public function newResultObject() { return new DifferentialRevision(); } /** * Execute the query as configured, returning matching * @{class:DifferentialRevision} objects. * * @return list List of matching DifferentialRevision objects. * @task exec */ protected function loadPage() { $data = $this->loadData(); $table = $this->newResultObject(); return $table->loadAllFromArray($data); } protected function willFilterPage(array $revisions) { $viewer = $this->getViewer(); $repository_phids = mpull($revisions, 'getRepositoryPHID'); $repository_phids = array_filter($repository_phids); $repositories = array(); if ($repository_phids) { $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()) ->withPHIDs($repository_phids) ->execute(); $repositories = mpull($repositories, null, 'getPHID'); } // If a revision is associated with a repository: // // - the viewer must be able to see the repository; or // - the viewer must have an automatic view capability. // // In the latter case, we'll load the revision but not load the repository. $can_view = PhabricatorPolicyCapability::CAN_VIEW; foreach ($revisions as $key => $revision) { $repo_phid = $revision->getRepositoryPHID(); if (!$repo_phid) { // The revision has no associated repository. Attach `null` and move on. $revision->attachRepository(null); continue; } $repository = idx($repositories, $repo_phid); if ($repository) { // The revision has an associated repository, and the viewer can see // it. Attach it and move on. $revision->attachRepository($repository); continue; } if ($revision->hasAutomaticCapability($can_view, $viewer)) { // The revision has an associated repository which the viewer can not // see, but the viewer has an automatic capability on this revision. // Load the revision without attaching a repository. $revision->attachRepository(null); continue; } if ($this->getViewer()->isOmnipotent()) { // The viewer is omnipotent. Allow the revision to load even without // a repository. $revision->attachRepository(null); continue; } // The revision has an associated repository, and the viewer can't see // it, and the viewer has no special capabilities. Filter out this // revision. $this->didRejectResult($revision); unset($revisions[$key]); } if (!$revisions) { return array(); } $table = new DifferentialRevision(); $conn_r = $table->establishConnection('r'); if ($this->needRelationships) { $this->loadRelationships($conn_r, $revisions); } if ($this->needCommitPHIDs) { $this->loadCommitPHIDs($conn_r, $revisions); } $need_active = $this->needActiveDiffs; $need_ids = $need_active || $this->needDiffIDs; if ($need_ids) { $this->loadDiffIDs($conn_r, $revisions); } if ($need_active) { $this->loadActiveDiffs($conn_r, $revisions); } if ($this->needHashes) { $this->loadHashes($conn_r, $revisions); } if ($this->needReviewerStatus || $this->needReviewerAuthority) { $this->loadReviewers($conn_r, $revisions); } return $revisions; } protected function didFilterPage(array $revisions) { $viewer = $this->getViewer(); if ($this->needFlags) { $flags = id(new PhabricatorFlagQuery()) ->setViewer($viewer) ->withOwnerPHIDs(array($viewer->getPHID())) ->withObjectPHIDs(mpull($revisions, 'getPHID')) ->execute(); $flags = mpull($flags, null, 'getObjectPHID'); foreach ($revisions as $revision) { $revision->attachFlag( $viewer, idx($flags, $revision->getPHID())); } } if ($this->needDrafts) { $drafts = id(new DifferentialDraft())->loadAllWhere( 'authorPHID = %s AND objectPHID IN (%Ls)', $viewer->getPHID(), mpull($revisions, 'getPHID')); $drafts = mgroup($drafts, 'getObjectPHID'); foreach ($revisions as $revision) { $revision->attachDrafts( $viewer, idx($drafts, $revision->getPHID(), array())); } } return $revisions; } private function loadData() { $table = $this->newResultObject(); $conn_r = $table->establishConnection('r'); $selects = array(); // NOTE: If the query includes "responsiblePHIDs", we execute it as a // UNION of revisions they own and revisions they're reviewing. This has // much better performance than doing it with JOIN/WHERE. if ($this->responsibles) { $basic_authors = $this->authors; $basic_reviewers = $this->reviewers; try { // Build the query where the responsible users are authors. $this->authors = array_merge($basic_authors, $this->responsibles); $this->reviewers = $basic_reviewers; $selects[] = $this->buildSelectStatement($conn_r); // Build the query where the responsible users are reviewers, or // projects they are members of are reviewers. $this->authors = $basic_authors; $this->reviewers = array_merge($basic_reviewers, $this->responsibles); $selects[] = $this->buildSelectStatement($conn_r); // Put everything back like it was. $this->authors = $basic_authors; $this->reviewers = $basic_reviewers; } catch (Exception $ex) { $this->authors = $basic_authors; $this->reviewers = $basic_reviewers; throw $ex; } } else { $selects[] = $this->buildSelectStatement($conn_r); } if (count($selects) > 1) { $this->buildingGlobalOrder = true; $query = qsprintf( $conn_r, '%Q %Q %Q', implode(' UNION DISTINCT ', $selects), $this->buildOrderClause($conn_r), $this->buildLimitClause($conn_r)); } else { $query = head($selects); } return queryfx_all($conn_r, '%Q', $query); } private function buildSelectStatement(AphrontDatabaseConnection $conn_r) { $table = new DifferentialRevision(); $select = $this->buildSelectClause($conn_r); $from = qsprintf( $conn_r, 'FROM %T r', $table->getTableName()); $joins = $this->buildJoinsClause($conn_r); $where = $this->buildWhereClause($conn_r); $group_by = $this->buildGroupClause($conn_r); $having = $this->buildHavingClause($conn_r); $this->buildingGlobalOrder = false; $order_by = $this->buildOrderClause($conn_r); $limit = $this->buildLimitClause($conn_r); return qsprintf( $conn_r, '(%Q %Q %Q %Q %Q %Q %Q %Q)', $select, $from, $joins, $where, $group_by, $having, $order_by, $limit); } /* -( Internals )---------------------------------------------------------- */ /** * @task internal */ private function buildJoinsClause($conn_r) { $joins = array(); if ($this->pathIDs) { $path_table = new DifferentialAffectedPath(); $joins[] = qsprintf( $conn_r, 'JOIN %T p ON p.revisionID = r.id', $path_table->getTableName()); } if ($this->commitHashes) { $joins[] = qsprintf( $conn_r, 'JOIN %T hash_rel ON hash_rel.revisionID = r.id', ArcanistDifferentialRevisionHash::TABLE_NAME); } if ($this->ccs) { $joins[] = qsprintf( $conn_r, 'JOIN %T e_ccs ON e_ccs.src = r.phid '. 'AND e_ccs.type = %s '. 'AND e_ccs.dst in (%Ls)', PhabricatorEdgeConfig::TABLE_NAME_EDGE, PhabricatorObjectHasSubscriberEdgeType::EDGECONST, $this->ccs); } if ($this->reviewers) { $joins[] = qsprintf( $conn_r, 'JOIN %T e_reviewers ON e_reviewers.src = r.phid '. 'AND e_reviewers.type = %s '. 'AND e_reviewers.dst in (%Ls)', PhabricatorEdgeConfig::TABLE_NAME_EDGE, DifferentialRevisionHasReviewerEdgeType::EDGECONST, $this->reviewers); } if ($this->draftAuthors) { $differential_draft = new DifferentialDraft(); $joins[] = qsprintf( $conn_r, 'JOIN %T has_draft ON has_draft.objectPHID = r.phid '. 'AND has_draft.authorPHID IN (%Ls)', $differential_draft->getTableName(), $this->draftAuthors); } if ($this->commitPHIDs) { $joins[] = qsprintf( $conn_r, 'JOIN %T commits ON commits.revisionID = r.id', DifferentialRevision::TABLE_COMMIT); } $joins[] = $this->buildJoinClauseParts($conn_r); return $this->formatJoinClause($joins); } /** * @task internal */ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { $where = array(); if ($this->pathIDs) { $path_clauses = array(); $repo_info = igroup($this->pathIDs, 'repositoryID'); foreach ($repo_info as $repository_id => $paths) { $path_clauses[] = qsprintf( $conn_r, '(p.repositoryID = %d AND p.pathID IN (%Ld))', $repository_id, ipull($paths, 'pathID')); } $path_clauses = '('.implode(' OR ', $path_clauses).')'; $where[] = $path_clauses; } if ($this->authors) { $where[] = qsprintf( $conn_r, 'r.authorPHID IN (%Ls)', $this->authors); } if ($this->revIDs) { $where[] = qsprintf( $conn_r, 'r.id IN (%Ld)', $this->revIDs); } if ($this->repositoryPHIDs) { $where[] = qsprintf( $conn_r, 'r.repositoryPHID IN (%Ls)', $this->repositoryPHIDs); } if ($this->commitHashes) { $hash_clauses = array(); foreach ($this->commitHashes as $info) { list($type, $hash) = $info; $hash_clauses[] = qsprintf( $conn_r, '(hash_rel.type = %s AND hash_rel.hash = %s)', $type, $hash); } $hash_clauses = '('.implode(' OR ', $hash_clauses).')'; $where[] = $hash_clauses; } if ($this->commitPHIDs) { $where[] = qsprintf( $conn_r, 'commits.commitPHID IN (%Ls)', $this->commitPHIDs); } if ($this->phids) { $where[] = qsprintf( $conn_r, 'r.phid IN (%Ls)', $this->phids); } if ($this->branches) { $where[] = qsprintf( $conn_r, 'r.branchName in (%Ls)', $this->branches); } if ($this->updatedEpochMin !== null) { $where[] = qsprintf( $conn_r, 'r.dateModified >= %d', $this->updatedEpochMin); } if ($this->updatedEpochMax !== null) { $where[] = qsprintf( $conn_r, 'r.dateModified <= %d', $this->updatedEpochMax); } // NOTE: Although the status constants are integers in PHP, the column is a // string column in MySQL, and MySQL won't use keys on string columns if // you put integers in the query. switch ($this->status) { case self::STATUS_ANY: break; case self::STATUS_OPEN: $where[] = qsprintf( $conn_r, 'r.status IN (%Ls)', DifferentialRevisionStatus::getOpenStatuses()); break; case self::STATUS_NEEDS_REVIEW: $where[] = qsprintf( $conn_r, 'r.status IN (%Ls)', array( ArcanistDifferentialRevisionStatus::NEEDS_REVIEW, )); break; case self::STATUS_NEEDS_REVISION: $where[] = qsprintf( $conn_r, 'r.status IN (%Ls)', array( ArcanistDifferentialRevisionStatus::NEEDS_REVISION, )); break; case self::STATUS_ACCEPTED: $where[] = qsprintf( $conn_r, 'r.status IN (%Ls)', array( ArcanistDifferentialRevisionStatus::ACCEPTED, )); break; case self::STATUS_CLOSED: $where[] = qsprintf( $conn_r, 'r.status IN (%Ls)', DifferentialRevisionStatus::getClosedStatuses()); break; case self::STATUS_ABANDONED: $where[] = qsprintf( $conn_r, 'r.status IN (%Ls)', array( ArcanistDifferentialRevisionStatus::ABANDONED, )); break; default: throw new Exception( pht("Unknown revision status filter constant '%s'!", $this->status)); } $where[] = $this->buildWhereClauseParts($conn_r); return $this->formatWhereClause($where); } /** * @task internal */ protected function shouldGroupQueryResultRows() { $join_triggers = array_merge( $this->pathIDs, $this->ccs, $this->reviewers); if (count($join_triggers) > 1) { return true; } return parent::shouldGroupQueryResultRows(); } public function getBuiltinOrders() { $orders = parent::getBuiltinOrders() + array( 'updated' => array( 'vector' => array('updated', 'id'), 'name' => pht('Date Updated (Latest First)'), 'aliases' => array(self::ORDER_MODIFIED), ), 'outdated' => array( 'vector' => array('-updated', '-id'), 'name' => pht('Date Updated (Oldest First)'), ), ); // Alias the "newest" builtin to the historical key for it. $orders['newest']['aliases'][] = self::ORDER_CREATED; return $orders; } protected function getDefaultOrderVector() { return array('updated', 'id'); } public function getOrderableColumns() { $primary = ($this->buildingGlobalOrder ? null : 'r'); return array( 'id' => array( 'table' => $primary, 'column' => 'id', 'type' => 'int', 'unique' => true, ), 'updated' => array( 'table' => $primary, 'column' => 'dateModified', 'type' => 'int', ), ); } protected function getPagingValueMap($cursor, array $keys) { $revision = $this->loadCursorObject($cursor); return array( 'id' => $revision->getID(), 'updated' => $revision->getDateModified(), ); } private function loadRelationships($conn_r, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $type_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; $type_subscriber = PhabricatorObjectHasSubscriberEdgeType::EDGECONST; $edges = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(mpull($revisions, 'getPHID')) ->withEdgeTypes(array($type_reviewer, $type_subscriber)) ->setOrder(PhabricatorEdgeQuery::ORDER_OLDEST_FIRST) ->execute(); $type_map = array( DifferentialRevision::RELATION_REVIEWER => $type_reviewer, DifferentialRevision::RELATION_SUBSCRIBED => $type_subscriber, ); foreach ($revisions as $revision) { $data = array(); foreach ($type_map as $rel_type => $edge_type) { $revision_edges = $edges[$revision->getPHID()][$edge_type]; foreach ($revision_edges as $dst_phid => $edge_data) { $data[] = array( 'relation' => $rel_type, 'objectPHID' => $dst_phid, 'reasonPHID' => null, ); } } $revision->attachRelationships($data); } } private function loadCommitPHIDs($conn_r, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $commit_phids = queryfx_all( $conn_r, 'SELECT * FROM %T WHERE revisionID IN (%Ld)', DifferentialRevision::TABLE_COMMIT, mpull($revisions, 'getID')); $commit_phids = igroup($commit_phids, 'revisionID'); foreach ($revisions as $revision) { $phids = idx($commit_phids, $revision->getID(), array()); $phids = ipull($phids, 'commitPHID'); $revision->attachCommitPHIDs($phids); } } private function loadDiffIDs($conn_r, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $diff_table = new DifferentialDiff(); $diff_ids = queryfx_all( $conn_r, 'SELECT revisionID, id FROM %T WHERE revisionID IN (%Ld) ORDER BY id DESC', $diff_table->getTableName(), mpull($revisions, 'getID')); $diff_ids = igroup($diff_ids, 'revisionID'); foreach ($revisions as $revision) { $ids = idx($diff_ids, $revision->getID(), array()); $ids = ipull($ids, 'id'); $revision->attachDiffIDs($ids); } } private function loadActiveDiffs($conn_r, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $diff_table = new DifferentialDiff(); $load_ids = array(); foreach ($revisions as $revision) { $diffs = $revision->getDiffIDs(); if ($diffs) { $load_ids[] = max($diffs); } } $active_diffs = array(); if ($load_ids) { $active_diffs = $diff_table->loadAllWhere( 'id IN (%Ld)', $load_ids); } $active_diffs = mpull($active_diffs, null, 'getRevisionID'); foreach ($revisions as $revision) { $revision->attachActiveDiff(idx($active_diffs, $revision->getID())); } } private function loadHashes( AphrontDatabaseConnection $conn_r, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $data = queryfx_all( $conn_r, 'SELECT * FROM %T WHERE revisionID IN (%Ld)', 'differential_revisionhash', mpull($revisions, 'getID')); $data = igroup($data, 'revisionID'); foreach ($revisions as $revision) { $hashes = idx($data, $revision->getID(), array()); $list = array(); foreach ($hashes as $hash) { $list[] = array($hash['type'], $hash['hash']); } $revision->attachHashes($list); } } private function loadReviewers( AphrontDatabaseConnection $conn_r, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST; $edges = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(mpull($revisions, 'getPHID')) ->withEdgeTypes(array($edge_type)) ->needEdgeData(true) ->setOrder(PhabricatorEdgeQuery::ORDER_OLDEST_FIRST) ->execute(); $viewer = $this->getViewer(); $viewer_phid = $viewer->getPHID(); $allow_key = 'differential.allow-self-accept'; $allow_self = PhabricatorEnv::getEnvConfig($allow_key); // Figure out which of these reviewers the viewer has authority to act as. if ($this->needReviewerAuthority && $viewer_phid) { $authority = $this->loadReviewerAuthority( $revisions, $edges, $allow_self); } foreach ($revisions as $revision) { $revision_edges = $edges[$revision->getPHID()][$edge_type]; $reviewers = array(); foreach ($revision_edges as $reviewer_phid => $edge) { - $reviewer = new DifferentialReviewer($reviewer_phid, $edge['data']); + $reviewer = new DifferentialReviewerProxy( + $reviewer_phid, + $edge['data']); if ($this->needReviewerAuthority) { if (!$viewer_phid) { // Logged-out users never have authority. $has_authority = false; } else if ((!$allow_self) && ($revision->getAuthorPHID() == $viewer_phid)) { // The author can never have authority unless we allow self-accept. $has_authority = false; } else { // Otherwise, look up whether the viewer has authority. $has_authority = isset($authority[$reviewer_phid]); } $reviewer->attachAuthority($viewer, $has_authority); } $reviewers[$reviewer_phid] = $reviewer; } $revision->attachReviewerStatus($reviewers); } } private function loadReviewerAuthority( array $revisions, array $edges, $allow_self) { $revision_map = mpull($revisions, null, 'getPHID'); $viewer_phid = $this->getViewer()->getPHID(); // Find all the project/package reviewers which the user may have authority // over. $project_phids = array(); $package_phids = array(); $project_type = PhabricatorProjectProjectPHIDType::TYPECONST; $package_type = PhabricatorOwnersPackagePHIDType::TYPECONST; $edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST; foreach ($edges as $src => $types) { if (!$allow_self) { if ($revision_map[$src]->getAuthorPHID() == $viewer_phid) { // If self-review isn't permitted, the user will never have // authority over projects on revisions they authored because you // can't accept your own revisions, so we don't need to load any // data about these reviewers. continue; } } $edge_data = idx($types, $edge_type, array()); foreach ($edge_data as $dst => $data) { $phid_type = phid_get_type($dst); if ($phid_type == $project_type) { $project_phids[] = $dst; } if ($phid_type == $package_type) { $package_phids[] = $dst; } } } // The viewer has authority over themselves. $user_authority = array_fuse(array($viewer_phid)); // And over any projects they are a member of. $project_authority = array(); if ($project_phids) { $project_authority = id(new PhabricatorProjectQuery()) ->setViewer($this->getViewer()) ->withPHIDs($project_phids) ->withMemberPHIDs(array($viewer_phid)) ->execute(); $project_authority = mpull($project_authority, 'getPHID'); $project_authority = array_fuse($project_authority); } // And over any packages they own. $package_authority = array(); if ($package_phids) { $package_authority = id(new PhabricatorOwnersPackageQuery()) ->setViewer($this->getViewer()) ->withPHIDs($package_phids) ->withAuthorityPHIDs(array($viewer_phid)) ->execute(); $package_authority = mpull($package_authority, 'getPHID'); $package_authority = array_fuse($package_authority); } return $user_authority + $project_authority + $package_authority; } public function getQueryApplicationClass() { return 'PhabricatorDifferentialApplication'; } protected function getPrimaryTableAlias() { return 'r'; } } diff --git a/src/applications/differential/storage/DifferentialChangeset.php b/src/applications/differential/storage/DifferentialChangeset.php index 4d7b9f5698..448cdb6343 100644 --- a/src/applications/differential/storage/DifferentialChangeset.php +++ b/src/applications/differential/storage/DifferentialChangeset.php @@ -1,229 +1,222 @@ array( 'metadata' => self::SERIALIZATION_JSON, 'oldProperties' => self::SERIALIZATION_JSON, 'newProperties' => self::SERIALIZATION_JSON, 'awayPaths' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'oldFile' => 'text255?', - 'filename' => 'text255', + 'oldFile' => 'bytes?', + 'filename' => 'bytes', 'changeType' => 'uint32', 'fileType' => 'uint32', 'addLines' => 'uint32', 'delLines' => 'uint32', // T6203/NULLABILITY // These should all be non-nullable, and store reasonable default // JSON values if empty. 'awayPaths' => 'text?', 'metadata' => 'text?', 'oldProperties' => 'text?', 'newProperties' => 'text?', ), self::CONFIG_KEY_SCHEMA => array( 'diffID' => array( 'columns' => array('diffID'), ), ), ) + parent::getConfiguration(); } public function getAffectedLineCount() { return $this->getAddLines() + $this->getDelLines(); } public function attachHunks(array $hunks) { assert_instances_of($hunks, 'DifferentialHunk'); $this->hunks = $hunks; return $this; } public function getHunks() { return $this->assertAttached($this->hunks); } public function getDisplayFilename() { $name = $this->getFilename(); if ($this->getFileType() == DifferentialChangeType::FILE_DIRECTORY) { $name .= '/'; } return $name; } public function addUnsavedHunk(DifferentialHunk $hunk) { if ($this->hunks === self::ATTACHABLE) { $this->hunks = array(); } $this->hunks[] = $hunk; $this->unsavedHunks[] = $hunk; return $this; } public function save() { $this->openTransaction(); $ret = parent::save(); foreach ($this->unsavedHunks as $hunk) { $hunk->setChangesetID($this->getID()); $hunk->save(); } $this->saveTransaction(); return $ret; } public function delete() { $this->openTransaction(); - $legacy_hunks = id(new DifferentialLegacyHunk())->loadAllWhere( - 'changesetID = %d', - $this->getID()); - foreach ($legacy_hunks as $legacy_hunk) { - $legacy_hunk->delete(); - } - $modern_hunks = id(new DifferentialModernHunk())->loadAllWhere( 'changesetID = %d', $this->getID()); foreach ($modern_hunks as $modern_hunk) { $modern_hunk->delete(); } $this->unsavedHunks = array(); queryfx( $this->establishConnection('w'), 'DELETE FROM %T WHERE id = %d', self::TABLE_CACHE, $this->getID()); $ret = parent::delete(); $this->saveTransaction(); return $ret; } public function getSortKey() { $sort_key = $this->getFilename(); // Sort files with ".h" in them first, so headers (.h, .hpp) come before // implementations (.c, .cpp, .cs). $sort_key = str_replace('.h', '.!h', $sort_key); return $sort_key; } public function makeNewFile() { $file = mpull($this->getHunks(), 'makeNewFile'); return implode('', $file); } public function makeOldFile() { $file = mpull($this->getHunks(), 'makeOldFile'); return implode('', $file); } public function makeChangesWithContext($num_lines = 3) { $with_context = array(); foreach ($this->getHunks() as $hunk) { $context = array(); $changes = explode("\n", $hunk->getChanges()); foreach ($changes as $l => $line) { $type = substr($line, 0, 1); if ($type == '+' || $type == '-') { $context += array_fill($l - $num_lines, 2 * $num_lines + 1, true); } } $with_context[] = array_intersect_key($changes, $context); } return array_mergev($with_context); } public function getAnchorName() { return substr(md5($this->getFilename()), 0, 8); } public function getAbsoluteRepositoryPath( PhabricatorRepository $repository = null, DifferentialDiff $diff = null) { $base = '/'; if ($diff && $diff->getSourceControlPath()) { $base = id(new PhutilURI($diff->getSourceControlPath()))->getPath(); } $path = $this->getFilename(); $path = rtrim($base, '/').'/'.ltrim($path, '/'); $svn = PhabricatorRepositoryType::REPOSITORY_TYPE_SVN; if ($repository && $repository->getVersionControlSystem() == $svn) { $prefix = $repository->getDetail('remote-uri'); $prefix = id(new PhutilURI($prefix))->getPath(); if (!strncmp($path, $prefix, strlen($prefix))) { $path = substr($path, strlen($prefix)); } $path = '/'.ltrim($path, '/'); } return $path; } public function getWhitespaceMatters() { $config = PhabricatorEnv::getEnvConfig('differential.whitespace-matters'); foreach ($config as $regexp) { if (preg_match($regexp, $this->getFilename())) { return true; } } return false; } public function attachDiff(DifferentialDiff $diff) { $this->diff = $diff; return $this; } public function getDiff() { return $this->assertAttached($this->diff); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, ); } public function getPolicy($capability) { return $this->getDiff()->getPolicy($capability); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return $this->getDiff()->hasAutomaticCapability($capability, $viewer); } } diff --git a/src/applications/differential/storage/DifferentialReviewer.php b/src/applications/differential/storage/DifferentialReviewerProxy.php similarity index 96% rename from src/applications/differential/storage/DifferentialReviewer.php rename to src/applications/differential/storage/DifferentialReviewerProxy.php index 1ad7fbc8b0..bf38ee27e3 100644 --- a/src/applications/differential/storage/DifferentialReviewer.php +++ b/src/applications/differential/storage/DifferentialReviewerProxy.php @@ -1,56 +1,56 @@ reviewerPHID = $reviewer_phid; $this->status = idx($edge_data, 'status'); $this->diffID = idx($edge_data, 'diff'); } public function getReviewerPHID() { return $this->reviewerPHID; } public function getStatus() { return $this->status; } public function getDiffID() { return $this->diffID; } public function isUser() { $user_type = PhabricatorPeopleUserPHIDType::TYPECONST; return (phid_get_type($this->getReviewerPHID()) == $user_type); } public function attachAuthority(PhabricatorUser $user, $has_authority) { $this->authority[$user->getPHID()] = $has_authority; return $this; } public function hasAuthority(PhabricatorUser $viewer) { // It would be nice to use assertAttachedKey() here, but we don't extend // PhabricatorLiskDAO, and faking that seems sketchy. $viewer_phid = $viewer->getPHID(); if (!array_key_exists($viewer_phid, $this->authority)) { throw new Exception(pht('You must %s first!', 'attachAuthority()')); } return $this->authority[$viewer_phid]; } public function getEdgeData() { return array( 'status' => $this->status, 'diffID' => $this->diffID, ); } } diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index 47443932e3..09e6cf932c 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -1,704 +1,724 @@ setViewer($actor) ->withClasses(array('PhabricatorDifferentialApplication')) ->executeOne(); $view_policy = $app->getPolicy( DifferentialDefaultViewCapability::CAPABILITY); return id(new DifferentialRevision()) ->setViewPolicy($view_policy) ->setAuthorPHID($actor->getPHID()) ->attachRelationships(array()) ->attachRepository(null) + ->attachActiveDiff(null) + ->attachReviewerStatus(array()) ->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'attached' => self::SERIALIZATION_JSON, 'unsubscribed' => self::SERIALIZATION_JSON, 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'title' => 'text255', 'originalTitle' => 'text255', 'status' => 'text32', 'summary' => 'text', 'testPlan' => 'text', 'authorPHID' => 'phid?', 'lastReviewerPHID' => 'phid?', 'lineCount' => 'uint32?', 'mailKey' => 'bytes40', 'branchName' => 'text255?', 'repositoryPHID' => 'phid?', ), self::CONFIG_KEY_SCHEMA => array( 'key_phid' => null, 'phid' => array( 'columns' => array('phid'), 'unique' => true, ), 'authorPHID' => array( 'columns' => array('authorPHID', 'status'), ), 'repositoryPHID' => array( 'columns' => array('repositoryPHID'), ), // If you (or a project you are a member of) is reviewing a significant // fraction of the revisions on an install, the result set of open // revisions may be smaller than the result set of revisions where you // are a reviewer. In these cases, this key is better than keys on the // edge table. 'key_status' => array( 'columns' => array('status', 'phid'), ), ), ) + parent::getConfiguration(); } public function setProperty($key, $value) { $this->properties[$key] = $value; return $this; } public function getProperty($key, $default = null) { return idx($this->properties, $key, $default); } public function hasRevisionProperty($key) { return array_key_exists($key, $this->properties); } public function getMonogram() { $id = $this->getID(); return "D{$id}"; } public function getURI() { return '/'.$this->getMonogram(); } public function setTitle($title) { $this->title = $title; if (!$this->getID()) { $this->originalTitle = $title; } return $this; } public function loadIDsByCommitPHIDs($phids) { if (!$phids) { return array(); } $revision_ids = queryfx_all( $this->establishConnection('r'), 'SELECT * FROM %T WHERE commitPHID IN (%Ls)', self::TABLE_COMMIT, $phids); return ipull($revision_ids, 'revisionID', 'commitPHID'); } public function loadCommitPHIDs() { if (!$this->getID()) { return ($this->commits = array()); } $commits = queryfx_all( $this->establishConnection('r'), 'SELECT commitPHID FROM %T WHERE revisionID = %d', self::TABLE_COMMIT, $this->getID()); $commits = ipull($commits, 'commitPHID'); return ($this->commits = $commits); } public function getCommitPHIDs() { return $this->assertAttached($this->commits); } public function getActiveDiff() { // TODO: Because it's currently technically possible to create a revision // without an associated diff, we allow an attached-but-null active diff. // It would be good to get rid of this once we make diff-attaching // transactional. return $this->assertAttached($this->activeDiff); } public function attachActiveDiff($diff) { $this->activeDiff = $diff; return $this; } public function getDiffIDs() { return $this->assertAttached($this->diffIDs); } public function attachDiffIDs(array $ids) { rsort($ids); $this->diffIDs = array_values($ids); return $this; } public function attachCommitPHIDs(array $phids) { $this->commits = array_values($phids); return $this; } public function getAttachedPHIDs($type) { return array_keys(idx($this->attached, $type, array())); } public function setAttachedPHIDs($type, array $phids) { $this->attached[$type] = array_fill_keys($phids, array()); return $this; } public function generatePHID() { return PhabricatorPHID::generateNewPHID( DifferentialRevisionPHIDType::TYPECONST); } public function loadActiveDiff() { return id(new DifferentialDiff())->loadOneWhere( 'revisionID = %d ORDER BY id DESC LIMIT 1', $this->getID()); } public function save() { if (!$this->getMailKey()) { $this->mailKey = Filesystem::readRandomCharacters(40); } return parent::save(); } public function loadRelationships() { if (!$this->getID()) { $this->relationships = array(); return; } $data = array(); $subscriber_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $this->getPHID(), PhabricatorObjectHasSubscriberEdgeType::EDGECONST); $subscriber_phids = array_reverse($subscriber_phids); foreach ($subscriber_phids as $phid) { $data[] = array( 'relation' => self::RELATION_SUBSCRIBED, 'objectPHID' => $phid, 'reasonPHID' => null, ); } $reviewer_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $this->getPHID(), DifferentialRevisionHasReviewerEdgeType::EDGECONST); $reviewer_phids = array_reverse($reviewer_phids); foreach ($reviewer_phids as $phid) { $data[] = array( 'relation' => self::RELATION_REVIEWER, 'objectPHID' => $phid, 'reasonPHID' => null, ); } return $this->attachRelationships($data); } public function attachRelationships(array $relationships) { $this->relationships = igroup($relationships, 'relation'); return $this; } public function getReviewers() { return $this->getRelatedPHIDs(self::RELATION_REVIEWER); } public function getCCPHIDs() { return $this->getRelatedPHIDs(self::RELATION_SUBSCRIBED); } private function getRelatedPHIDs($relation) { $this->assertAttached($this->relationships); return ipull($this->getRawRelations($relation), 'objectPHID'); } public function getRawRelations($relation) { return idx($this->relationships, $relation, array()); } public function getPrimaryReviewer() { $reviewers = $this->getReviewers(); $last = $this->lastReviewerPHID; if (!$last || !in_array($last, $reviewers)) { return head($this->getReviewers()); } return $last; } public function getHashes() { return $this->assertAttached($this->hashes); } public function attachHashes(array $hashes) { $this->hashes = $hashes; return $this; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $user) { // A revision's author (which effectively means "owner" after we added // commandeering) can always view and edit it. $author_phid = $this->getAuthorPHID(); if ($author_phid) { if ($user->getPHID() == $author_phid) { return true; } } return false; } public function describeAutomaticCapability($capability) { $description = array( pht('The owner of a revision can always view and edit it.'), ); switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: $description[] = pht("A revision's reviewers can always view it."); $description[] = pht( 'If a revision belongs to a repository, other users must be able '. 'to view the repository in order to view the revision.'); break; } return $description; } /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ public function getExtendedPolicy($capability, PhabricatorUser $viewer) { $extended = array(); switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: $repository_phid = $this->getRepositoryPHID(); $repository = $this->getRepository(); // Try to use the object if we have it, since it will save us some // data fetching later on. In some cases, we might not have it. $repository_ref = nonempty($repository, $repository_phid); if ($repository_ref) { $extended[] = array( $repository_ref, PhabricatorPolicyCapability::CAN_VIEW, ); } break; } return $extended; } /* -( PhabricatorTokenReceiverInterface )---------------------------------- */ public function getUsersToNotifyOfTokenGiven() { return array( $this->getAuthorPHID(), ); } public function getReviewerStatus() { return $this->assertAttached($this->reviewerStatus); } public function attachReviewerStatus(array $reviewers) { - assert_instances_of($reviewers, 'DifferentialReviewer'); + assert_instances_of($reviewers, 'DifferentialReviewerProxy'); $this->reviewerStatus = $reviewers; return $this; } + public function getReviewerPHIDsForEdit() { + $reviewers = $this->getReviewerStatus(); + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + + $value = array(); + foreach ($reviewers as $reviewer) { + $phid = $reviewer->getReviewerPHID(); + if ($reviewer->getStatus() == $status_blocking) { + $value[] = 'blocking('.$phid.')'; + } else { + $value[] = $phid; + } + } + + return $value; + } + public function getRepository() { return $this->assertAttached($this->repository); } public function attachRepository(PhabricatorRepository $repository = null) { $this->repository = $repository; return $this; } public function isClosed() { return DifferentialRevisionStatus::isClosedStatus($this->getStatus()); } public function getStatusIcon() { $map = array( ArcanistDifferentialRevisionStatus::NEEDS_REVIEW => 'fa-code grey', ArcanistDifferentialRevisionStatus::NEEDS_REVISION => 'fa-refresh red', ArcanistDifferentialRevisionStatus::CHANGES_PLANNED => 'fa-headphones red', ArcanistDifferentialRevisionStatus::ACCEPTED => 'fa-check green', ArcanistDifferentialRevisionStatus::CLOSED => 'fa-check-square-o black', ArcanistDifferentialRevisionStatus::ABANDONED => 'fa-plane black', ); return idx($map, $this->getStatus()); } public function getStatusDisplayName() { $status = $this->getStatus(); return ArcanistDifferentialRevisionStatus::getNameForRevisionStatus( $status); } public function getFlag(PhabricatorUser $viewer) { return $this->assertAttachedKey($this->flags, $viewer->getPHID()); } public function attachFlag( PhabricatorUser $viewer, PhabricatorFlag $flag = null) { $this->flags[$viewer->getPHID()] = $flag; return $this; } public function getDrafts(PhabricatorUser $viewer) { return $this->assertAttachedKey($this->drafts, $viewer->getPHID()); } public function attachDrafts(PhabricatorUser $viewer, array $drafts) { $this->drafts[$viewer->getPHID()] = $drafts; return $this; } /* -( HarbormasterBuildableInterface )------------------------------------- */ public function getHarbormasterBuildableDisplayPHID() { return $this->getHarbormasterContainerPHID(); } public function getHarbormasterBuildablePHID() { return $this->loadActiveDiff()->getPHID(); } public function getHarbormasterContainerPHID() { return $this->getPHID(); } public function getBuildVariables() { return array(); } public function getAvailableBuildVariables() { return array(); } /* -( PhabricatorSubscribableInterface )----------------------------------- */ public function isAutomaticallySubscribed($phid) { if ($phid == $this->getAuthorPHID()) { return true; } // TODO: This only happens when adding or removing CCs, and is safe from a // policy perspective, but the subscription pathway should have some // opportunity to load this data properly. For now, this is the only case // where implicit subscription is not an intrinsic property of the object. if ($this->reviewerStatus == self::ATTACHABLE) { $reviewers = id(new DifferentialRevisionQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs(array($this->getPHID())) ->needReviewerStatus(true) ->executeOne() ->getReviewerStatus(); } else { $reviewers = $this->getReviewerStatus(); } foreach ($reviewers as $reviewer) { if ($reviewer->getReviewerPHID() == $phid) { return true; } } return false; } /* -( PhabricatorCustomFieldInterface )------------------------------------ */ public function getCustomFieldSpecificationForRole($role) { return PhabricatorEnv::getEnvConfig('differential.fields'); } public function getCustomFieldBaseClass() { return 'DifferentialCustomField'; } public function getCustomFields() { return $this->assertAttached($this->customFields); } public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) { $this->customFields = $fields; return $this; } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new DifferentialTransactionEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new DifferentialTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { $viewer = $request->getViewer(); $render_data = $timeline->getRenderData(); $left = $request->getInt('left', idx($render_data, 'left')); $right = $request->getInt('right', idx($render_data, 'right')); $diffs = id(new DifferentialDiffQuery()) ->setViewer($request->getUser()) ->withIDs(array($left, $right)) ->execute(); $diffs = mpull($diffs, null, 'getID'); $left_diff = $diffs[$left]; $right_diff = $diffs[$right]; $old_ids = $request->getStr('old', idx($render_data, 'old')); $new_ids = $request->getStr('new', idx($render_data, 'new')); $old_ids = array_filter(explode(',', $old_ids)); $new_ids = array_filter(explode(',', $new_ids)); $type_inline = DifferentialTransaction::TYPE_INLINE; $changeset_ids = array_merge($old_ids, $new_ids); $inlines = array(); foreach ($timeline->getTransactions() as $xaction) { if ($xaction->getTransactionType() == $type_inline) { $inlines[] = $xaction->getComment(); $changeset_ids[] = $xaction->getComment()->getChangesetID(); } } if ($changeset_ids) { $changesets = id(new DifferentialChangesetQuery()) ->setViewer($request->getUser()) ->withIDs($changeset_ids) ->execute(); $changesets = mpull($changesets, null, 'getID'); } else { $changesets = array(); } foreach ($inlines as $key => $inline) { $inlines[$key] = DifferentialInlineComment::newFromModernComment( $inline); } $query = id(new DifferentialInlineCommentQuery()) ->needHidden(true) ->setViewer($viewer); // NOTE: This is a bit sketchy: this method adjusts the inlines as a // side effect, which means it will ultimately adjust the transaction // comments and affect timeline rendering. $query->adjustInlinesForChangesets( $inlines, array_select_keys($changesets, $old_ids), array_select_keys($changesets, $new_ids), $this); return $timeline ->setChangesets($changesets) ->setRevision($this) ->setLeftDiff($left_diff) ->setRightDiff($right_diff); } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); $diffs = id(new DifferentialDiffQuery()) ->setViewer($engine->getViewer()) ->withRevisionIDs(array($this->getID())) ->execute(); foreach ($diffs as $diff) { $engine->destroyObject($diff); } $conn_w = $this->establishConnection('w'); queryfx( $conn_w, 'DELETE FROM %T WHERE revisionID = %d', self::TABLE_COMMIT, $this->getID()); // we have to do paths a little differentally as they do not have // an id or phid column for delete() to act on $dummy_path = new DifferentialAffectedPath(); queryfx( $conn_w, 'DELETE FROM %T WHERE revisionID = %d', $dummy_path->getTableName(), $this->getID()); $this->delete(); $this->saveTransaction(); } /* -( PhabricatorFulltextInterface )--------------------------------------- */ public function newFulltextEngine() { return new DifferentialRevisionFulltextEngine(); } /* -( PhabricatorConduitResultInterface )---------------------------------- */ public function getFieldSpecificationsForConduit() { return array( id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('title') ->setType('string') ->setDescription(pht('The revision title.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('authorPHID') ->setType('phid') ->setDescription(pht('Revision author PHID.')), ); } public function getFieldValuesForConduit() { return array( 'title' => $this->getTitle(), 'authorPHID' => $this->getAuthorPHID(), ); } public function getConduitSearchAttachments() { return array(); } } diff --git a/src/applications/differential/storage/DifferentialTransaction.php b/src/applications/differential/storage/DifferentialTransaction.php index bc52227590..08c66c7fa5 100644 --- a/src/applications/differential/storage/DifferentialTransaction.php +++ b/src/applications/differential/storage/DifferentialTransaction.php @@ -1,667 +1,695 @@ getTransactionType(); + if ($xaction_type == PhabricatorTransactions::TYPE_CUSTOMFIELD) { + switch ($this->getMetadataValue('customfield:key')) { + case 'differential:title': + return new DifferentialRevisionTitleTransaction(); + case 'differential:test-plan': + return new DifferentialRevisionTestPlanTransaction(); + case 'differential:repository': + return new DifferentialRevisionRepositoryTransaction(); + } + } + + return parent::newFallbackModularTransactionType(); + } + public function setIsCommandeerSideEffect($is_side_effect) { $this->isCommandeerSideEffect = $is_side_effect; return $this; } public function getIsCommandeerSideEffect() { return $this->isCommandeerSideEffect; } public function getApplicationName() { return 'differential'; } public function getApplicationTransactionType() { return DifferentialRevisionPHIDType::TYPECONST; } public function getApplicationTransactionCommentObject() { return new DifferentialTransactionComment(); } public function getApplicationTransactionViewObject() { return new DifferentialTransactionView(); } public function shouldHide() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_UPDATE: // Older versions of this transaction have an ID for the new value, // and/or do not record the old value. Only hide the transaction if // the new value is a PHID, indicating that this is a newer style // transaction. if ($old === null) { if (phid_get_type($new) == DifferentialDiffPHIDType::TYPECONST) { return true; } } break; case PhabricatorTransactions::TYPE_EDGE: $add = array_diff_key($new, $old); $rem = array_diff_key($old, $new); // Hide metadata-only edge transactions. These correspond to users // accepting or rejecting revisions, but the change is always explicit // because of the TYPE_ACTION transaction. Rendering these transactions // just creates clutter. if (!$add && !$rem) { return true; } break; } return parent::shouldHide(); } public function isInlineCommentTransaction() { switch ($this->getTransactionType()) { case self::TYPE_INLINE: return true; } return parent::isInlineCommentTransaction(); } public function getRequiredHandlePHIDs() { $phids = parent::getRequiredHandlePHIDs(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_ACTION: if ($new == DifferentialAction::ACTION_CLOSE && $this->getMetadataValue('isCommitClose')) { $phids[] = $this->getMetadataValue('commitPHID'); if ($this->getMetadataValue('committerPHID')) { $phids[] = $this->getMetadataValue('committerPHID'); } if ($this->getMetadataValue('authorPHID')) { $phids[] = $this->getMetadataValue('authorPHID'); } } break; case self::TYPE_UPDATE: if ($new) { $phids[] = $new; } break; } return $phids; } public function getActionStrength() { switch ($this->getTransactionType()) { case self::TYPE_ACTION: return 3; case self::TYPE_UPDATE: return 2; } return parent::getActionStrength(); } public function getActionName() { switch ($this->getTransactionType()) { case self::TYPE_INLINE: return pht('Commented On'); case self::TYPE_UPDATE: $old = $this->getOldValue(); if ($old === null) { return pht('Request'); } else { return pht('Updated'); } case self::TYPE_ACTION: $map = array( DifferentialAction::ACTION_ACCEPT => pht('Accepted'), DifferentialAction::ACTION_REJECT => pht('Requested Changes To'), DifferentialAction::ACTION_RETHINK => pht('Planned Changes To'), DifferentialAction::ACTION_ABANDON => pht('Abandoned'), DifferentialAction::ACTION_CLOSE => pht('Closed'), DifferentialAction::ACTION_REQUEST => pht('Requested A Review Of'), DifferentialAction::ACTION_RESIGN => pht('Resigned From'), DifferentialAction::ACTION_ADDREVIEWERS => pht('Added Reviewers'), DifferentialAction::ACTION_CLAIM => pht('Commandeered'), DifferentialAction::ACTION_REOPEN => pht('Reopened'), ); $name = idx($map, $this->getNewValue()); if ($name !== null) { return $name; } break; } return parent::getActionName(); } public function getMailTags() { $tags = array(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_SUBSCRIBERS; $tags[] = self::MAILTAG_CC; break; case self::TYPE_ACTION: switch ($this->getNewValue()) { case DifferentialAction::ACTION_CLOSE: $tags[] = self::MAILTAG_CLOSED; break; } break; case self::TYPE_UPDATE: $old = $this->getOldValue(); if ($old === null) { $tags[] = self::MAILTAG_REVIEW_REQUEST; } else { $tags[] = self::MAILTAG_UPDATED; } break; case PhabricatorTransactions::TYPE_EDGE: switch ($this->getMetadataValue('edge:type')) { case DifferentialRevisionHasReviewerEdgeType::EDGECONST: $tags[] = self::MAILTAG_REVIEWERS; break; } break; case PhabricatorTransactions::TYPE_COMMENT: case self::TYPE_INLINE: $tags[] = self::MAILTAG_COMMENT; break; } if (!$tags) { $tags[] = self::MAILTAG_OTHER; } return $tags; } public function getTitle() { $author_phid = $this->getAuthorPHID(); $author_handle = $this->renderHandleLink($author_phid); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_INLINE: return pht( '%s added inline comments.', $author_handle); case self::TYPE_UPDATE: if ($this->getMetadataValue('isCommitUpdate')) { return pht( 'This revision was automatically updated to reflect the '. 'committed changes.'); } else if ($new) { // TODO: Migrate to PHIDs and use handles here? if (phid_get_type($new) == DifferentialDiffPHIDType::TYPECONST) { return pht( '%s updated this revision to %s.', $author_handle, $this->renderHandleLink($new)); } else { return pht( '%s updated this revision.', $author_handle); } } else { return pht( '%s updated this revision.', $author_handle); } case self::TYPE_ACTION: switch ($new) { case DifferentialAction::ACTION_CLOSE: if (!$this->getMetadataValue('isCommitClose')) { return DifferentialAction::getBasicStoryText( $new, $author_handle); } $commit_name = $this->renderHandleLink( $this->getMetadataValue('commitPHID')); $committer_phid = $this->getMetadataValue('committerPHID'); $author_phid = $this->getMetadataValue('authorPHID'); if ($this->getHandleIfExists($committer_phid)) { $committer_name = $this->renderHandleLink($committer_phid); } else { $committer_name = $this->getMetadataValue('committerName'); } if ($this->getHandleIfExists($author_phid)) { $author_name = $this->renderHandleLink($author_phid); } else { $author_name = $this->getMetadataValue('authorName'); } if ($committer_name && ($committer_name != $author_name)) { return pht( 'Closed by commit %s (authored by %s, committed by %s).', $commit_name, $author_name, $committer_name); } else { return pht( 'Closed by commit %s (authored by %s).', $commit_name, $author_name); } break; default: return DifferentialAction::getBasicStoryText($new, $author_handle); } break; case self::TYPE_STATUS: switch ($this->getNewValue()) { case ArcanistDifferentialRevisionStatus::ACCEPTED: return pht('This revision is now accepted and ready to land.'); case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: return pht('This revision now requires changes to proceed.'); case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: return pht('This revision now requires review to proceed.'); } } return parent::getTitle(); } public function renderExtraInformationLink() { if ($this->getMetadataValue('revisionMatchData')) { $details_href = '/differential/revision/closedetails/'.$this->getPHID().'/'; $details_link = javelin_tag( 'a', array( 'href' => $details_href, 'sigil' => 'workflow', ), pht('Explain Why')); return $details_link; } return parent::renderExtraInformationLink(); } public function getTitleForFeed() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $author_link = $this->renderHandleLink($author_phid); $object_link = $this->renderHandleLink($object_phid); switch ($this->getTransactionType()) { case self::TYPE_INLINE: return pht( '%s added inline comments to %s.', $author_link, $object_link); case self::TYPE_UPDATE: return pht( '%s updated the diff for %s.', $author_link, $object_link); case self::TYPE_ACTION: switch ($new) { case DifferentialAction::ACTION_ACCEPT: return pht( '%s accepted %s.', $author_link, $object_link); case DifferentialAction::ACTION_REJECT: return pht( '%s requested changes to %s.', $author_link, $object_link); case DifferentialAction::ACTION_RETHINK: return pht( '%s planned changes to %s.', $author_link, $object_link); case DifferentialAction::ACTION_ABANDON: return pht( '%s abandoned %s.', $author_link, $object_link); case DifferentialAction::ACTION_CLOSE: if (!$this->getMetadataValue('isCommitClose')) { return pht( '%s closed %s.', $author_link, $object_link); } else { $commit_name = $this->renderHandleLink( $this->getMetadataValue('commitPHID')); $committer_phid = $this->getMetadataValue('committerPHID'); $author_phid = $this->getMetadataValue('authorPHID'); if ($this->getHandleIfExists($committer_phid)) { $committer_name = $this->renderHandleLink($committer_phid); } else { $committer_name = $this->getMetadataValue('committerName'); } if ($this->getHandleIfExists($author_phid)) { $author_name = $this->renderHandleLink($author_phid); } else { $author_name = $this->getMetadataValue('authorName'); } // Check if the committer and author are the same. They're the // same if both resolved and are the same user, or if neither // resolved and the text is identical. if ($committer_phid && $author_phid) { $same_author = ($committer_phid == $author_phid); } else if (!$committer_phid && !$author_phid) { $same_author = ($committer_name == $author_name); } else { $same_author = false; } if ($committer_name && !$same_author) { return pht( '%s closed %s by committing %s (authored by %s).', $author_link, $object_link, $commit_name, $author_name); } else { return pht( '%s closed %s by committing %s.', $author_link, $object_link, $commit_name); } } break; case DifferentialAction::ACTION_REQUEST: return pht( '%s requested review of %s.', $author_link, $object_link); case DifferentialAction::ACTION_RECLAIM: return pht( '%s reclaimed %s.', $author_link, $object_link); case DifferentialAction::ACTION_RESIGN: return pht( '%s resigned from %s.', $author_link, $object_link); case DifferentialAction::ACTION_CLAIM: return pht( '%s commandeered %s.', $author_link, $object_link); case DifferentialAction::ACTION_REOPEN: return pht( '%s reopened %s.', $author_link, $object_link); } break; case self::TYPE_STATUS: switch ($this->getNewValue()) { case ArcanistDifferentialRevisionStatus::ACCEPTED: return pht( '%s is now accepted and ready to land.', $object_link); case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: return pht( '%s now requires changes to proceed.', $object_link); case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: return pht( '%s now requires review to proceed.', $object_link); } } return parent::getTitleForFeed(); } public function getIcon() { switch ($this->getTransactionType()) { case self::TYPE_INLINE: return 'fa-comment'; case self::TYPE_UPDATE: return 'fa-refresh'; case self::TYPE_STATUS: switch ($this->getNewValue()) { case ArcanistDifferentialRevisionStatus::ACCEPTED: return 'fa-check'; case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: return 'fa-times'; case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: return 'fa-undo'; } break; case self::TYPE_ACTION: switch ($this->getNewValue()) { case DifferentialAction::ACTION_CLOSE: return 'fa-check'; case DifferentialAction::ACTION_ACCEPT: return 'fa-check-circle-o'; case DifferentialAction::ACTION_REJECT: return 'fa-times-circle-o'; case DifferentialAction::ACTION_ABANDON: return 'fa-plane'; case DifferentialAction::ACTION_RETHINK: return 'fa-headphones'; case DifferentialAction::ACTION_REQUEST: return 'fa-refresh'; case DifferentialAction::ACTION_RECLAIM: case DifferentialAction::ACTION_REOPEN: return 'fa-bullhorn'; case DifferentialAction::ACTION_RESIGN: return 'fa-flag'; case DifferentialAction::ACTION_CLAIM: return 'fa-flag'; } case PhabricatorTransactions::TYPE_EDGE: switch ($this->getMetadataValue('edge:type')) { case DifferentialRevisionHasReviewerEdgeType::EDGECONST: return 'fa-user'; } } return parent::getIcon(); } public function shouldDisplayGroupWith(array $group) { // Never group status changes with other types of actions, they're indirect // and don't make sense when combined with direct actions. $type_status = self::TYPE_STATUS; if ($this->getTransactionType() == $type_status) { return false; } foreach ($group as $xaction) { if ($xaction->getTransactionType() == $type_status) { return false; } } return parent::shouldDisplayGroupWith($group); } public function getColor() { switch ($this->getTransactionType()) { case self::TYPE_UPDATE: return PhabricatorTransactions::COLOR_SKY; case self::TYPE_STATUS: switch ($this->getNewValue()) { case ArcanistDifferentialRevisionStatus::ACCEPTED: return PhabricatorTransactions::COLOR_GREEN; case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: return PhabricatorTransactions::COLOR_RED; case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: return PhabricatorTransactions::COLOR_ORANGE; } break; case self::TYPE_ACTION: switch ($this->getNewValue()) { case DifferentialAction::ACTION_CLOSE: return PhabricatorTransactions::COLOR_INDIGO; case DifferentialAction::ACTION_ACCEPT: return PhabricatorTransactions::COLOR_GREEN; case DifferentialAction::ACTION_REJECT: return PhabricatorTransactions::COLOR_RED; case DifferentialAction::ACTION_ABANDON: return PhabricatorTransactions::COLOR_INDIGO; case DifferentialAction::ACTION_RETHINK: return PhabricatorTransactions::COLOR_RED; case DifferentialAction::ACTION_REQUEST: return PhabricatorTransactions::COLOR_SKY; case DifferentialAction::ACTION_RECLAIM: return PhabricatorTransactions::COLOR_SKY; case DifferentialAction::ACTION_REOPEN: return PhabricatorTransactions::COLOR_SKY; case DifferentialAction::ACTION_RESIGN: return PhabricatorTransactions::COLOR_ORANGE; case DifferentialAction::ACTION_CLAIM: return PhabricatorTransactions::COLOR_YELLOW; } } return parent::getColor(); } public function getNoEffectDescription() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_EDGE: switch ($this->getMetadataValue('edge:type')) { case DifferentialRevisionHasReviewerEdgeType::EDGECONST: return pht( 'The reviewers you are trying to add are already reviewing '. 'this revision.'); } break; case self::TYPE_ACTION: switch ($this->getNewValue()) { case DifferentialAction::ACTION_CLOSE: return pht('This revision is already closed.'); case DifferentialAction::ACTION_ABANDON: return pht('This revision has already been abandoned.'); case DifferentialAction::ACTION_RECLAIM: return pht( 'You can not reclaim this revision because his revision is '. 'not abandoned.'); case DifferentialAction::ACTION_REOPEN: return pht( 'You can not reopen this revision because this revision is '. 'not closed.'); case DifferentialAction::ACTION_RETHINK: return pht('This revision already requires changes.'); case DifferentialAction::ACTION_REQUEST: return pht('Review is already requested for this revision.'); case DifferentialAction::ACTION_RESIGN: return pht( 'You can not resign from this revision because you are not '. 'a reviewer.'); case DifferentialAction::ACTION_CLAIM: return pht( 'You can not commandeer this revision because you already own '. 'it.'); case DifferentialAction::ACTION_ACCEPT: return pht('You have already accepted this revision.'); case DifferentialAction::ACTION_REJECT: return pht('You have already requested changes to this revision.'); } break; } return parent::getNoEffectDescription(); } public function renderAsTextForDoorkeeper( DoorkeeperFeedStoryPublisher $publisher, PhabricatorFeedStory $story, array $xactions) { $body = parent::renderAsTextForDoorkeeper($publisher, $story, $xactions); $inlines = array(); foreach ($xactions as $xaction) { if ($xaction->getTransactionType() == self::TYPE_INLINE) { $inlines[] = $xaction; } } // TODO: This is a bit gross, but far less bad than it used to be. It // could be further cleaned up at some point. if ($inlines) { $engine = PhabricatorMarkupEngine::newMarkupEngine(array()) ->setConfig('viewer', new PhabricatorUser()) ->setMode(PhutilRemarkupEngine::MODE_TEXT); $body .= "\n\n"; $body .= pht('Inline Comments'); $body .= "\n"; $changeset_ids = array(); foreach ($inlines as $inline) { $changeset_ids[] = $inline->getComment()->getChangesetID(); } $changesets = id(new DifferentialChangeset())->loadAllWhere( 'id IN (%Ld)', $changeset_ids); foreach ($inlines as $inline) { $comment = $inline->getComment(); $changeset = idx($changesets, $comment->getChangesetID()); if (!$changeset) { continue; } $filename = $changeset->getDisplayFilename(); $linenumber = $comment->getLineNumber(); $inline_text = $engine->markupText($comment->getContent()); $inline_text = rtrim($inline_text); $body .= "{$filename}:{$linenumber} {$inline_text}\n"; } } return $body; } } diff --git a/src/applications/differential/view/DifferentialReviewersView.php b/src/applications/differential/view/DifferentialReviewersView.php index b94e246d73..fd558d85f1 100644 --- a/src/applications/differential/view/DifferentialReviewersView.php +++ b/src/applications/differential/view/DifferentialReviewersView.php @@ -1,131 +1,131 @@ reviewers = $reviewers; return $this; } public function setHandles(array $handles) { assert_instances_of($handles, 'PhabricatorObjectHandle'); $this->handles = $handles; return $this; } public function setActiveDiff(DifferentialDiff $diff) { $this->diff = $diff; return $this; } public function render() { $viewer = $this->getUser(); $view = new PHUIStatusListView(); foreach ($this->reviewers as $reviewer) { $phid = $reviewer->getReviewerPHID(); $handle = $this->handles[$phid]; // If we're missing either the diff or action information for the // reviewer, render information as current. $is_current = (!$this->diff) || (!$reviewer->getDiffID()) || ($this->diff->getID() == $reviewer->getDiffID()); $item = new PHUIStatusItemView(); $item->setHighlighted($reviewer->hasAuthority($viewer)); switch ($reviewer->getStatus()) { case DifferentialReviewerStatus::STATUS_ADDED: $item->setIcon( PHUIStatusItemView::ICON_OPEN, 'bluegrey', pht('Review Requested')); break; case DifferentialReviewerStatus::STATUS_ACCEPTED: if ($is_current) { $item->setIcon( PHUIStatusItemView::ICON_ACCEPT, 'green', pht('Accepted')); } else { $item->setIcon( PHUIStatusItemView::ICON_ACCEPT, 'bluegrey', pht('Accepted Prior Diff')); } break; case DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER: $item->setIcon( 'fa-check-circle-o', 'bluegrey', pht('Accepted Prior Diff')); break; case DifferentialReviewerStatus::STATUS_REJECTED: if ($is_current) { $item->setIcon( PHUIStatusItemView::ICON_REJECT, 'red', pht('Requested Changes')); } else { $item->setIcon( 'fa-times-circle-o', 'bluegrey', pht('Requested Changes to Prior Diff')); } break; case DifferentialReviewerStatus::STATUS_REJECTED_OLDER: $item->setIcon( 'fa-times-circle-o', 'bluegrey', pht('Rejected Prior Diff')); break; case DifferentialReviewerStatus::STATUS_COMMENTED: if ($is_current) { $item->setIcon( 'fa-question-circle', 'blue', pht('Commented')); } else { $item->setIcon( 'fa-question-circle-o', 'bluegrey', pht('Commented Previously')); } break; case DifferentialReviewerStatus::STATUS_BLOCKING: $item->setIcon( PHUIStatusItemView::ICON_MINUS, 'red', pht('Blocking Review')); break; default: $item->setIcon( PHUIStatusItemView::ICON_QUESTION, 'bluegrey', pht('%s?', $reviewer->getStatus())); break; } $item->setTarget($handle->renderHovercardLink()); $view->addItem($item); } return $view; } } diff --git a/src/applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php b/src/applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php new file mode 100644 index 0000000000..63c7f2c32d --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php @@ -0,0 +1,95 @@ +getRepositoryPHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setRepositoryPHID($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + if ($old && $new) { + return pht( + '%s changed the repository for this revision from %s to %s.', + $this->renderAuthor(), + $this->renderHandle($old), + $this->renderHandle($new)); + } else if ($new) { + return pht( + '%s set the repository for this revision to %s.', + $this->renderAuthor(), + $this->renderHandle($new)); + } else { + return pht( + '%s removed %s as the repository for this revision.', + $this->renderAuthor(), + $this->renderHandle($old)); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + if ($old && $new) { + return pht( + '%s changed the repository for %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderHandle($old), + $this->renderHandle($new)); + } else if ($new) { + return pht( + '%s set the repository for %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderHandle($new)); + } else { + return pht( + '%s removed %s as the repository for %s.', + $this->renderAuthor(), + $this->renderHandle($old), + $this->renderObject()); + } + } + + public function validateTransactions($object, array $xactions) { + $actor = $this->getActor(); + + $errors = array(); + + $old_value = $object->getRepositoryPHID(); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + if (!$new_value) { + continue; + } + + if ($new_value == $old_value) { + continue; + } + + $repository = id(new PhabricatorRepositoryQuery()) + ->setViewer($actor) + ->withPHIDs(array($new_value)) + ->executeOne(); + if (!$repository) { + $errors[] = $this->newInvalidError( + pht( + 'Repository "%s" is not a valid repository, or you do not have '. + 'permission to view it.'), + $xaction); + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionReviewersTransaction.php b/src/applications/differential/xaction/DifferentialRevisionReviewersTransaction.php new file mode 100644 index 0000000000..6ecf738162 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionReviewersTransaction.php @@ -0,0 +1,368 @@ +getReviewerStatus(); + $reviewers = mpull($reviewers, 'getStatus', 'getReviewerPHID'); + return $reviewers; + } + + public function generateNewValue($object, $value) { + $actor = $this->getActor(); + + $datasource = id(new DifferentialBlockingReviewerDatasource()) + ->setViewer($actor); + + $reviewers = $this->generateOldValue($object); + $old_reviewers = $reviewers; + + // First, remove any reviewers we're getting rid of. + $rem = idx($value, '-', array()); + $rem = $datasource->evaluateTokens($rem); + foreach ($rem as $phid) { + unset($reviewers[$phid]); + } + + $add = idx($value, '+', array()); + $add = $datasource->evaluateTokens($add); + $add_map = array(); + foreach ($add as $spec) { + if (!is_array($spec)) { + $phid = $spec; + $status = DifferentialReviewerStatus::STATUS_ADDED; + } else { + $phid = $spec['phid']; + $status = $spec['type']; + } + + $add_map[$phid] = $status; + } + + $set = idx($value, '=', null); + if ($set !== null) { + $set = $datasource->evaluateTokens($set); + foreach ($set as $spec) { + if (!is_array($spec)) { + $phid = $spec; + $status = DifferentialReviewerStatus::STATUS_ADDED; + } else { + $phid = $spec['phid']; + $status = $spec['type']; + } + + $add_map[$phid] = $status; + } + + // We treat setting reviewers as though they were being added to an + // empty list, so we can share more code between pathways. + $reviewers = array(); + } + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + foreach ($add_map as $phid => $new_status) { + $old_status = idx($old_reviewers, $phid); + + // If we have an old status and this didn't make the reviewer blocking + // or nonblocking, just retain the old status. This makes sure we don't + // throw away rejects, accepts, etc. + if ($old_status) { + $was_blocking = ($old_status == $status_blocking); + $now_blocking = ($new_status == $status_blocking); + + $is_block = ($now_blocking && !$was_blocking); + $is_unblock = (!$now_blocking && $was_blocking); + + if (!$is_block && !$is_unblock) { + $reviewers[$phid] = $old_status; + continue; + } + } + + $reviewers[$phid] = $new_status; + } + + return $reviewers; + } + + public function getTransactionHasEffect($object, $old, $new) { + // At least for now, we ignore transactions which ONLY reorder reviewers + // without making any actual changes. + ksort($old); + ksort($new); + return ($old !== $new); + } + + public function applyExternalEffects($object, $value) { + $src_phid = $object->getPHID(); + + $old = $this->generateOldValue($object); + $new = $value; + $edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST; + + $editor = new PhabricatorEdgeEditor(); + + $rem = array_diff_key($old, $new); + foreach ($rem as $dst_phid => $status) { + $editor->removeEdge($src_phid, $edge_type, $dst_phid); + } + + foreach ($new as $dst_phid => $status) { + $old_status = idx($old, $dst_phid); + if ($old_status === $status) { + continue; + } + + $data = array( + 'data' => array( + 'status' => $status, + + // TODO: This seemes like it's buggy before the Modular Transactions + // changes. Figure out what's going on here? We don't have a very + // clean way to get the active diff ID right now. + 'diffID' => null, + ), + ); + + $editor->addEdge($src_phid, $edge_type, $dst_phid, $data); + } + + $editor->save(); + } + + public function getTitle() { + return $this->renderReviewerEditTitle(false); + } + + public function getTitleForFeed() { + return $this->renderReviewerEditTitle(true); + } + + private function renderReviewerEditTitle($is_feed) { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + $rem = array_diff_key($old, $new); + $add = array_diff_key($new, $old); + $rem_phids = array_keys($rem); + $add_phids = array_keys($add); + $total_count = count($rem) + count($add); + + $parts = array(); + + if ($rem && $add) { + if ($is_feed) { + $parts[] = pht( + '%s edited %s reviewer(s) for %s, added %s: %s; removed %s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + $this->renderObject(), + phutil_count($add_phids), + $this->renderHandleList($add_phids), + phutil_count($rem_phids), + $this->renderHandleList($rem_phids)); + } else { + $parts[] = pht( + '%s edited %s reviewer(s), added %s: %s; removed %s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + phutil_count($add_phids), + $this->renderHandleList($add_phids), + phutil_count($rem_phids), + $this->renderHandleList($rem_phids)); + } + } else if ($add) { + if ($is_feed) { + $parts[] = pht( + '%s added %s reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($add_phids), + $this->renderObject(), + $this->renderHandleList($add_phids)); + } else { + $parts[] = pht( + '%s added %s reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($add_phids), + $this->renderHandleList($add_phids)); + } + } else if ($rem) { + if ($is_feed) { + $parts[] = pht( + '%s removed %s reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($rem_phids), + $this->renderObject(), + $this->renderHandleList($rem_phids)); + } else { + $parts[] = pht( + '%s removed %s reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($rem_phids), + $this->renderHandleList($rem_phids)); + } + } + + $status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING; + $blocks = array(); + $unblocks = array(); + foreach ($new as $phid => $new_status) { + $old_status = idx($old, $phid); + if (!$old_status) { + continue; + } + + $was_blocking = ($old_status == $status_blocking); + $now_blocking = ($new_status == $status_blocking); + + $is_block = ($now_blocking && !$was_blocking); + $is_unblock = (!$now_blocking && $was_blocking); + + if ($is_block) { + $blocks[] = $phid; + } + if ($is_unblock) { + $unblocks[] = $phid; + } + } + + $total_count = count($blocks) + count($unblocks); + + if ($blocks && $unblocks) { + if ($is_feed) { + $parts[] = pht( + '%s changed %s blocking reviewer(s) for %s, added %s: %s; removed '. + '%s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + $this->renderObject(), + phutil_count($blocks), + $this->renderHandleList($blocks), + phutil_count($unblocks), + $this->renderHandleList($unblocks)); + } else { + $parts[] = pht( + '%s changed %s blocking reviewer(s), added %s: %s; removed %s: %s.', + $this->renderAuthor(), + new PhutilNumber($total_count), + phutil_count($blocks), + $this->renderHandleList($blocks), + phutil_count($unblocks), + $this->renderHandleList($unblocks)); + } + } else if ($blocks) { + if ($is_feed) { + $parts[] = pht( + '%s added %s blocking reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($blocks), + $this->renderObject(), + $this->renderHandleList($blocks)); + } else { + $parts[] = pht( + '%s added %s blocking reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($blocks), + $this->renderHandleList($blocks)); + } + } else if ($unblocks) { + if ($is_feed) { + $parts[] = pht( + '%s removed %s blocking reviewer(s) for %s: %s.', + $this->renderAuthor(), + phutil_count($unblocks), + $this->renderObject(), + $this->renderHandleList($unblocks)); + } else { + $parts[] = pht( + '%s removed %s blocking reviewer(s): %s.', + $this->renderAuthor(), + phutil_count($unblocks), + $this->renderHandleList($unblocks)); + } + } + + if ($this->isTextMode()) { + return implode(' ', $parts); + } else { + return phutil_implode_html(' ', $parts); + } + } + + public function validateTransactions($object, array $xactions) { + $actor = $this->getActor(); + $errors = array(); + + if (!$xactions) { + // If we aren't applying new reviewer transactions, just bail. We need + // reviewers to be attached to the revision continue validation, and + // they won't always be (for example, when mentioning a revision). + return $errors; + } + + $author_phid = $object->getAuthorPHID(); + $config_self_accept_key = 'differential.allow-self-accept'; + $allow_self_accept = PhabricatorEnv::getEnvConfig($config_self_accept_key); + + $old = $this->generateOldValue($object); + foreach ($xactions as $xaction) { + $new = $this->generateNewValue($object, $xaction->getNewValue()); + + $add = array_diff_key($new, $old); + if (!$add) { + continue; + } + + $objects = id(new PhabricatorObjectQuery()) + ->setViewer($actor) + ->withPHIDs(array_keys($add)) + ->execute(); + $objects = mpull($objects, null, 'getPHID'); + + foreach ($add as $phid => $status) { + if (!isset($objects[$phid])) { + $errors[] = $this->newInvalidError( + pht( + 'Reviewer "%s" is not a valid object.', + $phid), + $xaction); + continue; + } + + switch (phid_get_type($phid)) { + case PhabricatorPeopleUserPHIDType::TYPECONST: + case PhabricatorOwnersPackagePHIDType::TYPECONST: + case PhabricatorProjectProjectPHIDType::TYPECONST: + break; + default: + $errors[] = $this->newInvalidError( + pht( + 'Reviewer "%s" must be a user, a package, or a project.', + $phid), + $xaction); + continue 2; + } + + // NOTE: This weird behavior around commandeering is a bit unorthodox, + // but this restriction is an unusual one. + + $is_self = ($phid === $author_phid); + if ($is_self && !$allow_self_accept) { + if (!$xaction->getIsCommandeerSideEffect()) { + $errors[] = $this->newInvalidError( + pht('The author of a revision can not be a reviewer.'), + $xaction); + continue; + } + } + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php new file mode 100644 index 0000000000..a4f1dcafa5 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionSummaryTransaction.php @@ -0,0 +1,57 @@ +getSummary(); + } + + public function applyInternalEffects($object, $value) { + $object->setSummary($value); + } + + public function getTitle() { + return pht( + '%s edited the summary of this revision.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the summary of %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO REVISION SUMMARY'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php new file mode 100644 index 0000000000..bf2beab3d8 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php @@ -0,0 +1,75 @@ +getTestPlan(); + } + + public function applyInternalEffects($object, $value) { + $object->setTestPlan($value); + } + + public function getTitle() { + return pht( + '%s edited the test plan for this revision.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the test plan for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO TEST PLAN'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $is_required = PhabricatorEnv::getEnvConfig( + 'differential.require-test-plan-field'); + + if ($is_required) { + if ($this->isEmptyTextTransaction($object->getTestPlan(), $xactions)) { + $errors[] = $this->newRequiredError( + pht( + 'You must provide a test plan. Describe the actions you '. + 'performed to verify the behavior of this change.')); + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php new file mode 100644 index 0000000000..9b763c53ca --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionTitleTransaction.php @@ -0,0 +1,58 @@ +getTitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setTitle($value); + } + + public function getTitle() { + return pht( + '%s retitled this revision from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s retitled %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Revisions must have a title.')); + } + + $max_length = $object->getColumnMaximumByteLength('title'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht( + 'Revision title is too long: the maximum length of a '. + 'revision title is 255 bytes.'), + $xaction); + } + } + + return $errors; + } + +} diff --git a/src/applications/differential/xaction/DifferentialRevisionTransactionType.php b/src/applications/differential/xaction/DifferentialRevisionTransactionType.php new file mode 100644 index 0000000000..f740d97c74 --- /dev/null +++ b/src/applications/differential/xaction/DifferentialRevisionTransactionType.php @@ -0,0 +1,4 @@ +loadDiffusionContext(); if ($response) { return $response; } // NOTE: This controller is just here to make sure we call // willBeginExecution() on any /diffusion/X/ URI, so we can intercept // `git`, `hg` and `svn` HTTP protocol requests. // If we made it here, it's probably because the user copy-pasted a // clone URI with "/anything.git" at the end into their web browser. // Send them to the canonical repository URI. $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); return id(new AphrontRedirectResponse()) ->setURI($repository->getURI()); } } diff --git a/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php b/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php index 1c42fb027b..4c84d430cf 100644 --- a/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php +++ b/src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php @@ -1,278 +1,278 @@ getUser()->getIsMailingList()) { return false; } return true; } public function getPanelKey() { return 'vcspassword'; } public function getPanelName() { return pht('VCS Password'); } public function getPanelGroupKey() { return PhabricatorSettingsAuthenticationPanelGroup::PANELGROUPKEY; } public function isEnabled() { return PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth'); } public function processRequest(AphrontRequest $request) { $viewer = $request->getUser(); $user = $this->getUser(); $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession( $viewer, $request, '/settings/'); $vcspassword = id(new PhabricatorRepositoryVCSPassword()) ->loadOneWhere( 'userPHID = %s', $user->getPHID()); if (!$vcspassword) { $vcspassword = id(new PhabricatorRepositoryVCSPassword()); $vcspassword->setUserPHID($user->getPHID()); } $panel_uri = $this->getPanelURI('?saved=true'); $errors = array(); $e_password = true; $e_confirm = true; if ($request->isFormPost()) { if ($request->getBool('remove')) { if ($vcspassword->getID()) { $vcspassword->delete(); return id(new AphrontRedirectResponse())->setURI($panel_uri); } } $new_password = $request->getStr('password'); $confirm = $request->getStr('confirm'); if (!strlen($new_password)) { $e_password = pht('Required'); $errors[] = pht('Password is required.'); } else { $e_password = null; } if (!strlen($confirm)) { $e_confirm = pht('Required'); $errors[] = pht('You must confirm the new password.'); } else { $e_confirm = null; } if (!$errors) { $envelope = new PhutilOpaqueEnvelope($new_password); try { // NOTE: This test is against $viewer (not $user), so that the error // message below makes sense in the case that the two are different, // and because an admin reusing their own password is bad, while // system agents generally do not have passwords anyway. $same_password = $viewer->comparePassword($envelope); } catch (PhabricatorPasswordHasherUnavailableException $ex) { // If we're missing the hasher, just let the user continue. $same_password = false; } if ($new_password !== $confirm) { $e_password = pht('Does Not Match'); $e_confirm = pht('Does Not Match'); $errors[] = pht('Password and confirmation do not match.'); } else if ($same_password) { $e_password = pht('Not Unique'); $e_confirm = pht('Not Unique'); $errors[] = pht( 'This password is the same as another password associated '. 'with your account. You must use a unique password for '. 'VCS access.'); } else if ( PhabricatorCommonPasswords::isCommonPassword($new_password)) { $e_password = pht('Very Weak'); $e_confirm = pht('Very Weak'); $errors[] = pht( 'This password is extremely weak: it is one of the most common '. 'passwords in use. Choose a stronger password.'); } if (!$errors) { $vcspassword->setPassword($envelope, $user); $vcspassword->save(); return id(new AphrontRedirectResponse())->setURI($panel_uri); } } } $title = pht('Set VCS Password'); $form = id(new AphrontFormView()) ->setUser($viewer) ->appendRemarkupInstructions( pht( 'To access repositories hosted by Phabricator over HTTP, you must '. 'set a version control password. This password should be unique.'. "\n\n". "This password applies to all repositories available over ". "HTTP.")); if ($vcspassword->getID()) { $form ->appendChild( id(new AphrontFormPasswordControl()) ->setDisableAutocomplete(true) ->setLabel(pht('Current Password')) ->setDisabled(true) ->setValue('********************')); } else { $form ->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Current Password')) ->setValue(phutil_tag('em', array(), pht('No Password Set')))); } $form ->appendChild( id(new AphrontFormPasswordControl()) ->setDisableAutocomplete(true) ->setName('password') ->setLabel(pht('New VCS Password')) ->setError($e_password)) ->appendChild( id(new AphrontFormPasswordControl()) ->setDisableAutocomplete(true) ->setName('confirm') ->setLabel(pht('Confirm VCS Password')) ->setError($e_confirm)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Change Password'))); if (!$vcspassword->getID()) { $is_serious = PhabricatorEnv::getEnvConfig( 'phabricator.serious-business'); $suggest = Filesystem::readRandomBytes(128); $suggest = preg_replace('([^A-Za-z0-9/!().,;{}^&*%~])', '', $suggest); $suggest = substr($suggest, 0, 20); if ($is_serious) { $form->appendRemarkupInstructions( pht( 'Having trouble coming up with a good password? Try this randomly '. 'generated one, made by a computer:'. "\n\n". "`%s`", $suggest)); } else { $form->appendRemarkupInstructions( pht( 'Having trouble coming up with a good password? Try this '. - 'artisinal password, hand made in small batches by our expert '. + 'artisanal password, hand made in small batches by our expert '. 'craftspeople: '. "\n\n". "`%s`", $suggest)); } } $hash_envelope = new PhutilOpaqueEnvelope($vcspassword->getPasswordHash()); $form->appendChild( id(new AphrontFormStaticControl()) ->setLabel(pht('Current Algorithm')) ->setValue( PhabricatorPasswordHasher::getCurrentAlgorithmName($hash_envelope))); $form->appendChild( id(new AphrontFormStaticControl()) ->setLabel(pht('Best Available Algorithm')) ->setValue(PhabricatorPasswordHasher::getBestAlgorithmName())); if (strlen($hash_envelope->openEnvelope())) { try { $can_upgrade = PhabricatorPasswordHasher::canUpgradeHash( $hash_envelope); } catch (PhabricatorPasswordHasherUnavailableException $ex) { $can_upgrade = false; $errors[] = pht( 'Your VCS password is currently hashed using an algorithm which is '. 'no longer available on this install.'); $errors[] = pht( 'Because the algorithm implementation is missing, your password '. 'can not be used.'); $errors[] = pht( 'You can set a new password to replace the old password.'); } if ($can_upgrade) { $errors[] = pht( 'The strength of your stored VCS password hash can be upgraded. '. 'To upgrade, either: use the password to authenticate with a '. 'repository; or change your password.'); } } $object_box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setForm($form) ->setFormErrors($errors); $remove_form = id(new AphrontFormView()) ->setUser($viewer); if ($vcspassword->getID()) { $remove_form ->addHiddenInput('remove', true) ->appendRemarkupInstructions( pht( 'You can remove your VCS password, which will prevent your '. 'account from accessing repositories.')) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Remove Password'))); } else { $remove_form->appendRemarkupInstructions( pht( 'You do not currently have a VCS password set. If you set one, you '. 'can remove it here later.')); } $remove_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Remove VCS Password')) ->setForm($remove_form); $saved = null; if ($request->getBool('saved')) { $saved = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setTitle(pht('Password Updated')) ->appendChild(pht('Your VCS password has been updated.')); } return array( $saved, $object_box, $remove_box, ); } } diff --git a/src/applications/diviner/controller/DivinerBookEditController.php b/src/applications/diviner/controller/DivinerBookEditController.php index 758cc190bb..b783e96746 100644 --- a/src/applications/diviner/controller/DivinerBookEditController.php +++ b/src/applications/diviner/controller/DivinerBookEditController.php @@ -1,136 +1,134 @@ getViewer(); $book_name = $request->getURIData('book'); $book = id(new DivinerBookQuery()) ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->needProjectPHIDs(true) ->withNames(array($book_name)) ->executeOne(); if (!$book) { return new Aphront404Response(); } $view_uri = '/book/'.$book->getName().'/'; if ($request->isFormPost()) { $v_projects = $request->getArr('projectPHIDs'); $v_view = $request->getStr('viewPolicy'); $v_edit = $request->getStr('editPolicy'); $xactions = array(); $xactions[] = id(new DivinerLiveBookTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue( 'edge:type', PhabricatorProjectObjectHasProjectEdgeType::EDGECONST) ->setNewValue( array( '=' => array_fuse($v_projects), )); $xactions[] = id(new DivinerLiveBookTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) ->setNewValue($v_view); $xactions[] = id(new DivinerLiveBookTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) ->setNewValue($v_edit); id(new DivinerLiveBookEditor()) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->setActor($viewer) ->applyTransactions($book, $xactions); return id(new AphrontRedirectResponse())->setURI($view_uri); } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Edit Basics')); $crumbs->setBorder(true); $title = pht('Edit Book: %s', $book->getTitle()); $header_icon = 'fa-pencil'; $policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) ->setObject($book) ->execute(); $view_capability = PhabricatorPolicyCapability::CAN_VIEW; $edit_capability = PhabricatorPolicyCapability::CAN_EDIT; $form = id(new AphrontFormView()) ->setUser($viewer) ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorProjectDatasource()) ->setName('projectPHIDs') ->setLabel(pht('Tags')) ->setValue($book->getProjectPHIDs())) ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new DiffusionRepositoryDatasource()) ->setName('repositoryPHIDs') ->setLabel(pht('Repository')) ->setDisableBehavior(true) ->setLimit(1) ->setValue($book->getRepositoryPHID() ? array($book->getRepositoryPHID()) : null)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') ->setPolicyObject($book) ->setCapability($view_capability) - ->setPolicies($policies) - ->setCaption($book->describeAutomaticCapability($view_capability))) + ->setPolicies($policies)) ->appendChild( id(new AphrontFormPolicyControl()) ->setName('editPolicy') ->setPolicyObject($book) ->setCapability($edit_capability) - ->setPolicies($policies) - ->setCaption($book->describeAutomaticCapability($edit_capability))) + ->setPolicies($policies)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Save')) ->addCancelButton($view_uri)); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Book')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $timeline = $this->buildTransactionTimeline( $book, new DivinerLiveBookTransactionQuery()); $timeline->setShouldTerminate(true); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon($header_icon); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $box, $timeline, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } } diff --git a/src/applications/meta/query/PhabricatorAppSearchEngine.php b/src/applications/meta/query/PhabricatorAppSearchEngine.php index 62e1c1020e..b609a8b137 100644 --- a/src/applications/meta/query/PhabricatorAppSearchEngine.php +++ b/src/applications/meta/query/PhabricatorAppSearchEngine.php @@ -1,261 +1,261 @@ setParameter('name', $request->getStr('name')); $saved->setParameter( 'installed', $this->readBoolFromRequest($request, 'installed')); $saved->setParameter( 'prototypes', $this->readBoolFromRequest($request, 'prototypes')); $saved->setParameter( 'firstParty', $this->readBoolFromRequest($request, 'firstParty')); $saved->setParameter( 'launchable', $this->readBoolFromRequest($request, 'launchable')); $saved->setParameter( 'appemails', $this->readBoolFromRequest($request, 'appemails')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new PhabricatorApplicationQuery()) ->setOrder(PhabricatorApplicationQuery::ORDER_NAME) ->withUnlisted(false); $name = $saved->getParameter('name'); if (strlen($name)) { $query->withNameContains($name); } $installed = $saved->getParameter('installed'); if ($installed !== null) { $query->withInstalled($installed); } $prototypes = $saved->getParameter('prototypes'); if ($prototypes === null) { // NOTE: This is the old name of the 'prototypes' option, see T6084. $prototypes = $saved->getParameter('beta'); $saved->setParameter('prototypes', $prototypes); } if ($prototypes !== null) { $query->withPrototypes($prototypes); } $first_party = $saved->getParameter('firstParty'); if ($first_party !== null) { $query->withFirstParty($first_party); } $launchable = $saved->getParameter('launchable'); if ($launchable !== null) { $query->withLaunchable($launchable); } $appemails = $saved->getParameter('appemails'); if ($appemails !== null) { $query->withApplicationEmailSupport($appemails); } return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved) { $form ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Name Contains')) ->setName('name') ->setValue($saved->getParameter('name'))) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Installed')) ->setName('installed') ->setValue($this->getBoolFromQuery($saved, 'installed')) ->setOptions( array( '' => pht('Show All Applications'), 'true' => pht('Show Installed Applications'), 'false' => pht('Show Uninstalled Applications'), ))) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Prototypes')) ->setName('prototypes') ->setValue($this->getBoolFromQuery($saved, 'prototypes')) ->setOptions( array( '' => pht('Show All Applications'), 'true' => pht('Show Prototype Applications'), 'false' => pht('Show Released Applications'), ))) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Provenance')) ->setName('firstParty') ->setValue($this->getBoolFromQuery($saved, 'firstParty')) ->setOptions( array( '' => pht('Show All Applications'), 'true' => pht('Show First-Party Applications'), 'false' => pht('Show Third-Party Applications'), ))) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Launchable')) ->setName('launchable') ->setValue($this->getBoolFromQuery($saved, 'launchable')) ->setOptions( array( '' => pht('Show All Applications'), 'true' => pht('Show Launchable Applications'), 'false' => pht('Show Non-Launchable Applications'), ))) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel(pht('Application Emails')) ->setName('appemails') ->setValue($this->getBoolFromQuery($saved, 'appemails')) ->setOptions( array( '' => pht('Show All Applications'), 'true' => pht('Show Applications w/ App Email Support'), 'false' => pht('Show Applications w/o App Email Support'), ))); } protected function getURI($path) { return '/applications/'.$path; } protected function getBuiltinQueryNames() { return array( 'launcher' => pht('Launcher'), 'all' => pht('All Applications'), ); } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'launcher': return $query ->setParameter('installed', true) ->setParameter('launchable', true); case 'all': return $query; } return parent::buildSavedQueryFromBuiltin($query_key); } protected function renderResultList( array $all_applications, PhabricatorSavedQuery $query, array $handle) { assert_instances_of($all_applications, 'PhabricatorApplication'); $all_applications = msort($all_applications, 'getName'); if ($query->getQueryKey() == 'launcher') { $groups = mgroup($all_applications, 'getApplicationGroup'); } else { $groups = array($all_applications); } $group_names = PhabricatorApplication::getApplicationGroups(); $groups = array_select_keys($groups, array_keys($group_names)) + $groups; $results = array(); foreach ($groups as $group => $applications) { if (count($groups) > 1) { $results[] = phutil_tag( 'h1', array( - 'class' => 'phui-object-item-list-header', + 'class' => 'phui-oi-list-header', ), idx($group_names, $group, $group)); } $list = new PHUIObjectItemListView(); foreach ($applications as $application) { $icon = $application->getIcon(); if (!$icon) { $icon = 'application'; } $description = $application->getShortDescription(); $configure = id(new PHUIButtonView()) ->setTag('a') ->setHref('/applications/view/'.get_class($application).'/') ->setText(pht('Configure')) ->setColor(PHUIButtonView::GREY); $name = $application->getName(); if ($application->isPrototype()) { $name = $name.' '.pht('(Prototype)'); } $item = id(new PHUIObjectItemView()) ->setHeader($name) ->setImageIcon($icon) ->setSubhead($description) ->setLaunchButton($configure); if ($application->getBaseURI() && $application->isInstalled()) { $item->setHref($application->getBaseURI()); } if (!$application->isInstalled()) { $item->addAttribute(pht('Uninstalled')); $item->setDisabled(true); } if (!$application->isFirstParty()) { $item->addAttribute(pht('Extension')); } $list->addItem($item); } $results[] = $list; } $result = new PhabricatorApplicationSearchResultView(); $result->setContent($results); return $result; } } diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index 44672edd3c..a4666c5a21 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -1,139 +1,139 @@ getIsAdmin(); } public function getFlavorText() { return pht('Sort of a social utility.'); } public function getApplicationGroup() { return self::GROUP_UTILITIES; } public function canUninstall() { return false; } public function getRoutes() { return array( '/people/' => array( '(query/(?P[^/]+)/)?' => 'PhabricatorPeopleListController', 'logs/(?:query/(?P[^/]+)/)?' => 'PhabricatorPeopleLogsController', 'invite/' => array( '(?:query/(?P[^/]+)/)?' => 'PhabricatorPeopleInviteListController', 'send/' => 'PhabricatorPeopleInviteSendController', ), 'approve/(?P[1-9]\d*)/' => 'PhabricatorPeopleApproveController', '(?Pdisapprove)/(?P[1-9]\d*)/' => 'PhabricatorPeopleDisableController', '(?Pdisable)/(?P[1-9]\d*)/' => 'PhabricatorPeopleDisableController', 'empower/(?P[1-9]\d*)/' => 'PhabricatorPeopleEmpowerController', 'delete/(?P[1-9]\d*)/' => 'PhabricatorPeopleDeleteController', 'rename/(?P[1-9]\d*)/' => 'PhabricatorPeopleRenameController', 'welcome/(?P[1-9]\d*)/' => 'PhabricatorPeopleWelcomeController', 'create/' => 'PhabricatorPeopleCreateController', 'new/(?P[^/]+)/' => 'PhabricatorPeopleNewController', 'ldap/' => 'PhabricatorPeopleLdapController', 'editprofile/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileEditController', 'picture/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfilePictureController', 'manage/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileManageController', ), '/p/(?P[\w._-]+)/' => array( '' => 'PhabricatorPeopleProfileViewController', - 'panel/' - => $this->getPanelRouting('PhabricatorPeopleProfilePanelController'), + 'item/' => $this->getProfileMenuRouting( + 'PhabricatorPeopleProfileMenuController'), ), ); } public function getRemarkupRules() { return array( new PhabricatorMentionRemarkupRule(), ); } protected function getCustomCapabilities() { return array( PeopleCreateUsersCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, ), PeopleBrowseUserDirectoryCapability::CAPABILITY => array(), ); } public function loadStatus(PhabricatorUser $user) { if (!$user->getIsAdmin()) { return array(); } $limit = self::MAX_STATUS_ITEMS; $need_approval = id(new PhabricatorPeopleQuery()) ->setViewer($user) ->withIsApproved(false) ->withIsDisabled(false) ->setLimit($limit) ->execute(); if (!$need_approval) { return array(); } $status = array(); $count = count($need_approval); if ($count >= $limit) { $count_str = pht( '%s+ User(s) Need Approval', new PhutilNumber($limit - 1)); } else { $count_str = pht( '%s User(s) Need Approval', new PhutilNumber($count)); } $type = PhabricatorApplicationStatusView::TYPE_NEEDS_ATTENTION; $status[] = id(new PhabricatorApplicationStatusView()) ->setType($type) ->setText($count_str) ->setCount($count); return $status; } public function getApplicationSearchDocumentTypes() { return array( PhabricatorPeopleUserPHIDType::TYPECONST, ); } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index 74705f9809..1e0a9cbe18 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -1,63 +1,63 @@ user = $user; return $this; } public function getUser() { return $this->user; } public function buildApplicationMenu() { $menu = $this->newApplicationMenu(); $profile_menu = $this->getProfileMenu(); if ($profile_menu) { $menu->setProfileMenu($profile_menu); } return $menu; } protected function getProfileMenu() { if (!$this->profileMenu) { $user = $this->getUser(); if ($user) { $viewer = $this->getViewer(); - $engine = id(new PhabricatorPeopleProfilePanelEngine()) + $engine = id(new PhabricatorPeopleProfileMenuEngine()) ->setViewer($viewer) ->setProfileObject($user); $this->profileMenu = $engine->buildNavigation(); } } return $this->profileMenu; } protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); $user = $this->getUser(); if ($user) { $crumbs->addTextCrumb( $user->getUsername(), urisprintf('/p/%s/', $user->getUsername())); } return $crumbs; } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileEditController.php b/src/applications/people/controller/PhabricatorPeopleProfileEditController.php index 9f132a18d8..3eda8a968b 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileEditController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileEditController.php @@ -1,107 +1,107 @@ getViewer(); $id = $request->getURIData('id'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needProfileImage(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$user) { return new Aphront404Response(); } $this->setUser($user); $done_uri = $this->getApplicationURI("manage/{$id}/"); $field_list = PhabricatorCustomField::getObjectFields( $user, PhabricatorCustomField::ROLE_EDIT); $field_list ->setViewer($viewer) ->readFieldsFromStorage($user); $validation_exception = null; if ($request->isFormPost()) { $xactions = $field_list->buildFieldTransactionsFromRequest( new PhabricatorUserTransaction(), $request); $editor = id(new PhabricatorUserProfileEditor()) ->setActor($viewer) ->setContentSource( PhabricatorContentSource::newFromRequest($request)) ->setContinueOnNoEffect(true); try { $editor->applyTransactions($user, $xactions); return id(new AphrontRedirectResponse())->setURI($done_uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; } } $title = pht('Edit Profile'); $form = id(new AphrontFormView()) ->setUser($viewer); $field_list->appendFieldsToForm($form); $form ->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($done_uri) ->setValue(pht('Save Profile'))); $allow_public = PhabricatorEnv::getEnvConfig('policy.allow-public'); $note = null; if ($allow_public) { $note = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->appendChild(pht( 'Information on user profiles on this install is publicly '. 'visible.')); } $form_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Profile')) ->setValidationException($validation_exception) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Edit Profile')); $crumbs->setBorder(true); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $header = id(new PHUIHeaderView()) ->setHeader(pht('Edit Profile: %s', $user->getFullName())) ->setHeaderIcon('fa-pencil'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $note, $form_box, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setNavigation($nav) ->appendChild($view); } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php index d298660bd3..c5a3ceabd4 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php @@ -1,195 +1,195 @@ getViewer(); $id = $request->getURIData('id'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needProfile(true) ->needProfileImage(true) ->needAvailability(true) ->executeOne(); if (!$user) { return new Aphront404Response(); } $this->setUser($user); $profile = $user->loadUserProfile(); $picture = $user->getProfileImageURI(); $profile_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon()); $profile_icon = id(new PHUIIconView()) ->setIcon($profile_icon); $profile_title = $profile->getDisplayTitle(); $header = id(new PHUIHeaderView()) ->setHeader($user->getFullName()) ->setSubheader(array($profile_icon, $profile_title)) ->setImage($picture) ->setProfileHeader(true); $curtain = $this->buildCurtain($user); $properties = $this->buildPropertyView($user); $name = $user->getUsername(); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $timeline = $this->buildTransactionTimeline( $user, new PhabricatorPeopleTransactionQuery()); $timeline->setShouldTerminate(true); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Manage')); $crumbs->setBorder(true); $manage = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->addPropertySection(pht('Details'), $properties) ->setMainColumn( array( $timeline, )); return $this->newPage() ->setTitle( array( pht('Manage User'), $user->getUsername(), )) ->setNavigation($nav) ->setCrumbs($crumbs) ->appendChild( array( $manage, )); } private function buildPropertyView(PhabricatorUser $user) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($user); $field_list = PhabricatorCustomField::getObjectFields( $user, PhabricatorCustomField::ROLE_VIEW); $field_list->appendFieldsToPropertyList($user, $viewer, $view); return $view; } private function buildCurtain(PhabricatorUser $user) { $viewer = $this->getViewer(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $user, PhabricatorPolicyCapability::CAN_EDIT); $curtain = $this->newCurtainView($user); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Profile')) ->setHref($this->getApplicationURI('editprofile/'.$user->getID().'/')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-picture-o') ->setName(pht('Edit Profile Picture')) ->setHref($this->getApplicationURI('picture/'.$user->getID().'/')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-wrench') ->setName(pht('Edit Settings')) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref('/settings/user/'.$user->getUsername().'/')); if ($user->getIsAdmin()) { $empower_icon = 'fa-arrow-circle-o-down'; $empower_name = pht('Remove Administrator'); } else { $empower_icon = 'fa-arrow-circle-o-up'; $empower_name = pht('Make Administrator'); } $is_admin = $viewer->getIsAdmin(); $is_self = ($user->getPHID() === $viewer->getPHID()); $can_admin = ($is_admin && !$is_self); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon($empower_icon) ->setName($empower_name) ->setDisabled(!$can_admin) ->setWorkflow(true) ->setHref($this->getApplicationURI('empower/'.$user->getID().'/'))); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-tag') ->setName(pht('Change Username')) ->setDisabled(!$is_admin) ->setWorkflow(true) ->setHref($this->getApplicationURI('rename/'.$user->getID().'/'))); if ($user->getIsDisabled()) { $disable_icon = 'fa-check-circle-o'; $disable_name = pht('Enable User'); } else { $disable_icon = 'fa-ban'; $disable_name = pht('Disable User'); } $curtain->addAction( id(new PhabricatorActionView()) ->setIcon($disable_icon) ->setName($disable_name) ->setDisabled(!$can_admin) ->setWorkflow(true) ->setHref($this->getApplicationURI('disable/'.$user->getID().'/'))); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-times') ->setName(pht('Delete User')) ->setDisabled(!$can_admin) ->setWorkflow(true) ->setHref($this->getApplicationURI('delete/'.$user->getID().'/'))); $can_welcome = ($is_admin && $user->canEstablishWebSessions()); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-envelope') ->setName(pht('Send Welcome Email')) ->setWorkflow(true) ->setDisabled(!$can_welcome) ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/'))); return $curtain; } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php index 29b2290153..226646bc70 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfilePictureController.php @@ -1,278 +1,278 @@ getViewer(); $id = $request->getURIData('id'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needProfileImage(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$user) { return new Aphront404Response(); } $this->setUser($user); $name = $user->getUserName(); $done_uri = '/p/'.$name.'/'; $supported_formats = PhabricatorFile::getTransformableImageFormats(); $e_file = true; $errors = array(); if ($request->isFormPost()) { $phid = $request->getStr('phid'); $is_default = false; if ($phid == PhabricatorPHIDConstants::PHID_VOID) { $phid = null; $is_default = true; } else if ($phid) { $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); } else { if ($request->getFileExists('picture')) { $file = PhabricatorFile::newFromPHPUpload( $_FILES['picture'], array( 'authorPHID' => $viewer->getPHID(), 'canCDN' => true, )); } else { $e_file = pht('Required'); $errors[] = pht( 'You must choose a file when uploading a new profile picture.'); } } if (!$errors && !$is_default) { if (!$file->isTransformableImage()) { $e_file = pht('Not Supported'); $errors[] = pht( 'This server only supports these image formats: %s.', implode(', ', $supported_formats)); } else { $xform = PhabricatorFileTransform::getTransformByKey( PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE); $xformed = $xform->executeTransform($file); } } if (!$errors) { if ($is_default) { $user->setProfileImagePHID(null); } else { $user->setProfileImagePHID($xformed->getPHID()); $xformed->attachToObject($user->getPHID()); } $user->save(); return id(new AphrontRedirectResponse())->setURI($done_uri); } } $title = pht('Edit Profile Picture'); $form = id(new PHUIFormLayoutView()) ->setUser($viewer); $default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png'); $images = array(); $current = $user->getProfileImagePHID(); $has_current = false; if ($current) { $files = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($current)) ->execute(); if ($files) { $file = head($files); if ($file->isTransformableImage()) { $has_current = true; $images[$current] = array( 'uri' => $file->getBestURI(), 'tip' => pht('Current Picture'), ); } } } $builtins = array( 'user1.png', 'user2.png', 'user3.png', 'user4.png', 'user5.png', 'user6.png', 'user7.png', 'user8.png', 'user9.png', ); foreach ($builtins as $builtin) { $file = PhabricatorFile::loadBuiltin($viewer, $builtin); $images[$file->getPHID()] = array( 'uri' => $file->getBestURI(), 'tip' => pht('Builtin Image'), ); } // Try to add external account images for any associated external accounts. $accounts = id(new PhabricatorExternalAccountQuery()) ->setViewer($viewer) ->withUserPHIDs(array($user->getPHID())) ->needImages(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->execute(); foreach ($accounts as $account) { $file = $account->getProfileImageFile(); if ($account->getProfileImagePHID() != $file->getPHID()) { // This is a default image, just skip it. continue; } $provider = PhabricatorAuthProvider::getEnabledProviderByKey( $account->getProviderKey()); if ($provider) { $tip = pht('Picture From %s', $provider->getProviderName()); } else { $tip = pht('Picture From External Account'); } if ($file->isTransformableImage()) { $images[$file->getPHID()] = array( 'uri' => $file->getBestURI(), 'tip' => $tip, ); } } $images[PhabricatorPHIDConstants::PHID_VOID] = array( 'uri' => $default_image->getBestURI(), 'tip' => pht('Default Picture'), ); require_celerity_resource('people-profile-css'); Javelin::initBehavior('phabricator-tooltips', array()); $buttons = array(); foreach ($images as $phid => $spec) { $button = javelin_tag( 'button', array( 'class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $spec['tip'], 'size' => 300, ), ), phutil_tag( 'img', array( 'height' => 50, 'width' => 50, 'src' => $spec['uri'], ))); $button = array( phutil_tag( 'input', array( 'type' => 'hidden', 'name' => 'phid', 'value' => $phid, )), $button, ); $button = phabricator_form( $viewer, array( 'class' => 'profile-image-form', 'method' => 'POST', ), $button); $buttons[] = $button; } if ($has_current) { $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Current Picture')) ->setValue(array_shift($buttons))); } $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Use Picture')) ->setValue($buttons)); $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setFormErrors($errors) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $upload_form = id(new AphrontFormView()) ->setUser($viewer) ->setEncType('multipart/form-data') ->appendChild( id(new AphrontFormFileControl()) ->setName('picture') ->setLabel(pht('Upload Picture')) ->setError($e_file) ->setCaption( pht('Supported formats: %s', implode(', ', $supported_formats)))) ->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($done_uri) ->setValue(pht('Upload Picture'))); $upload_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Upload New Picture')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($upload_form); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Edit Profile Picture')); $crumbs->setBorder(true); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_MANAGE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $header = id(new PHUIHeaderView()) ->setHeader(pht('Edit Profile Picture')) ->setHeaderIcon('fa-camera'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $form_box, $upload_box, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setNavigation($nav) ->appendChild($view); } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php index 79134de017..17fc67e2f3 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileViewController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileViewController.php @@ -1,378 +1,378 @@ getViewer(); $username = $request->getURIData('username'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withUsernames(array($username)) ->needBadges(true) ->needProfileImage(true) ->needAvailability(true) ->executeOne(); if (!$user) { return new Aphront404Response(); } $this->setUser($user); $profile = $user->loadUserProfile(); $picture = $user->getProfileImageURI(); $profile_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon()); $profile_icon = id(new PHUIIconView()) ->setIcon($profile_icon); $profile_title = $profile->getDisplayTitle(); $header = id(new PHUIHeaderView()) ->setHeader($user->getFullName()) ->setSubheader(array($profile_icon, $profile_title)) ->setImage($picture) ->setProfileHeader(true); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $user, PhabricatorPolicyCapability::CAN_EDIT); if ($can_edit) { $id = $user->getID(); $header->setImageEditURL($this->getApplicationURI("picture/{$id}/")); } $properties = $this->buildPropertyView($user); $name = $user->getUsername(); $feed = $this->buildPeopleFeed($user, $viewer); $feed = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Recent Activity')) ->addClass('project-view-feed') ->appendChild($feed); $projects = $this->buildProjectsView($user); $calendar = $this->buildCalendarDayView($user); $badges = $this->buildBadgesView($user); require_celerity_resource('project-view-css'); $home = id(new PHUITwoColumnView()) ->setHeader($header) ->addClass('project-view-home') ->setMainColumn( array( $properties, $feed, )) ->setSideColumn( array( $projects, $calendar, $badges, )); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorPeopleProfilePanelEngine::PANEL_PROFILE); + $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_PROFILE); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); return $this->newPage() ->setTitle($user->getUsername()) ->setNavigation($nav) ->setCrumbs($crumbs) ->appendChild( array( $home, )); } private function buildPropertyView( PhabricatorUser $user) { $viewer = $this->getRequest()->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($user); $field_list = PhabricatorCustomField::getObjectFields( $user, PhabricatorCustomField::ROLE_VIEW); $field_list->appendFieldsToPropertyList($user, $viewer, $view); if (!$view->hasAnyProperties()) { return null; } $view = id(new PHUIObjectBoxView()) ->appendChild($view) ->addClass('project-view-properties'); return $view; } private function buildProjectsView( PhabricatorUser $user) { $viewer = $this->getViewer(); $projects = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withMemberPHIDs(array($user->getPHID())) ->needImages(true) ->withStatuses( array( PhabricatorProjectStatus::STATUS_ACTIVE, )) ->execute(); $header = id(new PHUIHeaderView()) ->setHeader(pht('Projects')); if (!empty($projects)) { $limit = 5; $render_phids = array_slice($projects, 0, $limit); $list = id(new PhabricatorProjectListView()) ->setUser($viewer) ->setProjects($render_phids); if (count($projects) > $limit) { $header_text = pht( 'Projects (%s)', phutil_count($projects)); $header = id(new PHUIHeaderView()) ->setHeader($header_text) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-list-ul') ->setText(pht('View All')) ->setHref('/project/?member='.$user->getPHID())); } } else { $error = id(new PHUIBoxView()) ->addClass('mlb') ->appendChild(pht('User does not belong to any projects.')); $list = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) ->appendChild($error); } $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->appendChild($list) ->setBackground(PHUIObjectBoxView::GREY); return $box; } private function buildCalendarDayView(PhabricatorUser $user) { $viewer = $this->getViewer(); $class = 'PhabricatorCalendarApplication'; if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { return null; } $midnight = PhabricatorTime::getTodayMidnightDateTime($viewer); $week_end = clone $midnight; $week_end = $week_end->modify('+3 days'); $range_start = $midnight->format('U'); $range_end = $week_end->format('U'); $events = id(new PhabricatorCalendarEventQuery()) ->setViewer($viewer) ->withDateRange($range_start, $range_end) ->withInvitedPHIDs(array($user->getPHID())) ->withIsCancelled(false) ->needRSVPs(array($viewer->getPHID())) ->execute(); $event_views = array(); foreach ($events as $event) { $viewer_is_invited = $event->isRSVPInvited($viewer->getPHID()); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $event, PhabricatorPolicyCapability::CAN_EDIT); $epoch_min = $event->getStartDateTimeEpoch(); $epoch_max = $event->getEndDateTimeEpoch(); $event_view = id(new AphrontCalendarEventView()) ->setCanEdit($can_edit) ->setEventID($event->getID()) ->setEpochRange($epoch_min, $epoch_max) ->setIsAllDay($event->getIsAllDay()) ->setIcon($event->getIcon()) ->setViewerIsInvited($viewer_is_invited) ->setName($event->getName()) ->setDatetimeSummary($event->renderEventDate($viewer, true)) ->setURI($event->getURI()); $event_views[] = $event_view; } $event_views = msort($event_views, 'getEpochStart'); $day_view = id(new PHUICalendarWeekView()) ->setViewer($viewer) ->setView('week') ->setEvents($event_views) ->setWeekLength(3) ->render(); $header = id(new PHUIHeaderView()) ->setHeader(pht('Calendar')) ->setHref( urisprintf( '/calendar/?invited=%s#R', $user->getUsername())); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->appendChild($day_view) ->addClass('calendar-profile-box') ->setBackground(PHUIObjectBoxView::GREY); return $box; } private function buildBadgesView(PhabricatorUser $user) { $viewer = $this->getViewer(); $class = 'PhabricatorBadgesApplication'; if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { return null; } $awards = array(); $badges = array(); if ($user->getBadgePHIDs()) { $awards = id(new PhabricatorBadgesAwardQuery()) ->setViewer($viewer) ->withRecipientPHIDs(array($user->getPHID())) ->execute(); $awards = mpull($awards, null, 'getBadgePHID'); $badges = array(); foreach ($awards as $award) { $badge = $award->getBadge(); if ($badge->getStatus() == PhabricatorBadgesBadge::STATUS_ACTIVE) { $badges[$award->getBadgePHID()] = $badge; } } } if (count($badges)) { $flex = new PHUIBadgeBoxView(); foreach ($badges as $badge) { if ($badge) { $awarder_info = array(); $award = idx($awards, $badge->getPHID(), null); $awarder_phid = $award->getAwarderPHID(); $awarder_handle = $viewer->renderHandle($awarder_phid); $awarder_info = pht( 'Awarded by %s', $awarder_handle->render()); $item = id(new PHUIBadgeView()) ->setIcon($badge->getIcon()) ->setHeader($badge->getName()) ->setSubhead($badge->getFlavor()) ->setQuality($badge->getQuality()) ->setHref($badge->getViewURI()) ->addByLine($awarder_info); $flex->addItem($item); } } } else { $error = id(new PHUIBoxView()) ->addClass('mlb') ->appendChild(pht('User does not have any badges.')); $flex = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) ->appendChild($error); } // Best option? $badges = id(new PhabricatorBadgesQuery()) ->setViewer($viewer) ->withStatuses(array( PhabricatorBadgesBadge::STATUS_ACTIVE, )) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->execute(); $button = id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-plus') ->setText(pht('Award')) ->setWorkflow(true) ->setHref('/badges/award/'.$user->getID().'/'); $can_award = false; if (count($badges)) { $can_award = true; } $header = id(new PHUIHeaderView()) ->setHeader(pht('Badges')); if (count($badges)) { $header->addActionLink($button); } $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->addClass('project-view-badges') ->appendChild($flex) ->setBackground(PHUIObjectBoxView::GREY); return $box; } private function buildPeopleFeed( PhabricatorUser $user, $viewer) { $query = new PhabricatorFeedQuery(); $query->setFilterPHIDs( array( $user->getPHID(), )); $query->setLimit(100); $query->setViewer($viewer); $stories = $query->execute(); $builder = new PhabricatorFeedBuilder($stories); $builder->setUser($viewer); $builder->setShowHovercards(true); $builder->setNoDataString(pht('To begin on such a grand journey, '. 'requires but just a single step.')); $view = $builder->buildView(); return $view->render(); } } diff --git a/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php new file mode 100644 index 0000000000..aab3896721 --- /dev/null +++ b/src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php @@ -0,0 +1,84 @@ +getProfileObject(); + $username = $user->getUsername(); + $username = phutil_escape_uri($username); + return "/p/{$username}/item/{$path}"; + } + + protected function getBuiltinProfileItems($object) { + $viewer = $this->getViewer(); + + $items = array(); + + $items[] = $this->newItem() + ->setBuiltinKey(self::ITEM_PROFILE) + ->setMenuItemKey(PhabricatorPeopleDetailsProfileMenuItem::MENUITEMKEY); + + $have_maniphest = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorManiphestApplication', + $viewer); + if ($have_maniphest) { + $uri = urisprintf( + '/maniphest/?statuses=open()&assigned=%s#R', + $object->getPHID()); + + $items[] = $this->newItem() + ->setBuiltinKey('tasks') + ->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY) + ->setMenuItemProperty('icon', 'maniphest') + ->setMenuItemProperty('name', pht('Open Tasks')) + ->setMenuItemProperty('uri', $uri); + } + + $have_differential = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorDifferentialApplication', + $viewer); + if ($have_differential) { + $uri = urisprintf( + '/differential/?authors=%s#R', + $object->getPHID()); + + $items[] = $this->newItem() + ->setBuiltinKey('revisions') + ->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY) + ->setMenuItemProperty('icon', 'differential') + ->setMenuItemProperty('name', pht('Revisions')) + ->setMenuItemProperty('uri', $uri); + } + + $have_diffusion = PhabricatorApplication::isClassInstalledForViewer( + 'PhabricatorDiffusionApplication', + $viewer); + if ($have_diffusion) { + $uri = urisprintf( + '/audit/?authors=%s#R', + $object->getPHID()); + + $items[] = $this->newItem() + ->setBuiltinKey('commits') + ->setMenuItemKey(PhabricatorLinkProfileMenuItem::MENUITEMKEY) + ->setMenuItemProperty('icon', 'diffusion') + ->setMenuItemProperty('name', pht('Commits')) + ->setMenuItemProperty('uri', $uri); + } + + $items[] = $this->newItem() + ->setBuiltinKey(self::ITEM_MANAGE) + ->setMenuItemKey(PhabricatorPeopleManageProfileMenuItem::MENUITEMKEY); + + return $items; + } + +} diff --git a/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php b/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php deleted file mode 100644 index db362d2049..0000000000 --- a/src/applications/people/engine/PhabricatorPeopleProfilePanelEngine.php +++ /dev/null @@ -1,84 +0,0 @@ -getProfileObject(); - $username = $user->getUsername(); - $username = phutil_escape_uri($username); - return "/p/{$username}/panel/{$path}"; - } - - protected function getBuiltinProfilePanels($object) { - $viewer = $this->getViewer(); - - $panels = array(); - - $panels[] = $this->newPanel() - ->setBuiltinKey(self::PANEL_PROFILE) - ->setPanelKey(PhabricatorPeopleDetailsProfilePanel::PANELKEY); - - $have_maniphest = PhabricatorApplication::isClassInstalledForViewer( - 'PhabricatorManiphestApplication', - $viewer); - if ($have_maniphest) { - $uri = urisprintf( - '/maniphest/?statuses=open()&assigned=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('tasks') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'maniphest') - ->setPanelProperty('name', pht('Open Tasks')) - ->setPanelProperty('uri', $uri); - } - - $have_differential = PhabricatorApplication::isClassInstalledForViewer( - 'PhabricatorDifferentialApplication', - $viewer); - if ($have_differential) { - $uri = urisprintf( - '/differential/?authors=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('revisions') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'differential') - ->setPanelProperty('name', pht('Revisions')) - ->setPanelProperty('uri', $uri); - } - - $have_diffusion = PhabricatorApplication::isClassInstalledForViewer( - 'PhabricatorDiffusionApplication', - $viewer); - if ($have_diffusion) { - $uri = urisprintf( - '/audit/?authors=%s#R', - $object->getPHID()); - - $panels[] = $this->newPanel() - ->setBuiltinKey('commits') - ->setPanelKey(PhabricatorLinkProfilePanel::PANELKEY) - ->setPanelProperty('icon', 'diffusion') - ->setPanelProperty('name', pht('Commits')) - ->setPanelProperty('uri', $uri); - } - - $panels[] = $this->newPanel() - ->setBuiltinKey(self::PANEL_MANAGE) - ->setPanelKey(PhabricatorPeopleManageProfilePanel::PANELKEY); - - return $panels; - } - -} diff --git a/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php b/src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php similarity index 66% rename from src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php rename to src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php index 83d45dfb9d..0f5cb6c1fa 100644 --- a/src/applications/people/profilepanel/PhabricatorPeopleDetailsProfilePanel.php +++ b/src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php @@ -1,59 +1,59 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $user = $config->getProfileObject(); $picture = $user->getProfileImageURI(); $name = $user->getUsername(); $href = urisprintf( '/p/%s/', $user->getUsername()); $item = $this->newItem() ->setHref($href) ->setName($name) ->setProfileImage($picture); return array( $item, ); } } diff --git a/src/applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php b/src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php similarity index 59% rename from src/applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php rename to src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php index 29000b5a94..78d3dca49d 100644 --- a/src/applications/people/profilepanel/PhabricatorPeopleManageProfilePanel.php +++ b/src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php @@ -1,59 +1,59 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $user = $config->getProfileObject(); $id = $user->getID(); $item = $this->newItem() ->setHref("/people/manage/{$id}/") ->setName($this->getDisplayName($config)) ->setIcon('fa-gears'); return array( $item, ); } } diff --git a/src/applications/policy/rule/PhabricatorPolicyRule.php b/src/applications/policy/rule/PhabricatorPolicyRule.php index bd5af9a1b8..2f9fac9cfb 100644 --- a/src/applications/policy/rule/PhabricatorPolicyRule.php +++ b/src/applications/policy/rule/PhabricatorPolicyRule.php @@ -1,200 +1,221 @@ new AphrontTokenizerTemplateView(), 'uri' => $datasource->getDatasourceURI(), 'placeholder' => $datasource->getPlaceholderText(), 'browseURI' => $datasource->getBrowseURI(), ); } public function getRuleOrder() { return 500; } public function getValueForStorage($value) { return $value; } public function getValueForDisplay(PhabricatorUser $viewer, $value) { return $value; } public function getRequiredHandlePHIDsForSummary($value) { $phids = array(); switch ($this->getValueControlType()) { case self::CONTROL_TYPE_TOKENIZER: $phids = $value; break; case self::CONTROL_TYPE_TEXT: case self::CONTROL_TYPE_SELECT: case self::CONTROL_TYPE_NONE: default: if (phid_get_type($value) != PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { $phids = array($value); } else { $phids = array(); } break; } return $phids; } /** * Return `true` if the given value creates a rule with a meaningful effect. * An example of a rule with no meaningful effect is a "users" rule with no * users specified. * * @return bool True if the value creates a meaningful rule. */ public function ruleHasEffect($value) { return true; } /* -( Transaction Hints )-------------------------------------------------- */ /** * Tell policy rules about upcoming transaction effects. * * Before transaction effects are applied, we try to stop users from making * edits which will lock them out of objects. We can't do this perfectly, * since they can set a policy to "the moon is full" moments before it wanes, * but we try to prevent as many mistakes as possible. * * Some policy rules depend on complex checks against object state which * we can't set up ahead of time. For example, subscriptions require database * writes. * * In cases like this, instead of doing writes, you can pass a hint about an * object to a policy rule. The rule can then look for hints and use them in * rendering a verdict about whether the user will be able to see the object * or not after applying the policy change. * * @param PhabricatorPolicyInterface Object to pass a hint about. * @param PhabricatorPolicyRule Rule to pass hint to. * @param wild Hint. * @return void */ public static function passTransactionHintToRule( PhabricatorPolicyInterface $object, PhabricatorPolicyRule $rule, $hint) { $cache = PhabricatorCaches::getRequestCache(); $cache->setKey(self::getObjectPolicyCacheKey($object, $rule), $hint); } final protected function getTransactionHint( PhabricatorPolicyInterface $object) { $cache = PhabricatorCaches::getRequestCache(); return $cache->getKey(self::getObjectPolicyCacheKey($object, $this)); } private static function getObjectPolicyCacheKey( PhabricatorPolicyInterface $object, PhabricatorPolicyRule $rule) { - $hash = spl_object_hash($object); - $rule = get_class($rule); - return 'policycache.'.$hash.'.'.$rule; + + // NOTE: This is quite a bit of a hack, but we don't currently have a + // better way to carry hints from the TransactionEditor into PolicyRules + // about pending policy changes. + + // Put some magic secret unique value on each object so we can pass + // information about it by proxy. This allows us to test if pending + // edits to an object will cause policy violations or not, before allowing + // those edits to go through. + + // Some better approaches might be: + // - Use traits to give `PhabricatorPolicyInterface` objects real + // storage (requires PHP 5.4.0). + // - Wrap policy objects in a container with extra storage which the + // policy filter knows how to unbox (lots of work). + + // When this eventually gets cleaned up, the corresponding hack in + // LiskDAO->__set() should also be cleaned up. + static $id = 0; + if (!isset($object->_hashKey)) { + @$object->_hashKey = 'object.id('.(++$id).')'; + } + + return $object->_hashKey; } /* -( Implementing Object Policies )--------------------------------------- */ /** * Return a unique string like "maniphest.author" to expose this rule as an * object policy. * * Object policy rules, like "Task Author", are more advanced than basic * policy rules (like "All Users") but not as powerful as custom rules. * * @return string Unique identifier for this rule. * @task objectpolicy */ public function getObjectPolicyKey() { return null; } final public function getObjectPolicyFullKey() { $key = $this->getObjectPolicyKey(); if (!$key) { throw new Exception( pht( 'This policy rule (of class "%s") does not have an associated '. 'object policy key.', get_class($this))); } return PhabricatorPolicyQuery::OBJECT_POLICY_PREFIX.$key; } public function getObjectPolicyName() { throw new PhutilMethodNotImplementedException(); } public function getObjectPolicyShortName() { return $this->getObjectPolicyName(); } public function getObjectPolicyIcon() { return 'fa-cube'; } public function getPolicyExplanation() { throw new PhutilMethodNotImplementedException(); } } diff --git a/src/applications/project/application/PhabricatorProjectApplication.php b/src/applications/project/application/PhabricatorProjectApplication.php index b8a6149e4f..8988f0f73a 100644 --- a/src/applications/project/application/PhabricatorProjectApplication.php +++ b/src/applications/project/application/PhabricatorProjectApplication.php @@ -1,150 +1,150 @@ array( '(?:query/(?P[^/]+)/)?' => 'PhabricatorProjectListController', 'filter/(?P[^/]+)/' => 'PhabricatorProjectListController', 'archive/(?P[1-9]\d*)/' => 'PhabricatorProjectArchiveController', 'lock/(?P[1-9]\d*)/' => 'PhabricatorProjectLockController', 'members/(?P[1-9]\d*)/' => 'PhabricatorProjectMembersViewController', 'members/(?P[1-9]\d*)/add/' => 'PhabricatorProjectMembersAddController', '(?Pmembers|watchers)/(?P[1-9]\d*)/remove/' => 'PhabricatorProjectMembersRemoveController', 'profile/(?P[1-9]\d*)/' => 'PhabricatorProjectProfileController', 'view/(?P[1-9]\d*)/' => 'PhabricatorProjectViewController', 'picture/(?P[1-9]\d*)/' => 'PhabricatorProjectEditPictureController', $this->getEditRoutePattern('edit/') => 'PhabricatorProjectEditController', - '(?P[1-9]\d*)/panel/' - => $this->getPanelRouting('PhabricatorProjectPanelController'), + '(?P[1-9]\d*)/item/' => $this->getProfileMenuRouting( + 'PhabricatorProjectMenuItemController'), 'subprojects/(?P[1-9]\d*)/' => 'PhabricatorProjectSubprojectsController', 'board/(?P[1-9]\d*)/'. '(?Pfilter/)?'. '(?:query/(?P[^/]+)/)?' => 'PhabricatorProjectBoardViewController', 'move/(?P[1-9]\d*)/' => 'PhabricatorProjectMoveController', 'cover/' => 'PhabricatorProjectCoverController', 'board/(?P[1-9]\d*)/' => array( 'edit/(?:(?P\d+)/)?' => 'PhabricatorProjectColumnEditController', 'hide/(?:(?P\d+)/)?' => 'PhabricatorProjectColumnHideController', 'column/(?:(?P\d+)/)?' => 'PhabricatorProjectColumnDetailController', 'import/' => 'PhabricatorProjectBoardImportController', 'reorder/' => 'PhabricatorProjectBoardReorderController', 'disable/' => 'PhabricatorProjectBoardDisableController', 'manage/' => 'PhabricatorProjectBoardManageController', 'background/' => 'PhabricatorProjectBoardBackgroundController', ), 'update/(?P[1-9]\d*)/(?P[^/]+)/' => 'PhabricatorProjectUpdateController', 'manage/(?P[1-9]\d*)/' => 'PhabricatorProjectManageController', '(?Pwatch|unwatch)/(?P[1-9]\d*)/' => 'PhabricatorProjectWatchController', 'silence/(?P[1-9]\d*)/' => 'PhabricatorProjectSilenceController', 'warning/(?P[1-9]\d*)/' => 'PhabricatorProjectSubprojectWarningController', 'default/(?P[1-9]\d*)/(?P[^/]+)/' => 'PhabricatorProjectDefaultController', ), '/tag/' => array( '(?P[^/]+)/' => 'PhabricatorProjectViewController', '(?P[^/]+)/board/' => 'PhabricatorProjectBoardViewController', ), ); } protected function getCustomCapabilities() { return array( ProjectCreateProjectsCapability::CAPABILITY => array(), ProjectCanLockProjectsCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, ), ProjectDefaultViewCapability::CAPABILITY => array( 'caption' => pht('Default view policy for newly created projects.'), 'template' => PhabricatorProjectProjectPHIDType::TYPECONST, 'capability' => PhabricatorPolicyCapability::CAN_VIEW, ), ProjectDefaultEditCapability::CAPABILITY => array( 'caption' => pht('Default edit policy for newly created projects.'), 'template' => PhabricatorProjectProjectPHIDType::TYPECONST, 'capability' => PhabricatorPolicyCapability::CAN_EDIT, ), ProjectDefaultJoinCapability::CAPABILITY => array( 'caption' => pht('Default join policy for newly created projects.'), 'template' => PhabricatorProjectProjectPHIDType::TYPECONST, 'capability' => PhabricatorPolicyCapability::CAN_JOIN, ), ); } public function getApplicationSearchDocumentTypes() { return array( PhabricatorProjectProjectPHIDType::TYPECONST, ); } public function getHelpDocumentationArticles(PhabricatorUser $viewer) { return array( array( 'name' => pht('Projects User Guide'), 'href' => PhabricatorEnv::getDoclink('Projects User Guide'), ), ); } } diff --git a/src/applications/project/controller/PhabricatorProjectBoardController.php b/src/applications/project/controller/PhabricatorProjectBoardController.php index 04ab714eb0..d0c6abf882 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardController.php @@ -1,14 +1,14 @@ selectFilter(PhabricatorProject::PANEL_WORKBOARD); + $menu->selectFilter(PhabricatorProject::ITEM_WORKBOARD); $menu->addClass('project-board-nav'); return $menu; } } diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index da992d9b19..fa2a423b09 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -1,1076 +1,1076 @@ getUser(); $response = $this->loadProject(); if ($response) { return $response; } $project = $this->getProject(); $this->readRequestState(); $board_uri = $this->getApplicationURI('board/'.$project->getID().'/'); $search_engine = id(new ManiphestTaskSearchEngine()) ->setViewer($viewer) ->setBaseURI($board_uri) ->setIsBoardView(true); if ($request->isFormPost() && !$request->getBool('initialize')) { $saved = $search_engine->buildSavedQueryFromRequest($request); $search_engine->saveQuery($saved); $filter_form = id(new AphrontFormView()) ->setUser($viewer); $search_engine->buildSearchForm($filter_form, $saved); if ($search_engine->getErrors()) { return $this->newDialog() ->setWidth(AphrontDialogView::WIDTH_FULL) ->setTitle(pht('Advanced Filter')) ->appendChild($filter_form->buildLayoutView()) ->setErrors($search_engine->getErrors()) ->setSubmitURI($board_uri) ->addSubmitButton(pht('Apply Filter')) ->addCancelButton($board_uri); } return id(new AphrontRedirectResponse())->setURI( $this->getURIWithState( $search_engine->getQueryResultsPageURI($saved->getQueryKey()))); } $query_key = $this->getDefaultFilter($project); $request_query = $request->getStr('filter'); if (strlen($request_query)) { $query_key = $request_query; } $uri_query = $request->getURIData('queryKey'); if (strlen($uri_query)) { $query_key = $uri_query; } $this->queryKey = $query_key; $custom_query = null; if ($search_engine->isBuiltinQuery($query_key)) { $saved = $search_engine->buildSavedQueryFromBuiltin($query_key); } else { $saved = id(new PhabricatorSavedQueryQuery()) ->setViewer($viewer) ->withQueryKeys(array($query_key)) ->executeOne(); if (!$saved) { return new Aphront404Response(); } $custom_query = $saved; } if ($request->getURIData('filter')) { $filter_form = id(new AphrontFormView()) ->setUser($viewer); $search_engine->buildSearchForm($filter_form, $saved); return $this->newDialog() ->setWidth(AphrontDialogView::WIDTH_FULL) ->setTitle(pht('Advanced Filter')) ->appendChild($filter_form->buildLayoutView()) ->setSubmitURI($board_uri) ->addSubmitButton(pht('Apply Filter')) ->addCancelButton($board_uri); } $task_query = $search_engine->buildQueryFromSavedQuery($saved); $select_phids = array($project->getPHID()); if ($project->getHasSubprojects() || $project->getHasMilestones()) { $descendants = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withAncestorProjectPHIDs($select_phids) ->execute(); foreach ($descendants as $descendant) { $select_phids[] = $descendant->getPHID(); } } $tasks = $task_query ->withEdgeLogicPHIDs( PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, PhabricatorQueryConstraint::OPERATOR_ANCESTOR, array($select_phids)) ->setOrder(ManiphestTaskQuery::ORDER_PRIORITY) ->setViewer($viewer) ->execute(); $tasks = mpull($tasks, null, 'getPHID'); $board_phid = $project->getPHID(); // Regardless of display order, pass tasks to the layout engine in ID order // so layout is consistent. $board_tasks = msort($tasks, 'getID'); $layout_engine = id(new PhabricatorBoardLayoutEngine()) ->setViewer($viewer) ->setBoardPHIDs(array($board_phid)) ->setObjectPHIDs(array_keys($board_tasks)) ->setFetchAllBoards(true) ->executeLayout(); $columns = $layout_engine->getColumns($board_phid); if (!$columns || !$project->getHasWorkboard()) { $has_normal_columns = false; foreach ($columns as $column) { if (!$column->getProxyPHID()) { $has_normal_columns = true; break; } } $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); if (!$has_normal_columns) { if (!$can_edit) { $content = $this->buildNoAccessContent($project); } else { $content = $this->buildInitializeContent($project); } } else { if (!$can_edit) { $content = $this->buildDisabledContent($project); } else { $content = $this->buildEnableContent($project); } } if ($content instanceof AphrontResponse) { return $content; } $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_WORKBOARD); + $nav->selectFilter(PhabricatorProject::ITEM_WORKBOARD); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Workboard')); return $this->newPage() ->setTitle( array( $project->getDisplayName(), pht('Workboard'), )) ->setNavigation($nav) ->setCrumbs($crumbs) ->appendChild($content); } $task_can_edit_map = id(new PhabricatorPolicyFilter()) ->setViewer($viewer) ->requireCapabilities(array(PhabricatorPolicyCapability::CAN_EDIT)) ->apply($tasks); // If this is a batch edit, select the editable tasks in the chosen column // and ship the user into the batch editor. $batch_edit = $request->getStr('batch'); if ($batch_edit) { if ($batch_edit !== self::BATCH_EDIT_ALL) { $column_id_map = mpull($columns, null, 'getID'); $batch_column = idx($column_id_map, $batch_edit); if (!$batch_column) { return new Aphront404Response(); } $batch_task_phids = $layout_engine->getColumnObjectPHIDs( $board_phid, $batch_column->getPHID()); foreach ($batch_task_phids as $key => $batch_task_phid) { if (empty($task_can_edit_map[$batch_task_phid])) { unset($batch_task_phids[$key]); } } $batch_tasks = array_select_keys($tasks, $batch_task_phids); } else { $batch_tasks = $task_can_edit_map; } if (!$batch_tasks) { $cancel_uri = $this->getURIWithState($board_uri); return $this->newDialog() ->setTitle(pht('No Editable Tasks')) ->appendParagraph( pht( 'The selected column contains no visible tasks which you '. 'have permission to edit.')) ->addCancelButton($board_uri); } $batch_ids = mpull($batch_tasks, 'getID'); $batch_ids = implode(',', $batch_ids); $batch_uri = new PhutilURI('/maniphest/batch/'); $batch_uri->setQueryParam('board', $this->id); $batch_uri->setQueryParam('batch', $batch_ids); return id(new AphrontRedirectResponse()) ->setURI($batch_uri); } $board_id = celerity_generate_unique_node_id(); $board = id(new PHUIWorkboardView()) ->setUser($viewer) ->setID($board_id) ->addSigil('jx-workboard') ->setMetadata( array( 'boardPHID' => $project->getPHID(), )); $visible_columns = array(); $column_phids = array(); $visible_phids = array(); foreach ($columns as $column) { if (!$this->showHidden) { if ($column->isHidden()) { continue; } } $proxy = $column->getProxy(); if ($proxy && !$proxy->isMilestone()) { // TODO: For now, don't show subproject columns because we can't // handle tasks with multiple positions yet. continue; } $task_phids = $layout_engine->getColumnObjectPHIDs( $board_phid, $column->getPHID()); $column_tasks = array_select_keys($tasks, $task_phids); // If we aren't using "natural" order, reorder the column by the original // query order. if ($this->sortKey != PhabricatorProjectColumn::ORDER_NATURAL) { $column_tasks = array_select_keys($column_tasks, array_keys($tasks)); } $column_phid = $column->getPHID(); $visible_columns[$column_phid] = $column; $column_phids[$column_phid] = $column_tasks; foreach ($column_tasks as $phid => $task) { $visible_phids[$phid] = $phid; } } $rendering_engine = id(new PhabricatorBoardRenderingEngine()) ->setViewer($viewer) ->setObjects(array_select_keys($tasks, $visible_phids)) ->setEditMap($task_can_edit_map) ->setExcludedProjectPHIDs($select_phids); $templates = array(); $column_maps = array(); $all_tasks = array(); foreach ($visible_columns as $column_phid => $column) { $column_tasks = $column_phids[$column_phid]; $panel = id(new PHUIWorkpanelView()) ->setHeader($column->getDisplayName()) ->setSubHeader($column->getDisplayType()) ->addSigil('workpanel'); $proxy = $column->getProxy(); if ($proxy) { $proxy_id = $proxy->getID(); $href = $this->getApplicationURI("view/{$proxy_id}/"); $panel->setHref($href); } $header_icon = $column->getHeaderIcon(); if ($header_icon) { $panel->setHeaderIcon($header_icon); } $display_class = $column->getDisplayClass(); if ($display_class) { $panel->addClass($display_class); } if ($column->isHidden()) { $panel->addClass('project-panel-hidden'); } $column_menu = $this->buildColumnMenu($project, $column); $panel->addHeaderAction($column_menu); $count_tag = id(new PHUITagView()) ->setType(PHUITagView::TYPE_SHADE) ->setShade(PHUITagView::COLOR_BLUE) ->addSigil('column-points') ->setName( javelin_tag( 'span', array( 'sigil' => 'column-points-content', ), pht('-'))) ->setStyle('display: none'); $panel->setHeaderTag($count_tag); $cards = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setFlush(true) ->setAllowEmptyList(true) ->addSigil('project-column') ->setItemClass('phui-workcard') ->setMetadata( array( 'columnPHID' => $column->getPHID(), 'pointLimit' => $column->getPointLimit(), )); foreach ($column_tasks as $task) { $object_phid = $task->getPHID(); $card = $rendering_engine->renderCard($object_phid); $templates[$object_phid] = hsprintf('%s', $card->getItem()); $column_maps[$column_phid][] = $object_phid; $all_tasks[$object_phid] = $task; } $panel->setCards($cards); $board->addPanel($panel); } $behavior_config = array( 'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'), 'createURI' => $this->getCreateURI(), 'uploadURI' => '/file/dropupload/', 'coverURI' => $this->getApplicationURI('cover/'), 'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(), 'pointsEnabled' => ManiphestTaskPoints::getIsEnabled(), 'boardPHID' => $project->getPHID(), 'order' => $this->sortKey, 'templateMap' => $templates, 'columnMaps' => $column_maps, 'orderMaps' => mpull($all_tasks, 'getWorkboardOrderVectors'), 'propertyMaps' => mpull($all_tasks, 'getWorkboardProperties'), 'boardID' => $board_id, 'projectPHID' => $project->getPHID(), ); $this->initBehavior('project-boards', $behavior_config); $sort_menu = $this->buildSortMenu( $viewer, $project, $this->sortKey); $filter_menu = $this->buildFilterMenu( $viewer, $project, $custom_query, $search_engine, $query_key); $manage_menu = $this->buildManageMenu($project, $this->showHidden); $header_link = phutil_tag( 'a', array( 'href' => $this->getApplicationURI('profile/'.$project->getID().'/'), ), $project->getName()); $board_box = id(new PHUIBoxView()) ->appendChild($board) ->addClass('project-board-wrapper'); $nav = $this->getProfileMenu(); $divider = id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_DIVIDER); $fullscreen = $this->buildFullscreenMenu(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Workboard')); $crumbs->setBorder(true); $crumbs->addAction($sort_menu); $crumbs->addAction($filter_menu); $crumbs->addAction($divider); $crumbs->addAction($manage_menu); $crumbs->addAction($fullscreen); $page = $this->newPage() ->setTitle( array( $project->getDisplayName(), pht('Workboard'), )) ->setPageObjectPHIDs(array($project->getPHID())) ->setShowFooter(false) ->setNavigation($nav) ->setCrumbs($crumbs) ->addQuicksandConfig( array( 'boardConfig' => $behavior_config, )) ->appendChild( array( $board_box, )); $background = $project->getDisplayWorkboardBackgroundColor(); if ($background !== null) { require_celerity_resource('phui-workboard-color-css'); $background_color_class = "phui-workboard-{$background}"; $page->addClass('phui-workboard-color'); $page->addClass($background_color_class); } return $page; } private function readRequestState() { $request = $this->getRequest(); $project = $this->getProject(); $this->showHidden = $request->getBool('hidden'); $this->id = $project->getID(); $sort_key = $this->getDefaultSort($project); $request_sort = $request->getStr('order'); if ($this->isValidSort($request_sort)) { $sort_key = $request_sort; } $this->sortKey = $sort_key; } private function getDefaultSort(PhabricatorProject $project) { $default_sort = $project->getDefaultWorkboardSort(); if ($this->isValidSort($default_sort)) { return $default_sort; } return PhabricatorProjectColumn::DEFAULT_ORDER; } private function getDefaultFilter(PhabricatorProject $project) { $default_filter = $project->getDefaultWorkboardFilter(); if (strlen($default_filter)) { return $default_filter; } return 'open'; } private function isValidSort($sort) { switch ($sort) { case PhabricatorProjectColumn::ORDER_NATURAL: case PhabricatorProjectColumn::ORDER_PRIORITY: return true; } return false; } private function buildSortMenu( PhabricatorUser $viewer, PhabricatorProject $project, $sort_key) { $sort_icon = id(new PHUIIconView()) ->setIcon('fa-sort-amount-asc bluegrey'); $named = array( PhabricatorProjectColumn::ORDER_NATURAL => pht('Natural'), PhabricatorProjectColumn::ORDER_PRIORITY => pht('Sort by Priority'), ); $base_uri = $this->getURIWithState(); $items = array(); foreach ($named as $key => $name) { $is_selected = ($key == $sort_key); if ($is_selected) { $active_order = $name; } $item = id(new PhabricatorActionView()) ->setIcon('fa-sort-amount-asc') ->setSelected($is_selected) ->setName($name); $uri = $base_uri->alter('order', $key); $item->setHref($uri); $items[] = $item; } $id = $project->getID(); $save_uri = "default/{$id}/sort/"; $save_uri = $this->getApplicationURI($save_uri); $save_uri = $this->getURIWithState($save_uri, $force = true); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $items[] = id(new PhabricatorActionView()) ->setIcon('fa-floppy-o') ->setName(pht('Save as Default')) ->setHref($save_uri) ->setWorkflow(true) ->setDisabled(!$can_edit); $sort_menu = id(new PhabricatorActionListView()) ->setUser($viewer); foreach ($items as $item) { $sort_menu->addAction($item); } $sort_button = id(new PHUIListItemView()) ->setName($active_order) ->setIcon('fa-sort-amount-asc') ->setHref('#') ->addSigil('boards-dropdown-menu') ->setMetadata( array( 'items' => hsprintf('%s', $sort_menu), )); return $sort_button; } private function buildFilterMenu( PhabricatorUser $viewer, PhabricatorProject $project, $custom_query, PhabricatorApplicationSearchEngine $engine, $query_key) { $named = array( 'open' => pht('Open Tasks'), 'all' => pht('All Tasks'), ); if ($viewer->isLoggedIn()) { $named['assigned'] = pht('Assigned to Me'); } if ($custom_query) { $named[$custom_query->getQueryKey()] = pht('Custom Filter'); } $items = array(); foreach ($named as $key => $name) { $is_selected = ($key == $query_key); if ($is_selected) { $active_filter = $name; } $is_custom = false; if ($custom_query) { $is_custom = ($key == $custom_query->getQueryKey()); } $item = id(new PhabricatorActionView()) ->setIcon('fa-search') ->setSelected($is_selected) ->setName($name); if ($is_custom) { $uri = $this->getApplicationURI( 'board/'.$this->id.'/filter/query/'.$key.'/'); $item->setWorkflow(true); } else { $uri = $engine->getQueryResultsPageURI($key); } $uri = $this->getURIWithState($uri) ->setQueryParam('filter', null); $item->setHref($uri); $items[] = $item; } $id = $project->getID(); $filter_uri = $this->getApplicationURI("board/{$id}/filter/"); $filter_uri = $this->getURIWithState($filter_uri, $force = true); $items[] = id(new PhabricatorActionView()) ->setIcon('fa-cog') ->setHref($filter_uri) ->setWorkflow(true) ->setName(pht('Advanced Filter...')); $save_uri = "default/{$id}/filter/"; $save_uri = $this->getApplicationURI($save_uri); $save_uri = $this->getURIWithState($save_uri, $force = true); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $items[] = id(new PhabricatorActionView()) ->setIcon('fa-floppy-o') ->setName(pht('Save as Default')) ->setHref($save_uri) ->setWorkflow(true) ->setDisabled(!$can_edit); $filter_menu = id(new PhabricatorActionListView()) ->setUser($viewer); foreach ($items as $item) { $filter_menu->addAction($item); } $filter_button = id(new PHUIListItemView()) ->setName($active_filter) ->setIcon('fa-search') ->setHref('#') ->addSigil('boards-dropdown-menu') ->setMetadata( array( 'items' => hsprintf('%s', $filter_menu), )); return $filter_button; } private function buildManageMenu( PhabricatorProject $project, $show_hidden) { $request = $this->getRequest(); $viewer = $request->getUser(); $id = $project->getID(); $manage_uri = $this->getApplicationURI("board/{$id}/manage/"); $add_uri = $this->getApplicationURI("board/{$id}/edit/"); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $manage_items = array(); $manage_items[] = id(new PhabricatorActionView()) ->setIcon('fa-plus') ->setName(pht('Add Column')) ->setHref($add_uri) ->setDisabled(!$can_edit) ->setWorkflow(true); $manage_items[] = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Manage Board')) ->setHref($manage_uri); if ($show_hidden) { $hidden_uri = $this->getURIWithState() ->setQueryParam('hidden', null); $hidden_icon = 'fa-eye-slash'; $hidden_text = pht('Hide Hidden Columns'); } else { $hidden_uri = $this->getURIWithState() ->setQueryParam('hidden', 'true'); $hidden_icon = 'fa-eye'; $hidden_text = pht('Show Hidden Columns'); } $manage_items[] = id(new PhabricatorActionView()) ->setIcon($hidden_icon) ->setName($hidden_text) ->setHref($hidden_uri); $batch_edit_uri = $request->getRequestURI(); $batch_edit_uri->setQueryParam('batch', self::BATCH_EDIT_ALL); $can_batch_edit = PhabricatorPolicyFilter::hasCapability( $viewer, PhabricatorApplication::getByClass('PhabricatorManiphestApplication'), ManiphestBulkEditCapability::CAPABILITY); $manage_items[] = id(new PhabricatorActionView()) ->setIcon('fa-list-ul') ->setName(pht('Batch Edit Visible Tasks...')) ->setHref($batch_edit_uri) ->setDisabled(!$can_batch_edit); $manage_menu = id(new PhabricatorActionListView()) ->setUser($viewer); foreach ($manage_items as $item) { $manage_menu->addAction($item); } $manage_button = id(new PHUIListItemView()) ->setIcon('fa-cog') ->setHref('#') ->addSigil('boards-dropdown-menu') ->addSigil('has-tooltip') ->setMetadata( array( 'tip' => pht('Manage'), 'align' => 'S', 'items' => hsprintf('%s', $manage_menu), )); return $manage_button; } private function buildFullscreenMenu() { $up = id(new PHUIListItemView()) ->setIcon('fa-arrows-alt') ->setHref('#') ->addClass('phui-workboard-expand-icon') ->addSigil('jx-toggle-class') ->addSigil('has-tooltip') ->setMetaData(array( 'tip' => pht('Fullscreen'), 'map' => array( 'phabricator-standard-page' => 'phui-workboard-fullscreen', ), )); return $up; } private function buildColumnMenu( PhabricatorProject $project, PhabricatorProjectColumn $column) { $request = $this->getRequest(); $viewer = $request->getUser(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $column_items = array(); if ($column->getProxyPHID()) { $default_phid = $column->getProxyPHID(); } else { $default_phid = $column->getProjectPHID(); } $column_items[] = id(new PhabricatorActionView()) ->setIcon('fa-plus') ->setName(pht('Create Task...')) ->setHref($this->getCreateURI()) ->addSigil('column-add-task') ->setMetadata( array( 'columnPHID' => $column->getPHID(), 'boardPHID' => $project->getPHID(), 'projectPHID' => $default_phid, )); $batch_edit_uri = $request->getRequestURI(); $batch_edit_uri->setQueryParam('batch', $column->getID()); $can_batch_edit = PhabricatorPolicyFilter::hasCapability( $viewer, PhabricatorApplication::getByClass('PhabricatorManiphestApplication'), ManiphestBulkEditCapability::CAPABILITY); $column_items[] = id(new PhabricatorActionView()) ->setIcon('fa-list-ul') ->setName(pht('Batch Edit Tasks...')) ->setHref($batch_edit_uri) ->setDisabled(!$can_batch_edit); $can_hide = ($can_edit && !$column->isDefaultColumn()); $hide_uri = 'board/'.$this->id.'/hide/'.$column->getID().'/'; $hide_uri = $this->getApplicationURI($hide_uri); $hide_uri = $this->getURIWithState($hide_uri); if (!$column->isHidden()) { $column_items[] = id(new PhabricatorActionView()) ->setName(pht('Hide Column')) ->setIcon('fa-eye-slash') ->setHref($hide_uri) ->setDisabled(!$can_hide) ->setWorkflow(true); } else { $column_items[] = id(new PhabricatorActionView()) ->setName(pht('Show Column')) ->setIcon('fa-eye') ->setHref($hide_uri) ->setDisabled(!$can_hide) ->setWorkflow(true); } $column_menu = id(new PhabricatorActionListView()) ->setUser($viewer); foreach ($column_items as $item) { $column_menu->addAction($item); } $column_button = id(new PHUIIconView()) ->setIcon('fa-caret-down') ->setHref('#') ->addSigil('boards-dropdown-menu') ->setMetadata( array( 'items' => hsprintf('%s', $column_menu), )); return $column_button; } /** * Add current state parameters (like order and the visibility of hidden * columns) to a URI. * * This allows actions which toggle or adjust one piece of state to keep * the rest of the board state persistent. If no URI is provided, this method * starts with the request URI. * * @param string|null URI to add state parameters to. * @param bool True to explicitly include all state. * @return PhutilURI URI with state parameters. */ private function getURIWithState($base = null, $force = false) { $project = $this->getProject(); if ($base === null) { $base = $this->getRequest()->getRequestURI(); } $base = new PhutilURI($base); if ($force || ($this->sortKey != $this->getDefaultSort($project))) { $base->setQueryParam('order', $this->sortKey); } else { $base->setQueryParam('order', null); } if ($force || ($this->queryKey != $this->getDefaultFilter($project))) { $base->setQueryParam('filter', $this->queryKey); } else { $base->setQueryParam('filter', null); } $base->setQueryParam('hidden', $this->showHidden ? 'true' : null); return $base; } private function getCreateURI() { $viewer = $this->getViewer(); // TODO: This should be cleaned up, but maybe we're going to make options // for each column or board? $edit_config = id(new ManiphestEditEngine()) ->setViewer($viewer) ->loadDefaultEditConfiguration(); if ($edit_config) { $form_key = $edit_config->getIdentifier(); $create_uri = "/maniphest/task/edit/form/{$form_key}/"; } else { $create_uri = '/maniphest/task/edit/'; } return $create_uri; } private function buildInitializeContent(PhabricatorProject $project) { $request = $this->getRequest(); $viewer = $this->getViewer(); $type = $request->getStr('initialize-type'); $id = $project->getID(); $profile_uri = $this->getApplicationURI("profile/{$id}/"); $board_uri = $this->getApplicationURI("board/{$id}/"); $import_uri = $this->getApplicationURI("board/{$id}/import/"); $set_default = $request->getBool('default'); if ($set_default) { $this - ->getProfilePanelEngine() - ->adjustDefault(PhabricatorProject::PANEL_WORKBOARD); + ->getProfileMenuEngine() + ->adjustDefault(PhabricatorProject::ITEM_WORKBOARD); } if ($request->isFormPost()) { if ($type == 'backlog-only') { $column = PhabricatorProjectColumn::initializeNewColumn($viewer) ->setSequence(0) ->setProperty('isDefault', true) ->setProjectPHID($project->getPHID()) ->save(); $project->setHasWorkboard(1)->save(); return id(new AphrontRedirectResponse()) ->setURI($board_uri); } else { return id(new AphrontRedirectResponse()) ->setURI($import_uri); } } // TODO: Tailor this UI if the project is already a parent project. We // should not offer options for creating a parent project workboard, since // they can't have their own columns. $new_selector = id(new AphrontFormRadioButtonControl()) ->setLabel(pht('Columns')) ->setName('initialize-type') ->setValue('backlog-only') ->addButton( 'backlog-only', pht('New Empty Board'), pht('Create a new board with just a backlog column.')) ->addButton( 'import', pht('Import Columns'), pht('Import board columns from another project.')); $default_checkbox = id(new AphrontFormCheckboxControl()) ->setLabel(pht('Make Default')) ->addCheckbox( 'default', 1, pht('Make the workboard the default view for this project.'), true); $form = id(new AphrontFormView()) ->setUser($viewer) ->addHiddenInput('initialize', 1) ->appendRemarkupInstructions( pht('The workboard for this project has not been created yet.')) ->appendControl($new_selector) ->appendControl($default_checkbox) ->appendControl( id(new AphrontFormSubmitControl()) ->addCancelButton($profile_uri) ->setValue(pht('Create Workboard'))); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Create Workboard')) ->setForm($form); return $box; } private function buildNoAccessContent(PhabricatorProject $project) { $viewer = $this->getViewer(); $id = $project->getID(); $profile_uri = $this->getApplicationURI("profile/{$id}/"); return $this->newDialog() ->setTitle(pht('Unable to Create Workboard')) ->appendParagraph( pht( 'The workboard for this project has not been created yet, '. 'but you do not have permission to create it. Only users '. 'who can edit this project can create a workboard for it.')) ->addCancelButton($profile_uri); } private function buildEnableContent(PhabricatorProject $project) { $request = $this->getRequest(); $viewer = $this->getViewer(); $id = $project->getID(); $profile_uri = $this->getApplicationURI("profile/{$id}/"); $board_uri = $this->getApplicationURI("board/{$id}/"); if ($request->isFormPost()) { $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction()) ->setTransactionType(PhabricatorProjectTransaction::TYPE_HASWORKBOARD) ->setNewValue(1); id(new PhabricatorProjectTransactionEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true) ->applyTransactions($project, $xactions); return id(new AphrontRedirectResponse()) ->setURI($board_uri); } return $this->newDialog() ->setTitle(pht('Workboard Disabled')) ->addHiddenInput('initialize', 1) ->appendParagraph( pht( 'This workboard has been disabled, but can be restored to its '. 'former glory.')) ->addCancelButton($profile_uri) ->addSubmitButton(pht('Enable Workboard')); } private function buildDisabledContent(PhabricatorProject $project) { $viewer = $this->getViewer(); $id = $project->getID(); $profile_uri = $this->getApplicationURI("profile/{$id}/"); return $this->newDialog() ->setTitle(pht('Workboard Disabled')) ->appendParagraph( pht( 'This workboard has been disabled, and you do not have permission '. 'to enable it. Only users who can edit this project can restore '. 'the workboard.')) ->addCancelButton($profile_uri); } } diff --git a/src/applications/project/controller/PhabricatorProjectController.php b/src/applications/project/controller/PhabricatorProjectController.php index 8da16f923b..45e2f193af 100644 --- a/src/applications/project/controller/PhabricatorProjectController.php +++ b/src/applications/project/controller/PhabricatorProjectController.php @@ -1,168 +1,169 @@ project = $project; return $this; } protected function getProject() { return $this->project; } protected function loadProject() { $viewer = $this->getViewer(); $request = $this->getRequest(); $id = nonempty( $request->getURIData('projectID'), $request->getURIData('id')); $slug = $request->getURIData('slug'); if ($slug) { $normal_slug = PhabricatorSlug::normalizeProjectSlug($slug); $is_abnormal = ($slug !== $normal_slug); $normal_uri = "/tag/{$normal_slug}/"; } else { $is_abnormal = false; } $query = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->needMembers(true) ->needWatchers(true) ->needImages(true) ->needSlugs(true); if ($slug) { $query->withSlugs(array($slug)); } else { $query->withIDs(array($id)); } $policy_exception = null; try { $project = $query->executeOne(); } catch (PhabricatorPolicyException $ex) { $policy_exception = $ex; $project = null; } if (!$project) { // This project legitimately does not exist, so just 404 the user. if (!$policy_exception) { return new Aphront404Response(); } // Here, the project exists but the user can't see it. If they are // using a non-canonical slug to view the project, redirect to the // canonical slug. If they're already using the canonical slug, rethrow // the exception to give them the policy error. if ($is_abnormal) { return id(new AphrontRedirectResponse())->setURI($normal_uri); } else { throw $policy_exception; } } // The user can view the project, but is using a noncanonical slug. // Redirect to the canonical slug. $primary_slug = $project->getPrimarySlug(); if ($slug && ($slug !== $primary_slug)) { $primary_uri = "/tag/{$primary_slug}/"; return id(new AphrontRedirectResponse())->setURI($primary_uri); } $this->setProject($project); return null; } public function buildApplicationMenu() { $menu = $this->newApplicationMenu(); $profile_menu = $this->getProfileMenu(); if ($profile_menu) { $menu->setProfileMenu($profile_menu); } $menu->setSearchEngine(new PhabricatorProjectSearchEngine()); return $menu; } protected function getProfileMenu() { if (!$this->profileMenu) { - $engine = $this->getProfilePanelEngine(); + $engine = $this->getProfileMenuEngine(); if ($engine) { $this->profileMenu = $engine->buildNavigation(); } } return $this->profileMenu; } protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); $project = $this->getProject(); if ($project) { $ancestors = $project->getAncestorProjects(); $ancestors = array_reverse($ancestors); $ancestors[] = $project; foreach ($ancestors as $ancestor) { $crumbs->addTextCrumb( $ancestor->getName(), $ancestor->getProfileURI() ); } } return $crumbs; } - protected function getProfilePanelEngine() { - if (!$this->profilePanelEngine) { + protected function getProfileMenuEngine() { + if (!$this->profileMenuEngine) { $viewer = $this->getViewer(); $project = $this->getProject(); if ($project) { - $engine = id(new PhabricatorProjectProfilePanelEngine()) + $engine = id(new PhabricatorProjectProfileMenuEngine()) ->setViewer($viewer) ->setController($this) ->setProfileObject($project); - $this->profilePanelEngine = $engine; + $this->profileMenuEngine = $engine; } } - return $this->profilePanelEngine; + + return $this->profileMenuEngine; } - protected function setProfilePanelEngine( - PhabricatorProjectProfilePanelEngine $engine) { - $this->profilePanelEngine = $engine; + protected function setProfileMenuEngine( + PhabricatorProjectProfileMenuEngine $engine) { + $this->profileMenuEngine = $engine; return $this; } protected function newCardResponse($board_phid, $object_phid) { $viewer = $this->getViewer(); $request = $this->getRequest(); $visible_phids = $request->getStrList('visiblePHIDs'); if (!$visible_phids) { $visible_phids = array(); } return id(new PhabricatorBoardResponseEngine()) ->setViewer($viewer) ->setBoardPHID($board_phid) ->setObjectPHID($object_phid) ->setVisiblePHIDs($visible_phids) ->buildResponse(); } } diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php index 34a2c1b00e..4352ec6ad8 100644 --- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php +++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php @@ -1,334 +1,334 @@ getViewer(); $id = $request->getURIData('id'); $project = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needImages(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$project) { return new Aphront404Response(); } $this->setProject($project); $edit_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); $view_uri = $this->getApplicationURI('profile/'.$project->getID().'/'); $supported_formats = PhabricatorFile::getTransformableImageFormats(); $e_file = true; $errors = array(); if ($request->isFormPost()) { $phid = $request->getStr('phid'); $is_default = false; if ($phid == PhabricatorPHIDConstants::PHID_VOID) { $phid = null; $is_default = true; } else if ($phid) { $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); } else { if ($request->getFileExists('picture')) { $file = PhabricatorFile::newFromPHPUpload( $_FILES['picture'], array( 'authorPHID' => $viewer->getPHID(), 'canCDN' => true, )); } else { $e_file = pht('Required'); $errors[] = pht( 'You must choose a file when uploading a new project picture.'); } } if (!$errors && !$is_default) { if (!$file->isTransformableImage()) { $e_file = pht('Not Supported'); $errors[] = pht( 'This server only supports these image formats: %s.', implode(', ', $supported_formats)); } else { $xform = PhabricatorFileTransform::getTransformByKey( PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE); $xformed = $xform->executeTransform($file); } } if (!$errors) { if ($is_default) { $new_value = null; } else { $new_value = $xformed->getPHID(); } $xactions = array(); $xactions[] = id(new PhabricatorProjectTransaction()) ->setTransactionType(PhabricatorProjectTransaction::TYPE_IMAGE) ->setNewValue($new_value); $editor = id(new PhabricatorProjectTransactionEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true); $editor->applyTransactions($project, $xactions); return id(new AphrontRedirectResponse())->setURI($edit_uri); } } $title = pht('Edit Project Picture'); $form = id(new PHUIFormLayoutView()) ->setUser($viewer); $default_image = PhabricatorFile::loadBuiltin($viewer, 'project.png'); $images = array(); $current = $project->getProfileImagePHID(); $has_current = false; if ($current) { $files = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($current)) ->execute(); if ($files) { $file = head($files); if ($file->isTransformableImage()) { $has_current = true; $images[$current] = array( 'uri' => $file->getBestURI(), 'tip' => pht('Current Picture'), ); } } } $images[PhabricatorPHIDConstants::PHID_VOID] = array( 'uri' => $default_image->getBestURI(), 'tip' => pht('No Picture'), ); require_celerity_resource('people-profile-css'); Javelin::initBehavior('phabricator-tooltips', array()); $buttons = array(); foreach ($images as $phid => $spec) { $button = javelin_tag( 'button', array( 'class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $spec['tip'], 'size' => 300, ), ), phutil_tag( 'img', array( 'height' => 50, 'width' => 50, 'src' => $spec['uri'], ))); $button = array( phutil_tag( 'input', array( 'type' => 'hidden', 'name' => 'phid', 'value' => $phid, )), $button, ); $button = phabricator_form( $viewer, array( 'class' => 'profile-image-form', 'method' => 'POST', ), $button); $buttons[] = $button; } if ($has_current) { $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Current Picture')) ->setValue(array_shift($buttons))); } $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Use Picture')) ->setValue( array( $this->renderDefaultForm($project), $buttons, ))); $launch_id = celerity_generate_unique_node_id(); $input_id = celerity_generate_unique_node_id(); Javelin::initBehavior( 'launch-icon-composer', array( 'launchID' => $launch_id, 'inputID' => $input_id, )); $compose_button = javelin_tag( 'button', array( 'class' => 'grey', 'id' => $launch_id, 'sigil' => 'icon-composer', ), pht('Choose Icon and Color...')); $compose_input = javelin_tag( 'input', array( 'type' => 'hidden', 'id' => $input_id, 'name' => 'phid', )); $compose_form = phabricator_form( $viewer, array( 'class' => 'profile-image-form', 'method' => 'POST', ), array( $compose_input, $compose_button, )); $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Quick Create')) ->setValue($compose_form)); $upload_form = id(new AphrontFormView()) ->setUser($viewer) ->setEncType('multipart/form-data') ->appendChild( id(new AphrontFormFileControl()) ->setName('picture') ->setLabel(pht('Upload Picture')) ->setError($e_file) ->setCaption( pht('Supported formats: %s', implode(', ', $supported_formats)))) ->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($edit_uri) ->setValue(pht('Upload Picture'))); $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setFormErrors($errors) ->setForm($form); $upload_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Upload New Picture')) ->setForm($upload_form); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MANAGE); + $nav->selectFilter(PhabricatorProject::ITEM_MANAGE); return $this->newPage() ->setTitle($title) ->setNavigation($nav) ->appendChild( array( $form_box, $upload_box, )); } private function renderDefaultForm(PhabricatorProject $project) { $viewer = $this->getViewer(); $compose_color = $project->getDisplayIconComposeColor(); $compose_icon = $project->getDisplayIconComposeIcon(); $default_builtin = id(new PhabricatorFilesComposeIconBuiltinFile()) ->setColor($compose_color) ->setIcon($compose_icon); $file_builtins = PhabricatorFile::loadBuiltins( $viewer, array($default_builtin)); $file_builtin = head($file_builtins); $default_button = javelin_tag( 'button', array( 'class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => pht('Use Icon and Color'), 'size' => 300, ), ), phutil_tag( 'img', array( 'height' => 50, 'width' => 50, 'src' => $file_builtin->getBestURI(), ))); $inputs = array( 'projectPHID' => $project->getPHID(), 'icon' => $compose_icon, 'color' => $compose_color, ); foreach ($inputs as $key => $value) { $inputs[$key] = javelin_tag( 'input', array( 'type' => 'hidden', 'name' => $key, 'value' => $value, )); } $default_form = phabricator_form( $viewer, array( 'class' => 'profile-image-form', 'method' => 'POST', 'action' => '/file/compose/', ), array( $inputs, $default_button, )); return $default_form; } } diff --git a/src/applications/project/controller/PhabricatorProjectManageController.php b/src/applications/project/controller/PhabricatorProjectManageController.php index c827f5abab..6ecdf6f62c 100644 --- a/src/applications/project/controller/PhabricatorProjectManageController.php +++ b/src/applications/project/controller/PhabricatorProjectManageController.php @@ -1,148 +1,148 @@ loadProject(); if ($response) { return $response; } $viewer = $request->getUser(); $project = $this->getProject(); $id = $project->getID(); $picture = $project->getProfileImageURI(); $header = id(new PHUIHeaderView()) ->setHeader(pht('Project History')) ->setUser($viewer) ->setPolicyObject($project) ->setImage($picture); if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) { $header->setStatus('fa-check', 'bluegrey', pht('Active')); } else { $header->setStatus('fa-ban', 'red', pht('Archived')); } $curtain = $this->buildCurtain($project); $properties = $this->buildPropertyListView($project); $timeline = $this->buildTransactionTimeline( $project, new PhabricatorProjectTransactionQuery()); $timeline->setShouldTerminate(true); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MANAGE); + $nav->selectFilter(PhabricatorProject::ITEM_MANAGE); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Manage')); $crumbs->setBorder(true); $manage = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->addPropertySection(pht('Details'), $properties) ->setMainColumn( array( $timeline, )); return $this->newPage() ->setNavigation($nav) ->setCrumbs($crumbs) ->setTitle( array( $project->getDisplayName(), pht('Manage'), )) ->appendChild( array( $manage, )); } private function buildCurtain(PhabricatorProject $project) { $viewer = $this->getViewer(); $id = $project->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $curtain = $this->newCurtainView($project); $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Details')) ->setIcon('fa-pencil') ->setHref($this->getApplicationURI("edit/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Menu')) ->setIcon('fa-th-list') - ->setHref($this->getApplicationURI("{$id}/panel/configure/")) + ->setHref($this->getApplicationURI("{$id}/item/configure/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Picture')) ->setIcon('fa-picture-o') ->setHref($this->getApplicationURI("picture/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); if ($project->isArchived()) { $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Activate Project')) ->setIcon('fa-check') ->setHref($this->getApplicationURI("archive/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); } else { $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Archive Project')) ->setIcon('fa-ban') ->setHref($this->getApplicationURI("archive/{$id}/")) ->setDisabled(!$can_edit) ->setWorkflow(true)); } return $curtain; } private function buildPropertyListView( PhabricatorProject $project) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $view->addProperty( pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true)); $field_list = PhabricatorCustomField::getObjectFields( $project, PhabricatorCustomField::ROLE_VIEW); $field_list->appendFieldsToPropertyList($project, $viewer, $view); return $view; } } diff --git a/src/applications/project/controller/PhabricatorProjectMembersViewController.php b/src/applications/project/controller/PhabricatorProjectMembersViewController.php index e98412ff31..959927c9f3 100644 --- a/src/applications/project/controller/PhabricatorProjectMembersViewController.php +++ b/src/applications/project/controller/PhabricatorProjectMembersViewController.php @@ -1,294 +1,294 @@ getViewer(); $id = $request->getURIData('id'); $project = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needMembers(true) ->needWatchers(true) ->needImages(true) ->executeOne(); if (!$project) { return new Aphront404Response(); } $this->setProject($project); $title = pht('Members and Watchers'); $properties = $this->buildProperties($project); $curtain = $this->buildCurtainView($project); $object_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Details')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addPropertyList($properties); $member_list = id(new PhabricatorProjectMemberListView()) ->setUser($viewer) ->setProject($project) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setUserPHIDs($project->getMemberPHIDs()); $watcher_list = id(new PhabricatorProjectWatcherListView()) ->setUser($viewer) ->setProject($project) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_MEMBERS); + $nav->selectFilter(PhabricatorProject::ITEM_MEMBERS); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Members')); $crumbs->setBorder(true); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon('fa-group'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->setMainColumn(array( $object_box, $member_list, $watcher_list, )); return $this->newPage() ->setNavigation($nav) ->setCrumbs($crumbs) ->setTitle(array($project->getName(), $title)) ->appendChild($view); } private function buildProperties(PhabricatorProject $project) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($project); if ($project->isMilestone()) { $icon_key = PhabricatorProjectIconSet::getMilestoneIconKey(); $icon = PhabricatorProjectIconSet::getIconIcon($icon_key); $target = PhabricatorProjectIconSet::getIconName($icon_key); $note = pht( 'Members of the parent project are members of this project.'); $show_join = false; } else if ($project->getHasSubprojects()) { $icon = 'fa-sitemap'; $target = pht('Parent Project'); $note = pht( 'Members of all subprojects are members of this project.'); $show_join = false; } else if ($project->getIsMembershipLocked()) { $icon = 'fa-lock'; $target = pht('Locked Project'); $note = pht( 'Users with access may join this project, but may not leave.'); $show_join = true; } else { $icon = 'fa-briefcase'; $target = pht('Normal Project'); $note = pht('Users with access may join and leave this project.'); $show_join = true; } $item = id(new PHUIStatusItemView()) ->setIcon($icon) ->setTarget(phutil_tag('strong', array(), $target)) ->setNote($note); $status = id(new PHUIStatusListView()) ->addItem($item); $view->addProperty(pht('Membership'), $status); if ($show_join) { $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( $viewer, $project); $view->addProperty( pht('Joinable By'), $descriptions[PhabricatorPolicyCapability::CAN_JOIN]); } $viewer_phid = $viewer->getPHID(); if ($project->isUserWatcher($viewer_phid)) { $watch_item = id(new PHUIStatusItemView()) ->setIcon('fa-eye green') ->setTarget(phutil_tag('strong', array(), pht('Watching'))) ->setNote( pht( 'You will receive mail about changes made to any related '. 'object.')); $watch_status = id(new PHUIStatusListView()) ->addItem($watch_item); $view->addProperty(pht('Watching'), $watch_status); } if ($project->isUserMember($viewer_phid)) { $is_silenced = $this->isProjectSilenced($project); if ($is_silenced) { $mail_icon = 'fa-envelope-o grey'; $mail_target = pht('Disabled'); $mail_note = pht( 'When mail is sent to project members, you will not receive '. 'a copy.'); } else { $mail_icon = 'fa-envelope-o green'; $mail_target = pht('Enabled'); $mail_note = pht( 'You will receive mail that is sent to project members.'); } $mail_item = id(new PHUIStatusItemView()) ->setIcon($mail_icon) ->setTarget(phutil_tag('strong', array(), $mail_target)) ->setNote($mail_note); $mail_status = id(new PHUIStatusListView()) ->addItem($mail_item); $view->addProperty(pht('Mail to Members'), $mail_status); } return $view; } private function buildCurtainView(PhabricatorProject $project) { $viewer = $this->getViewer(); $id = $project->getID(); $curtain = $this->newCurtainView($project); $is_locked = $project->getIsMembershipLocked(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $supports_edit = $project->supportsEditMembers(); $can_join = $supports_edit && PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_JOIN); $can_leave = $supports_edit && (!$is_locked || $can_edit); $viewer_phid = $viewer->getPHID(); if (!$project->isUserMember($viewer_phid)) { $curtain->addAction( id(new PhabricatorActionView()) ->setHref('/project/update/'.$project->getID().'/join/') ->setIcon('fa-plus') ->setDisabled(!$can_join) ->setWorkflow(true) ->setName(pht('Join Project'))); } else { $curtain->addAction( id(new PhabricatorActionView()) ->setHref('/project/update/'.$project->getID().'/leave/') ->setIcon('fa-times') ->setDisabled(!$can_leave) ->setWorkflow(true) ->setName(pht('Leave Project'))); } if (!$project->isUserWatcher($viewer->getPHID())) { $curtain->addAction( id(new PhabricatorActionView()) ->setWorkflow(true) ->setHref('/project/watch/'.$project->getID().'/') ->setIcon('fa-eye') ->setName(pht('Watch Project'))); } else { $curtain->addAction( id(new PhabricatorActionView()) ->setWorkflow(true) ->setHref('/project/unwatch/'.$project->getID().'/') ->setIcon('fa-eye-slash') ->setName(pht('Unwatch Project'))); } $can_silence = $project->isUserMember($viewer_phid); $is_silenced = $this->isProjectSilenced($project); if ($is_silenced) { $silence_text = pht('Enable Mail'); } else { $silence_text = pht('Disable Mail'); } $curtain->addAction( id(new PhabricatorActionView()) ->setName($silence_text) ->setIcon('fa-envelope-o') ->setHref("/project/silence/{$id}/") ->setWorkflow(true) ->setDisabled(!$can_silence)); $can_add = $can_edit && $supports_edit; $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Add Members')) ->setIcon('fa-user-plus') ->setHref("/project/members/{$id}/add/") ->setWorkflow(true) ->setDisabled(!$can_add)); $can_lock = $can_edit && $supports_edit && $this->hasApplicationCapability( ProjectCanLockProjectsCapability::CAPABILITY); if ($is_locked) { $lock_name = pht('Unlock Project'); $lock_icon = 'fa-unlock'; } else { $lock_name = pht('Lock Project'); $lock_icon = 'fa-lock'; } $curtain->addAction( id(new PhabricatorActionView()) ->setName($lock_name) ->setIcon($lock_icon) ->setHref($this->getApplicationURI("lock/{$id}/")) ->setDisabled(!$can_lock) ->setWorkflow(true)); return $curtain; } private function isProjectSilenced(PhabricatorProject $project) { $viewer = $this->getViewer(); $viewer_phid = $viewer->getPHID(); if (!$viewer_phid) { return false; } $edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST; $silenced = PhabricatorEdgeQuery::loadDestinationPHIDs( $project->getPHID(), $edge_type); $silenced = array_fuse($silenced); return isset($silenced[$viewer_phid]); } } diff --git a/src/applications/project/controller/PhabricatorProjectPanelController.php b/src/applications/project/controller/PhabricatorProjectMenuItemController.php similarity index 71% rename from src/applications/project/controller/PhabricatorProjectPanelController.php rename to src/applications/project/controller/PhabricatorProjectMenuItemController.php index d20b5b9828..bd615c3f8e 100644 --- a/src/applications/project/controller/PhabricatorProjectPanelController.php +++ b/src/applications/project/controller/PhabricatorProjectMenuItemController.php @@ -1,24 +1,24 @@ loadProject(); if ($response) { return $response; } $viewer = $this->getViewer(); $project = $this->getProject(); - $engine = id(new PhabricatorProjectProfilePanelEngine()) + $engine = id(new PhabricatorProjectProfileMenuEngine()) ->setProfileObject($project) ->setController($this); - $this->setProfilePanelEngine($engine); + $this->setProfileMenuEngine($engine); return $engine->buildResponse(); } } diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index c9f3c2b9d3..ca9732b6f1 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -1,294 +1,294 @@ loadProject(); if ($response) { return $response; } $viewer = $request->getUser(); $project = $this->getProject(); $id = $project->getID(); $picture = $project->getProfileImageURI(); $icon = $project->getDisplayIconIcon(); $icon_name = $project->getDisplayIconName(); $tag = id(new PHUITagView()) ->setIcon($icon) ->setName($icon_name) ->addClass('project-view-header-tag') ->setType(PHUITagView::TYPE_SHADE); $header = id(new PHUIHeaderView()) ->setHeader(array($project->getDisplayName(), $tag)) ->setUser($viewer) ->setPolicyObject($project) ->setImage($picture) ->setProfileHeader(true); if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ACTIVE) { $header->setStatus('fa-check', 'bluegrey', pht('Active')); } else { $header->setStatus('fa-ban', 'red', pht('Archived')); } $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); if ($can_edit) { $header->setImageEditURL($this->getApplicationURI("picture/{$id}/")); } $properties = $this->buildPropertyListView($project); $watch_action = $this->renderWatchAction($project); $header->addActionLink($watch_action); $milestone_list = $this->buildMilestoneList($project); $subproject_list = $this->buildSubprojectList($project); $member_list = id(new PhabricatorProjectMemberListView()) ->setUser($viewer) ->setProject($project) ->setLimit(5) ->setBackground(PHUIObjectBoxView::GREY) ->setUserPHIDs($project->getMemberPHIDs()); $watcher_list = id(new PhabricatorProjectWatcherListView()) ->setUser($viewer) ->setProject($project) ->setLimit(5) ->setBackground(PHUIObjectBoxView::GREY) ->setUserPHIDs($project->getWatcherPHIDs()); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_PROFILE); + $nav->selectFilter(PhabricatorProject::ITEM_PROFILE); $stories = id(new PhabricatorFeedQuery()) ->setViewer($viewer) ->setFilterPHIDs( array( $project->getPHID(), )) ->setLimit(50) ->execute(); $feed = $this->renderStories($stories); $feed = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Recent Activity')) ->addClass('project-view-feed') ->appendChild($feed); require_celerity_resource('project-view-css'); $home = id(new PHUITwoColumnView()) ->setHeader($header) ->addClass('project-view-home') ->setMainColumn( array( $properties, $feed, )) ->setSideColumn( array( $milestone_list, $subproject_list, $member_list, $watcher_list, )); $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); return $this->newPage() ->setNavigation($nav) ->setCrumbs($crumbs) ->setTitle($project->getDisplayName()) ->setPageObjectPHIDs(array($project->getPHID())) ->appendChild( array( $home, )); } private function buildPropertyListView( PhabricatorProject $project) { $request = $this->getRequest(); $viewer = $request->getUser(); $view = id(new PHUIPropertyListView()) ->setUser($viewer) ->setObject($project); $field_list = PhabricatorCustomField::getObjectFields( $project, PhabricatorCustomField::ROLE_VIEW); $field_list->appendFieldsToPropertyList($project, $viewer, $view); if (!$view->hasAnyProperties()) { return null; } $view = id(new PHUIObjectBoxView()) ->appendChild($view) ->addClass('project-view-properties'); return $view; } private function renderStories(array $stories) { assert_instances_of($stories, 'PhabricatorFeedStory'); $builder = new PhabricatorFeedBuilder($stories); $builder->setUser($this->getRequest()->getUser()); $builder->setShowHovercards(true); $view = $builder->buildView(); return $view; } private function renderWatchAction(PhabricatorProject $project) { $viewer = $this->getViewer(); $id = $project->getID(); if (!$viewer->isLoggedIn()) { $is_watcher = false; $is_ancestor = false; } else { $viewer_phid = $viewer->getPHID(); $is_watcher = $project->isUserWatcher($viewer_phid); $is_ancestor = $project->isUserAncestorWatcher($viewer_phid); } if ($is_ancestor && !$is_watcher) { $watch_icon = 'fa-eye'; $watch_text = pht('Watching Ancestor'); $watch_href = "/project/watch/{$id}/?via=profile"; $watch_disabled = true; } else if (!$is_watcher) { $watch_icon = 'fa-eye'; $watch_text = pht('Watch Project'); $watch_href = "/project/watch/{$id}/?via=profile"; $watch_disabled = false; } else { $watch_icon = 'fa-eye-slash'; $watch_text = pht('Unwatch Project'); $watch_href = "/project/unwatch/{$id}/?via=profile"; $watch_disabled = false; } $watch_icon = id(new PHUIIconView()) ->setIcon($watch_icon); return id(new PHUIButtonView()) ->setTag('a') ->setWorkflow(true) ->setIcon($watch_icon) ->setText($watch_text) ->setHref($watch_href) ->setDisabled($watch_disabled); } private function buildMilestoneList(PhabricatorProject $project) { if (!$project->getHasMilestones()) { return null; } $viewer = $this->getViewer(); $id = $project->getID(); $milestones = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withParentProjectPHIDs(array($project->getPHID())) ->needImages(true) ->withIsMilestone(true) ->withStatuses( array( PhabricatorProjectStatus::STATUS_ACTIVE, )) ->setOrderVector(array('milestoneNumber', 'id')) ->execute(); if (!$milestones) { return null; } $milestone_list = id(new PhabricatorProjectListView()) ->setUser($viewer) ->setProjects($milestones) ->renderList(); $view_all = id(new PHUIButtonView()) ->setTag('a') ->setIcon( id(new PHUIIconView()) ->setIcon('fa-list-ul')) ->setText(pht('View All')) ->setHref("/project/subprojects/{$id}/"); $header = id(new PHUIHeaderView()) ->setHeader(pht('Milestones')) ->addActionLink($view_all); return id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::GREY) ->setObjectList($milestone_list); } private function buildSubprojectList(PhabricatorProject $project) { if (!$project->getHasSubprojects()) { return null; } $viewer = $this->getViewer(); $id = $project->getID(); $limit = 25; $subprojects = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withParentProjectPHIDs(array($project->getPHID())) ->needImages(true) ->withStatuses( array( PhabricatorProjectStatus::STATUS_ACTIVE, )) ->withIsMilestone(false) ->setLimit($limit) ->execute(); if (!$subprojects) { return null; } $subproject_list = id(new PhabricatorProjectListView()) ->setUser($viewer) ->setProjects($subprojects) ->renderList(); $view_all = id(new PHUIButtonView()) ->setTag('a') ->setIcon( id(new PHUIIconView()) ->setIcon('fa-list-ul')) ->setText(pht('View All')) ->setHref("/project/subprojects/{$id}/"); $header = id(new PHUIHeaderView()) ->setHeader(pht('Subprojects')) ->addActionLink($view_all); return id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::GREY) ->setObjectList($subproject_list); } } diff --git a/src/applications/project/controller/PhabricatorProjectSubprojectsController.php b/src/applications/project/controller/PhabricatorProjectSubprojectsController.php index 1232d4010e..4a89bb4cde 100644 --- a/src/applications/project/controller/PhabricatorProjectSubprojectsController.php +++ b/src/applications/project/controller/PhabricatorProjectSubprojectsController.php @@ -1,262 +1,262 @@ getViewer(); $response = $this->loadProject(); if ($response) { return $response; } $project = $this->getProject(); $id = $project->getID(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $allows_subprojects = $project->supportsSubprojects(); $allows_milestones = $project->supportsMilestones(); if ($allows_subprojects) { $subprojects = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withParentProjectPHIDs(array($project->getPHID())) ->needImages(true) ->withIsMilestone(false) ->execute(); } else { $subprojects = array(); } if ($allows_milestones) { $milestones = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withParentProjectPHIDs(array($project->getPHID())) ->needImages(true) ->withIsMilestone(true) ->setOrderVector(array('milestoneNumber', 'id')) ->execute(); } else { $milestones = array(); } if ($milestones) { $milestone_list = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Milestones')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList( id(new PhabricatorProjectListView()) ->setUser($viewer) ->setProjects($milestones) ->renderList()); } else { $milestone_list = null; } if ($subprojects) { $subproject_list = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Subprojects')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList( id(new PhabricatorProjectListView()) ->setUser($viewer) ->setProjects($subprojects) ->renderList()); } else { $subproject_list = null; } $property_list = $this->buildPropertyList( $project, $milestones, $subprojects); $curtain = $this->buildCurtainView( $project, $milestones, $subprojects); $details = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Details')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addPropertyList($property_list); $nav = $this->getProfileMenu(); - $nav->selectFilter(PhabricatorProject::PANEL_SUBPROJECTS); + $nav->selectFilter(PhabricatorProject::ITEM_SUBPROJECTS); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Subprojects')); $crumbs->setBorder(true); $header = id(new PHUIHeaderView()) ->setHeader(pht('Subprojects and Milestones')) ->setHeaderIcon('fa-sitemap'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->setMainColumn(array( $details, $milestone_list, $subproject_list, )); return $this->newPage() ->setNavigation($nav) ->setCrumbs($crumbs) ->setTitle(array($project->getName(), pht('Subprojects'))) ->appendChild($view); } private function buildPropertyList( PhabricatorProject $project, array $milestones, array $subprojects) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $view->addProperty( pht('Prototype'), $this->renderStatus( 'fa-exclamation-triangle red', pht('Warning'), pht('Subprojects and milestones are only partially implemented.'))); if (!$project->supportsMilestones()) { $milestone_status = $this->renderStatus( 'fa-times grey', pht('Already Milestone'), pht( 'This project is already a milestone, and milestones may not '. 'have their own milestones.')); } else { if (!$milestones) { $milestone_status = $this->renderStatus( 'fa-check grey', pht('None Created'), pht( 'You can create milestones for this project.')); } else { $milestone_status = $this->renderStatus( 'fa-check green', pht('Has Milestones'), pht('This project has milestones.')); } } $view->addProperty(pht('Milestones'), $milestone_status); if (!$project->supportsSubprojects()) { $subproject_status = $this->renderStatus( 'fa-times grey', pht('Milestone'), pht( 'This project is a milestone, and milestones may not have '. 'subprojects.')); } else { if (!$subprojects) { $subproject_status = $this->renderStatus( 'fa-check grey', pht('None Created'), pht('You can create subprojects for this project.')); } else { $subproject_status = $this->renderStatus( 'fa-check green', pht('Has Subprojects'), pht( 'This project has subprojects.')); } } $view->addProperty(pht('Subprojects'), $subproject_status); return $view; } private function buildCurtainView( PhabricatorProject $project, array $milestones, array $subprojects) { $viewer = $this->getViewer(); $id = $project->getID(); $can_create = $this->hasApplicationCapability( ProjectCreateProjectsCapability::CAPABILITY); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $project, PhabricatorPolicyCapability::CAN_EDIT); $allows_milestones = $project->supportsMilestones(); $allows_subprojects = $project->supportsSubprojects(); $curtain = $this->newCurtainView($project); if ($allows_milestones && $milestones) { $milestone_text = pht('Create Next Milestone'); } else { $milestone_text = pht('Create Milestone'); } $can_milestone = ($can_create && $can_edit && $allows_milestones); $milestone_href = "/project/edit/?milestone={$id}"; $curtain->addAction( id(new PhabricatorActionView()) ->setName($milestone_text) ->setIcon('fa-plus') ->setHref($milestone_href) ->setDisabled(!$can_milestone) ->setWorkflow(!$can_milestone)); $can_subproject = ($can_create && $can_edit && $allows_subprojects); // If we're offering to create the first subproject, we're going to warn // the user about the effects before moving forward. if ($can_subproject && !$subprojects) { $subproject_href = "/project/warning/{$id}/"; $subproject_disabled = false; $subproject_workflow = true; } else { $subproject_href = "/project/edit/?parent={$id}"; $subproject_disabled = !$can_subproject; $subproject_workflow = !$can_subproject; } $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Create Subproject')) ->setIcon('fa-plus') ->setHref($subproject_href) ->setDisabled($subproject_disabled) ->setWorkflow($subproject_workflow)); return $curtain; } private function renderStatus($icon, $target, $note) { $item = id(new PHUIStatusItemView()) ->setIcon($icon) ->setTarget(phutil_tag('strong', array(), $target)) ->setNote($note); return id(new PHUIStatusListView()) ->addItem($item); } } diff --git a/src/applications/project/controller/PhabricatorProjectViewController.php b/src/applications/project/controller/PhabricatorProjectViewController.php index 412565c056..d2f8d4f58d 100644 --- a/src/applications/project/controller/PhabricatorProjectViewController.php +++ b/src/applications/project/controller/PhabricatorProjectViewController.php @@ -1,36 +1,36 @@ getRequest(); $viewer = $request->getViewer(); $response = $this->loadProject(); if ($response) { return $response; } $project = $this->getProject(); - $engine = $this->getProfilePanelEngine(); - $default = $engine->getDefaultPanel(); + $engine = $this->getProfileMenuEngine(); + $default = $engine->getDefaultItem(); switch ($default->getBuiltinKey()) { - case PhabricatorProject::PANEL_WORKBOARD: + case PhabricatorProject::ITEM_WORKBOARD: $controller_object = new PhabricatorProjectBoardViewController(); break; - case PhabricatorProject::PANEL_PROFILE: + case PhabricatorProject::ITEM_PROFILE: default: $controller_object = new PhabricatorProjectProfileController(); break; } return $this->delegateToController($controller_object); } } diff --git a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php new file mode 100644 index 0000000000..d3ea39e1e2 --- /dev/null +++ b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php @@ -0,0 +1,47 @@ +getProfileObject(); + $id = $project->getID(); + return "/project/{$id}/item/{$path}"; + } + + protected function getBuiltinProfileItems($object) { + $items = array(); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_PROFILE) + ->setMenuItemKey(PhabricatorProjectDetailsProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_POINTS) + ->setMenuItemKey(PhabricatorProjectPointsProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_WORKBOARD) + ->setMenuItemKey(PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_MEMBERS) + ->setMenuItemKey(PhabricatorProjectMembersProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_SUBPROJECTS) + ->setMenuItemKey( + PhabricatorProjectSubprojectsProfileMenuItem::MENUITEMKEY); + + $items[] = $this->newItem() + ->setBuiltinKey(PhabricatorProject::ITEM_MANAGE) + ->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY); + + return $items; + } + +} diff --git a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php b/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php deleted file mode 100644 index 3a34b6c80c..0000000000 --- a/src/applications/project/engine/PhabricatorProjectProfilePanelEngine.php +++ /dev/null @@ -1,46 +0,0 @@ -getProfileObject(); - $id = $project->getID(); - return "/project/{$id}/panel/{$path}"; - } - - protected function getBuiltinProfilePanels($object) { - $panels = array(); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_PROFILE) - ->setPanelKey(PhabricatorProjectDetailsProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_POINTS) - ->setPanelKey(PhabricatorProjectPointsProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_WORKBOARD) - ->setPanelKey(PhabricatorProjectWorkboardProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_MEMBERS) - ->setPanelKey(PhabricatorProjectMembersProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_SUBPROJECTS) - ->setPanelKey(PhabricatorProjectSubprojectsProfilePanel::PANELKEY); - - $panels[] = $this->newPanel() - ->setBuiltinKey(PhabricatorProject::PANEL_MANAGE) - ->setPanelKey(PhabricatorProjectManageProfilePanel::PANELKEY); - - return $panels; - } - -} diff --git a/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php b/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php index ce9fbf332c..5daacd315c 100644 --- a/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php +++ b/src/applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php @@ -1,76 +1,80 @@ getPHID(); if ($object_phid) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $object_phid, $project_edge_type); $project_phids = array_reverse($project_phids); } else { $project_phids = array(); } $projects_field = id(new PhabricatorProjectsEditField()) ->setKey('projectPHIDs') ->setLabel(pht('Tags')) ->setEditTypeKey('projects') ->setAliases(array('project', 'projects', 'tag', 'tags')) ->setIsCopyable(true) ->setUseEdgeTransactions(true) ->setCommentActionLabel(pht('Change Project Tags')) ->setCommentActionOrder(8000) ->setDescription(pht('Select project tags for the object.')) ->setTransactionType($edge_type) ->setMetadataValue('edge:type', $project_edge_type) ->setValue($project_phids); $projects_field->setViewer($engine->getViewer()); - $edit_add = $projects_field->getConduitEditType('projects.add') + $edit_add = $projects_field->getConduitEditType(self::EDITKEY_ADD) ->setConduitDescription(pht('Add project tags.')); - $edit_set = $projects_field->getConduitEditType('projects.set') + $edit_set = $projects_field->getConduitEditType(self::EDITKEY_SET) ->setConduitDescription( pht('Set project tags, overwriting current value.')); - $edit_rem = $projects_field->getConduitEditType('projects.remove') + $edit_rem = $projects_field->getConduitEditType(self::EDITKEY_REMOVE) ->setConduitDescription(pht('Remove project tags.')); return array( $projects_field, ); } } diff --git a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php similarity index 64% rename from src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php index 07e6ce4c10..becdd36c16 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectDetailsProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php @@ -1,64 +1,64 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $picture = $project->getProfileImageURI(); $name = $project->getName(); $href = "/project/profile/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setProfileImage($picture); return array( $item, ); } } diff --git a/src/applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php similarity index 60% rename from src/applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php index ae66c4cc3e..1bd7e796dc 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectManageProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php @@ -1,69 +1,69 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $name = $this->getDisplayName($config); $icon = 'fa-gears'; $href = "/project/manage/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php similarity index 65% rename from src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php index b5374416aa..580aacb635 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectMembersProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php @@ -1,59 +1,59 @@ getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $name = $this->getDisplayName($config); $icon = 'fa-group'; $href = "/project/members/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php similarity index 92% rename from src/applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php index 02a2f3984f..020e5626de 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectPointsProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php @@ -1,192 +1,192 @@ getViewer(); // Only render this element for milestones. if (!$object->isMilestone()) { return false; } // Don't show if points aren't configured. if (!ManiphestTaskPoints::getIsEnabled()) { return false; } // Points are only available if Maniphest is installed. $class = 'PhabricatorManiphestApplication'; if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { return false; } return true; } public function getDisplayName( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorInstructionsEditField()) ->setValue( pht( 'This is a progress bar which shows how many points of work '. 'are complete within the milestone. It has no configurable '. 'settings.')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $project = $config->getProfileObject(); $limit = 250; $tasks = id(new ManiphestTaskQuery()) ->setViewer($viewer) ->withEdgeLogicPHIDs( PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, PhabricatorQueryConstraint::OPERATOR_AND, array($project->getPHID())) ->setLimit($limit + 1) ->execute(); if (count($tasks) > $limit) { return $this->renderError( pht( 'Too many tasks to compute statistics for (more than %s).', new PhutilNumber($limit))); } if (!$tasks) { return $this->renderError( pht( 'This milestone has no tasks yet.')); } $statuses = array(); $points_done = 0; $points_total = 0; $no_points = 0; foreach ($tasks as $task) { $points = $task->getPoints(); if ($points === null) { $no_points++; continue; } if (!$points) { continue; } $status = $task->getStatus(); if (empty($statuses[$status])) { $statuses[$status] = 0; } $statuses[$status] += $points; if (ManiphestTaskStatus::isClosedStatus($status)) { $points_done += $points; } $points_total += $points; } if ($no_points == count($tasks)) { return $this->renderError( pht('No tasks have assigned point values.')); } if (!$points_total) { return $this->renderError( pht('All tasks with assigned point values are worth zero points.')); } $label = pht( '%s of %s %s', new PhutilNumber($points_done), new PhutilNumber($points_total), ManiphestTaskPoints::getPointsLabel()); $bar = id(new PHUISegmentBarView()) ->setLabel($label); $map = ManiphestTaskStatus::getTaskStatusMap(); $statuses = array_select_keys($statuses, array_keys($map)); foreach ($statuses as $status => $points) { if (!$points) { continue; } if (!ManiphestTaskStatus::isClosedStatus($status)) { continue; } $color = ManiphestTaskStatus::getStatusColor($status); if (!$color) { $color = 'sky'; } $tooltip = pht( '%s %s', new PhutilNumber($points), ManiphestTaskStatus::getTaskStatusName($status)); $bar->newSegment() ->setWidth($points / $points_total) ->setColor($color) ->setTooltip($tooltip); } $bar = phutil_tag( 'div', array( 'class' => 'phui-profile-segment-bar', ), $bar); $item = $this->newItem() ->appendChild($bar); return array( $item, ); } private function renderError($message) { $message = phutil_tag( 'div', array( 'class' => 'phui-profile-menu-error', ), $message); $item = $this->newItem() ->appendChild($message); return array( $item, ); } } diff --git a/src/applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php similarity index 71% rename from src/applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php index 342c8025aa..dfcb164f45 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectSubprojectsProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php @@ -1,71 +1,71 @@ isMilestone()) { return false; } return true; } public function getDisplayName( - PhabricatorProfilePanelConfiguration $config) { - $name = $config->getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $has_children = ($project->getHasSubprojects()) || ($project->getHasMilestones()); $id = $project->getID(); $name = $this->getDisplayName($config); $icon = 'fa-sitemap'; $href = "/project/subprojects/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setDisabled(!$has_children) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php b/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php similarity index 71% rename from src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php rename to src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php index 8bfeeb4cfe..6305bb4b13 100644 --- a/src/applications/project/profilepanel/PhabricatorProjectWorkboardProfilePanel.php +++ b/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php @@ -1,76 +1,76 @@ getViewer(); // Workboards are only available if Maniphest is installed. $class = 'PhabricatorManiphestApplication'; if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { return false; } return true; } public function getDisplayName( - PhabricatorProfilePanelConfiguration $config) { - $name = $config->getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) - ->setValue($config->getPanelProperty('name')), + ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $has_workboard = $project->getHasWorkboard(); $id = $project->getID(); $href = "/project/board/{$id}/"; $name = $this->getDisplayName($config); $item = $this->newItem() ->setHref($href) ->setName($name) ->setDisabled(!$has_workboard) ->setIcon('fa-columns'); return array( $item, ); } } diff --git a/src/applications/project/storage/PhabricatorProject.php b/src/applications/project/storage/PhabricatorProject.php index 6e4892b32a..47e251f3af 100644 --- a/src/applications/project/storage/PhabricatorProject.php +++ b/src/applications/project/storage/PhabricatorProject.php @@ -1,804 +1,804 @@ setViewer(PhabricatorUser::getOmnipotentUser()) ->withClasses(array('PhabricatorProjectApplication')) ->executeOne(); $view_policy = $app->getPolicy( ProjectDefaultViewCapability::CAPABILITY); $edit_policy = $app->getPolicy( ProjectDefaultEditCapability::CAPABILITY); $join_policy = $app->getPolicy( ProjectDefaultJoinCapability::CAPABILITY); $default_icon = PhabricatorProjectIconSet::getDefaultIconKey(); $default_color = PhabricatorProjectIconSet::getDefaultColorKey(); return id(new PhabricatorProject()) ->setAuthorPHID($actor->getPHID()) ->setIcon($default_icon) ->setColor($default_color) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->setJoinPolicy($join_policy) ->setIsMembershipLocked(0) ->attachMemberPHIDs(array()) ->attachSlugs(array()) ->setHasWorkboard(0) ->setHasMilestones(0) ->setHasSubprojects(0) ->attachParentProject(null); } public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, PhabricatorPolicyCapability::CAN_JOIN, ); } public function getPolicy($capability) { if ($this->isMilestone()) { return $this->getParentProject()->getPolicy($capability); } switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); case PhabricatorPolicyCapability::CAN_JOIN: return $this->getJoinPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { if ($this->isMilestone()) { return $this->getParentProject()->hasAutomaticCapability( $capability, $viewer); } $can_edit = PhabricatorPolicyCapability::CAN_EDIT; switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: if ($this->isUserMember($viewer->getPHID())) { // Project members can always view a project. return true; } break; case PhabricatorPolicyCapability::CAN_EDIT: $parent = $this->getParentProject(); if ($parent) { $can_edit_parent = PhabricatorPolicyFilter::hasCapability( $viewer, $parent, $can_edit); if ($can_edit_parent) { return true; } } break; case PhabricatorPolicyCapability::CAN_JOIN: if (PhabricatorPolicyFilter::hasCapability($viewer, $this, $can_edit)) { // Project editors can always join a project. return true; } break; } return false; } public function describeAutomaticCapability($capability) { // TODO: Clarify the additional rules that parent and subprojects imply. switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return pht('Members of a project can always view it.'); case PhabricatorPolicyCapability::CAN_JOIN: return pht('Users who can edit a project can always join it.'); } return null; } public function getExtendedPolicy($capability, PhabricatorUser $viewer) { $extended = array(); switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: $parent = $this->getParentProject(); if ($parent) { $extended[] = array( $parent, PhabricatorPolicyCapability::CAN_VIEW, ); } break; } return $extended; } public function isUserMember($user_phid) { if ($this->memberPHIDs !== self::ATTACHABLE) { return in_array($user_phid, $this->memberPHIDs); } return $this->assertAttachedKey($this->sparseMembers, $user_phid); } public function setIsUserMember($user_phid, $is_member) { if ($this->sparseMembers === self::ATTACHABLE) { $this->sparseMembers = array(); } $this->sparseMembers[$user_phid] = $is_member; return $this; } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'name' => 'sort128', 'status' => 'text32', 'primarySlug' => 'text128?', 'isMembershipLocked' => 'bool', 'profileImagePHID' => 'phid?', 'icon' => 'text32', 'color' => 'text32', 'mailKey' => 'bytes20', 'joinPolicy' => 'policy', 'parentProjectPHID' => 'phid?', 'hasWorkboard' => 'bool', 'hasMilestones' => 'bool', 'hasSubprojects' => 'bool', 'milestoneNumber' => 'uint32?', 'projectPath' => 'hashpath64', 'projectDepth' => 'uint32', 'projectPathKey' => 'bytes4', ), self::CONFIG_KEY_SCHEMA => array( 'key_icon' => array( 'columns' => array('icon'), ), 'key_color' => array( 'columns' => array('color'), ), 'key_milestone' => array( 'columns' => array('parentProjectPHID', 'milestoneNumber'), 'unique' => true, ), 'key_primaryslug' => array( 'columns' => array('primarySlug'), 'unique' => true, ), 'key_path' => array( 'columns' => array('projectPath', 'projectDepth'), ), 'key_pathkey' => array( 'columns' => array('projectPathKey'), 'unique' => true, ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorProjectProjectPHIDType::TYPECONST); } public function attachMemberPHIDs(array $phids) { $this->memberPHIDs = $phids; return $this; } public function getMemberPHIDs() { return $this->assertAttached($this->memberPHIDs); } public function isArchived() { return ($this->getStatus() == PhabricatorProjectStatus::STATUS_ARCHIVED); } public function getProfileImageURI() { return $this->getProfileImageFile()->getBestURI(); } public function attachProfileImageFile(PhabricatorFile $file) { $this->profileImageFile = $file; return $this; } public function getProfileImageFile() { return $this->assertAttached($this->profileImageFile); } public function isUserWatcher($user_phid) { if ($this->watcherPHIDs !== self::ATTACHABLE) { return in_array($user_phid, $this->watcherPHIDs); } return $this->assertAttachedKey($this->sparseWatchers, $user_phid); } public function isUserAncestorWatcher($user_phid) { $is_watcher = $this->isUserWatcher($user_phid); if (!$is_watcher) { $parent = $this->getParentProject(); if ($parent) { return $parent->isUserWatcher($user_phid); } } return $is_watcher; } public function getWatchedAncestorPHID($user_phid) { if ($this->isUserWatcher($user_phid)) { return $this->getPHID(); } $parent = $this->getParentProject(); if ($parent) { return $parent->getWatchedAncestorPHID($user_phid); } return null; } public function setIsUserWatcher($user_phid, $is_watcher) { if ($this->sparseWatchers === self::ATTACHABLE) { $this->sparseWatchers = array(); } $this->sparseWatchers[$user_phid] = $is_watcher; return $this; } public function attachWatcherPHIDs(array $phids) { $this->watcherPHIDs = $phids; return $this; } public function getWatcherPHIDs() { return $this->assertAttached($this->watcherPHIDs); } public function getAllAncestorWatcherPHIDs() { $parent = $this->getParentProject(); if ($parent) { $watchers = $parent->getAllAncestorWatcherPHIDs(); } else { $watchers = array(); } foreach ($this->getWatcherPHIDs() as $phid) { $watchers[$phid] = $phid; } return $watchers; } public function attachSlugs(array $slugs) { $this->slugs = $slugs; return $this; } public function getSlugs() { return $this->assertAttached($this->slugs); } public function getColor() { if ($this->isArchived()) { return PHUITagView::COLOR_DISABLED; } return $this->color; } public function getURI() { $id = $this->getID(); return "/project/view/{$id}/"; } public function getProfileURI() { $id = $this->getID(); return "/project/profile/{$id}/"; } public function save() { if (!$this->getMailKey()) { $this->setMailKey(Filesystem::readRandomCharacters(20)); } if (!strlen($this->getPHID())) { $this->setPHID($this->generatePHID()); } if (!strlen($this->getProjectPathKey())) { $hash = PhabricatorHash::digestForIndex($this->getPHID()); $hash = substr($hash, 0, 4); $this->setProjectPathKey($hash); } $path = array(); $depth = 0; if ($this->parentProjectPHID) { $parent = $this->getParentProject(); $path[] = $parent->getProjectPath(); $depth = $parent->getProjectDepth() + 1; } $path[] = $this->getProjectPathKey(); $path = implode('', $path); $limit = self::getProjectDepthLimit(); if ($depth >= $limit) { throw new Exception(pht('Project depth is too great.')); } $this->setProjectPath($path); $this->setProjectDepth($depth); $this->openTransaction(); $result = parent::save(); $this->updateDatasourceTokens(); $this->saveTransaction(); return $result; } public static function getProjectDepthLimit() { // This is limited by how many path hashes we can fit in the path // column. return 16; } public function updateDatasourceTokens() { $table = self::TABLE_DATASOURCE_TOKEN; $conn_w = $this->establishConnection('w'); $id = $this->getID(); $slugs = queryfx_all( $conn_w, 'SELECT * FROM %T WHERE projectPHID = %s', id(new PhabricatorProjectSlug())->getTableName(), $this->getPHID()); $all_strings = ipull($slugs, 'slug'); $all_strings[] = $this->getDisplayName(); $all_strings = implode(' ', $all_strings); $tokens = PhabricatorTypeaheadDatasource::tokenizeString($all_strings); $sql = array(); foreach ($tokens as $token) { $sql[] = qsprintf($conn_w, '(%d, %s)', $id, $token); } $this->openTransaction(); queryfx( $conn_w, 'DELETE FROM %T WHERE projectID = %d', $table, $id); foreach (PhabricatorLiskDAO::chunkSQL($sql) as $chunk) { queryfx( $conn_w, 'INSERT INTO %T (projectID, token) VALUES %Q', $table, $chunk); } $this->saveTransaction(); } public function isMilestone() { return ($this->getMilestoneNumber() !== null); } public function getParentProject() { return $this->assertAttached($this->parentProject); } public function attachParentProject(PhabricatorProject $project = null) { $this->parentProject = $project; return $this; } public function getAncestorProjectPaths() { $parts = array(); $path = $this->getProjectPath(); $parent_length = (strlen($path) - 4); for ($ii = $parent_length; $ii > 0; $ii -= 4) { $parts[] = substr($path, 0, $ii); } return $parts; } public function getAncestorProjects() { $ancestors = array(); $cursor = $this->getParentProject(); while ($cursor) { $ancestors[] = $cursor; $cursor = $cursor->getParentProject(); } return $ancestors; } public function supportsEditMembers() { if ($this->isMilestone()) { return false; } if ($this->getHasSubprojects()) { return false; } return true; } public function supportsMilestones() { if ($this->isMilestone()) { return false; } return true; } public function supportsSubprojects() { if ($this->isMilestone()) { return false; } return true; } public function loadNextMilestoneNumber() { $current = queryfx_one( $this->establishConnection('w'), 'SELECT MAX(milestoneNumber) n FROM %T WHERE parentProjectPHID = %s', $this->getTableName(), $this->getPHID()); if (!$current) { $number = 1; } else { $number = (int)$current['n'] + 1; } return $number; } public function getDisplayName() { $name = $this->getName(); // If this is a milestone, show it as "Parent > Sprint 99". if ($this->isMilestone()) { $name = pht( '%s (%s)', $this->getParentProject()->getName(), $name); } return $name; } public function getDisplayIconKey() { if ($this->isMilestone()) { $key = PhabricatorProjectIconSet::getMilestoneIconKey(); } else { $key = $this->getIcon(); } return $key; } public function getDisplayIconIcon() { $key = $this->getDisplayIconKey(); return PhabricatorProjectIconSet::getIconIcon($key); } public function getDisplayIconName() { $key = $this->getDisplayIconKey(); return PhabricatorProjectIconSet::getIconName($key); } public function getDisplayColor() { if ($this->isMilestone()) { return $this->getParentProject()->getColor(); } return $this->getColor(); } public function getDisplayIconComposeIcon() { $icon = $this->getDisplayIconIcon(); return $icon; } public function getDisplayIconComposeColor() { $color = $this->getDisplayColor(); $map = array( 'grey' => 'charcoal', 'checkered' => 'backdrop', ); return idx($map, $color, $color); } public function getProperty($key, $default = null) { return idx($this->properties, $key, $default); } public function setProperty($key, $value) { $this->properties[$key] = $value; return $this; } public function getDefaultWorkboardSort() { return $this->getProperty('workboard.sort.default'); } public function setDefaultWorkboardSort($sort) { return $this->setProperty('workboard.sort.default', $sort); } public function getDefaultWorkboardFilter() { return $this->getProperty('workboard.filter.default'); } public function setDefaultWorkboardFilter($filter) { return $this->setProperty('workboard.filter.default', $filter); } public function getWorkboardBackgroundColor() { return $this->getProperty('workboard.background'); } public function setWorkboardBackgroundColor($color) { return $this->setProperty('workboard.background', $color); } public function getDisplayWorkboardBackgroundColor() { $color = $this->getWorkboardBackgroundColor(); if ($color === null) { $parent = $this->getParentProject(); if ($parent) { return $parent->getDisplayWorkboardBackgroundColor(); } } if ($color === 'none') { $color = null; } return $color; } /* -( PhabricatorCustomFieldInterface )------------------------------------ */ public function getCustomFieldSpecificationForRole($role) { return PhabricatorEnv::getEnvConfig('projects.fields'); } public function getCustomFieldBaseClass() { return 'PhabricatorProjectCustomField'; } public function getCustomFields() { return $this->assertAttached($this->customFields); } public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) { $this->customFields = $fields; return $this; } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorProjectTransactionEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new PhabricatorProjectTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); $this->delete(); $columns = id(new PhabricatorProjectColumn()) ->loadAllWhere('projectPHID = %s', $this->getPHID()); foreach ($columns as $column) { $engine->destroyObject($column); } $slugs = id(new PhabricatorProjectSlug()) ->loadAllWhere('projectPHID = %s', $this->getPHID()); foreach ($slugs as $slug) { $slug->delete(); } $this->saveTransaction(); } /* -( PhabricatorFulltextInterface )--------------------------------------- */ public function newFulltextEngine() { return new PhabricatorProjectFulltextEngine(); } /* -( PhabricatorConduitResultInterface )---------------------------------- */ public function getFieldSpecificationsForConduit() { return array( id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('name') ->setType('string') ->setDescription(pht('The name of the project.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('slug') ->setType('string') ->setDescription(pht('Primary slug/hashtag.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('icon') ->setType('map') ->setDescription(pht('Information about the project icon.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('color') ->setType('map') ->setDescription(pht('Information about the project color.')), ); } public function getFieldValuesForConduit() { $color_key = $this->getColor(); $color_name = PhabricatorProjectIconSet::getColorName($color_key); return array( 'name' => $this->getName(), 'slug' => $this->getPrimarySlug(), 'icon' => array( 'key' => $this->getDisplayIconKey(), 'name' => $this->getDisplayIconName(), 'icon' => $this->getDisplayIconIcon(), ), 'color' => array( 'key' => $color_key, 'name' => $color_name, ), ); } public function getConduitSearchAttachments() { return array( id(new PhabricatorProjectsMembersSearchEngineAttachment()) ->setAttachmentKey('members'), id(new PhabricatorProjectsWatchersSearchEngineAttachment()) ->setAttachmentKey('watchers'), ); } /* -( PhabricatorColumnProxyInterface )------------------------------------ */ public function getProxyColumnName() { return $this->getName(); } public function getProxyColumnIcon() { return $this->getDisplayIconIcon(); } public function getProxyColumnClass() { if ($this->isMilestone()) { return 'phui-workboard-column-milestone'; } return null; } } diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php index 9cbb8db8e9..fe19849163 100644 --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -1,509 +1,514 @@ getArgv(); array_unshift($argv, __CLASS__); $args = new PhutilArgumentParser($argv); $args->parse( array( array( 'name' => 'no-discovery', 'help' => pht('Pull only, without discovering commits.'), ), array( 'name' => 'not', 'param' => 'repository', 'repeat' => true, 'help' => pht('Do not pull __repository__.'), ), array( 'name' => 'repositories', 'wildcard' => true, 'help' => pht('Pull specific __repositories__ instead of all.'), ), )); $no_discovery = $args->getArg('no-discovery'); $include = $args->getArg('repositories'); $exclude = $args->getArg('not'); // Each repository has an individual pull frequency; after we pull it, // wait that long to pull it again. When we start up, try to pull everything // serially. $retry_after = array(); $min_sleep = 15; $max_futures = 4; $futures = array(); $queue = array(); while (!$this->shouldExit()) { PhabricatorCaches::destroyRequestCache(); $device = AlmanacKeys::getLiveDevice(); $pullable = $this->loadPullableRepositories($include, $exclude, $device); // If any repositories have the NEEDS_UPDATE flag set, pull them // as soon as possible. $need_update_messages = $this->loadRepositoryUpdateMessages(true); foreach ($need_update_messages as $message) { $repo = idx($pullable, $message->getRepositoryID()); if (!$repo) { continue; } $this->log( pht( 'Got an update message for repository "%s"!', $repo->getMonogram())); $retry_after[$message->getRepositoryID()] = time(); } // If any repositories were deleted, remove them from the retry timer map // so we don't end up with a retry timer that never gets updated and // causes us to sleep for the minimum amount of time. $retry_after = array_select_keys( $retry_after, array_keys($pullable)); // Figure out which repositories we need to queue for an update. foreach ($pullable as $id => $repository) { $now = PhabricatorTime::getNow(); $display_name = $repository->getDisplayName(); if (isset($futures[$id])) { $this->log( pht( 'Repository "%s" is currently updating.', $display_name)); continue; } if (isset($queue[$id])) { $this->log( pht( 'Repository "%s" is already queued.', $display_name)); continue; } $after = idx($retry_after, $id); if (!$after) { $smart_wait = $repository->loadUpdateInterval($min_sleep); $last_update = $this->loadLastUpdate($repository); $after = $last_update + $smart_wait; $retry_after[$id] = $after; $this->log( pht( 'Scheduling repository "%s" with an update window of %s '. 'second(s). Last update was %s second(s) ago.', $display_name, new PhutilNumber($smart_wait), new PhutilNumber($now - $last_update))); } if ($after > time()) { $this->log( pht( 'Repository "%s" is not due for an update for %s second(s).', $display_name, new PhutilNumber($after - $now))); continue; } $this->log( pht( 'Scheduling repository "%s" for an update (%s seconds overdue).', $display_name, new PhutilNumber($now - $after))); $queue[$id] = $after; } // Process repositories in the order they became candidates for updates. asort($queue); // Dequeue repositories until we hit maximum parallelism. while ($queue && (count($futures) < $max_futures)) { foreach ($queue as $id => $time) { $repository = idx($pullable, $id); if (!$repository) { $this->log( pht('Repository %s is no longer pullable; skipping.', $id)); unset($queue[$id]); continue; } $display_name = $repository->getDisplayName(); $this->log( pht( 'Starting update for repository "%s".', $display_name)); unset($queue[$id]); $futures[$id] = $this->buildUpdateFuture( $repository, $no_discovery); break; } } if ($queue) { $this->log( pht( 'Not enough process slots to schedule the other %s '. 'repository(s) for updates yet.', phutil_count($queue))); } if ($futures) { $iterator = id(new FutureIterator($futures)) ->setUpdateInterval($min_sleep); foreach ($iterator as $id => $future) { $this->stillWorking(); if ($future === null) { $this->log(pht('Waiting for updates to complete...')); $this->stillWorking(); if ($this->loadRepositoryUpdateMessages()) { $this->log(pht('Interrupted by pending updates!')); break; } continue; } unset($futures[$id]); $retry_after[$id] = $this->resolveUpdateFuture( $pullable[$id], $future, $min_sleep); // We have a free slot now, so go try to fill it. break; } // Jump back into prioritization if we had any futures to deal with. continue; } $this->waitForUpdates($min_sleep, $retry_after); } } /** * @task pull */ private function buildUpdateFuture( PhabricatorRepository $repository, $no_discovery) { $bin = dirname(phutil_get_library_root('phabricator')).'/bin/repository'; $flags = array(); if ($no_discovery) { $flags[] = '--no-discovery'; } $monogram = $repository->getMonogram(); $future = new ExecFuture('%s update %Ls -- %s', $bin, $flags, $monogram); // Sometimes, the underlying VCS commands will hang indefinitely. We've // observed this occasionally with GitHub, and other users have observed // it with other VCS servers. // To limit the damage this can cause, kill the update out after a // reasonable amount of time, under the assumption that it has hung. // Since it's hard to know what a "reasonable" amount of time is given that // users may be downloading a repository full of pirated movies over a // potato, these limits are fairly generous. Repositories exceeding these // limits can be manually pulled with `bin/repository update X`, which can // just run for as long as it wants. if ($repository->isImporting()) { $timeout = phutil_units('4 hours in seconds'); } else { $timeout = phutil_units('15 minutes in seconds'); } $future->setTimeout($timeout); + // The default TERM inherited by this process is "unknown", which causes PHP + // to produce a warning upon startup. Override it to squash this output to + // STDERR. + $future->updateEnv('TERM', 'dumb'); + return $future; } /** * Check for repositories that should be updated immediately. * * With the `$consume` flag, an internal cursor will also be incremented so * that these messages are not returned by subsequent calls. * * @param bool Pass `true` to consume these messages, so the process will * not see them again. * @return list Pending update messages. * * @task pull */ private function loadRepositoryUpdateMessages($consume = false) { $type_need_update = PhabricatorRepositoryStatusMessage::TYPE_NEEDS_UPDATE; $messages = id(new PhabricatorRepositoryStatusMessage())->loadAllWhere( 'statusType = %s AND id > %d', $type_need_update, $this->statusMessageCursor); // Keep track of messages we've seen so that we don't load them again. // If we reload messages, we can get stuck a loop if we have a failing // repository: we update immediately in response to the message, but do // not clear the message because the update does not succeed. We then // immediately retry. Instead, messages are only permitted to trigger // an immediate update once. if ($consume) { foreach ($messages as $message) { $this->statusMessageCursor = max( $this->statusMessageCursor, $message->getID()); } } return $messages; } /** * @task pull */ private function loadLastUpdate(PhabricatorRepository $repository) { $table = new PhabricatorRepositoryStatusMessage(); $conn = $table->establishConnection('r'); $epoch = queryfx_one( $conn, 'SELECT MAX(epoch) last_update FROM %T WHERE repositoryID = %d AND statusType IN (%Ls)', $table->getTableName(), $repository->getID(), array( PhabricatorRepositoryStatusMessage::TYPE_INIT, PhabricatorRepositoryStatusMessage::TYPE_FETCH, )); if ($epoch) { return (int)$epoch['last_update']; } return PhabricatorTime::getNow(); } /** * @task pull */ private function loadPullableRepositories( array $include, array $exclude, AlmanacDevice $device = null) { $query = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()); if ($include) { $query->withIdentifiers($include); } $repositories = $query->execute(); $repositories = mpull($repositories, null, 'getPHID'); if ($include) { $map = $query->getIdentifierMap(); foreach ($include as $identifier) { if (empty($map[$identifier])) { throw new Exception( pht( 'No repository "%s" exists!', $identifier)); } } } if ($exclude) { $xquery = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()) ->withIdentifiers($exclude); $excluded_repos = $xquery->execute(); $xmap = $xquery->getIdentifierMap(); foreach ($exclude as $identifier) { if (empty($xmap[$identifier])) { throw new Exception( pht( 'No repository "%s" exists!', $identifier)); } } foreach ($excluded_repos as $excluded_repo) { unset($repositories[$excluded_repo->getPHID()]); } } foreach ($repositories as $key => $repository) { if (!$repository->isTracked()) { unset($repositories[$key]); } } $viewer = $this->getViewer(); $filter = id(new DiffusionLocalRepositoryFilter()) ->setViewer($viewer) ->setDevice($device) ->setRepositories($repositories); $repositories = $filter->execute(); foreach ($filter->getRejectionReasons() as $reason) { $this->log($reason); } // Shuffle the repositories, then re-key the array since shuffle() // discards keys. This is mostly for startup, we'll use soft priorities // later. shuffle($repositories); $repositories = mpull($repositories, null, 'getID'); return $repositories; } /** * @task pull */ private function resolveUpdateFuture( PhabricatorRepository $repository, ExecFuture $future, $min_sleep) { $display_name = $repository->getDisplayName(); $this->log(pht('Resolving update for "%s".', $display_name)); try { list($stdout, $stderr) = $future->resolvex(); } catch (Exception $ex) { $proxy = new PhutilProxyException( pht( 'Error while updating the "%s" repository.', $display_name), $ex); phlog($proxy); $smart_wait = $repository->loadUpdateInterval($min_sleep); return PhabricatorTime::getNow() + $smart_wait; } if (strlen($stderr)) { $stderr_msg = pht( 'Unexpected output while updating repository "%s": %s', $display_name, $stderr); phlog($stderr_msg); } $smart_wait = $repository->loadUpdateInterval($min_sleep); $this->log( pht( 'Based on activity in repository "%s", considering a wait of %s '. 'seconds before update.', $display_name, new PhutilNumber($smart_wait))); return PhabricatorTime::getNow() + $smart_wait; } /** * Sleep for a short period of time, waiting for update messages from the * * * @task pull */ private function waitForUpdates($min_sleep, array $retry_after) { $this->log( pht('No repositories need updates right now, sleeping...')); $sleep_until = time() + $min_sleep; if ($retry_after) { $sleep_until = min($sleep_until, min($retry_after)); } while (($sleep_until - time()) > 0) { $sleep_duration = ($sleep_until - time()); $this->log( pht( 'Sleeping for %s more second(s)...', new PhutilNumber($sleep_duration))); $this->sleep(1); if ($this->shouldExit()) { $this->log(pht('Awakened from sleep by graceful shutdown!')); return; } if ($this->loadRepositoryUpdateMessages()) { $this->log(pht('Awakened from sleep by pending updates!')); break; } } } } diff --git a/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php b/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php similarity index 63% rename from src/applications/search/editor/PhabricatorProfilePanelEditEngine.php rename to src/applications/search/editor/PhabricatorProfileMenuEditEngine.php index e5689c8e68..f7b8f76ec7 100644 --- a/src/applications/search/editor/PhabricatorProfilePanelEditEngine.php +++ b/src/applications/search/editor/PhabricatorProfileMenuEditEngine.php @@ -1,139 +1,141 @@ panelEngine = $engine; + public function setMenuEngine(PhabricatorProfileMenuEngine $engine) { + $this->menuEngine = $engine; return $this; } - public function getPanelEngine() { - return $this->panelEngine; + public function getMenuEngine() { + return $this->menuEngine; } public function setProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } public function getProfileObject() { return $this->profileObject; } - public function setNewPanelConfiguration( - PhabricatorProfilePanelConfiguration $configuration) { - $this->newPanelConfiguration = $configuration; + public function setNewMenuItemConfiguration( + PhabricatorProfileMenuItemConfiguration $configuration) { + $this->newMenuItemConfiguration = $configuration; return $this; } - public function getNewPanelConfiguration() { - return $this->newPanelConfiguration; + public function getNewMenuItemConfiguration() { + return $this->newMenuItemConfiguration; } public function setIsBuiltin($is_builtin) { $this->isBuiltin = $is_builtin; return $this; } public function getIsBuiltin() { return $this->isBuiltin; } public function getEngineName() { - return pht('Profile Panels'); + return pht('Profile Menu Items'); } public function getSummaryHeader() { - return pht('Edit Profile Panel Configurations'); + return pht('Edit Profile Menu Item Configurations'); } public function getSummaryText() { return pht('This engine is used to modify menu items on profiles.'); } public function getEngineApplicationClass() { return 'PhabricatorSearchApplication'; } protected function newEditableObject() { - if (!$this->newPanelConfiguration) { + if (!$this->newMenuItemConfiguration) { throw new Exception( - pht('Profile panels can not be generated without an object context.')); + pht( + 'Profile menu items can not be generated without an '. + 'object context.')); } - return clone $this->newPanelConfiguration; + return clone $this->newMenuItemConfiguration; } protected function newObjectQuery() { - return id(new PhabricatorProfilePanelConfigurationQuery()); + return id(new PhabricatorProfileMenuItemConfigurationQuery()); } protected function getObjectCreateTitleText($object) { if ($this->getIsBuiltin()) { return pht('Edit Builtin Item'); } else { return pht('Create Menu Item'); } } protected function getObjectCreateButtonText($object) { if ($this->getIsBuiltin()) { return pht('Save Changes'); } else { return pht('Create Menu Item'); } } protected function getObjectEditTitleText($object) { return pht('Edit Menu Item: %s', $object->getDisplayName()); } protected function getObjectEditShortText($object) { return pht('Edit Menu Item'); } protected function getObjectCreateShortText() { return pht('Edit Menu Item'); } protected function getObjectName() { return pht('Menu Item'); } protected function getObjectCreateCancelURI($object) { - return $this->getPanelEngine()->getConfigureURI(); + return $this->getMenuEngine()->getConfigureURI(); } protected function getObjectViewURI($object) { - return $this->getPanelEngine()->getConfigureURI(); + return $this->getMenuEngine()->getConfigureURI(); } protected function buildCustomEditFields($object) { - $panel = $object->getPanel(); - $fields = $panel->buildEditEngineFields($object); + $item = $object->getMenuItem(); + $fields = $item->buildEditEngineFields($object); $type_property = - PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY; foreach ($fields as $field) { $field ->setTransactionType($type_property) ->setMetadataValue('property.key', $field->getKey()); } return $fields; } } diff --git a/src/applications/search/editor/PhabricatorProfilePanelEditor.php b/src/applications/search/editor/PhabricatorProfileMenuEditor.php similarity index 52% rename from src/applications/search/editor/PhabricatorProfilePanelEditor.php rename to src/applications/search/editor/PhabricatorProfileMenuEditor.php index ce4dbeb8f0..d91bba272b 100644 --- a/src/applications/search/editor/PhabricatorProfilePanelEditor.php +++ b/src/applications/search/editor/PhabricatorProfileMenuEditor.php @@ -1,87 +1,90 @@ getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: $key = $xaction->getMetadataValue('property.key'); - return $object->getPanelProperty($key, null); - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: - return $object->getPanelOrder(); - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + return $object->getMenuItemProperty($key, null); + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: + return $object->getMenuItemOrder(); + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: return $object->getVisibility(); } } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: return $xaction->getNewValue(); - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: return (int)$xaction->getNewValue(); } } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: $key = $xaction->getMetadataValue('property.key'); $value = $xaction->getNewValue(); - $object->setPanelProperty($key, $value); + $object->setMenuItemProperty($key, $value); return; - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: - $object->setPanelOrder($xaction->getNewValue()); + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: + $object->setMenuItemOrder($xaction->getNewValue()); return; - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: $object->setVisibility($xaction->getNewValue()); return; } return parent::applyCustomInternalTransaction($object, $xaction); } protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: - case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: - case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER: + case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY: return; } return parent::applyCustomExternalTransaction($object, $xaction); } } diff --git a/src/applications/search/engine/PhabricatorProfilePanelEngine.php b/src/applications/search/engine/PhabricatorProfileMenuEngine.php similarity index 61% rename from src/applications/search/engine/PhabricatorProfilePanelEngine.php rename to src/applications/search/engine/PhabricatorProfileMenuEngine.php index d3c209ba68..d930b31314 100644 --- a/src/applications/search/engine/PhabricatorProfilePanelEngine.php +++ b/src/applications/search/engine/PhabricatorProfileMenuEngine.php @@ -1,965 +1,992 @@ viewer = $viewer; return $this; } public function getViewer() { return $this->viewer; } public function setProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } public function getProfileObject() { return $this->profileObject; } public function setController(PhabricatorController $controller) { $this->controller = $controller; return $this; } public function getController() { return $this->controller; } - private function setDefaultPanel( - PhabricatorProfilePanelConfiguration $default_panel) { - $this->defaultPanel = $default_panel; + private function setDefaultItem( + PhabricatorProfileMenuItemConfiguration $default_item) { + $this->defaultItem = $default_item; return $this; } - public function getDefaultPanel() { - $this->loadPanels(); - return $this->defaultPanel; + public function getDefaultItem() { + $this->loadItems(); + return $this->defaultItem; } - abstract protected function getPanelURI($path); + abstract protected function getItemURI($path); - abstract protected function isPanelEngineConfigurable(); + abstract protected function isMenuEngineConfigurable(); public function buildResponse() { $controller = $this->getController(); $viewer = $controller->getViewer(); $this->setViewer($viewer); $request = $controller->getRequest(); - $panel_action = $request->getURIData('panelAction'); + $item_action = $request->getURIData('itemAction'); // If the engine is not configurable, don't respond to any of the editing // or configuration routes. - if (!$this->isPanelEngineConfigurable()) { - switch ($panel_action) { + if (!$this->isMenuEngineConfigurable()) { + switch ($item_action) { case 'view': break; default: return new Aphront404Response(); } } - $panel_id = $request->getURIData('panelID'); + $item_id = $request->getURIData('itemID'); + $item_list = $this->getItems(); - $panel_list = $this->loadPanels(); - - $selected_panel = null; - if (strlen($panel_id)) { - $panel_id_int = (int)$panel_id; - foreach ($panel_list as $panel) { - if ($panel_id_int) { - if ((int)$panel->getID() === $panel_id_int) { - $selected_panel = $panel; + $selected_item = null; + if (strlen($item_id)) { + $item_id_int = (int)$item_id; + foreach ($item_list as $item) { + if ($item_id_int) { + if ((int)$item->getID() === $item_id_int) { + $selected_item = $item; break; } } - $builtin_key = $panel->getBuiltinKey(); - if ($builtin_key === (string)$panel_id) { - $selected_panel = $panel; + $builtin_key = $item->getBuiltinKey(); + if ($builtin_key === (string)$item_id) { + $selected_item = $item; break; } } } - switch ($panel_action) { + switch ($item_action) { case 'view': case 'info': case 'hide': case 'default': case 'builtin': - if (!$selected_panel) { + if (!$selected_item) { return new Aphront404Response(); } break; } $navigation = $this->buildNavigation(); - $navigation->selectFilter('panel.configure'); + $navigation->selectFilter('item.configure'); $crumbs = $controller->buildApplicationCrumbsForEditEngine(); - switch ($panel_action) { + switch ($item_action) { case 'view': - $content = $this->buildPanelViewContent($selected_panel); + $content = $this->buildItemViewContent($selected_item); break; case 'configure': - $content = $this->buildPanelConfigureContent($panel_list); + $content = $this->buildItemConfigureContent($item_list); $crumbs->addTextCrumb(pht('Configure Menu')); break; case 'reorder': - $content = $this->buildPanelReorderContent($panel_list); + $content = $this->buildItemReorderContent($item_list); break; case 'new': - $panel_key = $request->getURIData('panelKey'); - $content = $this->buildPanelNewContent($panel_key); + $item_key = $request->getURIData('itemKey'); + $content = $this->buildItemNewContent($item_key); break; case 'builtin': - $content = $this->buildPanelBuiltinContent($selected_panel); + $content = $this->buildItemBuiltinContent($selected_item); break; case 'hide': - $content = $this->buildPanelHideContent($selected_panel); + $content = $this->buildItemHideContent($selected_item); break; case 'default': - $content = $this->buildPanelDefaultContent( - $selected_panel, - $panel_list); + $content = $this->buildItemDefaultContent( + $selected_item, + $item_list); break; case 'edit': - $content = $this->buildPanelEditContent(); + $content = $this->buildItemEditContent(); break; default: throw new Exception( pht( - 'Unsupported panel action "%s".', - $panel_action)); + 'Unsupported item action "%s".', + $item_action)); } if ($content instanceof AphrontResponse) { return $content; } if ($content instanceof AphrontResponseProducerInterface) { return $content; } + $crumbs->setBorder(true); + return $controller->newPage() - ->setTitle(pht('Profile Stuff')) + ->setTitle(pht('Configure Menu')) ->setNavigation($navigation) ->setCrumbs($crumbs) ->appendChild($content); } public function buildNavigation() { if ($this->navigation) { return $this->navigation; } $nav = id(new AphrontSideNavFilterView()) ->setIsProfileMenu(true) - ->setBaseURI(new PhutilURI($this->getPanelURI(''))); + ->setBaseURI(new PhutilURI($this->getItemURI(''))); - $panels = $this->getPanels(); + $menu_items = $this->getItems(); + $filtered_items = array(); + foreach ($menu_items as $menu_item) { + if ($menu_item->isDisabled()) { + continue; + } + $filtered_items[] = $menu_item; + } + $filtered_groups = mgroup($filtered_items, 'getMenuItemKey'); + foreach ($filtered_groups as $group) { + $first_item = head($group); + $first_item->willBuildNavigationItems($group); + } - foreach ($panels as $panel) { - if ($panel->isDisabled()) { + foreach ($menu_items as $menu_item) { + if ($menu_item->isDisabled()) { continue; } - $items = $panel->buildNavigationMenuItems(); + $items = $menu_item->buildNavigationMenuItems(); foreach ($items as $item) { $this->validateNavigationMenuItem($item); } - // If the panel produced only a single item which does not otherwise + // If the item produced only a single item which does not otherwise // have a key, try to automatically assign it a reasonable key. This // makes selecting the correct item simpler. if (count($items) == 1) { $item = head($items); if ($item->getKey() === null) { - $builtin_key = $panel->getBuiltinKey(); - $panel_phid = $panel->getPHID(); + $builtin_key = $menu_item->getBuiltinKey(); + $item_phid = $menu_item->getPHID(); if ($builtin_key !== null) { $item->setKey($builtin_key); - } else if ($panel_phid !== null) { - $item->setKey($panel_phid); + } else if ($item_phid !== null) { + $item->setKey($item_phid); } } } foreach ($items as $item) { $nav->addMenuItem($item); } } $more_items = $this->newAutomaticMenuItems($nav); foreach ($more_items as $item) { $nav->addMenuItem($item); } $nav->selectFilter(null); $this->navigation = $nav; return $this->navigation; } - private function getPanels() { - if ($this->panels === null) { - $this->panels = $this->loadPanels(); + private function getItems() { + if ($this->items === null) { + $this->items = $this->loadItems(); } - return $this->panels; + return $this->items; } - private function loadPanels() { + private function loadItems() { $viewer = $this->getViewer(); $object = $this->getProfileObject(); - $panels = $this->loadBuiltinProfilePanels(); + $items = $this->loadBuiltinProfileItems(); - $stored_panels = id(new PhabricatorProfilePanelConfigurationQuery()) + $stored_items = id(new PhabricatorProfileMenuItemConfigurationQuery()) ->setViewer($viewer) ->withProfilePHIDs(array($object->getPHID())) ->execute(); - foreach ($stored_panels as $stored_panel) { - $impl = $stored_panel->getPanel(); + foreach ($stored_items as $stored_item) { + $impl = $stored_item->getMenuItem(); $impl->setViewer($viewer); } - // Merge the stored panels into the builtin panels. If a builtin panel has + // Merge the stored items into the builtin items. If a builtin item has // a stored version, replace the defaults with the stored changes. - foreach ($stored_panels as $stored_panel) { - if (!$stored_panel->shouldEnableForObject($object)) { + foreach ($stored_items as $stored_item) { + if (!$stored_item->shouldEnableForObject($object)) { continue; } - $builtin_key = $stored_panel->getBuiltinKey(); + $builtin_key = $stored_item->getBuiltinKey(); if ($builtin_key !== null) { // If this builtin actually exists, replace the builtin with the // stored configuration. Otherwise, we're just going to drop the // stored config: it corresponds to an out-of-date or uninstalled - // panel. - if (isset($panels[$builtin_key])) { - $panels[$builtin_key] = $stored_panel; + // item. + if (isset($items[$builtin_key])) { + $items[$builtin_key] = $stored_item; } else { continue; } } else { - $panels[] = $stored_panel; + $items[] = $stored_item; } } - $panels = msort($panels, 'getSortKey'); + $items = msort($items, 'getSortKey'); // Normalize keys since callers shouldn't rely on this array being // partially keyed. - $panels = array_values($panels); + $items = array_values($items); - // Make sure exactly one valid panel is marked as default. + // Make sure exactly one valid item is marked as default. $default = null; $first = null; - foreach ($panels as $panel) { - if (!$panel->canMakeDefault()) { + foreach ($items as $item) { + if (!$item->canMakeDefault()) { continue; } - if ($panel->isDefault()) { - $default = $panel; + if ($item->isDefault()) { + $default = $item; break; } if ($first === null) { - $first = $panel; + $first = $item; } } if (!$default) { $default = $first; } if ($default) { - $this->setDefaultPanel($default); + $this->setDefaultItem($default); } - return $panels; + return $items; } - private function loadBuiltinProfilePanels() { + private function loadBuiltinProfileItems() { $object = $this->getProfileObject(); - $builtins = $this->getBuiltinProfilePanels($object); + $builtins = $this->getBuiltinProfileItems($object); - $panels = PhabricatorProfilePanel::getAllPanels(); + $items = PhabricatorProfileMenuItem::getAllMenuItems(); $viewer = $this->getViewer(); $order = 1; $map = array(); foreach ($builtins as $builtin) { $builtin_key = $builtin->getBuiltinKey(); if (!$builtin_key) { throw new Exception( pht( - 'Object produced a builtin panel with no builtin panel key! '. - 'Builtin panels must have a unique key.')); + 'Object produced a builtin item with no builtin item key! '. + 'Builtin items must have a unique key.')); } if (isset($map[$builtin_key])) { throw new Exception( pht( - 'Object produced two panels with the same builtin key ("%s"). '. - 'Each panel must have a unique builtin key.', + 'Object produced two items with the same builtin key ("%s"). '. + 'Each item must have a unique builtin key.', $builtin_key)); } - $panel_key = $builtin->getPanelKey(); + $item_key = $builtin->getMenuItemKey(); - $panel = idx($panels, $panel_key); - if (!$panel) { + $item = idx($items, $item_key); + if (!$item) { throw new Exception( pht( - 'Builtin panel ("%s") specifies a bad panel key ("%s"); there '. - 'is no corresponding panel implementation available.', + 'Builtin item ("%s") specifies a bad item key ("%s"); there '. + 'is no corresponding item implementation available.', $builtin_key, - $panel_key)); + $item_key)); } - $panel = clone $panel; - $panel->setViewer($viewer); + $item = clone $item; + $item->setViewer($viewer); $builtin ->setProfilePHID($object->getPHID()) - ->attachPanel($panel) + ->attachMenuItem($item) ->attachProfileObject($object) - ->setPanelOrder($order); + ->setMenuItemOrder($order); if (!$builtin->shouldEnableForObject($object)) { continue; } $map[$builtin_key] = $builtin; $order++; } return $map; } private function validateNavigationMenuItem($item) { if (!($item instanceof PHUIListItemView)) { throw new Exception( pht( 'Expected buildNavigationMenuItems() to return a list of '. 'PHUIListItemView objects, but got a surprise.')); } } private function newAutomaticMenuItems(AphrontSideNavFilterView $nav) { $items = array(); // NOTE: We're adding a spacer item for the fixed footer, so that if the // menu taller than the page content you can still scroll down the page far // enough to access the last item without the content being obscured by the // fixed items. $items[] = id(new PHUIListItemView()) ->setHideInApplicationMenu(true) ->addClass('phui-profile-menu-spacer'); $collapse_id = celerity_generate_unique_node_id(); $viewer = $this->getViewer(); $collapse_key = PhabricatorProfileMenuCollapsedSetting::SETTINGKEY; $is_collapsed = $viewer->getUserSetting($collapse_key); if ($is_collapsed) { $nav->addClass('phui-profile-menu-collapsed'); } else { $nav->addClass('phui-profile-menu-expanded'); } if ($viewer->isLoggedIn()) { $settings_uri = '/settings/adjust/?key='.$collapse_key; } else { $settings_uri = null; } Javelin::initBehavior( 'phui-profile-menu', array( 'menuID' => $nav->getMainID(), 'collapseID' => $collapse_id, 'isCollapsed' => (bool)$is_collapsed, 'settingsURI' => $settings_uri, )); $collapse_icon = id(new PHUIIconCircleView()) ->addClass('phui-list-item-icon') ->addClass('phui-profile-menu-visible-when-expanded') ->setIcon('fa-chevron-left'); $expand_icon = id(new PHUIIconCircleView()) ->addClass('phui-list-item-icon') ->addClass('phui-profile-menu-visible-when-collapsed') ->addSigil('has-tooltip') ->setMetadata( array( 'tip' => pht('Expand'), 'align' => 'E', )) ->setIcon('fa-chevron-right'); $items[] = id(new PHUIListItemView()) ->setName('Collapse') ->addIcon($collapse_icon) ->addIcon($expand_icon) ->setID($collapse_id) ->addClass('phui-profile-menu-footer') ->addClass('phui-profile-menu-footer-1') ->setHideInApplicationMenu(true) ->setHref('#'); return $items; } public function getConfigureURI() { - return $this->getPanelURI('configure/'); + return $this->getItemURI('configure/'); } - private function buildPanelReorderContent(array $panels) { + private function buildItemReorderContent(array $items) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); PhabricatorPolicyFilter::requireCapability( $viewer, $object, PhabricatorPolicyCapability::CAN_EDIT); $controller = $this->getController(); $request = $controller->getRequest(); $request->validateCSRF(); $order = $request->getStrList('order'); $by_builtin = array(); $by_id = array(); - foreach ($panels as $key => $panel) { - $id = $panel->getID(); + foreach ($items as $key => $item) { + $id = $item->getID(); if ($id) { $by_id[$id] = $key; continue; } - $builtin_key = $panel->getBuiltinKey(); + $builtin_key = $item->getBuiltinKey(); if ($builtin_key) { $by_builtin[$builtin_key] = $key; continue; } } $key_order = array(); foreach ($order as $order_item) { if (isset($by_id[$order_item])) { $key_order[] = $by_id[$order_item]; continue; } if (isset($by_builtin[$order_item])) { $key_order[] = $by_builtin[$order_item]; continue; } } - $panels = array_select_keys($panels, $key_order) + $panels; + $items = array_select_keys($items, $key_order) + $items; $type_order = - PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER; $order = 1; - foreach ($panels as $panel) { + foreach ($items as $item) { $xactions = array(); - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) + $xactions[] = id(new PhabricatorProfileMenuItemConfigurationTransaction()) ->setTransactionType($type_order) ->setNewValue($order); - $editor = id(new PhabricatorProfilePanelEditor()) + $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) - ->applyTransactions($panel, $xactions); + ->applyTransactions($item, $xactions); $order++; } return id(new AphrontRedirectResponse()) ->setURI($this->getConfigureURI()); } - private function buildPanelConfigureContent(array $panels) { + private function buildItemConfigureContent(array $items) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); PhabricatorPolicyFilter::requireCapability( $viewer, $object, PhabricatorPolicyCapability::CAN_EDIT); $list_id = celerity_generate_unique_node_id(); Javelin::initBehavior( 'reorder-profile-menu-items', array( 'listID' => $list_id, - 'orderURI' => $this->getPanelURI('reorder/'), + 'orderURI' => $this->getItemURI('reorder/'), )); $list = id(new PHUIObjectItemListView()) ->setID($list_id); - foreach ($panels as $panel) { - $id = $panel->getID(); - $builtin_key = $panel->getBuiltinKey(); + foreach ($items as $item) { + $id = $item->getID(); + $builtin_key = $item->getBuiltinKey(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, - $panel, + $item, PhabricatorPolicyCapability::CAN_EDIT); - $item = id(new PHUIObjectItemView()); + $view = id(new PHUIObjectItemView()); - $name = $panel->getDisplayName(); - $type = $panel->getPanelTypeName(); + $name = $item->getDisplayName(); + $type = $item->getMenuItemTypeName(); if (!strlen(trim($name))) { $name = pht('Untitled "%s" Item', $type); } - $item->setHeader($name); - $item->addAttribute($type); + $view->setHeader($name); + $view->addAttribute($type); if ($can_edit) { - $item + $view ->setGrippable(true) ->addSigil('profile-menu-item') ->setMetadata( array( 'key' => nonempty($id, $builtin_key), )); if ($id) { - $default_uri = $this->getPanelURI("default/{$id}/"); + $default_uri = $this->getItemURI("default/{$id}/"); } else { - $default_uri = $this->getPanelURI("default/{$builtin_key}/"); + $default_uri = $this->getItemURI("default/{$builtin_key}/"); } - if ($panel->isDefault()) { + if ($item->isDefault()) { $default_icon = 'fa-thumb-tack green'; $default_text = pht('Current Default'); - } else if ($panel->canMakeDefault()) { + } else if ($item->canMakeDefault()) { $default_icon = 'fa-thumb-tack'; $default_text = pht('Make Default'); } else { $default_text = null; } if ($default_text !== null) { - $item->addAction( + $view->addAction( id(new PHUIListItemView()) ->setHref($default_uri) ->setWorkflow(true) ->setName($default_text) ->setIcon($default_icon)); } if ($id) { - $item->setHref($this->getPanelURI("edit/{$id}/")); - $hide_uri = $this->getPanelURI("hide/{$id}/"); + $view->setHref($this->getItemURI("edit/{$id}/")); + $hide_uri = $this->getItemURI("hide/{$id}/"); } else { - $item->setHref($this->getPanelURI("builtin/{$builtin_key}/")); - $hide_uri = $this->getPanelURI("hide/{$builtin_key}/"); + $view->setHref($this->getItemURI("builtin/{$builtin_key}/")); + $hide_uri = $this->getItemURI("hide/{$builtin_key}/"); } - if ($panel->isDisabled()) { + if ($item->isDisabled()) { $hide_icon = 'fa-plus'; $hide_text = pht('Enable'); - } else if ($panel->getBuiltinKey() !== null) { + } else if ($item->getBuiltinKey() !== null) { $hide_icon = 'fa-times'; $hide_text = pht('Disable'); } else { $hide_icon = 'fa-times'; $hide_text = pht('Delete'); } - $can_disable = $panel->canHidePanel(); + $can_disable = $item->canHideMenuItem(); - $item->addAction( + $view->addAction( id(new PHUIListItemView()) ->setHref($hide_uri) ->setWorkflow(true) ->setDisabled(!$can_disable) ->setName($hide_text) ->setIcon($hide_icon)); } - if ($panel->isDisabled()) { - $item->setDisabled(true); + if ($item->isDisabled()) { + $view->setDisabled(true); } - $list->addItem($item); + $list->addItem($view); } $action_view = id(new PhabricatorActionListView()) ->setUser($viewer); - $panel_types = PhabricatorProfilePanel::getAllPanels(); + $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); + $object = $this->getProfileObject(); - $action_view->addAction( + $action_list = id(new PhabricatorActionListView()) + ->setViewer($viewer); + + $action_list->addAction( id(new PhabricatorActionView()) ->setLabel(true) ->setName(pht('Add New Menu Item...'))); - foreach ($panel_types as $panel_type) { - if (!$panel_type->canAddToObject($object)) { + foreach ($item_types as $item_type) { + if (!$item_type->canAddToObject($object)) { continue; } - $panel_key = $panel_type->getPanelKey(); + $item_key = $item_type->getMenuItemKey(); - $action_view->addAction( + $action_list->addAction( id(new PhabricatorActionView()) - ->setIcon($panel_type->getPanelTypeIcon()) - ->setName($panel_type->getPanelTypeName()) - ->setHref($this->getPanelURI("new/{$panel_key}/"))); + ->setIcon($item_type->getMenuItemTypeIcon()) + ->setName($item_type->getMenuItemTypeName()) + ->setHref($this->getItemURI("new/{$item_key}/")) + ->setWorkflow(true)); } - $action_view->addAction( + $action_list->addAction( id(new PhabricatorActionView()) ->setLabel(true) ->setName(pht('Documentation'))); $doc_link = PhabricatorEnv::getDoclink('Profile Menu User Guide'); $doc_name = pht('Profile Menu User Guide'); - $action_view->addAction( + $action_list->addAction( id(new PhabricatorActionView()) ->setIcon('fa-book') ->setHref($doc_link) ->setName($doc_name)); - $action_button = id(new PHUIButtonView()) - ->setTag('a') - ->setText(pht('Configure Menu')) - ->setHref('#') - ->setIcon('fa-gear') - ->setDropdownMenu($action_view); - $header = id(new PHUIHeaderView()) ->setHeader(pht('Profile Menu Items')) - ->setSubHeader(pht('Drag tabs to reorder menu')) - ->addActionLink($action_button); + ->setHeaderIcon('fa-list'); $box = id(new PHUIObjectBoxView()) - ->setHeader($header) + ->setHeaderText(pht('Navigation')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList($list); - return $box; + $panel = id(new PHUICurtainPanelView()) + ->appendChild($action_view); + + $curtain = id(new PHUICurtainView()) + ->setViewer($viewer) + ->setActionList($action_list); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setCurtain($curtain) + ->setMainColumn( + array( + $box, + )); + + return $view; } - private function buildPanelNewContent($panel_key) { - $panel_types = PhabricatorProfilePanel::getAllPanels(); - $panel_type = idx($panel_types, $panel_key); - if (!$panel_type) { + private function buildItemNewContent($item_key) { + $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); + $item_type = idx($item_types, $item_key); + if (!$item_type) { return new Aphront404Response(); } $object = $this->getProfileObject(); - if (!$panel_type->canAddToObject($object)) { + if (!$item_type->canAddToObject($object)) { return new Aphront404Response(); } - $configuration = - PhabricatorProfilePanelConfiguration::initializeNewPanelConfiguration( - $object, - $panel_type); + $configuration = PhabricatorProfileMenuItemConfiguration::initializeNewItem( + $object, + $item_type); $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); $controller = $this->getController(); - return id(new PhabricatorProfilePanelEditEngine()) - ->setPanelEngine($this) + return id(new PhabricatorProfileMenuEditEngine()) + ->setMenuEngine($this) ->setProfileObject($object) - ->setNewPanelConfiguration($configuration) + ->setNewMenuItemConfiguration($configuration) ->setController($controller) ->buildResponse(); } - private function buildPanelEditContent() { + private function buildItemEditContent() { $viewer = $this->getViewer(); $object = $this->getProfileObject(); $controller = $this->getController(); - return id(new PhabricatorProfilePanelEditEngine()) - ->setPanelEngine($this) + return id(new PhabricatorProfileMenuEditEngine()) + ->setMenuEngine($this) ->setProfileObject($object) ->setController($controller) ->buildResponse(); } - private function buildPanelBuiltinContent( - PhabricatorProfilePanelConfiguration $configuration) { + private function buildItemBuiltinContent( + PhabricatorProfileMenuItemConfiguration $configuration) { - // If this builtin panel has already been persisted, redirect to the + // If this builtin item has already been persisted, redirect to the // edit page. $id = $configuration->getID(); if ($id) { return id(new AphrontRedirectResponse()) - ->setURI($this->getPanelURI("edit/{$id}/")); + ->setURI($this->getItemURI("edit/{$id}/")); } - // Otherwise, act like we're creating a new panel, we're just starting + // Otherwise, act like we're creating a new item, we're just starting // with the builtin template. $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); $object = $this->getProfileObject(); $controller = $this->getController(); - return id(new PhabricatorProfilePanelEditEngine()) + return id(new PhabricatorProfileMenuEditEngine()) ->setIsBuiltin(true) - ->setPanelEngine($this) + ->setMenuEngine($this) ->setProfileObject($object) - ->setNewPanelConfiguration($configuration) + ->setNewMenuItemConfiguration($configuration) ->setController($controller) ->buildResponse(); } - private function buildPanelHideContent( - PhabricatorProfilePanelConfiguration $configuration) { + private function buildItemHideContent( + PhabricatorProfileMenuItemConfiguration $configuration) { $controller = $this->getController(); $request = $controller->getRequest(); $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); - if (!$configuration->canHidePanel()) { + if (!$configuration->canHideMenuItem()) { return $controller->newDialog() - ->setTitle(pht('Mandatory Panel')) + ->setTitle(pht('Mandatory Item')) ->appendParagraph( - pht('This panel is very important, and can not be disabled.')) + pht('This menu item is very important, and can not be disabled.')) ->addCancelButton($this->getConfigureURI()); } if ($configuration->getBuiltinKey() === null) { $new_value = null; $title = pht('Delete Menu Item'); $body = pht('Delete this menu item?'); $button = pht('Delete Menu Item'); } else if ($configuration->isDisabled()) { - $new_value = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; + $new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE; $title = pht('Enable Menu Item'); $body = pht( 'Enable this menu item? It will appear in the menu again.'); $button = pht('Enable Menu Item'); } else { - $new_value = PhabricatorProfilePanelConfiguration::VISIBILITY_DISABLED; + $new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DISABLED; $title = pht('Disable Menu Item'); $body = pht( 'Disable this menu item? It will no longer appear in the menu, but '. 'you can re-enable it later.'); $button = pht('Disable Menu Item'); } $v_visibility = $configuration->getVisibility(); if ($request->isFormPost()) { if ($new_value === null) { $configuration->delete(); } else { $type_visibility = - PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY; $xactions = array(); - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) - ->setTransactionType($type_visibility) - ->setNewValue($new_value); + $xactions[] = + id(new PhabricatorProfileMenuItemConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($new_value); - $editor = id(new PhabricatorProfilePanelEditor()) + $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($configuration, $xactions); } return id(new AphrontRedirectResponse()) ->setURI($this->getConfigureURI()); } return $controller->newDialog() ->setTitle($title) ->appendParagraph($body) ->addCancelButton($this->getConfigureURI()) ->addSubmitButton($button); } - private function buildPanelDefaultContent( - PhabricatorProfilePanelConfiguration $configuration, - array $panels) { + private function buildItemDefaultContent( + PhabricatorProfileMenuItemConfiguration $configuration, + array $items) { $controller = $this->getController(); $request = $controller->getRequest(); $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); $done_uri = $this->getConfigureURI(); if (!$configuration->canMakeDefault()) { return $controller->newDialog() ->setTitle(pht('Not Defaultable')) ->appendParagraph( pht( 'This item can not be set as the default item. This is usually '. 'because the item has no page of its own, or links to an '. 'external page.')) ->addCancelButton($done_uri); } if ($configuration->isDefault()) { return $controller->newDialog() ->setTitle(pht('Already Default')) ->appendParagraph( pht( 'This item is already set as the default item for this menu.')) ->addCancelButton($done_uri); } if ($request->isFormPost()) { $key = $configuration->getID(); if (!$key) { $key = $configuration->getBuiltinKey(); } $this->adjustDefault($key); return id(new AphrontRedirectResponse()) ->setURI($done_uri); } return $controller->newDialog() ->setTitle(pht('Make Default')) ->appendParagraph( pht( 'Set this item as the default for this menu? Users arriving on '. 'this page will be shown the content of this item by default.')) ->addCancelButton($done_uri) ->addSubmitButton(pht('Make Default')); } - protected function newPanel() { - return PhabricatorProfilePanelConfiguration::initializeNewBuiltin(); + protected function newItem() { + return PhabricatorProfileMenuItemConfiguration::initializeNewBuiltin(); } public function adjustDefault($key) { $controller = $this->getController(); $request = $controller->getRequest(); $viewer = $request->getViewer(); - $panels = $this->loadPanels(); + $items = $this->loadItems(); - // To adjust the default panel, we first change any existing panels that - // are marked as defaults to "visible", then make the new default panel + // To adjust the default item, we first change any existing items that + // are marked as defaults to "visible", then make the new default item // the default. $default = array(); $visible = array(); - foreach ($panels as $panel) { - $builtin_key = $panel->getBuiltinKey(); - $id = $panel->getID(); + foreach ($items as $item) { + $builtin_key = $item->getBuiltinKey(); + $id = $item->getID(); $is_target = (($builtin_key !== null) && ($builtin_key === $key)) || (($id !== null) && ((int)$id === (int)$key)); if ($is_target) { - if (!$panel->isDefault()) { - $default[] = $panel; + if (!$item->isDefault()) { + $default[] = $item; } } else { - if ($panel->isDefault()) { - $visible[] = $panel; + if ($item->isDefault()) { + $visible[] = $item; } } } $type_visibility = - PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY; + PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY; - $v_visible = PhabricatorProfilePanelConfiguration::VISIBILITY_VISIBLE; - $v_default = PhabricatorProfilePanelConfiguration::VISIBILITY_DEFAULT; + $v_visible = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE; + $v_default = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DEFAULT; $apply = array( array($v_visible, $visible), array($v_default, $default), ); foreach ($apply as $group) { - list($value, $panels) = $group; - foreach ($panels as $panel) { + list($value, $items) = $group; + foreach ($items as $item) { $xactions = array(); - $xactions[] = id(new PhabricatorProfilePanelConfigurationTransaction()) - ->setTransactionType($type_visibility) - ->setNewValue($value); + $xactions[] = + id(new PhabricatorProfileMenuItemConfigurationTransaction()) + ->setTransactionType($type_visibility) + ->setNewValue($value); - $editor = id(new PhabricatorProfilePanelEditor()) + $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) - ->applyTransactions($panel, $xactions); + ->applyTransactions($item, $xactions); } } return $this; } } diff --git a/src/applications/search/profilepanel/PhabricatorApplicationProfilePanel.php b/src/applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php similarity index 70% rename from src/applications/search/profilepanel/PhabricatorApplicationProfilePanel.php rename to src/applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php index f2d53f936d..214819100e 100644 --- a/src/applications/search/profilepanel/PhabricatorApplicationProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php @@ -1,79 +1,79 @@ getApplication($config); if ($app) { return $app->getName(); } else { return pht('(Uninstalled Application)'); } return $app->getName(); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorDatasourceEditField()) ->setKey('application') ->setLabel(pht('Application')) ->setDatasource(new PhabricatorApplicationDatasource()) - ->setSingleValue($config->getPanelProperty('application')), + ->setSingleValue($config->getMenuItemProperty('application')), ); } private function getApplication( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); - $phid = $config->getPanelProperty('application'); + $phid = $config->getMenuItemProperty('application'); $app = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); return $app; } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $app = $this->getApplication($config); if (!$app) { return array(); } $is_installed = PhabricatorApplication::isClassInstalledForViewer( get_class($app), $viewer); if (!$is_installed) { return array(); } $item = $this->newItem() ->setHref($app->getApplicationURI()) ->setName($app->getName()) ->setIcon($app->getIcon()); return array( $item, ); } } diff --git a/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php new file mode 100644 index 0000000000..9074b1b117 --- /dev/null +++ b/src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php @@ -0,0 +1,112 @@ +dashboard = $dashboard; + return $this; + } + + public function getDashboard() { + $dashboard = $this->dashboard; + if (!$dashboard) { + return null; + } else if ($dashboard->isArchived()) { + return null; + } + return $dashboard; + } + + public function willBuildNavigationItems(array $items) { + $viewer = $this->getViewer(); + $dashboard_phids = array(); + foreach ($items as $item) { + $dashboard_phids[] = $item->getMenuItemProperty('dashboardPHID'); + } + + $dashboards = id(new PhabricatorDashboardQuery()) + ->setViewer($viewer) + ->withPHIDs($dashboard_phids) + ->execute(); + + $dashboards = mpull($dashboards, null, 'getPHID'); + foreach ($items as $item) { + $dashboard_phid = $item->getMenuItemProperty('dashboardPHID'); + $dashboard = idx($dashboards, $dashboard_phid, null); + $item->getMenuItem()->attachDashboard($dashboard); + } + } + + public function getDisplayName( + PhabricatorProfileMenuItemConfiguration $config) { + $dashboard = $this->getDashboard(); + if (!$dashboard) { + return pht('(Restricted/Invalid Dashboard)'); + } + if (strlen($this->getName($config))) { + return $this->getName($config); + } else { + return $dashboard->getName(); + } + } + + public function buildEditEngineFields( + PhabricatorProfileMenuItemConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setValue($this->getName($config)), + id(new PhabricatorDatasourceEditField()) + ->setKey('dashboardPHID') + ->setLabel(pht('Dashboard')) + ->setDatasource(new PhabricatorDashboardDatasource()) + ->setSingleValue($config->getMenuItemProperty('dashboardPHID')), + ); + } + + private function getName( + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('name'); + } + + protected function newNavigationMenuItems( + PhabricatorProfileMenuItemConfiguration $config) { + + $dashboard = $this->getDashboard(); + if (!$dashboard) { + return array(); + } + + $icon = $dashboard->getIcon(); + $name = $this->getDisplayName($config); + $href = $dashboard->getViewURI(); + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setIcon($icon); + + return array( + $item, + ); + } + +} diff --git a/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php b/src/applications/search/menuitem/PhabricatorDividerProfileMenuItem.php similarity index 65% rename from src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php rename to src/applications/search/menuitem/PhabricatorDividerProfileMenuItem.php index 1458cac56c..255e0d4b72 100644 --- a/src/applications/search/profilepanel/PhabricatorDividerProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorDividerProfileMenuItem.php @@ -1,48 +1,48 @@ setValue( pht( 'This is a visual divider which you can use to separate '. 'sections in the menu. It does not have any configurable '. 'options.')), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $item = $this->newItem() ->addClass('phui-divider'); return array( $item, ); } } diff --git a/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php b/src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php similarity index 65% rename from src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php rename to src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php index 18654dccd3..5571788cc1 100644 --- a/src/applications/search/profilepanel/PhabricatorLinkProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorLinkProfileMenuItem.php @@ -1,94 +1,94 @@ getLinkName($config); } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setIsRequired(true) ->setValue($this->getLinkName($config)), id(new PhabricatorTextEditField()) ->setKey('uri') ->setLabel(pht('URI')) ->setIsRequired(true) ->setValue($this->getLinkURI($config)), id(new PhabricatorIconSetEditField()) ->setKey('icon') ->setLabel(pht('Icon')) - ->setIconSet(new PhabricatorProfilePanelIconSet()) + ->setIconSet(new PhabricatorProfileMenuItemIconSet()) ->setValue($this->getLinkIcon($config)), ); } private function getLinkName( - PhabricatorProfilePanelConfiguration $config) { - return $config->getPanelProperty('name'); + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('name'); } private function getLinkIcon( - PhabricatorProfilePanelConfiguration $config) { - return $config->getPanelProperty('icon', 'link'); + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('icon', 'link'); } private function getLinkURI( - PhabricatorProfilePanelConfiguration $config) { - return $config->getPanelProperty('uri'); + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('uri'); } private function isValidLinkURI($uri) { return PhabricatorEnv::isValidURIForLink($uri); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { $icon = $this->getLinkIcon($config); $name = $this->getLinkName($config); $href = $this->getLinkURI($config); if (!$this->isValidLinkURI($href)) { $href = '#'; } - $icon_object = id(new PhabricatorProfilePanelIconSet()) + $icon_object = id(new PhabricatorProfileMenuItemIconSet()) ->getIcon($icon); if ($icon_object) { $icon_class = $icon_object->getIcon(); } else { $icon_class = 'fa-link'; } $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon_class); return array( $item, ); } } diff --git a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php b/src/applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php similarity index 88% rename from src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php rename to src/applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php index 5a645039ec..f53bc2b0eb 100644 --- a/src/applications/search/profilepanel/PhabricatorMotivatorProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php @@ -1,164 +1,164 @@ getOptions(); - $name = idx($options, $config->getPanelProperty('source')); + $name = idx($options, $config->getMenuItemProperty('source')); if ($name !== null) { return pht('Motivator: %s', $name); } else { return pht('Motivator'); } } public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorInstructionsEditField()) ->setValue( pht( 'Motivate your team with inspirational quotes from great minds. '. - 'This panel shows a new quote every day.')), + 'This menu item shows a new quote every day.')), id(new PhabricatorSelectEditField()) ->setKey('source') ->setLabel(pht('Source')) ->setOptions($this->getOptions()), ); } private function getOptions() { return array( 'catfacts' => pht('Cat Facts'), ); } protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { - $source = $config->getPanelProperty('source'); + $source = $config->getMenuItemProperty('source'); switch ($source) { case 'catfacts': default: $facts = $this->getCatFacts(); break; } $fact = $this->selectFact($facts); switch ($source) { case 'catfacts': default: $fact = array( id(new PHUIIconView())->setIcon('fa-paw'), ' ', $fact, ); break; } $fact = phutil_tag( 'div', array( 'class' => 'phui-motivator', ), $fact); $item = $this->newItem() ->appendChild($fact); return array( $item, ); } private function getCatFacts() { return array( pht('Cats purr when they are happy, upset, or asleep.'), pht('The first cats evolved on the savanah about 8,000 years ago.'), pht( 'Cats have a tail, two feet, between one and three ears, and two '. 'other feet.'), pht('Cats use their keen sense of smell to avoid feeling empathy.'), pht('The first cats evolved in swamps about 65 years ago.'), pht( 'You can tell how warm a cat is by examining the coloration: cooler '. 'areas are darker.'), pht( 'Cat tails are flexible because they contain thousands of tiny '. 'bones.'), pht( 'A cattail is a wetland plant with an appearance that resembles '. 'the tail of a cat.'), pht( 'Cats must eat a diet rich in fish to replace the tiny bones in '. 'their tails.'), pht('Cats are stealthy predators and nearly invisible to radar.'), pht( 'Cats use a special type of magnetism to help them land on their '. 'feet.'), pht( 'A cat can run seven times faster than a human, but only for a '. 'short distance.'), pht( 'The largest recorded cat was nearly 11 inches long from nose to '. 'tail.'), pht( 'Not all cats can retract their claws, but most of them can.'), pht( 'In the wild, cats and racoons sometimes hunt together in packs.'), pht( 'The Spanish word for cat is "cato". The biggest cat is called '. '"el cato".'), pht( 'The Japanese word for cat is "kome", which is also the word for '. 'rice. Japanese cats love to eat rice, so the two are synonymous.'), pht('Cats have five pointy ends.'), pht('cat -A can find mice hiding in files.'), pht('A cat\'s visual, olfactory, and auditory senses, '. 'Contribute to their hunting skills and natural defenses.'), pht( 'Cats with high self-esteem seek out high perches '. 'to launch their attacks. Watch out!'), pht('Cats prefer vanilla ice cream.'), pht('Taco cat spelled backwards is taco cat.'), pht( 'Cats will often bring you their prey because they feel sorry '. 'for your inability to hunt.'), pht('Cats spend most of their time plotting to kill their owner.'), ); } private function selectFact(array $facts) { // This is a simple pseudorandom number generator that avoids touching // srand(), because it would seed it to a highly predictable value. It // selects a new fact every day. $seed = ((int)date('Y') * 366) + (int)date('z'); for ($ii = 0; $ii < 32; $ii++) { $seed = ((1664525 * $seed) + 1013904223) % (1 << 31); } return $facts[$seed % count($facts)]; } } diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanel.php b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php similarity index 53% rename from src/applications/search/profilepanel/PhabricatorProfilePanel.php rename to src/applications/search/menuitem/PhabricatorProfileMenuItem.php index 8fcbd3f96a..c47d9afe8e 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanel.php +++ b/src/applications/search/menuitem/PhabricatorProfileMenuItem.php @@ -1,71 +1,73 @@ newNavigationMenuItems($config); } abstract protected function newNavigationMenuItems( - PhabricatorProfilePanelConfiguration $config); + PhabricatorProfileMenuItemConfiguration $config); - public function getPanelTypeIcon() { + public function willBuildNavigationItems(array $items) {} + + public function getMenuItemTypeIcon() { return null; } - abstract public function getPanelTypeName(); + abstract public function getMenuItemTypeName(); abstract public function getDisplayName( - PhabricatorProfilePanelConfiguration $config); + PhabricatorProfileMenuItemConfiguration $config); public function buildEditEngineFields( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return array(); } public function canAddToObject($object) { return false; } public function shouldEnableForObject($object) { return true; } - public function canHidePanel( - PhabricatorProfilePanelConfiguration $config) { + public function canHideMenuItem( + PhabricatorProfileMenuItemConfiguration $config) { return true; } public function canMakeDefault( - PhabricatorProfilePanelConfiguration $config) { + PhabricatorProfileMenuItemConfiguration $config) { return false; } public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } public function getViewer() { return $this->viewer; } - final public function getPanelKey() { - return $this->getPhobjectClassConstant('PANELKEY'); + final public function getMenuItemKey() { + return $this->getPhobjectClassConstant('MENUITEMKEY'); } - final public static function getAllPanels() { + final public static function getAllMenuItems() { return id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) - ->setUniqueMethod('getPanelKey') + ->setUniqueMethod('getMenuItemKey') ->execute(); } protected function newItem() { return new PHUIListItemView(); } } diff --git a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php b/src/applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php similarity index 94% rename from src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php rename to src/applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php index bc3b15a7cf..74333cc087 100644 --- a/src/applications/search/profilepanel/PhabricatorProfilePanelIconSet.php +++ b/src/applications/search/menuitem/PhabricatorProfileMenuItemIconSet.php @@ -1,72 +1,72 @@ 'link', 'icon' => 'fa-link', 'name' => pht('Link'), ), array( 'key' => 'maniphest', 'icon' => 'fa-anchor', 'name' => pht('Maniphest'), ), array( 'key' => 'feed', 'icon' => 'fa-newspaper-o', 'name' => pht('Feed'), ), array( 'key' => 'phriction', 'icon' => 'fa-book', 'name' => pht('Phriction'), ), array( 'key' => 'conpherence', 'icon' => 'fa-comments', 'name' => pht('Conpherence'), ), array( 'key' => 'differential', 'icon' => 'fa-cog', 'name' => pht('Differential'), ), array( 'key' => 'diffusion', 'icon' => 'fa-code', 'name' => pht('Diffusion'), ), array( 'key' => 'calendar', 'icon' => 'fa-calendar', 'name' => pht('Calendar'), ), array( 'key' => 'create', 'icon' => 'fa-plus', 'name' => pht('Create'), ), ); $icons = array(); foreach ($list as $spec) { $icons[] = id(new PhabricatorIconSetIcon()) ->setKey($spec['key']) ->setIcon($spec['icon']) ->setLabel($spec['name']); } return $icons; } } diff --git a/src/applications/search/menuitem/PhabricatorProjectProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorProjectProfileMenuItem.php new file mode 100644 index 0000000000..002a3fcace --- /dev/null +++ b/src/applications/search/menuitem/PhabricatorProjectProfileMenuItem.php @@ -0,0 +1,113 @@ +project = $project; + return $this; + } + + public function getProject() { + $project = $this->project; + if (!$project) { + return null; + } else if ($project->isArchived()) { + return null; + } + return $project; + } + + public function willBuildNavigationItems(array $items) { + $viewer = $this->getViewer(); + $project_phids = array(); + foreach ($items as $item) { + $project_phids[] = $item->getMenuItemProperty('project'); + } + + $projects = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withPHIDs($project_phids) + ->needImages(true) + ->execute(); + + $projects = mpull($projects, null, 'getPHID'); + foreach ($items as $item) { + $project_phid = $item->getMenuItemProperty('project'); + $project = idx($projects, $project_phid, null); + $item->getMenuItem()->attachProject($project); + } + } + + public function getDisplayName( + PhabricatorProfileMenuItemConfiguration $config) { + $project = $this->getProject(); + if (!$project) { + return pht('(Restricted/Invalid Project)'); + } + if (strlen($this->getName($config))) { + return $this->getName($config); + } else { + return $project->getName(); + } + } + + public function buildEditEngineFields( + PhabricatorProfileMenuItemConfiguration $config) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setValue($this->getName($config)), + id(new PhabricatorDatasourceEditField()) + ->setKey('project') + ->setLabel(pht('Project')) + ->setDatasource(new PhabricatorProjectDatasource()) + ->setSingleValue($config->getMenuItemProperty('project')), + ); + } + + private function getName( + PhabricatorProfileMenuItemConfiguration $config) { + return $config->getMenuItemProperty('name'); + } + + protected function newNavigationMenuItems( + PhabricatorProfileMenuItemConfiguration $config) { + + $project = $this->getProject(); + if (!$project) { + return array(); + } + + $picture = $project->getProfileImageURI(); + $name = $this->getDisplayName($config); + $href = $project->getURI(); + + $item = $this->newItem() + ->setHref($href) + ->setName($name) + ->setProfileImage($picture); + + return array( + $item, + ); + } + +} diff --git a/src/applications/search/phidtype/PhabricatorProfilePanelPHIDType.php b/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php similarity index 69% rename from src/applications/search/phidtype/PhabricatorProfilePanelPHIDType.php rename to src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php index e2285e2543..0fbdcaca48 100644 --- a/src/applications/search/phidtype/PhabricatorProfilePanelPHIDType.php +++ b/src/applications/search/phidtype/PhabricatorProfileMenuItemPHIDType.php @@ -1,39 +1,39 @@ withPHIDs($phids); } public function loadHandles( PhabricatorHandleQuery $query, array $handles, array $objects) { foreach ($handles as $phid => $handle) { $config = $objects[$phid]; - $handle->setName(pht('Profile Panel')); + $handle->setName(pht('Profile Menu Item')); } } } diff --git a/src/applications/search/query/PhabricatorProfilePanelConfigurationQuery.php b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php similarity index 74% rename from src/applications/search/query/PhabricatorProfilePanelConfigurationQuery.php rename to src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php index 52e12581cf..f8172638c3 100644 --- a/src/applications/search/query/PhabricatorProfilePanelConfigurationQuery.php +++ b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationQuery.php @@ -1,102 +1,103 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withProfilePHIDs(array $phids) { $this->profilePHIDs = $phids; return $this; } public function newResultObject() { - return new PhabricatorProfilePanelConfiguration(); + return new PhabricatorProfileMenuItemConfiguration(); } protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->ids !== null) { $where[] = qsprintf( $conn, 'id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn, 'phid IN (%Ls)', $this->phids); } if ($this->profilePHIDs !== null) { $where[] = qsprintf( $conn, 'profilePHID IN (%Ls)', $this->profilePHIDs); } return $where; } protected function willFilterPage(array $page) { - $panels = PhabricatorProfilePanel::getAllPanels(); - foreach ($page as $key => $panel) { - $panel_type = idx($panels, $panel->getPanelKey()); - if (!$panel_type) { - $this->didRejectResult($panel); + $items = PhabricatorProfileMenuItem::getAllMenuItems(); + foreach ($page as $key => $item) { + $item_type = idx($items, $item->getMenuItemKey()); + if (!$item_type) { + $this->didRejectResult($item); unset($page[$key]); continue; } - $panel->attachPanel($panel_type); + $item_type = clone $item_type; + $item->attachMenuItem($item_type); } if (!$page) { return array(); } $profile_phids = mpull($page, 'getProfilePHID'); $profiles = id(new PhabricatorObjectQuery()) ->setViewer($this->getViewer()) ->setParentQuery($this) ->withPHIDs($profile_phids) ->execute(); $profiles = mpull($profiles, null, 'getPHID'); - foreach ($page as $key => $panel) { - $profile = idx($profiles, $panel->getProfilePHID()); + foreach ($page as $key => $item) { + $profile = idx($profiles, $item->getProfilePHID()); if (!$profile) { - $this->didRejectResult($panel); + $this->didRejectResult($item); unset($page[$key]); continue; } - $panel->attachProfileObject($profile); + $item->attachProfileObject($profile); } return $page; } public function getQueryApplicationClass() { return 'PhabricatorSearchApplication'; } } diff --git a/src/applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php new file mode 100644 index 0000000000..0023660512 --- /dev/null +++ b/src/applications/search/query/PhabricatorProfileMenuItemConfigurationTransactionQuery.php @@ -0,0 +1,10 @@ +setVisibility(self::VISIBILITY_VISIBLE); } - public static function initializeNewPanelConfiguration( + public static function initializeNewItem( $profile_object, - PhabricatorProfilePanel $panel) { + PhabricatorProfileMenuItem $item) { return self::initializeNewBuiltin() ->setProfilePHID($profile_object->getPHID()) - ->setPanelKey($panel->getPanelKey()) - ->attachPanel($panel) + ->setMenuItemKey($item->getMenuItemKey()) + ->attachMenuItem($item) ->attachProfileObject($profile_object); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( - 'panelProperties' => self::SERIALIZATION_JSON, + 'menuItemProperties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( - 'panelKey' => 'text64', + 'menuItemKey' => 'text64', 'builtinKey' => 'text64?', - 'panelOrder' => 'uint32?', + 'menuItemOrder' => 'uint32?', 'visibility' => 'text32', ), self::CONFIG_KEY_SCHEMA => array( 'key_profile' => array( - 'columns' => array('profilePHID', 'panelOrder'), + 'columns' => array('profilePHID', 'menuItemOrder'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( - PhabricatorProfilePanelPHIDType::TYPECONST); + PhabricatorProfileMenuItemPHIDType::TYPECONST); } - public function attachPanel(PhabricatorProfilePanel $panel) { - $this->panel = $panel; + public function attachMenuItem(PhabricatorProfileMenuItem $item) { + $this->menuItem = $item; return $this; } - public function getPanel() { - return $this->assertAttached($this->panel); + public function getMenuItem() { + return $this->assertAttached($this->menuItem); } public function attachProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } public function getProfileObject() { return $this->assertAttached($this->profileObject); } - public function setPanelProperty($key, $value) { - $this->panelProperties[$key] = $value; + public function setMenuItemProperty($key, $value) { + $this->menuItemProperties[$key] = $value; return $this; } - public function getPanelProperty($key, $default = null) { - return idx($this->panelProperties, $key, $default); + public function getMenuItemProperty($key, $default = null) { + return idx($this->menuItemProperties, $key, $default); } public function buildNavigationMenuItems() { - return $this->getPanel()->buildNavigationMenuItems($this); + return $this->getMenuItem()->buildNavigationMenuItems($this); } - public function getPanelTypeName() { - return $this->getPanel()->getPanelTypeName(); + public function getMenuItemTypeName() { + return $this->getMenuItem()->getMenuItemTypeName(); } public function getDisplayName() { - return $this->getPanel()->getDisplayName($this); + return $this->getMenuItem()->getDisplayName($this); } public function canMakeDefault() { - return $this->getPanel()->canMakeDefault($this); + return $this->getMenuItem()->canMakeDefault($this); } - public function canHidePanel() { - return $this->getPanel()->canHidePanel($this); + public function canHideMenuItem() { + return $this->getMenuItem()->canHideMenuItem($this); } public function shouldEnableForObject($object) { - return $this->getPanel()->shouldEnableForObject($object); + return $this->getMenuItem()->shouldEnableForObject($object); + } + + public function willBuildNavigationItems(array $items) { + return $this->getMenuItem()->willBuildNavigationItems($items); } public function getSortKey() { - $order = $this->getPanelOrder(); + $order = $this->getMenuItemOrder(); if ($order === null) { $order = 'Z'; } else { $order = sprintf('%020d', $order); } return sprintf( '~%s%020d', $order, $this->getID()); } public function isDisabled() { - if (!$this->canHidePanel()) { + if (!$this->canHideMenuItem()) { return false; } return ($this->getVisibility() === self::VISIBILITY_DISABLED); } public function isDefault() { return ($this->getVisibility() === self::VISIBILITY_DEFAULT); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { return PhabricatorPolicies::getMostOpenPolicy(); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return $this->getProfileObject()->hasAutomaticCapability( $capability, $viewer); } /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ public function getExtendedPolicy($capability, PhabricatorUser $viewer) { return array( array( $this->getProfileObject(), $capability, ), ); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { - return new PhabricatorProfilePanelEditor(); + return new PhabricatorProfileMenuEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { - return new PhabricatorProfilePanelConfigurationTransaction(); + return new PhabricatorProfileMenuItemConfigurationTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } } diff --git a/src/applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php b/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php similarity index 59% rename from src/applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php rename to src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php index 28181cb217..b1d30a5b9d 100644 --- a/src/applications/search/storage/PhabricatorProfilePanelConfigurationTransaction.php +++ b/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php @@ -1,22 +1,27 @@ buildEdgeSchemata(new PhabricatorProfilePanelConfiguration()); + $this->buildEdgeSchemata(new PhabricatorProfileMenuItemConfiguration()); $this->buildRawSchema( 'search', PhabricatorSearchDocument::STOPWORDS_TABLE, array( 'value' => 'sort32', ), array()); } } diff --git a/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php b/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php index d12db30f83..ac950eade1 100644 --- a/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php +++ b/src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php @@ -1,223 +1,223 @@ getViewer(); $preferences = $this->getPreferences(); $pinned_key = PhabricatorPinnedApplicationsSetting::SETTINGKEY; $pinned = $preferences->getSettingValue($pinned_key); $apps = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) ->withInstalled(true) ->withUnlisted(false) ->withLaunchable(true) ->execute(); $app_list = array(); foreach ($pinned as $app) { if (isset($apps[$app])) { $app_list[$app] = $apps[$app]; } } if ($request->getBool('reset')) { if ($request->isFormPost()) { $this->writePinnedApplications($preferences, null); return id(new AphrontRedirectResponse()) ->setURI($this->getPanelURI()); } return $this->newDialog() ->setTitle(pht('Reset Applications')) ->addHiddenInput('reset', 'true') ->appendParagraph( pht('Reset pinned applications to their defaults?')) ->addSubmitButton(pht('Reset Applications')) ->addCancelButton($this->getPanelURI()); } if ($request->getBool('add')) { $options = array(); foreach ($apps as $app) { $options[get_class($app)] = $app->getName(); } asort($options); unset($options['PhabricatorApplicationsApplication']); if ($request->isFormPost()) { $pins = $request->getArr('pin'); $phid = head($pins); $app = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); if ($app) { $pin = get_class($app); } else { // This likely means the user submitted an empty form // which will cause nothing to happen. $pin = ''; } if (isset($options[$pin]) && !in_array($pin, $pinned)) { $pinned[] = $pin; $this->writePinnedApplications($preferences, $pinned); return id(new AphrontRedirectResponse()) ->setURI($this->getPanelURI()); } } $options_control = id(new AphrontFormTokenizerControl()) ->setName('pin') ->setLabel(pht('Application')) ->setDatasource(new PhabricatorApplicationDatasource()) ->setLimit(1); $form = id(new AphrontFormView()) ->setViewer($viewer) ->addHiddenInput('add', 'true') ->appendRemarkupInstructions( pht('Choose an application to pin to your home page.')) ->appendControl($options_control); return $this->newDialog() ->setWidth(AphrontDialogView::WIDTH_FORM) ->setTitle(pht('Pin Application')) ->appendChild($form->buildLayoutView()) ->addSubmitButton(pht('Pin Application')) ->addCancelButton($this->getPanelURI()); } $unpin = $request->getStr('unpin'); if ($unpin) { $app = idx($apps, $unpin); if ($app) { if ($request->isFormPost()) { $pinned = array_diff($pinned, array($unpin)); $this->writePinnedApplications($preferences, $pinned); return id(new AphrontRedirectResponse()) ->setURI($this->getPanelURI()); } return $this->newDialog() ->setTitle(pht('Unpin Application')) ->addHiddenInput('unpin', $unpin) ->appendParagraph( pht( 'Unpin the %s application from your home page?', phutil_tag('strong', array(), $app->getName()))) ->addSubmitButton(pht('Unpin Application')) ->addCancelButton($this->getPanelURI()); } } $order = $request->getStrList('order'); if ($order && $request->validateCSRF()) { $this->writePinnedApplications($preferences, $order); return id(new AphrontRedirectResponse()) ->setURI($this->getPanelURI()); } $list_id = celerity_generate_unique_node_id(); $list = id(new PHUIObjectItemListView()) ->setViewer($viewer) - ->setID($list_id); + ->setID($list_id) + ->setDrag(true); Javelin::initBehavior( 'reorder-applications', array( 'listID' => $list_id, 'panelURI' => $this->getPanelURI(), )); foreach ($app_list as $key => $application) { if ($key == 'PhabricatorApplicationsApplication') { continue; } $icon = $application->getIcon(); if (!$icon) { $icon = 'fa-globe'; } $item = id(new PHUIObjectItemView()) ->setHeader($application->getName()) ->setImageIcon($icon) - ->addAttribute($application->getShortDescription()) ->setGrippable(true); $item->addAction( id(new PHUIListItemView()) ->setIcon('fa-times') ->setHref($this->getPanelURI().'?unpin='.$key) ->setWorkflow(true)); $item->addSigil('pinned-application'); $item->setMetadata( array( 'applicationClass' => $key, )); $list->addItem($item); } $header = id(new PHUIHeaderView()) ->setHeader(pht('Pinned Applications')) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Pin Application')) ->setHref($this->getPanelURI().'?add=true') ->setWorkflow(true) ->setIcon('fa-thumb-tack')) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Reset to Defaults')) ->setHref($this->getPanelURI().'?reset=true') ->setWorkflow(true) ->setIcon('fa-recycle')); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->setObjectList($list); return $box; } private function writePinnedApplications( PhabricatorUserPreferences $preferences, $pinned) { $pinned_key = PhabricatorPinnedApplicationsSetting::SETTINGKEY; $this->writeSetting($preferences, $pinned_key, $pinned); } } diff --git a/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php b/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php index a0a6cbf7be..ac0d3896cc 100644 --- a/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php +++ b/src/applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php @@ -1,70 +1,74 @@ getPHID(); if ($object_phid) { $sub_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID( $object_phid); } else { $sub_phids = array(); } $subscribers_field = id(new PhabricatorSubscribersEditField()) ->setKey('subscriberPHIDs') ->setLabel(pht('Subscribers')) ->setEditTypeKey('subscribers') ->setAliases(array('subscriber', 'subscribers')) ->setIsCopyable(true) ->setUseEdgeTransactions(true) ->setCommentActionLabel(pht('Change Subscribers')) ->setCommentActionOrder(9000) ->setDescription(pht('Choose subscribers.')) ->setTransactionType($subscribers_type) ->setValue($sub_phids); $subscribers_field->setViewer($engine->getViewer()); - $edit_add = $subscribers_field->getConduitEditType('subscribers.add') + $edit_add = $subscribers_field->getConduitEditType(self::EDITKEY_ADD) ->setConduitDescription(pht('Add subscribers.')); - $edit_set = $subscribers_field->getConduitEditType('subscribers.set') + $edit_set = $subscribers_field->getConduitEditType(self::EDITKEY_SET) ->setConduitDescription( pht('Set subscribers, overwriting current value.')); - $edit_rem = $subscribers_field->getConduitEditType('subscribers.remove') + $edit_rem = $subscribers_field->getConduitEditType(self::EDITKEY_REMOVE) ->setConduitDescription(pht('Remove subscribers.')); return array( $subscribers_field, ); } } diff --git a/src/applications/transactions/editfield/PhabricatorCommentEditField.php b/src/applications/transactions/editfield/PhabricatorCommentEditField.php index 5d9c2b54da..f04002ed92 100644 --- a/src/applications/transactions/editfield/PhabricatorCommentEditField.php +++ b/src/applications/transactions/editfield/PhabricatorCommentEditField.php @@ -1,26 +1,45 @@ isWebOnly = $is_web_only; + return $this; + } + + public function getIsWebOnly() { + return $this->isWebOnly; + } + protected function newControl() { return new PhabricatorRemarkupControl(); } protected function newEditType() { return new PhabricatorCommentEditType(); } protected function newConduitParameterType() { - return new ConduitStringParameterType(); + if ($this->getIsWebOnly()) { + return null; + } else { + return new ConduitStringParameterType(); + } } public function shouldGenerateTransactionsFromSubmit() { - return false; + return !$this->isPrimaryCommentField(); } public function shouldGenerateTransactionsFromComment() { - return true; + return $this->isPrimaryCommentField(); + } + + private function isPrimaryCommentField() { + return ($this->getKey() === 'comment'); } } diff --git a/src/applications/transactions/editfield/PhabricatorDividerEditField.php b/src/applications/transactions/editfield/PhabricatorDividerEditField.php new file mode 100644 index 0000000000..553c5256bc --- /dev/null +++ b/src/applications/transactions/editfield/PhabricatorDividerEditField.php @@ -0,0 +1,18 @@ +setValue($this->getValue()); + } + + protected function newHTTPParameterType() { + return null; + } + + protected function newConduitParameterType() { + return null; + } + +} diff --git a/src/applications/transactions/edittype/PhabricatorEditType.php b/src/applications/transactions/edittype/PhabricatorEditType.php index 298238aeb1..1451ec2c04 100644 --- a/src/applications/transactions/edittype/PhabricatorEditType.php +++ b/src/applications/transactions/edittype/PhabricatorEditType.php @@ -1,158 +1,165 @@ label = $label; return $this; } public function getLabel() { return $this->label; } 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 generateTransactions( PhabricatorApplicationTransaction $template, array $spec); protected function newTransaction( PhabricatorApplicationTransaction $template) { $xaction = id(clone $template) ->setTransactionType($this->getTransactionType()); foreach ($this->getMetadata() as $key => $value) { $xaction->setMetadataValue($key, $value); } return $xaction; } public function setEditField(PhabricatorEditField $edit_field) { $this->editField = $edit_field; return $this; } public function getEditField() { return $this->editField; } /* -( Conduit )------------------------------------------------------------ */ protected function newConduitParameterType() { if ($this->conduitParameterType) { return clone $this->conduitParameterType; } return null; } public function setConduitParameterType(ConduitParameterType $type) { $this->conduitParameterType = $type; return $this; } public function getConduitParameterType() { return $this->newConduitParameterType(); } public function getConduitType() { $parameter_type = $this->getConduitParameterType(); + if (!$parameter_type) { + throw new Exception( + pht( + 'Edit type (with key "%s") is missing a Conduit parameter type.', + $this->getEditType())); + } + return $parameter_type->getTypeName(); } public function setConduitTypeDescription($conduit_type_description) { $this->conduitTypeDescription = $conduit_type_description; return $this; } public function getConduitTypeDescription() { if ($this->conduitTypeDescription === null) { if ($this->getEditField()) { return $this->getEditField()->getConduitTypeDescription(); } } return $this->conduitTypeDescription; } public function setConduitDescription($conduit_description) { $this->conduitDescription = $conduit_description; return $this; } public function getConduitDescription() { if ($this->conduitDescription === null) { if ($this->getEditField()) { return $this->getEditField()->getConduitDescription(); } } return $this->conduitDescription; } public function setConduitDocumentation($conduit_documentation) { $this->conduitDocumentation = $conduit_documentation; return $this; } public function getConduitDocumentation() { if ($this->conduitDocumentation === null) { if ($this->getEditField()) { return $this->getEditField()->getConduitDocumentation(); } } return $this->conduitDocumentation; } } diff --git a/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php b/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php index a0a303bdc7..7eb2aee037 100644 --- a/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php +++ b/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php @@ -1,60 +1,61 @@ getApplicationTransactionTemplate(); try { $comment = $xaction->getApplicationTransactionCommentObject(); } catch (PhutilMethodNotImplementedException $ex) { $comment = null; } return (bool)$comment; } public function buildCustomEditFields( PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $comment_type = PhabricatorTransactions::TYPE_COMMENT; $comment_field = id(new PhabricatorCommentEditField()) - ->setKey('comment') + ->setKey(self::EDITKEY) ->setLabel(pht('Comments')) ->setAliases(array('comments')) ->setIsHidden(true) ->setIsReorderable(false) ->setIsDefaultable(false) ->setIsLockable(false) ->setTransactionType($comment_type) ->setConduitDescription(pht('Make comments.')) ->setConduitTypeDescription( pht('Comment to add, formatted as remarkup.')) ->setValue(null); return array( $comment_field, ); } } diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index cc583d34c2..8157166bb4 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -1,1662 +1,1671 @@ ignoreOnNoEffect = $ignore; return $this; } public function getIgnoreOnNoEffect() { return $this->ignoreOnNoEffect; } public function shouldGenerateOldValue() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_BUILDABLE: case PhabricatorTransactions::TYPE_TOKEN: case PhabricatorTransactions::TYPE_CUSTOMFIELD: case PhabricatorTransactions::TYPE_INLINESTATE: return false; } return true; } abstract public function getApplicationTransactionType(); private function getApplicationObjectTypeName() { $types = PhabricatorPHIDType::getAllTypes(); $type = idx($types, $this->getApplicationTransactionType()); if ($type) { return $type->getTypeName(); } return pht('Object'); } public function getApplicationTransactionCommentObject() { throw new PhutilMethodNotImplementedException(); } public function getApplicationTransactionViewObject() { return new PhabricatorApplicationTransactionView(); } public function getMetadataValue($key, $default = null) { return idx($this->metadata, $key, $default); } public function setMetadataValue($key, $value) { $this->metadata[$key] = $value; return $this; } public function generatePHID() { $type = PhabricatorApplicationTransactionTransactionPHIDType::TYPECONST; $subtype = $this->getApplicationTransactionType(); return PhabricatorPHID::generateNewPHID($type, $subtype); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'oldValue' => self::SERIALIZATION_JSON, 'newValue' => self::SERIALIZATION_JSON, 'metadata' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'commentPHID' => 'phid?', 'commentVersion' => 'uint32', 'contentSource' => 'text', 'transactionType' => 'text32', ), self::CONFIG_KEY_SCHEMA => array( 'key_object' => array( 'columns' => array('objectPHID'), ), ), ) + parent::getConfiguration(); } public function setContentSource(PhabricatorContentSource $content_source) { $this->contentSource = $content_source->serialize(); return $this; } public function getContentSource() { return PhabricatorContentSource::newFromSerialized($this->contentSource); } public function hasComment() { return $this->getComment() && strlen($this->getComment()->getContent()); } public function getComment() { if ($this->commentNotLoaded) { throw new Exception(pht('Comment for this transaction was not loaded.')); } return $this->comment; } public function setIsCreateTransaction($create) { return $this->setMetadataValue('core.create', $create); } public function getIsCreateTransaction() { return (bool)$this->getMetadataValue('core.create', false); } public function setIsDefaultTransaction($default) { return $this->setMetadataValue('core.default', $default); } public function getIsDefaultTransaction() { return (bool)$this->getMetadataValue('core.default', false); } public function attachComment( PhabricatorApplicationTransactionComment $comment) { $this->comment = $comment; $this->commentNotLoaded = false; return $this; } public function setCommentNotLoaded($not_loaded) { $this->commentNotLoaded = $not_loaded; return $this; } public function attachObject($object) { $this->object = $object; return $this; } public function getObject() { return $this->assertAttached($this->object); } public function getRemarkupChanges() { $changes = $this->newRemarkupChanges(); assert_instances_of($changes, 'PhabricatorTransactionRemarkupChange'); // Convert older-style remarkup blocks into newer-style remarkup changes. // This builds changes that do not have the correct "old value", so rules // that operate differently against edits (like @user mentions) won't work // properly. foreach ($this->getRemarkupBlocks() as $block) { $changes[] = $this->newRemarkupChange() ->setOldValue(null) ->setNewValue($block); } $comment = $this->getComment(); if ($comment) { if ($comment->hasOldComment()) { $old_value = $comment->getOldComment()->getContent(); } else { $old_value = null; } $new_value = $comment->getContent(); $changes[] = $this->newRemarkupChange() ->setOldValue($old_value) ->setNewValue($new_value); } return $changes; } protected function newRemarkupChanges() { return array(); } protected function newRemarkupChange() { return id(new PhabricatorTransactionRemarkupChange()) ->setTransaction($this); } /** * @deprecated */ public function getRemarkupBlocks() { $blocks = array(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { $custom_blocks = $field->getApplicationTransactionRemarkupBlocks( $this); foreach ($custom_blocks as $custom_block) { $blocks[] = $custom_block; } } break; } return $blocks; } public function setOldValue($value) { $this->oldValueHasBeenSet = true; $this->writeField('oldValue', $value); return $this; } public function hasOldValue() { return $this->oldValueHasBeenSet; } /* -( Rendering )---------------------------------------------------------- */ public function setRenderingTarget($rendering_target) { $this->renderingTarget = $rendering_target; return $this; } public function getRenderingTarget() { return $this->renderingTarget; } public function attachViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } public function getViewer() { return $this->assertAttached($this->viewer); } public function getRequiredHandlePHIDs() { $phids = array(); $old = $this->getOldValue(); $new = $this->getNewValue(); $phids[] = array($this->getAuthorPHID()); $phids[] = array($this->getObjectPHID()); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { $phids[] = $field->getApplicationTransactionRequiredHandlePHIDs( $this); } break; case PhabricatorTransactions::TYPE_SUBSCRIBERS: $phids[] = $old; $phids[] = $new; break; case PhabricatorTransactions::TYPE_EDGE: $phids[] = ipull($old, 'dst'); $phids[] = ipull($new, 'dst'); break; case PhabricatorTransactions::TYPE_COLUMNS: foreach ($new as $move) { $phids[] = array( $move['columnPHID'], $move['boardPHID'], ); $phids[] = $move['fromColumnPHIDs']; } break; case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: if (!PhabricatorPolicyQuery::isSpecialPolicy($old)) { $phids[] = array($old); } if (!PhabricatorPolicyQuery::isSpecialPolicy($new)) { $phids[] = array($new); } break; case PhabricatorTransactions::TYPE_SPACE: if ($old) { $phids[] = array($old); } if ($new) { $phids[] = array($new); } break; case PhabricatorTransactions::TYPE_TOKEN: break; case PhabricatorTransactions::TYPE_BUILDABLE: $phid = $this->getMetadataValue('harbormaster:buildablePHID'); if ($phid) { $phids[] = array($phid); } break; } if ($this->getComment()) { $phids[] = array($this->getComment()->getAuthorPHID()); } return array_mergev($phids); } public function setHandles(array $handles) { $this->handles = $handles; return $this; } public function getHandle($phid) { if (empty($this->handles[$phid])) { throw new Exception( pht( 'Transaction ("%s", of type "%s") requires a handle ("%s") that it '. 'did not load.', $this->getPHID(), $this->getTransactionType(), $phid)); } return $this->handles[$phid]; } public function getHandleIfExists($phid) { return idx($this->handles, $phid); } public function getHandles() { if ($this->handles === null) { throw new Exception( pht('Transaction requires handles and it did not load them.')); } return $this->handles; } public function renderHandleLink($phid) { if ($this->renderingTarget == self::TARGET_HTML) { return $this->getHandle($phid)->renderLink(); } else { return $this->getHandle($phid)->getLinkName(); } } public function renderHandleList(array $phids) { $links = array(); foreach ($phids as $phid) { $links[] = $this->renderHandleLink($phid); } if ($this->renderingTarget == self::TARGET_HTML) { return phutil_implode_html(', ', $links); } else { return implode(', ', $links); } } private function renderSubscriberList(array $phids, $change_type) { if ($this->getRenderingTarget() == self::TARGET_TEXT) { return $this->renderHandleList($phids); } else { $handles = array_select_keys($this->getHandles(), $phids); return id(new SubscriptionListStringBuilder()) ->setHandles($handles) ->setObjectPHID($this->getPHID()) ->buildTransactionString($change_type); } } protected function renderPolicyName($phid, $state = 'old') { $policy = PhabricatorPolicy::newFromPolicyAndHandle( $phid, $this->getHandleIfExists($phid)); if ($this->renderingTarget == self::TARGET_HTML) { switch ($policy->getType()) { case PhabricatorPolicyType::TYPE_CUSTOM: $policy->setHref('/transactions/'.$state.'/'.$this->getPHID().'/'); $policy->setWorkflow(true); break; default: break; } $output = $policy->renderDescription(); } else { $output = hsprintf('%s', $policy->getFullName()); } return $output; } public function getIcon() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: $comment = $this->getComment(); if ($comment && $comment->getIsRemoved()) { return 'fa-trash'; } return 'fa-comment'; case PhabricatorTransactions::TYPE_SUBSCRIBERS: $old = $this->getOldValue(); $new = $this->getNewValue(); $add = array_diff($new, $old); $rem = array_diff($old, $new); if ($add && $rem) { return 'fa-user'; } else if ($add) { return 'fa-user-plus'; } else if ($rem) { return 'fa-user-times'; } else { return 'fa-user'; } case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: return 'fa-lock'; case PhabricatorTransactions::TYPE_EDGE: return 'fa-link'; case PhabricatorTransactions::TYPE_BUILDABLE: return 'fa-wrench'; case PhabricatorTransactions::TYPE_TOKEN: return 'fa-trophy'; case PhabricatorTransactions::TYPE_SPACE: return 'fa-th-large'; case PhabricatorTransactions::TYPE_COLUMNS: return 'fa-columns'; } return 'fa-pencil'; } public function getToken() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_TOKEN: $old = $this->getOldValue(); $new = $this->getNewValue(); if ($new) { $icon = substr($new, 10); } else { $icon = substr($old, 10); } return array($icon, !$this->getNewValue()); } return array(null, null); } public function getColor() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT; $comment = $this->getComment(); if ($comment && $comment->getIsRemoved()) { return 'black'; } break; case PhabricatorTransactions::TYPE_BUILDABLE: switch ($this->getNewValue()) { case HarbormasterBuildable::STATUS_PASSED: return 'green'; case HarbormasterBuildable::STATUS_FAILED: return 'red'; } break; } return null; } protected function getTransactionCustomField() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CUSTOMFIELD: $key = $this->getMetadataValue('customfield:key'); if (!$key) { return null; } $object = $this->getObject(); if (!($object instanceof PhabricatorCustomFieldInterface)) { return null; } $field = PhabricatorCustomField::getObjectField( $object, PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS, $key); if (!$field) { return null; } $field->setViewer($this->getViewer()); return $field; } return null; } public function shouldHide() { // Never hide comments. if ($this->hasComment()) { return false; } // Hide creation transactions if the old value is empty. These are // transactions like "alice set the task tile to: ...", which are // essentially never interesting. if ($this->getIsCreateTransaction()) { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_SPACE: break; default: $old = $this->getOldValue(); if (is_array($old) && !$old) { return true; } if (!is_array($old)) { if (!strlen($old)) { return true; } // The integer 0 is also uninteresting by default; this is often // an "off" flag for something like "All Day Event". if ($old === 0) { return true; } } break; } } // Hide creation transactions setting values to defaults, even if // the old value is not empty. For example, tasks may have a global // default view policy of "All Users", but a particular form sets the // policy to "Administrators". The transaction corresponding to this // change is not interesting, since it is the default behavior of the // form. if ($this->getIsCreateTransaction()) { if ($this->getIsDefaultTransaction()) { return true; } } switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_SPACE: if ($this->getIsCreateTransaction()) { break; } // TODO: Remove this eventually, this is handling old changes during // object creation prior to the introduction of "create" and "default" // transaction display flags. // NOTE: We can also hit this case with Space transactions that later // update a default space (`null`) to an explicit space, so handling // the Space case may require some finesse. if ($this->getOldValue() === null) { return true; } else { return false; } break; case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { return $field->shouldHideInApplicationTransactions($this); } break; case PhabricatorTransactions::TYPE_COLUMNS: return !$this->getInterestingMoves($this->getNewValue()); case PhabricatorTransactions::TYPE_EDGE: $edge_type = $this->getMetadataValue('edge:type'); switch ($edge_type) { case PhabricatorObjectMentionsObjectEdgeType::EDGECONST: case ManiphestTaskHasDuplicateTaskEdgeType::EDGECONST: case ManiphestTaskIsDuplicateOfTaskEdgeType::EDGECONST: return true; break; case PhabricatorObjectMentionedByObjectEdgeType::EDGECONST: $new = ipull($this->getNewValue(), 'dst'); $old = ipull($this->getOldValue(), 'dst'); $add = array_diff($new, $old); $add_value = reset($add); $add_handle = $this->getHandle($add_value); if ($add_handle->getPolicyFiltered()) { return true; } return false; break; default: break; } break; } return false; } public function shouldHideForMail(array $xactions) { if ($this->isSelfSubscription()) { return true; } switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_TOKEN: return true; case PhabricatorTransactions::TYPE_BUILDABLE: switch ($this->getNewValue()) { case HarbormasterBuildable::STATUS_FAILED: // For now, only ever send mail when builds fail. We might let // you customize this later, but in most cases this is probably // completely uninteresting. return false; } return true; case PhabricatorTransactions::TYPE_EDGE: $edge_type = $this->getMetadataValue('edge:type'); switch ($edge_type) { case PhabricatorObjectMentionsObjectEdgeType::EDGECONST: case PhabricatorObjectMentionedByObjectEdgeType::EDGECONST: return true; case PhabricatorProjectObjectHasProjectEdgeType::EDGECONST: // When an object is first created, we hide any corresponding // project transactions in the web UI because you can just look at // the UI element elsewhere on screen to see which projects it // is tagged with. However, in mail there's no other way to get // this information, and it has some amount of value to users, so // we keep the transaction. See T10493. return false; default: break; } break; } if ($this->isInlineCommentTransaction()) { $inlines = array(); // If there's a normal comment, we don't need to publish the inline // transaction, since the normal comment covers things. foreach ($xactions as $xaction) { if ($xaction->isInlineCommentTransaction()) { $inlines[] = $xaction; continue; } // We found a normal comment, so hide this inline transaction. if ($xaction->hasComment()) { return true; } } // If there are several inline comments, only publish the first one. if ($this !== head($inlines)) { return true; } } return $this->shouldHide(); } public function shouldHideForFeed() { if ($this->isSelfSubscription()) { return true; } switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_TOKEN: return true; case PhabricatorTransactions::TYPE_BUILDABLE: switch ($this->getNewValue()) { case HarbormasterBuildable::STATUS_FAILED: // For now, don't notify on build passes either. These are pretty // high volume and annoying, with very little present value. We // might want to turn them back on in the specific case of // build successes on the current document? return false; } return true; case PhabricatorTransactions::TYPE_EDGE: $edge_type = $this->getMetadataValue('edge:type'); switch ($edge_type) { case PhabricatorObjectMentionsObjectEdgeType::EDGECONST: case PhabricatorObjectMentionedByObjectEdgeType::EDGECONST: return true; break; default: break; } break; case PhabricatorTransactions::TYPE_INLINESTATE: return true; } return $this->shouldHide(); } public function getTitleForMail() { return id(clone $this)->setRenderingTarget('text')->getTitle(); } public function getTitleForHTMLMail() { $title = $this->getTitleForMail(); if ($title === null) { return null; } if ($this->hasChangeDetails()) { $details_uri = $this->getChangeDetailsURI(); $details_uri = PhabricatorEnv::getProductionURI($details_uri); $show_details = phutil_tag( 'a', array( 'href' => $details_uri, ), pht('(Show Details)')); $title = array($title, ' ', $show_details); } return $title; } public function getChangeDetailsURI() { return '/transactions/detail/'.$this->getPHID().'/'; } public function getBodyForMail() { if ($this->isInlineCommentTransaction()) { // We don't return inline comment content as mail body content, because // applications need to contextualize it (by adding line numbers, for // example) in order for it to make sense. return null; } $comment = $this->getComment(); if ($comment && strlen($comment->getContent())) { return $comment->getContent(); } return null; } public function getNoEffectDescription() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: return pht('You can not post an empty comment.'); case PhabricatorTransactions::TYPE_VIEW_POLICY: return pht( 'This %s already has that view policy.', $this->getApplicationObjectTypeName()); case PhabricatorTransactions::TYPE_EDIT_POLICY: return pht( 'This %s already has that edit policy.', $this->getApplicationObjectTypeName()); case PhabricatorTransactions::TYPE_JOIN_POLICY: return pht( 'This %s already has that join policy.', $this->getApplicationObjectTypeName()); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return pht( 'All users are already subscribed to this %s.', $this->getApplicationObjectTypeName()); case PhabricatorTransactions::TYPE_SPACE: return pht('This object is already in that space.'); case PhabricatorTransactions::TYPE_EDGE: return pht('Edges already exist; transaction has no effect.'); case PhabricatorTransactions::TYPE_COLUMNS: return pht( 'You have not moved this object to any columns it is not '. 'already in.'); } return pht( 'Transaction (of type "%s") has no effect.', $this->getTransactionType()); } public function getTitle() { $author_phid = $this->getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: return pht( '%s created this object.', $this->renderHandleLink($author_phid)); case PhabricatorTransactions::TYPE_COMMENT: return pht( '%s added a comment.', $this->renderHandleLink($author_phid)); case PhabricatorTransactions::TYPE_VIEW_POLICY: if ($this->getIsCreateTransaction()) { return pht( '%s created this object with visibility "%s".', $this->renderHandleLink($author_phid), $this->renderPolicyName($new, 'new')); } else { return pht( '%s changed the visibility from "%s" to "%s".', $this->renderHandleLink($author_phid), $this->renderPolicyName($old, 'old'), $this->renderPolicyName($new, 'new')); } case PhabricatorTransactions::TYPE_EDIT_POLICY: if ($this->getIsCreateTransaction()) { return pht( '%s created this object with edit policy "%s".', $this->renderHandleLink($author_phid), $this->renderPolicyName($new, 'new')); } else { return pht( '%s changed the edit policy from "%s" to "%s".', $this->renderHandleLink($author_phid), $this->renderPolicyName($old, 'old'), $this->renderPolicyName($new, 'new')); } case PhabricatorTransactions::TYPE_JOIN_POLICY: if ($this->getIsCreateTransaction()) { return pht( '%s created this object with join policy "%s".', $this->renderHandleLink($author_phid), $this->renderPolicyName($new, 'new')); } else { return pht( '%s changed the join policy from "%s" to "%s".', $this->renderHandleLink($author_phid), $this->renderPolicyName($old, 'old'), $this->renderPolicyName($new, 'new')); } case PhabricatorTransactions::TYPE_SPACE: if ($this->getIsCreateTransaction()) { return pht( '%s created this object in space %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($new)); } else { return pht( '%s shifted this object from the %s space to the %s space.', $this->renderHandleLink($author_phid), $this->renderHandleLink($old), $this->renderHandleLink($new)); } case PhabricatorTransactions::TYPE_SUBSCRIBERS: $add = array_diff($new, $old); $rem = array_diff($old, $new); if ($add && $rem) { return pht( '%s edited subscriber(s), added %d: %s; removed %d: %s.', $this->renderHandleLink($author_phid), count($add), $this->renderSubscriberList($add, 'add'), count($rem), $this->renderSubscriberList($rem, 'rem')); } else if ($add) { return pht( '%s added %d subscriber(s): %s.', $this->renderHandleLink($author_phid), count($add), $this->renderSubscriberList($add, 'add')); } else if ($rem) { return pht( '%s removed %d subscriber(s): %s.', $this->renderHandleLink($author_phid), count($rem), $this->renderSubscriberList($rem, 'rem')); } else { // This is used when rendering previews, before the user actually // selects any CCs. return pht( '%s updated subscribers...', $this->renderHandleLink($author_phid)); } break; case PhabricatorTransactions::TYPE_EDGE: $new = ipull($new, 'dst'); $old = ipull($old, 'dst'); $add = array_diff($new, $old); $rem = array_diff($old, $new); $type = $this->getMetadata('edge:type'); $type = head($type); $type_obj = PhabricatorEdgeType::getByConstant($type); if ($add && $rem) { return $type_obj->getTransactionEditString( $this->renderHandleLink($author_phid), new PhutilNumber(count($add) + count($rem)), phutil_count($add), $this->renderHandleList($add), phutil_count($rem), $this->renderHandleList($rem)); } else if ($add) { return $type_obj->getTransactionAddString( $this->renderHandleLink($author_phid), phutil_count($add), $this->renderHandleList($add)); } else if ($rem) { return $type_obj->getTransactionRemoveString( $this->renderHandleLink($author_phid), phutil_count($rem), $this->renderHandleList($rem)); } else { return $type_obj->getTransactionPreviewString( $this->renderHandleLink($author_phid)); } case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { return $field->getApplicationTransactionTitle($this); } else { - return pht( - '%s edited a custom field.', - $this->renderHandleLink($author_phid)); + $developer_mode = 'phabricator.developer-mode'; + $is_developer = PhabricatorEnv::getEnvConfig($developer_mode); + if ($is_developer) { + return pht( + '%s edited a custom field (with key "%s").', + $this->renderHandleLink($author_phid), + $this->getMetadata('customfield:key')); + } else { + return pht( + '%s edited a custom field.', + $this->renderHandleLink($author_phid)); + } } case PhabricatorTransactions::TYPE_TOKEN: if ($old && $new) { return pht( '%s updated a token.', $this->renderHandleLink($author_phid)); } else if ($old) { return pht( '%s rescinded a token.', $this->renderHandleLink($author_phid)); } else { return pht( '%s awarded a token.', $this->renderHandleLink($author_phid)); } case PhabricatorTransactions::TYPE_BUILDABLE: switch ($this->getNewValue()) { case HarbormasterBuildable::STATUS_BUILDING: return pht( '%s started building %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink( $this->getMetadataValue('harbormaster:buildablePHID'))); case HarbormasterBuildable::STATUS_PASSED: return pht( '%s completed building %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink( $this->getMetadataValue('harbormaster:buildablePHID'))); case HarbormasterBuildable::STATUS_FAILED: return pht( '%s failed to build %s!', $this->renderHandleLink($author_phid), $this->renderHandleLink( $this->getMetadataValue('harbormaster:buildablePHID'))); default: return null; } case PhabricatorTransactions::TYPE_INLINESTATE: $done = 0; $undone = 0; foreach ($new as $phid => $state) { if ($state == PhabricatorInlineCommentInterface::STATE_DONE) { $done++; } else { $undone++; } } if ($done && $undone) { return pht( '%s marked %s inline comment(s) as done and %s inline comment(s) '. 'as not done.', $this->renderHandleLink($author_phid), new PhutilNumber($done), new PhutilNumber($undone)); } else if ($done) { return pht( '%s marked %s inline comment(s) as done.', $this->renderHandleLink($author_phid), new PhutilNumber($done)); } else { return pht( '%s marked %s inline comment(s) as not done.', $this->renderHandleLink($author_phid), new PhutilNumber($undone)); } break; case PhabricatorTransactions::TYPE_COLUMNS: $moves = $this->getInterestingMoves($new); if (count($moves) == 1) { $move = head($moves); $from_columns = $move['fromColumnPHIDs']; $to_column = $move['columnPHID']; $board_phid = $move['boardPHID']; if (count($from_columns) == 1) { return pht( '%s moved this task from %s to %s on the %s board.', $this->renderHandleLink($author_phid), $this->renderHandleLink(head($from_columns)), $this->renderHandleLink($to_column), $this->renderHandleLink($board_phid)); } else { return pht( '%s moved this task to %s on the %s board.', $this->renderHandleLink($author_phid), $this->renderHandleLink($to_column), $this->renderHandleLink($board_phid)); } } else { $fragments = array(); foreach ($moves as $move) { $fragments[] = pht( '%s (%s)', $this->renderHandleLink($board_phid), $this->renderHandleLink($to_column)); } return pht( '%s moved this task on %s board(s): %s.', $this->renderHandleLink($author_phid), phutil_count($moves), phutil_implode_html(', ', $fragments)); } break; default: // In developer mode, provide a better hint here about which string // we're missing. $developer_mode = 'phabricator.developer-mode'; $is_developer = PhabricatorEnv::getEnvConfig($developer_mode); if ($is_developer) { return pht( '%s edited this object (transaction type "%s").', $this->renderHandleLink($author_phid), $this->getTransactionType()); } else { return pht( '%s edited this %s.', $this->renderHandleLink($author_phid), $this->getApplicationObjectTypeName()); } } } public function getTitleForFeed() { $author_phid = $this->getAuthorPHID(); $object_phid = $this->getObjectPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: return pht( '%s created %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_COMMENT: return pht( '%s added a comment to %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_VIEW_POLICY: return pht( '%s changed the visibility for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_EDIT_POLICY: return pht( '%s changed the edit policy for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_JOIN_POLICY: return pht( '%s changed the join policy for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return pht( '%s updated subscribers of %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_SPACE: return pht( '%s shifted %s from the %s space to the %s space.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), $this->renderHandleLink($old), $this->renderHandleLink($new)); case PhabricatorTransactions::TYPE_EDGE: $new = ipull($new, 'dst'); $old = ipull($old, 'dst'); $add = array_diff($new, $old); $rem = array_diff($old, $new); $type = $this->getMetadata('edge:type'); $type = head($type); $type_obj = PhabricatorEdgeType::getByConstant($type); if ($add && $rem) { return $type_obj->getFeedEditString( $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), new PhutilNumber(count($add) + count($rem)), phutil_count($add), $this->renderHandleList($add), phutil_count($rem), $this->renderHandleList($rem)); } else if ($add) { return $type_obj->getFeedAddString( $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), phutil_count($add), $this->renderHandleList($add)); } else if ($rem) { return $type_obj->getFeedRemoveString( $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), phutil_count($rem), $this->renderHandleList($rem)); } else { return pht( '%s edited edge metadata for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { return $field->getApplicationTransactionTitleForFeed($this); } else { return pht( '%s edited a custom field on %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); } case PhabricatorTransactions::TYPE_BUILDABLE: switch ($this->getNewValue()) { case HarbormasterBuildable::STATUS_BUILDING: return pht( '%s started building %s for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink( $this->getMetadataValue('harbormaster:buildablePHID')), $this->renderHandleLink($object_phid)); case HarbormasterBuildable::STATUS_PASSED: return pht( '%s completed building %s for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink( $this->getMetadataValue('harbormaster:buildablePHID')), $this->renderHandleLink($object_phid)); case HarbormasterBuildable::STATUS_FAILED: return pht( '%s failed to build %s for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink( $this->getMetadataValue('harbormaster:buildablePHID')), $this->renderHandleLink($object_phid)); default: return null; } case PhabricatorTransactions::TYPE_COLUMNS: $moves = $this->getInterestingMoves($new); if (count($moves) == 1) { $move = head($moves); $from_columns = $move['fromColumnPHIDs']; $to_column = $move['columnPHID']; $board_phid = $move['boardPHID']; if (count($from_columns) == 1) { return pht( '%s moved %s from %s to %s on the %s board.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), $this->renderHandleLink(head($from_columns)), $this->renderHandleLink($to_column), $this->renderHandleLink($board_phid)); } else { return pht( '%s moved %s to %s on the %s board.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), $this->renderHandleLink($to_column), $this->renderHandleLink($board_phid)); } } else { $fragments = array(); foreach ($moves as $move) { $fragments[] = pht( '%s (%s)', $this->renderHandleLink($board_phid), $this->renderHandleLink($to_column)); } return pht( '%s moved %s on %s board(s): %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), phutil_count($moves), phutil_implode_html(', ', $fragments)); } break; } return $this->getTitle(); } public function getMarkupFieldsForFeed(PhabricatorFeedStory $story) { $fields = array(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: $text = $this->getComment()->getContent(); if (strlen($text)) { $fields[] = 'comment/'.$this->getID(); } break; } return $fields; } public function getMarkupTextForFeed(PhabricatorFeedStory $story, $field) { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: $text = $this->getComment()->getContent(); return PhabricatorMarkupEngine::summarize($text); } return null; } public function getBodyForFeed(PhabricatorFeedStory $story) { $remarkup = $this->getRemarkupBodyForFeed($story); if ($remarkup !== null) { $remarkup = PhabricatorMarkupEngine::summarize($remarkup); return new PHUIRemarkupView($this->viewer, $remarkup); } $old = $this->getOldValue(); $new = $this->getNewValue(); $body = null; switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: $text = $this->getComment()->getContent(); if (strlen($text)) { $body = $story->getMarkupFieldOutput('comment/'.$this->getID()); } break; } return $body; } public function getRemarkupBodyForFeed(PhabricatorFeedStory $story) { return null; } public function getActionStrength() { if ($this->isInlineCommentTransaction()) { return 0.25; } switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: return 0.5; case PhabricatorTransactions::TYPE_SUBSCRIBERS: if ($this->isSelfSubscription()) { // Make this weaker than TYPE_COMMENT. return 0.25; } if ($this->isApplicationAuthor()) { // When applications (most often: Herald) change subscriptions it // is very uninteresting. return 0.000000001; } // In other cases, subscriptions are more interesting than comments // (which are shown anyway) but less interesting than any other type of // transaction. return 0.75; } return 1.0; } public function isCommentTransaction() { if ($this->hasComment()) { return true; } switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: return true; } return false; } public function isInlineCommentTransaction() { return false; } public function getActionName() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_COMMENT: return pht('Commented On'); case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: return pht('Changed Policy'); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return pht('Changed Subscribers'); case PhabricatorTransactions::TYPE_BUILDABLE: switch ($this->getNewValue()) { case HarbormasterBuildable::STATUS_PASSED: return pht('Build Passed'); case HarbormasterBuildable::STATUS_FAILED: return pht('Build Failed'); default: return pht('Build Status'); } default: return pht('Updated'); } } public function getMailTags() { return array(); } public function hasChangeDetails() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { return $field->getApplicationTransactionHasChangeDetails($this); } break; } return false; } public function hasChangeDetailsForMail() { return $this->hasChangeDetails(); } public function renderChangeDetailsForMail(PhabricatorUser $viewer) { $view = $this->renderChangeDetails($viewer); if ($view instanceof PhabricatorApplicationTransactionTextDiffDetailView) { return $view->renderForMail(); } return null; } public function renderChangeDetails(PhabricatorUser $viewer) { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getTransactionCustomField(); if ($field) { return $field->getApplicationTransactionChangeDetails($this, $viewer); } break; } return $this->renderTextCorpusChangeDetails( $viewer, $this->getOldValue(), $this->getNewValue()); } public function renderTextCorpusChangeDetails( PhabricatorUser $viewer, $old, $new) { return id(new PhabricatorApplicationTransactionTextDiffDetailView()) ->setUser($viewer) ->setOldText($old) ->setNewText($new); } public function attachTransactionGroup(array $group) { assert_instances_of($group, __CLASS__); $this->transactionGroup = $group; return $this; } public function getTransactionGroup() { return $this->transactionGroup; } /** * Should this transaction be visually grouped with an existing transaction * group? * * @param list List of transactions. * @return bool True to display in a group with the other transactions. */ public function shouldDisplayGroupWith(array $group) { $this_source = null; if ($this->getContentSource()) { $this_source = $this->getContentSource()->getSource(); } foreach ($group as $xaction) { // Don't group transactions by different authors. if ($xaction->getAuthorPHID() != $this->getAuthorPHID()) { return false; } // Don't group transactions for different objects. if ($xaction->getObjectPHID() != $this->getObjectPHID()) { return false; } // Don't group anything into a group which already has a comment. if ($xaction->isCommentTransaction()) { return false; } // Don't group transactions from different content sources. $other_source = null; if ($xaction->getContentSource()) { $other_source = $xaction->getContentSource()->getSource(); } if ($other_source != $this_source) { return false; } // Don't group transactions which happened more than 2 minutes apart. $apart = abs($xaction->getDateCreated() - $this->getDateCreated()); if ($apart > (60 * 2)) { return false; } } return true; } public function renderExtraInformationLink() { $herald_xscript_id = $this->getMetadataValue('herald:transcriptID'); if ($herald_xscript_id) { return phutil_tag( 'a', array( 'href' => '/herald/transcript/'.$herald_xscript_id.'/', ), pht('View Herald Transcript')); } return null; } public function renderAsTextForDoorkeeper( DoorkeeperFeedStoryPublisher $publisher, PhabricatorFeedStory $story, array $xactions) { $text = array(); $body = array(); foreach ($xactions as $xaction) { $xaction_body = $xaction->getBodyForMail(); if ($xaction_body !== null) { $body[] = $xaction_body; } if ($xaction->shouldHideForMail($xactions)) { continue; } $old_target = $xaction->getRenderingTarget(); $new_target = self::TARGET_TEXT; $xaction->setRenderingTarget($new_target); if ($publisher->getRenderWithImpliedContext()) { $text[] = $xaction->getTitle(); } else { $text[] = $xaction->getTitleForFeed(); } $xaction->setRenderingTarget($old_target); } $text = implode("\n", $text); $body = implode("\n\n", $body); return rtrim($text."\n\n".$body); } /** * Test if this transaction is just a user subscribing or unsubscribing * themselves. */ private function isSelfSubscription() { $type = $this->getTransactionType(); if ($type != PhabricatorTransactions::TYPE_SUBSCRIBERS) { return false; } $old = $this->getOldValue(); $new = $this->getNewValue(); $add = array_diff($old, $new); $rem = array_diff($new, $old); if ((count($add) + count($rem)) != 1) { // More than one user affected. return false; } $affected_phid = head(array_merge($add, $rem)); if ($affected_phid != $this->getAuthorPHID()) { // Affected user is someone else. return false; } return true; } private function isApplicationAuthor() { $author_phid = $this->getAuthorPHID(); $author_type = phid_get_type($author_phid); $application_type = PhabricatorApplicationApplicationPHIDType::TYPECONST; return ($author_type == $application_type); } private function getInterestingMoves(array $moves) { // Remove moves which only shift the position of a task within a column. foreach ($moves as $key => $move) { $from_phids = array_fuse($move['fromColumnPHIDs']); if (isset($from_phids[$move['columnPHID']])) { unset($moves[$key]); } } return $moves; } /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return ($viewer->getPHID() == $this->getAuthorPHID()); } public function describeAutomaticCapability($capability) { return pht( 'Transactions are visible to users that can see the object which was '. 'acted upon. Some transactions - in particular, comments - are '. 'editable by the transaction author.'); } public function getModularType() { return null; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); $comment_template = null; try { $comment_template = $this->getApplicationTransactionCommentObject(); } catch (Exception $ex) { // Continue; no comments for these transactions. } if ($comment_template) { $comments = $comment_template->loadAllWhere( 'transactionPHID = %s', $this->getPHID()); foreach ($comments as $comment) { $engine->destroyObject($comment); } } $this->delete(); $this->saveTransaction(); } } diff --git a/src/applications/transactions/storage/PhabricatorModularTransaction.php b/src/applications/transactions/storage/PhabricatorModularTransaction.php index e62d550bb9..035a2585fd 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransaction.php +++ b/src/applications/transactions/storage/PhabricatorModularTransaction.php @@ -1,160 +1,168 @@ getTransactionImplementation(); } final protected function getTransactionImplementation() { if (!$this->implementation) { $this->implementation = $this->newTransactionImplementation(); } return $this->implementation; } public function newModularTransactionTypes() { $base_class = $this->getBaseTransactionClass(); $types = id(new PhutilClassMapQuery()) ->setAncestorClass($base_class) ->setUniqueMethod('getTransactionTypeConstant') ->execute(); // Add core transaction types. $types += id(new PhutilClassMapQuery()) ->setAncestorClass('PhabricatorCoreTransactionType') ->setUniqueMethod('getTransactionTypeConstant') ->execute(); return $types; } private function newTransactionImplementation() { $types = $this->newModularTransactionTypes(); $key = $this->getTransactionType(); if (empty($types[$key])) { - $type = new PhabricatorCoreVoidTransaction(); + $type = $this->newFallbackModularTransactionType(); } else { $type = clone $types[$key]; } $type->setStorage($this); return $type; } + protected function newFallbackModularTransactionType() { + return new PhabricatorCoreVoidTransaction(); + } + final public function generateOldValue($object) { return $this->getTransactionImplementation()->generateOldValue($object); } final public function generateNewValue($object) { return $this->getTransactionImplementation() ->generateNewValue($object, $this->getNewValue()); } final public function willApplyTransactions($object, array $xactions) { return $this->getTransactionImplementation() ->willApplyTransactions($object, $xactions); } final public function applyInternalEffects($object) { return $this->getTransactionImplementation() ->applyInternalEffects($object); } final public function applyExternalEffects($object) { return $this->getTransactionImplementation() ->applyExternalEffects($object); } - final public function shouldHide() { + /* final */ public function shouldHide() { if ($this->getTransactionImplementation()->shouldHide()) { return true; } return parent::shouldHide(); } - final public function getIcon() { + /* final */ public function getIcon() { $icon = $this->getTransactionImplementation()->getIcon(); if ($icon !== null) { return $icon; } return parent::getIcon(); } - final public function getTitle() { + /* final */ public function getTitle() { $title = $this->getTransactionImplementation()->getTitle(); if ($title !== null) { return $title; } return parent::getTitle(); } public function getTitleForMail() { $old_target = $this->getRenderingTarget(); $new_target = self::TARGET_TEXT; $this->setRenderingTarget($new_target); $title = $this->getTitle(); $this->setRenderingTarget($old_target); return $title; } - final public function getTitleForFeed() { + /* final */ public function getTitleForFeed() { $title = $this->getTransactionImplementation()->getTitleForFeed(); if ($title !== null) { return $title; } return parent::getTitleForFeed(); } - final public function getColor() { + /* final */ public function getColor() { $color = $this->getTransactionImplementation()->getColor(); if ($color !== null) { return $color; } return parent::getColor(); } public function attachViewer(PhabricatorUser $viewer) { $this->getTransactionImplementation()->setViewer($viewer); return parent::attachViewer($viewer); } final public function hasChangeDetails() { if ($this->getTransactionImplementation()->hasChangeDetailView()) { return true; } return parent::hasChangeDetails(); } final public function renderChangeDetails(PhabricatorUser $viewer) { $impl = $this->getTransactionImplementation(); $impl->setViewer($viewer); $view = $impl->newChangeDetailView(); if ($view !== null) { return $view; } return parent::renderChangeDetails($viewer); } final protected function newRemarkupChanges() { return $this->getTransactionImplementation()->newRemarkupChanges(); } } diff --git a/src/applications/transactions/storage/PhabricatorModularTransactionType.php b/src/applications/transactions/storage/PhabricatorModularTransactionType.php index 84bc4a07ec..2606264778 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php +++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php @@ -1,294 +1,304 @@ getPhobjectClassConstant('TRANSACTIONTYPE'); } public function generateOldValue($object) { throw new PhutilMethodNotImplementedException(); } public function generateNewValue($object, $value) { return $value; } public function validateTransactions($object, array $xactions) { return array(); } public function willApplyTransactions($object, array $xactions) { return; } public function applyInternalEffects($object, $value) { return; } public function applyExternalEffects($object, $value) { return; } public function getTransactionHasEffect($object, $old, $new) { return ($old !== $new); } public function extractFilePHIDs($object, $value) { return array(); } public function shouldHide() { return false; } public function getIcon() { return null; } public function getTitle() { return null; } public function getTitleForFeed() { return null; } public function getColor() { return null; } public function hasChangeDetailView() { return false; } public function newChangeDetailView() { - throw new PhutilMethodNotImplementedException(); + return null; } public function getMailDiffSectionHeader() { return pht('EDIT DETAILS'); } public function newRemarkupChanges() { return array(); } final public function setStorage( PhabricatorApplicationTransaction $xaction) { $this->storage = $xaction; return $this; } private function getStorage() { return $this->storage; } final public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } final protected function getViewer() { return $this->viewer; } final public function getActor() { return $this->getEditor()->getActor(); } final public function getActingAsPHID() { return $this->getEditor()->getActingAsPHID(); } final public function setEditor( PhabricatorApplicationTransactionEditor $editor) { $this->editor = $editor; return $this; } final protected function getEditor() { if (!$this->editor) { throw new PhutilInvalidStateException('setEditor'); } return $this->editor; } final protected function getAuthorPHID() { return $this->getStorage()->getAuthorPHID(); } final protected function getObjectPHID() { return $this->getStorage()->getObjectPHID(); } final protected function getObject() { return $this->getStorage()->getObject(); } final protected function getOldValue() { return $this->getStorage()->getOldValue(); } final protected function getNewValue() { return $this->getStorage()->getNewValue(); } final protected function renderAuthor() { $author_phid = $this->getAuthorPHID(); return $this->getStorage()->renderHandleLink($author_phid); } final protected function renderObject() { $object_phid = $this->getObjectPHID(); return $this->getStorage()->renderHandleLink($object_phid); } final protected function renderHandle($phid) { $viewer = $this->getViewer(); $display = $viewer->renderHandle($phid); if ($this->isTextMode()) { $display->setAsText(true); } return $display; } final protected function renderOldHandle() { return $this->renderHandle($this->getOldValue()); } final protected function renderNewHandle() { return $this->renderHandle($this->getNewValue()); } final protected function renderHandleList(array $phids) { $viewer = $this->getViewer(); $display = $viewer->renderHandleList($phids) ->setAsInline(true); if ($this->isTextMode()) { $display->setAsText(true); } return $display; } final protected function renderValue($value) { if ($this->isTextMode()) { return sprintf('"%s"', $value); } return phutil_tag( 'span', array( 'class' => 'phui-timeline-value', ), $value); } final protected function renderOldValue() { return $this->renderValue($this->getOldValue()); } final protected function renderNewValue() { return $this->renderValue($this->getNewValue()); } final protected function renderDate($epoch) { $viewer = $this->getViewer(); // We accept either epoch timestamps or dictionaries describing a // PhutilCalendarDateTime. if (is_array($epoch)) { $datetime = PhutilCalendarAbsoluteDateTime::newFromDictionary($epoch) ->setViewerTimezone($viewer->getTimezoneIdentifier()); $all_day = $datetime->getIsAllDay(); $epoch = $datetime->getEpoch(); } else { $all_day = false; } if ($all_day) { $display = phabricator_date($epoch, $viewer); } else { $display = phabricator_datetime($epoch, $viewer); // When rendering to text, we explicitly render the offset from UTC to // provide context to the date: the mail may be generating with the // server's settings, or the user may later refer back to it after // changing timezones. - if ($this->isTextMode()) { + if ($this->isRenderingTargetExternal()) { $offset = $viewer->getTimeZoneOffsetInHours(); if ($offset >= 0) { $display = pht('%s (UTC+%d)', $display, $offset); } else { $display = pht('%s (UTC-%d)', $display, abs($offset)); } } } return $this->renderValue($display); } final protected function renderOldDate() { return $this->renderDate($this->getOldValue()); } final protected function renderNewDate() { return $this->renderDate($this->getNewValue()); } final protected function newError($title, $message, $xaction = null) { return new PhabricatorApplicationTransactionValidationError( $this->getTransactionTypeConstant(), $title, $message, $xaction); } final protected function newRequiredError($message, $xaction = null) { return $this->newError(pht('Required'), $message, $xaction) ->setIsMissingFieldError(true); } final protected function newInvalidError($message, $xaction = null) { return $this->newError(pht('Invalid'), $message, $xaction); } final protected function isNewObject() { return $this->getEditor()->getIsNewObject(); } final protected function isEmptyTextTransaction($value, array $xactions) { foreach ($xactions as $xaction) { $value = $xaction->getNewValue(); } return !strlen($value); } - private function isTextMode() { + /** + * When rendering to external targets (Email/Asana/etc), we need to include + * more information that users can't obtain later. + */ + final protected function isRenderingTargetExternal() { + // Right now, this is our best proxy for this: + return $this->isTextMode(); + // "TARGET_TEXT" means "EMail" and "TARGET_HTML" means "Web". + } + + final protected function isTextMode() { $target = $this->getStorage()->getRenderingTarget(); return ($target == PhabricatorApplicationTransaction::TARGET_TEXT); } final protected function newRemarkupChange() { return id(new PhabricatorTransactionRemarkupChange()) ->setTransaction($this->getStorage()); } final protected function isCreateTransaction() { return $this->getStorage()->getIsCreateTransaction(); } } diff --git a/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php b/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php new file mode 100644 index 0000000000..725716bdaf --- /dev/null +++ b/src/applications/transactions/typeahead/PhabricatorEditEngineDatasource.php @@ -0,0 +1,39 @@ +executeQuery($query); + $results = array(); + foreach ($forms as $form) { + + $result = id(new PhabricatorTypeaheadResult()) + ->setName($form->getName()) + ->setPHID($form->getPHID()); + + if ($form->getIsDisabled()) { + $result->setClosed(pht('Archived')); + } + + $results[] = $result; + } + + return $this->filterResultsAgainstTokens($results); + } + +} diff --git a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php index 2c5556cb4a..6956561490 100644 --- a/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php +++ b/src/applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php @@ -1,539 +1,554 @@ limit = $limit; return $this; } public function getLimit() { return $this->limit; } public function setOffset($offset) { $this->offset = $offset; return $this; } public function getOffset() { return $this->offset; } public function setViewer(PhabricatorUser $viewer) { $this->viewer = $viewer; return $this; } public function getViewer() { return $this->viewer; } public function setRawQuery($raw_query) { $this->rawQuery = $raw_query; return $this; } public function getPrefixQuery() { return phutil_utf8_strtolower($this->getRawQuery()); } public function getRawQuery() { return $this->rawQuery; } public function setQuery($query) { $this->query = $query; return $this; } public function getQuery() { return $this->query; } public function setParameters(array $params) { $this->parameters = $params; return $this; } public function getParameters() { return $this->parameters; } public function getParameter($name, $default = null) { return idx($this->parameters, $name, $default); } public function setIsBrowse($is_browse) { $this->isBrowse = $is_browse; return $this; } public function getIsBrowse() { return $this->isBrowse; } public function setPhase($phase) { $this->phase = $phase; return $this; } public function getPhase() { return $this->phase; } public function getDatasourceURI() { $uri = new PhutilURI('/typeahead/class/'.get_class($this).'/'); $uri->setQueryParams($this->parameters); return (string)$uri; } public function getBrowseURI() { if (!$this->isBrowsable()) { return null; } $uri = new PhutilURI('/typeahead/browse/'.get_class($this).'/'); $uri->setQueryParams($this->parameters); return (string)$uri; } abstract public function getPlaceholderText(); public function getBrowseTitle() { return get_class($this); } abstract public function getDatasourceApplicationClass(); abstract public function loadResults(); protected function loadResultsForPhase($phase, $limit) { // By default, sources just load all of their results in every phase and // rely on filtering at a higher level to sequence phases correctly. $this->setLimit($limit); return $this->loadResults(); } protected function didLoadResults(array $results) { return $results; } public static function tokenizeString($string) { $string = phutil_utf8_strtolower($string); $string = trim($string); if (!strlen($string)) { return array(); } // NOTE: Splitting on "(" and ")" is important for milestones. $tokens = preg_split('/[\s\[\]\(\)-]+/u', $string); $tokens = array_unique($tokens); // Make sure we don't return the empty token, as this will boil down to a // JOIN against every token. foreach ($tokens as $key => $value) { if (!strlen($value)) { unset($tokens[$key]); } } return array_values($tokens); } public function getTokens() { return self::tokenizeString($this->getRawQuery()); } protected function executeQuery( PhabricatorCursorPagedPolicyAwareQuery $query) { return $query ->setViewer($this->getViewer()) ->setOffset($this->getOffset()) ->setLimit($this->getLimit()) ->execute(); } /** * Can the user browse through results from this datasource? * * Browsable datasources allow the user to switch from typeahead mode to * a browse mode where they can scroll through all results. * * By default, datasources are browsable, but some datasources can not * generate a meaningful result set or can't filter results on the server. * * @return bool */ public function isBrowsable() { return true; } /** * Filter a list of results, removing items which don't match the query * tokens. * * This is useful for datasources which return a static list of hard-coded * or configured results and can't easily do query filtering in a real * query class. Instead, they can just build the entire result set and use * this method to filter it. * * For datasources backed by database objects, this is often much less * efficient than filtering at the query level. * * @param list List of typeahead results. * @return list Filtered results. */ protected function filterResultsAgainstTokens(array $results) { $tokens = $this->getTokens(); if (!$tokens) { return $results; } $map = array(); foreach ($tokens as $token) { $map[$token] = strlen($token); } foreach ($results as $key => $result) { $rtokens = self::tokenizeString($result->getName()); // For each token in the query, we need to find a match somewhere // in the result name. foreach ($map as $token => $length) { // Look for a match. $match = false; foreach ($rtokens as $rtoken) { if (!strncmp($rtoken, $token, $length)) { // This part of the result name has the query token as a prefix. $match = true; break; } } if (!$match) { // We didn't find a match for this query token, so throw the result // away. Try with the next result. unset($results[$key]); break; } } } return $results; } protected function newFunctionResult() { return id(new PhabricatorTypeaheadResult()) ->setTokenType(PhabricatorTypeaheadTokenView::TYPE_FUNCTION) ->setIcon('fa-asterisk') ->addAttribute(pht('Function')); } public function newInvalidToken($name) { return id(new PhabricatorTypeaheadTokenView()) ->setValue($name) ->setIcon('fa-exclamation-circle') ->setTokenType(PhabricatorTypeaheadTokenView::TYPE_INVALID); } public function renderTokens(array $values) { $phids = array(); $setup = array(); $tokens = array(); foreach ($values as $key => $value) { if (!self::isFunctionToken($value)) { $phids[$key] = $value; } else { $function = $this->parseFunction($value); if ($function) { $setup[$function['name']][$key] = $function; } else { $name = pht('Invalid Function: %s', $value); $tokens[$key] = $this->newInvalidToken($name) ->setKey($value); } } } // Give special non-function tokens which are also not PHIDs (like statuses // and priorities) an opportunity to render. $type_unknown = PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN; $special = array(); foreach ($values as $key => $value) { if (phid_get_type($value) == $type_unknown) { $special[$key] = $value; } } if ($special) { $special_tokens = $this->renderSpecialTokens($special); foreach ($special_tokens as $key => $token) { $tokens[$key] = $token; unset($phids[$key]); } } if ($phids) { $handles = $this->getViewer()->loadHandles($phids); foreach ($phids as $key => $phid) { $handle = $handles[$phid]; $tokens[$key] = PhabricatorTypeaheadTokenView::newFromHandle($handle); } } if ($setup) { foreach ($setup as $function_name => $argv_list) { // Render the function tokens. $function_tokens = $this->renderFunctionTokens( $function_name, ipull($argv_list, 'argv')); // Rekey the function tokens using the original array keys. $function_tokens = array_combine( array_keys($argv_list), $function_tokens); // For any functions which were invalid, set their value to the // original input value before it was parsed. foreach ($function_tokens as $key => $token) { $type = $token->getTokenType(); if ($type == PhabricatorTypeaheadTokenView::TYPE_INVALID) { $token->setKey($values[$key]); } } $tokens += $function_tokens; } } return array_select_keys($tokens, array_keys($values)); } protected function renderSpecialTokens(array $values) { return array(); } /* -( Token Functions )---------------------------------------------------- */ /** * @task functions */ public function getDatasourceFunctions() { return array(); } /** * @task functions */ public function getAllDatasourceFunctions() { return $this->getDatasourceFunctions(); } /** * @task functions */ protected function canEvaluateFunction($function) { return $this->shouldStripFunction($function); } /** * @task functions */ protected function shouldStripFunction($function) { $functions = $this->getDatasourceFunctions(); return isset($functions[$function]); } /** * @task functions */ protected function evaluateFunction($function, array $argv_list) { throw new PhutilMethodNotImplementedException(); } /** * @task functions */ protected function evaluateValues(array $values) { return $values; } /** * @task functions */ public function evaluateTokens(array $tokens) { $results = array(); $evaluate = array(); foreach ($tokens as $token) { if (!self::isFunctionToken($token)) { $results[] = $token; } else { - $evaluate[] = $token; + // Put a placeholder in the result list so that we retain token order + // when possible. We'll overwrite this below. + $results[] = null; + $evaluate[last_key($results)] = $token; } } $results = $this->evaluateValues($results); - foreach ($evaluate as $function) { + foreach ($evaluate as $result_key => $function) { $function = self::parseFunction($function); if (!$function) { throw new PhabricatorTypeaheadInvalidTokenException(); } $name = $function['name']; $argv = $function['argv']; - foreach ($this->evaluateFunction($name, array($argv)) as $phid) { - $results[] = $phid; + $evaluated_tokens = $this->evaluateFunction($name, array($argv)); + if (!$evaluated_tokens) { + unset($results[$result_key]); + } else { + $is_first = true; + foreach ($evaluated_tokens as $phid) { + if ($is_first) { + $results[$result_key] = $phid; + $is_first = false; + } else { + $results[] = $phid; + } + } } } + $results = array_values($results); $results = $this->didEvaluateTokens($results); return $results; } /** * @task functions */ protected function didEvaluateTokens(array $results) { return $results; } /** * @task functions */ public static function isFunctionToken($token) { // We're looking for a "(" so that a string like "members(q" is identified // and parsed as a function call. This allows us to start generating // results immeidately, before the user fully types out "members(quack)". return (strpos($token, '(') !== false); } /** * @task functions */ public function parseFunction($token, $allow_partial = false) { $matches = null; if ($allow_partial) { $ok = preg_match('/^([^(]+)\((.*?)\)?$/', $token, $matches); } else { $ok = preg_match('/^([^(]+)\((.*)\)$/', $token, $matches); } if (!$ok) { return null; } $function = trim($matches[1]); if (!$this->canEvaluateFunction($function)) { return null; } return array( 'name' => $function, 'argv' => array(trim($matches[2])), ); } /** * @task functions */ public function renderFunctionTokens($function, array $argv_list) { throw new PhutilMethodNotImplementedException(); } /** * @task functions */ public function setFunctionStack(array $function_stack) { $this->functionStack = $function_stack; return $this; } /** * @task functions */ public function getFunctionStack() { return $this->functionStack; } /** * @task functions */ protected function getCurrentFunction() { return nonempty(last($this->functionStack), null); } protected function renderTokensFromResults(array $results, array $values) { $tokens = array(); foreach ($values as $key => $value) { if (empty($results[$value])) { continue; } $tokens[$key] = PhabricatorTypeaheadTokenView::newFromTypeaheadResult( $results[$value]); } return $tokens; } public function getWireTokens(array $values) { // TODO: This is a bit hacky for now: we're sort of generating wire // results, rendering them, then reverting them back to wire results. This // is pretty silly. It would probably be much cleaner to make // renderTokens() call this method instead, then render from the result // structure. $rendered = $this->renderTokens($values); $tokens = array(); foreach ($rendered as $key => $render) { $tokens[$key] = id(new PhabricatorTypeaheadResult()) ->setPHID($render->getKey()) ->setIcon($render->getIcon()) ->setColor($render->getColor()) ->setDisplayName($render->getValue()) ->setTokenType($render->getTokenType()); } return mpull($tokens, 'getWireFormat', 'getPHID'); } } diff --git a/src/docs/contributor/version.diviner b/src/docs/contributor/version.diviner index 81b1c845ef..a13c12d86f 100644 --- a/src/docs/contributor/version.diviner +++ b/src/docs/contributor/version.diviner @@ -1,57 +1,80 @@ @title Providing Version Information @group detail How to provide version information with reports made to the upstream. Overview ======== When you submit a bug report, we require that you include version information. Despite our insistence that users update before reporting issues, many reports we receive describe issues which have already been resolved. Including version information in your report allows us to quickly determine that you are out of date and that updating will fix your issue. That said, your report must also include reproduction steps, and you should be unable to generate valid reproduction steps for an issue which has already been resolved because valid reproduction steps must also reproduce against a clean, up-to-date install. See @{article:Providing Reproduction Steps} for details. Phabricator Version =================== To get Phabricator version information: - Go to the {nav Config} application. You can type "Config" into the global search box, or navigate to `https://your.install.com/config/`. You must be an administrator to access this application. - Click {nav Versions} in the left menu. - Copy and paste all of the information on the page into your report. Arcanist Version ================ To get Arcanist version information: - Run `arc version`. - Copy and paste all of the output into your report. Other Versions ============== In general, we use `git` commit hashes as version identifiers, so you can identify the version of something by running `git show` and copy/pasting the hash from the output. This may be useful if you're encountering an issue which prevents you from reaching the version reporting screen. +Running a Fork? +=============== + +If you've forked Phabricator and have local commits, please make sure you are +reporting upstream commit hashes, not local commit hashes. The UI will attempt +to figure out where you branched from, but it may not be able to in all cases. + +If you report local commit hashes instead of upstream commit hashes we can not +go look up the commit hashes to figure out which changes they correspond to, so +we can not use that information to determine out how old your install is or +which patches you are missing. + +In most cases, you can find the upstream commit you've branched from like this: + +``` +$ git merge-base HEAD origin/master +```` + +Note that if you report a bug and have local commits, we will almost always ask +you to reproduce the issue against a clean copy of Phabricator before we +continue. You can get help faster by doing this //before// reporting an issue. + + Next Steps ========== Continue by: - returning to @{article:Contributing Bug Reports}. diff --git a/src/docs/user/configuration/configuring_file_storage.diviner b/src/docs/user/configuration/configuring_file_storage.diviner index 64942b493e..d6abb22c13 100644 --- a/src/docs/user/configuration/configuring_file_storage.diviner +++ b/src/docs/user/configuration/configuring_file_storage.diviner @@ -1,202 +1,202 @@ @title Configuring File Storage @group config Setup file storage and support for large files. Overview ======== This document describes how to configure Phabricator to support large file uploads, and how to choose where Phabricator stores files. There are two major things to configure: - set up PHP and your HTTP server to accept large requests; - choose and configure a storage engine. The following sections will guide you through this configuration. How Phabricator Stores Files ============================ Phabricator stores files in "storage engines", which are modular backends that implement access to some storage system (like MySQL, the filesystem, or a cloud storage service like Amazon S3). Phabricator stores large files by breaking them up into many chunks (a few megabytes in size) and storing the chunks in an underlying storage engine. This makes it easier to implement new storage engines and gives Phabricator more flexibility in managing file data. The first section of this document discusses configuring your install so that PHP and your HTTP server will accept requests which are larger than the size of one file chunk. Without this configuration, file chunk data will be rejected. The second section discusses choosing and configuring storage engines, so data is stored where you want it to be. Configuring Upload Limits ========================= File uploads are limited by several pieces of configuration at different layers of the stack. Generally, the minimum value of all the limits is the effective one. To upload large files, you need to increase all the limits to at least **32MB**. This will allow you to upload file chunks, which will let Phabricator store arbitrarily large files. The settings which limit file uploads are: **HTTP Server**: The HTTP server may set a limit on the maximum request size. If you exceed this limit, you'll see a default server page with an HTTP error. These directives limit the total size of the request body, so they must be somewhat larger than the desired maximum filesize. - **Apache**: Apache limits requests with the Apache `LimitRequestBody` directive. - **nginx**: nginx limits requests with the nginx `client_max_body_size` directive. This often defaults to `1M`. - **lighttpd**: lighttpd limits requests with the lighttpd `server.max-request-size` directive. Set the applicable limit to at least **32MB**. Phabricator can not read these settings, so it can not raise setup warnings if they are misconfigured. **PHP**: PHP has several directives which limit uploads. These directives are found in `php.ini`. - **post_max_size**: Maximum POST request size PHP will accept. If you exceed this, Phabricator will give you a useful error. This often defaults to `8M`. Set this to at least `32MB`. Phabricator will give you a setup warning about this if it is set too low. - **memory_limit**: For some uploads, file data will be read into memory before Phabricator can adjust the memory limit. If you exceed this, PHP may give you a useful error, depending on your configuration. It is recommended that you set this to `-1` to disable it. Phabricator will give you a setup warning about this if it is set too low. You may also want to configure these PHP options: - **max_input_vars**: When files are uploaded via HTML5 drag and drop file upload APIs, PHP parses the file body as though it contained normal POST parameters, and may trigger `max_input_vars` if a file has a lot of brackets in it. You may need to set it to some astronomically high value. - **upload_max_filesize**: Maximum file size PHP will accept in a raw file upload. This is not normally used when uploading files via drag-and-drop, but affects some other kinds of file uploads. If you exceed this, Phabricator will give you a useful error. This often defaults to `2M`. Set this to at least `32MB`. Once you've adjusted all this configuration, your server will be able to receive chunk uploads. As long as you have somewhere to store them, this will enable you to store arbitrarily large files. Storage Engines =============== Phabricator supports several different file storage engines: | Engine | Setup | Cost | Notes | |--------|-------|------|-------| | MySQL | Automatic | Free | May not scale well. | | Local Disk | Easy | Free | Does not scale well. | | Amazon S3 | Easy | Cheap | Scales well. | | Custom | Hard | Varies | Implement a custom storage engine. | You can review available storage engines and their configuration by navigating to {nav Applications > Files > Help/Options > Storage Engines} in the web UI. By default, Phabricator is configured to store files up to 1MB in MySQL, and reject files larger than 1MB. To store larger files, you can either: - increase the MySQL limit to at least 8MB; or - configure another storage engine. Doing either of these will enable the chunk storage engine and support for arbitrarily large files. The remaining sections of this document discuss the available storage engines and how to configure them. Engine: MySQL ============= - **Pros**: Low latency, no setup required. - **Cons**: Storing files in a database is a classic bad idea. May become difficult to administrate if you have a large amount of data. MySQL storage is configured by default, for files up to (just under) 1MB. You can configure it with these keys: - - `storage.mysql-engine.max-size`: Change the filesize limit. Set to 0 - to disable. + - `storage.mysql-engine.max-size`: Change the filesize limit, in bytes. Set + to 0 to disable. For most installs, it is reasonable to leave this engine as-is and let small files (like thumbnails and profile images) be stored in MySQL, which is usually the lowest-latency filestore, even if you configure another storage engine. -To support large files, increase this limit to at least **8MB**. This will -activate chunk storage in MySQL. +To support large files, increase this limit to at least `8388608` (8MB). +This will activate chunk storage in MySQL. Engine: Local Disk ================== - **Pros**: Simple to setup. - **Cons**: Doesn't scale to multiple web frontends without NFS. To configure file storage on the local disk, set: - `storage.local-disk.path`: Set to some writable directory on local disk. Make that directory. Engine: Amazon S3 ================= - **Pros**: Scales well. - **Cons**: Slightly more complicated than other engines, not free. To enable file storage in S3, set these keys: - `amazon-s3.access-key`: Your AWS access key. - `amazon-s3.secret-key`: Your AWS secret key. - `amazon-s3.region`: Your AWS S3 region. - `amazon-s3.endpoint`: Your AWS S3 endpoint. - `storage.s3.bucket`: S3 bucket name where files should be stored. Testing Storage Engines ======================= You can test that things are correctly configured by dragging and dropping a file onto the Phabricator home page. If engines have been configured properly, the file should upload. Migrating Files Between Engines =============================== If you want to move files between storage engines, you can use the `bin/files` script to perform migrations. For example, suppose you previously used MySQL but recently set up S3 and want to migrate all your files there. First, migrate one file to make sure things work: phabricator/ $ ./bin/files migrate --engine amazon-s3 F12345 If that works properly, you can then migrate everything: phabricator/ $ ./bin/files migrate --engine amazon-s3 --all You can use `--dry-run` to show which migrations would be performed without taking any action. Run `bin/files help` for more options and information. Next Steps ========== Continue by: - reviewing at-rest encryption options with @{article:Configuring Encryption}; or - returning to the @{article:Configuration Guide}. diff --git a/src/docs/user/userguide/drydock_blueprints.diviner b/src/docs/user/userguide/drydock_blueprints.diviner index 46c8a27f5e..21c4342fa6 100644 --- a/src/docs/user/userguide/drydock_blueprints.diviner +++ b/src/docs/user/userguide/drydock_blueprints.diviner @@ -1,80 +1,80 @@ @title Drydock Blueprints @group userguide Overview of Drydock blueprint types. Overview ======== IMPORTANT: Drydock is not a mature application and may be difficult to configure and use for now. Drydock builds and manages various hardware and software resources, like hosts and repository working copies. Other applications can use these resources to perform useful work (like running tests or builds). -For additional disussion of Drydock, see @{article:Drydock User Guide}. +For additional discussion of Drydock, see @{article:Drydock User Guide}. Drydock can't create any resources until you configure it. You'll configure Drydock by creating **Blueprints**. Each blueprint tells Drydock how to build a specific kind of resource, how many it is allowed to build, where it should build them, who is authorized to request them, and so on. You can create a new blueprint in Drydock from the web UI: {nav Drydock > Blueprints > New Blueprint} Each blueprint builds resources of a specific type, like hosts or repository working copies. Detailed topic guides are available for each resource type: **Hosts**: Hosts are the building block for most other resources. For details, see @{article:Drydock Blueprints: Hosts}. **Working Copies**: Working copies allow Drydock to perform repository operations like running tests, performing builds, and handling merges. Authorizing Access ================== Before objects in other applications can use a blueprint, the blueprint must authorize them. This mostly serves to prevent users with limited access from executing operations on trusted hosts. For additional discussion, see @{article:Drydock User Guide: Security}. This also broadly prevents Drydock from surprising you by coming up with a valid but unintended solution to an allocation problem which runs some operation on resources that are techincally suitable but not desirable. For example, you may not want your Android builds running on your iPhone build tier, even if there's no technical reason they can't. You can review active authorizations and pending authorization requests in the "Active Authorizations" section of the blueprint detail screen. To approve an authorization, click it and select {nav Approve Authorization}. Until you do, the requesting object won't be able to access resources from the blueprint. You can also decline an authorization. This prevents use of resources and removes it from the authorization approval queue. Disabling Blueprints ==================== You can disable a blueprint by selecting {nav Disable Blueprint} from the blueprint detail screen. Disabled blueprints will no longer be used for new allocations. However, existing resources will continue to function. Next Steps ========== Continue by: - returning to the @{article:Drydock User Guide}. diff --git a/src/docs/user/userguide/profile_menu.diviner b/src/docs/user/userguide/profile_menu.diviner index bd278b2702..2b4ffc4be8 100644 --- a/src/docs/user/userguide/profile_menu.diviner +++ b/src/docs/user/userguide/profile_menu.diviner @@ -1,149 +1,149 @@ @title Profile Menu User Guide @group userguide Master profile menus for projects and other objects. Overview ======== Some objects, like projects, have customizable menus called "profile menus". This guide discusses how to add, remove, reorder, configure and extend these menus. Supported Applications ====================== These applications currently support profile menus: | Application | Support | |-----|-----| | Projects | Full | | People | //Read-Only// | Collapsing and Expanding ======================== To collapse a full-width profile menu, click {nav icon="angle-left", name="Collapse"}. To expand a narrow menu, click {nav icon="angle-right", name="Expand"}. If you're logged in, this setting is sticky, and all menus will respect your preference. Editing Menus ============= You can only edit an object's menu if you can edit the object. For example, you must have permission to edit a project in order to reconfigure the menu for the project. To edit a menu, click {nav icon="cogs", name="Manage"} in the menu, then click {nav icon="th-list", name="Edit Menu"}. This brings you to the menu configuration interface which allows you to add and remove items, reorder the menu, edit existing items, and choose a default item. Menus are comprised of a list of items. Some of the items are builtin (for example, projects have builtin "Profile", "Workboard" and "Members" items). You can also add custom items. Builtin and custom items mostly behave in similar ways, but there are a few exceptions (for example, you can not completely delete builtin items). Adding Items ============ To add new items to a menu, use {nav icon="cog", name="Configure Menu"} and choose a type of item to add. See below for more details on available items. You can also find a link to this documentation in the same menu, if you want to reference it later. Reordering Items ================ To reorder items, drag and drop them to the desired position. Your changes will be reflected in the item ordering in the menu. Setting a Default ================= The default item controls what content is shown when a user browses to the object's main page. For example, the default item for a project controls where the user ends up when they click a link to the project from another application. To choose a default item, click {nav icon="thumb-tack", name="Make Default"}. Not all kinds of items can be set as the default item. For example, you can not set a separator line as a default because the item can't be selected and has no content. If no default is explicitly selected, or a default is deleted or disabled, the first item which is eligible to be a default is used as the default item. Removing Items ============== To remove items, click the {nav icon="times", name="Delete"} action. Builtin items can not be deleted and have a {nav icon="times", name="Disable"} action instead, which will hide them but not delete them. You an re-enable a disabled item with the {nav icon="plus', name="Enable"} action. A few items can not be hidden or deleted. For example, the {nav icon="cogs", name="Manage"} item must always be available in the menu because if you hid it by accident there would no longer be a way to access the configuration interface and fix the mistake. Removing or hiding an item does not disable the underlying functionality. For example, if you hide the "Members" item for a project, that just removes it from the menu. The project still has members, and users can still navigate to the members page by following a link to it from elsewhere in the application or entering the URI manually. Editing Items ============= To edit an item, click the name of the item. This will show you available configuration for the item and allow you to edit it. Which properties are editable depends on what sort of item you are editing. Most items can be renamed, and some items have more settings available. For example, when editing a link, you can choose the link target and select an icon for the item. A few items have no configuration. For example, visual separator lines are purely cosmetic and have no available settings. Available Items =============== When you add items, you can choose between different types of items to add. Which item types are available depends on what sort of object you are editing the menu for, but most objects support these items: - {icon link} **Link**: Allows you to create an item which links to somewhere else in Phabricator, or to an external site. - {icon minus} **Divider**: Adds a visual separator to the menu. This is purely cosmetic. - {icon coffee} **Motivator**: Motivate your employees with inspirational quotes. A new quote every day! To learn more about how an item works, try adding it. You can always delete it later if it doesn't do what you wanted. Writing New Item Types ====================== IMPORTANT: This feature is not stable, and the API is subject to change. -To add new types of items, subclass @{class:PhabricatorProfilePanel}. +To add new types of items, subclass @{class:PhabricatorProfileMenuItem}. diff --git a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php index 8d448f624b..ffdb157d8e 100644 --- a/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php +++ b/src/infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php @@ -1,134 +1,137 @@ customField = $custom_field; return $this; } public function getCustomField() { return $this->customField; } public function setCustomFieldHTTPParameterType( AphrontHTTPParameterType $type) { $this->httpParameterType = $type; return $this; } public function getCustomFieldHTTPParameterType() { return $this->httpParameterType; } public function setCustomFieldConduitParameterType( ConduitParameterType $type) { $this->conduitParameterType = $type; return $this; } public function getCustomFieldConduitParameterType() { return $this->conduitParameterType; } protected function buildControl() { + if ($this->getIsConduitOnly()) { + return null; + } + $field = $this->getCustomField(); $clone = clone $field; $value = $this->getValue(); $clone->setValueFromApplicationTransactions($value); return $clone->renderEditControl(array()); } protected function newEditType() { + $type = id(new PhabricatorCustomFieldEditType()) + ->setCustomField($this->getCustomField()); + $conduit_type = $this->newConduitParameterType(); - if (!$conduit_type) { - return null; + if ($conduit_type) { + $type->setConduitParameterType($conduit_type); } - $type = id(new PhabricatorCustomFieldEditType()) - ->setCustomField($this->getCustomField()) - ->setConduitParameterType($conduit_type); - return $type; } public function getValueForTransaction() { $value = $this->getValue(); $field = $this->getCustomField(); // Avoid changing the value of the field itself, since later calls would // incorrectly reflect the new value. $clone = clone $field; $clone->setValueFromApplicationTransactions($value); return $clone->getNewValueForApplicationTransactions(); } protected function getValueExistsInSubmit(AphrontRequest $request, $key) { return true; } protected function getValueFromSubmit(AphrontRequest $request, $key) { $field = $this->getCustomField(); $clone = clone $field; $clone->readValueFromRequest($request); return $clone->getNewValueForApplicationTransactions(); } protected function newConduitEditTypes() { $field = $this->getCustomField(); if (!$field->shouldAppearInConduitTransactions()) { return array(); } return parent::newConduitEditTypes(); } protected function newHTTPParameterType() { $type = $this->getCustomFieldHTTPParameterType(); if ($type) { return clone $type; } return null; } protected function newConduitParameterType() { $type = $this->getCustomFieldConduitParameterType(); if ($type) { return clone $type; } return null; } public function getAllReadValueFromRequestKeys() { $keys = array(); // NOTE: This piece of complexity is so we can expose a reasonable key in // the UI ("custom.x") instead of a crufty internal key ("std:app:x"). // Perhaps we can simplify this some day. // In the parent, this is just getKey(), but that returns a cumbersome // key in EditFields. Use the simpler edit type key instead. $keys[] = $this->getEditTypeKey(); foreach ($this->getAliases() as $alias) { $keys[] = $alias; } return $keys; } } diff --git a/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php b/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php index b9427905b8..3edc898cb7 100644 --- a/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php +++ b/src/infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php @@ -1,53 +1,53 @@ getViewer(); $field_list = PhabricatorCustomField::getObjectFields( $object, - PhabricatorCustomField::ROLE_EDIT); + PhabricatorCustomField::ROLE_EDITENGINE); $field_list->setViewer($viewer); if ($object->getID()) { $field_list->readFieldsFromStorage($object); } $results = array(); foreach ($field_list->getFields() as $field) { $edit_fields = $field->getEditEngineFields($engine); foreach ($edit_fields as $edit_field) { $results[] = $edit_field; } } return $results; } } diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php index 7791700a14..8f88c1469e 100644 --- a/src/infrastructure/customfield/field/PhabricatorCustomField.php +++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php @@ -1,1458 +1,1479 @@ getCustomFields(); } catch (PhabricatorDataNotAttachedException $ex) { $attachment = new PhabricatorCustomFieldAttachment(); $object->attachCustomFields($attachment); } try { $field_list = $attachment->getCustomFieldList($role); } catch (PhabricatorCustomFieldNotAttachedException $ex) { $base_class = $object->getCustomFieldBaseClass(); $spec = $object->getCustomFieldSpecificationForRole($role); if (!is_array($spec)) { throw new Exception( pht( "Expected an array from %s for object of class '%s'.", 'getCustomFieldSpecificationForRole()', get_class($object))); } $fields = self::buildFieldList( $base_class, $spec, $object); foreach ($fields as $key => $field) { if (!$field->shouldEnableForRole($role)) { unset($fields[$key]); } } foreach ($fields as $field) { $field->setObject($object); } $field_list = new PhabricatorCustomFieldList($fields); $attachment->addCustomFieldList($role, $field_list); } return $field_list; } /** * @task apps */ public static function getObjectField( PhabricatorCustomFieldInterface $object, $role, $field_key) { $fields = self::getObjectFields($object, $role)->getFields(); return idx($fields, $field_key); } /** * @task apps */ public static function buildFieldList( $base_class, array $spec, $object, array $options = array()) { $field_objects = id(new PhutilClassMapQuery()) ->setAncestorClass($base_class) ->execute(); $fields = array(); foreach ($field_objects as $field_object) { $field_object = clone $field_object; foreach ($field_object->createFields($object) as $field) { $key = $field->getFieldKey(); if (isset($fields[$key])) { throw new Exception( pht( "Both '%s' and '%s' define a custom field with ". "field key '%s'. Field keys must be unique.", get_class($fields[$key]), get_class($field), $key)); } $fields[$key] = $field; } } foreach ($fields as $key => $field) { if (!$field->isFieldEnabled()) { unset($fields[$key]); } } $fields = array_select_keys($fields, array_keys($spec)) + $fields; if (empty($options['withDisabled'])) { foreach ($fields as $key => $field) { if (isset($spec[$key]['disabled'])) { $is_disabled = $spec[$key]['disabled']; } else { $is_disabled = $field->shouldDisableByDefault(); } if ($is_disabled) { if ($field->canDisableField()) { unset($fields[$key]); } } } } return $fields; } /* -( Core Properties and Field Identity )--------------------------------- */ /** * Return a key which uniquely identifies this field, like * "mycompany:dinosaur:count". Normally you should provide some level of * namespacing to prevent collisions. * * @return string String which uniquely identifies this field. * @task core */ public function getFieldKey() { if ($this->proxy) { return $this->proxy->getFieldKey(); } throw new PhabricatorCustomFieldImplementationIncompleteException( $this, $field_key_is_incomplete = true); } public function getModernFieldKey() { if ($this->proxy) { return $this->proxy->getModernFieldKey(); } return $this->getFieldKey(); } /** * Return a human-readable field name. * * @return string Human readable field name. * @task core */ public function getFieldName() { if ($this->proxy) { return $this->proxy->getFieldName(); } return $this->getModernFieldKey(); } /** * Return a short, human-readable description of the field's behavior. This * provides more context to administrators when they are customizing fields. * * @return string|null Optional human-readable description. * @task core */ public function getFieldDescription() { if ($this->proxy) { return $this->proxy->getFieldDescription(); } return null; } /** * Most field implementations are unique, in that one class corresponds to * one field. However, some field implementations are general and a single * implementation may drive several fields. * * For general implementations, the general field implementation can return * multiple field instances here. * * @param object The object to create fields for. * @return list List of fields. * @task core */ public function createFields($object) { return array($this); } /** * You can return `false` here if the field should not be enabled for any * role. For example, it might depend on something (like an application or * library) which isn't installed, or might have some global configuration * which allows it to be disabled. * * @return bool False to completely disable this field for all roles. * @task core */ public function isFieldEnabled() { if ($this->proxy) { return $this->proxy->isFieldEnabled(); } return true; } /** * Low level selector for field availability. Fields can appear in different * roles (like an edit view, a list view, etc.), but not every field needs * to appear everywhere. Fields that are disabled in a role won't appear in * that context within applications. * * Normally, you do not need to override this method. Instead, override the * methods specific to roles you want to enable. For example, implement * @{method:shouldUseStorage()} to activate the `'storage'` role. * * @return bool True to enable the field for the given role. * @task core */ public function shouldEnableForRole($role) { // NOTE: All of these calls proxy individually, so we don't need to // proxy this call as a whole. switch ($role) { case self::ROLE_APPLICATIONTRANSACTIONS: return $this->shouldAppearInApplicationTransactions(); case self::ROLE_APPLICATIONSEARCH: return $this->shouldAppearInApplicationSearch(); case self::ROLE_STORAGE: return $this->shouldUseStorage(); case self::ROLE_EDIT: return $this->shouldAppearInEditView(); case self::ROLE_VIEW: return $this->shouldAppearInPropertyView(); case self::ROLE_LIST: return $this->shouldAppearInListView(); case self::ROLE_GLOBALSEARCH: return $this->shouldAppearInGlobalSearch(); case self::ROLE_CONDUIT: return $this->shouldAppearInConduitDictionary(); case self::ROLE_TRANSACTIONMAIL: return $this->shouldAppearInTransactionMail(); case self::ROLE_HERALD: return $this->shouldAppearInHerald(); + case self::ROLE_EDITENGINE: + return $this->shouldAppearInEditView() || + $this->shouldAppearInEditEngine(); case self::ROLE_DEFAULT: return true; default: throw new Exception(pht("Unknown field role '%s'!", $role)); } } /** * Allow administrators to disable this field. Most fields should allow this, * but some are fundamental to the behavior of the application and can be * locked down to avoid chaos, disorder, and the decline of civilization. * * @return bool False to prevent this field from being disabled through * configuration. * @task core */ public function canDisableField() { return true; } public function shouldDisableByDefault() { return false; } /** * Return an index string which uniquely identifies this field. * * @return string Index string which uniquely identifies this field. * @task core */ final public function getFieldIndex() { return PhabricatorHash::digestForIndex($this->getFieldKey()); } /* -( Field Proxies )------------------------------------------------------ */ /** * Proxies allow a field to use some other field's implementation for most * of their behavior while still subclassing an application field. When a * proxy is set for a field with @{method:setProxy}, all of its methods will * call through to the proxy by default. * * This is most commonly used to implement configuration-driven custom fields * using @{class:PhabricatorStandardCustomField}. * * This method must be overridden to return `true` before a field can accept * proxies. * * @return bool True if you can @{method:setProxy} this field. * @task proxy */ public function canSetProxy() { if ($this instanceof PhabricatorStandardCustomFieldInterface) { return true; } return false; } /** * Set the proxy implementation for this field. See @{method:canSetProxy} for * discussion of field proxies. * * @param PhabricatorCustomField Field implementation. * @return this */ final public function setProxy(PhabricatorCustomField $proxy) { if (!$this->canSetProxy()) { throw new PhabricatorCustomFieldNotProxyException($this); } $this->proxy = $proxy; return $this; } /** * Get the field's proxy implementation, if any. For discussion, see * @{method:canSetProxy}. * * @return PhabricatorCustomField|null Proxy field, if one is set. */ final public function getProxy() { return $this->proxy; } /* -( Contextual Data )---------------------------------------------------- */ /** * Sets the object this field belongs to. * * @param PhabricatorCustomFieldInterface The object this field belongs to. * @return this * @task context */ final public function setObject(PhabricatorCustomFieldInterface $object) { if ($this->proxy) { $this->proxy->setObject($object); return $this; } $this->object = $object; $this->didSetObject($object); return $this; } /** * Read object data into local field storage, if applicable. * * @param PhabricatorCustomFieldInterface The object this field belongs to. * @return this * @task context */ public function readValueFromObject(PhabricatorCustomFieldInterface $object) { if ($this->proxy) { $this->proxy->readValueFromObject($object); } return $this; } /** * Get the object this field belongs to. * * @return PhabricatorCustomFieldInterface The object this field belongs to. * @task context */ final public function getObject() { if ($this->proxy) { return $this->proxy->getObject(); } return $this->object; } /** * This is a hook, primarily for subclasses to load object data. * * @return PhabricatorCustomFieldInterface The object this field belongs to. * @return void */ protected function didSetObject(PhabricatorCustomFieldInterface $object) { return; } /** * @task context */ final public function setViewer(PhabricatorUser $viewer) { if ($this->proxy) { $this->proxy->setViewer($viewer); return $this; } $this->viewer = $viewer; return $this; } /** * @task context */ final public function getViewer() { if ($this->proxy) { return $this->proxy->getViewer(); } return $this->viewer; } /** * @task context */ final protected function requireViewer() { if ($this->proxy) { return $this->proxy->requireViewer(); } if (!$this->viewer) { throw new PhabricatorCustomFieldDataNotAvailableException($this); } return $this->viewer; } /* -( Rendering Utilities )------------------------------------------------ */ /** * @task render */ protected function renderHandleList(array $handles) { if (!$handles) { return null; } $out = array(); foreach ($handles as $handle) { $out[] = $handle->renderHovercardLink(); } return phutil_implode_html(phutil_tag('br'), $out); } /* -( Storage )------------------------------------------------------------ */ /** * Return true to use field storage. * * Fields which can be edited by the user will most commonly use storage, * while some other types of fields (for instance, those which just display * information in some stylized way) may not. Many builtin fields do not use * storage because their data is available on the object itself. * * If you implement this, you must also implement @{method:getValueForStorage} * and @{method:setValueFromStorage}. * * @return bool True to use storage. * @task storage */ public function shouldUseStorage() { if ($this->proxy) { return $this->proxy->shouldUseStorage(); } return false; } /** * Return a new, empty storage object. This should be a subclass of * @{class:PhabricatorCustomFieldStorage} which is bound to the application's * database. * * @return PhabricatorCustomFieldStorage New empty storage object. * @task storage */ public function newStorageObject() { // NOTE: This intentionally isn't proxied, to avoid call cycles. throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Return a serialized representation of the field value, appropriate for * storing in auxiliary field storage. You must implement this method if * you implement @{method:shouldUseStorage}. * * If the field value is a scalar, it can be returned unmodiifed. If not, * it should be serialized (for example, using JSON). * * @return string Serialized field value. * @task storage */ public function getValueForStorage() { if ($this->proxy) { return $this->proxy->getValueForStorage(); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Set the field's value given a serialized storage value. This is called * when the field is loaded; if no data is available, the value will be * null. You must implement this method if you implement * @{method:shouldUseStorage}. * * Usually, the value can be loaded directly. If it isn't a scalar, you'll * need to undo whatever serialization you applied in * @{method:getValueForStorage}. * * @param string|null Serialized field representation (from * @{method:getValueForStorage}) or null if no value has * ever been stored. * @return this * @task storage */ public function setValueFromStorage($value) { if ($this->proxy) { return $this->proxy->setValueFromStorage($value); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } public function didSetValueFromStorage() { if ($this->proxy) { return $this->proxy->didSetValueFromStorage(); } return $this; } /* -( ApplicationSearch )-------------------------------------------------- */ /** * Appearing in ApplicationSearch allows a field to be indexed and searched * for. * * @return bool True to appear in ApplicationSearch. * @task appsearch */ public function shouldAppearInApplicationSearch() { if ($this->proxy) { return $this->proxy->shouldAppearInApplicationSearch(); } return false; } /** * Return one or more indexes which this field can meaningfully query against * to implement ApplicationSearch. * * Normally, you should build these using @{method:newStringIndex} and * @{method:newNumericIndex}. For example, if a field holds a numeric value * it might return a single numeric index: * * return array($this->newNumericIndex($this->getValue())); * * If a field holds a more complex value (like a list of users), it might * return several string indexes: * * $indexes = array(); * foreach ($this->getValue() as $phid) { * $indexes[] = $this->newStringIndex($phid); * } * return $indexes; * * @return list List of indexes. * @task appsearch */ public function buildFieldIndexes() { if ($this->proxy) { return $this->proxy->buildFieldIndexes(); } return array(); } /** * Return an index against which this field can be meaningfully ordered * against to implement ApplicationSearch. * * This should be a single index, normally built using * @{method:newStringIndex} and @{method:newNumericIndex}. * * The value of the index is not used. * * Return null from this method if the field can not be ordered. * * @return PhabricatorCustomFieldIndexStorage A single index to order by. * @task appsearch */ public function buildOrderIndex() { if ($this->proxy) { return $this->proxy->buildOrderIndex(); } return null; } /** * Build a new empty storage object for storing string indexes. Normally, * this should be a concrete subclass of * @{class:PhabricatorCustomFieldStringIndexStorage}. * * @return PhabricatorCustomFieldStringIndexStorage Storage object. * @task appsearch */ protected function newStringIndexStorage() { // NOTE: This intentionally isn't proxied, to avoid call cycles. throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Build a new empty storage object for storing string indexes. Normally, * this should be a concrete subclass of * @{class:PhabricatorCustomFieldStringIndexStorage}. * * @return PhabricatorCustomFieldStringIndexStorage Storage object. * @task appsearch */ protected function newNumericIndexStorage() { // NOTE: This intentionally isn't proxied, to avoid call cycles. throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Build and populate storage for a string index. * * @param string String to index. * @return PhabricatorCustomFieldStringIndexStorage Populated storage. * @task appsearch */ protected function newStringIndex($value) { if ($this->proxy) { return $this->proxy->newStringIndex(); } $key = $this->getFieldIndex(); return $this->newStringIndexStorage() ->setIndexKey($key) ->setIndexValue($value); } /** * Build and populate storage for a numeric index. * * @param string Numeric value to index. * @return PhabricatorCustomFieldNumericIndexStorage Populated storage. * @task appsearch */ protected function newNumericIndex($value) { if ($this->proxy) { return $this->proxy->newNumericIndex(); } $key = $this->getFieldIndex(); return $this->newNumericIndexStorage() ->setIndexKey($key) ->setIndexValue($value); } /** * Read a query value from a request, for storage in a saved query. Normally, * this method should, e.g., read a string out of the request. * * @param PhabricatorApplicationSearchEngine Engine building the query. * @param AphrontRequest Request to read from. * @return wild * @task appsearch */ public function readApplicationSearchValueFromRequest( PhabricatorApplicationSearchEngine $engine, AphrontRequest $request) { if ($this->proxy) { return $this->proxy->readApplicationSearchValueFromRequest( $engine, $request); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Constrain a query, given a field value. Generally, this method should * use `with...()` methods to apply filters or other constraints to the * query. * * @param PhabricatorApplicationSearchEngine Engine executing the query. * @param PhabricatorCursorPagedPolicyAwareQuery Query to constrain. * @param wild Constraint provided by the user. * @return void * @task appsearch */ public function applyApplicationSearchConstraintToQuery( PhabricatorApplicationSearchEngine $engine, PhabricatorCursorPagedPolicyAwareQuery $query, $value) { if ($this->proxy) { return $this->proxy->applyApplicationSearchConstraintToQuery( $engine, $query, $value); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Append search controls to the interface. * * @param PhabricatorApplicationSearchEngine Engine constructing the form. * @param AphrontFormView The form to update. * @param wild Value from the saved query. * @return void * @task appsearch */ public function appendToApplicationSearchForm( PhabricatorApplicationSearchEngine $engine, AphrontFormView $form, $value) { if ($this->proxy) { return $this->proxy->appendToApplicationSearchForm( $engine, $form, $value); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /* -( ApplicationTransactions )-------------------------------------------- */ /** * Appearing in ApplicationTrasactions allows a field to be edited using * standard workflows. * * @return bool True to appear in ApplicationTransactions. * @task appxaction */ public function shouldAppearInApplicationTransactions() { if ($this->proxy) { return $this->proxy->shouldAppearInApplicationTransactions(); } return false; } /** * @task appxaction */ public function getApplicationTransactionType() { if ($this->proxy) { return $this->proxy->getApplicationTransactionType(); } return PhabricatorTransactions::TYPE_CUSTOMFIELD; } /** * @task appxaction */ public function getApplicationTransactionMetadata() { if ($this->proxy) { return $this->proxy->getApplicationTransactionMetadata(); } return array(); } /** * @task appxaction */ public function getOldValueForApplicationTransactions() { if ($this->proxy) { return $this->proxy->getOldValueForApplicationTransactions(); } return $this->getValueForStorage(); } /** * @task appxaction */ public function getNewValueForApplicationTransactions() { if ($this->proxy) { return $this->proxy->getNewValueForApplicationTransactions(); } return $this->getValueForStorage(); } /** * @task appxaction */ public function setValueFromApplicationTransactions($value) { if ($this->proxy) { return $this->proxy->setValueFromApplicationTransactions($value); } return $this->setValueFromStorage($value); } /** * @task appxaction */ public function getNewValueFromApplicationTransactions( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getNewValueFromApplicationTransactions($xaction); } return $xaction->getNewValue(); } /** * @task appxaction */ public function getApplicationTransactionHasEffect( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getApplicationTransactionHasEffect($xaction); } return ($xaction->getOldValue() !== $xaction->getNewValue()); } /** * @task appxaction */ public function applyApplicationTransactionInternalEffects( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->applyApplicationTransactionInternalEffects($xaction); } return; } /** * @task appxaction */ public function getApplicationTransactionRemarkupBlocks( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getApplicationTransactionRemarkupBlocks($xaction); } return array(); } /** * @task appxaction */ public function applyApplicationTransactionExternalEffects( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->applyApplicationTransactionExternalEffects($xaction); } if (!$this->shouldEnableForRole(self::ROLE_STORAGE)) { return; } $this->setValueFromApplicationTransactions($xaction->getNewValue()); $value = $this->getValueForStorage(); $table = $this->newStorageObject(); $conn_w = $table->establishConnection('w'); if ($value === null) { queryfx( $conn_w, 'DELETE FROM %T WHERE objectPHID = %s AND fieldIndex = %s', $table->getTableName(), $this->getObject()->getPHID(), $this->getFieldIndex()); } else { queryfx( $conn_w, 'INSERT INTO %T (objectPHID, fieldIndex, fieldValue) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE fieldValue = VALUES(fieldValue)', $table->getTableName(), $this->getObject()->getPHID(), $this->getFieldIndex(), $value); } return; } /** * Validate transactions for an object. This allows you to raise an error * when a transaction would set a field to an invalid value, or when a field * is required but no transactions provide value. * * @param PhabricatorLiskDAO Editor applying the transactions. * @param string Transaction type. This type is always * `PhabricatorTransactions::TYPE_CUSTOMFIELD`, it is provided for * convenience when constructing exceptions. * @param list Transactions being applied, * which may be empty if this field is not being edited. * @return list Validation * errors. * * @task appxaction */ public function validateApplicationTransactions( PhabricatorApplicationTransactionEditor $editor, $type, array $xactions) { if ($this->proxy) { return $this->proxy->validateApplicationTransactions( $editor, $type, $xactions); } return array(); } public function getApplicationTransactionTitle( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getApplicationTransactionTitle( $xaction); } $author_phid = $xaction->getAuthorPHID(); return pht( '%s updated this object.', $xaction->renderHandleLink($author_phid)); } public function getApplicationTransactionTitleForFeed( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getApplicationTransactionTitleForFeed( $xaction); } $author_phid = $xaction->getAuthorPHID(); $object_phid = $xaction->getObjectPHID(); return pht( '%s updated %s.', $xaction->renderHandleLink($author_phid), $xaction->renderHandleLink($object_phid)); } public function getApplicationTransactionHasChangeDetails( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getApplicationTransactionHasChangeDetails( $xaction); } return false; } public function getApplicationTransactionChangeDetails( PhabricatorApplicationTransaction $xaction, PhabricatorUser $viewer) { if ($this->proxy) { return $this->proxy->getApplicationTransactionChangeDetails( $xaction, $viewer); } return null; } public function getApplicationTransactionRequiredHandlePHIDs( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->getApplicationTransactionRequiredHandlePHIDs( $xaction); } return array(); } public function shouldHideInApplicationTransactions( PhabricatorApplicationTransaction $xaction) { if ($this->proxy) { return $this->proxy->shouldHideInApplicationTransactions($xaction); } return false; } /* -( Transaction Mail )--------------------------------------------------- */ /** * @task xactionmail */ public function shouldAppearInTransactionMail() { if ($this->proxy) { return $this->proxy->shouldAppearInTransactionMail(); } return false; } /** * @task xactionmail */ public function updateTransactionMailBody( PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions) { if ($this->proxy) { return $this->proxy->updateTransactionMailBody($body, $editor, $xactions); } return; } /* -( Edit View )---------------------------------------------------------- */ public function getEditEngineFields(PhabricatorEditEngine $engine) { $field = $this->newStandardEditField($engine); return array( $field, ); } protected function newEditField() { $field = id(new PhabricatorCustomFieldEditField()) ->setCustomField($this); $http_type = $this->getHTTPParameterType(); if ($http_type) { $field->setCustomFieldHTTPParameterType($http_type); } $conduit_type = $this->getConduitEditParameterType(); if ($conduit_type) { $field->setCustomFieldConduitParameterType($conduit_type); } return $field; } protected function newStandardEditField() { if ($this->proxy) { return $this->proxy->newStandardEditField(); } + if (!$this->shouldAppearInEditView()) { + $conduit_only = true; + } else { + $conduit_only = false; + } + return $this->newEditField() ->setKey($this->getFieldKey()) ->setEditTypeKey($this->getModernFieldKey()) ->setLabel($this->getFieldName()) ->setDescription($this->getFieldDescription()) ->setTransactionType($this->getApplicationTransactionType()) + ->setIsConduitOnly($conduit_only) ->setValue($this->getNewValueForApplicationTransactions()); } protected function getHTTPParameterType() { if ($this->proxy) { return $this->proxy->getHTTPParameterType(); } return null; } /** * @task edit */ public function shouldAppearInEditView() { if ($this->proxy) { return $this->proxy->shouldAppearInEditView(); } return false; } + /** + * @task edit + */ + public function shouldAppearInEditEngine() { + if ($this->proxy) { + return $this->proxy->shouldAppearInEditEngine(); + } + return false; + } + /** * @task edit */ public function readValueFromRequest(AphrontRequest $request) { if ($this->proxy) { return $this->proxy->readValueFromRequest($request); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * @task edit */ public function getRequiredHandlePHIDsForEdit() { if ($this->proxy) { return $this->proxy->getRequiredHandlePHIDsForEdit(); } return array(); } /** * @task edit */ public function getInstructionsForEdit() { if ($this->proxy) { return $this->proxy->getInstructionsForEdit(); } return null; } /** * @task edit */ public function renderEditControl(array $handles) { if ($this->proxy) { return $this->proxy->renderEditControl($handles); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /* -( Property View )------------------------------------------------------ */ /** * @task view */ public function shouldAppearInPropertyView() { if ($this->proxy) { return $this->proxy->shouldAppearInPropertyView(); } return false; } /** * @task view */ public function renderPropertyViewLabel() { if ($this->proxy) { return $this->proxy->renderPropertyViewLabel(); } return $this->getFieldName(); } /** * @task view */ public function renderPropertyViewValue(array $handles) { if ($this->proxy) { return $this->proxy->renderPropertyViewValue($handles); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * @task view */ public function getStyleForPropertyView() { if ($this->proxy) { return $this->proxy->getStyleForPropertyView(); } return 'property'; } /** * @task view */ public function getIconForPropertyView() { if ($this->proxy) { return $this->proxy->getIconForPropertyView(); } return null; } /** * @task view */ public function getRequiredHandlePHIDsForPropertyView() { if ($this->proxy) { return $this->proxy->getRequiredHandlePHIDsForPropertyView(); } return array(); } /* -( List View )---------------------------------------------------------- */ /** * @task list */ public function shouldAppearInListView() { if ($this->proxy) { return $this->proxy->shouldAppearInListView(); } return false; } /** * @task list */ public function renderOnListItem(PHUIObjectItemView $view) { if ($this->proxy) { return $this->proxy->renderOnListItem($view); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /* -( Global Search )------------------------------------------------------ */ /** * @task globalsearch */ public function shouldAppearInGlobalSearch() { if ($this->proxy) { return $this->proxy->shouldAppearInGlobalSearch(); } return false; } /** * @task globalsearch */ public function updateAbstractDocument( PhabricatorSearchAbstractDocument $document) { if ($this->proxy) { return $this->proxy->updateAbstractDocument($document); } return $document; } /* -( Conduit )------------------------------------------------------------ */ /** * @task conduit */ public function shouldAppearInConduitDictionary() { if ($this->proxy) { return $this->proxy->shouldAppearInConduitDictionary(); } return false; } /** * @task conduit */ public function getConduitDictionaryValue() { if ($this->proxy) { return $this->proxy->getConduitDictionaryValue(); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } public function shouldAppearInConduitTransactions() { if ($this->proxy) { return $this->proxy->shouldAppearInConduitDictionary(); } return false; } public function getConduitSearchParameterType() { return $this->newConduitSearchParameterType(); } protected function newConduitSearchParameterType() { if ($this->proxy) { return $this->proxy->newConduitSearchParameterType(); } return null; } public function getConduitEditParameterType() { return $this->newConduitEditParameterType(); } protected function newConduitEditParameterType() { if ($this->proxy) { return $this->proxy->newConduitEditParameterType(); } return null; } /* -( Herald )------------------------------------------------------------- */ /** * Return `true` to make this field available in Herald. * * @return bool True to expose the field in Herald. * @task herald */ public function shouldAppearInHerald() { if ($this->proxy) { return $this->proxy->shouldAppearInHerald(); } return false; } /** * Get the name of the field in Herald. By default, this uses the * normal field name. * * @return string Herald field name. * @task herald */ public function getHeraldFieldName() { if ($this->proxy) { return $this->proxy->getHeraldFieldName(); } return $this->getFieldName(); } /** * Get the field value for evaluation by Herald. * * @return wild Field value. * @task herald */ public function getHeraldFieldValue() { if ($this->proxy) { return $this->proxy->getHeraldFieldValue(); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Get the available conditions for this field in Herald. * * @return list List of Herald condition constants. * @task herald */ public function getHeraldFieldConditions() { if ($this->proxy) { return $this->proxy->getHeraldFieldConditions(); } throw new PhabricatorCustomFieldImplementationIncompleteException($this); } /** * Get the Herald value type for the given condition. * * @param const Herald condition constant. * @return const|null Herald value type, or null to use the default. * @task herald */ public function getHeraldFieldValueType($condition) { if ($this->proxy) { return $this->proxy->getHeraldFieldValueType($condition); } return null; } public function getHeraldFieldStandardType() { if ($this->proxy) { return $this->proxy->getHeraldFieldStandardType(); } return null; } public function getHeraldDatasource() { if ($this->proxy) { return $this->proxy->getHeraldDatasource(); } return null; } } diff --git a/src/infrastructure/storage/lisk/LiskDAO.php b/src/infrastructure/storage/lisk/LiskDAO.php index 71cfba3d54..0527c3cf1e 100644 --- a/src/infrastructure/storage/lisk/LiskDAO.php +++ b/src/infrastructure/storage/lisk/LiskDAO.php @@ -1,2018 +1,2021 @@ setName('Sawyer') * ->setBreed('Pug') * ->save(); * * Note that **Lisk automatically builds getters and setters for all of your * object's protected properties** via @{method:__call}. If you want to add * custom behavior to your getters or setters, you can do so by overriding the * @{method:readField} and @{method:writeField} methods. * * Calling @{method:save} will persist the object to the database. After calling * @{method:save}, you can call @{method:getID} to retrieve the object's ID. * * To load objects by ID, use the @{method:load} method: * * $dog = id(new Dog())->load($id); * * This will load the Dog record with ID $id into $dog, or `null` if no such * record exists (@{method:load} is an instance method rather than a static * method because PHP does not support late static binding, at least until PHP * 5.3). * * To update an object, change its properties and save it: * * $dog->setBreed('Lab')->save(); * * To delete an object, call @{method:delete}: * * $dog->delete(); * * That's Lisk CRUD in a nutshell. * * = Queries = * * Often, you want to load a bunch of objects, or execute a more specialized * query. Use @{method:loadAllWhere} or @{method:loadOneWhere} to do this: * * $pugs = $dog->loadAllWhere('breed = %s', 'Pug'); * $sawyer = $dog->loadOneWhere('name = %s', 'Sawyer'); * * These methods work like @{function@libphutil:queryfx}, but only take half of * a query (the part after the WHERE keyword). Lisk will handle the connection, * columns, and object construction; you are responsible for the rest of it. * @{method:loadAllWhere} returns a list of objects, while * @{method:loadOneWhere} returns a single object (or `null`). * * There's also a @{method:loadRelatives} method which helps to prevent the 1+N * queries problem. * * = Managing Transactions = * * Lisk uses a transaction stack, so code does not generally need to be aware * of the transactional state of objects to implement correct transaction * semantics: * * $obj->openTransaction(); * $obj->save(); * $other->save(); * // ... * $other->openTransaction(); * $other->save(); * $another->save(); * if ($some_condition) { * $other->saveTransaction(); * } else { * $other->killTransaction(); * } * // ... * $obj->saveTransaction(); * * Assuming ##$obj##, ##$other## and ##$another## live on the same database, * this code will work correctly by establishing savepoints. * * Selects whose data are used later in the transaction should be included in * @{method:beginReadLocking} or @{method:beginWriteLocking} block. * * @task conn Managing Connections * @task config Configuring Lisk * @task load Loading Objects * @task info Examining Objects * @task save Writing Objects * @task hook Hooks and Callbacks * @task util Utilities * @task xaction Managing Transactions * @task isolate Isolation for Unit Testing */ abstract class LiskDAO extends Phobject { const CONFIG_IDS = 'id-mechanism'; const CONFIG_TIMESTAMPS = 'timestamps'; const CONFIG_AUX_PHID = 'auxiliary-phid'; const CONFIG_SERIALIZATION = 'col-serialization'; const CONFIG_BINARY = 'binary'; const CONFIG_COLUMN_SCHEMA = 'col-schema'; const CONFIG_KEY_SCHEMA = 'key-schema'; const CONFIG_NO_TABLE = 'no-table'; const CONFIG_NO_MUTATE = 'no-mutate'; const SERIALIZATION_NONE = 'id'; const SERIALIZATION_JSON = 'json'; const SERIALIZATION_PHP = 'php'; const IDS_AUTOINCREMENT = 'ids-auto'; const IDS_COUNTER = 'ids-counter'; const IDS_MANUAL = 'ids-manual'; const COUNTER_TABLE_NAME = 'lisk_counter'; private static $processIsolationLevel = 0; private static $transactionIsolationLevel = 0; private $ephemeral = false; private $forcedConnection; private static $connections = array(); private $inSet = null; protected $id; protected $phid; protected $dateCreated; protected $dateModified; /** * Build an empty object. * * @return obj Empty object. */ public function __construct() { $id_key = $this->getIDKey(); if ($id_key) { $this->$id_key = null; } } /* -( Managing Connections )----------------------------------------------- */ /** * Establish a live connection to a database service. This method should * return a new connection. Lisk handles connection caching and management; * do not perform caching deeper in the stack. * * @param string Mode, either 'r' (reading) or 'w' (reading and writing). * @return AphrontDatabaseConnection New database connection. * @task conn */ abstract protected function establishLiveConnection($mode); /** * Return a namespace for this object's connections in the connection cache. * Generally, the database name is appropriate. Two connections are considered * equivalent if they have the same connection namespace and mode. * * @return string Connection namespace for cache * @task conn */ abstract protected function getConnectionNamespace(); /** * Get an existing, cached connection for this object. * * @param mode Connection mode. * @return AprontDatabaseConnection|null Connection, if it exists in cache. * @task conn */ protected function getEstablishedConnection($mode) { $key = $this->getConnectionNamespace().':'.$mode; if (isset(self::$connections[$key])) { return self::$connections[$key]; } return null; } /** * Store a connection in the connection cache. * * @param mode Connection mode. * @param AphrontDatabaseConnection Connection to cache. * @return this * @task conn */ protected function setEstablishedConnection( $mode, AphrontDatabaseConnection $connection, $force_unique = false) { $key = $this->getConnectionNamespace().':'.$mode; if ($force_unique) { $key .= ':unique'; while (isset(self::$connections[$key])) { $key .= '!'; } } self::$connections[$key] = $connection; return $this; } /** * Force an object to use a specific connection. * * This overrides all connection management and forces the object to use * a specific connection when interacting with the database. * * @param AphrontDatabaseConnection Connection to force this object to use. * @task conn */ public function setForcedConnection(AphrontDatabaseConnection $connection) { $this->forcedConnection = $connection; return $this; } /* -( Configuring Lisk )--------------------------------------------------- */ /** * Change Lisk behaviors, like ID configuration and timestamps. If you want * to change these behaviors, you should override this method in your child * class and change the options you're interested in. For example: * * protected function getConfiguration() { * return array( * Lisk_DataAccessObject::CONFIG_EXAMPLE => true, * ) + parent::getConfiguration(); * } * * The available options are: * * CONFIG_IDS * Lisk objects need to have a unique identifying ID. The three mechanisms * available for generating this ID are IDS_AUTOINCREMENT (default, assumes * the ID column is an autoincrement primary key), IDS_MANUAL (you are taking * full responsibility for ID management), or IDS_COUNTER (see below). * * InnoDB does not persist the value of `auto_increment` across restarts, * and instead initializes it to `MAX(id) + 1` during startup. This means it * may reissue the same autoincrement ID more than once, if the row is deleted * and then the database is restarted. To avoid this, you can set an object to * use a counter table with IDS_COUNTER. This will generally behave like * IDS_AUTOINCREMENT, except that the counter value will persist across * restarts and inserts will be slightly slower. If a database stores any * DAOs which use this mechanism, you must create a table there with this * schema: * * CREATE TABLE lisk_counter ( * counterName VARCHAR(64) COLLATE utf8_bin PRIMARY KEY, * counterValue BIGINT UNSIGNED NOT NULL * ) ENGINE=InnoDB DEFAULT CHARSET=utf8; * * CONFIG_TIMESTAMPS * Lisk can automatically handle keeping track of a `dateCreated' and * `dateModified' column, which it will update when it creates or modifies * an object. If you don't want to do this, you may disable this option. * By default, this option is ON. * * CONFIG_AUX_PHID * This option can be enabled by being set to some truthy value. The meaning * of this value is defined by your PHID generation mechanism. If this option * is enabled, a `phid' property will be populated with a unique PHID when an * object is created (or if it is saved and does not currently have one). You * need to override generatePHID() and hook it into your PHID generation * mechanism for this to work. By default, this option is OFF. * * CONFIG_SERIALIZATION * You can optionally provide a column serialization map that will be applied * to values when they are written to the database. For example: * * self::CONFIG_SERIALIZATION => array( * 'complex' => self::SERIALIZATION_JSON, * ) * * This will cause Lisk to JSON-serialize the 'complex' field before it is * written, and unserialize it when it is read. * * CONFIG_BINARY * You can optionally provide a map of columns to a flag indicating that * they store binary data. These columns will not raise an error when * handling binary writes. * * CONFIG_COLUMN_SCHEMA * Provide a map of columns to schema column types. * * CONFIG_KEY_SCHEMA * Provide a map of key names to key specifications. * * CONFIG_NO_TABLE * Allows you to specify that this object does not actually have a table in * the database. * * CONFIG_NO_MUTATE * Provide a map of columns which should not be included in UPDATE statements. * If you have some columns which are always written to explicitly and should * never be overwritten by a save(), you can specify them here. This is an * advanced, specialized feature and there are usually better approaches for * most locking/contention problems. * * @return dictionary Map of configuration options to values. * * @task config */ protected function getConfiguration() { return array( self::CONFIG_IDS => self::IDS_AUTOINCREMENT, self::CONFIG_TIMESTAMPS => true, ); } /** * Determine the setting of a configuration option for this class of objects. * * @param const Option name, one of the CONFIG_* constants. * @return mixed Option value, if configured (null if unavailable). * * @task config */ public function getConfigOption($option_name) { static $options = null; if (!isset($options)) { $options = $this->getConfiguration(); } return idx($options, $option_name); } /* -( Loading Objects )---------------------------------------------------- */ /** * Load an object by ID. You need to invoke this as an instance method, not * a class method, because PHP doesn't have late static binding (until * PHP 5.3.0). For example: * * $dog = id(new Dog())->load($dog_id); * * @param int Numeric ID identifying the object to load. * @return obj|null Identified object, or null if it does not exist. * * @task load */ public function load($id) { if (is_object($id)) { $id = (string)$id; } if (!$id || (!is_int($id) && !ctype_digit($id))) { return null; } return $this->loadOneWhere( '%C = %d', $this->getIDKeyForUse(), $id); } /** * Loads all of the objects, unconditionally. * * @return dict Dictionary of all persisted objects of this type, keyed * on object ID. * * @task load */ public function loadAll() { return $this->loadAllWhere('1 = 1'); } /** * Load all objects which match a WHERE clause. You provide everything after * the 'WHERE'; Lisk handles everything up to it. For example: * * $old_dogs = id(new Dog())->loadAllWhere('age > %d', 7); * * The pattern and arguments are as per queryfx(). * * @param string queryfx()-style SQL WHERE clause. * @param ... Zero or more conversions. * @return dict Dictionary of matching objects, keyed on ID. * * @task load */ public function loadAllWhere($pattern /* , $arg, $arg, $arg ... */) { $args = func_get_args(); $data = call_user_func_array( array($this, 'loadRawDataWhere'), $args); return $this->loadAllFromArray($data); } /** * Load a single object identified by a 'WHERE' clause. You provide * everything after the 'WHERE', and Lisk builds the first half of the * query. See loadAllWhere(). This method is similar, but returns a single * result instead of a list. * * @param string queryfx()-style SQL WHERE clause. * @param ... Zero or more conversions. * @return obj|null Matching object, or null if no object matches. * * @task load */ public function loadOneWhere($pattern /* , $arg, $arg, $arg ... */) { $args = func_get_args(); $data = call_user_func_array( array($this, 'loadRawDataWhere'), $args); if (count($data) > 1) { throw new AphrontCountQueryException( pht( 'More than one result from %s!', __FUNCTION__.'()')); } $data = reset($data); if (!$data) { return null; } return $this->loadFromArray($data); } protected function loadRawDataWhere($pattern /* , $args... */) { $connection = $this->establishConnection('r'); $lock_clause = ''; if ($connection->isReadLocking()) { $lock_clause = 'FOR UPDATE'; } else if ($connection->isWriteLocking()) { $lock_clause = 'LOCK IN SHARE MODE'; } $args = func_get_args(); $args = array_slice($args, 1); $pattern = 'SELECT * FROM %T WHERE '.$pattern.' %Q'; array_unshift($args, $this->getTableName()); array_push($args, $lock_clause); array_unshift($args, $pattern); return call_user_func_array( array($connection, 'queryData'), $args); } /** * Reload an object from the database, discarding any changes to persistent * properties. This is primarily useful after entering a transaction but * before applying changes to an object. * * @return this * * @task load */ public function reload() { if (!$this->getID()) { throw new Exception( pht("Unable to reload object that hasn't been loaded!")); } $result = $this->loadOneWhere( '%C = %d', $this->getIDKeyForUse(), $this->getID()); if (!$result) { throw new AphrontObjectMissingQueryException(); } return $this; } /** * Initialize this object's properties from a dictionary. Generally, you * load single objects with loadOneWhere(), but sometimes it may be more * convenient to pull data from elsewhere directly (e.g., a complicated * join via @{method:queryData}) and then load from an array representation. * * @param dict Dictionary of properties, which should be equivalent to * selecting a row from the table or calling * @{method:getProperties}. * @return this * * @task load */ public function loadFromArray(array $row) { static $valid_properties = array(); $map = array(); foreach ($row as $k => $v) { // We permit (but ignore) extra properties in the array because a // common approach to building the array is to issue a raw SELECT query // which may include extra explicit columns or joins. // This pathway is very hot on some pages, so we're inlining a cache // and doing some microoptimization to avoid a strtolower() call for each // assignment. The common path (assigning a valid property which we've // already seen) always incurs only one empty(). The second most common // path (assigning an invalid property which we've already seen) costs // an empty() plus an isset(). if (empty($valid_properties[$k])) { if (isset($valid_properties[$k])) { // The value is set but empty, which means it's false, so we've // already determined it's not valid. We don't need to check again. continue; } $valid_properties[$k] = $this->hasProperty($k); if (!$valid_properties[$k]) { continue; } } $map[$k] = $v; } $this->willReadData($map); foreach ($map as $prop => $value) { $this->$prop = $value; } $this->didReadData(); return $this; } /** * Initialize a list of objects from a list of dictionaries. Usually you * load lists of objects with @{method:loadAllWhere}, but sometimes that * isn't flexible enough. One case is if you need to do joins to select the * right objects: * * function loadAllWithOwner($owner) { * $data = $this->queryData( * 'SELECT d.* * FROM owner o * JOIN owner_has_dog od ON o.id = od.ownerID * JOIN dog d ON od.dogID = d.id * WHERE o.id = %d', * $owner); * return $this->loadAllFromArray($data); * } * * This is a lot messier than @{method:loadAllWhere}, but more flexible. * * @param list List of property dictionaries. * @return dict List of constructed objects, keyed on ID. * * @task load */ public function loadAllFromArray(array $rows) { $result = array(); $id_key = $this->getIDKey(); foreach ($rows as $row) { $obj = clone $this; if ($id_key && isset($row[$id_key])) { $result[$row[$id_key]] = $obj->loadFromArray($row); } else { $result[] = $obj->loadFromArray($row); } if ($this->inSet) { $this->inSet->addToSet($obj); } } return $result; } /** * This method helps to prevent the 1+N queries problem. It happens when you * execute a query for each row in a result set. Like in this code: * * COUNTEREXAMPLE, name=Easy to write but expensive to execute * $diffs = id(new DifferentialDiff())->loadAllWhere( * 'revisionID = %d', * $revision->getID()); * foreach ($diffs as $diff) { * $changesets = id(new DifferentialChangeset())->loadAllWhere( * 'diffID = %d', * $diff->getID()); * // Do something with $changesets. * } * * One can solve this problem by reading all the dependent objects at once and * assigning them later: * * COUNTEREXAMPLE, name=Cheaper to execute but harder to write and maintain * $diffs = id(new DifferentialDiff())->loadAllWhere( * 'revisionID = %d', * $revision->getID()); * $all_changesets = id(new DifferentialChangeset())->loadAllWhere( * 'diffID IN (%Ld)', * mpull($diffs, 'getID')); * $all_changesets = mgroup($all_changesets, 'getDiffID'); * foreach ($diffs as $diff) { * $changesets = idx($all_changesets, $diff->getID(), array()); * // Do something with $changesets. * } * * The method @{method:loadRelatives} abstracts this approach which allows * writing a code which is simple and efficient at the same time: * * name=Easy to write and cheap to execute * $diffs = $revision->loadRelatives(new DifferentialDiff(), 'revisionID'); * foreach ($diffs as $diff) { * $changesets = $diff->loadRelatives( * new DifferentialChangeset(), * 'diffID'); * // Do something with $changesets. * } * * This will load dependent objects for all diffs in the first call of * @{method:loadRelatives} and use this result for all following calls. * * The method supports working with set of sets, like in this code: * * $diffs = $revision->loadRelatives(new DifferentialDiff(), 'revisionID'); * foreach ($diffs as $diff) { * $changesets = $diff->loadRelatives( * new DifferentialChangeset(), * 'diffID'); * foreach ($changesets as $changeset) { * $hunks = $changeset->loadRelatives( * new DifferentialHunk(), * 'changesetID'); * // Do something with hunks. * } * } * * This code will execute just three queries - one to load all diffs, one to * load all their related changesets and one to load all their related hunks. * You can try to write an equivalent code without using this method as * a homework. * * The method also supports retrieving referenced objects, for example authors * of all diffs (using shortcut @{method:loadOneRelative}): * * foreach ($diffs as $diff) { * $author = $diff->loadOneRelative( * new PhabricatorUser(), * 'phid', * 'getAuthorPHID'); * // Do something with author. * } * * It is also possible to specify additional conditions for the `WHERE` * clause. Similarly to @{method:loadAllWhere}, you can specify everything * after `WHERE` (except `LIMIT`). Contrary to @{method:loadAllWhere}, it is * allowed to pass only a constant string (`%` doesn't have a special * meaning). This is intentional to avoid mistakes with using data from one * row in retrieving other rows. Example of a correct usage: * * $status = $author->loadOneRelative( * new PhabricatorCalendarEvent(), * 'userPHID', * 'getPHID', * '(UNIX_TIMESTAMP() BETWEEN dateFrom AND dateTo)'); * * @param LiskDAO Type of objects to load. * @param string Name of the column in target table. * @param string Method name in this table. * @param string Additional constraints on returned rows. It supports no * placeholders and requires putting the WHERE part into * parentheses. It's not possible to use LIMIT. * @return list Objects of type $object. * * @task load */ public function loadRelatives( LiskDAO $object, $foreign_column, $key_method = 'getID', $where = '') { if (!$this->inSet) { id(new LiskDAOSet())->addToSet($this); } $relatives = $this->inSet->loadRelatives( $object, $foreign_column, $key_method, $where); return idx($relatives, $this->$key_method(), array()); } /** * Load referenced row. See @{method:loadRelatives} for details. * * @param LiskDAO Type of objects to load. * @param string Name of the column in target table. * @param string Method name in this table. * @param string Additional constraints on returned rows. It supports no * placeholders and requires putting the WHERE part into * parentheses. It's not possible to use LIMIT. * @return LiskDAO Object of type $object or null if there's no such object. * * @task load */ final public function loadOneRelative( LiskDAO $object, $foreign_column, $key_method = 'getID', $where = '') { $relatives = $this->loadRelatives( $object, $foreign_column, $key_method, $where); if (!$relatives) { return null; } if (count($relatives) > 1) { throw new AphrontCountQueryException( pht( 'More than one result from %s!', __FUNCTION__.'()')); } return reset($relatives); } final public function putInSet(LiskDAOSet $set) { $this->inSet = $set; return $this; } final protected function getInSet() { return $this->inSet; } /* -( Examining Objects )-------------------------------------------------- */ /** * Set unique ID identifying this object. You normally don't need to call this * method unless with `IDS_MANUAL`. * * @param mixed Unique ID. * @return this * @task save */ public function setID($id) { static $id_key = null; if ($id_key === null) { $id_key = $this->getIDKeyForUse(); } $this->$id_key = $id; return $this; } /** * Retrieve the unique ID identifying this object. This value will be null if * the object hasn't been persisted and you didn't set it manually. * * @return mixed Unique ID. * * @task info */ public function getID() { static $id_key = null; if ($id_key === null) { $id_key = $this->getIDKeyForUse(); } return $this->$id_key; } public function getPHID() { return $this->phid; } /** * Test if a property exists. * * @param string Property name. * @return bool True if the property exists. * @task info */ public function hasProperty($property) { return (bool)$this->checkProperty($property); } /** * Retrieve a list of all object properties. This list only includes * properties that are declared as protected, and it is expected that * all properties returned by this function should be persisted to the * database. * Properties that should not be persisted must be declared as private. * * @return dict Dictionary of normalized (lowercase) to canonical (original * case) property names. * * @task info */ protected function getAllLiskProperties() { static $properties = null; if (!isset($properties)) { $class = new ReflectionClass(get_class($this)); $properties = array(); foreach ($class->getProperties(ReflectionProperty::IS_PROTECTED) as $p) { $properties[strtolower($p->getName())] = $p->getName(); } $id_key = $this->getIDKey(); if ($id_key != 'id') { unset($properties['id']); } if (!$this->getConfigOption(self::CONFIG_TIMESTAMPS)) { unset($properties['datecreated']); unset($properties['datemodified']); } if ($id_key != 'phid' && !$this->getConfigOption(self::CONFIG_AUX_PHID)) { unset($properties['phid']); } } return $properties; } /** * Check if a property exists on this object. * * @return string|null Canonical property name, or null if the property * does not exist. * * @task info */ protected function checkProperty($property) { static $properties = null; if ($properties === null) { $properties = $this->getAllLiskProperties(); } $property = strtolower($property); if (empty($properties[$property])) { return null; } return $properties[$property]; } /** * Get or build the database connection for this object. * * @param string 'r' for read, 'w' for read/write. * @param bool True to force a new connection. The connection will not * be retrieved from or saved into the connection cache. * @return LiskDatabaseConnection Lisk connection object. * * @task info */ public function establishConnection($mode, $force_new = false) { if ($mode != 'r' && $mode != 'w') { throw new Exception( pht( "Unknown mode '%s', should be 'r' or 'w'.", $mode)); } if ($this->forcedConnection) { return $this->forcedConnection; } if (self::shouldIsolateAllLiskEffectsToCurrentProcess()) { $mode = 'isolate-'.$mode; $connection = $this->getEstablishedConnection($mode); if (!$connection) { $connection = $this->establishIsolatedConnection($mode); $this->setEstablishedConnection($mode, $connection); } return $connection; } if (self::shouldIsolateAllLiskEffectsToTransactions()) { // If we're doing fixture transaction isolation, force the mode to 'w' // so we always get the same connection for reads and writes, and thus // can see the writes inside the transaction. $mode = 'w'; } // TODO: There is currently no protection on 'r' queries against writing. $connection = null; if (!$force_new) { if ($mode == 'r') { // If we're requesting a read connection but already have a write // connection, reuse the write connection so that reads can take place // inside transactions. $connection = $this->getEstablishedConnection('w'); } if (!$connection) { $connection = $this->getEstablishedConnection($mode); } } if (!$connection) { $connection = $this->establishLiveConnection($mode); if (self::shouldIsolateAllLiskEffectsToTransactions()) { $connection->openTransaction(); } $this->setEstablishedConnection( $mode, $connection, $force_unique = $force_new); } return $connection; } /** * Convert this object into a property dictionary. This dictionary can be * restored into an object by using @{method:loadFromArray} (unless you're * using legacy features with CONFIG_CONVERT_CAMELCASE, but in that case you * should just go ahead and die in a fire). * * @return dict Dictionary of object properties. * * @task info */ protected function getAllLiskPropertyValues() { $map = array(); foreach ($this->getAllLiskProperties() as $p) { // We may receive a warning here for properties we've implicitly added // through configuration; squelch it. $map[$p] = @$this->$p; } return $map; } /* -( Writing Objects )---------------------------------------------------- */ /** * Make an object read-only. * * Making an object ephemeral indicates that you will be changing state in * such a way that you would never ever want it to be written back to the * storage. */ public function makeEphemeral() { $this->ephemeral = true; return $this; } private function isEphemeralCheck() { if ($this->ephemeral) { throw new LiskEphemeralObjectException(); } } /** * Persist this object to the database. In most cases, this is the only * method you need to call to do writes. If the object has not yet been * inserted this will do an insert; if it has, it will do an update. * * @return this * * @task save */ public function save() { if ($this->shouldInsertWhenSaved()) { return $this->insert(); } else { return $this->update(); } } /** * Save this object, forcing the query to use REPLACE regardless of object * state. * * @return this * * @task save */ public function replace() { $this->isEphemeralCheck(); return $this->insertRecordIntoDatabase('REPLACE'); } /** * Save this object, forcing the query to use INSERT regardless of object * state. * * @return this * * @task save */ public function insert() { $this->isEphemeralCheck(); return $this->insertRecordIntoDatabase('INSERT'); } /** * Save this object, forcing the query to use UPDATE regardless of object * state. * * @return this * * @task save */ public function update() { $this->isEphemeralCheck(); $this->willSaveObject(); $data = $this->getAllLiskPropertyValues(); // Remove colums flagged as nonmutable from the update statement. $no_mutate = $this->getConfigOption(self::CONFIG_NO_MUTATE); if ($no_mutate) { foreach ($no_mutate as $column) { unset($data[$column]); } } $this->willWriteData($data); $map = array(); foreach ($data as $k => $v) { $map[$k] = $v; } $conn = $this->establishConnection('w'); $binary = $this->getBinaryColumns(); foreach ($map as $key => $value) { if (!empty($binary[$key])) { $map[$key] = qsprintf($conn, '%C = %nB', $key, $value); } else { $map[$key] = qsprintf($conn, '%C = %ns', $key, $value); } } $map = implode(', ', $map); $id = $this->getID(); $conn->query( 'UPDATE %T SET %Q WHERE %C = '.(is_int($id) ? '%d' : '%s'), $this->getTableName(), $map, $this->getIDKeyForUse(), $id); // We can't detect a missing object because updating an object without // changing any values doesn't affect rows. We could jiggle timestamps // to catch this for objects which track them if we wanted. $this->didWriteData(); return $this; } /** * Delete this object, permanently. * * @return this * * @task save */ public function delete() { $this->isEphemeralCheck(); $this->willDelete(); $conn = $this->establishConnection('w'); $conn->query( 'DELETE FROM %T WHERE %C = %d', $this->getTableName(), $this->getIDKeyForUse(), $this->getID()); $this->didDelete(); return $this; } /** * Internal implementation of INSERT and REPLACE. * * @param const Either "INSERT" or "REPLACE", to force the desired mode. * * @task save */ protected function insertRecordIntoDatabase($mode) { $this->willSaveObject(); $data = $this->getAllLiskPropertyValues(); $conn = $this->establishConnection('w'); $id_mechanism = $this->getConfigOption(self::CONFIG_IDS); switch ($id_mechanism) { case self::IDS_AUTOINCREMENT: // If we are using autoincrement IDs, let MySQL assign the value for the // ID column, if it is empty. If the caller has explicitly provided a // value, use it. $id_key = $this->getIDKeyForUse(); if (empty($data[$id_key])) { unset($data[$id_key]); } break; case self::IDS_COUNTER: // If we are using counter IDs, assign a new ID if we don't already have // one. $id_key = $this->getIDKeyForUse(); if (empty($data[$id_key])) { $counter_name = $this->getTableName(); $id = self::loadNextCounterValue($conn, $counter_name); $this->setID($id); $data[$id_key] = $id; } break; case self::IDS_MANUAL: break; default: throw new Exception(pht('Unknown %s mechanism!', 'CONFIG_IDs')); } $this->willWriteData($data); $columns = array_keys($data); $binary = $this->getBinaryColumns(); foreach ($data as $key => $value) { try { if (!empty($binary[$key])) { $data[$key] = qsprintf($conn, '%nB', $value); } else { $data[$key] = qsprintf($conn, '%ns', $value); } } catch (AphrontParameterQueryException $parameter_exception) { throw new PhutilProxyException( pht( "Unable to insert or update object of class %s, field '%s' ". "has a non-scalar value.", get_class($this), $key), $parameter_exception); } } $data = implode(', ', $data); $conn->query( '%Q INTO %T (%LC) VALUES (%Q)', $mode, $this->getTableName(), $columns, $data); // Only use the insert id if this table is using auto-increment ids if ($id_mechanism === self::IDS_AUTOINCREMENT) { $this->setID($conn->getInsertID()); } $this->didWriteData(); return $this; } /** * Method used to determine whether to insert or update when saving. * * @return bool true if the record should be inserted */ protected function shouldInsertWhenSaved() { $key_type = $this->getConfigOption(self::CONFIG_IDS); if ($key_type == self::IDS_MANUAL) { throw new Exception( pht( 'You are using manual IDs. You must override the %s method '. 'to properly detect when to insert a new record.', __FUNCTION__.'()')); } else { return !$this->getID(); } } /* -( Hooks and Callbacks )------------------------------------------------ */ /** * Retrieve the database table name. By default, this is the class name. * * @return string Table name for object storage. * * @task hook */ public function getTableName() { return get_class($this); } /** * Retrieve the primary key column, "id" by default. If you can not * reasonably name your ID column "id", override this method. * * @return string Name of the ID column. * * @task hook */ public function getIDKey() { return 'id'; } protected function getIDKeyForUse() { $id_key = $this->getIDKey(); if (!$id_key) { throw new Exception( pht( 'This DAO does not have a single-part primary key. The method you '. 'called requires a single-part primary key.')); } return $id_key; } /** * Generate a new PHID, used by CONFIG_AUX_PHID. * * @return phid Unique, newly allocated PHID. * * @task hook */ public function generatePHID() { $type = $this->getPHIDType(); return PhabricatorPHID::generateNewPHID($type); } public function getPHIDType() { throw new PhutilMethodNotImplementedException(); } /** * Hook to apply serialization or validation to data before it is written to * the database. See also @{method:willReadData}. * * @task hook */ protected function willWriteData(array &$data) { $this->applyLiskDataSerialization($data, false); } /** * Hook to perform actions after data has been written to the database. * * @task hook */ protected function didWriteData() {} /** * Hook to make internal object state changes prior to INSERT, REPLACE or * UPDATE. * * @task hook */ protected function willSaveObject() { $use_timestamps = $this->getConfigOption(self::CONFIG_TIMESTAMPS); if ($use_timestamps) { if (!$this->getDateCreated()) { $this->setDateCreated(time()); } $this->setDateModified(time()); } if ($this->getConfigOption(self::CONFIG_AUX_PHID) && !$this->getPHID()) { $this->setPHID($this->generatePHID()); } } /** * Hook to apply serialization or validation to data as it is read from the * database. See also @{method:willWriteData}. * * @task hook */ protected function willReadData(array &$data) { $this->applyLiskDataSerialization($data, $deserialize = true); } /** * Hook to perform an action on data after it is read from the database. * * @task hook */ protected function didReadData() {} /** * Hook to perform an action before the deletion of an object. * * @task hook */ protected function willDelete() {} /** * Hook to perform an action after the deletion of an object. * * @task hook */ protected function didDelete() {} /** * Reads the value from a field. Override this method for custom behavior * of @{method:getField} instead of overriding getField directly. * * @param string Canonical field name * @return mixed Value of the field * * @task hook */ protected function readField($field) { if (isset($this->$field)) { return $this->$field; } return null; } /** * Writes a value to a field. Override this method for custom behavior of * setField($value) instead of overriding setField directly. * * @param string Canonical field name * @param mixed Value to write * * @task hook */ protected function writeField($field, $value) { $this->$field = $value; } /* -( Manging Transactions )----------------------------------------------- */ /** * Increase transaction stack depth. * * @return this */ public function openTransaction() { $this->establishConnection('w')->openTransaction(); return $this; } /** * Decrease transaction stack depth, saving work. * * @return this */ public function saveTransaction() { $this->establishConnection('w')->saveTransaction(); return $this; } /** * Decrease transaction stack depth, discarding work. * * @return this */ public function killTransaction() { $this->establishConnection('w')->killTransaction(); return $this; } /** * Begins read-locking selected rows with SELECT ... FOR UPDATE, so that * other connections can not read them (this is an enormous oversimplification * of FOR UPDATE semantics; consult the MySQL documentation for details). To * end read locking, call @{method:endReadLocking}. For example: * * $beach->openTransaction(); * $beach->beginReadLocking(); * * $beach->reload(); * $beach->setGrainsOfSand($beach->getGrainsOfSand() + 1); * $beach->save(); * * $beach->endReadLocking(); * $beach->saveTransaction(); * * @return this * @task xaction */ public function beginReadLocking() { $this->establishConnection('w')->beginReadLocking(); return $this; } /** * Ends read-locking that began at an earlier @{method:beginReadLocking} call. * * @return this * @task xaction */ public function endReadLocking() { $this->establishConnection('w')->endReadLocking(); return $this; } /** * Begins write-locking selected rows with SELECT ... LOCK IN SHARE MODE, so * that other connections can not update or delete them (this is an * oversimplification of LOCK IN SHARE MODE semantics; consult the * MySQL documentation for details). To end write locking, call * @{method:endWriteLocking}. * * @return this * @task xaction */ public function beginWriteLocking() { $this->establishConnection('w')->beginWriteLocking(); return $this; } /** * Ends write-locking that began at an earlier @{method:beginWriteLocking} * call. * * @return this * @task xaction */ public function endWriteLocking() { $this->establishConnection('w')->endWriteLocking(); return $this; } /* -( Isolation )---------------------------------------------------------- */ /** * @task isolate */ public static function beginIsolateAllLiskEffectsToCurrentProcess() { self::$processIsolationLevel++; } /** * @task isolate */ public static function endIsolateAllLiskEffectsToCurrentProcess() { self::$processIsolationLevel--; if (self::$processIsolationLevel < 0) { throw new Exception( pht('Lisk process isolation level was reduced below 0.')); } } /** * @task isolate */ public static function shouldIsolateAllLiskEffectsToCurrentProcess() { return (bool)self::$processIsolationLevel; } /** * @task isolate */ private function establishIsolatedConnection($mode) { $config = array(); return new AphrontIsolatedDatabaseConnection($config); } /** * @task isolate */ public static function beginIsolateAllLiskEffectsToTransactions() { if (self::$transactionIsolationLevel === 0) { self::closeAllConnections(); } self::$transactionIsolationLevel++; } /** * @task isolate */ public static function endIsolateAllLiskEffectsToTransactions() { self::$transactionIsolationLevel--; if (self::$transactionIsolationLevel < 0) { throw new Exception( pht('Lisk transaction isolation level was reduced below 0.')); } else if (self::$transactionIsolationLevel == 0) { foreach (self::$connections as $key => $conn) { if ($conn) { $conn->killTransaction(); } } self::closeAllConnections(); } } /** * @task isolate */ public static function shouldIsolateAllLiskEffectsToTransactions() { return (bool)self::$transactionIsolationLevel; } /** * Close any connections with no recent activity. * * Long-running processes can use this method to clean up connections which * have not been used recently. * * @param int Close connections with no activity for this many seconds. * @return void */ public static function closeInactiveConnections($idle_window) { $connections = self::$connections; $now = PhabricatorTime::getNow(); foreach ($connections as $key => $connection) { $last_active = $connection->getLastActiveEpoch(); $idle_duration = ($now - $last_active); if ($idle_duration <= $idle_window) { continue; } self::closeConnection($key); } } public static function closeAllConnections() { $connections = self::$connections; foreach ($connections as $key => $connection) { self::closeConnection($key); } } private static function closeConnection($key) { if (empty(self::$connections[$key])) { throw new Exception( pht( 'No database connection with connection key "%s" exists!', $key)); } $connection = self::$connections[$key]; unset(self::$connections[$key]); $connection->close(); } /* -( Utilities )---------------------------------------------------------- */ /** * Applies configured serialization to a dictionary of values. * * @task util */ protected function applyLiskDataSerialization(array &$data, $deserialize) { $serialization = $this->getConfigOption(self::CONFIG_SERIALIZATION); if ($serialization) { foreach (array_intersect_key($serialization, $data) as $col => $format) { switch ($format) { case self::SERIALIZATION_NONE: break; case self::SERIALIZATION_PHP: if ($deserialize) { $data[$col] = unserialize($data[$col]); } else { $data[$col] = serialize($data[$col]); } break; case self::SERIALIZATION_JSON: if ($deserialize) { $data[$col] = json_decode($data[$col], true); } else { $data[$col] = phutil_json_encode($data[$col]); } break; default: throw new Exception( pht("Unknown serialization format '%s'.", $format)); } } } } /** * Black magic. Builds implied get*() and set*() for all properties. * * @param string Method name. * @param list Argument vector. * @return mixed get*() methods return the property value. set*() methods * return $this. * @task util */ public function __call($method, $args) { // NOTE: PHP has a bug that static variables defined in __call() are shared // across all children classes. Call a different method to work around this // bug. return $this->call($method, $args); } /** * @task util */ final protected function call($method, $args) { // NOTE: This method is very performance-sensitive (many thousands of calls // per page on some pages), and thus has some silliness in the name of // optimizations. static $dispatch_map = array(); if ($method[0] === 'g') { if (isset($dispatch_map[$method])) { $property = $dispatch_map[$method]; } else { if (substr($method, 0, 3) !== 'get') { throw new Exception(pht("Unable to resolve method '%s'!", $method)); } $property = substr($method, 3); if (!($property = $this->checkProperty($property))) { throw new Exception(pht('Bad getter call: %s', $method)); } $dispatch_map[$method] = $property; } return $this->readField($property); } if ($method[0] === 's') { if (isset($dispatch_map[$method])) { $property = $dispatch_map[$method]; } else { if (substr($method, 0, 3) !== 'set') { throw new Exception(pht("Unable to resolve method '%s'!", $method)); } $property = substr($method, 3); $property = $this->checkProperty($property); if (!$property) { throw new Exception(pht('Bad setter call: %s', $method)); } $dispatch_map[$method] = $property; } $this->writeField($property, $args[0]); return $this; } throw new Exception(pht("Unable to resolve method '%s'.", $method)); } /** * Warns against writing to undeclared property. * * @task util */ public function __set($name, $value) { - phlog( - pht( - 'Wrote to undeclared property %s.', - get_class($this).'::$'.$name)); + // Hack for policy system hints, see PhabricatorPolicyRule for notes. + if ($name != '_hashKey') { + phlog( + pht( + 'Wrote to undeclared property %s.', + get_class($this).'::$'.$name)); + } $this->$name = $value; } /** * Increments a named counter and returns the next value. * * @param AphrontDatabaseConnection Database where the counter resides. * @param string Counter name to create or increment. * @return int Next counter value. * * @task util */ public static function loadNextCounterValue( AphrontDatabaseConnection $conn_w, $counter_name) { // NOTE: If an insert does not touch an autoincrement row or call // LAST_INSERT_ID(), MySQL normally does not change the value of // LAST_INSERT_ID(). This can cause a counter's value to leak to a // new counter if the second counter is created after the first one is // updated. To avoid this, we insert LAST_INSERT_ID(1), to ensure the // LAST_INSERT_ID() is always updated and always set correctly after the // query completes. queryfx( $conn_w, 'INSERT INTO %T (counterName, counterValue) VALUES (%s, LAST_INSERT_ID(1)) ON DUPLICATE KEY UPDATE counterValue = LAST_INSERT_ID(counterValue + 1)', self::COUNTER_TABLE_NAME, $counter_name); return $conn_w->getInsertID(); } /** * Returns the current value of a named counter. * * @param AphrontDatabaseConnection Database where the counter resides. * @param string Counter name to read. * @return int|null Current value, or `null` if the counter does not exist. * * @task util */ public static function loadCurrentCounterValue( AphrontDatabaseConnection $conn_r, $counter_name) { $row = queryfx_one( $conn_r, 'SELECT counterValue FROM %T WHERE counterName = %s', self::COUNTER_TABLE_NAME, $counter_name); if (!$row) { return null; } return (int)$row['counterValue']; } /** * Overwrite a named counter, forcing it to a specific value. * * If the counter does not exist, it is created. * * @param AphrontDatabaseConnection Database where the counter resides. * @param string Counter name to create or overwrite. * @return void * * @task util */ public static function overwriteCounterValue( AphrontDatabaseConnection $conn_w, $counter_name, $counter_value) { queryfx( $conn_w, 'INSERT INTO %T (counterName, counterValue) VALUES (%s, %d) ON DUPLICATE KEY UPDATE counterValue = VALUES(counterValue)', self::COUNTER_TABLE_NAME, $counter_name, $counter_value); } private function getBinaryColumns() { return $this->getConfigOption(self::CONFIG_BINARY); } public function getSchemaColumns() { $custom_map = $this->getConfigOption(self::CONFIG_COLUMN_SCHEMA); if (!$custom_map) { $custom_map = array(); } $serialization = $this->getConfigOption(self::CONFIG_SERIALIZATION); if (!$serialization) { $serialization = array(); } $serialization_map = array( self::SERIALIZATION_JSON => 'text', self::SERIALIZATION_PHP => 'bytes', ); $binary_map = $this->getBinaryColumns(); $id_mechanism = $this->getConfigOption(self::CONFIG_IDS); if ($id_mechanism == self::IDS_AUTOINCREMENT) { $id_type = 'auto'; } else { $id_type = 'id'; } $builtin = array( 'id' => $id_type, 'phid' => 'phid', 'viewPolicy' => 'policy', 'editPolicy' => 'policy', 'epoch' => 'epoch', 'dateCreated' => 'epoch', 'dateModified' => 'epoch', ); $map = array(); foreach ($this->getAllLiskProperties() as $property) { // First, use types specified explicitly in the table configuration. if (array_key_exists($property, $custom_map)) { $map[$property] = $custom_map[$property]; continue; } // If we don't have an explicit type, try a builtin type for the // column. $type = idx($builtin, $property); if ($type) { $map[$property] = $type; continue; } // If the column has serialization, we can infer the column type. if (isset($serialization[$property])) { $type = idx($serialization_map, $serialization[$property]); if ($type) { $map[$property] = $type; continue; } } if (isset($binary_map[$property])) { $map[$property] = 'bytes'; continue; } if ($property === 'spacePHID') { $map[$property] = 'phid?'; continue; } // If the column is named `somethingPHID`, infer it is a PHID. if (preg_match('/[a-z]PHID$/', $property)) { $map[$property] = 'phid'; continue; } // If the column is named `somethingID`, infer it is an ID. if (preg_match('/[a-z]ID$/', $property)) { $map[$property] = 'id'; continue; } // We don't know the type of this column. $map[$property] = PhabricatorConfigSchemaSpec::DATATYPE_UNKNOWN; } return $map; } public function getSchemaKeys() { $custom_map = $this->getConfigOption(self::CONFIG_KEY_SCHEMA); if (!$custom_map) { $custom_map = array(); } $default_map = array(); foreach ($this->getAllLiskProperties() as $property) { switch ($property) { case 'id': $default_map['PRIMARY'] = array( 'columns' => array('id'), 'unique' => true, ); break; case 'phid': $default_map['key_phid'] = array( 'columns' => array('phid'), 'unique' => true, ); break; case 'spacePHID': $default_map['key_space'] = array( 'columns' => array('spacePHID'), ); break; } } return $custom_map + $default_map; } public function getColumnMaximumByteLength($column) { $map = $this->getSchemaColumns(); if (!isset($map[$column])) { throw new Exception( pht( 'Object (of class "%s") does not have a column "%s".', get_class($this), $column)); } $data_type = $map[$column]; return id(new PhabricatorStorageSchemaSpec()) ->getMaximumByteLengthForDataType($data_type); } } diff --git a/src/view/layout/PhabricatorActionView.php b/src/view/layout/PhabricatorActionView.php index 493f8c3dbd..8788529945 100644 --- a/src/view/layout/PhabricatorActionView.php +++ b/src/view/layout/PhabricatorActionView.php @@ -1,315 +1,319 @@ selected = $selected; return $this; } public function getSelected() { return $this->selected; } public function setMetadata($metadata) { $this->metadata = $metadata; return $this; } public function getMetadata() { return $this->metadata; } public function setDownload($download) { $this->download = $download; return $this; } public function getDownload() { return $this->download; } public function setHref($href) { $this->href = $href; return $this; } public function addSigil($sigil) { $this->sigils[] = $sigil; return $this; } public function getHref() { return $this->href; } public function setIcon($icon) { $this->icon = $icon; return $this; } public function setName($name) { $this->name = $name; return $this; } public function getName() { return $this->name; } public function setLabel($label) { $this->label = $label; return $this; } public function setDisabled($disabled) { $this->disabled = $disabled; return $this; } public function getDisabled() { return $this->disabled; } public function setWorkflow($workflow) { $this->workflow = $workflow; return $this; } public function setRenderAsForm($form) { $this->renderAsForm = $form; return $this; } public function setOpenInNewWindow($open_in_new_window) { $this->openInNewWindow = $open_in_new_window; return $this; } public function getOpenInNewWindow() { return $this->openInNewWindow; } public function getID() { if (!$this->id) { $this->id = celerity_generate_unique_node_id(); } return $this->id; } public function setSubmenu(array $submenu) { $this->submenu = $submenu; if (!$this->getHref()) { $this->setHref('#'); } return $this; } public function getItems($depth = 0) { $items = array(); $items[] = $this; foreach ($this->submenu as $action) { foreach ($action->getItems($depth + 1) as $item) { $item ->setHidden(true) ->setDepth($depth + 1); $items[] = $item; } } return $items; } public function setHidden($hidden) { $this->hidden = $hidden; return $this; } public function getHidden() { return $this->hidden; } public function setDepth($depth) { $this->depth = $depth; return $this; } public function getDepth() { return $this->depth; } public function render() { $caret_id = celerity_generate_unique_node_id(); $icon = null; if ($this->icon) { $color = ''; if ($this->disabled) { $color = ' grey'; } $icon = id(new PHUIIconView()) ->addClass('phabricator-action-view-icon') ->setIcon($this->icon.$color); } if ($this->href) { $sigils = array(); if ($this->workflow) { $sigils[] = 'workflow'; } if ($this->download) { $sigils[] = 'download'; } if ($this->sigils) { $sigils = array_merge($sigils, $this->sigils); } $sigils = $sigils ? implode(' ', $sigils) : null; if ($this->renderAsForm) { if (!$this->hasViewer()) { throw new Exception( pht( 'Call %s when rendering an action as a form.', 'setViewer()')); } $item = javelin_tag( 'button', array( 'class' => 'phabricator-action-view-item', ), array($icon, $this->name)); $item = phabricator_form( $this->getViewer(), array( 'action' => $this->getHref(), 'method' => 'POST', 'sigil' => $sigils, 'meta' => $this->metadata, ), $item); } else { if ($this->getOpenInNewWindow()) { $target = '_blank'; } else { $target = null; } if ($this->submenu) { $caret = javelin_tag( 'span', array( 'class' => 'caret-right', 'id' => $caret_id, ), ''); } else { $caret = null; } $item = javelin_tag( 'a', array( 'href' => $this->getHref(), 'class' => 'phabricator-action-view-item', 'target' => $target, 'sigil' => $sigils, 'meta' => $this->metadata, ), array($icon, $this->name, $caret)); } } else { $item = phutil_tag( 'span', array( 'class' => 'phabricator-action-view-item', ), array($icon, $this->name)); } $classes = array(); $classes[] = 'phabricator-action-view'; if ($this->disabled) { $classes[] = 'phabricator-action-view-disabled'; } if ($this->label) { $classes[] = 'phabricator-action-view-label'; } if ($this->selected) { $classes[] = 'phabricator-action-view-selected'; } if ($this->submenu) { $classes[] = 'phabricator-action-view-submenu'; } + if ($this->getHref()) { + $classes[] = 'phabricator-action-view-href'; + } + $style = array(); if ($this->hidden) { $style[] = 'display: none;'; } if ($this->depth) { $indent = ($this->depth * 16); $style[] = "margin-left: {$indent}px;"; } $sigil = null; $meta = null; if ($this->submenu) { Javelin::initBehavior('phui-submenu'); $sigil = 'phui-submenu'; $item_ids = array(); foreach ($this->submenu as $subitem) { $item_ids[] = $subitem->getID(); } $meta = array( 'itemIDs' => $item_ids, 'caretID' => $caret_id, ); } return javelin_tag( 'li', array( 'id' => $this->getID(), 'class' => implode(' ', $classes), 'style' => implode(' ', $style), 'sigil' => $sigil, 'meta' => $meta, ), $item); } } diff --git a/src/view/phui/PHUIObjectItemListView.php b/src/view/phui/PHUIObjectItemListView.php index 6c81053f0a..53e86382c2 100644 --- a/src/view/phui/PHUIObjectItemListView.php +++ b/src/view/phui/PHUIObjectItemListView.php @@ -1,142 +1,160 @@ allowEmptyList = $allow_empty_list; return $this; } public function getAllowEmptyList() { return $this->allowEmptyList; } public function setFlush($flush) { $this->flush = $flush; return $this; } public function setHeader($header) { $this->header = $header; return $this; } public function setPager($pager) { $this->pager = $pager; return $this; } public function setSimple($simple) { $this->simple = $simple; return $this; } public function setBig($big) { $this->big = $big; return $this; } + public function setDrag($drag) { + $this->drag = $drag; + $this->setItemClass('phui-oi-drag'); + return $this; + } + public function setNoDataString($no_data_string) { $this->noDataString = $no_data_string; return $this; } public function addItem(PHUIObjectItemView $item) { $this->items[] = $item; return $this; } public function setItemClass($item_class) { $this->itemClass = $item_class; return $this; } protected function getTagName() { return 'ul'; } protected function getTagAttributes() { $classes = array(); + $classes[] = 'phui-oi-list-view'; - $classes[] = 'phui-object-item-list-view'; if ($this->flush) { - $classes[] = 'phui-object-list-flush'; + $classes[] = 'phui-oi-list-flush'; + require_celerity_resource('phui-oi-flush-ui-css'); } + if ($this->simple) { - $classes[] = 'phui-object-list-simple'; + $classes[] = 'phui-oi-list-simple'; + require_celerity_resource('phui-oi-simple-ui-css'); } + if ($this->big) { - $classes[] = 'phui-object-list-big'; + $classes[] = 'phui-oi-list-big'; + require_celerity_resource('phui-oi-big-ui-css'); + } + + if ($this->drag) { + $classes[] = 'phui-oi-list-drag'; + require_celerity_resource('phui-oi-drag-ui-css'); } return array( 'class' => $classes, ); } protected function getTagContent() { $viewer = $this->getUser(); - require_celerity_resource('phui-object-item-list-view-css'); + require_celerity_resource('phui-oi-list-view-css'); + require_celerity_resource('phui-oi-color-css'); $header = null; if (strlen($this->header)) { $header = phutil_tag( 'h1', array( - 'class' => 'phui-object-item-list-header', + 'class' => 'phui-oi-list-header', ), $this->header); } if ($this->items) { if ($viewer) { foreach ($this->items as $item) { $item->setUser($viewer); } } foreach ($this->items as $item) { $item->addClass($this->itemClass); } $items = $this->items; } else if ($this->allowEmptyList) { $items = null; } else { $string = nonempty($this->noDataString, pht('No data.')); $string = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) ->appendChild($string); $items = phutil_tag( 'li', array( - 'class' => 'phui-object-item-empty', + 'class' => 'phui-oi-empty', ), $string); } $pager = null; if ($this->pager) { $pager = $this->pager; } return array( $header, $items, $pager, $this->renderChildren(), ); } } diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php index 80fe6fb4d0..6d193081d2 100644 --- a/src/view/phui/PHUIObjectItemView.php +++ b/src/view/phui/PHUIObjectItemView.php @@ -1,740 +1,740 @@ disabled = $disabled; return $this; } public function getDisabled() { return $this->disabled; } public function addHeadIcon($icon) { $this->headIcons[] = $icon; return $this; } public function setObjectName($name) { $this->objectName = $name; return $this; } public function setGrippable($grippable) { $this->grippable = $grippable; return $this; } public function getGrippable() { return $this->grippable; } public function setEffect($effect) { $this->effect = $effect; return $this; } public function getEffect() { return $this->effect; } public function setObject($object) { $this->object = $object; return $this; } public function getObject() { return $this->object; } public function setHref($href) { $this->href = $href; return $this; } public function getHref() { return $this->href; } public function setHeader($header) { $this->header = $header; return $this; } public function setSubHead($subhead) { $this->subhead = $subhead; return $this; } public function setBadge(PHUIBadgeMiniView $badge) { $this->badge = $badge; return $this; } public function setCountdown($num, $noun) { $this->countdownNum = $num; $this->countdownNoun = $noun; return $this; } public function setTitleText($title_text) { $this->titleText = $title_text; return $this; } public function getTitleText() { return $this->titleText; } public function getHeader() { return $this->header; } public function addByline($byline) { $this->bylines[] = $byline; return $this; } public function setImageURI($image_uri) { $this->imageURI = $image_uri; return $this; } public function getImageURI() { return $this->imageURI; } public function setImageIcon($image_icon) { if (!$image_icon instanceof PHUIIconView) { $image_icon = id(new PHUIIconView()) ->setIcon($image_icon); } $this->imageIcon = $image_icon; return $this; } public function getImageIcon() { return $this->imageIcon; } public function setCoverImage($image) { $this->coverImage = $image; return $this; } public function setEpoch($epoch) { $date = phabricator_datetime($epoch, $this->getUser()); $this->addIcon('none', $date); return $this; } public function addAction(PHUIListItemView $action) { if (count($this->actions) >= 3) { throw new Exception(pht('Limit 3 actions per item.')); } $this->actions[] = $action; return $this; } public function addIcon($icon, $label = null, $attributes = array()) { $this->icons[] = array( 'icon' => $icon, 'label' => $label, 'attributes' => $attributes, ); return $this; } /** * This method has been deprecated, use @{method:setImageIcon} instead. * * @deprecated */ public function setIcon($icon) { phlog( pht('Deprecated call to setIcon(), use setImageIcon() instead.')); return $this->setImageIcon($icon); } public function setStatusIcon($icon, $label = null) { $this->statusIcon = array( 'icon' => $icon, 'label' => $label, ); return $this; } public function addHandleIcon( PhabricatorObjectHandle $handle, $label = null) { $this->handleIcons[] = array( 'icon' => $handle, 'label' => $label, ); return $this; } public function setBarColor($bar_color) { $this->barColor = $bar_color; return $this; } public function getBarColor() { return $this->barColor; } public function addAttribute($attribute) { if (!empty($attribute)) { $this->attributes[] = $attribute; } return $this; } public function setLaunchButton(PHUIButtonView $button) { $button->setSize(PHUIButtonView::SMALL); $this->launchButton = $button; return $this; } protected function getTagName() { return 'li'; } protected function getTagAttributes() { $item_classes = array(); - $item_classes[] = 'phui-object-item'; + $item_classes[] = 'phui-oi'; if ($this->icons) { - $item_classes[] = 'phui-object-item-with-icons'; + $item_classes[] = 'phui-oi-with-icons'; } if ($this->attributes) { - $item_classes[] = 'phui-object-item-with-attrs'; + $item_classes[] = 'phui-oi-with-attrs'; } if ($this->handleIcons) { - $item_classes[] = 'phui-object-item-with-handle-icons'; + $item_classes[] = 'phui-oi-with-handle-icons'; } if ($this->barColor) { - $item_classes[] = 'phui-object-item-bar-color-'.$this->barColor; + $item_classes[] = 'phui-oi-bar-color-'.$this->barColor; } else { - $item_classes[] = 'phui-object-item-no-bar'; + $item_classes[] = 'phui-oi-no-bar'; } if ($this->actions) { $n = count($this->actions); - $item_classes[] = 'phui-object-item-with-actions'; - $item_classes[] = 'phui-object-item-with-'.$n.'-actions'; + $item_classes[] = 'phui-oi-with-actions'; + $item_classes[] = 'phui-oi-with-'.$n.'-actions'; } if ($this->disabled) { - $item_classes[] = 'phui-object-item-disabled'; + $item_classes[] = 'phui-oi-disabled'; } switch ($this->effect) { case 'highlighted': - $item_classes[] = 'phui-object-item-highlighted'; + $item_classes[] = 'phui-oi-highlighted'; break; case 'selected': - $item_classes[] = 'phui-object-item-selected'; + $item_classes[] = 'phui-oi-selected'; break; case 'visited': - $item_classes[] = 'phui-object-item-visited'; + $item_classes[] = 'phui-oi-visited'; break; case null: break; default: throw new Exception(pht('Invalid effect!')); } if ($this->getGrippable()) { - $item_classes[] = 'phui-object-item-grippable'; + $item_classes[] = 'phui-oi-grippable'; } if ($this->getImageURI()) { - $item_classes[] = 'phui-object-item-with-image'; + $item_classes[] = 'phui-oi-with-image'; } if ($this->getImageIcon()) { - $item_classes[] = 'phui-object-item-with-image-icon'; + $item_classes[] = 'phui-oi-with-image-icon'; } return array( 'class' => $item_classes, ); } protected function getTagContent() { $viewer = $this->getUser(); $content_classes = array(); - $content_classes[] = 'phui-object-item-content'; + $content_classes[] = 'phui-oi-content'; $header_name = array(); if ($viewer) { $header_name[] = id(new PHUISpacesNamespaceContextView()) ->setUser($viewer) ->setObject($this->object); } if ($this->objectName) { $header_name[] = array( phutil_tag( 'span', array( - 'class' => 'phui-object-item-objname', + 'class' => 'phui-oi-objname', ), $this->objectName), ' ', ); } $title_text = null; if ($this->titleText) { $title_text = $this->titleText; } else if ($this->href) { $title_text = $this->header; } $header_link = phutil_tag( $this->href ? 'a' : 'div', array( 'href' => $this->href, - 'class' => 'phui-object-item-link', + 'class' => 'phui-oi-link', 'title' => $title_text, ), $this->header); // Wrap the header content in a with the "slippery" sigil. This // prevents us from beginning a drag if you click the text (like "T123"), // but not if you click the white space after the header. $header = phutil_tag( 'div', array( - 'class' => 'phui-object-item-name', + 'class' => 'phui-oi-name', ), javelin_tag( 'span', array( 'sigil' => 'slippery', ), array( $this->headIcons, $header_name, $header_link, ))); $icons = array(); if ($this->icons) { $icon_list = array(); foreach ($this->icons as $spec) { $icon = $spec['icon']; $icon = id(new PHUIIconView()) ->setIcon($icon) - ->addClass('phui-object-item-icon-image'); + ->addClass('phui-oi-icon-image'); if (isset($spec['attributes']['tip'])) { $sigil = 'has-tooltip'; $meta = array( 'tip' => $spec['attributes']['tip'], 'align' => 'W', ); $icon->addSigil($sigil); $icon->setMetadata($meta); } $label = phutil_tag( 'span', array( - 'class' => 'phui-object-item-icon-label', + 'class' => 'phui-oi-icon-label', ), $spec['label']); if (isset($spec['attributes']['href'])) { $icon_href = phutil_tag( 'a', array('href' => $spec['attributes']['href']), array($icon, $label)); } else { $icon_href = array($icon, $label); } $classes = array(); - $classes[] = 'phui-object-item-icon'; + $classes[] = 'phui-oi-icon'; if (isset($spec['attributes']['class'])) { $classes[] = $spec['attributes']['class']; } $icon_list[] = javelin_tag( 'li', array( 'class' => implode(' ', $classes), ), $icon_href); } $icons[] = phutil_tag( 'ul', array( - 'class' => 'phui-object-item-icons', + 'class' => 'phui-oi-icons', ), $icon_list); } $handle_bar = null; if ($this->handleIcons) { $handle_bar = array(); foreach ($this->handleIcons as $handleicon) { $handle_bar[] = $this->renderHandleIcon($handleicon['icon'], $handleicon['label']); } $handle_bar = phutil_tag( 'li', array( - 'class' => 'phui-object-item-handle-icons', + 'class' => 'phui-oi-handle-icons', ), $handle_bar); } $bylines = array(); if ($this->bylines) { foreach ($this->bylines as $byline) { $bylines[] = phutil_tag( 'div', array( - 'class' => 'phui-object-item-byline', + 'class' => 'phui-oi-byline', ), $byline); } $bylines = phutil_tag( 'div', array( - 'class' => 'phui-object-item-bylines', + 'class' => 'phui-oi-bylines', ), $bylines); } $subhead = null; if ($this->subhead) { $subhead = phutil_tag( 'div', array( - 'class' => 'phui-object-item-subhead', + 'class' => 'phui-oi-subhead', ), $this->subhead); } if ($icons) { $icons = phutil_tag( 'div', array( 'class' => 'phui-object-icon-pane', ), $icons); } $attrs = null; if ($this->attributes || $handle_bar) { $attrs = array(); $spacer = phutil_tag( 'span', array( - 'class' => 'phui-object-item-attribute-spacer', + 'class' => 'phui-oi-attribute-spacer', ), "\xC2\xB7"); $first = true; foreach ($this->attributes as $attribute) { $attrs[] = phutil_tag( 'li', array( - 'class' => 'phui-object-item-attribute', + 'class' => 'phui-oi-attribute', ), array( ($first ? null : $spacer), $attribute, )); $first = false; } $attrs = phutil_tag( 'ul', array( - 'class' => 'phui-object-item-attributes', + 'class' => 'phui-oi-attributes', ), array( $handle_bar, $attrs, )); } $status = null; if ($this->statusIcon) { $icon = $this->statusIcon; $status = $this->renderStatusIcon($icon['icon'], $icon['label']); } $grippable = null; if ($this->getGrippable()) { $grippable = phutil_tag( 'div', array( - 'class' => 'phui-object-item-grip', + 'class' => 'phui-oi-grip', ), ''); } $content = phutil_tag( 'div', array( 'class' => implode(' ', $content_classes), ), array( $subhead, $attrs, $this->renderChildren(), )); $image = null; if ($this->getImageURI()) { $image = phutil_tag( 'div', array( - 'class' => 'phui-object-item-image', + 'class' => 'phui-oi-image', 'style' => 'background-image: url('.$this->getImageURI().')', ), ''); } else if ($this->getImageIcon()) { $image = phutil_tag( 'div', array( - 'class' => 'phui-object-item-image-icon', + 'class' => 'phui-oi-image-icon', ), $this->getImageIcon()); } if ($image && $this->href) { $image = phutil_tag( 'a', array( 'href' => $this->href, ), $image); } /* Build a fake table */ $column0 = null; if ($status) { $column0 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col0', + 'class' => 'phui-oi-col0', ), $status); } if ($this->badge) { $column0 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col0 phui-object-item-badge', + 'class' => 'phui-oi-col0 phui-oi-badge', ), $this->badge); } if ($this->countdownNum) { $countdown = phutil_tag( 'div', array( - 'class' => 'phui-object-item-countdown-number', + 'class' => 'phui-oi-countdown-number', ), array( phutil_tag_div('', $this->countdownNum), phutil_tag_div('', $this->countdownNoun), )); $column0 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col0 phui-object-item-countdown', + 'class' => 'phui-oi-col0 phui-oi-countdown', ), $countdown); } $column1 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col1', + 'class' => 'phui-oi-col1', ), array( $header, $content, )); $column2 = null; if ($icons || $bylines) { $column2 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col2', + 'class' => 'phui-oi-col2', ), array( $icons, $bylines, )); } if ($this->launchButton) { $column2 = phutil_tag( 'div', array( - 'class' => 'phui-object-item-col2 phui-object-item-launch-button', + 'class' => 'phui-oi-col2 phui-oi-launch-button', ), array( $this->launchButton, )); } $table = phutil_tag( 'div', array( - 'class' => 'phui-object-item-table', + 'class' => 'phui-oi-table', ), phutil_tag_div( - 'phui-object-item-table-row', + 'phui-oi-table-row', array( $column0, $column1, $column2, ))); $box = phutil_tag( 'div', array( - 'class' => 'phui-object-item-content-box', + 'class' => 'phui-oi-content-box', ), array( $grippable, $table, )); $actions = array(); if ($this->actions) { Javelin::initBehavior('phabricator-tooltips'); foreach (array_reverse($this->actions) as $action) { $action->setRenderNameAsTooltip(true); $actions[] = $action; } $actions = phutil_tag( 'ul', array( - 'class' => 'phui-object-item-actions', + 'class' => 'phui-oi-actions', ), $actions); } $frame_content = phutil_tag( 'div', array( - 'class' => 'phui-object-item-frame-content', + 'class' => 'phui-oi-frame-content', ), array( $actions, $image, $box, )); $frame_cover = null; if ($this->coverImage) { $cover_image = phutil_tag( 'img', array( 'src' => $this->coverImage, - 'class' => 'phui-object-item-cover-image', + 'class' => 'phui-oi-cover-image', )); $frame_cover = phutil_tag( 'div', array( - 'class' => 'phui-object-item-frame-cover', + 'class' => 'phui-oi-frame-cover', ), $cover_image); } $frame = phutil_tag( 'div', array( - 'class' => 'phui-object-item-frame', + 'class' => 'phui-oi-frame', ), array( $frame_cover, $frame_content, )); return $frame; } private function renderStatusIcon($icon, $label) { Javelin::initBehavior('phabricator-tooltips'); $icon = id(new PHUIIconView()) ->setIcon($icon); $options = array( - 'class' => 'phui-object-item-status-icon', + 'class' => 'phui-oi-status-icon', ); if (strlen($label)) { $options['sigil'] = 'has-tooltip'; $options['meta'] = array('tip' => $label, 'size' => 300); } return javelin_tag('div', $options, $icon); } private function renderHandleIcon(PhabricatorObjectHandle $handle, $label) { Javelin::initBehavior('phabricator-tooltips'); $options = array( - 'class' => 'phui-object-item-handle-icon', + 'class' => 'phui-oi-handle-icon', 'style' => 'background-image: url('.$handle->getImageURI().')', ); if (strlen($label)) { $options['sigil'] = 'has-tooltip'; $options['meta'] = array('tip' => $label, 'align' => 'E'); } return javelin_tag('span', $options, ''); } } diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php index 87fee5cfa6..a5834befd3 100644 --- a/src/view/phui/PHUITimelineEventView.php +++ b/src/view/phui/PHUITimelineEventView.php @@ -1,667 +1,673 @@ authorPHID = $author_phid; return $this; } public function getAuthorPHID() { return $this->authorPHID; } public function setQuoteRef($quote_ref) { $this->quoteRef = $quote_ref; return $this; } public function getQuoteRef() { return $this->quoteRef; } public function setQuoteTargetID($quote_target_id) { $this->quoteTargetID = $quote_target_id; return $this; } public function getQuoteTargetID() { return $this->quoteTargetID; } public function setIsNormalComment($is_normal_comment) { $this->isNormalComment = $is_normal_comment; return $this; } public function getIsNormalComment() { return $this->isNormalComment; } public function setHideByDefault($hide_by_default) { $this->hideByDefault = $hide_by_default; return $this; } public function getHideByDefault() { return $this->hideByDefault; } public function setTransactionPHID($transaction_phid) { $this->transactionPHID = $transaction_phid; return $this; } public function getTransactionPHID() { return $this->transactionPHID; } public function setIsEdited($is_edited) { $this->isEdited = $is_edited; return $this; } public function getIsEdited() { return $this->isEdited; } public function setIsPreview($is_preview) { $this->isPreview = $is_preview; return $this; } public function getIsPreview() { return $this->isPreview; } public function setIsEditable($is_editable) { $this->isEditable = $is_editable; return $this; } public function getIsEditable() { return $this->isEditable; } public function setIsRemovable($is_removable) { $this->isRemovable = $is_removable; return $this; } public function getIsRemovable() { return $this->isRemovable; } public function setDateCreated($date_created) { $this->dateCreated = $date_created; return $this; } public function getDateCreated() { return $this->dateCreated; } public function setContentSource(PhabricatorContentSource $content_source) { $this->contentSource = $content_source; return $this; } public function getContentSource() { return $this->contentSource; } public function setUserHandle(PhabricatorObjectHandle $handle) { $this->userHandle = $handle; return $this; } public function setAnchor($anchor) { $this->anchor = $anchor; return $this; } public function getAnchor() { return $this->anchor; } public function setTitle($title) { $this->title = $title; return $this; } public function addClass($class) { $this->classes[] = $class; return $this; } public function addBadge(PHUIBadgeMiniView $badge) { $this->badges[] = $badge; return $this; } public function setIcon($icon) { $this->icon = $icon; return $this; } public function setColor($color) { $this->color = $color; return $this; } public function setReallyMajorEvent($me) { $this->reallyMajorEvent = $me; return $this; } public function setHideCommentOptions($hide_comment_options) { $this->hideCommentOptions = $hide_comment_options; return $this; } public function getHideCommentOptions() { return $this->hideCommentOptions; } public function setToken($token, $removed = false) { $this->token = $token; $this->tokenRemoved = $removed; return $this; } public function getEventGroup() { return array_merge(array($this), $this->eventGroup); } public function addEventToGroup(PHUITimelineEventView $event) { $this->eventGroup[] = $event; return $this; } protected function shouldRenderEventTitle() { if ($this->title === null) { return false; } return true; } protected function renderEventTitle($force_icon, $has_menu, $extra) { $title = $this->title; $title_classes = array(); $title_classes[] = 'phui-timeline-title'; $icon = null; if ($this->icon || $force_icon) { $title_classes[] = 'phui-timeline-title-with-icon'; } if ($has_menu) { $title_classes[] = 'phui-timeline-title-with-menu'; } if ($this->icon) { $fill_classes = array(); $fill_classes[] = 'phui-timeline-icon-fill'; if ($this->color) { $fill_classes[] = 'fill-has-color'; $fill_classes[] = 'phui-timeline-icon-fill-'.$this->color; } $icon = id(new PHUIIconView()) ->setIcon($this->icon) ->addClass('phui-timeline-icon'); $icon = phutil_tag( 'span', array( 'class' => implode(' ', $fill_classes), ), $icon); } $token = null; if ($this->token) { $token = id(new PHUIIconView()) ->addClass('phui-timeline-token') ->setSpriteSheet(PHUIIconView::SPRITE_TOKENS) ->setSpriteIcon($this->token); if ($this->tokenRemoved) { $token->addClass('strikethrough'); } } $title = phutil_tag( 'div', array( 'class' => implode(' ', $title_classes), ), array($icon, $token, $title, $extra)); return $title; } public function render() { $events = $this->getEventGroup(); // Move events with icons first. $icon_keys = array(); foreach ($this->getEventGroup() as $key => $event) { if ($event->icon) { $icon_keys[] = $key; } } $events = array_select_keys($events, $icon_keys) + $events; $force_icon = (bool)$icon_keys; $menu = null; $items = array(); $has_menu = false; if (!$this->getIsPreview() && !$this->getHideCommentOptions()) { foreach ($this->getEventGroup() as $event) { $items[] = $event->getMenuItems($this->anchor); if ($event->hasChildren()) { $has_menu = true; } } $items = array_mergev($items); } if ($items || $has_menu) { $icon = id(new PHUIIconView()) ->setIcon('fa-caret-down'); $aural = javelin_tag( 'span', array( 'aural' => true, ), pht('Comment Actions')); if ($items) { $sigil = 'phui-dropdown-menu'; Javelin::initBehavior('phui-dropdown-menu'); } else { $sigil = null; } $action_list = id(new PhabricatorActionListView()) ->setUser($this->getUser()); foreach ($items as $item) { $action_list->addAction($item); } $menu = javelin_tag( $items ? 'a' : 'span', array( 'href' => '#', 'class' => 'phui-timeline-menu', 'sigil' => $sigil, 'aria-haspopup' => 'true', 'aria-expanded' => 'false', 'meta' => $action_list->getDropdownMenuMetadata(), ), array( $aural, $icon, )); $has_menu = true; } // Render "extra" information (timestamp, etc). $extra = $this->renderExtra($events); $show_badges = false; $group_titles = array(); $group_items = array(); $group_children = array(); foreach ($events as $event) { if ($event->shouldRenderEventTitle()) { + + // Render the group anchor here, outside the title box. If we render + // it inside the title box it ends up completely hidden and Chrome 55 + // refuses to jump to it. See T11997 for discussion. + + if ($extra && $this->anchor) { + $group_titles[] = id(new PhabricatorAnchorView()) + ->setAnchorName($this->anchor) + ->render(); + } + $group_titles[] = $event->renderEventTitle( $force_icon, $has_menu, $extra); // Don't render this information more than once. $extra = null; } if ($event->hasChildren()) { $group_children[] = $event->renderChildren(); $show_badges = true; } } $image_uri = $this->userHandle->getImageURI(); $wedge = phutil_tag( 'div', array( 'class' => 'phui-timeline-wedge phui-timeline-border', 'style' => (nonempty($image_uri)) ? '' : 'display: none;', ), ''); $image = null; $badges = null; if ($image_uri) { $image = phutil_tag( ($this->userHandle->getURI()) ? 'a' : 'div', array( 'style' => 'background-image: url('.$image_uri.')', 'class' => 'phui-timeline-image', 'href' => $this->userHandle->getURI(), ), ''); if ($this->badges && $show_badges) { $flex = new PHUIBadgeBoxView(); $flex->addItems($this->badges); $flex->setCollapsed(true); $badges = phutil_tag( 'div', array( 'class' => 'phui-timeline-badges', ), $flex); } } $content_classes = array(); $content_classes[] = 'phui-timeline-content'; $classes = array(); $classes[] = 'phui-timeline-event-view'; if ($group_children) { $classes[] = 'phui-timeline-major-event'; $content = phutil_tag( 'div', array( 'class' => 'phui-timeline-inner-content', ), array( $group_titles, $menu, phutil_tag( 'div', array( 'class' => 'phui-timeline-core-content', ), $group_children), )); } else { $classes[] = 'phui-timeline-minor-event'; $content = $group_titles; } $content = phutil_tag( 'div', array( 'class' => 'phui-timeline-group phui-timeline-border', ), $content); $content = phutil_tag( 'div', array( 'class' => implode(' ', $content_classes), ), array($image, $badges, $wedge, $content)); $outer_classes = $this->classes; $outer_classes[] = 'phui-timeline-shell'; $color = null; foreach ($this->getEventGroup() as $event) { if ($event->color) { $color = $event->color; break; } } if ($color) { $outer_classes[] = 'phui-timeline-'.$color; } $sigil = null; $meta = null; if ($this->getTransactionPHID()) { $sigil = 'transaction'; $meta = array( 'phid' => $this->getTransactionPHID(), 'anchor' => $this->anchor, ); } $major_event = null; if ($this->reallyMajorEvent) { $major_event = phutil_tag( 'div', array( 'class' => 'phui-timeline-event-view '. 'phui-timeline-spacer '. 'phui-timeline-spacer-bold', '', )); } return array( javelin_tag( 'div', array( 'class' => implode(' ', $outer_classes), 'id' => $this->anchor ? 'anchor-'.$this->anchor : null, 'sigil' => $sigil, 'meta' => $meta, ), phutil_tag( 'div', array( 'class' => implode(' ', $classes), ), $content)), $major_event, ); } private function renderExtra(array $events) { $extra = array(); if ($this->getIsPreview()) { $extra[] = pht('PREVIEW'); } else { foreach ($events as $event) { if ($event->getIsEdited()) { $extra[] = pht('Edited'); break; } } $source = $this->getContentSource(); $content_source = null; if ($source) { $content_source = id(new PhabricatorContentSourceView()) ->setContentSource($source) ->setUser($this->getUser()); $content_source = pht('Via %s', $content_source->getSourceName()); } $date_created = null; foreach ($events as $event) { if ($event->getDateCreated()) { if ($date_created === null) { $date_created = $event->getDateCreated(); } else { $date_created = min($event->getDateCreated(), $date_created); } } } if ($date_created) { $date = phabricator_datetime( $date_created, $this->getUser()); if ($this->anchor) { Javelin::initBehavior('phabricator-watch-anchor'); Javelin::initBehavior('phabricator-tooltips'); - $anchor = id(new PhabricatorAnchorView()) - ->setAnchorName($this->anchor) - ->render(); - $date = array( - $anchor, javelin_tag( 'a', array( 'href' => '#'.$this->anchor, 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $content_source, - ), + ), ), $date), ); } $extra[] = $date; } } $extra = javelin_tag( 'span', array( 'class' => 'phui-timeline-extra', ), phutil_implode_html( javelin_tag( 'span', array( 'aural' => false, ), self::DELIMITER), $extra)); return $extra; } private function getMenuItems($anchor) { $xaction_phid = $this->getTransactionPHID(); $items = array(); if ($this->getIsEditable()) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setHref('/transactions/edit/'.$xaction_phid.'/') ->setName(pht('Edit Comment')) ->addSigil('transaction-edit') ->setMetadata( array( 'anchor' => $anchor, )); } if ($this->getQuoteTargetID()) { $ref = null; if ($this->getQuoteRef()) { $ref = $this->getQuoteRef(); if ($anchor) { $ref = $ref.'#'.$anchor; } } $items[] = id(new PhabricatorActionView()) ->setIcon('fa-quote-left') ->setHref('#') ->setName(pht('Quote')) ->addSigil('transaction-quote') ->setMetadata( array( 'targetID' => $this->getQuoteTargetID(), 'uri' => '/transactions/quote/'.$xaction_phid.'/', 'ref' => $ref, )); } if ($this->getIsNormalComment()) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-cutlery') ->setHref('/transactions/raw/'.$xaction_phid.'/') ->setName(pht('View Raw')) ->addSigil('transaction-raw') ->setMetadata( array( 'anchor' => $anchor, )); $content_source = $this->getContentSource(); $source_email = PhabricatorEmailContentSource::SOURCECONST; if ($content_source->getSource() == $source_email) { $source_id = $content_source->getContentSourceParameter('id'); if ($source_id) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-envelope-o') ->setHref('/transactions/raw/'.$xaction_phid.'/?email') ->setName(pht('View Email Body')) ->addSigil('transaction-raw') ->setMetadata( array( 'anchor' => $anchor, )); } } } if ($this->getIsRemovable()) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-times') ->setHref('/transactions/remove/'.$xaction_phid.'/') ->setName(pht('Remove Comment')) ->addSigil('transaction-remove') ->setMetadata( array( 'anchor' => $anchor, )); } if ($this->getIsEdited()) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-list') ->setHref('/transactions/history/'.$xaction_phid.'/') ->setName(pht('View Edit History')) ->setWorkflow(true); } return $items; } } diff --git a/webroot/rsrc/css/aphront/dialog-view.css b/webroot/rsrc/css/aphront/dialog-view.css index 9cf56394df..3b2de1cee6 100644 --- a/webroot/rsrc/css/aphront/dialog-view.css +++ b/webroot/rsrc/css/aphront/dialog-view.css @@ -1,189 +1,189 @@ /** * @provides aphront-dialog-view-css */ .aphront-dialog-view { width: 540px; margin: 32px auto 16px; border: 1px solid {$lightblueborder}; border-radius: 3px; background-color: #fff; } .jx-client-dialog .aphront-dialog-view { box-shadow: {$dropshadow}; } .device-phone .aphront-dialog-view { margin: 16px; width: auto; } .aphront-dialog-view-standalone { margin: 32px auto; } .aphront-dialog-head { padding: 12px 12px 0 12px; } .aphront-dialog-flush .aphront-dialog-body { padding: 0; } .aphront-dialog-view-width-form { width: 600px; } .aphront-dialog-view-width-full { width: 90%; max-width: 1040px; } .aphront-dialog-body { background: #fff; padding: 16px; border: none; } .device-phone .aphront-dialog-body { padding: 8px; } .aphront-dialog-tail { border: none; position: relative; background: {$lightgreybackground}; padding: 8px 16px; border-top: 1px solid {$thinblueborder}; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; } .device .aphront-dialog-resize { /* No resizing on devices. */ display: none; } .aphront-dialog-resize { position: absolute; right: -4px; bottom: -4px; width: 18px; height: 18px; background-image: url(/rsrc/image/resize.png); background-size: 100%; cursor: nwse-resize; pointer-events: all; } .aphront-dialog-foot { padding: 6px 0; float: left; } .aphront-dialog-tail button, .aphront-dialog-tail a.button { float: right; margin-left: 8px; } .jx-client-dialog { position: absolute; width: 100%; } .jx-mask { opacity: .7; background: #292f33; position: fixed; top: 0; left: 0; right: 0; bottom: 0; } .jx-dark-mask { background: #292f33; opacity: 0.95; } .jx-white-mask { background: #fff; opacity: 1; } .jx-date-mask { background: #292f33; opacity: 0.5; } .device-desktop .jx-date-mask { display: none; } .aphront-exception-dialog { width: 95%; } .aphront-exception-dialog .exception-message { font-size: 14px; background: {$sh-yellowbackground}; border: 1px solid {$sh-yellowborder}; padding: 12px; white-space: pre-wrap; } .aphront-exception-dialog .exception-trace { margin-top: 16px; } .aphront-access-dialog { width: 50%; } .aphront-policy-explain-dialog .aphront-dialog-body { padding: 0 12px; } .aphront-policy-rejection { font-weight: bold; } .aphront-capability-details { margin: 20px 0 4px; } .aphront-dialog-view-paragraph + .aphront-dialog-view-paragraph { margin-top: 16px; } -.device-desktop .aphront-dialog-flush .phui-object-item-list-view { +.device-desktop .aphront-dialog-flush .phui-oi-list-view { margin: 0; padding: 0; } -.aphront-dialog-flush .phui-object-item-list-view.phui-object-list-stackable - .phui-object-item { +.aphront-dialog-flush .phui-oi-list-view.phui-object-list-stackable + .phui-oi { border: 0; } -.aphront-dialog-flush .phui-object-item-list-view.phui-object-list-stackable - .phui-object-item-frame { +.aphront-dialog-flush .phui-oi-list-view.phui-object-list-stackable + .phui-oi-frame { border: 0; border-top: 1px solid {$thinblueborder}; } .aphront-dialog-object-list .phui-object-box { border: none; padding: 0; margin: 0; } .aphront-dialog-object-list .aphront-dialog-body { padding: 0 12px; } .aphront-dialog-tab-group .aphront-dialog-body { padding: 0 12px; } diff --git a/webroot/rsrc/css/application/config/config-page.css b/webroot/rsrc/css/application/config/config-page.css index 5fe15aadb8..82cb9642d2 100644 --- a/webroot/rsrc/css/application/config/config-page.css +++ b/webroot/rsrc/css/application/config/config-page.css @@ -1,77 +1,77 @@ /** * @provides config-page-css */ .config-page-header { margin: 28px 24px 0; padding-bottom: 28px; border-bottom: 1px solid {$thinblueborder}; } .device-phone .config-page-header { margin: 4px 12px 0; padding-bottom: 4px; } .config-page-header .phui-profile-header { padding: 0; } .device-phone .config-page-header .phui-profile-header { padding-left: 4px; padding-right: 4px; } .config-page-header .phui-profile-header.phui-header-shell .phui-header-header { font-size: 20px; } .device-phone .config-page-header .phui-profile-header.phui-header-shell .phui-header-header { font-size: 16px; } .config-page-content { margin: 0 24px; } .device-phone .config-page-content { margin: 0 4px; } -.device-desktop .config-page-content .phui-object-item-list-view { +.device-desktop .config-page-content .phui-oi-list-view { padding-left: 0; padding-right: 0; } .device-desktop .config-page-content .phui-document-fluid .phui-document-view { padding: 16px 0; margin: 0; } .config-page-content .aphront-table-view { border: none; } .config-page-property { padding-top: 4px; border-bottom: 1px solid {$thinblueborder}; } .config-page-content .aphront-table-notice { padding: 0; } .config-page-content .aphront-table-notice .phui-info-view { margin-left: 0; margin-right: 0; } .config-page-content .aphront-table-wrap + .aphront-table-wrap { margin-top: 20px; border-top: 1px solid {$thinblueborder}; } .config-page-content .phui-box.phui-box-blue-property { margin-top: 16px; } diff --git a/webroot/rsrc/css/application/flag/flag.css b/webroot/rsrc/css/application/flag/flag.css index 8f6f7a45e8..7d5f0af5d2 100644 --- a/webroot/rsrc/css/application/flag/flag.css +++ b/webroot/rsrc/css/application/flag/flag.css @@ -1,83 +1,83 @@ /** * @provides phabricator-flag-css */ .phabricator-flag-icon { padding: 8px; background: transparent 0 0 no-repeat; } -.phui-object-item .phabricator-flag-icon { +.phui-oi .phabricator-flag-icon { float: left; margin: 2px; margin-right: 8px; margin-bottom: 0; } .phabricator-flag-radio { padding-left: 18px; margin: 1px; background: transparent 0 0 no-repeat; } .phabricator-flag-color-0 { background-image: url(/rsrc/image/icon/fatcow/flag_red.png); } .phabricator-flag-color-1 { background-image: url(/rsrc/image/icon/fatcow/flag_orange.png); } .phabricator-flag-color-2 { background-image: url(/rsrc/image/icon/fatcow/flag_yellow.png); } .phabricator-flag-color-3 { background-image: url(/rsrc/image/icon/fatcow/flag_green.png); } .phabricator-flag-color-4 { background-image: url(/rsrc/image/icon/fatcow/flag_blue.png); } .phabricator-flag-color-5 { background-image: url(/rsrc/image/icon/fatcow/flag_pink.png); } .phabricator-flag-color-6 { background-image: url(/rsrc/image/icon/fatcow/flag_purple.png); } .phabricator-flag-color-7 { background-image: url(/rsrc/image/icon/fatcow/flag_finish.png); } .phabricator-flag-ghost { background-image: url(/rsrc/image/icon/fatcow/flag_ghost.png); } .phabricator-flag-select-control .phabricator-flag-select-label { border: 1px solid #aaaaaa; width: 48px; height: 24px; border-radius: 4px; position: relative; display: inline-block; cursor: pointer; margin: 0 4px 4px 0; } .phabricator-flag-select-control .phabricator-flag-select-checkbox { position: absolute; top: 2px; left: 4px; width: auto; } .phabricator-flag-select-control .phui-icon-view { position: absolute; width: 16px; height: 16px; top: 4px; left: 24px; } diff --git a/webroot/rsrc/css/application/phame/phame.css b/webroot/rsrc/css/application/phame/phame.css index 6a9a5b5717..7b20009356 100644 --- a/webroot/rsrc/css/application/phame/phame.css +++ b/webroot/rsrc/css/application/phame/phame.css @@ -1,323 +1,323 @@ /** * @provides phame-css */ .phame-blog-description { max-width: 800px; margin: 32px auto; position: relative; padding: 0 8px; } .phame-blog-description-name { font-weight: bold; font-size: {$biggerfontsize}; margin: 0 0 4px 50px; } .phame-blog-description-content { margin-left: 50px; } .phame-blog-description-image { display: inline-block; background-repeat: no-repeat; background-size: 100%; - box-shadow: inset 0 0 0 1px rgba({$alphagrey},.15); width: 40px; height: 40px; border-radius: 3px; position: absolute; } .phame-blog-description + .phui-document-view-pro-box { border-top: 1px solid rgba({$alphablue}, 0.20); } .phame-home-view .phui-document-view.phui-document-view-pro { margin: 0; } .phame-home-view .phui-side-column { background-color: #fff; } .phame-home-view { background-color: #fff; border-bottom: 1px solid rgba({$alphagrey},.1); } .phame-home-view .phame-home-container { max-width: 980px; margin: 0 auto; } .phame-home-view .phui-document-container { border: none; } .phame-blog-list { margin: 96px 16px 16px 16px; } .phame-blog-list + .phame-blog-list { margin-top: 24px; } .device .phame-blog-list { margin: 16px; } .device-phone .phame-blog-list { margin: 16px 8px; } .phame-blog-list-header { font-size: {$biggerfontsize}; margin-bottom: 16px; } .phame-blog-list-header a { color: {$darkbluetext}; } .phame-blog-list-item { display: block; color: {$darkgreytext}; position: relative; margin-bottom: 8px; padding-right: 20px; } .phame-blog-list-title:hover { color: {$violet}; text-decoration: none; } .phame-blog-list-image { display: inline-block; background-repeat: no-repeat; background-size: 100%; - box-shadow: inset 0 0 0 1px rgba({$alphagrey},.15); width: 24px; height: 24px; border-radius: 3px; position: absolute; } .phame-blog-list-title { margin-left: 30px; margin-top: 2px; display: inline-block; font-weight: bold; color: {$bluetext}; width: 190px; overflow: hidden; } .phame-blog-list-new-post { display: block; position: absolute; top: 6px; right: 0; } .phame-blog-list-new-post:hover { color: {$violet}; text-decoration: none; } .phame-blog-list-new-post:hover .phame-blog-list-icon { color: {$violet}; } .phame-blog-list-icon { display: block; height: 14px; width: 14px; color: {$lightbluetext}; } .phame-next-post-view { margin: 0 auto; padding: 12px 0; font-family: 'Aleo', {$fontfamily}; } .phame-next { width: 360px; float: right; text-align: right; color: #000; position: relative; } .phame-next-arrow, .phame-previous-arrow { border: 1px solid {$lightblueborder}; border-radius: 36px; height: 36px; width: 36px; text-align: center; } .phame-next-arrow .phui-icon-view, .phame-previous-arrow .phui-icon-view { height: 36px; width: 34px; font-size: 24px; line-height: 35px; color: {$lightblueborder}; } .phame-previous-arrow { float: left; } .phame-next-arrow { float: right; } .phame-previous { width: 360px; float: left; text-align: left; color: #000; position: relative; } .device .phame-previous, .device .phame-next { width: 100px; } .device .phame-previous .phame-previous-title, .device .phame-next .phame-next-title { display: none; } .phame-next:hover, .phame-previous:hover { text-decoration: none; } .phame-next:hover .phame-next-arrow, .phame-previous:hover .phame-previous-arrow { border-color: {$indigo}; } .phame-next:hover .phui-icon-view, .phame-previous:hover .phui-icon-view { color: {$indigo}; } .phame-next-header, .phame-previous-header { font-weight: bold; font-size: {$biggerfontsize}; } .phame-next-header { top: 2px; right: 50px; position: absolute; } .phame-next-title { top: 22px; right: 50px; position: absolute; } .phame-previous-header { top: 2px; left: 50px; position: absolute; } .phame-previous-title { top: 22px; left: 50px; position: absolute; } .phame-404 { margin: 48px auto; padding: 12px 24px; border-radius: 6px; min-width: 240px; width: 50%; color: {$darkgreytext}; background: {$greybackground}; } /* Blog Chrome */ .phame-live-view .phui-crumbs-view { - background: #fff; border: none; - padding-left: 8px; + width: 960px; + margin: 0 auto; + padding: 4px 0; } /* Hero Image */ .phame-header-hero { background-color: #fff; + margin-top: 16px; } .phame-header-image { max-height: 320px; max-width: 100%; margin: 0 auto; } .phui-document-view.phui-document-view-pro .phui-header-shell.phame-header-bar { border-top: 1px solid {$thinblueborder}; border-bottom: none; padding: 4px 0; } .phame-header-bar .phui-header-subheader { margin: 0; } .phame-mega-header { margin: 0 auto; text-align: center; background: #fff; padding: 16px 0 24px; } .device-phone .phame-mega-header { padding: 24px 0; } .phame-mega-header .phame-header-title { color: #000; font-size: 28px; font-weight: bold; font-family: 'Aleo', {$fontfamily}; padding-top: 24px; } .device-phone .phame-mega-header .phame-header-title { padding-top: 0; } .phame-mega-header .phame-header-subtitle { color: {$greytext}; font-size: 20px; font-family: 'Aleo', {$fontfamily}; padding-top: 8px; } .phame-comment-view .phui-comment-form-view .phui-comment-action-bar { display: none; } .phame-comment-view .phui-comment-form-view .phui-comment-has-actions .phui-comment-textarea-control { padding-top: 16px; } .phame-comment-view .phui-document-view-pro-box .phui-object-box { margin-bottom: 16px; } diff --git a/webroot/rsrc/css/application/project/project-view.css b/webroot/rsrc/css/application/project/project-view.css index 7fc3001d80..5b72e1c9eb 100644 --- a/webroot/rsrc/css/application/project/project-view.css +++ b/webroot/rsrc/css/application/project/project-view.css @@ -1,89 +1,89 @@ /** * @provides project-view-css */ .project-view-header-tag { margin-left: 8px; font-size: {$normalfontsize}; color: {$bluetext}; font-family: {$fontfamily}; font-weight: normal; } .device-phone .project-view-header-tag { display: block; margin-left: -4px; } .project-view-header-tag .phui-icon-view { color: {$bluetext}; } .device .project-view-home .phui-two-column-row { display: flex; flex-direction: column-reverse; } .project-view-home .phui-box.project-view-properties { margin: 0 0 16px 0; padding: 0; border: 1px solid rgba({$alphagrey}, .2); background-color: #fff; } .device-desktop .phui-two-column-view .project-view-properties .phui-property-list-container { padding: 12px 0; } .project-view-properties .phui-property-list-container + .phui-property-list-text-content { border-color: rgba({$alphagrey},.2); } .project-view-properties .phui-property-list-key { width: auto; margin-left: 4px; } .project-view-properties .phui-property-list-section-header { border: none; padding: 12px 4px 0; } .project-view-feed.phui-object-box.phui-box-border { border: 1px solid rgba({$alphagrey}, .2); } .project-view-home .phui-box-grey { padding: 0; } .project-view-home .phui-box-grey .phui-header-shell { padding: 6px 6px 6px 12px; } .project-view-home .phui-box-grey .phui-header-header { font-size: {$biggerfontsize}; } .project-view-home .phui-box-grey .phui-header-action-link { margin-top: 0; margin-bottom: 0; } -.project-view-home .phui-box-grey .phui-object-item-list-view { +.project-view-home .phui-box-grey .phui-oi-list-view { padding: 4px 8px 0 8px; } .project-view-badges .phui-badge-flex-view { background-color: #fff; } -.project-view-home .phui-box-grey .phui-object-item-attribute .phui-icon-view { +.project-view-home .phui-box-grey .phui-oi-attribute .phui-icon-view { color: {$lightgreytext}; } .profile-no-badges { padding: 24px 0; } diff --git a/webroot/rsrc/css/application/search/search-results.css b/webroot/rsrc/css/application/search/search-results.css index f02efe1315..734d86c029 100644 --- a/webroot/rsrc/css/application/search/search-results.css +++ b/webroot/rsrc/css/application/search/search-results.css @@ -1,18 +1,18 @@ /** * @provides phabricator-search-results-css */ -.phui-object-item-link strong { +.phui-oi-link strong { color: {$fire}; text-decoration: underline; } .phui-source-fragment { color: {$darkgreytext}; } .phui-source-fragment strong { background-color: {$lightyellow}; font-weight: normal; color: #000; } diff --git a/webroot/rsrc/css/layout/phabricator-source-code-view.css b/webroot/rsrc/css/layout/phabricator-source-code-view.css index 4bd57fcfcb..7e956b580a 100644 --- a/webroot/rsrc/css/layout/phabricator-source-code-view.css +++ b/webroot/rsrc/css/layout/phabricator-source-code-view.css @@ -1,74 +1,74 @@ /** * @provides phabricator-source-code-view-css */ .phabricator-source-code-container { overflow-x: auto; overflow-y: hidden; border: 1px solid {$sh-lightyellowborder}; border-radius: 3px; background-color: #FFFEF5; } -.phui-object-item .phabricator-source-code-container { +.phui-oi .phabricator-source-code-container { margin-left: 8px; } .phabricator-source-code-view tr:first-child * { padding-top: 8px; } .phabricator-source-code-view tr:last-child * { padding-bottom: 8px; } .phabricator-source-code { white-space: pre-wrap; padding: 2px 8px 1px; width: 100%; } .phabricator-source-line { background-color: {$sh-yellowbackground}; text-align: right; padding: 2px 6px 1px 12px; border-right: 1px solid {$sh-lightyellowborder}; color: {$sh-yellowtext}; /* When the user selects rows of source, don't visibly select the line numbers beside them. We use JS to strip the line numbers out when the user copies the text. */ -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select: none; -ms-user-select: none; user-select: none; white-space: nowrap; } th.phabricator-source-line a { color: {$darkbluetext}; } th.phabricator-source-line:hover { background: {$sh-lightyellowborder}; cursor: pointer; } .phabricator-source-highlight { background: {$sh-yellowbackground}; } .phabricator-source-code-summary { padding-bottom: 8px; } /* If a Paste has enormously long lines, truncate them in the summary on the list page. They'll be fully visible on the Paste itself. */ .phabricator-source-code-summary .phabricator-source-code-container { overflow-x: hidden; } .phabricator-source-code-summary .phabricator-source-code { white-space: nowrap; } diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css new file mode 100644 index 0000000000..7fcc6d4ef7 --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-big-ui.css @@ -0,0 +1,48 @@ +/** + * @provides phui-oi-big-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-oi-list-big ul.phui-oi-list-view { + margin: 0; + padding: 20px; +} + +.phui-oi-list-big .phui-oi-no-bar .phui-oi-frame { + border: 0; +} + +.phui-oi-list-big .phui-oi-image-icon { + margin: 8px 2px 12px; +} + +.phui-oi-list-big a.phui-oi-link { + color: #000; + font-size: {$biggestfontsize}; +} + +.phui-oi-list-big .phui-oi-name { + padding-top: 6px; +} + +.phui-oi-list-big .phui-oi-launch-button a.button { + font-size: {$normalfontsize}; + padding: 3px 12px 4px; +} + +.device-desktop .phui-oi-list-big .phui-oi { + margin-bottom: 8px; +} + +.phui-oi-list-big .phui-oi-col0 { + vertical-align: top; + padding: 0; +} + +.phui-oi-list-big .phui-oi-status-icon { + padding: 5px; +} + +.phui-oi-list-big .phui-oi-visited a.phui-oi-link { + color: {$violet}; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-color.css b/webroot/rsrc/css/phui/object-item/phui-oi-color.css new file mode 100644 index 0000000000..e9ec630727 --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-color.css @@ -0,0 +1,68 @@ +/** + * @provides phui-oi-color-css + * @requires phui-oi-list-view-css + */ + + +/* - Bar Colors ---------------------------------------------------------------- + Colors for the left-hand border bars, used to indicate object status or other + attributes. +*/ + +.phui-oi-bar-color-red { + border-left-color: {$red}; +} + +.phui-oi-bar-color-orange { + border-left-color: {$orange}; +} + +.phui-oi-bar-color-yellow { + border-left-color: {$yellow}; +} + +.phui-oi-bar-color-green { + border-left-color: {$green}; +} + +.phui-oi-bar-color-sky { + border-left-color: {$sky}; +} + +.phui-oi-bar-color-blue { + border-left-color: {$blue}; +} + +.phui-oi-bar-color-indigo { + border-left-color: {$indigo}; +} + +.phui-oi-bar-color-violet { + border-left-color: {$violet}; +} + +.phui-oi-bar-color-pink { + border-left-color: {$pink}; +} + +.phui-oi-bar-color-fire { + border-left-color: {$fire}; +} + +.phui-oi-bar-color-bluegrey { + border-left-color: {$bluetext}; +} + +.phui-oi-bar-color-lightbluetext { + border-left-color: {$lightbluetext}; +} + +.phui-oi-bar-color-grey, +.phui-oi-bar-color-lightgreytext { + border-left-color: {$lightgreytext}; +} + +.phui-oi-bar-color-black, +.phui-oi-bar-color-dark { + border-left-color: {$darkgreytext}; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-drag-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-drag-ui.css new file mode 100644 index 0000000000..caf9ff8dd0 --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-drag-ui.css @@ -0,0 +1,59 @@ +/** + * @provides phui-oi-drag-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-object-box .phui-oi-list-view.phui-oi-list-drag { + margin-top: 8px; + margin-bottom: 4px; +} + +.phui-oi.phui-oi-drag { + background: {$bluebackground}; + border-radius: 3px; + border: none; +} + +.phui-oi.phui-oi-drag, +.phui-oi.phui-oi-drag .phui-oi-frame { + border: none; +} + +.phui-object-box .phui-oi-list-view .phui-oi.phui-oi-drag { + margin-top: 4px; +} + +.phui-oi-drag.phui-oi-with-image-icon .phui-oi-frame, +.phui-oi-drag.phui-oi-with-image .phui-oi-frame, +.phui-oi-drag .phui-oi-frame { + min-height: 36px; +} + +.phui-oi-drag .phui-oi-list-icon { + height: auto; + width: auto; +} + +.phui-oi-drag .phui-oi-image-icon .phui-icon-view { + height: 16px; + width: 16px; + font-size: 16px; + line-height: 20px; +} + +.phui-oi-drag.phui-oi-grippable .phui-oi-frame { + padding-left: 28px; +} + +.phui-oi-drag .phui-oi-grip { + left: 4px; +} + +.phui-oi-drag.phui-oi-with-image-icon .phui-oi-content-box, +.phui-oi-drag.phui-oi-with-image .phui-oi-content-box { + margin-left: 24px; +} + +.phui-oi-list-drag .drag-ghost { + margin-top: 4px; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-flush-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-flush-ui.css new file mode 100644 index 0000000000..2902cb22ce --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-flush-ui.css @@ -0,0 +1,13 @@ +/** + * @provides phui-oi-flush-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-oi-list-view.phui-oi-list-flush { + padding: 0; + margin: 0; +} + +.phui-object-box .phui-oi-list-flush .phui-oi { + margin: 0; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css new file mode 100644 index 0000000000..018245e21c --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css @@ -0,0 +1,625 @@ +/** + * @provides phui-oi-list-view-css + */ + +.phui-oi { + border-left-width: 0; +} + +ul.phui-oi-list-view { + padding: 8px; + list-style: none; +} + +.device-desktop .phui-oi-list-view { + padding: 16px; +} + +.phui-oi-list-view + .phui-oi-list-view { + padding-top: 0; +} + +.phui-object-box .phui-oi-list-view .phui-oi { + margin: 0; +} + +.phui-oi-list-view .phui-info-view { + margin: 0; +} + +.phui-object-box .phui-oi-list-view .phui-info-view { + color: {$greytext}; + border: none; +} + +.phui-oi { + border-style: solid; + border-color: {$lightgreyborder}; + margin: 5px 0; + overflow: hidden; + background: #fff; + margin-bottom: 4px; +} + +.phui-oi .phui-icon-view { + display: inline-block; +} + +.phui-oi-frame { + border-color: {$lightblueborder}; + border-width: 1px 1px 1px 0; + border-style: solid; + position: relative; + min-height: 33px; + overflow: hidden; +} + +.phui-oi-cover-image { + display: none; +} + +.phui-oi-no-bar .phui-oi-frame { + border-width: 1px; +} + +.device-desktop .phui-oi { + margin: 0 0 4px 0; +} + +.phui-object-box .phui-oi-list-view { + margin: 0; +} + +.phui-oi-status-icon { + font-weight: bold; + padding: 3px; + font-size: 16px; +} + +.phui-oi-list-view .phui-oi-col0 .phui-icon-view { + width: 17px; + text-align: center; + overflow: visible; + position: relative; + left: -1px; +} + +.phui-oi-name { + padding: 8px 8px 0; + white-space: nowrap; + word-wrap: break-word; + overflow: hidden; + text-overflow: ellipsis; + font-weight: bold; + -webkit-font-smoothing: antialiased; +} + +.device-phone .phui-oi-name { + overflow: normal; + white-space: normal; + font-weight: bold; +} + +.phui-oi-link { + display: inline; +} + +.phui-oi-objname { + color: #000; + cursor: text; + font-weight: bold; +} + +.phui-oi-content { + margin: 4px 8px 2px 0; + overflow: hidden; +} + +.phui-oi-grippable { + cursor: move; +} + +.device .phui-oi-grippable { + cursor: normal; +} + +.phui-oi-grip { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 20px; + background: url('/rsrc/image/texture/grip.png') center center no-repeat; +} + +.device .phui-oi-grip { + display: none; +} + +.phui-oi-grippable .phui-oi-frame { + padding-left: 16px; +} + +.device .phui-oi-grippable .phui-oi-frame { + padding-left: 0; +} + +.phui-oi-list-header { + padding: 0 0 8px 0; + color: {$darkgreytext}; +} + +.phui-oi-table { + display: table; + table-layout: fixed; + width: 100%; +} + +.phui-oi-table-row { + display: table-row; +} + +.phui-oi-col0 { + width: 20px; + display: table-cell; + vertical-align: middle; + padding-left: 4px; +} + +.device-phone .phui-oi-col0 { + vertical-align: top; + padding-top: 8px; +} + +.phui-oi-col1 { + display: table-cell; + vertical-align: top; +} + +.phui-oi-col2 { + width: 160px; + display: table-cell; + vertical-align: top; +} + +.device-phone .phui-oi-col1, +.device-phone .phui-oi-col2 { + display: block; + width: auto; +} + +/* - Item Actions -------------------------------------------------------------- + + Action buttons, like "Edit" and "Delete". + +*/ + +.phui-oi-actions { + position: absolute; + right: 4px; + top: 4px; + bottom: 4px; + vertical-align: middle; + text-align: right; +} + +.phui-oi-actions .phui-list-item-view { + float: right; + height: 100%; + width: 24px; + display: inline-block; + position: relative; +} + +.phui-oi-actions .phui-list-item-href { + display: inline-block; + position: relative; + width: 24px; + height: 100%; +} + +.device-desktop .phui-oi-actions .phui-list-item-href:hover { + background: {$hoverblue}; + border-radius: 3px; +} + +.phui-oi-actions .phui-list-item-icon { + width: 14px; + height: 14px; + position: absolute; + display: block; + top: 50%; + margin-top: -7px; + left: 3px; +} + +.phui-oi-actions .phui-list-item-name { + display: none; +} + +.phui-oi-with-1-actions .phui-oi-content-box { + margin-right: 28px; + overflow: hidden; +} + +.phui-oi-with-2-actions .phui-oi-content-box { + margin-right: 54px; + overflow: hidden; +} + +.phui-oi-with-3-actions .phui-oi-content-box { + margin-right: 76px; + overflow: hidden; +} + + +/* - Object Box List ----------------------------------------------------------- + + Tighter, stacking list when inside an Object Box + +*/ + +.phui-object-box .phui-oi-list-view { + padding: 0; + border: none; +} + +.phui-object-box .phui-oi-frame { + border-right: none; +} + +.phui-object-box .phui-oi:last-child + .phui-oi-frame { + border-bottom: none; +} + + +/* - Subhead ------------------------------------------------------------------- + + Descriptive Text or Links under the main header, before attributes. + +*/ + +.phui-oi-subhead { + color: {$greytext}; + padding: 0 8px 6px; +} + + +/* - Attribute List ------------------------------------------------------------ + + Object attributes, commonly used to render created date, etc. + +*/ + +.phui-oi-attributes { + padding: 0 8px 6px; + line-height: 18px; + min-height: 21px; +} + +.phui-oi-attribute { + display: inline-block; + color: {$greytext}; + vertical-align: top; +} + +.phui-oi-attribute-spacer { + padding: 0 4px; +} + + +/* - Icons --------------------------------------------------------------------- + + Icons, which show object state. On mobile, they are rendered without labels + to save space. + +*/ + +.phui-object-icon-pane { + margin: 8px 0 4px; +} + +.device-phone .phui-object-icon-pane { + margin: 0 0 4px; +} + +.phui-oi-icons { + padding: 0 4px 0 0; +} + +.device-phone .phui-oi-icons { + padding: 0 0 0 8px; +} + +ul.phui-oi-icons { + margin: 0; +} + +.phui-oi-icon { + vertical-align: middle; + font-size: {$smallerfontsize}; + color: {$greytext}; + text-align: right; + white-space: nowrap; + overflow: hidden; + min-height: 18px; + line-height: 18px; +} + +.device-phone .phui-oi-icon { + text-align: left; + font-size: 13px; +} + +/* + * Items with icon 'none' still have on mobile, thus creating a weird vertical + * margin for elements which follow + */ +.device-phone .phui-oi-icon .none { + display: none; +} + +.phui-oi-icon-image { + width: 14px; + height: 14px; + font-size: 13px; + margin-right: 4px; +} + + +/* - Disabled ------------------------------------------------------------------ + + Disabled/inactive objects. + +*/ + + +.phui-oi.phui-oi-disabled .phui-oi-link, +.phui-oi.phui-oi-disabled .phui-oi-link a { + color: {$lightgreytext}; +} + +.phui-oi.phui-oi-disabled .phui-oi-frame { + border-color: #d7d7d7; +} + +.phui-oi.phui-oi-disabled .phui-oi-objname { + color: {$greytext}; + text-decoration: line-through; +} + + +/* - Effects ------------------------------------------------------------------- + + Effects like highlighted items. + +*/ + +.phui-oi.phui-oi-highlighted { + background: {$sh-yellowbackground}; +} + +ul.phui-oi-list-view .phui-oi-highlighted + .phui-oi-frame { + border-color: {$sh-yellowborder}; +} + +.phui-oi-selected { + background: {$sh-bluebackground}; +} + +ul.phui-oi-list-view .phui-oi-selected + .phui-oi-frame { + border-color: {$sh-blueborder}; +} + + +/* - Handle Icons -------------------------------------------------------------- + + Shows owners, reviewers, etc., using profile picture icons. + +*/ + +.phui-oi-handle-icons { + bottom: 0; + right: 4px; + position: absolute; +} + +.phui-oi-handle-icon { + width: 24px; + height: 24px; + display: inline-block; + background-size: 100%; + border-radius: 3px; + background-repeat: no-repeat; +} + + +/* - Bylines ------------------------------------------------------------------- + + Shows owners, authors, reviewers, etc., in text. + +*/ + +.phui-oi-bylines { + padding: 0 4px 0 8px; + margin: 4px 0 8px; + font-size: {$smallerfontsize}; + color: {$greytext}; + text-align: right; +} + +.phui-oi-byline { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.device-phone .phui-oi-bylines { + float: none; + text-align: left; + padding: 0 8px; + font-size: {$normalfontsize}; +} + + +/* - Draggable List ------------------------------------------------------------ + + These classes are applied by and/or provided for use with JX.DraggableList. + +*/ + +.drag-ghost { + position: relative; + background: {$sh-indigobackground}; + border-radius: 3px; + margin-bottom: 4px; + border: 1px dashed {$sh-indigoborder}; +} + +.drag-dragging { + opacity: 0.25; +} + +.drag-sending { + opacity: 0.5; +} + +.drag-clone, +.drag-frame { + /* This allows mousewheel events to pass through the clone and frame while + they are being dragged. Without this, the mousewheel does not work during + a drag operation. */ + pointer-events: none; +} + +.drag-frame { + position: fixed; + overflow: hidden; + left: 0; + right: 0; + top: 0; + bottom: 0; +} + +.drag-clone { + position: absolute; + list-style: none; +} + +/* - Badges ---------------------------------------------------------------- */ + +.phui-oi-col0.phui-oi-badge { + width: 28px; +} + +.phui-oi-col0.phui-oi-badge .phui-icon-view { + left: 0; +} + +/* - Countdowns ------------------------------------------------------------ */ + +.phui-oi-col0.phui-oi-countdown { + width: 52px; + padding: 0; +} + +.phui-oi-countdown .phui-oi-countdown-number { + border-right: 1px solid {$thinblueborder}; + text-align: center; + color: {$bluetext}; +} + + +/* - Dashboards ------------------------------------------------------------ */ + +.phui-object-box .phui-oi-list-view .phui-oi-frame { + border: none; + border-bottom: 1px solid {$thinblueborder}; +} + +.drag-clone.phui-oi-standard .phui-oi-frame { + border: none; + opacity: 0.8; + background: {$sh-bluebackground}; +} + +.phui-object-box .phui-oi-list-header { + font-size: {$normalfontsize}; + color: {$darkbluetext}; + border-top: 1px solid {$thinblueborder}; + border-bottom: 1px solid {$thinblueborder}; + padding: 8px; + background-color: {$lightgreybackground}; +} + +.phui-object-box .phui-header-shell + .phui-oi-list-view .phui-oi-list-header, +.phui-object-box .phui-object-box-hidden-content + .phui-oi-list-view + .phui-oi-list-header, +.phui-object-box .phui-object-box-hidden-content + .phui-oi-list-header { + border-top: none; + } + +.dashboard-pane .phui-oi-empty .phui-info-view { + border: none; + margin: 0; +} + +.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up + .aphront-multi-column-column-outer.third .phui-oi-col2 { + display: none; + } + + +/* - Launcher List ---------------------------------------------------------- */ + +.phui-oi-image-icon { + background: none; + width: 40px; + height: 40px; + margin: 8px 6px; + position: absolute; +} + +.phui-oi-image-icon .phui-icon-view { + position: absolute; + width: 40px; + height: 40px; + font-size: 26px; + text-align: center; + line-height: 36px; +} + +.phui-oi-image { + width: 40px; + height: 40px; + border-radius: 3px; + background-size: 100%; + margin: 8px 6px; + position: absolute; +} + +.phui-oi-with-image-icon .phui-oi-frame, +.phui-oi-with-image .phui-oi-frame { + min-height: 52px; +} + +.phui-oi-with-image-icon .phui-oi-content-box, +.phui-oi-with-image .phui-oi-content-box { + margin-left: 46px; +} + +/* - Launcher Button -------------------------------------------------------- */ + +.phui-oi-col2.phui-oi-launch-button { + text-align: right; + vertical-align: middle; + padding-right: 4px; +} + +.device-phone .phui-oi-col2.phui-oi-launch-button { + padding: 0 8px 8px; + text-align: left; +} diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css new file mode 100644 index 0000000000..e838f1ce3e --- /dev/null +++ b/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css @@ -0,0 +1,43 @@ +/** + * @provides phui-oi-simple-ui-css + * @requires phui-oi-list-view-css + */ + +.phui-oi-list-simple .phui-oi-with-image .phui-oi-frame { + min-height: 26px; +} + +.phui-oi-list-simple .phui-oi-image { + height: 26px; + width: 26px; + margin: 0; +} + +.phui-oi-list-simple .phui-oi-with-image + .phui-oi-content-box { + margin-left: 32px; +} + +.phui-oi-list-simple .phui-oi-name { + padding: 2px 0; +} + +.phui-oi-list-simple .phui-oi-name a { + color: {$darkbluetext}; +} + +.phui-oi-list-view.phui-oi-list-simple .phui-oi-frame { + border: none; + margin-bottom: 4px; +} + +.phui-oi-list-view.phui-oi-list-simple li:last-child + .phui-oi-frame { + margin: 0; +} + +.phui-oi-list-simple .phui-oi-actions { + top: 2px; + bottom: 2px; + right: 2px; +} diff --git a/webroot/rsrc/css/phui/phui-box.css b/webroot/rsrc/css/phui/phui-box.css index 8d2acd0069..ef0816f826 100644 --- a/webroot/rsrc/css/phui/phui-box.css +++ b/webroot/rsrc/css/phui/phui-box.css @@ -1,116 +1,116 @@ /** * @provides phui-box-css */ .phui-box-border { border: 1px solid {$lightblueborder}; background-color: #fff; border-radius: 3px; } .phui-box.focus { box-shadow: 0 0 5px 5px rgba(255, 255, 0, 0.90); } .phui-box-grey { background-color: #F7F7F9; border-radius: 3px; border-color: rgba({$alphagrey},.2); } .phui-box-blue { background-color: {$bluebackground}; border-radius: 3px; border-color: {$thinblueborder}; } -.phui-box-blue .phui-object-item, -.phui-box-grey .phui-object-item { +.phui-box-blue .phui-oi, +.phui-box-grey .phui-oi { background: transparent; } -.phui-box-blue .phui-object-item-link, -.phui-box-grey .phui-object-item-link { +.phui-box-blue .phui-oi-link, +.phui-box-grey .phui-oi-link { color: {$darkbluetext}; } -.phui-box-blue .phui-object-item-list-view, -.phui-box-grey .phui-object-item-list-view { +.phui-box-blue .phui-oi-list-view, +.phui-box-grey .phui-oi-list-view { background-color: #fff; } .phui-box-blue .phui-header-shell { border-color: {$thinblueborder}; } .phui-box-grey .phui-header-shell { border-color: rgba({$alphagrey},.1); } .phui-object-box.phui-box-blue div.phui-info-severity-nodata, .phui-object-box.phui-box-grey div.phui-info-severity-nodata { background: transparent; padding: 20px 4px 24px; text-align: center; border: none; color: {$greytext}; } /* Property Boxes */ .phui-box.phui-box-blue-property { border-radius: 3px; border-color: {$lightblueborder}; margin: 0; padding: 0; } .phui-box.phui-box-blue-property .phui-header-header .phui-header-icon { margin-right: 6px; } .phui-box.phui-box-blue-property .phui-header-action-link { margin-top: 0; margin-bottom: 0; } .device .phui-box.phui-box-blue-property { padding: 0; } .phui-box.phui-object-box.phui-box-blue-property .phui-header-shell { background-color: #eff3fc; border-top-right-radius: 3px; border-top-left-radius: 3px; padding: 6px 16px; } body.device .phui-box.phui-box-blue-property .phui-header-shell, body.device .phui-box-blue-property.phui-object-box.phui-object-box-collapsed .phui-header-shell { padding: 6px 12px; margin-top: 0; } .phui-box.phui-box-blue-property .phui-header-header { font-size: {$biggerfontsize}; color: {$bluetext}; } -.phui-box-blue-property .phui-object-item-list-view { +.phui-box-blue-property .phui-oi-list-view { padding: 2px 8px; } body .phui-box-blue-property.phui-object-box.phui-object-box-collapsed { padding: 0; } body .phui-box-blue-property .phui-header-shell + .phui-object-box { margin-bottom: 0; } .phui-box-blue-property .phui-header-shell + .phui-object-box .phui-header-shell { background: #fff; } diff --git a/webroot/rsrc/css/phui/phui-button.css b/webroot/rsrc/css/phui/phui-button.css index 51807fa48e..15142d3b1a 100644 --- a/webroot/rsrc/css/phui/phui-button.css +++ b/webroot/rsrc/css/phui/phui-button.css @@ -1,404 +1,411 @@ /** * @provides phui-button-css */ button, a.button { font: {$basefont}; -webkit-font-smoothing: antialiased; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } button.phabricator-action-view-item { -webkit-font-smoothing: auto; } -button::-moz-focus-inner { - padding: 0; +button::-moz-focus-inner, +input::-moz-focus-inner { border: 0; + padding: 0; +} + +button:focus, +a.button:focus { + outline: 0; + box-shadow: 0 0 2pt 2pt rgba(82, 168, 236, 0.7); } button, a.button, a.button:visited, input[type="submit"] { background-color: #2980b9; border: 1px solid #2980b9; background-image: linear-gradient(to bottom, #3498db, #2980b9); color: white; cursor: pointer; font-weight: bold; font-size: {$normalfontsize}; display: inline-block; padding: 3px 12px 4px; text-align: center; white-space: nowrap; border-radius: 3px; } /* Buttons with images (full size only) */ button.icon, a.icon, a.icon:visited { padding-left: 0; position: relative; text-indent: 29px; } button.green, a.green, a.green:visited { background-color: {$green}; border-color: {$green}; background-image: linear-gradient(to bottom, #23BB5B, #139543); } button.grey, input[type="submit"].grey, a.grey, a.grey:visited { background-color: #F7F7F9; background-image: linear-gradient(to bottom, #ffffff, #f1f0f1); border: 1px solid rgba({$alphablue},.2); color: {$darkgreytext}; } button.simple, input[type="submit"].simple, a.simple, a.simple:visited { background: #fff; color: {$blue}; border: 1px solid {$blue}; } a.simple.current { background: {$lightblue}; } button.simple .phui-icon-view, input[type="submit"].simple .phui-icon-view, a.simple .phui-icon-view, a.simple:visited .phui-icon-view { color: {$blue}; } a.disabled, button.disabled, button[disabled] { filter:alpha(opacity=50); -moz-opacity: 0.5; -khtml-opacity: 0.5; opacity: 0.5; } a.phuix-dropdown-open { color: {$greytext}; } a.button:hover, button:hover { text-decoration: none; background-color: #2980b9; background-image: linear-gradient(to bottom, #3498db, #1b6ba0); border-color: #115988; transition: 0.1s; } a.button.grey:hover, button.grey:hover { background-image: linear-gradient(to bottom, #ffffff, #eeebec); border-color: rgba({$alphablue}, 0.3); transition: 0.1s; } a.button.green:hover, button.green:hover { border-color: #127336; background-color: #0DAD48; background-image: linear-gradient(to bottom, #23BB5B, #178841); transition: 0.1s; } a.button.simple:hover, button.simple:hover { background-color: {$blue}; background-image: linear-gradient(to bottom, {$blue}, {$blue}); color: #fff; transition: 0.1s; } a.button.simple:hover .phui-icon-view, button.simple:hover .phui-icon-view { color: #fff; transition: 0.1s; } a.button.simple .phui-icon-view { border: none; } a.button.simple.phuix-dropdown-open { background-color: #fff; color: {$blue}; box-shadow: none; } a.button.simple.phuix-dropdown-open:hover .phui-icon-view { color: {$blue}; } body a.button.disabled:hover, body button.disabled:hover, body a.button.disabled:active, body button.disabled:active { box-shadow: none; } button.small, a.small, a.small:visited { padding: 2px 8px; height: auto; font-size: {$smallestfontsize}; line-height: 16px; } button.link { display: inline; border: none; background: transparent; background-image: none; font-weight: normal; padding: 0; margin: 0; font-size: inherit; border-bottom: none; text-decoration: none; color: #19558D; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } button.link:hover { text-decoration: underline; } .phuix-dropdown-menu { position: absolute; width: 240px; background: #fff; margin-top: -1px; padding: 5px 0; box-shadow: {$dropshadow}; border: 1px solid {$blueborder}; border-radius: 3px; margin-bottom: 16px; } .phuix-dropdown-menu a:focus { /* We automatically focus links in dropdown menus for assistive devices, but this is distracting for visual user agents. */ outline: none; } a.policy-control { width: 240px; text-align: left; } a.policy-control .caret { float: right; } .caret { display: inline-block; width: 0; height: 0; vertical-align: top; border-top: 5px solid #fff; border-right: 5px solid transparent; border-left: 5px solid transparent; content: ""; } .caret-right { display: inline-block; width: 0; height: 0; vertical-align: middle; border-left: 7px solid {$greytext}; border-top: 5px solid transparent; border-bottom: 5px solid transparent; content: ""; margin-bottom: 4px; } .caret-left { display: inline-block; width: 0; height: 0; vertical-align: middle; border-right: 7px solid {$greytext}; border-bottom: 5px solid transparent; border-top: 5px solid transparent; content: ""; margin-bottom: 4px; } .dropdown .caret { margin-top: 7px; margin-left: 6px; } .small.dropdown .caret { margin-top: 6px; } .grey.dropdown .caret { border-top-color: #000; } .phabricator-action-view-submenu .caret-right { float: right; margin-top: 4px; margin-right: 6px; border-left-color: {$alphablue}; } .phabricator-action-view-submenu .caret { float: right; margin-top: 5px; margin-right: 4px; border-top: 7px solid {$lightgreytext}; } .phabricator-action-list-view .phabricator-action-view-submenu.phui-submenu-open .phabricator-action-view-item { background-color: rgba({$alphablue}, 0.07); color: {$sky}; border-radius: 3px; } .phabricator-action-list-view .phabricator-action-view-submenu.phui-submenu-open .phabricator-action-view-item .phui-icon-view { color: {$sky}; } /* Icons */ .button.has-icon { position: relative; } .button .phui-icon-view { display: inline-block; position: absolute; top: 6px; left: 10px; } .button.icon-last .phui-icon-view { left: auto; right: 10px; } .phui-button-bar .button .phui-icon-view { left: 9px; } .button.has-icon .phui-button-text { margin-left: 16px; } .button.has-icon.icon-last .phui-button-text { margin: 0 16px 0 0; } /* Login Buttons */ .button.big.has-icon { padding: 4px 20px 4px 14px; border-radius: 4px; text-align: left; } .button.big.has-icon .phui-button-text { margin-left: 30px; display: block; } .button.big.has-icon .phui-button-subtext { color: {$greytext}; font-size: {$smallerfontsize}; line-height: 15px; font-weight: normal; } /* PHUI Button Bar */ .phui-button-bar-borderless .button { border: 0; background-color: transparent; background-image: none; padding-left: 10px; padding-right: 10px; } .phui-button-bar-borderless .button .phui-icon-view { font-size: 15px; color: rgba({$alphagrey},.4); } .phui-button-bar-borderless .button:hover { background-color: transparent; background-image: none; border-radius: 3px; } .phui-button-bar-borderless .button:hover .phui-icon-view { color: rgba({$alphagrey},.9); } .phui-button-bar-borderless .button { border: 0; } .phui-button-bar a.button.has-icon { display: inline-block; height: 18px; width: 6px; } .phui-button-bar .phui-button-bar-first { border-top-right-radius: 0px; border-bottom-right-radius: 0px; } .phui-button-bar .phui-button-bar-middle { border-radius: 0; border-left: none; } .phui-button-bar .phui-button-bar-last { border-left: none; border-top-left-radius: 0px; border-bottom-left-radius: 0px; } .phui-button-bar .button.simple:hover { border-color: {$lightblueborder}; background-color: #fff; background-image: none; color: {$sky}; } .phui-button-bar .button.simple:hover .phui-icon-view { border-color: {$lightblueborder}; color: {$sky}; background-image: none; } diff --git a/webroot/rsrc/css/phui/phui-crumbs-view.css b/webroot/rsrc/css/phui/phui-crumbs-view.css index 3cf8013723..d2d0744819 100644 --- a/webroot/rsrc/css/phui/phui-crumbs-view.css +++ b/webroot/rsrc/css/phui/phui-crumbs-view.css @@ -1,132 +1,132 @@ /** * @provides phui-crumbs-view-css */ .phui-crumbs-view { overflow: hidden; vertical-align: top; padding: 0 12px 0 20px; /* TODO: Position this over the slider for Differential's file tree view. Remove this once that gets sorted out. */ position: relative; -webkit-font-smoothing: antialiased; background-color: {$page.background}; } .printable .phui-crumbs-view { display: none; } .phui-crumbs-view, .phui-crumbs-view a.phui-crumb-view, .phui-crumbs-view a.phui-crumbs-action { color: {$darkbluetext}; font-weight: bold; text-decoration: none; } .device-tablet .phui-crumbs-view, .device-phone .phui-crumbs-view, .project-board-nav .phui-crumbs-view { padding-left: 8px; padding-right: 8px; } .phui-crumbs-view a.phui-crumbs-action-disabled, .phui-crumbs-view a.phui-crumbs-action-disabled .phui-icon-view { color: {$lightgreytext}; } .phui-crumbs-view + .phui-header-shell { border-top: none; } .device-desktop .phui-crumbs-view a:hover { text-decoration: underline; } .phui-crumb-view { float: left; padding: 8px 0; } .device-phone .phui-crumb-view.phabricator-last-crumb .phui-crumb-name, .device-phone .phui-crumb-view.phui-crumb-has-icon, .device-phone .phui-crumb-has-icon + .phui-crumb-divider { display: inline-block; } .device-phone .phui-crumb-name, .device-phone .phui-crumb-divider { display: none; } .phui-crumb-has-icon .phui-icon-view { margin: 0 4px; } .device-phone .phui-crumb-icon { margin-left: 7px; } .phui-crumbs-actions { float: right; white-space: nowrap; } .phui-crumbs-action { display: inline-block; height: 17px; padding: 8px 12px; position: relative; } .device-phone a.phui-crumbs-action { padding: 8px 6px; } .device-desktop .phui-crumbs-view a:hover, .device-desktop .phui-crumbs-view a:hover .phui-icon-view { color: {$blue}; text-decoration: none; } .device-phone .phui-crumbs-action-name { display: none; } a.phui-crumbs-action .phui-icon-view { color: {$darkbluetext}; } a.phui-crumbs-action .phui-crumbs-action-name { margin-left: 6px; } .device-phone a.phui-crumbs-action .phui-icon-view { margin-left: 4px; } .phui-crumb-divider { margin: 2px 8px; } .phui-crumbs-view.phui-crumbs-border { border-bottom: 1px solid rgba({$alphagrey},.1); } body .phui-crumbs-view + .phui-object-box { margin-top: 0; } -body .phui-crumbs-view + .phui-object-item-list-view { +body .phui-crumbs-view + .phui-oi-list-view { padding-top: 0; } .phui-crumb-action-divider { border-left: 1px solid {$lightgreyborder}; } .phui-crumbs-action-icon + .phui-crumbs-action-icon { padding-left: 4px; } diff --git a/webroot/rsrc/css/phui/phui-object-item-list-view.css b/webroot/rsrc/css/phui/phui-object-item-list-view.css deleted file mode 100644 index 2f77102f42..0000000000 --- a/webroot/rsrc/css/phui/phui-object-item-list-view.css +++ /dev/null @@ -1,790 +0,0 @@ -/** - * @provides phui-object-item-list-view-css - */ - -ul.phui-object-item-list-view { - padding: 8px; - list-style: none; -} - -.device-desktop .phui-object-item-list-view { - padding: 16px; -} - -.phui-object-item-list-view + .phui-object-item-list-view { - padding-top: 0; -} - -.phui-object-item-list-view.phui-object-list-flush { - padding: 0; - margin: 0; -} - -.phui-object-box .phui-object-item-list-view .phui-object-item { - margin: 0; -} - -.phui-object-item-list-view .phui-info-view { - margin: 0; -} - -.phui-object-box .phui-object-item-list-view .phui-info-view { - color: {$greytext}; - border: none; -} - -.phui-object-item { - border-style: solid; - border-color: {$lightgreyborder}; - margin: 5px 0; - overflow: hidden; - background: #fff; - margin-bottom: 4px; -} - -.phui-object-item .phui-icon-view { - display: inline-block; -} - -.phui-object-item-frame { - border-color: {$lightblueborder}; - border-width: 1px 1px 1px 0; - border-style: solid; - position: relative; - min-height: 33px; - overflow: hidden; -} - -.phui-object-item-cover-image { - display: none; -} - -.phui-object-item-no-bar .phui-object-item-frame { - border-width: 1px; -} - -.device-desktop .phui-object-item { - margin: 0 0 4px 0; -} - -.phui-object-box .phui-object-list-flush .phui-object-item { - margin: 0; -} - -.phui-object-box .phui-object-item-list-view { - margin: 0; -} - -.phui-object-item-status-icon { - font-weight: bold; - padding: 3px; - font-size: 16px; -} - -.phui-object-item-list-view .phui-object-item-col0 .phui-icon-view { - width: 17px; - text-align: center; - overflow: visible; - position: relative; - left: -1px; -} - -.phui-object-item-name { - padding: 8px 8px 0; - white-space: nowrap; - word-wrap: break-word; - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; - -webkit-font-smoothing: antialiased; -} - -.device-phone .phui-object-item-name { - overflow: normal; - white-space: normal; - font-weight: bold; -} - -.phui-object-item-link { - display: inline; -} - -.phui-object-item-objname { - color: #000; - cursor: text; - font-weight: bold; -} - -.phui-object-item-content { - margin: 4px 8px 2px 0; - overflow: hidden; -} - -.phui-object-item-grippable { - cursor: move; -} - -.device .phui-object-item-grippable { - cursor: normal; -} - -.phui-object-item-grip { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 20px; - background: url('/rsrc/image/texture/grip.png') center center no-repeat; -} - -.device .phui-object-item-grip { - display: none; -} - -.phui-object-item-grippable .phui-object-item-frame { - padding-left: 16px; -} - -.device .phui-object-item-grippable .phui-object-item-frame { - padding-left: 0; -} - -.phui-object-item-list-header { - padding: 0 0 8px 0; - color: {$darkgreytext}; -} - -.phui-object-item-table { - display: table; - table-layout: fixed; - width: 100%; -} - -.phui-object-item-table-row { - display: table-row; -} - -.phui-object-item-col0 { - width: 20px; - display: table-cell; - vertical-align: middle; - padding-left: 4px; -} - -.device-phone .phui-object-item-col0 { - vertical-align: top; - padding-top: 8px; -} - -.phui-object-item-col1 { - display: table-cell; - vertical-align: top; -} - -.phui-object-item-col2 { - width: 160px; - display: table-cell; - vertical-align: top; -} - -.device-phone .phui-object-item-col1, -.device-phone .phui-object-item-col2 { - display: block; - width: auto; -} - -/* - Item Actions -------------------------------------------------------------- - - Action buttons, like "Edit" and "Delete". - -*/ - -.phui-object-item-actions { - position: absolute; - right: 4px; - top: 4px; - bottom: 4px; - vertical-align: middle; - text-align: right; -} - -.phui-object-item-actions .phui-list-item-view { - float: right; - height: 100%; - width: 24px; - display: inline-block; - position: relative; -} - -.phui-object-item-actions .phui-list-item-href { - display: inline-block; - position: relative; - width: 24px; - height: 100%; -} - -.device-desktop .phui-object-item-actions .phui-list-item-href:hover { - background: {$hoverblue}; - border-radius: 3px; -} - -.phui-object-item-actions .phui-list-item-icon { - width: 14px; - height: 14px; - position: absolute; - display: block; - top: 50%; - margin-top: -7px; - left: 3px; -} - -.phui-object-item-actions .phui-list-item-name { - display: none; -} - -.phui-object-item-with-1-actions .phui-object-item-content-box { - margin-right: 28px; - overflow: hidden; -} - -.phui-object-item-with-2-actions .phui-object-item-content-box { - margin-right: 54px; - overflow: hidden; -} - -.phui-object-item-with-3-actions .phui-object-item-content-box { - margin-right: 76px; - overflow: hidden; -} - - -/* - Object Box List ----------------------------------------------------------- - - Tighter, stacking list when inside an Object Box - -*/ - -.phui-object-box .phui-object-item-list-view { - padding: 0; - border: none; -} - -.phui-object-box .phui-object-item-frame { - border-right: none; -} - -.phui-object-box .phui-object-item:last-child - .phui-object-item-frame { - border-bottom: none; -} - - -/* - Subhead ------------------------------------------------------------------- - - Descriptive Text or Links under the main header, before attributes. - -*/ - -.phui-object-item-subhead { - color: {$greytext}; - padding: 0 8px 6px; -} - - -/* - Attribute List ------------------------------------------------------------ - - Object attributes, commonly used to render created date, etc. - -*/ - -.phui-object-item-attributes { - padding: 0 8px 6px; - line-height: 18px; - min-height: 21px; -} - -.phui-object-item-attribute { - display: inline-block; - color: {$greytext}; - vertical-align: top; -} - -.phui-object-item-attribute-spacer { - padding: 0 4px; -} - - -/* - Icons --------------------------------------------------------------------- - - Icons, which show object state. On mobile, they are rendered without labels - to save space. - -*/ - -.phui-object-icon-pane { - margin: 8px 0 4px; -} - -.device-phone .phui-object-icon-pane { - margin: 0 0 4px; -} - -.phui-object-item-icons { - padding: 0 4px 0 0; -} - -.device-phone .phui-object-item-icons { - padding: 0 0 0 8px; -} - -ul.phui-object-item-icons { - margin: 0; -} - -.phui-object-item-icon { - vertical-align: middle; - font-size: {$smallerfontsize}; - color: {$greytext}; - text-align: right; - white-space: nowrap; - overflow: hidden; - min-height: 18px; - line-height: 18px; -} - -.device-phone .phui-object-item-icon { - text-align: left; - font-size: 13px; -} - -/* - * Items with icon 'none' still have on mobile, thus creating a weird vertical - * margin for elements which follow - */ -.device-phone .phui-object-item-icon .none { - display: none; -} - -.phui-object-item-icon-image { - width: 14px; - height: 14px; - font-size: 13px; - margin-right: 4px; -} - -/* - Bar Colors ---------------------------------------------------------------- - Colors for the left-hand border bars, used to indicate object status or other - attributes. -*/ - -.phui-object-item { - border-left-width: 0; -} - -.phui-object-item-bar-color-red { - border-left-color: {$red}; -} - -.phui-object-item-bar-color-orange { - border-left-color: {$orange}; -} - -.phui-object-item-bar-color-yellow { - border-left-color: {$yellow}; -} - -.phui-object-item-bar-color-green { - border-left-color: {$green}; -} - -.phui-object-item-bar-color-sky { - border-left-color: {$sky}; -} - -.phui-object-item-bar-color-blue { - border-left-color: {$blue}; -} - -.phui-object-item-bar-color-indigo { - border-left-color: {$indigo}; -} - -.phui-object-item-bar-color-violet { - border-left-color: {$violet}; -} - -.phui-object-item-bar-color-pink { - border-left-color: {$pink}; -} - -.phui-object-item-bar-color-fire { - border-left-color: {$fire}; -} - -.phui-object-item-bar-color-bluegrey { - border-left-color: {$bluetext}; -} - -.phui-object-item-bar-color-lightbluetext { - border-left-color: {$lightbluetext}; -} - -.phui-object-item-bar-color-grey, -.phui-object-item-bar-color-lightgreytext { - border-left-color: {$lightgreytext}; -} - -.phui-object-item-bar-color-black, -.phui-object-item-bar-color-dark { - border-left-color: {$darkgreytext}; -} - - -/* - Disabled ------------------------------------------------------------------ - - Disabled/inactive objects. - -*/ - - -.phui-object-item.phui-object-item-disabled .phui-object-item-link, -.phui-object-item.phui-object-item-disabled .phui-object-item-link a { - color: {$lightgreytext}; -} - -.phui-object-item.phui-object-item-disabled .phui-object-item-frame { - border-color: #d7d7d7; -} - -.phui-object-item.phui-object-item-disabled .phui-object-item-objname { - color: {$greytext}; - text-decoration: line-through; -} - - -/* - Effects ------------------------------------------------------------------- - - Effects like highlighted items. - -*/ - -.phui-object-item.phui-object-item-highlighted { - background: {$sh-yellowbackground}; -} - -ul.phui-object-item-list-view .phui-object-item-highlighted - .phui-object-item-frame { - border-color: {$sh-yellowborder}; -} - -.phui-object-item-selected { - background: {$sh-bluebackground}; -} - -ul.phui-object-item-list-view .phui-object-item-selected - .phui-object-item-frame { - border-color: {$sh-blueborder}; -} - - -/* - Handle Icons -------------------------------------------------------------- - - Shows owners, reviewers, etc., using profile picture icons. - -*/ - -.phui-object-item-handle-icons { - bottom: 0; - right: 4px; - position: absolute; -} - -.phui-object-item-handle-icon { - width: 24px; - height: 24px; - display: inline-block; - background-size: 100%; - border-radius: 3px; - background-repeat: no-repeat; -} - - -/* - Bylines ------------------------------------------------------------------- - - Shows owners, authors, reviewers, etc., in text. - -*/ - -.phui-object-item-bylines { - padding: 0 4px 0 8px; - margin: 4px 0 8px; - font-size: {$smallerfontsize}; - color: {$greytext}; - text-align: right; -} - -.phui-object-item-byline { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.device-phone .phui-object-item-bylines { - float: none; - text-align: left; - padding: 0 8px; - font-size: {$normalfontsize}; -} - - -/* - Draggable List ------------------------------------------------------------ - - These classes are applied by and/or provided for use with JX.DraggableList. - -*/ - -.drag-ghost { - position: relative; - background: {$sh-indigobackground}; - border-radius: 3px; - margin-bottom: 4px; - border: 1px dashed {$sh-indigoborder}; -} - -.drag-dragging { - opacity: 0.25; -} - -.drag-sending { - opacity: 0.5; -} - -.drag-clone, -.drag-frame { - /* This allows mousewheel events to pass through the clone and frame while - they are being dragged. Without this, the mousewheel does not work during - a drag operation. */ - pointer-events: none; -} - -.drag-frame { - position: fixed; - overflow: hidden; - left: 0; - right: 0; - top: 0; - bottom: 0; -} - -.drag-clone { - position: absolute; - list-style: none; -} - -/* - Badges ---------------------------------------------------------------- */ - -.phui-object-item-col0.phui-object-item-badge { - width: 28px; -} - -.phui-object-item-col0.phui-object-item-badge .phui-icon-view { - left: 0; -} - -/* - Countdowns ------------------------------------------------------------ */ - -.phui-object-item-col0.phui-object-item-countdown { - width: 52px; - padding: 0; -} - -.phui-object-item-countdown .phui-object-item-countdown-number { - border-right: 1px solid {$thinblueborder}; - text-align: center; - color: {$bluetext}; -} - - -/* - Dashboards ------------------------------------------------------------ */ - -.phui-object-box .phui-object-item-list-view .phui-object-item-frame { - border: none; - border-bottom: 1px solid {$thinblueborder}; -} - -.drag-clone.phui-object-item-standard .phui-object-item-frame { - border: none; - opacity: 0.8; - background: {$sh-bluebackground}; -} - -.phui-object-box .phui-object-item-list-header { - font-size: {$normalfontsize}; - color: {$darkbluetext}; - border-top: 1px solid {$thinblueborder}; - border-bottom: 1px solid {$thinblueborder}; - padding: 8px; - background-color: {$lightgreybackground}; -} - -.phui-object-box .phui-header-shell + .phui-object-item-list-view - .phui-object-item-list-header, -.phui-object-box .phui-object-box-hidden-content + .phui-object-item-list-view - .phui-object-item-list-header, -.phui-object-box .phui-object-box-hidden-content + - .phui-object-item-list-header { - border-top: none; - } - -.dashboard-pane .phui-object-item-empty .phui-info-view { - border: none; - margin: 0; -} - -.device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up - .aphront-multi-column-column-outer.third .phui-object-item-col2 { - display: none; - } - - -/* - Launcher List ---------------------------------------------------------- */ - -.phui-object-item-image-icon { - background: none; - width: 40px; - height: 40px; - margin: 8px 6px; - position: absolute; -} - -.phui-object-item-image-icon .phui-icon-view { - position: absolute; - width: 40px; - height: 40px; - font-size: 26px; - text-align: center; - line-height: 36px; -} - -.phui-object-item-image { - width: 40px; - height: 40px; - border-radius: 3px; - background-size: 100%; - margin: 8px 6px; - position: absolute; -} - -.phui-object-item-with-image-icon .phui-object-item-frame, -.phui-object-item-with-image .phui-object-item-frame { - min-height: 52px; -} - -.phui-object-item-with-image-icon .phui-object-item-content-box, -.phui-object-item-with-image .phui-object-item-content-box { - margin-left: 46px; -} - -/* - Launcher Button -------------------------------------------------------- */ - -.phui-object-item-col2.phui-object-item-launch-button { - text-align: right; - vertical-align: middle; - padding-right: 4px; -} - -.device-phone .phui-object-item-col2.phui-object-item-launch-button { - padding: 0 8px 8px; - text-align: left; -} - -/* - Simple List------------------------------------------------------------- */ - -.phui-object-list-simple .phui-object-item-with-image .phui-object-item-frame { - min-height: 26px; -} - -.phui-object-list-simple .phui-object-item-image { - height: 26px; - width: 26px; - margin: 0; -} - -.phui-object-list-simple .phui-object-item-with-image - .phui-object-item-content-box { - margin-left: 32px; -} - -.phui-object-list-simple .phui-object-item-name { - padding: 2px 0; -} - -.phui-object-list-simple .phui-object-item-name a { - color: {$darkbluetext}; -} - -.phui-object-item-list-view.phui-object-list-simple .phui-object-item-frame { - border: none; - margin-bottom: 4px; -} - -.phui-object-item-list-view.phui-object-list-simple li:last-child - .phui-object-item-frame { - margin: 0; -} - -.phui-object-list-simple .phui-object-item-actions { - top: 2px; - bottom: 2px; - right: 2px; -} - -/* - Big List---------------------------------------------------------------- */ - -.phui-object-list-big ul.phui-object-item-list-view { - margin: 0; - padding: 20px; -} - -.phui-object-list-big .phui-object-item-no-bar .phui-object-item-frame { - border: 0; -} - -.phui-object-list-big .phui-object-item-image-icon { - margin: 8px 2px 12px; -} - -.phui-object-list-big a.phui-object-item-link { - color: #000; - font-size: {$biggestfontsize}; -} - -.phui-object-list-big .phui-object-item-name { - padding-top: 6px; -} - -.phui-object-list-big .phui-object-item-launch-button a.button { - font-size: {$normalfontsize}; - padding: 3px 12px 4px; -} - -.device-desktop .phui-object-list-big .phui-object-item { - margin-bottom: 8px; -} - -.phui-object-list-big .phui-object-item-col0 { - vertical-align: top; - padding: 0; -} - -.phui-object-list-big .phui-object-item-status-icon { - padding: 5px; -} - -.phui-object-list-big .phui-object-item-visited a.phui-object-item-link { - color: {$violet}; -} - -.device-desktop .phui-object-list-big .phui-object-item-frame:hover { - -} diff --git a/webroot/rsrc/css/phui/phui-tag-view.css b/webroot/rsrc/css/phui/phui-tag-view.css index 729c4719e5..f14909bc06 100644 --- a/webroot/rsrc/css/phui/phui-tag-view.css +++ b/webroot/rsrc/css/phui/phui-tag-view.css @@ -1,417 +1,417 @@ /** * @provides phui-tag-view-css */ .phui-tag-view { font-weight: bold; text-decoration: none; position: relative; -webkit-font-smoothing: antialiased; white-space: nowrap; } a.phui-tag-view:hover { text-decoration: none; } .phui-tag-core-closed { text-decoration: line-through; color: rgba({$alphablack},0.5); } .phui-tag-core-closed:hover { text-decoration: none; } .phui-tag-core { color: inherit; border: 1px solid transparent; border-radius: 3px; padding: 0 4px; } .phui-tag-type-state .phui-tag-core { padding: 1px 6px; } .phui-tag-view.phui-tag-type-state .phui-icon-view { margin: 0 6px 0 0; } .phui-tag-view .phui-icon-view { display: inline-block; margin: 0 4px 0 2px; } .phui-tag-dot { position: relative; display: inline-block; width: 6px; height: 6px; margin-right: 4px; top: -1px; border-radius: 6px; border: 1px solid transparent; } .phui-tag-type-state { color: #ffffff; text-shadow: rgba(100, 100, 100, 0.40) 0px -1px 1px; } .phui-tag-type-object, a.phui-tag-type-object, a.phui-tag-type-object:link, .phui-tag-core-closed .phui-tag-color-object { color: #000; } .phui-tag-type-person { white-space: nowrap; color: #19558d; } .phui-tag-color-red { background-color: {$red}; border-color: {$red}; } .phui-tag-color-orange { background-color: {$orange}; border-color: {$orange}; } .phui-tag-color-yellow { background-color: {$yellow}; border-color: {$yellow}; } .phui-tag-color-blue { background-color: {$blue}; border-color: {$blue}; } .phui-tag-color-indigo { background-color: {$indigo}; border-color: {$indigo}; } .phui-tag-color-green { background-color: {$green}; border-color: {$green}; } .phui-tag-color-violet { background-color: {$violet}; border-color: {$violet}; } .phui-tag-color-black { background-color: #333333; border-color: #333333; } .phui-tag-color-grey { background-color: {$lightgreytext}; border-color: {$lightgreytext}; } .phui-tag-color-white { background-color: #f7f7f7; border-color: #f7f7f7; } .phui-tag-color-object { background-color: #e7e7e7; border-color: #e7e7e7; } .phui-tag-color-person { background-color: #f1f7ff; border-color: #f1f7ff; } a.phui-tag-view:hover .phui-tag-core.phui-tag-color-person { border-color: #d9ebfd; } a.phui-tag-view:hover .phui-tag-core.phui-tag-color-object { border-color: #d7d7d7; } .phabricator-handle-tag-list-item + .phabricator-handle-tag-list-item { margin-top: 4px; } -.phui-object-item .phabricator-handle-tag-list { +.phui-oi .phabricator-handle-tag-list { display: inline; } -.phui-object-item .phabricator-handle-tag-list-item { +.phui-oi .phabricator-handle-tag-list-item { display: inline-block; margin: 0 4px 2px 0; } /* - Shaded Tags --------------------------------------------------------------- For object representation inside text areas and lists. */ .phui-tag-shade { font-weight: normal; } .phui-tag-shade .phui-icon-view { font-size: 12px; } .phui-tag-shade-slim .phui-icon-view { font-size: 11px; } .phui-tag-shade-slim .phui-tag-core { font-size: {$smallerfontsize}; } /* - Red -------------------------------------------------------------------- */ .phui-tag-shade-red .phui-tag-core, .jx-tokenizer-token.red { background: {$sh-redbackground}; border-color: {$sh-lightredborder}; color: {$sh-redtext}; } .phui-tag-shade-red .phui-icon-view, .jx-tokenizer-token.red .phui-icon-view, .jx-tokenizer-token.red .jx-tokenizer-x { color: {$sh-redicon}; } a.phui-tag-view:hover.phui-tag-shade-red .phui-tag-core, .jx-tokenizer-token.red:hover { border-color: {$sh-redborder}; } /* - Orange ----------------------------------------------------------------- */ .phui-tag-shade-orange .phui-tag-core, .jx-tokenizer-token.orange { background: {$sh-orangebackground}; border-color: {$sh-lightorangeborder}; color: {$sh-orangetext}; } .phui-tag-shade-orange .phui-icon-view, .jx-tokenizer-token.orange .phui-icon-view, .jx-tokenizer-token.orange .jx-tokenizer-x { color: {$sh-orangeicon}; } a.phui-tag-view:hover.phui-tag-shade-orange .phui-tag-core, .jx-tokenizer-token.orange:hover { border-color: {$sh-orangeborder}; } /* - Yellow ----------------------------------------------------------------- */ .phui-tag-shade-yellow .phui-tag-core, .jx-tokenizer-token.yellow { background: {$sh-yellowbackground}; border-color: {$sh-lightyellowborder}; color: {$sh-yellowtext}; } .phui-tag-shade-yellow .phui-icon-view, .jx-tokenizer-token.yellow .phui-icon-view, .jx-tokenizer-token.yellow .jx-tokenizer-x { color: {$sh-yellowicon}; } a.phui-tag-view:hover.phui-tag-shade-yellow .phui-tag-core, .jx-tokenizer-token.yellow:hover { border-color: {$sh-yellowborder}; } /* - Blue ------------------------------------------------------------------- */ .phui-tag-shade-blue .phui-tag-core, .jx-tokenizer-token.blue { background: {$sh-bluebackground}; border-color: {$sh-lightblueborder}; color: {$sh-bluetext}; } .phui-tag-shade-blue .phui-icon-view, .jx-tokenizer-token.blue .phui-icon-view, .jx-tokenizer-token.blue .jx-tokenizer-x { color: {$sh-blueicon}; } a.phui-tag-view:hover.phui-tag-shade-blue .phui-tag-core, .jx-tokenizer-token.blue:hover { border-color: {$sh-blueborder}; } /* - Sky ------------------------------------------------------------------- */ .phui-tag-shade-sky .phui-tag-core, .jx-tokenizer-token.sky { background: #E0F0FA; border-color: {$sh-lightblueborder}; color: {$sh-bluetext}; } .phui-tag-shade-sky .phui-icon-view, .jx-tokenizer-token.sky .phui-icon-view, .jx-tokenizer-token.sky .jx-tokenizer-x { color: {$sh-blueicon}; } a.phui-tag-view:hover.phui-tag-shade-sky .phui-tag-core, .jx-tokenizer-token.sky:hover { border-color: {$sh-blueborder}; } /* - Indigo ----------------------------------------------------------------- */ .phui-tag-shade-indigo .phui-tag-core, .jx-tokenizer-token.indigo { background: {$sh-indigobackground}; border-color: {$sh-lightindigoborder}; color: {$sh-indigotext}; } .phui-tag-shade-indigo .phui-icon-view, .jx-tokenizer-token.indigo .phui-icon-view, .jx-tokenizer-token.indigo .jx-tokenizer-x { color: {$sh-indigoicon}; } a.phui-tag-view:hover.phui-tag-shade-indigo .phui-tag-core, .jx-tokenizer-token.indigo:hover { border-color: {$sh-indigoborder}; } /* - Green ------------------------------------------------------------------ */ .phui-tag-shade-green .phui-tag-core, .jx-tokenizer-token.green { background: {$sh-greenbackground}; border-color: {$sh-lightgreenborder}; color: {$sh-greentext}; } .phui-tag-shade-green .phui-icon-view, .jx-tokenizer-token.green .phui-icon-view, .jx-tokenizer-token.green .jx-tokenizer-x { color: {$sh-greenicon}; } a.phui-tag-view:hover.phui-tag-shade-green .phui-tag-core, .jx-tokenizer-token.green:hover { border-color: {$sh-greenborder}; } /* - Violet ----------------------------------------------------------------- */ .phui-tag-shade-violet .phui-tag-core, .jx-tokenizer-token.violet { background: {$sh-violetbackground}; border-color: {$sh-lightvioletborder}; color: {$sh-violettext}; } .phui-tag-shade-violet .phui-icon-view, .jx-tokenizer-token.violet .phui-icon-view, .jx-tokenizer-token.violet .jx-tokenizer-x { color: {$sh-violeticon}; } a.phui-tag-view:hover.phui-tag-shade-violet .phui-tag-core, .jx-tokenizer-token.violet:hover { border-color: {$sh-violetborder}; } /* - Pink ------------------------------------------------------------------- */ .phui-tag-shade-pink .phui-tag-core, .jx-tokenizer-token.pink { background: {$sh-pinkbackground}; border-color: {$sh-lightpinkborder}; color: {$sh-pinktext}; } .phui-tag-shade-pink .phui-icon-view, .jx-tokenizer-token.pink .phui-icon-view, .jx-tokenizer-token.pink .jx-tokenizer-x { color: {$sh-pinkicon}; } a.phui-tag-view:hover.phui-tag-shade-pink .phui-tag-core, .jx-tokenizer-token.pink:hover { border-color: {$sh-pinkborder}; } /* - Grey ------------------------------------------------------------------- */ .phui-tag-shade-grey .phui-tag-core, .jx-tokenizer-token.grey { background: {$sh-greybackground}; border-color: {$sh-lightgreyborder}; color: {$sh-greytext}; } .phui-tag-shade-grey .phui-icon-view, .jx-tokenizer-token.grey .phui-icon-view, .jx-tokenizer-token.grey .jx-tokenizer-x { color: {$sh-greyicon}; } a.phui-tag-view:hover.phui-tag-shade-grey .phui-tag-core, .jx-tokenizer-token.grey:hover { border-color: {$sh-greyborder}; } /* - Checkered -------------------------------------------------------------- */ .phui-tag-shade-checkered .phui-tag-core, .jx-tokenizer-token.checkered { background: url(/rsrc/image/checker_lighter.png); border-style: dashed; border-color: {$sh-greyborder}; color: {$sh-greytext}; text-shadow: 1px 1px #fff; } .phui-tag-shade-checkered .phui-icon-view, .jx-tokenizer-token.checkered .phui-icon-view, .jx-tokenizer-token.checkered .jx-tokenizer-x { color: {$sh-greyicon}; } a.phui-tag-view:hover.phui-tag-shade-checkered .phui-tag-core, .jx-tokenizer-token.checkered:hover { border-style: solid; border-color: {$sh-greyborder}; } /* - Disabled --------------------------------------------------------------- */ .phui-tag-shade-disabled .phui-tag-core { background-color: {$sh-disabledbackground}; border-color: {$sh-lightdisabledborder}; color: {$sh-disabledtext}; } .phui-tag-shade-disabled .phui-icon-view { color: {$sh-disabledicon}; } a.phui-tag-view:hover.phui-tag-shade-disabled .phui-tag-core { border-color: {$sh-disabledborder}; } diff --git a/webroot/rsrc/css/phui/phui-two-column-view.css b/webroot/rsrc/css/phui/phui-two-column-view.css index aea567d025..0020df8b84 100644 --- a/webroot/rsrc/css/phui/phui-two-column-view.css +++ b/webroot/rsrc/css/phui/phui-two-column-view.css @@ -1,235 +1,235 @@ /** * @provides phui-two-column-view-css */ .phui-two-column-view .phui-two-column-header { background-color: #fff; border-bottom: 1px solid rgba({$alphagrey}, .12); margin-bottom: 24px; } .device .phui-two-column-view .phui-two-column-header { margin-bottom: 12px; } .phui-two-column-view.with-subheader .phui-two-column-header { margin-bottom: 0; } .phui-two-column-header .phui-header-header { font-size: 20px; font-family: 'Aleo', {$fontfamily}; color: #000; } .device-phone .phui-two-column-header .phui-header-header { font-size: 16px; } .phui-two-column-view .phui-two-column-header .phui-header-shell { padding: 24px 32px 28px; border: none; } .phui-two-column-view .phui-two-column-header .phui-profile-header.phui-header-shell { padding-bottom: 20px; } .device .phui-two-column-view .phui-two-column-header .phui-header-shell { padding: 12px 12px 16px; } .phui-two-column-header .phui-header-subheader { margin-top: 12px; } .phui-two-column-subheader { padding: 12px 32px; } .device .phui-two-column-subheader { padding: 12px 16px; } .device-desktop .phui-two-column-content { padding: 0 32px; } .device .phui-two-column-content { padding: 0 12px; } .device-desktop .phui-two-column-view .phui-main-column { float: left; width: calc(100% - 320px); } .device-desktop .phui-two-column-view .phui-side-column { float: right; width: 300px; } .device-desktop .phui-two-column-view.phui-side-column-left .phui-main-column { float: right; width: calc(100% - 280px); } .device-desktop .phui-two-column-view.phui-side-column-left .phui-side-column { float: left; width: 260px; } .device .phui-side-column { margin-bottom: 20px; } .phui-two-column-view .phui-two-column-content .phui-object-box { margin: 0 0 20px 0; } /* Timeline */ .phui-two-column-view .phui-timeline-view { padding: 0; background-position: 80px; } .phui-two-column-view .phui-main-column .phui-object-box + .phui-timeline-view { margin-top: -20px; } .device .phui-two-column-view .phui-timeline-view { background-position: 16px; padding: 0; } .device-phone .phui-two-column-view .phui-timeline-event-view { margin: 0; } .phui-main-column > .phui-timeline-view:first-child { border-top: 1px solid {$thinblueborder}; } .device-phone .phui-main-column .phui-timeline-older-transactions-are-hidden { margin: 0; } /* Main Column Properties */ .device-desktop .phui-main-column .phui-property-list-key { margin-left: 0; width: 160px; } .device-desktop .phui-main-column .phui-property-list-value { margin-left: 8px; width: calc(100% - 200px); } /* Property / Action List */ .phui-two-column-properties .phabricator-action-list-view { padding-top: 4px; padding-bottom: 12px; } .device-desktop .phui-two-column-view .phui-property-list-container { padding: 16px 0; } .device-desktop .phui-two-column-view .phui-property-list-properties-wrap.phui-property-list-stacked { padding: 0 16px; } .device .phui-two-column-view .phui-property-list-container { padding: 12px 8px; } .phui-two-column-view .phui-property-list-container .keyboard-shortcuts-available { display: none; } .device .phui-two-column-content .phui-two-column-properties.phui-object-box { padding: 0 12px; } .phabricator-action-view button.phabricator-action-view-item, .phabricator-action-view-item { padding: 5px 4px 5px 28px; } -.device-desktop .phui-two-column-properties .phabricator-action-view:hover +.device-desktop .phui-two-column-properties .phabricator-action-view-href:hover .phabricator-action-view-item { text-decoration: none; background-color: rgba({$alphablue}, .08); color: {$sky}; border-radius: 3px; } -.device-desktop .phui-two-column-properties .phabricator-action-view:hover +.device-desktop .phui-two-column-properties .phabricator-action-view-href:hover .phabricator-action-view-icon { color: {$sky}; } .phui-two-column-view .phui-property-list-section-header, .phui-two-column-view .phui-property-list-text-content { margin: 0 16px; } .device .phui-two-column-view .phui-property-list-section-header, .device .phui-two-column-view .phui-property-list-text-content { margin: 0 8px; } /* Info View */ .phui-two-column-view .phui-info-view { margin: 0 0 20px 0; padding: 16px; } .device .phui-two-column-view .phui-info-view { margin: 0 0 20px 0; padding: 12px; } -.phui-two-column-view .phui-side-column .phui-object-item-empty +.phui-two-column-view .phui-side-column .phui-oi-empty .phui-info-view { margin-bottom: 0; } .phui-two-column-view .phui-box-blue-property .phui-header-shell + .phui-info-view { margin: 16px; } .device .phui-two-column-view .phui-box-blue-property .phui-header-shell + .phui-info-view { margin: 8px; } /* Navigation */ .phui-two-column-view .side-has-nav .phabricator-nav-local { width: auto; position: static; margin: 0; } .device .phui-two-column-view .side-has-nav { display: none; } /* Document View */ .phui-two-column-view .phui-two-column-content .phui-document-fluid .phui-document-view { margin: 0 0 20px 0; } diff --git a/webroot/rsrc/css/phui/workboards/phui-workcard.css b/webroot/rsrc/css/phui/workboards/phui-workcard.css index 64792c6915..5af162b4bc 100644 --- a/webroot/rsrc/css/phui/workboards/phui-workcard.css +++ b/webroot/rsrc/css/phui/workboards/phui-workcard.css @@ -1,176 +1,176 @@ /** * @provides phui-workcard-view-css */ -.phui-workcard.phui-object-item { +.phui-workcard.phui-oi { background-color: #fff; border-radius: 3px; margin-bottom: 8px; border-left-width: 4px; box-sizing: border-box; } -.phui-workcard .phui-object-item-name { +.phui-workcard .phui-oi-name { padding-bottom: 4px; } -.phui-workcard .phui-object-item-content { +.phui-workcard .phui-oi-content { margin-top: 0; } -.phui-workcard .phui-object-item-frame { +.phui-workcard .phui-oi-frame { border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-color: {$thinblueborder}; border-bottom-color: {$lightblueborder}; } -.phui-workcard.phui-object-item .phui-object-item-objname { +.phui-workcard.phui-oi .phui-oi-objname { -webkit-touch-callout: text; -webkit-user-select: text; -khtml-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; } -.phui-workcard .phui-object-item-link { +.phui-workcard .phui-oi-link { white-space: normal; font-weight: normal; color: #000; margin-left: 2px; } -.phui-object-item-disabled.phui-workcard { +.phui-oi-disabled.phui-workcard { background-color: rgba({$alphawhite},.67); } -.phui-object-item-disabled.phui-workcard .phui-object-item-link { +.phui-oi-disabled.phui-workcard .phui-oi-link { color: {$greytext}; } -.device-desktop .phui-workcard .phui-object-item-with-1-actions - .phui-object-item-content-box { +.device-desktop .phui-workcard .phui-oi-with-1-actions + .phui-oi-content-box { margin-right: 0; overflow: hidden; } -.phui-workcard .phui-object-item-objname { +.phui-workcard .phui-oi-objname { vertical-align: top; } -.phui-workcard.phui-object-item-grippable .phui-object-item-frame { +.phui-workcard.phui-oi-grippable .phui-oi-frame { padding-left: 0; } -.phui-workcard .phui-object-item-grip { +.phui-workcard .phui-oi-grip { display: none; } .device-desktop .phui-workcard .phui-list-item-icon { display: none; } -.phui-workcard.phui-object-item .phui-list-item-href { +.phui-workcard.phui-oi .phui-list-item-href { height: 24px; width: 24px; } -.device-desktop .phui-workcard.phui-object-item:hover +.device-desktop .phui-workcard.phui-oi:hover .phui-list-item-href { background: #fff; opacity: .7; } -.device-desktop .phui-workcard.phui-object-item +.device-desktop .phui-workcard.phui-oi .phui-list-item-href:hover { background: {$sh-bluebackground}; opacity: 1; } -.phui-workcard.phui-object-item:hover .phui-list-item-icon { +.phui-workcard.phui-oi:hover .phui-list-item-icon { display: block; } -.phui-workcard .phui-object-item-attributes { +.phui-workcard .phui-oi-attributes { margin-right: 12px; } .phui-workpanel-view .drag-ghost { margin-bottom: 8px; } -.phui-workcard .phui-object-item-cover-image { +.phui-workcard .phui-oi-cover-image { display: block; padding: 8px 8px 0 8px; width: 263px; } -.phui-workcard.phui-object-item.phui-workcard-upload-target { +.phui-workcard.phui-oi.phui-workcard-upload-target { background-color: {$sh-greenbackground}; } -.phui-object-item-list-view .phui-workcard:last-child { +.phui-oi-list-view .phui-workcard:last-child { margin-bottom: 0; } -.phui-workcard .phui-object-item-attribute-spacer { +.phui-workcard .phui-oi-attribute-spacer { display: none; } .phui-workcard .phui-workcard-points { margin: 0 4px 2px 0; display: inline-block; } -.phui-workcard .phui-object-item-attribute { +.phui-workcard .phui-oi-attribute { display: inline; } /* - Draggable Colors --------------------------------------------------------*/ -.phui-workcard.phui-object-item.drag-clone { +.phui-workcard.phui-oi.drag-clone { box-shadow: {$dropshadow}; background-color: {$sh-greybackground}; } -.phui-workcard.phui-object-item.drag-clone .phui-list-item-href { +.phui-workcard.phui-oi.drag-clone .phui-list-item-href { display: none; } -.phui-workcard.drag-clone.phui-object-item-bar-color-red { +.phui-workcard.drag-clone.phui-oi-bar-color-red { background-color: {$sh-redbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-orange { +.phui-workcard.drag-clone.phui-oi-bar-color-orange { background-color: {$sh-orangebackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-yellow { +.phui-workcard.drag-clone.phui-oi-bar-color-yellow { background-color: {$sh-yellowbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-green { +.phui-workcard.drag-clone.phui-oi-bar-color-green { background-color: {$sh-greenbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-blue { +.phui-workcard.drag-clone.phui-oi-bar-color-blue { background-color: {$sh-bluebackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-indigo { +.phui-workcard.drag-clone.phui-oi-bar-color-indigo { background-color: {$sh-indigobackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-violet { +.phui-workcard.drag-clone.phui-oi-bar-color-violet { background-color: {$sh-violetbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-pink { +.phui-workcard.drag-clone.phui-oi-bar-color-pink { background-color: {$sh-pinkbackground}; } -.phui-workcard.drag-clone.phui-object-item-bar-color-sky { +.phui-workcard.drag-clone.phui-oi-bar-color-sky { background-color: {$sh-bluebackground}; } diff --git a/webroot/rsrc/css/phui/workboards/phui-workpanel.css b/webroot/rsrc/css/phui/workboards/phui-workpanel.css index 899c6f74eb..617ff5aa6d 100644 --- a/webroot/rsrc/css/phui/workboards/phui-workpanel.css +++ b/webroot/rsrc/css/phui/workboards/phui-workpanel.css @@ -1,139 +1,139 @@ /** * @provides phui-workpanel-view-css * @requires phui-workcard-view-css */ .phui-workpanel-view .phui-header-shell { padding: 8px; width: 284px; } .phui-workpanel-view .phui-header-shell .phui-header-header { font-size: {$biggerfontsize}; line-height: 18px; color: {$darkbluetext}; } .phui-workpanel-view .phui-header-shell .phui-header-subheader { padding: 0 4px; margin: 0; display: inline-block; color: {$lightgreytext}; font-size: {$normalfontsize}; } .device .phui-workpanel-view .phui-header-shell { width: auto; } .phui-workboard-view { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .phui-workpanel-view .phui-box-grey { background-color: rgba({$alphablue},0.1); } .phui-workpanel-view.phui-workboard-column-milestone .phui-box-grey { background-color: rgba(234, 230, 247, 0.85); } .phui-workpanel-view .phui-header-col2 .phui-icon-view { margin-right: 4px; } .phui-workpanel-view .phui-workpanel-header-action { float: right; width: 24px; } .phui-workpanel-view .phui-workpanel-body { padding: 8px 4px 8px 0; } .phui-workpanel-view .phui-workpanel-body-content { padding: 0 4px 0 8px; } .device .phui-workpanel-view .phui-workpanel-body { padding: 8px 0; } .phui-workpanel-view .phui-workpanel-footer-action a { color: {$darkbluetext}; font-weight: bold; } .device-desktop .phui-workpanel-view .phui-workpanel-footer-action:hover { background-color: rgba(100,100,100,.1); border-radius: 3px; } .device-desktop .aphront-multi-column-fixed .phui-workpanel-view { width: 300px; } .device-phone .aphront-multi-column-fixed .phui-workpanel-view, .device-phone .phui-workpanel-view .phui-header-shell { width: auto; } -.phui-workpanel-body .phui-object-item-list-view { +.phui-workpanel-body .phui-oi-list-view { min-height: 54px; background-color: transparent; } .device .aphront-multi-column-outer div.aphront-multi-column-column-outer .phui-workpanel-body { width: auto; } .project-panel-hidden { opacity: 0.75; } .device-desktop .phui-workpanel-body-content { max-height: calc(100vh - 162px); overflow-y: auto; overflow-x: hidden; } .device-desktop .phui-workpanel-body-content::-webkit-scrollbar { height: 8px; width: 8px; background: rgba({$alphablue},0.2); border-radius: 4px; } .device-desktop .phui-workpanel-body-content::-webkit-scrollbar-thumb { background: rgba({$alphablue},0.4); border-radius: 4px; } -.project-panel-empty .phui-object-item-list-view { +.project-panel-empty .phui-oi-list-view { background: rgba(234, 230, 247, 0.85); border-radius: 3px; margin-bottom: 4px; border: 1px dashed {$sh-indigoborder}; } -.project-panel-empty .phui-object-item-list-view .drag-ghost { +.project-panel-empty .phui-oi-list-view .drag-ghost { display: none; } -.project-panel-empty .phui-object-item-list-view.drag-target-list { +.project-panel-empty .phui-oi-list-view.drag-target-list { background: rgba({$alphawhite},.7); } .phui-workpanel-view.project-panel-over-limit .phui-header-header { color: {$red}; } .phui-workpanel-view.project-panel-over-limit .phui-header-shell { border-color: {$red}; } diff --git a/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js b/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js index 30a557e268..b7728abb57 100644 --- a/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js +++ b/webroot/rsrc/js/application/maniphest/behavior-batch-selector.js @@ -1,170 +1,170 @@ /** * @provides javelin-behavior-maniphest-batch-selector * @requires javelin-behavior * javelin-dom * javelin-stratcom * javelin-util */ JX.behavior('maniphest-batch-selector', function(config) { var selected = {}; // Test if a task node is selected. var get_id = function(task) { return JX.Stratcom.getData(task).taskID; }; var is_selected = function(task) { return (get_id(task) in selected); }; // Change the selected state of a task. var change = function(task, to) { if (to === undefined) { to = !is_selected(task); } if (to) { selected[get_id(task)] = true; } else { delete selected[get_id(task)]; } JX.DOM.alterClass( task, - 'phui-object-item-selected', + 'phui-oi-selected', is_selected(task)); update(); }; var redraw = function (task) { var selected = is_selected(task); change(task, selected); }; JX.Stratcom.listen( 'subpriority-changed', null, function (e) { e.kill(); var data = e.getData(); redraw(data.task); }); // Change all tasks to some state (used by "select all" / "clear selection" // buttons). var changeall = function(to) { var inputs = JX.DOM.scry(document.body, 'li', 'maniphest-task'); for (var ii = 0; ii < inputs.length; ii++) { change(inputs[ii], to); } }; // Clear any document text selection after toggling a task via shift click, // since errant clicks tend to start selecting various ranges otherwise. var clear_selection = function() { if (window.getSelection) { if (window.getSelection().empty) { window.getSelection().empty(); } else if (window.getSelection().removeAllRanges) { window.getSelection().removeAllRanges(); } } else if (document.selection) { document.selection.empty(); } }; // Update the status text showing how many tasks are selected, and the button // state. var update = function() { var count = JX.keys(selected).length; var status; if (count === 0) { status = 'Shift-Click to Select Tasks'; } else if (status == 1) { status = '1 Selected Task'; } else { status = count + ' Selected Tasks'; } JX.DOM.setContent(JX.$(config.status), status); var submit = JX.$(config.submit); var disable = (count === 0); submit.disabled = disable; JX.DOM.alterClass(submit, 'disabled', disable); }; // When he user shift-clicks the task, update the rest of the application // state. JX.Stratcom.listen( 'click', 'maniphest-task', function(e) { var raw = e.getRawEvent(); if (!raw.shiftKey) { return; } if (raw.ctrlKey || raw.altKey || raw.metaKey || e.isRightButton()) { return; } if (JX.Stratcom.pass(e)) { return; } e.kill(); change(e.getNode('maniphest-task')); clear_selection(); }); // When the user clicks "Select All", select all tasks. JX.DOM.listen( JX.$(config.selectNone), 'click', null, function(e) { changeall(false); e.kill(); }); // When the user clicks "Clear Selection", clear the selection. JX.DOM.listen( JX.$(config.selectAll), 'click', null, function(e) { changeall(true); e.kill(); }); // When the user submits the form, dump selected state into it. JX.DOM.listen( JX.$(config.formID), 'submit', null, function() { var inputs = []; for (var k in selected) { inputs.push( JX.$N('input', {type: 'hidden', name: 'batch[]', value: k})); } JX.DOM.setContent(JX.$(config.idContainer), inputs); }); update(); });