diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 51bc9338d2..cb44dd5585 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -1,2356 +1,2356 @@ array( 'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => 'e0cb8094', + 'core.pkg.css' => '7a73ffc5', 'core.pkg.js' => '5c737607', 'differential.pkg.css' => 'b8df73d4', 'differential.pkg.js' => '67c9ea4c', 'diffusion.pkg.css' => '42c75c37', 'diffusion.pkg.js' => '91192d85', 'maniphest.pkg.css' => '35995d6d', 'maniphest.pkg.js' => '286955ae', 'rsrc/audio/basic/alert.mp3' => '17889334', 'rsrc/audio/basic/bing.mp3' => 'a817a0c3', 'rsrc/audio/basic/pock.mp3' => '0fa843d0', 'rsrc/audio/basic/tap.mp3' => '02d16994', 'rsrc/audio/basic/ting.mp3' => 'a6b6540e', 'rsrc/css/aphront/aphront-bars.css' => '4a327b4a', 'rsrc/css/aphront/dark-console.css' => '7f06cda2', 'rsrc/css/aphront/dialog-view.css' => 'b70c70df', 'rsrc/css/aphront/list-filter-view.css' => 'feb64255', 'rsrc/css/aphront/multi-column.css' => 'fbc00ba3', 'rsrc/css/aphront/notification.css' => '30240bd2', 'rsrc/css/aphront/panel-view.css' => '46923d46', 'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf', - 'rsrc/css/aphront/table-view.css' => '76eda3f8', + 'rsrc/css/aphront/table-view.css' => 'daa1f9df', 'rsrc/css/aphront/tokenizer.css' => 'b52d0668', 'rsrc/css/aphront/tooltip.css' => 'e3f2412f', 'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2', 'rsrc/css/aphront/typeahead.css' => '8779483d', 'rsrc/css/application/almanac/almanac.css' => '2e050f4f', 'rsrc/css/application/auth/auth.css' => 'add92fd8', 'rsrc/css/application/base/main-menu-view.css' => '8e2d9a28', 'rsrc/css/application/base/notification-menu.css' => 'e6962e89', 'rsrc/css/application/base/phui-theme.css' => '35883b37', 'rsrc/css/application/base/standard-page-view.css' => '8a295cb9', 'rsrc/css/application/chatlog/chatlog.css' => 'abdc76ee', 'rsrc/css/application/conduit/conduit-api.css' => 'ce2cfc41', 'rsrc/css/application/config/config-options.css' => '16c920ae', 'rsrc/css/application/config/config-template.css' => '20babf50', 'rsrc/css/application/config/setup-issue.css' => '5eed85b2', 'rsrc/css/application/config/unhandled-exception.css' => '9da8fdab', 'rsrc/css/application/conpherence/color.css' => 'b17746b0', 'rsrc/css/application/conpherence/durable-column.css' => '2d57072b', 'rsrc/css/application/conpherence/header-pane.css' => 'c9a3db8e', 'rsrc/css/application/conpherence/menu.css' => '67f4680d', 'rsrc/css/application/conpherence/message-pane.css' => 'd244db1e', 'rsrc/css/application/conpherence/notification.css' => '6a3d4e58', 'rsrc/css/application/conpherence/participant-pane.css' => '69e0058a', 'rsrc/css/application/conpherence/transaction.css' => '3a3f5e7e', 'rsrc/css/application/contentsource/content-source-view.css' => 'cdf0d579', 'rsrc/css/application/countdown/timer.css' => 'bff8012f', 'rsrc/css/application/daemon/bulk-job.css' => '73af99f5', 'rsrc/css/application/dashboard/dashboard.css' => '4267d6c6', 'rsrc/css/application/diff/inline-comment-summary.css' => '81eb368d', 'rsrc/css/application/differential/add-comment.css' => '7e5900d9', 'rsrc/css/application/differential/changeset-view.css' => '73660575', 'rsrc/css/application/differential/core.css' => 'bdb93065', 'rsrc/css/application/differential/phui-inline-comment.css' => '48acce5b', 'rsrc/css/application/differential/revision-comment.css' => '7dbc8d1d', 'rsrc/css/application/differential/revision-history.css' => '8aa3eac5', 'rsrc/css/application/differential/revision-list.css' => '93d2df7d', 'rsrc/css/application/differential/table-of-contents.css' => '0e3364c7', 'rsrc/css/application/diffusion/diffusion-icons.css' => '23b31a1b', 'rsrc/css/application/diffusion/diffusion-readme.css' => 'b68a76e4', 'rsrc/css/application/diffusion/diffusion-repository.css' => 'b89e8c6c', 'rsrc/css/application/diffusion/diffusion.css' => 'b54c77b0', 'rsrc/css/application/feed/feed.css' => 'd8b6e3f8', 'rsrc/css/application/files/global-drag-and-drop.css' => '1d2713a4', 'rsrc/css/application/flag/flag.css' => '2b77be8d', 'rsrc/css/application/harbormaster/harbormaster.css' => '8dfe16b2', 'rsrc/css/application/herald/herald-test.css' => 'e004176f', 'rsrc/css/application/herald/herald.css' => '648d39e2', 'rsrc/css/application/maniphest/report.css' => '3d53188b', 'rsrc/css/application/maniphest/task-edit.css' => '272daa84', 'rsrc/css/application/maniphest/task-summary.css' => '61d1667e', 'rsrc/css/application/objectselector/object-selector.css' => 'ee77366f', 'rsrc/css/application/owners/owners-path-editor.css' => 'fa7c13ef', 'rsrc/css/application/paste/paste.css' => 'b37bcd38', 'rsrc/css/application/people/people-picture-menu-item.css' => 'fe8e07cf', 'rsrc/css/application/people/people-profile.css' => '2ea2daa1', 'rsrc/css/application/phame/phame.css' => '799febf9', 'rsrc/css/application/pholio/pholio-edit.css' => '4df55b3b', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '722b48c2', 'rsrc/css/application/pholio/pholio.css' => '88ef5ef1', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '3b9868a8', 'rsrc/css/application/phortune/phortune-invoice.css' => '4436b241', 'rsrc/css/application/phortune/phortune.css' => '12e8251a', 'rsrc/css/application/phrequent/phrequent.css' => 'bd79cc67', 'rsrc/css/application/phriction/phriction-document-css.css' => '03380da0', 'rsrc/css/application/policy/policy-edit.css' => '8794e2ed', 'rsrc/css/application/policy/policy-transaction-detail.css' => 'c02b8384', 'rsrc/css/application/policy/policy.css' => 'ceb56a08', 'rsrc/css/application/ponder/ponder-view.css' => '05a09d0a', 'rsrc/css/application/project/project-card-view.css' => '3b1f7b20', 'rsrc/css/application/project/project-view.css' => '567858b3', 'rsrc/css/application/releeph/releeph-core.css' => 'f81ff2db', 'rsrc/css/application/releeph/releeph-preview-branch.css' => '22db5c07', 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '0ac1ea31', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => 'bce37359', 'rsrc/css/application/search/application-search-view.css' => '0f7c06d8', 'rsrc/css/application/search/search-results.css' => '9ea70ace', 'rsrc/css/application/slowvote/slowvote.css' => '1694baed', 'rsrc/css/application/tokens/tokens.css' => 'ce5a50bd', 'rsrc/css/application/uiexample/example.css' => 'b4795059', 'rsrc/css/core/core.css' => '1b29ed61', 'rsrc/css/core/remarkup.css' => '9e627d41', 'rsrc/css/core/syntax.css' => '8a16f91b', 'rsrc/css/core/z-index.css' => '99c0f5eb', 'rsrc/css/diviner/diviner-shared.css' => '4bd263b0', 'rsrc/css/font/font-awesome.css' => '3883938a', 'rsrc/css/font/font-lato.css' => '23631304', 'rsrc/css/font/phui-font-icon-base.css' => 'd7994e06', 'rsrc/css/layout/phabricator-filetree-view.css' => '56cdd875', 'rsrc/css/layout/phabricator-source-code-view.css' => '03d7ac28', 'rsrc/css/phui/button/phui-button-bar.css' => 'a4aa75c4', 'rsrc/css/phui/button/phui-button-simple.css' => '1ff278aa', 'rsrc/css/phui/button/phui-button.css' => 'ea704902', 'rsrc/css/phui/calendar/phui-calendar-day.css' => '9597d706', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'ccd7e4e2', 'rsrc/css/phui/calendar/phui-calendar-month.css' => 'cb758c42', 'rsrc/css/phui/calendar/phui-calendar.css' => 'f11073aa', 'rsrc/css/phui/object-item/phui-oi-big-ui.css' => '9e037c7a', 'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0', 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc', 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e', 'rsrc/css/phui/object-item/phui-oi-list-view.css' => '909f3844', 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46', - 'rsrc/css/phui/phui-action-list.css' => 'c1a7631d', + 'rsrc/css/phui/phui-action-list.css' => 'c4972757', 'rsrc/css/phui/phui-action-panel.css' => '6c386cbf', 'rsrc/css/phui/phui-badge.css' => '666e25ad', 'rsrc/css/phui/phui-basic-nav-view.css' => '56ebd66d', 'rsrc/css/phui/phui-big-info-view.css' => '362ad37b', 'rsrc/css/phui/phui-box.css' => '5ed3b8cb', 'rsrc/css/phui/phui-bulk-editor.css' => '374d5e30', 'rsrc/css/phui/phui-chart.css' => '7853a69b', 'rsrc/css/phui/phui-cms.css' => '8c05c41e', 'rsrc/css/phui/phui-comment-form.css' => '68a2d99a', 'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0', 'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf', 'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6', 'rsrc/css/phui/phui-document-pro.css' => 'b9613a10', 'rsrc/css/phui/phui-document-summary.css' => 'b068eed1', 'rsrc/css/phui/phui-document.css' => '52b748a5', 'rsrc/css/phui/phui-feed-story.css' => 'a0c05029', 'rsrc/css/phui/phui-fontkit.css' => '9b714a5e', 'rsrc/css/phui/phui-form-view.css' => '0807e7ac', 'rsrc/css/phui/phui-form.css' => '159e2d9c', 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', 'rsrc/css/phui/phui-header-view.css' => '93cea4ec', 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', 'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec', - 'rsrc/css/phui/phui-icon.css' => '281f964d', + 'rsrc/css/phui/phui-icon.css' => '4cbc684a', 'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2', 'rsrc/css/phui/phui-info-view.css' => '37b8d9ce', 'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4', 'rsrc/css/phui/phui-left-right.css' => '68513c34', 'rsrc/css/phui/phui-lightbox.css' => '4ebf22da', 'rsrc/css/phui/phui-list.css' => '470b1adb', 'rsrc/css/phui/phui-object-box.css' => '9b58483d', 'rsrc/css/phui/phui-pager.css' => 'd022c7ad', 'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8', 'rsrc/css/phui/phui-property-list-view.css' => 'cad62236', 'rsrc/css/phui/phui-remarkup-preview.css' => '91767007', 'rsrc/css/phui/phui-segment-bar-view.css' => '5166b370', 'rsrc/css/phui/phui-spacing.css' => 'b05cadc3', 'rsrc/css/phui/phui-status.css' => 'e5ff8be0', 'rsrc/css/phui/phui-tag-view.css' => 'a42fe34f', 'rsrc/css/phui/phui-timeline-view.css' => '1e348e4b', 'rsrc/css/phui/phui-two-column-view.css' => '01e6991e', 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'e86de308', 'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98', 'rsrc/css/phui/workboards/phui-workcard.css' => '8c536f90', 'rsrc/css/phui/workboards/phui-workpanel.css' => 'bd546a49', 'rsrc/css/sprite-login.css' => '18b368a6', 'rsrc/css/sprite-tokens.css' => 'f1896dc5', 'rsrc/css/syntax/syntax-default.css' => '055fc231', 'rsrc/externals/d3/d3.min.js' => 'd67475f5', 'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '23f8c698', 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '70983df0', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => 'cd02f93b', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '351fd46a', 'rsrc/externals/font/lato/lato-bold.eot' => '7367aa5e', 'rsrc/externals/font/lato/lato-bold.svg' => '681aa4f5', 'rsrc/externals/font/lato/lato-bold.ttf' => '66d3c296', 'rsrc/externals/font/lato/lato-bold.woff' => '89d9fba7', 'rsrc/externals/font/lato/lato-bold.woff2' => '389fcdb1', 'rsrc/externals/font/lato/lato-bolditalic.eot' => '03eeb4da', 'rsrc/externals/font/lato/lato-bolditalic.svg' => 'f56fa11c', 'rsrc/externals/font/lato/lato-bolditalic.ttf' => '9c3aec21', 'rsrc/externals/font/lato/lato-bolditalic.woff' => 'bfbd0616', 'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'bc7d1274', 'rsrc/externals/font/lato/lato-italic.eot' => '7db5b247', 'rsrc/externals/font/lato/lato-italic.svg' => 'b1ae496f', 'rsrc/externals/font/lato/lato-italic.ttf' => '43eed813', 'rsrc/externals/font/lato/lato-italic.woff' => 'c28975e1', 'rsrc/externals/font/lato/lato-italic.woff2' => 'fffc0d8c', 'rsrc/externals/font/lato/lato-regular.eot' => '06e0c291', 'rsrc/externals/font/lato/lato-regular.svg' => '3ad95f53', 'rsrc/externals/font/lato/lato-regular.ttf' => 'e2e9c398', 'rsrc/externals/font/lato/lato-regular.woff' => '0b13d332', 'rsrc/externals/font/lato/lato-regular.woff2' => '8f846797', 'rsrc/externals/javelin/core/Event.js' => 'c03f2fb4', 'rsrc/externals/javelin/core/Stratcom.js' => '0889b835', 'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '048472d2', 'rsrc/externals/javelin/core/__tests__/install.js' => '14a7e671', 'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'a28464bb', 'rsrc/externals/javelin/core/__tests__/util.js' => 'e29a4354', 'rsrc/externals/javelin/core/init.js' => '98e6504a', 'rsrc/externals/javelin/core/init_node.js' => '16961339', 'rsrc/externals/javelin/core/install.js' => '5902260c', 'rsrc/externals/javelin/core/util.js' => '22ae1776', 'rsrc/externals/javelin/docs/Base.js' => '5a401d7d', 'rsrc/externals/javelin/docs/onload.js' => 'ee58fb62', 'rsrc/externals/javelin/ext/fx/Color.js' => '78f811c9', 'rsrc/externals/javelin/ext/fx/FX.js' => '34450586', 'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => '202a2e85', 'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => '1c850a26', 'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '72960bc1', 'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '225bbb98', 'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => '6cfa0008', 'rsrc/externals/javelin/ext/view/HTMLView.js' => 'f8c4e135', 'rsrc/externals/javelin/ext/view/View.js' => '289bf236', 'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => '876506b6', 'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => 'a9942052', 'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '9aae2b66', 'rsrc/externals/javelin/ext/view/ViewVisitor.js' => '308f9fe4', 'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => '6e50a13f', 'rsrc/externals/javelin/ext/view/__tests__/View.js' => 'd284be5d', 'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => 'a9f35511', 'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '3a1b81f6', 'rsrc/externals/javelin/lib/Cookie.js' => '05d290ef', 'rsrc/externals/javelin/lib/DOM.js' => '94681e22', 'rsrc/externals/javelin/lib/History.js' => '030b4f7a', 'rsrc/externals/javelin/lib/JSON.js' => '541f81c3', 'rsrc/externals/javelin/lib/Leader.js' => '0d2490ce', 'rsrc/externals/javelin/lib/Mask.js' => '7c4d8998', 'rsrc/externals/javelin/lib/Quicksand.js' => 'd3799cb4', 'rsrc/externals/javelin/lib/Request.js' => '91863989', 'rsrc/externals/javelin/lib/Resource.js' => '740956e1', 'rsrc/externals/javelin/lib/Routable.js' => '6a18c42e', 'rsrc/externals/javelin/lib/Router.js' => '32755edb', 'rsrc/externals/javelin/lib/Scrollbar.js' => 'a43ae2ae', 'rsrc/externals/javelin/lib/Sound.js' => 'e562708c', 'rsrc/externals/javelin/lib/URI.js' => '2e255291', 'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb', 'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e', 'rsrc/externals/javelin/lib/Workflow.js' => '958e9045', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae', 'rsrc/externals/javelin/lib/__tests__/URI.js' => '6fff0c2b', 'rsrc/externals/javelin/lib/__tests__/behavior.js' => '8426ebeb', 'rsrc/externals/javelin/lib/behavior.js' => 'fce5d170', 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => '89a1ae3a', 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => 'a4356cde', 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'a241536a', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '22ee68a5', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '23387297', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '5a79f6c3', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '8badee71', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '80bff3af', 'rsrc/favicons/favicon-16x16.png' => '4c51a03a', 'rsrc/favicons/mask-icon.svg' => 'db699fe1', 'rsrc/image/BFCFDA.png' => '74b5c88b', 'rsrc/image/actions/edit.png' => 'fd987dff', 'rsrc/image/avatar.png' => '0d17c6c4', 'rsrc/image/checker_dark.png' => '7fc8fa7b', 'rsrc/image/checker_light.png' => '3157a202', 'rsrc/image/checker_lighter.png' => 'c45928c1', 'rsrc/image/controls/checkbox-checked.png' => '1770d7a0', 'rsrc/image/controls/checkbox-unchecked.png' => 'e1deba0a', 'rsrc/image/d5d8e1.png' => '6764616e', 'rsrc/image/darkload.gif' => '5bd41a89', 'rsrc/image/divot.png' => '0fbe2453', 'rsrc/image/examples/hero.png' => '5d8c4b21', 'rsrc/image/grippy_texture.png' => 'a7d222b5', 'rsrc/image/icon/fatcow/arrow_branch.png' => '98149d9f', 'rsrc/image/icon/fatcow/arrow_merge.png' => 'e142f4f8', 'rsrc/image/icon/fatcow/calendar_edit.png' => '5ff44a08', 'rsrc/image/icon/fatcow/document_black.png' => 'd3515fa5', 'rsrc/image/icon/fatcow/flag_blue.png' => '54db2e5c', 'rsrc/image/icon/fatcow/flag_finish.png' => '2953a51b', 'rsrc/image/icon/fatcow/flag_ghost.png' => '7d9ada92', 'rsrc/image/icon/fatcow/flag_green.png' => '010f7161', 'rsrc/image/icon/fatcow/flag_orange.png' => '6c384ca5', 'rsrc/image/icon/fatcow/flag_pink.png' => '11ac6b12', 'rsrc/image/icon/fatcow/flag_purple.png' => 'c4f423a4', 'rsrc/image/icon/fatcow/flag_red.png' => '9e6d8817', 'rsrc/image/icon/fatcow/flag_yellow.png' => '906733f4', 'rsrc/image/icon/fatcow/key_question.png' => 'c10c26db', 'rsrc/image/icon/fatcow/link.png' => '8edbf327', 'rsrc/image/icon/fatcow/page_white_edit.png' => '17ef5625', 'rsrc/image/icon/fatcow/page_white_put.png' => '82430c91', 'rsrc/image/icon/fatcow/source/conduit.png' => '5b55130c', 'rsrc/image/icon/fatcow/source/email.png' => '8a32b77f', 'rsrc/image/icon/fatcow/source/fax.png' => '8bc2a49b', 'rsrc/image/icon/fatcow/source/mobile.png' => '0a918412', 'rsrc/image/icon/fatcow/source/tablet.png' => 'fc50b050', 'rsrc/image/icon/fatcow/source/web.png' => '70433af3', 'rsrc/image/icon/subscribe.png' => '07ef454e', 'rsrc/image/icon/tango/attachment.png' => 'bac9032d', 'rsrc/image/icon/tango/edit.png' => 'e6296206', 'rsrc/image/icon/tango/go-down.png' => '0b903712', 'rsrc/image/icon/tango/log.png' => '86b6a6f4', 'rsrc/image/icon/tango/upload.png' => '3fe6b92d', 'rsrc/image/icon/unsubscribe.png' => 'db04378a', 'rsrc/image/lightblue-header.png' => 'e6d483c6', 'rsrc/image/logo/light-eye.png' => '72337472', 'rsrc/image/main_texture.png' => '894d03c4', 'rsrc/image/menu_texture.png' => '896c9ade', 'rsrc/image/people/harding.png' => '95b2db63', 'rsrc/image/people/jefferson.png' => 'e883a3a2', 'rsrc/image/people/lincoln.png' => 'be2c07c5', 'rsrc/image/people/mckinley.png' => '6af510a0', 'rsrc/image/people/taft.png' => 'b15ab07e', 'rsrc/image/people/user0.png' => '4bc64b40', 'rsrc/image/people/user1.png' => '8063f445', 'rsrc/image/people/user2.png' => 'd28246c0', 'rsrc/image/people/user3.png' => 'fb1ac12d', 'rsrc/image/people/user4.png' => 'fe4fac8f', 'rsrc/image/people/user5.png' => '3d07065c', 'rsrc/image/people/user6.png' => 'e4bd47c8', 'rsrc/image/people/user7.png' => '71d8fe8b', 'rsrc/image/people/user8.png' => '85f86bf7', 'rsrc/image/people/user9.png' => '523db8aa', 'rsrc/image/people/washington.png' => '86159e68', 'rsrc/image/phrequent_active.png' => 'de66dc50', 'rsrc/image/phrequent_inactive.png' => '79c61baf', 'rsrc/image/resize.png' => '9cc83373', 'rsrc/image/sprite-login-X2.png' => '604545f6', 'rsrc/image/sprite-login.png' => '7a001a9a', 'rsrc/image/sprite-tokens-X2.png' => '21621dd9', 'rsrc/image/sprite-tokens.png' => 'bede2580', 'rsrc/image/texture/card-gradient.png' => 'e6892cb4', 'rsrc/image/texture/dark-menu-hover.png' => '390a4fa1', 'rsrc/image/texture/dark-menu.png' => '542f699c', 'rsrc/image/texture/grip.png' => 'bc80753a', 'rsrc/image/texture/panel-header-gradient.png' => '65004dbf', 'rsrc/image/texture/phlnx-bg.png' => '6c9cd31d', 'rsrc/image/texture/pholio-background.gif' => '84910bfc', 'rsrc/image/texture/table_header.png' => '7652d1ad', 'rsrc/image/texture/table_header_hover.png' => '12ea5236', 'rsrc/image/texture/table_header_tall.png' => '5cc420c4', 'rsrc/js/application/aphlict/Aphlict.js' => '022516b4', 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'e9a2940f', 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => '4e61fa88', 'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'c3703a16', 'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => '070679fe', 'rsrc/js/application/calendar/behavior-day-view.js' => '727a5a61', 'rsrc/js/application/calendar/behavior-event-all-day.js' => '0b1bc990', 'rsrc/js/application/calendar/behavior-month-view.js' => '158c64e0', 'rsrc/js/application/config/behavior-reorder-fields.js' => '2539f834', 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'aec8e38c', 'rsrc/js/application/conpherence/behavior-conpherence-search.js' => '91befbcc', 'rsrc/js/application/conpherence/behavior-durable-column.js' => 'fa6f30b2', 'rsrc/js/application/conpherence/behavior-menu.js' => '8c2ed2bf', 'rsrc/js/application/conpherence/behavior-participant-pane.js' => '43ba89a2', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '4ae58b5a', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '5a6f6a06', 'rsrc/js/application/conpherence/behavior-toggle-widget.js' => '8f959ad0', 'rsrc/js/application/countdown/timer.js' => '6a162524', 'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => '3829a3cf', 'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '09ecf50c', 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '076bd092', 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '9b1cbd76', 'rsrc/js/application/diff/DiffChangeset.js' => 'e7cf10d6', 'rsrc/js/application/diff/DiffChangesetList.js' => 'b91204e9', 'rsrc/js/application/diff/DiffInline.js' => 'a4a14a94', 'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17', 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 'rsrc/js/application/differential/behavior-populate.js' => 'dfa1d313', 'rsrc/js/application/differential/behavior-user-select.js' => 'e18685c0', 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => '94243d89', 'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'b7b73831', 'rsrc/js/application/diffusion/behavior-commit-branches.js' => '4b671572', 'rsrc/js/application/diffusion/behavior-commit-graph.js' => '1c88f154', 'rsrc/js/application/diffusion/behavior-locate-file.js' => '87428eb2', 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'c715c123', 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '6a85bc5a', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '47a0728b', 'rsrc/js/application/files/behavior-document-engine.js' => '243d6c22', 'rsrc/js/application/files/behavior-icon-composer.js' => '38a6cedb', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => 'a17b84f1', 'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => 'b347a301', 'rsrc/js/application/herald/HeraldRuleEditor.js' => '27daef73', 'rsrc/js/application/herald/PathTypeahead.js' => 'ad486db3', 'rsrc/js/application/herald/herald-rule-editor.js' => '0922e81d', 'rsrc/js/application/maniphest/behavior-batch-selector.js' => 'cffd39b4', 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'c8147a20', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'c687e867', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '8400307c', 'rsrc/js/application/owners/OwnersPathEditor.js' => '2a8b62d9', 'rsrc/js/application/owners/owners-path-editor.js' => 'ff688a7a', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '48fe33d0', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '3eed1f2b', 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => '5aa1544e', 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '02cb4398', 'rsrc/js/application/phortune/behavior-test-payment-form.js' => '4a7fb02b', 'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f', 'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9', 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172', 'rsrc/js/application/projects/WorkboardBoard.js' => '45d0b2b1', 'rsrc/js/application/projects/WorkboardCard.js' => '9a513421', 'rsrc/js/application/projects/WorkboardColumn.js' => '8573dc1b', 'rsrc/js/application/projects/WorkboardController.js' => '42c7a5a7', 'rsrc/js/application/projects/behavior-project-boards.js' => '05c74d65', 'rsrc/js/application/projects/behavior-project-create.js' => '34c53422', 'rsrc/js/application/projects/behavior-reorder-columns.js' => '8ac32fd9', 'rsrc/js/application/releeph/releeph-preview-branch.js' => '75184d68', 'rsrc/js/application/releeph/releeph-request-state-change.js' => '9f081f05', 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'aa3a100c', 'rsrc/js/application/repository/repository-crossreference.js' => 'db0c0214', 'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e5bdb730', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'b86f297f', 'rsrc/js/application/transactions/behavior-comment-actions.js' => '4dffaeb2', 'rsrc/js/application/transactions/behavior-reorder-configs.js' => '4842f137', 'rsrc/js/application/transactions/behavior-reorder-fields.js' => '0ad8d31f', 'rsrc/js/application/transactions/behavior-show-older-transactions.js' => '600f440c', 'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => '2bdadf1a', 'rsrc/js/application/transactions/behavior-transaction-list.js' => '9cec214e', 'rsrc/js/application/typeahead/behavior-typeahead-browse.js' => '70245195', 'rsrc/js/application/typeahead/behavior-typeahead-search.js' => '7b139193', 'rsrc/js/application/uiexample/gesture-example.js' => '242dedd0', 'rsrc/js/application/uiexample/notification-example.js' => '29819b75', 'rsrc/js/core/Busy.js' => '5202e831', 'rsrc/js/core/DragAndDropFileUpload.js' => '4370900d', 'rsrc/js/core/DraggableList.js' => '3c6bd549', 'rsrc/js/core/Favicon.js' => '7930776a', 'rsrc/js/core/FileUpload.js' => 'ab85e184', 'rsrc/js/core/Hovercard.js' => '074f0783', 'rsrc/js/core/KeyboardShortcut.js' => 'c9749dcd', 'rsrc/js/core/KeyboardShortcutManager.js' => '37b8a04a', 'rsrc/js/core/MultirowRowManager.js' => '5b54c823', 'rsrc/js/core/Notification.js' => 'a9b91e3f', 'rsrc/js/core/Prefab.js' => 'bf457520', 'rsrc/js/core/ShapedRequest.js' => 'abf88db8', 'rsrc/js/core/TextAreaUtils.js' => 'f340a484', 'rsrc/js/core/Title.js' => '43bc9360', 'rsrc/js/core/ToolTip.js' => '83754533', 'rsrc/js/core/behavior-active-nav.js' => '7353f43d', 'rsrc/js/core/behavior-audio-source.js' => '3dc5ad43', 'rsrc/js/core/behavior-autofocus.js' => '65bb0011', 'rsrc/js/core/behavior-badge-view.js' => '92cdd7b6', 'rsrc/js/core/behavior-bulk-editor.js' => 'aa6d2308', 'rsrc/js/core/behavior-choose-control.js' => '04f8a1e3', 'rsrc/js/core/behavior-copy.js' => 'cf32921f', 'rsrc/js/core/behavior-detect-timezone.js' => '78bc5d94', 'rsrc/js/core/behavior-device.js' => '0cf79f45', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '7ad020a5', 'rsrc/js/core/behavior-fancy-datepicker.js' => '956f3eeb', 'rsrc/js/core/behavior-file-tree.js' => 'ee82cedb', 'rsrc/js/core/behavior-form.js' => '55d7b788', 'rsrc/js/core/behavior-gesture.js' => 'b58d1a2a', 'rsrc/js/core/behavior-global-drag-and-drop.js' => '1cab0e9a', 'rsrc/js/core/behavior-high-security-warning.js' => 'dae2d55b', 'rsrc/js/core/behavior-history-install.js' => '6a1583a8', 'rsrc/js/core/behavior-hovercard.js' => '6c379000', 'rsrc/js/core/behavior-keyboard-pager.js' => '1325b731', 'rsrc/js/core/behavior-keyboard-shortcuts.js' => '2cc87f49', 'rsrc/js/core/behavior-lightbox-attachments.js' => 'c7e748bf', 'rsrc/js/core/behavior-line-linker.js' => 'e15c8b1f', 'rsrc/js/core/behavior-linked-container.js' => '74446546', 'rsrc/js/core/behavior-more.js' => '506aa3f4', 'rsrc/js/core/behavior-object-selector.js' => 'a4af0b4a', 'rsrc/js/core/behavior-oncopy.js' => '418f6684', 'rsrc/js/core/behavior-phabricator-nav.js' => 'f166c949', 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '2f80333f', 'rsrc/js/core/behavior-read-only-warning.js' => 'b9109f8f', 'rsrc/js/core/behavior-redirect.js' => '407ee861', 'rsrc/js/core/behavior-refresh-csrf.js' => '46116c01', 'rsrc/js/core/behavior-remarkup-load-image.js' => '202bfa3f', 'rsrc/js/core/behavior-remarkup-preview.js' => 'd8a86cfb', 'rsrc/js/core/behavior-reorder-applications.js' => 'aa371860', 'rsrc/js/core/behavior-reveal-content.js' => 'b105a3a6', 'rsrc/js/core/behavior-scrollbar.js' => '92388bae', 'rsrc/js/core/behavior-search-typeahead.js' => '1cb7d027', 'rsrc/js/core/behavior-select-content.js' => 'e8240b50', 'rsrc/js/core/behavior-select-on-click.js' => '66365ee2', 'rsrc/js/core/behavior-setup-check-https.js' => '01384686', 'rsrc/js/core/behavior-time-typeahead.js' => '5803b9e7', 'rsrc/js/core/behavior-toggle-class.js' => 'f5c78ae3', 'rsrc/js/core/behavior-tokenizer.js' => '3b4899b0', 'rsrc/js/core/behavior-tooltip.js' => '73ecc1f8', 'rsrc/js/core/behavior-user-menu.js' => '60cd9241', 'rsrc/js/core/behavior-watch-anchor.js' => '0e6d261f', 'rsrc/js/core/behavior-workflow.js' => '9623adc1', 'rsrc/js/core/darkconsole/DarkLog.js' => '3b869402', 'rsrc/js/core/darkconsole/DarkMessage.js' => '26cd4b73', 'rsrc/js/core/darkconsole/behavior-dark-console.js' => 'f39d968b', 'rsrc/js/core/phtize.js' => '2f1db1ed', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '5cf0501a', 'rsrc/js/phui/behavior-phui-file-upload.js' => 'e150bd50', 'rsrc/js/phui/behavior-phui-selectable-list.js' => 'b26a41e4', 'rsrc/js/phui/behavior-phui-submenu.js' => 'b5e9bff9', 'rsrc/js/phui/behavior-phui-tab-group.js' => '242aa08b', 'rsrc/js/phuix/PHUIXActionListView.js' => 'c68f183f', 'rsrc/js/phuix/PHUIXActionView.js' => 'aaa08f3b', 'rsrc/js/phuix/PHUIXAutocomplete.js' => '58cc4ab8', 'rsrc/js/phuix/PHUIXButtonView.js' => '55a24e84', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bdce4d78', 'rsrc/js/phuix/PHUIXExample.js' => 'c2c500a7', 'rsrc/js/phuix/PHUIXFormControl.js' => '38c1f3fb', 'rsrc/js/phuix/PHUIXIconView.js' => 'a5257c4e', ), 'symbols' => array( 'almanac-css' => '2e050f4f', 'aphront-bars' => '4a327b4a', 'aphront-dark-console-css' => '7f06cda2', 'aphront-dialog-view-css' => 'b70c70df', 'aphront-list-filter-view-css' => 'feb64255', 'aphront-multi-column-view-css' => 'fbc00ba3', 'aphront-panel-view-css' => '46923d46', - 'aphront-table-view-css' => '76eda3f8', + 'aphront-table-view-css' => 'daa1f9df', 'aphront-tokenizer-control-css' => 'b52d0668', 'aphront-tooltip-css' => 'e3f2412f', 'aphront-typeahead-control-css' => '8779483d', 'application-search-view-css' => '0f7c06d8', 'auth-css' => 'add92fd8', 'bulk-job-css' => '73af99f5', 'conduit-api-css' => 'ce2cfc41', 'config-options-css' => '16c920ae', 'conpherence-color-css' => 'b17746b0', 'conpherence-durable-column-view' => '2d57072b', 'conpherence-header-pane-css' => 'c9a3db8e', 'conpherence-menu-css' => '67f4680d', 'conpherence-message-pane-css' => 'd244db1e', 'conpherence-notification-css' => '6a3d4e58', 'conpherence-participant-pane-css' => '69e0058a', 'conpherence-thread-manager' => 'aec8e38c', 'conpherence-transaction-css' => '3a3f5e7e', 'd3' => 'd67475f5', 'differential-changeset-view-css' => '73660575', 'differential-core-view-css' => 'bdb93065', 'differential-revision-add-comment-css' => '7e5900d9', 'differential-revision-comment-css' => '7dbc8d1d', 'differential-revision-history-css' => '8aa3eac5', 'differential-revision-list-css' => '93d2df7d', 'differential-table-of-contents-css' => '0e3364c7', 'diffusion-css' => 'b54c77b0', 'diffusion-icons-css' => '23b31a1b', 'diffusion-readme-css' => 'b68a76e4', 'diffusion-repository-css' => 'b89e8c6c', 'diviner-shared-css' => '4bd263b0', 'font-fontawesome' => '3883938a', 'font-lato' => '23631304', 'global-drag-and-drop-css' => '1d2713a4', 'harbormaster-css' => '8dfe16b2', 'herald-css' => '648d39e2', 'herald-rule-editor' => '27daef73', 'herald-test-css' => 'e004176f', 'inline-comment-summary-css' => '81eb368d', 'javelin-aphlict' => '022516b4', 'javelin-behavior' => 'fce5d170', 'javelin-behavior-aphlict-dropdown' => 'e9a2940f', 'javelin-behavior-aphlict-listen' => '4e61fa88', 'javelin-behavior-aphlict-status' => 'c3703a16', 'javelin-behavior-aphront-basic-tokenizer' => '3b4899b0', 'javelin-behavior-aphront-drag-and-drop-textarea' => '7ad020a5', 'javelin-behavior-aphront-form-disable-on-submit' => '55d7b788', 'javelin-behavior-aphront-more' => '506aa3f4', 'javelin-behavior-audio-source' => '3dc5ad43', 'javelin-behavior-audit-preview' => 'b7b73831', 'javelin-behavior-badge-view' => '92cdd7b6', 'javelin-behavior-bulk-editor' => 'aa6d2308', 'javelin-behavior-bulk-job-reload' => '3829a3cf', 'javelin-behavior-calendar-month-view' => '158c64e0', 'javelin-behavior-choose-control' => '04f8a1e3', 'javelin-behavior-comment-actions' => '4dffaeb2', 'javelin-behavior-config-reorder-fields' => '2539f834', 'javelin-behavior-conpherence-menu' => '8c2ed2bf', 'javelin-behavior-conpherence-participant-pane' => '43ba89a2', 'javelin-behavior-conpherence-pontificate' => '4ae58b5a', 'javelin-behavior-conpherence-search' => '91befbcc', 'javelin-behavior-countdown-timer' => '6a162524', 'javelin-behavior-dark-console' => 'f39d968b', 'javelin-behavior-dashboard-async-panel' => '09ecf50c', 'javelin-behavior-dashboard-move-panels' => '076bd092', 'javelin-behavior-dashboard-query-panel-select' => '1e413dc9', 'javelin-behavior-dashboard-tab-panel' => '9b1cbd76', 'javelin-behavior-day-view' => '727a5a61', 'javelin-behavior-desktop-notifications-control' => '070679fe', 'javelin-behavior-detect-timezone' => '78bc5d94', 'javelin-behavior-device' => '0cf79f45', 'javelin-behavior-diff-preview-link' => 'f51e9c17', 'javelin-behavior-differential-diff-radios' => '925fe8cd', 'javelin-behavior-differential-populate' => 'dfa1d313', 'javelin-behavior-differential-user-select' => 'e18685c0', 'javelin-behavior-diffusion-commit-branches' => '4b671572', 'javelin-behavior-diffusion-commit-graph' => '1c88f154', 'javelin-behavior-diffusion-locate-file' => '87428eb2', 'javelin-behavior-diffusion-pull-lastmodified' => 'c715c123', 'javelin-behavior-document-engine' => '243d6c22', 'javelin-behavior-doorkeeper-tag' => '6a85bc5a', 'javelin-behavior-drydock-live-operation-status' => '47a0728b', 'javelin-behavior-durable-column' => 'fa6f30b2', 'javelin-behavior-editengine-reorder-configs' => '4842f137', 'javelin-behavior-editengine-reorder-fields' => '0ad8d31f', 'javelin-behavior-event-all-day' => '0b1bc990', 'javelin-behavior-fancy-datepicker' => '956f3eeb', 'javelin-behavior-global-drag-and-drop' => '1cab0e9a', 'javelin-behavior-harbormaster-log' => 'b347a301', 'javelin-behavior-herald-rule-editor' => '0922e81d', 'javelin-behavior-high-security-warning' => 'dae2d55b', 'javelin-behavior-history-install' => '6a1583a8', 'javelin-behavior-icon-composer' => '38a6cedb', 'javelin-behavior-launch-icon-composer' => 'a17b84f1', 'javelin-behavior-lightbox-attachments' => 'c7e748bf', 'javelin-behavior-line-chart' => 'c8147a20', 'javelin-behavior-linked-container' => '74446546', 'javelin-behavior-maniphest-batch-selector' => 'cffd39b4', 'javelin-behavior-maniphest-list-editor' => 'c687e867', 'javelin-behavior-maniphest-subpriority-editor' => '8400307c', 'javelin-behavior-owners-path-editor' => 'ff688a7a', 'javelin-behavior-passphrase-credential-control' => '48fe33d0', 'javelin-behavior-phabricator-active-nav' => '7353f43d', 'javelin-behavior-phabricator-autofocus' => '65bb0011', 'javelin-behavior-phabricator-clipboard-copy' => 'cf32921f', 'javelin-behavior-phabricator-file-tree' => 'ee82cedb', 'javelin-behavior-phabricator-gesture' => 'b58d1a2a', 'javelin-behavior-phabricator-gesture-example' => '242dedd0', 'javelin-behavior-phabricator-keyboard-pager' => '1325b731', 'javelin-behavior-phabricator-keyboard-shortcuts' => '2cc87f49', 'javelin-behavior-phabricator-line-linker' => 'e15c8b1f', 'javelin-behavior-phabricator-nav' => 'f166c949', 'javelin-behavior-phabricator-notification-example' => '29819b75', 'javelin-behavior-phabricator-object-selector' => 'a4af0b4a', 'javelin-behavior-phabricator-oncopy' => '418f6684', 'javelin-behavior-phabricator-remarkup-assist' => '2f80333f', 'javelin-behavior-phabricator-reveal-content' => 'b105a3a6', 'javelin-behavior-phabricator-search-typeahead' => '1cb7d027', 'javelin-behavior-phabricator-show-older-transactions' => '600f440c', 'javelin-behavior-phabricator-tooltips' => '73ecc1f8', 'javelin-behavior-phabricator-transaction-comment-form' => '2bdadf1a', 'javelin-behavior-phabricator-transaction-list' => '9cec214e', 'javelin-behavior-phabricator-watch-anchor' => '0e6d261f', 'javelin-behavior-pholio-mock-edit' => '3eed1f2b', 'javelin-behavior-pholio-mock-view' => '5aa1544e', 'javelin-behavior-phui-dropdown-menu' => '5cf0501a', 'javelin-behavior-phui-file-upload' => 'e150bd50', 'javelin-behavior-phui-hovercards' => '6c379000', 'javelin-behavior-phui-selectable-list' => 'b26a41e4', 'javelin-behavior-phui-submenu' => 'b5e9bff9', 'javelin-behavior-phui-tab-group' => '242aa08b', 'javelin-behavior-phuix-example' => 'c2c500a7', 'javelin-behavior-policy-control' => '0eaa33a9', 'javelin-behavior-policy-rule-editor' => '9347f172', 'javelin-behavior-project-boards' => '05c74d65', 'javelin-behavior-project-create' => '34c53422', 'javelin-behavior-quicksand-blacklist' => '5a6f6a06', 'javelin-behavior-read-only-warning' => 'b9109f8f', 'javelin-behavior-redirect' => '407ee861', 'javelin-behavior-refresh-csrf' => '46116c01', 'javelin-behavior-releeph-preview-branch' => '75184d68', 'javelin-behavior-releeph-request-state-change' => '9f081f05', 'javelin-behavior-releeph-request-typeahead' => 'aa3a100c', 'javelin-behavior-remarkup-load-image' => '202bfa3f', 'javelin-behavior-remarkup-preview' => 'd8a86cfb', 'javelin-behavior-reorder-applications' => 'aa371860', 'javelin-behavior-reorder-columns' => '8ac32fd9', 'javelin-behavior-reorder-profile-menu-items' => 'e5bdb730', 'javelin-behavior-repository-crossreference' => 'db0c0214', 'javelin-behavior-scrollbar' => '92388bae', 'javelin-behavior-search-reorder-queries' => 'b86f297f', 'javelin-behavior-select-content' => 'e8240b50', 'javelin-behavior-select-on-click' => '66365ee2', 'javelin-behavior-setup-check-https' => '01384686', 'javelin-behavior-stripe-payment-form' => '02cb4398', 'javelin-behavior-test-payment-form' => '4a7fb02b', 'javelin-behavior-time-typeahead' => '5803b9e7', 'javelin-behavior-toggle-class' => 'f5c78ae3', 'javelin-behavior-toggle-widget' => '8f959ad0', 'javelin-behavior-typeahead-browse' => '70245195', 'javelin-behavior-typeahead-search' => '7b139193', 'javelin-behavior-user-menu' => '60cd9241', 'javelin-behavior-view-placeholder' => 'a9942052', 'javelin-behavior-workflow' => '9623adc1', 'javelin-color' => '78f811c9', 'javelin-cookie' => '05d290ef', 'javelin-diffusion-locate-file-source' => '94243d89', 'javelin-dom' => '94681e22', 'javelin-dynval' => '202a2e85', 'javelin-event' => 'c03f2fb4', 'javelin-fx' => '34450586', 'javelin-history' => '030b4f7a', 'javelin-install' => '5902260c', 'javelin-json' => '541f81c3', 'javelin-leader' => '0d2490ce', 'javelin-magical-init' => '98e6504a', 'javelin-mask' => '7c4d8998', 'javelin-quicksand' => 'd3799cb4', 'javelin-reactor' => '1c850a26', 'javelin-reactor-dom' => '6cfa0008', 'javelin-reactor-node-calmer' => '225bbb98', 'javelin-reactornode' => '72960bc1', 'javelin-request' => '91863989', 'javelin-resource' => '740956e1', 'javelin-routable' => '6a18c42e', 'javelin-router' => '32755edb', 'javelin-scrollbar' => 'a43ae2ae', 'javelin-sound' => 'e562708c', 'javelin-stratcom' => '0889b835', 'javelin-tokenizer' => '89a1ae3a', 'javelin-typeahead' => 'a4356cde', 'javelin-typeahead-composite-source' => '22ee68a5', 'javelin-typeahead-normalizer' => 'a241536a', 'javelin-typeahead-ondemand-source' => '23387297', 'javelin-typeahead-preloaded-source' => '5a79f6c3', 'javelin-typeahead-source' => '8badee71', 'javelin-typeahead-static-source' => '80bff3af', 'javelin-uri' => '2e255291', 'javelin-util' => '22ae1776', 'javelin-vector' => 'e9c80beb', 'javelin-view' => '289bf236', 'javelin-view-html' => 'f8c4e135', 'javelin-view-interpreter' => '876506b6', 'javelin-view-renderer' => '9aae2b66', 'javelin-view-visitor' => '308f9fe4', 'javelin-websocket' => 'fdc13e4e', 'javelin-workboard-board' => '45d0b2b1', 'javelin-workboard-card' => '9a513421', 'javelin-workboard-column' => '8573dc1b', 'javelin-workboard-controller' => '42c7a5a7', 'javelin-workflow' => '958e9045', 'maniphest-report-css' => '3d53188b', 'maniphest-task-edit-css' => '272daa84', 'maniphest-task-summary-css' => '61d1667e', 'multirow-row-manager' => '5b54c823', 'owners-path-editor' => '2a8b62d9', 'owners-path-editor-css' => 'fa7c13ef', 'paste-css' => 'b37bcd38', 'path-typeahead' => 'ad486db3', 'people-picture-menu-item-css' => 'fe8e07cf', 'people-profile-css' => '2ea2daa1', - 'phabricator-action-list-view-css' => 'c1a7631d', + 'phabricator-action-list-view-css' => 'c4972757', 'phabricator-busy' => '5202e831', 'phabricator-chatlog-css' => 'abdc76ee', 'phabricator-content-source-view-css' => 'cdf0d579', 'phabricator-core-css' => '1b29ed61', 'phabricator-countdown-css' => 'bff8012f', 'phabricator-darklog' => '3b869402', 'phabricator-darkmessage' => '26cd4b73', 'phabricator-dashboard-css' => '4267d6c6', 'phabricator-diff-changeset' => 'e7cf10d6', 'phabricator-diff-changeset-list' => 'b91204e9', 'phabricator-diff-inline' => 'a4a14a94', 'phabricator-drag-and-drop-file-upload' => '4370900d', 'phabricator-draggable-list' => '3c6bd549', 'phabricator-fatal-config-template-css' => '20babf50', 'phabricator-favicon' => '7930776a', 'phabricator-feed-css' => 'd8b6e3f8', 'phabricator-file-upload' => 'ab85e184', 'phabricator-filetree-view-css' => '56cdd875', 'phabricator-flag-css' => '2b77be8d', 'phabricator-keyboard-shortcut' => 'c9749dcd', 'phabricator-keyboard-shortcut-manager' => '37b8a04a', 'phabricator-main-menu-view' => '8e2d9a28', 'phabricator-nav-view-css' => 'f8a0c1bf', 'phabricator-notification' => 'a9b91e3f', 'phabricator-notification-css' => '30240bd2', 'phabricator-notification-menu-css' => 'e6962e89', 'phabricator-object-selector-css' => 'ee77366f', 'phabricator-phtize' => '2f1db1ed', 'phabricator-prefab' => 'bf457520', 'phabricator-remarkup-css' => '9e627d41', 'phabricator-search-results-css' => '9ea70ace', 'phabricator-shaped-request' => 'abf88db8', 'phabricator-slowvote-css' => '1694baed', 'phabricator-source-code-view-css' => '03d7ac28', 'phabricator-standard-page-view' => '8a295cb9', 'phabricator-textareautils' => 'f340a484', 'phabricator-title' => '43bc9360', 'phabricator-tooltip' => '83754533', 'phabricator-ui-example-css' => 'b4795059', 'phabricator-zindex-css' => '99c0f5eb', 'phame-css' => '799febf9', 'pholio-css' => '88ef5ef1', 'pholio-edit-css' => '4df55b3b', 'pholio-inline-comments-css' => '722b48c2', 'phortune-credit-card-form' => 'd12d214f', 'phortune-credit-card-form-css' => '3b9868a8', 'phortune-css' => '12e8251a', 'phortune-invoice-css' => '4436b241', 'phrequent-css' => 'bd79cc67', 'phriction-document-css' => '03380da0', 'phui-action-panel-css' => '6c386cbf', 'phui-badge-view-css' => '666e25ad', 'phui-basic-nav-view-css' => '56ebd66d', 'phui-big-info-view-css' => '362ad37b', 'phui-box-css' => '5ed3b8cb', 'phui-bulk-editor-css' => '374d5e30', 'phui-button-bar-css' => 'a4aa75c4', 'phui-button-css' => 'ea704902', 'phui-button-simple-css' => '1ff278aa', 'phui-calendar-css' => 'f11073aa', 'phui-calendar-day-css' => '9597d706', 'phui-calendar-list-css' => 'ccd7e4e2', 'phui-calendar-month-css' => 'cb758c42', 'phui-chart-css' => '7853a69b', 'phui-cms-css' => '8c05c41e', 'phui-comment-form-css' => '68a2d99a', 'phui-comment-panel-css' => 'ec4e31c0', 'phui-crumbs-view-css' => '614f43cf', 'phui-curtain-view-css' => '68c5efb6', 'phui-document-summary-view-css' => 'b068eed1', 'phui-document-view-css' => '52b748a5', 'phui-document-view-pro-css' => 'b9613a10', 'phui-feed-story-css' => 'a0c05029', 'phui-font-icon-base-css' => 'd7994e06', 'phui-fontkit-css' => '9b714a5e', 'phui-form-css' => '159e2d9c', 'phui-form-view-css' => '0807e7ac', 'phui-head-thing-view-css' => 'd7f293df', 'phui-header-view-css' => '93cea4ec', 'phui-hovercard' => '074f0783', 'phui-hovercard-view-css' => '6ca90fa0', 'phui-icon-set-selector-css' => '7aa5f3ec', - 'phui-icon-view-css' => '281f964d', + 'phui-icon-view-css' => '4cbc684a', 'phui-image-mask-css' => '62c7f4d2', 'phui-info-view-css' => '37b8d9ce', 'phui-inline-comment-view-css' => '48acce5b', 'phui-invisible-character-view-css' => 'c694c4a4', 'phui-left-right-css' => '68513c34', 'phui-lightbox-css' => '4ebf22da', 'phui-list-view-css' => '470b1adb', 'phui-object-box-css' => '9b58483d', 'phui-oi-big-ui-css' => '9e037c7a', 'phui-oi-color-css' => 'b517bfa0', 'phui-oi-drag-ui-css' => 'da15d3dc', 'phui-oi-flush-ui-css' => '490e2e2e', 'phui-oi-list-view-css' => '909f3844', 'phui-oi-simple-ui-css' => '6a30fa46', 'phui-pager-css' => 'd022c7ad', 'phui-pinboard-view-css' => '1f08f5d8', 'phui-property-list-view-css' => 'cad62236', 'phui-remarkup-preview-css' => '91767007', 'phui-segment-bar-view-css' => '5166b370', 'phui-spacing-css' => 'b05cadc3', 'phui-status-list-view-css' => 'e5ff8be0', 'phui-tag-view-css' => 'a42fe34f', 'phui-theme-css' => '35883b37', 'phui-timeline-view-css' => '1e348e4b', 'phui-two-column-view-css' => '01e6991e', 'phui-workboard-color-css' => 'e86de308', 'phui-workboard-view-css' => '74fc9d98', 'phui-workcard-view-css' => '8c536f90', 'phui-workpanel-view-css' => 'bd546a49', 'phuix-action-list-view' => 'c68f183f', 'phuix-action-view' => 'aaa08f3b', 'phuix-autocomplete' => '58cc4ab8', 'phuix-button-view' => '55a24e84', 'phuix-dropdown-menu' => 'bdce4d78', 'phuix-form-control-view' => '38c1f3fb', 'phuix-icon-view' => 'a5257c4e', 'policy-css' => 'ceb56a08', 'policy-edit-css' => '8794e2ed', 'policy-transaction-detail-css' => 'c02b8384', 'ponder-view-css' => '05a09d0a', 'project-card-view-css' => '3b1f7b20', 'project-view-css' => '567858b3', 'releeph-core' => 'f81ff2db', 'releeph-preview-branch' => '22db5c07', 'releeph-request-differential-create-dialog' => '0ac1ea31', 'releeph-request-typeahead-css' => 'bce37359', 'setup-issue-css' => '5eed85b2', 'sprite-login-css' => '18b368a6', 'sprite-tokens-css' => 'f1896dc5', 'syntax-default-css' => '055fc231', 'syntax-highlighting-css' => '8a16f91b', 'tokens-css' => 'ce5a50bd', 'typeahead-browse-css' => 'b7ed02d2', 'unhandled-exception-css' => '9da8fdab', ), 'requires' => array( '01384686' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), '022516b4' => array( 'javelin-install', 'javelin-util', 'javelin-websocket', 'javelin-leader', 'javelin-json', ), '02cb4398' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), '030b4f7a' => array( 'javelin-stratcom', 'javelin-install', 'javelin-uri', 'javelin-util', ), '04f8a1e3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', ), '05c74d65' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'javelin-workboard-controller', ), '05d290ef' => array( 'javelin-install', 'javelin-util', ), '070679fe' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-uri', 'phabricator-notification', ), '074f0783' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-request', 'javelin-uri', ), '076bd092' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '0889b835' => array( 'javelin-install', 'javelin-event', 'javelin-util', 'javelin-magical-init', ), '0922e81d' => array( 'herald-rule-editor', 'javelin-behavior', ), '09ecf50c' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), '0ad8d31f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '0cf79f45' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', 'javelin-install', ), '0d2490ce' => array( 'javelin-install', ), '0e6d261f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), '0eaa33a9' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'javelin-workflow', 'phuix-icon-view', ), '1325b731' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-keyboard-shortcut', ), '1c850a26' => array( 'javelin-install', 'javelin-util', ), '1c88f154' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '1cab0e9a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-mask', 'phabricator-drag-and-drop-file-upload', ), '1cb7d027' => array( 'javelin-behavior', 'javelin-typeahead-ondemand-source', 'javelin-typeahead', 'javelin-dom', 'javelin-uri', 'javelin-util', 'javelin-stratcom', 'phabricator-prefab', 'phuix-icon-view', ), '1e413dc9' => array( 'javelin-behavior', 'javelin-dom', ), '1ff278aa' => array( 'phui-button-css', ), '202a2e85' => array( 'javelin-install', 'javelin-reactornode', 'javelin-util', 'javelin-reactor', ), '202bfa3f' => array( 'javelin-behavior', 'javelin-request', ), '225bbb98' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', ), '22ee68a5' => array( 'javelin-install', 'javelin-typeahead-source', 'javelin-util', ), 23387297 => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), 23631304 => array( 'phui-fontkit-css', ), '242aa08b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '242dedd0' => array( 'javelin-stratcom', 'javelin-behavior', 'javelin-vector', 'javelin-dom', ), '243d6c22' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '2539f834' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-json', 'phabricator-draggable-list', ), '27daef73' => array( 'multirow-row-manager', 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-json', 'phabricator-prefab', ), '289bf236' => array( 'javelin-install', 'javelin-util', ), '29819b75' => array( 'phabricator-notification', 'javelin-stratcom', 'javelin-behavior', ), '2a8b62d9' => array( 'multirow-row-manager', 'javelin-install', 'path-typeahead', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'phuix-form-control-view', ), '2bdadf1a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', 'phabricator-shaped-request', ), '2cc87f49' => array( 'javelin-behavior', 'javelin-workflow', 'javelin-json', 'javelin-dom', 'phabricator-keyboard-shortcut', ), '2e255291' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', ), '2f1db1ed' => array( 'javelin-util', ), '2f80333f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-phtize', 'phabricator-textareautils', 'javelin-workflow', 'javelin-vector', 'phuix-autocomplete', 'javelin-mask', ), '308f9fe4' => array( 'javelin-install', 'javelin-util', ), '32755edb' => array( 'javelin-install', 'javelin-util', ), 34450586 => array( 'javelin-color', 'javelin-install', 'javelin-util', ), '34c53422' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', ), '37b8a04a' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), '3829a3cf' => array( 'javelin-behavior', 'javelin-uri', ), '38a6cedb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '38c1f3fb' => array( 'javelin-install', 'javelin-dom', ), '3b4899b0' => array( 'javelin-behavior', 'phabricator-prefab', ), '3c6bd549' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'javelin-vector', 'javelin-magical-init', ), '3dc5ad43' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', ), '3eed1f2b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', 'javelin-quicksand', 'phabricator-phtize', 'phabricator-drag-and-drop-file-upload', 'phabricator-draggable-list', ), '407ee861' => array( 'javelin-behavior', 'javelin-uri', ), '418f6684' => array( 'javelin-behavior', 'javelin-dom', ), '42c7a5a7' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'phabricator-drag-and-drop-file-upload', 'javelin-workboard-board', ), '4370900d' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-dom', 'javelin-uri', 'phabricator-file-upload', ), '43ba89a2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-notification', 'conpherence-thread-manager', ), '43bc9360' => array( 'javelin-install', ), '45d0b2b1' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', 'javelin-workboard-column', ), '46116c01' => array( 'javelin-request', 'javelin-behavior', 'javelin-dom', 'javelin-router', 'javelin-util', 'phabricator-busy', ), '47a0728b' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', ), '4842f137' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '48fe33d0' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'javelin-uri', ), '490e2e2e' => array( 'phui-oi-list-view-css', ), '4a7fb02b' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), '4ae58b5a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', 'conpherence-thread-manager', ), '4b671572' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', ), '4dffaeb2' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phuix-form-control-view', 'phuix-icon-view', 'javelin-behavior-phabricator-gesture', ), '4e61fa88' => 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', ), '506aa3f4' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5202e831' => array( 'javelin-install', 'javelin-dom', 'javelin-fx', ), '541f81c3' => array( 'javelin-install', ), '55a24e84' => array( 'javelin-install', 'javelin-dom', ), '55d7b788' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5803b9e7' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', 'javelin-typeahead-static-source', ), '58cc4ab8' => array( 'javelin-install', 'javelin-dom', 'phuix-icon-view', 'phabricator-prefab', ), '5902260c' => array( 'javelin-util', 'javelin-magical-init', ), '5a6f6a06' => array( 'javelin-behavior', 'javelin-quicksand', ), '5a79f6c3' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), '5aa1544e' => 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', ), '5b54c823' => array( 'javelin-install', 'javelin-stratcom', 'javelin-dom', 'javelin-util', ), '5cf0501a' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), '600f440c' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-busy', ), '60cd9241' => array( 'javelin-behavior', ), '65bb0011' => array( 'javelin-behavior', 'javelin-dom', ), '66365ee2' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '6a1583a8' => array( 'javelin-behavior', 'javelin-history', ), '6a162524' => array( 'javelin-behavior', 'javelin-dom', ), '6a18c42e' => array( 'javelin-install', ), '6a30fa46' => array( 'phui-oi-list-view-css', ), '6a85bc5a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-magical-init', ), '6c379000' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'phui-hovercard', ), '6cfa0008' => array( 'javelin-dom', 'javelin-dynval', 'javelin-reactor', 'javelin-reactornode', 'javelin-install', 'javelin-util', ), 70245195 => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '727a5a61' => array( 'phuix-icon-view', ), '72960bc1' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', 'javelin-reactor-node-calmer', ), '7353f43d' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', ), 73660575 => array( 'phui-inline-comment-view-css', ), '73ecc1f8' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'phabricator-tooltip', ), '740956e1' => array( 'javelin-util', 'javelin-uri', 'javelin-install', ), 74446546 => array( 'javelin-behavior', 'javelin-dom', ), '75184d68' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-request', ), '78bc5d94' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), '78f811c9' => array( 'javelin-install', ), '7930776a' => array( 'javelin-install', 'javelin-dom', ), '7ad020a5' => array( 'javelin-behavior', 'javelin-dom', 'phabricator-drag-and-drop-file-upload', 'phabricator-textareautils', ), '7b139193' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '7c4d8998' => array( 'javelin-install', 'javelin-dom', ), '80bff3af' => array( 'javelin-install', 'javelin-typeahead-source', ), 83754533 => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', ), '8400307c' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '8573dc1b' => array( 'javelin-install', 'javelin-workboard-card', ), '87428eb2' => array( 'javelin-behavior', 'javelin-diffusion-locate-file-source', 'javelin-dom', 'javelin-typeahead', 'javelin-uri', ), '876506b6' => array( 'javelin-view', 'javelin-install', 'javelin-dom', ), '89a1ae3a' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', ), '8a16f91b' => array( 'syntax-default-css', ), '8ac32fd9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '8badee71' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-typeahead-normalizer', ), '8c2ed2bf' => 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', ), '8e2d9a28' => array( 'phui-theme-css', ), '8f959ad0' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', ), 91863989 => array( 'javelin-install', 'javelin-stratcom', 'javelin-util', 'javelin-behavior', 'javelin-json', 'javelin-dom', 'javelin-resource', 'javelin-routable', ), '91befbcc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', ), '92388bae' => array( 'javelin-behavior', 'javelin-scrollbar', ), '925fe8cd' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '92cdd7b6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '9347f172' => array( 'javelin-behavior', 'multirow-row-manager', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'javelin-json', ), '94243d89' => array( 'javelin-install', 'javelin-dom', 'javelin-typeahead-preloaded-source', 'javelin-util', ), '94681e22' => array( 'javelin-magical-init', 'javelin-install', 'javelin-util', 'javelin-vector', 'javelin-stratcom', ), '956f3eeb' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), '958e9045' => array( 'javelin-stratcom', 'javelin-request', 'javelin-dom', 'javelin-vector', 'javelin-install', 'javelin-util', 'javelin-mask', 'javelin-uri', 'javelin-routable', ), '9623adc1' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-router', ), '9a513421' => array( 'javelin-install', ), '9aae2b66' => array( 'javelin-install', 'javelin-util', ), '9b1cbd76' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '9cec214e' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-uri', 'phabricator-textareautils', ), '9e037c7a' => array( 'phui-oi-list-view-css', ), '9f081f05' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-keyboard-shortcut', ), 'a17b84f1' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), 'a241536a' => array( 'javelin-install', ), 'a4356cde' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-util', ), 'a43ae2ae' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), 'a4a14a94' => array( 'javelin-dom', ), 'a4aa75c4' => array( 'phui-button-css', 'phui-button-simple-css', ), 'a4af0b4a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', 'javelin-util', ), 'a5257c4e' => array( 'javelin-install', 'javelin-dom', ), 'a9942052' => array( 'javelin-behavior', 'javelin-dom', 'javelin-view-renderer', 'javelin-install', ), 'a9b91e3f' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'phabricator-notification-css', ), 'aa371860' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'aa3a100c' => array( 'javelin-behavior', 'javelin-dom', 'javelin-typeahead', 'javelin-typeahead-ondemand-source', 'javelin-dom', ), 'aa6d2308' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'multirow-row-manager', 'javelin-json', 'phuix-form-control-view', ), 'aaa08f3b' => array( 'javelin-install', 'javelin-dom', 'javelin-util', ), 'ab85e184' => array( 'javelin-install', 'javelin-dom', 'phabricator-notification', ), 'abf88db8' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-router', ), 'ad486db3' => array( 'javelin-install', 'javelin-typeahead', 'javelin-dom', 'javelin-request', 'javelin-typeahead-ondemand-source', 'javelin-util', ), 'aec8e38c' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-aphlict', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', ), 'b105a3a6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'b26a41e4' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'b347a301' => array( 'javelin-behavior', ), 'b517bfa0' => array( 'phui-oi-list-view-css', ), 'b52d0668' => array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), 'b58d1a2a' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-magical-init', ), 'b5e9bff9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'b7b73831' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'b86f297f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'b9109f8f' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'b91204e9' => array( 'javelin-install', 'phuix-button-view', ), 'bd546a49' => array( 'phui-workcard-view-css', ), 'bdce4d78' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', 'javelin-stratcom', ), 'bf457520' => 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', ), 'c03f2fb4' => array( 'javelin-install', ), 'c2c500a7' => array( 'javelin-install', 'javelin-dom', 'phuix-button-view', ), 'c3703a16' => array( 'javelin-behavior', 'javelin-aphlict', 'phabricator-phtize', 'javelin-dom', ), 'c687e867' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-fx', 'javelin-util', ), 'c68f183f' => array( 'javelin-install', 'javelin-dom', ), 'c715c123' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-json', ), 'c7e748bf' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-mask', 'javelin-util', 'phuix-icon-view', 'phabricator-busy', ), 'c8147a20' => array( 'javelin-behavior', 'javelin-dom', 'javelin-vector', 'phui-chart-css', ), 'c9749dcd' => array( 'javelin-install', 'javelin-util', 'phabricator-keyboard-shortcut-manager', ), 'cf32921f' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'cffd39b4' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-util', ), 'd12d214f' => array( 'javelin-install', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-util', ), 'd3799cb4' => array( 'javelin-install', ), 'd8a86cfb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'da15d3dc' => array( 'phui-oi-list-view-css', ), 'dae2d55b' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'db0c0214' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-uri', ), 'dfa1d313' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-tooltip', 'phabricator-diff-changeset-list', 'phabricator-diff-changeset', ), 'e150bd50' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), 'e15c8b1f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-history', ), 'e18685c0' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'e562708c' => array( 'javelin-install', ), 'e5bdb730' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'e7cf10d6' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', 'phabricator-diff-inline', ), 'e8240b50' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'e9a2940f' => array( 'javelin-behavior', 'javelin-request', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', 'javelin-behavior-device', 'phabricator-title', 'phabricator-favicon', ), 'e9c80beb' => array( 'javelin-install', 'javelin-event', ), 'ec4e31c0' => array( 'phui-timeline-view-css', ), 'ee77366f' => array( 'aphront-dialog-view-css', ), 'ee82cedb' => array( 'javelin-behavior', 'phabricator-keyboard-shortcut', 'javelin-stratcom', ), 'f166c949' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-dom', 'javelin-magical-init', 'javelin-vector', 'javelin-request', 'javelin-util', ), 'f340a484' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', ), 'f39d968b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-util', 'javelin-dom', 'javelin-request', 'phabricator-keyboard-shortcut', 'phabricator-darklog', 'phabricator-darkmessage', ), 'f51e9c17' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'f5c78ae3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'f8c4e135' => array( 'javelin-install', 'javelin-dom', 'javelin-view-visitor', 'javelin-util', ), 'fa6f30b2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-behavior-device', 'javelin-scrollbar', 'javelin-quicksand', 'phabricator-keyboard-shortcut', 'conpherence-thread-manager', ), 'fce5d170' => array( 'javelin-magical-init', 'javelin-util', ), 'fdc13e4e' => array( 'javelin-install', ), 'ff688a7a' => array( 'owners-path-editor', 'javelin-behavior', ), ), 'packages' => array( 'conpherence.pkg.css' => array( 'conpherence-durable-column-view', 'conpherence-menu-css', 'conpherence-color-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-button-simple-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-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', 'phabricator-action-list-view-css', 'phui-property-list-view-css', 'phui-tag-view-css', 'phui-list-view-css', 'font-fontawesome', 'font-lato', '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-sound', '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', 'javelin-behavior-aphlict-status', 'javelin-behavior-user-menu', 'phabricator-favicon', ), '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-populate', 'javelin-behavior-differential-diff-radios', 'javelin-behavior-aphront-drag-and-drop-textarea', 'javelin-behavior-phabricator-object-selector', 'javelin-behavior-repository-crossreference', 'javelin-behavior-differential-user-select', 'javelin-behavior-aphront-more', 'phabricator-diff-inline', 'phabricator-diff-changeset', 'phabricator-diff-changeset-list', ), '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/sql/autopatches/20190206.external.01.legalpad.sql b/resources/sql/autopatches/20190206.external.01.legalpad.sql new file mode 100644 index 0000000000..8afa9dd9ff --- /dev/null +++ b/resources/sql/autopatches/20190206.external.01.legalpad.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_legalpad.legalpad_documentsignature + SET signerPHID = NULL WHERE signerPHID LIKE 'PHID-XUSR-%'; diff --git a/resources/sql/autopatches/20190206.external.02.email.sql b/resources/sql/autopatches/20190206.external.02.email.sql new file mode 100644 index 0000000000..14f5f4791f --- /dev/null +++ b/resources/sql/autopatches/20190206.external.02.email.sql @@ -0,0 +1,2 @@ +DELETE FROM {$NAMESPACE}_user.user_externalaccount + WHERE accountType = 'email'; diff --git a/resources/sql/autopatches/20190207.packages.01.state.sql b/resources/sql/autopatches/20190207.packages.01.state.sql new file mode 100644 index 0000000000..0e74f269ba --- /dev/null +++ b/resources/sql/autopatches/20190207.packages.01.state.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_owners.owners_package + ADD auditingState VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/resources/sql/autopatches/20190207.packages.02.migrate.sql b/resources/sql/autopatches/20190207.packages.02.migrate.sql new file mode 100644 index 0000000000..60bf364ac1 --- /dev/null +++ b/resources/sql/autopatches/20190207.packages.02.migrate.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_owners.owners_package + SET auditingState = IF(auditingEnabled = 0, 'none', 'audit'); diff --git a/resources/sql/autopatches/20190207.packages.03.drop.sql b/resources/sql/autopatches/20190207.packages.03.drop.sql new file mode 100644 index 0000000000..24d0ce1a4f --- /dev/null +++ b/resources/sql/autopatches/20190207.packages.03.drop.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_owners.owners_package + DROP auditingEnabled; diff --git a/resources/sql/autopatches/20190207.packages.04.xactions.php b/resources/sql/autopatches/20190207.packages.04.xactions.php new file mode 100644 index 0000000000..5a8609166e --- /dev/null +++ b/resources/sql/autopatches/20190207.packages.04.xactions.php @@ -0,0 +1,41 @@ +establishConnection('w'); +$iterator = new LiskRawMigrationIterator($conn, $table->getTableName()); + +// Migrate "Auditing State" transactions for Owners Packages from old values +// (which were "0" or "1", as JSON integer literals, without quotes) to new +// values (which are JSON strings, with quotes). + +foreach ($iterator as $row) { + if ($row['transactionType'] !== 'owners.auditing') { + continue; + } + + $old_value = (int)$row['oldValue']; + $new_value = (int)$row['newValue']; + + if (!$old_value) { + $old_value = 'none'; + } else { + $old_value = 'audit'; + } + + if (!$new_value) { + $new_value = 'none'; + } else { + $new_value = 'audit'; + } + + $old_value = phutil_json_encode($old_value); + $new_value = phutil_json_encode($new_value); + + queryfx( + $conn, + 'UPDATE %R SET oldValue = %s, newValue = %s WHERE id = %d', + $table, + $old_value, + $new_value, + $row['id']); +} diff --git a/resources/sql/patches/133.imagemacro.sql b/resources/sql/patches/133.imagemacro.sql index 01852c6b48..1477fd879f 100644 --- a/resources/sql/patches/133.imagemacro.sql +++ b/resources/sql/patches/133.imagemacro.sql @@ -1,2 +1,2 @@ -ALTER IGNORE TABLE `{$NAMESPACE}_file`.`file_imagemacro` - ADD UNIQUE `name` (`name`); +ALTER TABLE `{$NAMESPACE}_file`.`file_imagemacro` + ADD UNIQUE KEY `name` (`name`); diff --git a/resources/sql/patches/20130611.migrateoauth.php b/resources/sql/patches/20130611.migrateoauth.php index 3622b2772e..92fe854cfd 100644 --- a/resources/sql/patches/20130611.migrateoauth.php +++ b/resources/sql/patches/20130611.migrateoauth.php @@ -1,66 +1,14 @@ establishConnection('w'); $table_name = 'user_oauthinfo'; -$conn_w = $table->establishConnection('w'); - -$xaccount = new PhabricatorExternalAccount(); - -echo pht('Migrating OAuth to %s...', 'ExternalAccount')."\n"; -$domain_map = array( - 'disqus' => 'disqus.com', - 'facebook' => 'facebook.com', - 'github' => 'github.com', - 'google' => 'google.com', -); - -try { - $phabricator_oauth_uri = new PhutilURI( - PhabricatorEnv::getEnvConfig('phabricator.oauth-uri')); - $domain_map['phabricator'] = $phabricator_oauth_uri->getDomain(); -} catch (Exception $ex) { - // Ignore; this likely indicates that we have removed `phabricator.oauth-uri` - // in some future diff. +foreach (new LiskRawMigrationIterator($conn, $table_name) as $row) { + throw new Exception( + pht( + 'Your Phabricator install has ancient OAuth account data and is '. + 'too old to upgrade directly to a modern version of Phabricator. '. + 'Upgrade to a version released between June 2013 and February 2019 '. + 'first, then upgrade to a modern version.')); } - -$rows = queryfx_all( - $conn_w, - 'SELECT * FROM user_oauthinfo'); -foreach ($rows as $row) { - echo pht('Migrating row ID #%d.', $row['id'])."\n"; - $user = id(new PhabricatorUser())->loadOneWhere( - 'id = %d', - $row['userID']); - if (!$user) { - echo pht('Bad user ID!')."\n"; - continue; - } - - $domain = idx($domain_map, $row['oauthProvider']); - if (empty($domain)) { - echo pht('Unknown OAuth provider!')."\n"; - continue; - } - - - $xaccount = id(new PhabricatorExternalAccount()) - ->setUserPHID($user->getPHID()) - ->setAccountType($row['oauthProvider']) - ->setAccountDomain($domain) - ->setAccountID($row['oauthUID']) - ->setAccountURI($row['accountURI']) - ->setUsername($row['accountName']) - ->setDateCreated($row['dateCreated']); - - try { - $xaccount->save(); - } catch (Exception $ex) { - phlog($ex); - } -} - -echo pht('Done.')."\n"; diff --git a/resources/sql/patches/20130611.nukeldap.php b/resources/sql/patches/20130611.nukeldap.php index 3f225cfa84..0f0b976a58 100644 --- a/resources/sql/patches/20130611.nukeldap.php +++ b/resources/sql/patches/20130611.nukeldap.php @@ -1,41 +1,14 @@ establishConnection('w'); $table_name = 'user_ldapinfo'; -$conn_w = $table->establishConnection('w'); - -$xaccount = new PhabricatorExternalAccount(); - -echo pht('Migrating LDAP to %s...', 'ExternalAccount')."\n"; - -$rows = queryfx_all($conn_w, 'SELECT * FROM %T', $table_name); -foreach ($rows as $row) { - echo pht('Migrating row ID #%d.', $row['id'])."\n"; - $user = id(new PhabricatorUser())->loadOneWhere( - 'id = %d', - $row['userID']); - if (!$user) { - echo pht('Bad user ID!')."\n"; - continue; - } - - $xaccount = id(new PhabricatorExternalAccount()) - ->setUserPHID($user->getPHID()) - ->setAccountType('ldap') - ->setAccountDomain('self') - ->setAccountID($row['ldapUsername']) - ->setUsername($row['ldapUsername']) - ->setDateCreated($row['dateCreated']); - - try { - $xaccount->save(); - } catch (Exception $ex) { - phlog($ex); - } +foreach (new LiskRawMigrationIterator($conn, $table_name) as $row) { + throw new Exception( + pht( + 'Your Phabricator install has ancient LDAP account data and is '. + 'too old to upgrade directly to a modern version of Phabricator. '. + 'Upgrade to a version released between June 2013 and February 2019 '. + 'first, then upgrade to a modern version.')); } - -echo pht('Done.')."\n"; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 324fc3c5de..b704a7cc2e 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,11722 +1,11732 @@ 2, 'class' => array( 'AlmanacAddress' => 'applications/almanac/util/AlmanacAddress.php', 'AlmanacBinding' => 'applications/almanac/storage/AlmanacBinding.php', 'AlmanacBindingDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacBindingDeletePropertyTransaction.php', 'AlmanacBindingDisableController' => 'applications/almanac/controller/AlmanacBindingDisableController.php', 'AlmanacBindingDisableTransaction' => 'applications/almanac/xaction/AlmanacBindingDisableTransaction.php', 'AlmanacBindingEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacBindingEditConduitAPIMethod.php', 'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php', 'AlmanacBindingEditEngine' => 'applications/almanac/editor/AlmanacBindingEditEngine.php', 'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php', 'AlmanacBindingInterfaceTransaction' => 'applications/almanac/xaction/AlmanacBindingInterfaceTransaction.php', 'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php', 'AlmanacBindingPropertyEditEngine' => 'applications/almanac/editor/AlmanacBindingPropertyEditEngine.php', 'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php', 'AlmanacBindingSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacBindingSearchConduitAPIMethod.php', 'AlmanacBindingSearchEngine' => 'applications/almanac/query/AlmanacBindingSearchEngine.php', 'AlmanacBindingServiceTransaction' => 'applications/almanac/xaction/AlmanacBindingServiceTransaction.php', 'AlmanacBindingSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacBindingSetPropertyTransaction.php', 'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php', 'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php', 'AlmanacBindingTransactionQuery' => 'applications/almanac/query/AlmanacBindingTransactionQuery.php', 'AlmanacBindingTransactionType' => 'applications/almanac/xaction/AlmanacBindingTransactionType.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', 'AlmanacDeletePropertyEditField' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditField.php', 'AlmanacDeletePropertyEditType' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditType.php', 'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php', 'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php', 'AlmanacDeviceDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceDeletePropertyTransaction.php', 'AlmanacDeviceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceEditConduitAPIMethod.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', 'AlmanacDeviceNameTransaction' => 'applications/almanac/xaction/AlmanacDeviceNameTransaction.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', 'AlmanacDeviceSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceSetPropertyTransaction.php', 'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php', 'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php', 'AlmanacDeviceTransactionType' => 'applications/almanac/xaction/AlmanacDeviceTransactionType.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', 'AlmanacInterfaceAddressTransaction' => 'applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php', 'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php', 'AlmanacInterfaceDeleteController' => 'applications/almanac/controller/AlmanacInterfaceDeleteController.php', 'AlmanacInterfaceDestroyTransaction' => 'applications/almanac/xaction/AlmanacInterfaceDestroyTransaction.php', 'AlmanacInterfaceDeviceTransaction' => 'applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php', 'AlmanacInterfaceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacInterfaceEditConduitAPIMethod.php', 'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php', 'AlmanacInterfaceEditEngine' => 'applications/almanac/editor/AlmanacInterfaceEditEngine.php', 'AlmanacInterfaceEditor' => 'applications/almanac/editor/AlmanacInterfaceEditor.php', 'AlmanacInterfaceNetworkTransaction' => 'applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php', 'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php', 'AlmanacInterfacePortTransaction' => 'applications/almanac/xaction/AlmanacInterfacePortTransaction.php', 'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php', 'AlmanacInterfaceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacInterfaceSearchConduitAPIMethod.php', 'AlmanacInterfaceSearchEngine' => 'applications/almanac/query/AlmanacInterfaceSearchEngine.php', 'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php', 'AlmanacInterfaceTransaction' => 'applications/almanac/storage/AlmanacInterfaceTransaction.php', 'AlmanacInterfaceTransactionType' => 'applications/almanac/xaction/AlmanacInterfaceTransactionType.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', 'AlmanacModularTransaction' => 'applications/almanac/storage/AlmanacModularTransaction.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', 'AlmanacNamespaceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNamespaceEditConduitAPIMethod.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', 'AlmanacNamespaceNameTransaction' => 'applications/almanac/xaction/AlmanacNamespaceNameTransaction.php', 'AlmanacNamespacePHIDType' => 'applications/almanac/phid/AlmanacNamespacePHIDType.php', 'AlmanacNamespaceQuery' => 'applications/almanac/query/AlmanacNamespaceQuery.php', 'AlmanacNamespaceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNamespaceSearchConduitAPIMethod.php', 'AlmanacNamespaceSearchEngine' => 'applications/almanac/query/AlmanacNamespaceSearchEngine.php', 'AlmanacNamespaceTransaction' => 'applications/almanac/storage/AlmanacNamespaceTransaction.php', 'AlmanacNamespaceTransactionQuery' => 'applications/almanac/query/AlmanacNamespaceTransactionQuery.php', 'AlmanacNamespaceTransactionType' => 'applications/almanac/xaction/AlmanacNamespaceTransactionType.php', 'AlmanacNamespaceViewController' => 'applications/almanac/controller/AlmanacNamespaceViewController.php', 'AlmanacNetwork' => 'applications/almanac/storage/AlmanacNetwork.php', 'AlmanacNetworkController' => 'applications/almanac/controller/AlmanacNetworkController.php', 'AlmanacNetworkEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNetworkEditConduitAPIMethod.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', 'AlmanacNetworkNameTransaction' => 'applications/almanac/xaction/AlmanacNetworkNameTransaction.php', 'AlmanacNetworkPHIDType' => 'applications/almanac/phid/AlmanacNetworkPHIDType.php', 'AlmanacNetworkQuery' => 'applications/almanac/query/AlmanacNetworkQuery.php', 'AlmanacNetworkSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNetworkSearchConduitAPIMethod.php', 'AlmanacNetworkSearchEngine' => 'applications/almanac/query/AlmanacNetworkSearchEngine.php', 'AlmanacNetworkTransaction' => 'applications/almanac/storage/AlmanacNetworkTransaction.php', 'AlmanacNetworkTransactionQuery' => 'applications/almanac/query/AlmanacNetworkTransactionQuery.php', 'AlmanacNetworkTransactionType' => 'applications/almanac/xaction/AlmanacNetworkTransactionType.php', 'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php', 'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php', 'AlmanacPropertiesEditEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesEditEngineExtension.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', 'AlmanacServiceDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacServiceDeletePropertyTransaction.php', 'AlmanacServiceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacServiceEditConduitAPIMethod.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', 'AlmanacServiceNameTransaction' => 'applications/almanac/xaction/AlmanacServiceNameTransaction.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', 'AlmanacServiceSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacServiceSetPropertyTransaction.php', 'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php', 'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php', 'AlmanacServiceTransactionType' => 'applications/almanac/xaction/AlmanacServiceTransactionType.php', 'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php', 'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php', 'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php', 'AlmanacServiceTypeTransaction' => 'applications/almanac/xaction/AlmanacServiceTypeTransaction.php', 'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php', 'AlmanacSetPropertyEditField' => 'applications/almanac/engineextension/AlmanacSetPropertyEditField.php', 'AlmanacSetPropertyEditType' => 'applications/almanac/engineextension/AlmanacSetPropertyEditType.php', 'AlmanacTransactionType' => 'applications/almanac/xaction/AlmanacTransactionType.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', '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', 'BulkParameterType' => 'applications/transactions/bulk/type/BulkParameterType.php', 'BulkPointsParameterType' => 'applications/transactions/bulk/type/BulkPointsParameterType.php', 'BulkRemarkupParameterType' => 'applications/transactions/bulk/type/BulkRemarkupParameterType.php', 'BulkSelectParameterType' => 'applications/transactions/bulk/type/BulkSelectParameterType.php', 'BulkStringParameterType' => 'applications/transactions/bulk/type/BulkStringParameterType.php', 'BulkTokenizerParameterType' => 'applications/transactions/bulk/type/BulkTokenizerParameterType.php', 'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php', 'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php', 'CelerityAPI' => 'applications/celerity/CelerityAPI.php', 'CelerityDarkModePostprocessor' => 'applications/celerity/postprocessor/CelerityDarkModePostprocessor.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', 'CelerityRedGreenPostprocessor' => 'applications/celerity/postprocessor/CelerityRedGreenPostprocessor.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', 'ConduitConstantDescription' => 'applications/conduit/data/ConduitConstantDescription.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', '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', 'ConpherenceEditConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceEditConduitAPIMethod.php', 'ConpherenceEditEngine' => 'applications/conpherence/editor/ConpherenceEditEngine.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', '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', 'ConpherenceQueryThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryThreadConduitAPIMethod.php', 'ConpherenceQueryTransactionConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php', 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', 'ConpherenceRoomEditController' => 'applications/conpherence/controller/ConpherenceRoomEditController.php', 'ConpherenceRoomListController' => 'applications/conpherence/controller/ConpherenceRoomListController.php', 'ConpherenceRoomPictureController' => 'applications/conpherence/controller/ConpherenceRoomPictureController.php', 'ConpherenceRoomPreferencesController' => 'applications/conpherence/controller/ConpherenceRoomPreferencesController.php', 'ConpherenceRoomSettings' => 'applications/conpherence/constants/ConpherenceRoomSettings.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', 'ConpherenceThreadDateMarkerTransaction' => 'applications/conpherence/xaction/ConpherenceThreadDateMarkerTransaction.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', 'ConpherenceThreadParticipantsTransaction' => 'applications/conpherence/xaction/ConpherenceThreadParticipantsTransaction.php', 'ConpherenceThreadPictureTransaction' => 'applications/conpherence/xaction/ConpherenceThreadPictureTransaction.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', 'ConpherenceThreadTitleTransaction' => 'applications/conpherence/xaction/ConpherenceThreadTitleTransaction.php', 'ConpherenceThreadTopicTransaction' => 'applications/conpherence/xaction/ConpherenceThreadTopicTransaction.php', 'ConpherenceThreadTransactionType' => 'applications/conpherence/xaction/ConpherenceThreadTransactionType.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', 'CountdownEditConduitAPIMethod' => 'applications/countdown/conduit/CountdownEditConduitAPIMethod.php', 'CountdownSearchConduitAPIMethod' => 'applications/countdown/conduit/CountdownSearchConduitAPIMethod.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', 'DarkConsoleRealtimePlugin' => 'applications/console/plugin/DarkConsoleRealtimePlugin.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', 'DifferentialAdjustmentMapTestCase' => 'applications/differential/storage/__tests__/DifferentialAdjustmentMapTestCase.php', 'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php', 'DifferentialAsanaRepresentationField' => 'applications/differential/customfield/DifferentialAsanaRepresentationField.php', 'DifferentialAuditorsCommitMessageField' => 'applications/differential/field/DifferentialAuditorsCommitMessageField.php', 'DifferentialAuditorsField' => 'applications/differential/customfield/DifferentialAuditorsField.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', 'DifferentialBuildableEngine' => 'applications/differential/harbormaster/DifferentialBuildableEngine.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', 'DifferentialChangesetEngine' => 'applications/differential/engine/DifferentialChangesetEngine.php', 'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php', 'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php', 'DifferentialChangesetListController' => 'applications/differential/controller/DifferentialChangesetListController.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', 'DifferentialChangesetSearchEngine' => 'applications/differential/query/DifferentialChangesetSearchEngine.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', 'DifferentialCloseConduitAPIMethod' => 'applications/differential/conduit/DifferentialCloseConduitAPIMethod.php', 'DifferentialCommitMessageCustomField' => 'applications/differential/field/DifferentialCommitMessageCustomField.php', 'DifferentialCommitMessageField' => 'applications/differential/field/DifferentialCommitMessageField.php', 'DifferentialCommitMessageFieldTestCase' => 'applications/differential/field/__tests__/DifferentialCommitMessageFieldTestCase.php', 'DifferentialCommitMessageParser' => 'applications/differential/parser/DifferentialCommitMessageParser.php', 'DifferentialCommitMessageParserTestCase' => 'applications/differential/parser/__tests__/DifferentialCommitMessageParserTestCase.php', 'DifferentialCommitsField' => 'applications/differential/customfield/DifferentialCommitsField.php', 'DifferentialCommitsSearchEngineAttachment' => 'applications/differential/engineextension/DifferentialCommitsSearchEngineAttachment.php', 'DifferentialConduitAPIMethod' => 'applications/differential/conduit/DifferentialConduitAPIMethod.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', 'DifferentialDiffSearchConduitAPIMethod' => 'applications/differential/conduit/DifferentialDiffSearchConduitAPIMethod.php', 'DifferentialDiffSearchEngine' => 'applications/differential/query/DifferentialDiffSearchEngine.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', 'DifferentialDraftField' => 'applications/differential/customfield/DifferentialDraftField.php', 'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', 'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', 'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.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', 'DifferentialGitSVNIDCommitMessageField' => 'applications/differential/field/DifferentialGitSVNIDCommitMessageField.php', 'DifferentialHarbormasterField' => 'applications/differential/customfield/DifferentialHarbormasterField.php', 'DifferentialHeraldStateReasons' => 'applications/differential/herald/DifferentialHeraldStateReasons.php', 'DifferentialHiddenComment' => 'applications/differential/storage/DifferentialHiddenComment.php', 'DifferentialHostField' => 'applications/differential/customfield/DifferentialHostField.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', 'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php', 'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php', 'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php', 'DifferentialLegacyQuery' => 'applications/differential/constants/DifferentialLegacyQuery.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', 'DifferentialMailEngineExtension' => 'applications/differential/engineextension/DifferentialMailEngineExtension.php', 'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php', 'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.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', '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', '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', 'DifferentialReviewedByCommitMessageField' => 'applications/differential/field/DifferentialReviewedByCommitMessageField.php', 'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php', 'DifferentialReviewerDatasource' => 'applications/differential/typeahead/DifferentialReviewerDatasource.php', 'DifferentialReviewerForRevisionEdgeType' => 'applications/differential/edge/DifferentialReviewerForRevisionEdgeType.php', 'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php', 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingReviewersHeraldAction.php', 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddBlockingSelfHeraldAction.php', 'DifferentialReviewersAddReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddReviewersHeraldAction.php', 'DifferentialReviewersAddSelfHeraldAction' => 'applications/differential/herald/DifferentialReviewersAddSelfHeraldAction.php', 'DifferentialReviewersCommitMessageField' => 'applications/differential/field/DifferentialReviewersCommitMessageField.php', 'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php', 'DifferentialReviewersHeraldAction' => 'applications/differential/herald/DifferentialReviewersHeraldAction.php', 'DifferentialReviewersSearchEngineAttachment' => 'applications/differential/engineextension/DifferentialReviewersSearchEngineAttachment.php', 'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php', 'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php', 'DifferentialRevisionAbandonTransaction' => 'applications/differential/xaction/DifferentialRevisionAbandonTransaction.php', 'DifferentialRevisionAcceptTransaction' => 'applications/differential/xaction/DifferentialRevisionAcceptTransaction.php', 'DifferentialRevisionActionTransaction' => 'applications/differential/xaction/DifferentialRevisionActionTransaction.php', 'DifferentialRevisionAffectedFilesHeraldField' => 'applications/differential/herald/DifferentialRevisionAffectedFilesHeraldField.php', 'DifferentialRevisionAuthorHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorHeraldField.php', 'DifferentialRevisionAuthorProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionAuthorProjectsHeraldField.php', 'DifferentialRevisionBuildableTransaction' => 'applications/differential/xaction/DifferentialRevisionBuildableTransaction.php', 'DifferentialRevisionCloseDetailsController' => 'applications/differential/controller/DifferentialRevisionCloseDetailsController.php', 'DifferentialRevisionCloseTransaction' => 'applications/differential/xaction/DifferentialRevisionCloseTransaction.php', 'DifferentialRevisionClosedStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionClosedStatusDatasource.php', 'DifferentialRevisionCommandeerTransaction' => 'applications/differential/xaction/DifferentialRevisionCommandeerTransaction.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', 'DifferentialRevisionDraftEngine' => 'applications/differential/engine/DifferentialRevisionDraftEngine.php', 'DifferentialRevisionEditConduitAPIMethod' => 'applications/differential/conduit/DifferentialRevisionEditConduitAPIMethod.php', 'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', 'DifferentialRevisionEditEngine' => 'applications/differential/editor/DifferentialRevisionEditEngine.php', 'DifferentialRevisionFerretEngine' => 'applications/differential/search/DifferentialRevisionFerretEngine.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', 'DifferentialRevisionHoldDraftTransaction' => 'applications/differential/xaction/DifferentialRevisionHoldDraftTransaction.php', 'DifferentialRevisionIDCommitMessageField' => 'applications/differential/field/DifferentialRevisionIDCommitMessageField.php', 'DifferentialRevisionInlineTransaction' => 'applications/differential/xaction/DifferentialRevisionInlineTransaction.php', 'DifferentialRevisionInlinesController' => 'applications/differential/controller/DifferentialRevisionInlinesController.php', 'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php', 'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php', 'DifferentialRevisionMailReceiver' => 'applications/differential/mail/DifferentialRevisionMailReceiver.php', 'DifferentialRevisionOpenStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionOpenStatusDatasource.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', 'DifferentialRevisionPlanChangesTransaction' => 'applications/differential/xaction/DifferentialRevisionPlanChangesTransaction.php', 'DifferentialRevisionQuery' => 'applications/differential/query/DifferentialRevisionQuery.php', 'DifferentialRevisionReclaimTransaction' => 'applications/differential/xaction/DifferentialRevisionReclaimTransaction.php', 'DifferentialRevisionRejectTransaction' => 'applications/differential/xaction/DifferentialRevisionRejectTransaction.php', 'DifferentialRevisionRelationship' => 'applications/differential/relationships/DifferentialRevisionRelationship.php', 'DifferentialRevisionRelationshipSource' => 'applications/search/relationship/DifferentialRevisionRelationshipSource.php', 'DifferentialRevisionReopenTransaction' => 'applications/differential/xaction/DifferentialRevisionReopenTransaction.php', 'DifferentialRevisionRepositoryHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryHeraldField.php', 'DifferentialRevisionRepositoryProjectsHeraldField' => 'applications/differential/herald/DifferentialRevisionRepositoryProjectsHeraldField.php', 'DifferentialRevisionRepositoryTransaction' => 'applications/differential/xaction/DifferentialRevisionRepositoryTransaction.php', 'DifferentialRevisionRequestReviewTransaction' => 'applications/differential/xaction/DifferentialRevisionRequestReviewTransaction.php', 'DifferentialRevisionRequiredActionResultBucket' => 'applications/differential/query/DifferentialRevisionRequiredActionResultBucket.php', 'DifferentialRevisionResignTransaction' => 'applications/differential/xaction/DifferentialRevisionResignTransaction.php', 'DifferentialRevisionResultBucket' => 'applications/differential/query/DifferentialRevisionResultBucket.php', 'DifferentialRevisionReviewTransaction' => 'applications/differential/xaction/DifferentialRevisionReviewTransaction.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', 'DifferentialRevisionStatusDatasource' => 'applications/differential/typeahead/DifferentialRevisionStatusDatasource.php', 'DifferentialRevisionStatusFunctionDatasource' => 'applications/differential/typeahead/DifferentialRevisionStatusFunctionDatasource.php', 'DifferentialRevisionStatusHeraldField' => 'applications/differential/herald/DifferentialRevisionStatusHeraldField.php', 'DifferentialRevisionStatusTransaction' => 'applications/differential/xaction/DifferentialRevisionStatusTransaction.php', 'DifferentialRevisionSummaryHeraldField' => 'applications/differential/herald/DifferentialRevisionSummaryHeraldField.php', 'DifferentialRevisionSummaryTransaction' => 'applications/differential/xaction/DifferentialRevisionSummaryTransaction.php', 'DifferentialRevisionTestPlanHeraldField' => 'applications/differential/herald/DifferentialRevisionTestPlanHeraldField.php', 'DifferentialRevisionTestPlanTransaction' => 'applications/differential/xaction/DifferentialRevisionTestPlanTransaction.php', 'DifferentialRevisionTimelineEngine' => 'applications/differential/engine/DifferentialRevisionTimelineEngine.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', 'DifferentialRevisionUpdateTransaction' => 'applications/differential/xaction/DifferentialRevisionUpdateTransaction.php', 'DifferentialRevisionViewController' => 'applications/differential/controller/DifferentialRevisionViewController.php', 'DifferentialRevisionVoidTransaction' => 'applications/differential/xaction/DifferentialRevisionVoidTransaction.php', 'DifferentialRevisionWrongStateTransaction' => 'applications/differential/xaction/DifferentialRevisionWrongStateTransaction.php', 'DifferentialSchemaSpec' => 'applications/differential/storage/DifferentialSchemaSpec.php', 'DifferentialSetDiffPropertyConduitAPIMethod' => 'applications/differential/conduit/DifferentialSetDiffPropertyConduitAPIMethod.php', 'DifferentialStoredCustomField' => 'applications/differential/customfield/DifferentialStoredCustomField.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', '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', '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', 'DiffusionBlameController' => 'applications/diffusion/controller/DiffusionBlameController.php', 'DiffusionBlameQuery' => 'applications/diffusion/query/blame/DiffusionBlameQuery.php', 'DiffusionBlockHeraldAction' => 'applications/diffusion/herald/DiffusionBlockHeraldAction.php', 'DiffusionBranchListView' => 'applications/diffusion/view/DiffusionBranchListView.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', 'DiffusionBuildableEngine' => 'applications/diffusion/harbormaster/DiffusionBuildableEngine.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', 'DiffusionCloneController' => 'applications/diffusion/controller/DiffusionCloneController.php', 'DiffusionCloneURIView' => 'applications/diffusion/view/DiffusionCloneURIView.php', 'DiffusionCommandEngine' => 'applications/diffusion/protocol/DiffusionCommandEngine.php', 'DiffusionCommandEngineTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionCommandEngineTestCase.php', 'DiffusionCommitAcceptTransaction' => 'applications/diffusion/xaction/DiffusionCommitAcceptTransaction.php', 'DiffusionCommitActionTransaction' => 'applications/diffusion/xaction/DiffusionCommitActionTransaction.php', 'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.php', 'DiffusionCommitAuditStatus' => 'applications/diffusion/DiffusionCommitAuditStatus.php', 'DiffusionCommitAuditTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditTransaction.php', 'DiffusionCommitAuditorsHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuditorsHeraldField.php', 'DiffusionCommitAuditorsTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php', 'DiffusionCommitAuthorHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuthorHeraldField.php', 'DiffusionCommitAuthorProjectsHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuthorProjectsHeraldField.php', 'DiffusionCommitAutocloseHeraldField' => 'applications/diffusion/herald/DiffusionCommitAutocloseHeraldField.php', 'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php', 'DiffusionCommitBranchesHeraldField' => 'applications/diffusion/herald/DiffusionCommitBranchesHeraldField.php', 'DiffusionCommitBuildableTransaction' => 'applications/diffusion/xaction/DiffusionCommitBuildableTransaction.php', 'DiffusionCommitCommitterHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterHeraldField.php', 'DiffusionCommitCommitterProjectsHeraldField' => 'applications/diffusion/herald/DiffusionCommitCommitterProjectsHeraldField.php', 'DiffusionCommitConcernTransaction' => 'applications/diffusion/xaction/DiffusionCommitConcernTransaction.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', 'DiffusionCommitDraftEngine' => 'applications/diffusion/engine/DiffusionCommitDraftEngine.php', 'DiffusionCommitEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCommitEditConduitAPIMethod.php', 'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php', 'DiffusionCommitEditEngine' => 'applications/diffusion/editor/DiffusionCommitEditEngine.php', 'DiffusionCommitFerretEngine' => 'applications/repository/search/DiffusionCommitFerretEngine.php', 'DiffusionCommitFulltextEngine' => 'applications/repository/search/DiffusionCommitFulltextEngine.php', 'DiffusionCommitHasPackageEdgeType' => 'applications/diffusion/edge/DiffusionCommitHasPackageEdgeType.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', 'DiffusionCommitListController' => 'applications/diffusion/controller/DiffusionCommitListController.php', 'DiffusionCommitListView' => 'applications/diffusion/view/DiffusionCommitListView.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', 'DiffusionCommitRequiredActionResultBucket' => 'applications/diffusion/query/DiffusionCommitRequiredActionResultBucket.php', 'DiffusionCommitResignTransaction' => 'applications/diffusion/xaction/DiffusionCommitResignTransaction.php', 'DiffusionCommitResultBucket' => 'applications/diffusion/query/DiffusionCommitResultBucket.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', 'DiffusionCommitRevisionAcceptingReviewersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionAcceptingReviewersHeraldField.php', 'DiffusionCommitRevisionHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionHeraldField.php', 'DiffusionCommitRevisionReviewersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionReviewersHeraldField.php', 'DiffusionCommitRevisionSubscribersHeraldField' => 'applications/diffusion/herald/DiffusionCommitRevisionSubscribersHeraldField.php', 'DiffusionCommitSearchConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCommitSearchConduitAPIMethod.php', 'DiffusionCommitStateTransaction' => 'applications/diffusion/xaction/DiffusionCommitStateTransaction.php', 'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php', 'DiffusionCommitTimelineEngine' => 'applications/diffusion/engine/DiffusionCommitTimelineEngine.php', 'DiffusionCommitTransactionType' => 'applications/diffusion/xaction/DiffusionCommitTransactionType.php', 'DiffusionCommitVerifyTransaction' => 'applications/diffusion/xaction/DiffusionCommitVerifyTransaction.php', 'DiffusionCompareController' => 'applications/diffusion/controller/DiffusionCompareController.php', 'DiffusionConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionConduitAPIMethod.php', 'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php', 'DiffusionCreateRepositoriesCapability' => 'applications/diffusion/capability/DiffusionCreateRepositoriesCapability.php', 'DiffusionDaemonLockException' => 'applications/diffusion/exception/DiffusionDaemonLockException.php', 'DiffusionDatasourceEngineExtension' => 'applications/diffusion/engineextension/DiffusionDatasourceEngineExtension.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', 'DiffusionDocumentController' => 'applications/diffusion/controller/DiffusionDocumentController.php', 'DiffusionDocumentRenderingEngine' => 'applications/diffusion/document/DiffusionDocumentRenderingEngine.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', 'DiffusionGraphController' => 'applications/diffusion/controller/DiffusionGraphController.php', 'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php', 'DiffusionHistoryListView' => 'applications/diffusion/view/DiffusionHistoryListView.php', 'DiffusionHistoryQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php', 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 'DiffusionHistoryView' => 'applications/diffusion/view/DiffusionHistoryView.php', 'DiffusionHovercardEngineExtension' => 'applications/diffusion/engineextension/DiffusionHovercardEngineExtension.php', 'DiffusionIdentityAssigneeDatasource' => 'applications/diffusion/typeahead/DiffusionIdentityAssigneeDatasource.php', 'DiffusionIdentityAssigneeEditField' => 'applications/diffusion/editfield/DiffusionIdentityAssigneeEditField.php', 'DiffusionIdentityAssigneeSearchField' => 'applications/diffusion/searchfield/DiffusionIdentityAssigneeSearchField.php', 'DiffusionIdentityEditController' => 'applications/diffusion/controller/DiffusionIdentityEditController.php', 'DiffusionIdentityListController' => 'applications/diffusion/controller/DiffusionIdentityListController.php', 'DiffusionIdentityUnassignedDatasource' => 'applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php', 'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php', 'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', 'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', 'DiffusionInternalAncestorsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalAncestorsConduitAPIMethod.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', 'DiffusionLogController' => 'applications/diffusion/controller/DiffusionLogController.php', 'DiffusionLookSoonConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionLookSoonConduitAPIMethod.php', 'DiffusionLowLevelCommitFieldsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitFieldsQuery.php', 'DiffusionLowLevelCommitQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelCommitQuery.php', 'DiffusionLowLevelFilesizeQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelFilesizeQuery.php', 'DiffusionLowLevelGitRefQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelGitRefQuery.php', 'DiffusionLowLevelMercurialBranchesQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialBranchesQuery.php', 'DiffusionLowLevelMercurialPathsQuery' => 'applications/diffusion/query/lowlevel/DiffusionLowLevelMercurialPathsQuery.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', 'DiffusionMercurialFlagInjectionException' => 'applications/diffusion/exception/DiffusionMercurialFlagInjectionException.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', 'DiffusionPatternSearchView' => 'applications/diffusion/view/DiffusionPatternSearchView.php', 'DiffusionPhpExternalSymbolsSource' => 'applications/diffusion/symbol/DiffusionPhpExternalSymbolsSource.php', 'DiffusionPreCommitContentAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAffectedFilesHeraldField.php', 'DiffusionPreCommitContentAuthorHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorHeraldField.php', 'DiffusionPreCommitContentAuthorProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorProjectsHeraldField.php', 'DiffusionPreCommitContentAuthorRawHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentAuthorRawHeraldField.php', 'DiffusionPreCommitContentBranchesHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentBranchesHeraldField.php', 'DiffusionPreCommitContentCommitterHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentCommitterHeraldField.php', 'DiffusionPreCommitContentCommitterProjectsHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentCommitterProjectsHeraldField.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', 'DiffusionPreCommitContentPackageHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPackageHeraldField.php', 'DiffusionPreCommitContentPackageOwnerHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentPackageOwnerHeraldField.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', 'DiffusionPreCommitContentRevisionAcceptingReviewersHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitContentRevisionAcceptingReviewersHeraldField.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', 'DiffusionPreCommitUsesGitLFSHeraldField' => 'applications/diffusion/herald/DiffusionPreCommitUsesGitLFSHeraldField.php', 'DiffusionPullEventGarbageCollector' => 'applications/diffusion/garbagecollector/DiffusionPullEventGarbageCollector.php', 'DiffusionPullLogListController' => 'applications/diffusion/controller/DiffusionPullLogListController.php', 'DiffusionPullLogListView' => 'applications/diffusion/view/DiffusionPullLogListView.php', 'DiffusionPullLogSearchEngine' => 'applications/diffusion/query/DiffusionPullLogSearchEngine.php', 'DiffusionPushCapability' => 'applications/diffusion/capability/DiffusionPushCapability.php', 'DiffusionPushEventViewController' => 'applications/diffusion/controller/DiffusionPushEventViewController.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', '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', 'DiffusionRepositoryEditEnormousController' => 'applications/diffusion/controller/DiffusionRepositoryEditEnormousController.php', 'DiffusionRepositoryEditUpdateController' => 'applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php', 'DiffusionRepositoryFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php', 'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php', 'DiffusionRepositoryIdentityEditor' => 'applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php', 'DiffusionRepositoryIdentitySearchEngine' => 'applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php', 'DiffusionRepositoryLimitsManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryLimitsManagementPanel.php', 'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php', 'DiffusionRepositoryManageController' => 'applications/diffusion/controller/DiffusionRepositoryManageController.php', 'DiffusionRepositoryManagePanelsController' => 'applications/diffusion/controller/DiffusionRepositoryManagePanelsController.php', 'DiffusionRepositoryManagementBuildsPanelGroup' => 'applications/diffusion/management/DiffusionRepositoryManagementBuildsPanelGroup.php', 'DiffusionRepositoryManagementIntegrationsPanelGroup' => 'applications/diffusion/management/DiffusionRepositoryManagementIntegrationsPanelGroup.php', 'DiffusionRepositoryManagementMainPanelGroup' => 'applications/diffusion/management/DiffusionRepositoryManagementMainPanelGroup.php', 'DiffusionRepositoryManagementOtherPanelGroup' => 'applications/diffusion/management/DiffusionRepositoryManagementOtherPanelGroup.php', 'DiffusionRepositoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryManagementPanel.php', 'DiffusionRepositoryManagementPanelGroup' => 'applications/diffusion/management/DiffusionRepositoryManagementPanelGroup.php', 'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php', 'DiffusionRepositoryPoliciesManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryPoliciesManagementPanel.php', 'DiffusionRepositoryProfilePictureController' => 'applications/diffusion/controller/DiffusionRepositoryProfilePictureController.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', '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', 'DiffusionSyncLogListController' => 'applications/diffusion/controller/DiffusionSyncLogListController.php', 'DiffusionSyncLogListView' => 'applications/diffusion/view/DiffusionSyncLogListView.php', 'DiffusionSyncLogSearchEngine' => 'applications/diffusion/query/DiffusionSyncLogSearchEngine.php', 'DiffusionTagListController' => 'applications/diffusion/controller/DiffusionTagListController.php', 'DiffusionTagListView' => 'applications/diffusion/view/DiffusionTagListView.php', 'DiffusionTagTableView' => 'applications/diffusion/view/DiffusionTagTableView.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', 'DrydockAcquiredBrokenResourceException' => 'applications/drydock/exception/DrydockAcquiredBrokenResourceException.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', 'DrydockBlueprintDisableTransaction' => 'applications/drydock/xaction/DrydockBlueprintDisableTransaction.php', 'DrydockBlueprintEditConduitAPIMethod' => 'applications/drydock/conduit/DrydockBlueprintEditConduitAPIMethod.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', 'DrydockBlueprintNameTransaction' => 'applications/drydock/xaction/DrydockBlueprintNameTransaction.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', 'DrydockBlueprintTransactionType' => 'applications/drydock/xaction/DrydockBlueprintTransactionType.php', 'DrydockBlueprintTypeTransaction' => 'applications/drydock/xaction/DrydockBlueprintTypeTransaction.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', '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', 'DrydockLeaseAllocationFailureLogType' => 'applications/drydock/logtype/DrydockLeaseAllocationFailureLogType.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', 'DrydockLeaseReacquireLogType' => 'applications/drydock/logtype/DrydockLeaseReacquireLogType.php', 'DrydockLeaseReclaimLogType' => 'applications/drydock/logtype/DrydockLeaseReclaimLogType.php', 'DrydockLeaseReleaseController' => 'applications/drydock/controller/DrydockLeaseReleaseController.php', 'DrydockLeaseReleasedLogType' => 'applications/drydock/logtype/DrydockLeaseReleasedLogType.php', 'DrydockLeaseSearchConduitAPIMethod' => 'applications/drydock/conduit/DrydockLeaseSearchConduitAPIMethod.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', 'DrydockOperationWorkLogType' => 'applications/drydock/logtype/DrydockOperationWorkLogType.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', 'DrydockResourceAllocationFailureLogType' => 'applications/drydock/logtype/DrydockResourceAllocationFailureLogType.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', 'DrydockResourceLockException' => 'applications/drydock/exception/DrydockResourceLockException.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', 'DrydockTextLogType' => 'applications/drydock/logtype/DrydockTextLogType.php', 'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php', 'DrydockWorker' => 'applications/drydock/worker/DrydockWorker.php', 'DrydockWorkingCopyBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php', 'EdgeSearchConduitAPIMethod' => 'infrastructure/edges/conduit/EdgeSearchConduitAPIMethod.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', 'FileDeletionWorker' => 'applications/files/worker/FileDeletionWorker.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', 'FundBackerRefundTransaction' => 'applications/fund/xaction/FundBackerRefundTransaction.php', 'FundBackerSearchEngine' => 'applications/fund/query/FundBackerSearchEngine.php', 'FundBackerStatusTransaction' => 'applications/fund/xaction/FundBackerStatusTransaction.php', 'FundBackerTransaction' => 'applications/fund/storage/FundBackerTransaction.php', 'FundBackerTransactionQuery' => 'applications/fund/query/FundBackerTransactionQuery.php', 'FundBackerTransactionType' => 'applications/fund/xaction/FundBackerTransactionType.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', 'FundInitiativeBackerTransaction' => 'applications/fund/xaction/FundInitiativeBackerTransaction.php', 'FundInitiativeCloseController' => 'applications/fund/controller/FundInitiativeCloseController.php', 'FundInitiativeDescriptionTransaction' => 'applications/fund/xaction/FundInitiativeDescriptionTransaction.php', 'FundInitiativeEditController' => 'applications/fund/controller/FundInitiativeEditController.php', 'FundInitiativeEditEngine' => 'applications/fund/editor/FundInitiativeEditEngine.php', 'FundInitiativeEditor' => 'applications/fund/editor/FundInitiativeEditor.php', 'FundInitiativeFerretEngine' => 'applications/fund/search/FundInitiativeFerretEngine.php', 'FundInitiativeFulltextEngine' => 'applications/fund/search/FundInitiativeFulltextEngine.php', 'FundInitiativeListController' => 'applications/fund/controller/FundInitiativeListController.php', 'FundInitiativeMerchantTransaction' => 'applications/fund/xaction/FundInitiativeMerchantTransaction.php', 'FundInitiativeNameTransaction' => 'applications/fund/xaction/FundInitiativeNameTransaction.php', 'FundInitiativePHIDType' => 'applications/fund/phid/FundInitiativePHIDType.php', 'FundInitiativeQuery' => 'applications/fund/query/FundInitiativeQuery.php', 'FundInitiativeRefundTransaction' => 'applications/fund/xaction/FundInitiativeRefundTransaction.php', 'FundInitiativeRemarkupRule' => 'applications/fund/remarkup/FundInitiativeRemarkupRule.php', 'FundInitiativeReplyHandler' => 'applications/fund/mail/FundInitiativeReplyHandler.php', 'FundInitiativeRisksTransaction' => 'applications/fund/xaction/FundInitiativeRisksTransaction.php', 'FundInitiativeSearchEngine' => 'applications/fund/query/FundInitiativeSearchEngine.php', 'FundInitiativeStatusTransaction' => 'applications/fund/xaction/FundInitiativeStatusTransaction.php', 'FundInitiativeTransaction' => 'applications/fund/storage/FundInitiativeTransaction.php', 'FundInitiativeTransactionComment' => 'applications/fund/storage/FundInitiativeTransactionComment.php', 'FundInitiativeTransactionQuery' => 'applications/fund/query/FundInitiativeTransactionQuery.php', 'FundInitiativeTransactionType' => 'applications/fund/xaction/FundInitiativeTransactionType.php', 'FundInitiativeViewController' => 'applications/fund/controller/FundInitiativeViewController.php', 'FundSchemaSpec' => 'applications/fund/storage/FundSchemaSpec.php', 'HarbormasterAbortOlderBuildsBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterAbortOlderBuildsBuildStepImplementation.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', 'HarbormasterBuildLogDownloadController' => 'applications/harbormaster/controller/HarbormasterBuildLogDownloadController.php', 'HarbormasterBuildLogPHIDType' => 'applications/harbormaster/phid/HarbormasterBuildLogPHIDType.php', 'HarbormasterBuildLogQuery' => 'applications/harbormaster/query/HarbormasterBuildLogQuery.php', 'HarbormasterBuildLogRenderController' => 'applications/harbormaster/controller/HarbormasterBuildLogRenderController.php', 'HarbormasterBuildLogSearchConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildLogSearchConduitAPIMethod.php', 'HarbormasterBuildLogSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildLogSearchEngine.php', 'HarbormasterBuildLogTestCase' => 'applications/harbormaster/__tests__/HarbormasterBuildLogTestCase.php', 'HarbormasterBuildLogView' => 'applications/harbormaster/view/HarbormasterBuildLogView.php', 'HarbormasterBuildLogViewController' => 'applications/harbormaster/controller/HarbormasterBuildLogViewController.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', 'HarbormasterBuildPlanSearchAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildPlanSearchAPIMethod.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', 'HarbormasterBuildTargetSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildTargetSearchEngine.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', 'HarbormasterBuildableEngine' => 'applications/harbormaster/engine/HarbormasterBuildableEngine.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', 'HarbormasterBuildableSearchAPIMethod' => 'applications/harbormaster/conduit/HarbormasterBuildableSearchAPIMethod.php', 'HarbormasterBuildableSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildableSearchEngine.php', 'HarbormasterBuildableStatus' => 'applications/harbormaster/constants/HarbormasterBuildableStatus.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', 'HarbormasterBuildkiteBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php', 'HarbormasterBuildkiteBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildkiteBuildableInterface.php', 'HarbormasterBuildkiteHookController' => 'applications/harbormaster/controller/HarbormasterBuildkiteHookController.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', 'HarbormasterControlBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterControlBuildStepGroup.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', 'HarbormasterLogWorker' => 'applications/harbormaster/worker/HarbormasterLogWorker.php', 'HarbormasterManagementArchiveLogsWorkflow' => 'applications/harbormaster/management/HarbormasterManagementArchiveLogsWorkflow.php', 'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php', 'HarbormasterManagementPublishWorkflow' => 'applications/harbormaster/management/HarbormasterManagementPublishWorkflow.php', 'HarbormasterManagementRebuildLogWorkflow' => 'applications/harbormaster/management/HarbormasterManagementRebuildLogWorkflow.php', 'HarbormasterManagementRestartWorkflow' => 'applications/harbormaster/management/HarbormasterManagementRestartWorkflow.php', 'HarbormasterManagementUpdateWorkflow' => 'applications/harbormaster/management/HarbormasterManagementUpdateWorkflow.php', 'HarbormasterManagementWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWorkflow.php', 'HarbormasterManagementWriteLogWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWriteLogWorkflow.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', 'HarbormasterTargetSearchAPIMethod' => 'applications/harbormaster/conduit/HarbormasterTargetSearchAPIMethod.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', 'HeraldActingUserField' => 'applications/herald/field/HeraldActingUserField.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', 'HeraldAdapterDatasource' => 'applications/herald/typeahead/HeraldAdapterDatasource.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', 'HeraldBuildableState' => 'applications/herald/state/HeraldBuildableState.php', 'HeraldCallWebhookAction' => 'applications/herald/action/HeraldCallWebhookAction.php', 'HeraldCommentAction' => 'applications/herald/action/HeraldCommentAction.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', 'HeraldCoreStateReasons' => 'applications/herald/state/HeraldCoreStateReasons.php', 'HeraldCreateWebhooksCapability' => 'applications/herald/capability/HeraldCreateWebhooksCapability.php', 'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php', 'HeraldDeprecatedFieldGroup' => 'applications/herald/field/HeraldDeprecatedFieldGroup.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', 'HeraldMailableState' => 'applications/herald/state/HeraldMailableState.php', 'HeraldManageGlobalRulesCapability' => 'applications/herald/capability/HeraldManageGlobalRulesCapability.php', 'HeraldManagementWorkflow' => 'applications/herald/management/HeraldManagementWorkflow.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', 'HeraldRemarkupFieldValue' => 'applications/herald/value/HeraldRemarkupFieldValue.php', 'HeraldRemarkupRule' => 'applications/herald/remarkup/HeraldRemarkupRule.php', 'HeraldRule' => 'applications/herald/storage/HeraldRule.php', 'HeraldRuleAdapter' => 'applications/herald/adapter/HeraldRuleAdapter.php', 'HeraldRuleAdapterField' => 'applications/herald/field/rule/HeraldRuleAdapterField.php', 'HeraldRuleController' => 'applications/herald/controller/HeraldRuleController.php', 'HeraldRuleDatasource' => 'applications/herald/typeahead/HeraldRuleDatasource.php', 'HeraldRuleEditor' => 'applications/herald/editor/HeraldRuleEditor.php', 'HeraldRuleField' => 'applications/herald/field/rule/HeraldRuleField.php', 'HeraldRuleFieldGroup' => 'applications/herald/field/rule/HeraldRuleFieldGroup.php', 'HeraldRuleListController' => 'applications/herald/controller/HeraldRuleListController.php', 'HeraldRulePHIDType' => 'applications/herald/phid/HeraldRulePHIDType.php', 'HeraldRuleQuery' => 'applications/herald/query/HeraldRuleQuery.php', 'HeraldRuleReplyHandler' => 'applications/herald/mail/HeraldRuleReplyHandler.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', 'HeraldRuleTypeDatasource' => 'applications/herald/typeahead/HeraldRuleTypeDatasource.php', 'HeraldRuleTypeField' => 'applications/herald/field/rule/HeraldRuleTypeField.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', 'HeraldState' => 'applications/herald/state/HeraldState.php', 'HeraldStateReasons' => 'applications/herald/state/HeraldStateReasons.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', 'HeraldTestManagementWorkflow' => 'applications/herald/management/HeraldTestManagementWorkflow.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', 'HeraldWebhook' => 'applications/herald/storage/HeraldWebhook.php', 'HeraldWebhookCallManagementWorkflow' => 'applications/herald/management/HeraldWebhookCallManagementWorkflow.php', 'HeraldWebhookController' => 'applications/herald/controller/HeraldWebhookController.php', 'HeraldWebhookDatasource' => 'applications/herald/typeahead/HeraldWebhookDatasource.php', 'HeraldWebhookEditController' => 'applications/herald/controller/HeraldWebhookEditController.php', 'HeraldWebhookEditEngine' => 'applications/herald/editor/HeraldWebhookEditEngine.php', 'HeraldWebhookEditor' => 'applications/herald/editor/HeraldWebhookEditor.php', 'HeraldWebhookKeyController' => 'applications/herald/controller/HeraldWebhookKeyController.php', 'HeraldWebhookListController' => 'applications/herald/controller/HeraldWebhookListController.php', 'HeraldWebhookManagementWorkflow' => 'applications/herald/management/HeraldWebhookManagementWorkflow.php', 'HeraldWebhookNameTransaction' => 'applications/herald/xaction/HeraldWebhookNameTransaction.php', 'HeraldWebhookPHIDType' => 'applications/herald/phid/HeraldWebhookPHIDType.php', 'HeraldWebhookQuery' => 'applications/herald/query/HeraldWebhookQuery.php', 'HeraldWebhookRequest' => 'applications/herald/storage/HeraldWebhookRequest.php', 'HeraldWebhookRequestGarbageCollector' => 'applications/herald/garbagecollector/HeraldWebhookRequestGarbageCollector.php', 'HeraldWebhookRequestListView' => 'applications/herald/view/HeraldWebhookRequestListView.php', 'HeraldWebhookRequestPHIDType' => 'applications/herald/phid/HeraldWebhookRequestPHIDType.php', 'HeraldWebhookRequestQuery' => 'applications/herald/query/HeraldWebhookRequestQuery.php', 'HeraldWebhookSearchEngine' => 'applications/herald/query/HeraldWebhookSearchEngine.php', 'HeraldWebhookStatusTransaction' => 'applications/herald/xaction/HeraldWebhookStatusTransaction.php', 'HeraldWebhookTestController' => 'applications/herald/controller/HeraldWebhookTestController.php', 'HeraldWebhookTransaction' => 'applications/herald/storage/HeraldWebhookTransaction.php', 'HeraldWebhookTransactionQuery' => 'applications/herald/query/HeraldWebhookTransactionQuery.php', 'HeraldWebhookTransactionType' => 'applications/herald/xaction/HeraldWebhookTransactionType.php', 'HeraldWebhookURITransaction' => 'applications/herald/xaction/HeraldWebhookURITransaction.php', 'HeraldWebhookViewController' => 'applications/herald/controller/HeraldWebhookViewController.php', 'HeraldWebhookWorker' => 'applications/herald/worker/HeraldWebhookWorker.php', 'Javelin' => 'infrastructure/javelin/Javelin.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', 'LegalpadDocumentDatasource' => 'applications/legalpad/typeahead/LegalpadDocumentDatasource.php', 'LegalpadDocumentDoneController' => 'applications/legalpad/controller/LegalpadDocumentDoneController.php', 'LegalpadDocumentEditController' => 'applications/legalpad/controller/LegalpadDocumentEditController.php', 'LegalpadDocumentEditEngine' => 'applications/legalpad/editor/LegalpadDocumentEditEngine.php', 'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php', 'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php', 'LegalpadDocumentManageController' => 'applications/legalpad/controller/LegalpadDocumentManageController.php', 'LegalpadDocumentPreambleTransaction' => 'applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php', 'LegalpadDocumentQuery' => 'applications/legalpad/query/LegalpadDocumentQuery.php', 'LegalpadDocumentRemarkupRule' => 'applications/legalpad/remarkup/LegalpadDocumentRemarkupRule.php', 'LegalpadDocumentRequireSignatureTransaction' => 'applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.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', 'LegalpadDocumentSignatureTypeTransaction' => 'applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php', 'LegalpadDocumentSignatureVerificationController' => 'applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php', 'LegalpadDocumentSignatureViewController' => 'applications/legalpad/controller/LegalpadDocumentSignatureViewController.php', 'LegalpadDocumentTextTransaction' => 'applications/legalpad/xaction/LegalpadDocumentTextTransaction.php', 'LegalpadDocumentTitleTransaction' => 'applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php', 'LegalpadDocumentTransactionType' => 'applications/legalpad/xaction/LegalpadDocumentTransactionType.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', 'LiskChunkTestCase' => 'infrastructure/storage/lisk/__tests__/LiskChunkTestCase.php', 'LiskDAO' => 'infrastructure/storage/lisk/LiskDAO.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', 'MacroEditConduitAPIMethod' => 'applications/macro/conduit/MacroEditConduitAPIMethod.php', 'MacroEmojiExample' => 'applications/uiexample/examples/MacroEmojiExample.php', 'MacroQueryConduitAPIMethod' => 'applications/macro/conduit/MacroQueryConduitAPIMethod.php', 'ManiphestAssignEmailCommand' => 'applications/maniphest/command/ManiphestAssignEmailCommand.php', 'ManiphestAssigneeDatasource' => 'applications/maniphest/typeahead/ManiphestAssigneeDatasource.php', 'ManiphestBulkEditCapability' => 'applications/maniphest/capability/ManiphestBulkEditCapability.php', 'ManiphestBulkEditController' => 'applications/maniphest/controller/ManiphestBulkEditController.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', 'ManiphestEditConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestEditConduitAPIMethod.php', 'ManiphestEditEngine' => 'applications/maniphest/editor/ManiphestEditEngine.php', 'ManiphestEmailCommand' => 'applications/maniphest/command/ManiphestEmailCommand.php', 'ManiphestGetTaskTransactionsConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestGetTaskTransactionsConduitAPIMethod.php', 'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php', 'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php', 'ManiphestMailEngineExtension' => 'applications/maniphest/engineextension/ManiphestMailEngineExtension.php', 'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php', 'ManiphestPointsConfigType' => 'applications/maniphest/config/ManiphestPointsConfigType.php', 'ManiphestPrioritiesConfigType' => 'applications/maniphest/config/ManiphestPrioritiesConfigType.php', 'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php', 'ManiphestPrioritySearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestPrioritySearchConduitAPIMethod.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', 'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php', 'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php', 'ManiphestStatusesConfigType' => 'applications/maniphest/config/ManiphestStatusesConfigType.php', 'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php', 'ManiphestSubtypesConfigType' => 'applications/maniphest/config/ManiphestSubtypesConfigType.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', 'ManiphestTaskAttachTransaction' => 'applications/maniphest/xaction/ManiphestTaskAttachTransaction.php', 'ManiphestTaskAuthorHeraldField' => 'applications/maniphest/herald/ManiphestTaskAuthorHeraldField.php', 'ManiphestTaskAuthorPolicyRule' => 'applications/maniphest/policyrule/ManiphestTaskAuthorPolicyRule.php', 'ManiphestTaskBulkEngine' => 'applications/maniphest/bulk/ManiphestTaskBulkEngine.php', 'ManiphestTaskCloseAsDuplicateRelationship' => 'applications/maniphest/relationship/ManiphestTaskCloseAsDuplicateRelationship.php', 'ManiphestTaskClosedStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskClosedStatusDatasource.php', 'ManiphestTaskCoverImageTransaction' => 'applications/maniphest/xaction/ManiphestTaskCoverImageTransaction.php', 'ManiphestTaskDependedOnByTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php', 'ManiphestTaskDependsOnTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskDependsOnTaskEdgeType.php', 'ManiphestTaskDescriptionHeraldField' => 'applications/maniphest/herald/ManiphestTaskDescriptionHeraldField.php', 'ManiphestTaskDescriptionTransaction' => 'applications/maniphest/xaction/ManiphestTaskDescriptionTransaction.php', 'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php', 'ManiphestTaskEdgeTransaction' => 'applications/maniphest/xaction/ManiphestTaskEdgeTransaction.php', 'ManiphestTaskEditController' => 'applications/maniphest/controller/ManiphestTaskEditController.php', 'ManiphestTaskEditEngineLock' => 'applications/maniphest/editor/ManiphestTaskEditEngineLock.php', 'ManiphestTaskFerretEngine' => 'applications/maniphest/search/ManiphestTaskFerretEngine.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', 'ManiphestTaskMFAEngine' => 'applications/maniphest/engine/ManiphestTaskMFAEngine.php', 'ManiphestTaskMailReceiver' => 'applications/maniphest/mail/ManiphestTaskMailReceiver.php', 'ManiphestTaskMergeInRelationship' => 'applications/maniphest/relationship/ManiphestTaskMergeInRelationship.php', 'ManiphestTaskMergedFromTransaction' => 'applications/maniphest/xaction/ManiphestTaskMergedFromTransaction.php', 'ManiphestTaskMergedIntoTransaction' => 'applications/maniphest/xaction/ManiphestTaskMergedIntoTransaction.php', 'ManiphestTaskOpenStatusDatasource' => 'applications/maniphest/typeahead/ManiphestTaskOpenStatusDatasource.php', 'ManiphestTaskOwnerTransaction' => 'applications/maniphest/xaction/ManiphestTaskOwnerTransaction.php', 'ManiphestTaskPHIDResolver' => 'applications/maniphest/httpparametertype/ManiphestTaskPHIDResolver.php', 'ManiphestTaskPHIDType' => 'applications/maniphest/phid/ManiphestTaskPHIDType.php', 'ManiphestTaskParentTransaction' => 'applications/maniphest/xaction/ManiphestTaskParentTransaction.php', 'ManiphestTaskPoints' => 'applications/maniphest/constants/ManiphestTaskPoints.php', 'ManiphestTaskPointsTransaction' => 'applications/maniphest/xaction/ManiphestTaskPointsTransaction.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', 'ManiphestTaskPriorityTransaction' => 'applications/maniphest/xaction/ManiphestTaskPriorityTransaction.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', 'ManiphestTaskStatusTransaction' => 'applications/maniphest/xaction/ManiphestTaskStatusTransaction.php', 'ManiphestTaskSubpriorityTransaction' => 'applications/maniphest/xaction/ManiphestTaskSubpriorityTransaction.php', 'ManiphestTaskSubtaskController' => 'applications/maniphest/controller/ManiphestTaskSubtaskController.php', 'ManiphestTaskSubtypeDatasource' => 'applications/maniphest/typeahead/ManiphestTaskSubtypeDatasource.php', 'ManiphestTaskTestCase' => 'applications/maniphest/__tests__/ManiphestTaskTestCase.php', 'ManiphestTaskTitleHeraldField' => 'applications/maniphest/herald/ManiphestTaskTitleHeraldField.php', 'ManiphestTaskTitleTransaction' => 'applications/maniphest/xaction/ManiphestTaskTitleTransaction.php', 'ManiphestTaskTransactionType' => 'applications/maniphest/xaction/ManiphestTaskTransactionType.php', 'ManiphestTaskUnblockTransaction' => 'applications/maniphest/xaction/ManiphestTaskUnblockTransaction.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', 'NuanceCommandImplementation' => 'applications/nuance/command/NuanceCommandImplementation.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', 'NuanceFormItemType' => 'applications/nuance/item/NuanceFormItemType.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', 'NuanceItemCommandSpec' => 'applications/nuance/command/NuanceItemCommandSpec.php', 'NuanceItemCommandTransaction' => 'applications/nuance/xaction/NuanceItemCommandTransaction.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', 'NuanceItemOwnerTransaction' => 'applications/nuance/xaction/NuanceItemOwnerTransaction.php', 'NuanceItemPHIDType' => 'applications/nuance/phid/NuanceItemPHIDType.php', 'NuanceItemPropertyTransaction' => 'applications/nuance/xaction/NuanceItemPropertyTransaction.php', 'NuanceItemQuery' => 'applications/nuance/query/NuanceItemQuery.php', 'NuanceItemQueueTransaction' => 'applications/nuance/xaction/NuanceItemQueueTransaction.php', 'NuanceItemRequestorTransaction' => 'applications/nuance/xaction/NuanceItemRequestorTransaction.php', 'NuanceItemSearchEngine' => 'applications/nuance/query/NuanceItemSearchEngine.php', 'NuanceItemSourceTransaction' => 'applications/nuance/xaction/NuanceItemSourceTransaction.php', 'NuanceItemStatusTransaction' => 'applications/nuance/xaction/NuanceItemStatusTransaction.php', 'NuanceItemTransaction' => 'applications/nuance/storage/NuanceItemTransaction.php', 'NuanceItemTransactionComment' => 'applications/nuance/storage/NuanceItemTransactionComment.php', 'NuanceItemTransactionQuery' => 'applications/nuance/query/NuanceItemTransactionQuery.php', 'NuanceItemTransactionType' => 'applications/nuance/xaction/NuanceItemTransactionType.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', 'NuanceQueueNameTransaction' => 'applications/nuance/xaction/NuanceQueueNameTransaction.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', 'NuanceQueueTransactionType' => 'applications/nuance/xaction/NuanceQueueTransactionType.php', 'NuanceQueueViewController' => 'applications/nuance/controller/NuanceQueueViewController.php', 'NuanceQueueWorkController' => 'applications/nuance/controller/NuanceQueueWorkController.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', 'NuanceSourceDefaultQueueTransaction' => 'applications/nuance/xaction/NuanceSourceDefaultQueueTransaction.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', 'NuanceSourceNameTransaction' => 'applications/nuance/xaction/NuanceSourceNameTransaction.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', 'NuanceSourceTransactionType' => 'applications/nuance/xaction/NuanceSourceTransactionType.php', 'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php', 'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php', 'NuanceTrashCommand' => 'applications/nuance/command/NuanceTrashCommand.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', 'PHUIBigInfoExample' => 'applications/uiexample/examples/PHUIBigInfoExample.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', 'PHUIDiffInlineCommentPreviewListView' => 'infrastructure/diff/view/PHUIDiffInlineCommentPreviewListView.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', 'PHUIDiffInlineThreader' => 'infrastructure/diff/view/PHUIDiffInlineThreader.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', 'PHUIDocumentView' => 'view/phui/PHUIDocumentView.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', 'PHUIFormTimerControl' => 'view/form/control/PHUIFormTimerControl.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', 'PHUIHomeView' => 'applications/home/view/PHUIHomeView.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', 'PHUIInfoView' => 'view/phui/PHUIInfoView.php', 'PHUIInvisibleCharacterTestCase' => 'view/phui/__tests__/PHUIInvisibleCharacterTestCase.php', 'PHUIInvisibleCharacterView' => 'view/phui/PHUIInvisibleCharacterView.php', 'PHUILeftRightExample' => 'applications/uiexample/examples/PHUILeftRightExample.php', 'PHUILeftRightView' => 'view/phui/PHUILeftRightView.php', 'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php', 'PHUIListItemView' => 'view/phui/PHUIListItemView.php', 'PHUIListView' => 'view/phui/PHUIListView.php', 'PHUIListViewTestCase' => 'view/layout/__tests__/PHUIListViewTestCase.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', 'PHUIRemarkupImageView' => 'infrastructure/markup/view/PHUIRemarkupImageView.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', 'PHUIXComponentsExample' => 'applications/uiexample/examples/PHUIXComponentsExample.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', 'PassphraseCredentialConduitTransaction' => 'applications/passphrase/xaction/PassphraseCredentialConduitTransaction.php', 'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php', 'PassphraseCredentialCreateController' => 'applications/passphrase/controller/PassphraseCredentialCreateController.php', 'PassphraseCredentialDescriptionTransaction' => 'applications/passphrase/xaction/PassphraseCredentialDescriptionTransaction.php', 'PassphraseCredentialDestroyController' => 'applications/passphrase/controller/PassphraseCredentialDestroyController.php', 'PassphraseCredentialDestroyTransaction' => 'applications/passphrase/xaction/PassphraseCredentialDestroyTransaction.php', 'PassphraseCredentialEditController' => 'applications/passphrase/controller/PassphraseCredentialEditController.php', 'PassphraseCredentialFerretEngine' => 'applications/passphrase/search/PassphraseCredentialFerretEngine.php', 'PassphraseCredentialFulltextEngine' => 'applications/passphrase/search/PassphraseCredentialFulltextEngine.php', 'PassphraseCredentialListController' => 'applications/passphrase/controller/PassphraseCredentialListController.php', 'PassphraseCredentialLockController' => 'applications/passphrase/controller/PassphraseCredentialLockController.php', 'PassphraseCredentialLockTransaction' => 'applications/passphrase/xaction/PassphraseCredentialLockTransaction.php', 'PassphraseCredentialLookedAtTransaction' => 'applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php', 'PassphraseCredentialNameTransaction' => 'applications/passphrase/xaction/PassphraseCredentialNameTransaction.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', 'PassphraseCredentialSecretIDTransaction' => 'applications/passphrase/xaction/PassphraseCredentialSecretIDTransaction.php', 'PassphraseCredentialTransaction' => 'applications/passphrase/storage/PassphraseCredentialTransaction.php', 'PassphraseCredentialTransactionEditor' => 'applications/passphrase/editor/PassphraseCredentialTransactionEditor.php', 'PassphraseCredentialTransactionQuery' => 'applications/passphrase/query/PassphraseCredentialTransactionQuery.php', 'PassphraseCredentialTransactionType' => 'applications/passphrase/xaction/PassphraseCredentialTransactionType.php', 'PassphraseCredentialType' => 'applications/passphrase/credentialtype/PassphraseCredentialType.php', 'PassphraseCredentialTypeTestCase' => 'applications/passphrase/credentialtype/__tests__/PassphraseCredentialTypeTestCase.php', 'PassphraseCredentialUsernameTransaction' => 'applications/passphrase/xaction/PassphraseCredentialUsernameTransaction.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', 'PeopleDisableUsersCapability' => 'applications/people/capability/PeopleDisableUsersCapability.php', 'PeopleHovercardEngineExtension' => 'applications/people/engineextension/PeopleHovercardEngineExtension.php', 'PeopleMainMenuBarExtension' => 'applications/people/engineextension/PeopleMainMenuBarExtension.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', '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', 'PhabricatorAmazonSNSFuture' => 'applications/metamta/future/PhabricatorAmazonSNSFuture.php', 'PhabricatorAnchorView' => 'view/layout/PhabricatorAnchorView.php', 'PhabricatorAphlictManagementDebugWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementDebugWorkflow.php', 'PhabricatorAphlictManagementNotifyWorkflow' => 'applications/aphlict/management/PhabricatorAphlictManagementNotifyWorkflow.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', 'PhabricatorApplicationApplicationTransaction' => 'applications/meta/storage/PhabricatorApplicationApplicationTransaction.php', 'PhabricatorApplicationApplicationTransactionQuery' => 'applications/meta/query/PhabricatorApplicationApplicationTransactionQuery.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', 'PhabricatorApplicationEditEngine' => 'applications/meta/editor/PhabricatorApplicationEditEngine.php', 'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php', 'PhabricatorApplicationEditor' => 'applications/meta/editor/PhabricatorApplicationEditor.php', 'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php', 'PhabricatorApplicationMailReceiver' => 'applications/metamta/receiver/PhabricatorApplicationMailReceiver.php', 'PhabricatorApplicationObjectMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorApplicationObjectMailEngineExtension.php', 'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php', 'PhabricatorApplicationPolicyChangeTransaction' => 'applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php', 'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php', 'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php', 'PhabricatorApplicationSchemaSpec' => 'applications/meta/storage/PhabricatorApplicationSchemaSpec.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', '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', 'PhabricatorApplicationTransactionType' => 'applications/meta/xactions/PhabricatorApplicationTransactionType.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', 'PhabricatorApplicationTransactionWarningException' => 'applications/transactions/exception/PhabricatorApplicationTransactionWarningException.php', 'PhabricatorApplicationTransactionWarningResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionWarningResponse.php', 'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php', 'PhabricatorApplicationUninstallTransaction' => 'applications/meta/xactions/PhabricatorApplicationUninstallTransaction.php', 'PhabricatorApplicationsApplication' => 'applications/meta/application/PhabricatorApplicationsApplication.php', 'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php', 'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php', 'PhabricatorApplyEditField' => 'applications/transactions/editfield/PhabricatorApplyEditField.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', 'PhabricatorAudioDocumentEngine' => 'applications/files/document/PhabricatorAudioDocumentEngine.php', 'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php', 'PhabricatorAuditApplication' => 'applications/audit/application/PhabricatorAuditApplication.php', 'PhabricatorAuditCommentEditor' => 'applications/audit/editor/PhabricatorAuditCommentEditor.php', 'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php', 'PhabricatorAuditEditor' => 'applications/audit/editor/PhabricatorAuditEditor.php', 'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.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', 'PhabricatorAuditReplyHandler' => 'applications/audit/mail/PhabricatorAuditReplyHandler.php', 'PhabricatorAuditStatusConstants' => 'applications/audit/constants/PhabricatorAuditStatusConstants.php', 'PhabricatorAuditSynchronizeManagementWorkflow' => 'applications/audit/management/PhabricatorAuditSynchronizeManagementWorkflow.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', 'PhabricatorAuditUpdateOwnersManagementWorkflow' => 'applications/audit/management/PhabricatorAuditUpdateOwnersManagementWorkflow.php', 'PhabricatorAuthAccountView' => 'applications/auth/view/PhabricatorAuthAccountView.php', 'PhabricatorAuthApplication' => 'applications/auth/application/PhabricatorAuthApplication.php', 'PhabricatorAuthAuthFactorPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php', 'PhabricatorAuthAuthFactorProviderPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthFactorProviderPHIDType.php', 'PhabricatorAuthAuthProviderPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php', 'PhabricatorAuthCSRFEngine' => 'applications/auth/engine/PhabricatorAuthCSRFEngine.php', 'PhabricatorAuthChallenge' => 'applications/auth/storage/PhabricatorAuthChallenge.php', 'PhabricatorAuthChallengeGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthChallengeGarbageCollector.php', 'PhabricatorAuthChallengePHIDType' => 'applications/auth/phid/PhabricatorAuthChallengePHIDType.php', 'PhabricatorAuthChallengeQuery' => 'applications/auth/query/PhabricatorAuthChallengeQuery.php', 'PhabricatorAuthChangePasswordAction' => 'applications/auth/action/PhabricatorAuthChangePasswordAction.php', 'PhabricatorAuthConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthConduitAPIMethod.php', 'PhabricatorAuthConduitTokenRevoker' => 'applications/auth/revoker/PhabricatorAuthConduitTokenRevoker.php', 'PhabricatorAuthConfirmLinkController' => 'applications/auth/controller/PhabricatorAuthConfirmLinkController.php', 'PhabricatorAuthContactNumber' => 'applications/auth/storage/PhabricatorAuthContactNumber.php', 'PhabricatorAuthContactNumberController' => 'applications/auth/controller/contact/PhabricatorAuthContactNumberController.php', 'PhabricatorAuthContactNumberDisableController' => 'applications/auth/controller/contact/PhabricatorAuthContactNumberDisableController.php', 'PhabricatorAuthContactNumberEditController' => 'applications/auth/controller/contact/PhabricatorAuthContactNumberEditController.php', 'PhabricatorAuthContactNumberEditEngine' => 'applications/auth/editor/PhabricatorAuthContactNumberEditEngine.php', 'PhabricatorAuthContactNumberEditor' => 'applications/auth/editor/PhabricatorAuthContactNumberEditor.php', 'PhabricatorAuthContactNumberMFAEngine' => 'applications/auth/engine/PhabricatorAuthContactNumberMFAEngine.php', 'PhabricatorAuthContactNumberNumberTransaction' => 'applications/auth/xaction/PhabricatorAuthContactNumberNumberTransaction.php', 'PhabricatorAuthContactNumberPHIDType' => 'applications/auth/phid/PhabricatorAuthContactNumberPHIDType.php', 'PhabricatorAuthContactNumberPrimaryController' => 'applications/auth/controller/contact/PhabricatorAuthContactNumberPrimaryController.php', 'PhabricatorAuthContactNumberPrimaryTransaction' => 'applications/auth/xaction/PhabricatorAuthContactNumberPrimaryTransaction.php', 'PhabricatorAuthContactNumberQuery' => 'applications/auth/query/PhabricatorAuthContactNumberQuery.php', 'PhabricatorAuthContactNumberStatusTransaction' => 'applications/auth/xaction/PhabricatorAuthContactNumberStatusTransaction.php', 'PhabricatorAuthContactNumberTestController' => 'applications/auth/controller/contact/PhabricatorAuthContactNumberTestController.php', 'PhabricatorAuthContactNumberTransaction' => 'applications/auth/storage/PhabricatorAuthContactNumberTransaction.php', 'PhabricatorAuthContactNumberTransactionQuery' => 'applications/auth/query/PhabricatorAuthContactNumberTransactionQuery.php', 'PhabricatorAuthContactNumberTransactionType' => 'applications/auth/xaction/PhabricatorAuthContactNumberTransactionType.php', 'PhabricatorAuthContactNumberViewController' => 'applications/auth/controller/contact/PhabricatorAuthContactNumberViewController.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', 'PhabricatorAuthFactorConfigQuery' => 'applications/auth/query/PhabricatorAuthFactorConfigQuery.php', 'PhabricatorAuthFactorProvider' => 'applications/auth/storage/PhabricatorAuthFactorProvider.php', 'PhabricatorAuthFactorProviderController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderController.php', 'PhabricatorAuthFactorProviderDuoCredentialTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderDuoCredentialTransaction.php', 'PhabricatorAuthFactorProviderDuoEnrollTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderDuoEnrollTransaction.php', 'PhabricatorAuthFactorProviderDuoHostnameTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderDuoHostnameTransaction.php', 'PhabricatorAuthFactorProviderDuoUsernamesTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderDuoUsernamesTransaction.php', 'PhabricatorAuthFactorProviderEditController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderEditController.php', 'PhabricatorAuthFactorProviderEditEngine' => 'applications/auth/editor/PhabricatorAuthFactorProviderEditEngine.php', 'PhabricatorAuthFactorProviderEditor' => 'applications/auth/editor/PhabricatorAuthFactorProviderEditor.php', 'PhabricatorAuthFactorProviderEnrollMessageTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderEnrollMessageTransaction.php', 'PhabricatorAuthFactorProviderListController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderListController.php', 'PhabricatorAuthFactorProviderMFAEngine' => 'applications/auth/engine/PhabricatorAuthFactorProviderMFAEngine.php', 'PhabricatorAuthFactorProviderMessageController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderMessageController.php', 'PhabricatorAuthFactorProviderNameTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderNameTransaction.php', 'PhabricatorAuthFactorProviderQuery' => 'applications/auth/query/PhabricatorAuthFactorProviderQuery.php', 'PhabricatorAuthFactorProviderStatus' => 'applications/auth/constants/PhabricatorAuthFactorProviderStatus.php', 'PhabricatorAuthFactorProviderStatusTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderStatusTransaction.php', 'PhabricatorAuthFactorProviderTransaction' => 'applications/auth/storage/PhabricatorAuthFactorProviderTransaction.php', 'PhabricatorAuthFactorProviderTransactionQuery' => 'applications/auth/query/PhabricatorAuthFactorProviderTransactionQuery.php', 'PhabricatorAuthFactorProviderTransactionType' => 'applications/auth/xaction/PhabricatorAuthFactorProviderTransactionType.php', 'PhabricatorAuthFactorProviderViewController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderViewController.php', 'PhabricatorAuthFactorResult' => 'applications/auth/factor/PhabricatorAuthFactorResult.php', 'PhabricatorAuthFactorTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthFactorTestCase.php', 'PhabricatorAuthFinishController' => 'applications/auth/controller/PhabricatorAuthFinishController.php', 'PhabricatorAuthHMACKey' => 'applications/auth/storage/PhabricatorAuthHMACKey.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', 'PhabricatorAuthLoginMessageType' => 'applications/auth/message/PhabricatorAuthLoginMessageType.php', 'PhabricatorAuthLogoutConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthLogoutConduitAPIMethod.php', 'PhabricatorAuthMFAEditEngineExtension' => 'applications/auth/engineextension/PhabricatorAuthMFAEditEngineExtension.php', 'PhabricatorAuthMFASyncTemporaryTokenType' => 'applications/auth/factor/PhabricatorAuthMFASyncTemporaryTokenType.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', 'PhabricatorAuthManagementListMFAProvidersWorkflow' => 'applications/auth/management/PhabricatorAuthManagementListMFAProvidersWorkflow.php', 'PhabricatorAuthManagementRecoverWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRecoverWorkflow.php', 'PhabricatorAuthManagementRefreshWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php', 'PhabricatorAuthManagementRevokeWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRevokeWorkflow.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', 'PhabricatorAuthMessage' => 'applications/auth/storage/PhabricatorAuthMessage.php', 'PhabricatorAuthMessageController' => 'applications/auth/controller/message/PhabricatorAuthMessageController.php', 'PhabricatorAuthMessageEditController' => 'applications/auth/controller/message/PhabricatorAuthMessageEditController.php', 'PhabricatorAuthMessageEditEngine' => 'applications/auth/editor/PhabricatorAuthMessageEditEngine.php', 'PhabricatorAuthMessageEditor' => 'applications/auth/editor/PhabricatorAuthMessageEditor.php', 'PhabricatorAuthMessageListController' => 'applications/auth/controller/message/PhabricatorAuthMessageListController.php', 'PhabricatorAuthMessagePHIDType' => 'applications/auth/phid/PhabricatorAuthMessagePHIDType.php', 'PhabricatorAuthMessageQuery' => 'applications/auth/query/PhabricatorAuthMessageQuery.php', 'PhabricatorAuthMessageTextTransaction' => 'applications/auth/xaction/PhabricatorAuthMessageTextTransaction.php', 'PhabricatorAuthMessageTransaction' => 'applications/auth/storage/PhabricatorAuthMessageTransaction.php', 'PhabricatorAuthMessageTransactionQuery' => 'applications/auth/query/PhabricatorAuthMessageTransactionQuery.php', 'PhabricatorAuthMessageTransactionType' => 'applications/auth/xaction/PhabricatorAuthMessageTransactionType.php', 'PhabricatorAuthMessageType' => 'applications/auth/message/PhabricatorAuthMessageType.php', 'PhabricatorAuthMessageViewController' => 'applications/auth/controller/message/PhabricatorAuthMessageViewController.php', 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', 'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php', 'PhabricatorAuthNewFactorAction' => 'applications/auth/action/PhabricatorAuthNewFactorAction.php', 'PhabricatorAuthOldOAuthRedirectController' => 'applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php', 'PhabricatorAuthOneTimeLoginController' => 'applications/auth/controller/PhabricatorAuthOneTimeLoginController.php', 'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthOneTimeLoginTemporaryTokenType.php', 'PhabricatorAuthPassword' => 'applications/auth/storage/PhabricatorAuthPassword.php', 'PhabricatorAuthPasswordEditor' => 'applications/auth/editor/PhabricatorAuthPasswordEditor.php', 'PhabricatorAuthPasswordEngine' => 'applications/auth/engine/PhabricatorAuthPasswordEngine.php', 'PhabricatorAuthPasswordException' => 'applications/auth/password/PhabricatorAuthPasswordException.php', 'PhabricatorAuthPasswordHashInterface' => 'applications/auth/password/PhabricatorAuthPasswordHashInterface.php', 'PhabricatorAuthPasswordPHIDType' => 'applications/auth/phid/PhabricatorAuthPasswordPHIDType.php', 'PhabricatorAuthPasswordQuery' => 'applications/auth/query/PhabricatorAuthPasswordQuery.php', 'PhabricatorAuthPasswordResetTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthPasswordResetTemporaryTokenType.php', 'PhabricatorAuthPasswordRevokeTransaction' => 'applications/auth/xaction/PhabricatorAuthPasswordRevokeTransaction.php', 'PhabricatorAuthPasswordRevoker' => 'applications/auth/revoker/PhabricatorAuthPasswordRevoker.php', 'PhabricatorAuthPasswordTestCase' => 'applications/auth/__tests__/PhabricatorAuthPasswordTestCase.php', 'PhabricatorAuthPasswordTransaction' => 'applications/auth/storage/PhabricatorAuthPasswordTransaction.php', 'PhabricatorAuthPasswordTransactionQuery' => 'applications/auth/query/PhabricatorAuthPasswordTransactionQuery.php', 'PhabricatorAuthPasswordTransactionType' => 'applications/auth/xaction/PhabricatorAuthPasswordTransactionType.php', 'PhabricatorAuthPasswordUpgradeTransaction' => 'applications/auth/xaction/PhabricatorAuthPasswordUpgradeTransaction.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', 'PhabricatorAuthProviderController' => 'applications/auth/controller/config/PhabricatorAuthProviderController.php', + 'PhabricatorAuthProviderViewController' => 'applications/auth/controller/config/PhabricatorAuthProviderViewController.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', 'PhabricatorAuthRevoker' => 'applications/auth/revoker/PhabricatorAuthRevoker.php', 'PhabricatorAuthSSHKey' => 'applications/auth/storage/PhabricatorAuthSSHKey.php', 'PhabricatorAuthSSHKeyController' => 'applications/auth/controller/PhabricatorAuthSSHKeyController.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', 'PhabricatorAuthSSHKeyRevokeController' => 'applications/auth/controller/PhabricatorAuthSSHKeyRevokeController.php', 'PhabricatorAuthSSHKeySearchEngine' => 'applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php', 'PhabricatorAuthSSHKeyTableView' => 'applications/auth/view/PhabricatorAuthSSHKeyTableView.php', 'PhabricatorAuthSSHKeyTestCase' => 'applications/auth/__tests__/PhabricatorAuthSSHKeyTestCase.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', 'PhabricatorAuthSSHRevoker' => 'applications/auth/revoker/PhabricatorAuthSSHRevoker.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', 'PhabricatorAuthSessionPHIDType' => 'applications/auth/phid/PhabricatorAuthSessionPHIDType.php', 'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php', 'PhabricatorAuthSessionRevoker' => 'applications/auth/revoker/PhabricatorAuthSessionRevoker.php', 'PhabricatorAuthSetPasswordController' => 'applications/auth/controller/PhabricatorAuthSetPasswordController.php', 'PhabricatorAuthSetupCheck' => 'applications/config/check/PhabricatorAuthSetupCheck.php', 'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php', 'PhabricatorAuthTemporaryToken' => 'applications/auth/storage/PhabricatorAuthTemporaryToken.php', 'PhabricatorAuthTemporaryTokenGarbageCollector' => 'applications/auth/garbagecollector/PhabricatorAuthTemporaryTokenGarbageCollector.php', 'PhabricatorAuthTemporaryTokenQuery' => 'applications/auth/query/PhabricatorAuthTemporaryTokenQuery.php', 'PhabricatorAuthTemporaryTokenRevoker' => 'applications/auth/revoker/PhabricatorAuthTemporaryTokenRevoker.php', 'PhabricatorAuthTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthTemporaryTokenType.php', 'PhabricatorAuthTemporaryTokenTypeModule' => 'applications/auth/tokentype/PhabricatorAuthTemporaryTokenTypeModule.php', 'PhabricatorAuthTerminateSessionController' => 'applications/auth/controller/PhabricatorAuthTerminateSessionController.php', 'PhabricatorAuthTestSMSAction' => 'applications/auth/action/PhabricatorAuthTestSMSAction.php', 'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php', 'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php', 'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php', 'PhabricatorAuthWelcomeMailMessageType' => 'applications/auth/message/PhabricatorAuthWelcomeMailMessageType.php', 'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php', 'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.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', 'PhabricatorBadgesAwardTestDataGenerator' => 'applications/badges/lipsum/PhabricatorBadgesAwardTestDataGenerator.php', 'PhabricatorBadgesBadge' => 'applications/badges/storage/PhabricatorBadgesBadge.php', 'PhabricatorBadgesBadgeAwardTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeAwardTransaction.php', 'PhabricatorBadgesBadgeDescriptionTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeDescriptionTransaction.php', 'PhabricatorBadgesBadgeFlavorTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeFlavorTransaction.php', 'PhabricatorBadgesBadgeIconTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeIconTransaction.php', 'PhabricatorBadgesBadgeNameNgrams' => 'applications/badges/storage/PhabricatorBadgesBadgeNameNgrams.php', 'PhabricatorBadgesBadgeNameTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeNameTransaction.php', 'PhabricatorBadgesBadgeQualityTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeQualityTransaction.php', 'PhabricatorBadgesBadgeRevokeTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeRevokeTransaction.php', 'PhabricatorBadgesBadgeStatusTransaction' => 'applications/badges/xaction/PhabricatorBadgesBadgeStatusTransaction.php', 'PhabricatorBadgesBadgeTestDataGenerator' => 'applications/badges/lipsum/PhabricatorBadgesBadgeTestDataGenerator.php', 'PhabricatorBadgesBadgeTransactionType' => 'applications/badges/xaction/PhabricatorBadgesBadgeTransactionType.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', 'PhabricatorBadgesLootContextFreeGrammar' => 'applications/badges/lipsum/PhabricatorBadgesLootContextFreeGrammar.php', 'PhabricatorBadgesMailReceiver' => 'applications/badges/mail/PhabricatorBadgesMailReceiver.php', 'PhabricatorBadgesPHIDType' => 'applications/badges/phid/PhabricatorBadgesPHIDType.php', 'PhabricatorBadgesProfileController' => 'applications/badges/controller/PhabricatorBadgesProfileController.php', 'PhabricatorBadgesQuality' => 'applications/badges/constants/PhabricatorBadgesQuality.php', 'PhabricatorBadgesQuery' => 'applications/badges/query/PhabricatorBadgesQuery.php', 'PhabricatorBadgesRecipientsController' => 'applications/badges/controller/PhabricatorBadgesRecipientsController.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', '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', 'PhabricatorBoardColumnsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorBoardColumnsSearchEngineAttachment.php', 'PhabricatorBoardLayoutEngine' => 'applications/project/engine/PhabricatorBoardLayoutEngine.php', 'PhabricatorBoardRenderingEngine' => 'applications/project/engine/PhabricatorBoardRenderingEngine.php', 'PhabricatorBoardResponseEngine' => 'applications/project/engine/PhabricatorBoardResponseEngine.php', 'PhabricatorBoolConfigType' => 'applications/config/type/PhabricatorBoolConfigType.php', 'PhabricatorBoolEditField' => 'applications/transactions/editfield/PhabricatorBoolEditField.php', 'PhabricatorBoolMailStamp' => 'applications/metamta/stamp/PhabricatorBoolMailStamp.php', 'PhabricatorBritishEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorBritishEnglishTranslation.php', 'PhabricatorBuiltinDraftEngine' => 'applications/transactions/draft/PhabricatorBuiltinDraftEngine.php', 'PhabricatorBuiltinFileCachePurger' => 'applications/cache/purger/PhabricatorBuiltinFileCachePurger.php', 'PhabricatorBuiltinPatchList' => 'infrastructure/storage/patch/PhabricatorBuiltinPatchList.php', 'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php', 'PhabricatorBulkEditGroup' => 'applications/transactions/bulk/PhabricatorBulkEditGroup.php', 'PhabricatorBulkEngine' => 'applications/transactions/bulk/PhabricatorBulkEngine.php', 'PhabricatorBulkManagementExportWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementExportWorkflow.php', 'PhabricatorBulkManagementMakeSilentWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementMakeSilentWorkflow.php', 'PhabricatorBulkManagementWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementWorkflow.php', 'PhabricatorCSVExportFormat' => 'infrastructure/export/format/PhabricatorCSVExportFormat.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', 'PhabricatorCachePurger' => 'applications/cache/purger/PhabricatorCachePurger.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', 'PhabricatorCalendarEventFerretEngine' => 'applications/calendar/search/PhabricatorCalendarEventFerretEngine.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', 'PhabricatorCelerityApplication' => 'applications/celerity/application/PhabricatorCelerityApplication.php', 'PhabricatorCelerityTestCase' => '__tests__/PhabricatorCelerityTestCase.php', 'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php', 'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.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', 'PhabricatorCheckboxesEditField' => 'applications/transactions/editfield/PhabricatorCheckboxesEditField.php', 'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php', 'PhabricatorClassConfigType' => 'applications/config/type/PhabricatorClassConfigType.php', 'PhabricatorClusterConfigOptions' => 'applications/config/option/PhabricatorClusterConfigOptions.php', 'PhabricatorClusterDatabasesConfigType' => 'infrastructure/cluster/config/PhabricatorClusterDatabasesConfigType.php', 'PhabricatorClusterException' => 'infrastructure/cluster/exception/PhabricatorClusterException.php', 'PhabricatorClusterExceptionHandler' => 'infrastructure/cluster/exception/PhabricatorClusterExceptionHandler.php', 'PhabricatorClusterImpossibleWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImpossibleWriteException.php', 'PhabricatorClusterImproperWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImproperWriteException.php', 'PhabricatorClusterMailersConfigType' => 'infrastructure/cluster/config/PhabricatorClusterMailersConfigType.php', 'PhabricatorClusterNoHostForRoleException' => 'infrastructure/cluster/exception/PhabricatorClusterNoHostForRoleException.php', 'PhabricatorClusterSearchConfigType' => 'infrastructure/cluster/config/PhabricatorClusterSearchConfigType.php', 'PhabricatorClusterServiceHealthRecord' => 'infrastructure/cluster/PhabricatorClusterServiceHealthRecord.php', 'PhabricatorClusterStrandedException' => 'infrastructure/cluster/exception/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', 'PhabricatorConduitCallManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitCallManagementWorkflow.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', 'PhabricatorConduitManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitManagementWorkflow.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', 'PhabricatorConfigClusterSearchController' => 'applications/config/controller/PhabricatorConfigClusterSearchController.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', 'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php', 'PhabricatorConfigPurgeCacheController' => 'applications/config/controller/PhabricatorConfigPurgeCacheController.php', 'PhabricatorConfigRegexOptionType' => 'applications/config/custom/PhabricatorConfigRegexOptionType.php', 'PhabricatorConfigRemarkupRule' => 'infrastructure/markup/rule/PhabricatorConfigRemarkupRule.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', 'PhabricatorConfigType' => 'applications/config/type/PhabricatorConfigType.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', 'PhabricatorConpherenceProfileMenuItem' => 'applications/search/menuitem/PhabricatorConpherenceProfileMenuItem.php', 'PhabricatorConpherenceRoomContextFreeGrammar' => 'applications/conpherence/lipsum/PhabricatorConpherenceRoomContextFreeGrammar.php', 'PhabricatorConpherenceRoomTestDataGenerator' => 'applications/conpherence/lipsum/PhabricatorConpherenceRoomTestDataGenerator.php', 'PhabricatorConpherenceSoundSetting' => 'applications/settings/setting/PhabricatorConpherenceSoundSetting.php', 'PhabricatorConpherenceThreadPHIDType' => 'applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php', 'PhabricatorConpherenceWidgetVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceWidgetVisibleSetting.php', 'PhabricatorConsoleApplication' => 'applications/console/application/PhabricatorConsoleApplication.php', 'PhabricatorConsoleContentSource' => 'infrastructure/contentsource/PhabricatorConsoleContentSource.php', 'PhabricatorContactNumbersSettingsPanel' => 'applications/settings/panel/PhabricatorContactNumbersSettingsPanel.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', 'PhabricatorCountFact' => 'applications/fact/fact/PhabricatorCountFact.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', 'PhabricatorCountdownDescriptionTransaction' => 'applications/countdown/xaction/PhabricatorCountdownDescriptionTransaction.php', 'PhabricatorCountdownEditController' => 'applications/countdown/controller/PhabricatorCountdownEditController.php', 'PhabricatorCountdownEditEngine' => 'applications/countdown/editor/PhabricatorCountdownEditEngine.php', 'PhabricatorCountdownEditor' => 'applications/countdown/editor/PhabricatorCountdownEditor.php', 'PhabricatorCountdownEpochTransaction' => 'applications/countdown/xaction/PhabricatorCountdownEpochTransaction.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', 'PhabricatorCountdownTitleTransaction' => 'applications/countdown/xaction/PhabricatorCountdownTitleTransaction.php', 'PhabricatorCountdownTransaction' => 'applications/countdown/storage/PhabricatorCountdownTransaction.php', 'PhabricatorCountdownTransactionComment' => 'applications/countdown/storage/PhabricatorCountdownTransactionComment.php', 'PhabricatorCountdownTransactionQuery' => 'applications/countdown/query/PhabricatorCountdownTransactionQuery.php', 'PhabricatorCountdownTransactionType' => 'applications/countdown/xaction/PhabricatorCountdownTransactionType.php', 'PhabricatorCountdownView' => 'applications/countdown/view/PhabricatorCountdownView.php', 'PhabricatorCountdownViewController' => 'applications/countdown/controller/PhabricatorCountdownViewController.php', 'PhabricatorCredentialEditField' => 'applications/transactions/editfield/PhabricatorCredentialEditField.php', 'PhabricatorCursorPagedPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php', 'PhabricatorCustomField' => 'infrastructure/customfield/field/PhabricatorCustomField.php', 'PhabricatorCustomFieldApplicationSearchAnyFunctionDatasource' => 'infrastructure/customfield/datasource/PhabricatorCustomFieldApplicationSearchAnyFunctionDatasource.php', 'PhabricatorCustomFieldApplicationSearchDatasource' => 'infrastructure/customfield/datasource/PhabricatorCustomFieldApplicationSearchDatasource.php', 'PhabricatorCustomFieldApplicationSearchNoneFunctionDatasource' => 'infrastructure/customfield/datasource/PhabricatorCustomFieldApplicationSearchNoneFunctionDatasource.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', 'PhabricatorCustomFieldExportEngineExtension' => 'infrastructure/export/engine/PhabricatorCustomFieldExportEngineExtension.php', 'PhabricatorCustomFieldFulltextEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldFulltextEngineExtension.php', 'PhabricatorCustomFieldHeraldAction' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldAction.php', 'PhabricatorCustomFieldHeraldActionGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldActionGroup.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', 'PhabricatorCustomUIFooterConfigType' => 'applications/config/custom/PhabricatorCustomUIFooterConfigType.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', 'PhabricatorDaemonLockLog' => 'applications/daemon/storage/PhabricatorDaemonLockLog.php', 'PhabricatorDaemonLockLogGarbageCollector' => 'applications/daemon/garbagecollector/PhabricatorDaemonLockLogGarbageCollector.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', 'PhabricatorDashboardArrangeController' => 'applications/dashboard/controller/PhabricatorDashboardArrangeController.php', 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.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', 'PhabricatorDashboardProfileController' => 'applications/dashboard/controller/PhabricatorDashboardProfileController.php', 'PhabricatorDashboardProfileMenuItem' => 'applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php', 'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', 'PhabricatorDashboardQueryPanelInstallController' => 'applications/dashboard/controller/PhabricatorDashboardQueryPanelInstallController.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', 'PhabricatorDashboardViewController' => 'applications/dashboard/controller/PhabricatorDashboardViewController.php', 'PhabricatorDataCacheSpec' => 'applications/cache/spec/PhabricatorDataCacheSpec.php', 'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php', 'PhabricatorDatabaseRef' => 'infrastructure/cluster/PhabricatorDatabaseRef.php', 'PhabricatorDatabaseRefParser' => 'infrastructure/cluster/PhabricatorDatabaseRefParser.php', 'PhabricatorDatabaseSetupCheck' => 'applications/config/check/PhabricatorDatabaseSetupCheck.php', 'PhabricatorDatasourceApplicationEngineExtension' => 'applications/meta/engineextension/PhabricatorDatasourceApplicationEngineExtension.php', 'PhabricatorDatasourceEditField' => 'applications/transactions/editfield/PhabricatorDatasourceEditField.php', 'PhabricatorDatasourceEditType' => 'applications/transactions/edittype/PhabricatorDatasourceEditType.php', 'PhabricatorDatasourceEngine' => 'applications/search/engine/PhabricatorDatasourceEngine.php', 'PhabricatorDatasourceEngineExtension' => 'applications/search/engineextension/PhabricatorDatasourceEngineExtension.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', 'PhabricatorDestructibleCodex' => 'applications/system/codex/PhabricatorDestructibleCodex.php', 'PhabricatorDestructibleCodexInterface' => 'applications/system/interface/PhabricatorDestructibleCodexInterface.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', 'PhabricatorDifferentialMigrateHunkWorkflow' => 'applications/differential/management/PhabricatorDifferentialMigrateHunkWorkflow.php', 'PhabricatorDifferentialRebuildChangesetsWorkflow' => 'applications/differential/management/PhabricatorDifferentialRebuildChangesetsWorkflow.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', 'PhabricatorDividerEditField' => 'applications/transactions/editfield/PhabricatorDividerEditField.php', 'PhabricatorDividerProfileMenuItem' => 'applications/search/menuitem/PhabricatorDividerProfileMenuItem.php', 'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php', 'PhabricatorDocumentEngine' => 'applications/files/document/PhabricatorDocumentEngine.php', 'PhabricatorDocumentRef' => 'applications/files/document/PhabricatorDocumentRef.php', 'PhabricatorDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorDocumentRenderingEngine.php', 'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php', 'PhabricatorDoubleExportField' => 'infrastructure/export/field/PhabricatorDoubleExportField.php', 'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php', 'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php', 'PhabricatorDraftEngine' => 'applications/transactions/draft/PhabricatorDraftEngine.php', 'PhabricatorDraftInterface' => 'applications/transactions/draft/PhabricatorDraftInterface.php', 'PhabricatorDrydockApplication' => 'applications/drydock/application/PhabricatorDrydockApplication.php', 'PhabricatorDuoAuthFactor' => 'applications/auth/factor/PhabricatorDuoAuthFactor.php', 'PhabricatorDuoFuture' => 'applications/auth/future/PhabricatorDuoFuture.php', 'PhabricatorEdgeChangeRecord' => 'infrastructure/edges/util/PhabricatorEdgeChangeRecord.php', 'PhabricatorEdgeChangeRecordTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeChangeRecordTestCase.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', 'PhabricatorEdgeObject' => 'infrastructure/edges/conduit/PhabricatorEdgeObject.php', 'PhabricatorEdgeObjectQuery' => 'infrastructure/edges/query/PhabricatorEdgeObjectQuery.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', 'PhabricatorEditEngineBulkJobType' => 'applications/transactions/bulk/PhabricatorEditEngineBulkJobType.php', 'PhabricatorEditEngineCheckboxesCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineCheckboxesCommentAction.php', 'PhabricatorEditEngineColumnsCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineColumnsCommentAction.php', 'PhabricatorEditEngineCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineCommentAction.php', 'PhabricatorEditEngineCommentActionGroup' => 'applications/transactions/commentaction/PhabricatorEditEngineCommentActionGroup.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', 'PhabricatorEditEngineConfigurationSubtypeController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSubtypeController.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', 'PhabricatorEditEngineDatasource' => 'applications/transactions/typeahead/PhabricatorEditEngineDatasource.php', 'PhabricatorEditEngineDefaultLock' => 'applications/transactions/editengine/PhabricatorEditEngineDefaultLock.php', 'PhabricatorEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditEngineExtension.php', 'PhabricatorEditEngineExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditEngineExtensionModule.php', 'PhabricatorEditEngineListController' => 'applications/transactions/controller/PhabricatorEditEngineListController.php', 'PhabricatorEditEngineLock' => 'applications/transactions/editengine/PhabricatorEditEngineLock.php', 'PhabricatorEditEngineLockableInterface' => 'applications/transactions/editengine/PhabricatorEditEngineLockableInterface.php', 'PhabricatorEditEngineMFAEngine' => 'applications/transactions/editengine/PhabricatorEditEngineMFAEngine.php', 'PhabricatorEditEngineMFAInterface' => 'applications/transactions/editengine/PhabricatorEditEngineMFAInterface.php', 'PhabricatorEditEnginePointsCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEnginePointsCommentAction.php', 'PhabricatorEditEngineProfileMenuItem' => 'applications/search/menuitem/PhabricatorEditEngineProfileMenuItem.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', 'PhabricatorEditEngineStaticCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineStaticCommentAction.php', 'PhabricatorEditEngineSubtype' => 'applications/transactions/editengine/PhabricatorEditEngineSubtype.php', 'PhabricatorEditEngineSubtypeInterface' => 'applications/transactions/editengine/PhabricatorEditEngineSubtypeInterface.php', 'PhabricatorEditEngineSubtypeMap' => 'applications/transactions/editengine/PhabricatorEditEngineSubtypeMap.php', 'PhabricatorEditEngineSubtypeTestCase' => 'applications/transactions/editengine/__tests__/PhabricatorEditEngineSubtypeTestCase.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', 'PhabricatorEditorExtension' => 'applications/transactions/engineextension/PhabricatorEditorExtension.php', 'PhabricatorEditorExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditorExtensionModule.php', 'PhabricatorEditorMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditorMailEngineExtension.php', 'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php', 'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php', 'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php', 'PhabricatorElasticsearchHost' => 'infrastructure/cluster/search/PhabricatorElasticsearchHost.php', 'PhabricatorElasticsearchQueryBuilder' => 'applications/search/fulltextstorage/PhabricatorElasticsearchQueryBuilder.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', 'PhabricatorEmailStampsSetting' => 'applications/settings/setting/PhabricatorEmailStampsSetting.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', 'PhabricatorEmojiDatasource' => 'applications/macro/typeahead/PhabricatorEmojiDatasource.php', 'PhabricatorEmojiRemarkupRule' => 'applications/macro/markup/PhabricatorEmojiRemarkupRule.php', 'PhabricatorEmojiTranslation' => 'infrastructure/internationalization/translation/PhabricatorEmojiTranslation.php', 'PhabricatorEmptyQueryException' => 'infrastructure/query/PhabricatorEmptyQueryException.php', 'PhabricatorEnumConfigType' => 'applications/config/type/PhabricatorEnumConfigType.php', 'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php', 'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php', 'PhabricatorEpochEditField' => 'applications/transactions/editfield/PhabricatorEpochEditField.php', 'PhabricatorEpochExportField' => 'infrastructure/export/field/PhabricatorEpochExportField.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', 'PhabricatorExcelExportFormat' => 'infrastructure/export/format/PhabricatorExcelExportFormat.php', 'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php', 'PhabricatorExportEngine' => 'infrastructure/export/engine/PhabricatorExportEngine.php', 'PhabricatorExportEngineBulkJobType' => 'infrastructure/export/engine/PhabricatorExportEngineBulkJobType.php', 'PhabricatorExportEngineExtension' => 'infrastructure/export/engine/PhabricatorExportEngineExtension.php', 'PhabricatorExportField' => 'infrastructure/export/field/PhabricatorExportField.php', 'PhabricatorExportFormat' => 'infrastructure/export/format/PhabricatorExportFormat.php', 'PhabricatorExportFormatSetting' => 'infrastructure/export/engine/PhabricatorExportFormatSetting.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', 'PhabricatorFact' => 'applications/fact/fact/PhabricatorFact.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', 'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php', 'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php', 'PhabricatorFactDaemon' => 'applications/fact/daemon/PhabricatorFactDaemon.php', 'PhabricatorFactDatapointQuery' => 'applications/fact/query/PhabricatorFactDatapointQuery.php', 'PhabricatorFactDimension' => 'applications/fact/storage/PhabricatorFactDimension.php', 'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php', 'PhabricatorFactEngineTestCase' => 'applications/fact/engine/__tests__/PhabricatorFactEngineTestCase.php', 'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php', 'PhabricatorFactIntDatapoint' => 'applications/fact/storage/PhabricatorFactIntDatapoint.php', 'PhabricatorFactKeyDimension' => 'applications/fact/storage/PhabricatorFactKeyDimension.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', 'PhabricatorFactManagementWorkflow' => 'applications/fact/management/PhabricatorFactManagementWorkflow.php', 'PhabricatorFactObjectController' => 'applications/fact/controller/PhabricatorFactObjectController.php', 'PhabricatorFactObjectDimension' => 'applications/fact/storage/PhabricatorFactObjectDimension.php', 'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php', 'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php', 'PhabricatorFaviconRef' => 'applications/files/favicon/PhabricatorFaviconRef.php', 'PhabricatorFaviconRefQuery' => 'applications/files/favicon/PhabricatorFaviconRefQuery.php', 'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php', 'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php', 'PhabricatorFavoritesMainMenuBarExtension' => 'applications/favorites/engineextension/PhabricatorFavoritesMainMenuBarExtension.php', 'PhabricatorFavoritesMenuItemController' => 'applications/favorites/controller/PhabricatorFavoritesMenuItemController.php', 'PhabricatorFavoritesProfileMenuEngine' => 'applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.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', 'PhabricatorFerretEngine' => 'applications/search/ferret/PhabricatorFerretEngine.php', 'PhabricatorFerretEngineTestCase' => 'applications/search/ferret/__tests__/PhabricatorFerretEngineTestCase.php', 'PhabricatorFerretFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorFerretFulltextEngineExtension.php', 'PhabricatorFerretFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorFerretFulltextStorageEngine.php', 'PhabricatorFerretInterface' => 'applications/search/ferret/PhabricatorFerretInterface.php', 'PhabricatorFerretMetadata' => 'applications/search/ferret/PhabricatorFerretMetadata.php', 'PhabricatorFerretSearchEngineExtension' => 'applications/search/engineextension/PhabricatorFerretSearchEngineExtension.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', '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', 'PhabricatorFileDeleteTransaction' => 'applications/files/xaction/PhabricatorFileDeleteTransaction.php', 'PhabricatorFileDocumentController' => 'applications/files/controller/PhabricatorFileDocumentController.php', 'PhabricatorFileDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php', 'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php', 'PhabricatorFileEditController' => 'applications/files/controller/PhabricatorFileEditController.php', 'PhabricatorFileEditEngine' => 'applications/files/editor/PhabricatorFileEditEngine.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', 'PhabricatorFileIntegrityException' => 'applications/files/exception/PhabricatorFileIntegrityException.php', 'PhabricatorFileLightboxController' => 'applications/files/controller/PhabricatorFileLightboxController.php', 'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php', 'PhabricatorFileListController' => 'applications/files/controller/PhabricatorFileListController.php', 'PhabricatorFileNameNgrams' => 'applications/files/storage/PhabricatorFileNameNgrams.php', 'PhabricatorFileNameTransaction' => 'applications/files/xaction/PhabricatorFileNameTransaction.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', 'PhabricatorFileSearchConduitAPIMethod' => 'applications/files/conduit/PhabricatorFileSearchConduitAPIMethod.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', 'PhabricatorFileTransactionType' => 'applications/files/xaction/PhabricatorFileTransactionType.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', 'PhabricatorFileUploadSourceByteLimitException' => 'applications/files/uploadsource/PhabricatorFileUploadSourceByteLimitException.php', 'PhabricatorFileViewController' => 'applications/files/controller/PhabricatorFileViewController.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', 'PhabricatorFilesComposeAvatarBuiltinFile' => 'applications/files/builtin/PhabricatorFilesComposeAvatarBuiltinFile.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', 'PhabricatorFilesManagementIntegrityWorkflow' => 'applications/files/management/PhabricatorFilesManagementIntegrityWorkflow.php', 'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.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', 'PhabricatorFiletreeWidthSetting' => 'applications/settings/setting/PhabricatorFiletreeWidthSetting.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', 'PhabricatorFulltextResultSet' => 'applications/search/query/PhabricatorFulltextResultSet.php', 'PhabricatorFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorFulltextStorageEngine.php', 'PhabricatorFulltextToken' => 'applications/search/query/PhabricatorFulltextToken.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', 'PhabricatorGarbageCollectorManagementCompactEdgesWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCompactEdgesWorkflow.php', 'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementSetPolicyWorkflow.php', 'PhabricatorGarbageCollectorManagementWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementWorkflow.php', 'PhabricatorGeneralCachePurger' => 'applications/cache/purger/PhabricatorGeneralCachePurger.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', 'PhabricatorHMACTestCase' => 'infrastructure/util/__tests__/PhabricatorHMACTestCase.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', 'PhabricatorHeraldApplication' => 'applications/herald/application/PhabricatorHeraldApplication.php', 'PhabricatorHeraldContentSource' => 'applications/herald/contentsource/PhabricatorHeraldContentSource.php', 'PhabricatorHexdumpDocumentEngine' => 'applications/files/document/PhabricatorHexdumpDocumentEngine.php', 'PhabricatorHighSecurityRequestExceptionHandler' => 'aphront/handler/PhabricatorHighSecurityRequestExceptionHandler.php', 'PhabricatorHomeApplication' => 'applications/home/application/PhabricatorHomeApplication.php', 'PhabricatorHomeConstants' => 'applications/home/constants/PhabricatorHomeConstants.php', 'PhabricatorHomeController' => 'applications/home/controller/PhabricatorHomeController.php', 'PhabricatorHomeLauncherProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeLauncherProfileMenuItem.php', 'PhabricatorHomeMenuItemController' => 'applications/home/controller/PhabricatorHomeMenuItemController.php', 'PhabricatorHomeProfileMenuEngine' => 'applications/home/engine/PhabricatorHomeProfileMenuEngine.php', 'PhabricatorHomeProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeProfileMenuItem.php', 'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php', 'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php', 'PhabricatorIDExportField' => 'infrastructure/export/field/PhabricatorIDExportField.php', 'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php', 'PhabricatorIDsSearchField' => 'applications/search/field/PhabricatorIDsSearchField.php', 'PhabricatorIconDatasource' => 'applications/files/typeahead/PhabricatorIconDatasource.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', 'PhabricatorImageDocumentEngine' => 'applications/files/document/PhabricatorImageDocumentEngine.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', 'PhabricatorIndexableInterface' => 'applications/search/interface/PhabricatorIndexableInterface.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', 'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php', 'PhabricatorIntEditField' => 'applications/transactions/editfield/PhabricatorIntEditField.php', 'PhabricatorIntExportField' => 'infrastructure/export/field/PhabricatorIntExportField.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', 'PhabricatorJSONConfigType' => 'applications/config/type/PhabricatorJSONConfigType.php', 'PhabricatorJSONDocumentEngine' => 'applications/files/document/PhabricatorJSONDocumentEngine.php', 'PhabricatorJSONExportFormat' => 'infrastructure/export/format/PhabricatorJSONExportFormat.php', 'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php', 'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php', 'PhabricatorJupyterDocumentEngine' => 'applications/files/document/PhabricatorJupyterDocumentEngine.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', 'PhabricatorLabelProfileMenuItem' => 'applications/search/menuitem/PhabricatorLabelProfileMenuItem.php', 'PhabricatorLanguageSettingsPanel' => 'applications/settings/panel/PhabricatorLanguageSettingsPanel.php', 'PhabricatorLegalpadApplication' => 'applications/legalpad/application/PhabricatorLegalpadApplication.php', 'PhabricatorLegalpadDocumentPHIDType' => 'applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php', 'PhabricatorLegalpadSignaturePolicyRule' => 'applications/legalpad/policyrule/PhabricatorLegalpadSignaturePolicyRule.php', 'PhabricatorLibraryTestCase' => '__tests__/PhabricatorLibraryTestCase.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', 'PhabricatorLiskExportEngineExtension' => 'infrastructure/export/engine/PhabricatorLiskExportEngineExtension.php', 'PhabricatorLiskFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorLiskFulltextEngineExtension.php', 'PhabricatorLiskSearchEngineExtension' => 'applications/search/engineextension/PhabricatorLiskSearchEngineExtension.php', 'PhabricatorLiskSerializer' => 'infrastructure/storage/lisk/PhabricatorLiskSerializer.php', 'PhabricatorListExportField' => 'infrastructure/export/field/PhabricatorListExportField.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', 'PhabricatorLockLogManagementWorkflow' => 'applications/daemon/management/PhabricatorLockLogManagementWorkflow.php', 'PhabricatorLockManagementWorkflow' => 'applications/daemon/management/PhabricatorLockManagementWorkflow.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', 'PhabricatorMacroAudioBehaviorTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php', 'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php', 'PhabricatorMacroAudioTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioTransaction.php', 'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php', 'PhabricatorMacroDatasource' => 'applications/macro/typeahead/PhabricatorMacroDatasource.php', 'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php', 'PhabricatorMacroDisabledTransaction' => 'applications/macro/xaction/PhabricatorMacroDisabledTransaction.php', 'PhabricatorMacroEditController' => 'applications/macro/controller/PhabricatorMacroEditController.php', 'PhabricatorMacroEditEngine' => 'applications/macro/editor/PhabricatorMacroEditEngine.php', 'PhabricatorMacroEditor' => 'applications/macro/editor/PhabricatorMacroEditor.php', 'PhabricatorMacroFileTransaction' => 'applications/macro/xaction/PhabricatorMacroFileTransaction.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', 'PhabricatorMacroNameTransaction' => 'applications/macro/xaction/PhabricatorMacroNameTransaction.php', 'PhabricatorMacroQuery' => 'applications/macro/query/PhabricatorMacroQuery.php', 'PhabricatorMacroReplyHandler' => 'applications/macro/mail/PhabricatorMacroReplyHandler.php', 'PhabricatorMacroSearchEngine' => 'applications/macro/query/PhabricatorMacroSearchEngine.php', 'PhabricatorMacroTestCase' => 'applications/macro/xaction/__tests__/PhabricatorMacroTestCase.php', 'PhabricatorMacroTransaction' => 'applications/macro/storage/PhabricatorMacroTransaction.php', 'PhabricatorMacroTransactionComment' => 'applications/macro/storage/PhabricatorMacroTransactionComment.php', 'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php', 'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php', 'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php', 'PhabricatorMailAdapter' => 'applications/metamta/adapter/PhabricatorMailAdapter.php', 'PhabricatorMailAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailAmazonSESAdapter.php', 'PhabricatorMailAmazonSNSAdapter' => 'applications/metamta/adapter/PhabricatorMailAmazonSNSAdapter.php', 'PhabricatorMailAttachment' => 'applications/metamta/message/PhabricatorMailAttachment.php', 'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php', 'PhabricatorMailEmailEngine' => 'applications/metamta/engine/PhabricatorMailEmailEngine.php', 'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php', 'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php', 'PhabricatorMailEmailMessage' => 'applications/metamta/message/PhabricatorMailEmailMessage.php', 'PhabricatorMailEmailSubjectHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailSubjectHeraldField.php', 'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php', 'PhabricatorMailExternalMessage' => 'applications/metamta/message/PhabricatorMailExternalMessage.php', 'PhabricatorMailHeader' => 'applications/metamta/message/PhabricatorMailHeader.php', 'PhabricatorMailMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailMailgunAdapter.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', 'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php', 'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php', 'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php', 'PhabricatorMailMessageEngine' => 'applications/metamta/engine/PhabricatorMailMessageEngine.php', 'PhabricatorMailMustEncryptHeraldAction' => 'applications/metamta/herald/PhabricatorMailMustEncryptHeraldAction.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', 'PhabricatorMailPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailPostmarkAdapter.php', 'PhabricatorMailPropertiesDestructionEngineExtension' => 'applications/metamta/engineextension/PhabricatorMailPropertiesDestructionEngineExtension.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', 'PhabricatorMailSMSEngine' => 'applications/metamta/engine/PhabricatorMailSMSEngine.php', 'PhabricatorMailSMSMessage' => 'applications/metamta/message/PhabricatorMailSMSMessage.php', 'PhabricatorMailSMTPAdapter' => 'applications/metamta/adapter/PhabricatorMailSMTPAdapter.php', 'PhabricatorMailSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailSendGridAdapter.php', 'PhabricatorMailSendmailAdapter' => 'applications/metamta/adapter/PhabricatorMailSendmailAdapter.php', 'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php', 'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php', 'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php', 'PhabricatorMailTestAdapter' => 'applications/metamta/adapter/PhabricatorMailTestAdapter.php', 'PhabricatorMailTwilioAdapter' => 'applications/metamta/adapter/PhabricatorMailTwilioAdapter.php', 'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php', 'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php', 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', 'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php', 'PhabricatorManageProfileMenuItem' => 'applications/search/menuitem/PhabricatorManageProfileMenuItem.php', 'PhabricatorManagementWorkflow' => 'infrastructure/management/PhabricatorManagementWorkflow.php', 'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php', 'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php', 'PhabricatorManiphestTaskFactEngine' => 'applications/fact/engine/PhabricatorManiphestTaskFactEngine.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', 'PhabricatorMemeEngine' => 'applications/macro/engine/PhabricatorMemeEngine.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', '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', 'PhabricatorMetaMTAMailProperties' => 'applications/metamta/storage/PhabricatorMetaMTAMailProperties.php', 'PhabricatorMetaMTAMailPropertiesQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.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', 'PhabricatorMetaMTAPostmarkReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.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', + 'PhabricatorMetronome' => 'infrastructure/util/PhabricatorMetronome.php', + 'PhabricatorMetronomeTestCase' => 'infrastructure/util/__tests__/PhabricatorMetronomeTestCase.php', 'PhabricatorMetronomicTriggerClock' => 'infrastructure/daemon/workers/clock/PhabricatorMetronomicTriggerClock.php', 'PhabricatorModularTransaction' => 'applications/transactions/storage/PhabricatorModularTransaction.php', 'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php', 'PhabricatorMonogramDatasourceEngineExtension' => 'applications/typeahead/engineextension/PhabricatorMonogramDatasourceEngineExtension.php', 'PhabricatorMonospacedFontSetting' => 'applications/settings/setting/PhabricatorMonospacedFontSetting.php', 'PhabricatorMonospacedTextareasSetting' => 'applications/settings/setting/PhabricatorMonospacedTextareasSetting.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', 'PhabricatorMutedByEdgeType' => 'applications/transactions/edges/PhabricatorMutedByEdgeType.php', 'PhabricatorMutedEdgeType' => 'applications/transactions/edges/PhabricatorMutedEdgeType.php', 'PhabricatorMySQLConfigOptions' => 'applications/config/option/PhabricatorMySQLConfigOptions.php', 'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php', 'PhabricatorMySQLSearchHost' => 'infrastructure/cluster/search/PhabricatorMySQLSearchHost.php', 'PhabricatorMySQLSetupCheck' => 'applications/config/check/PhabricatorMySQLSetupCheck.php', 'PhabricatorNamedQuery' => 'applications/search/storage/PhabricatorNamedQuery.php', 'PhabricatorNamedQueryConfig' => 'applications/search/storage/PhabricatorNamedQueryConfig.php', 'PhabricatorNamedQueryConfigQuery' => 'applications/search/query/PhabricatorNamedQueryConfigQuery.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', 'PhabricatorNotificationServersConfigType' => 'applications/notification/config/PhabricatorNotificationServersConfigType.php', 'PhabricatorNotificationStatusView' => 'applications/notification/view/PhabricatorNotificationStatusView.php', 'PhabricatorNotificationTestController' => 'applications/notification/controller/PhabricatorNotificationTestController.php', 'PhabricatorNotificationUIExample' => 'applications/uiexample/examples/PhabricatorNotificationUIExample.php', 'PhabricatorNotificationsApplication' => 'applications/notification/application/PhabricatorNotificationsApplication.php', 'PhabricatorNotificationsSetting' => 'applications/settings/setting/PhabricatorNotificationsSetting.php', 'PhabricatorNotificationsSettingsPanel' => 'applications/settings/panel/PhabricatorNotificationsSettingsPanel.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', 'PhabricatorObjectHasDraftEdgeType' => 'applications/transactions/edges/PhabricatorObjectHasDraftEdgeType.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', 'PhabricatorObjectStatus' => 'infrastructure/status/PhabricatorObjectStatus.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', + 'PhabricatorOwnersAuditRule' => 'applications/owners/constants/PhabricatorOwnersAuditRule.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', 'PhabricatorOwnersHovercardEngineExtension' => 'applications/owners/engineextension/PhabricatorOwnersHovercardEngineExtension.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', 'PhabricatorOwnersPackageContextFreeGrammar' => 'applications/owners/lipsum/PhabricatorOwnersPackageContextFreeGrammar.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', 'PhabricatorOwnersPackageFerretEngine' => 'applications/owners/search/PhabricatorOwnersPackageFerretEngine.php', 'PhabricatorOwnersPackageFulltextEngine' => 'applications/owners/search/PhabricatorOwnersPackageFulltextEngine.php', 'PhabricatorOwnersPackageFunctionDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php', 'PhabricatorOwnersPackageIgnoredTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageIgnoredTransaction.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', 'PhabricatorOwnersPackageTestDataGenerator' => 'applications/owners/lipsum/PhabricatorOwnersPackageTestDataGenerator.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', 'PhabricatorOwnersPathContextFreeGrammar' => 'applications/owners/lipsum/PhabricatorOwnersPathContextFreeGrammar.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', 'PhabricatorPDFDocumentEngine' => 'applications/files/document/PhabricatorPDFDocumentEngine.php', 'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php', 'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php', 'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php', 'PhabricatorPHIDExportField' => 'infrastructure/export/field/PhabricatorPHIDExportField.php', 'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php', 'PhabricatorPHIDListEditField' => 'applications/transactions/editfield/PhabricatorPHIDListEditField.php', 'PhabricatorPHIDListEditType' => 'applications/transactions/edittype/PhabricatorPHIDListEditType.php', 'PhabricatorPHIDListExportField' => 'infrastructure/export/field/PhabricatorPHIDListExportField.php', 'PhabricatorPHIDMailStamp' => 'applications/metamta/stamp/PhabricatorPHIDMailStamp.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', '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', 'PhabricatorPasswordDestructionEngineExtension' => 'applications/auth/extension/PhabricatorPasswordDestructionEngineExtension.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', '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', 'PhabricatorPeopleAvailabilitySearchEngineAttachment' => 'applications/people/engineextension/PhabricatorPeopleAvailabilitySearchEngineAttachment.php', 'PhabricatorPeopleBadgesProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleBadgesProfileMenuItem.php', 'PhabricatorPeopleCommitsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleCommitsProfileMenuItem.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', 'PhabricatorPeopleDatasourceEngineExtension' => 'applications/people/engineextension/PhabricatorPeopleDatasourceEngineExtension.php', 'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.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', 'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php', 'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php', 'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php', 'PhabricatorPeopleManagementWorkflow' => 'applications/people/management/PhabricatorPeopleManagementWorkflow.php', 'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php', 'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php', 'PhabricatorPeopleOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleOwnerDatasource.php', 'PhabricatorPeoplePictureProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeoplePictureProfileMenuItem.php', 'PhabricatorPeopleProfileBadgesController' => 'applications/people/controller/PhabricatorPeopleProfileBadgesController.php', 'PhabricatorPeopleProfileCommitsController' => 'applications/people/controller/PhabricatorPeopleProfileCommitsController.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php', 'PhabricatorPeopleProfileImageWorkflow' => 'applications/people/management/PhabricatorPeopleProfileImageWorkflow.php', 'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php', 'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php', 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', 'PhabricatorPeopleProfileRevisionsController' => 'applications/people/controller/PhabricatorPeopleProfileRevisionsController.php', 'PhabricatorPeopleProfileTasksController' => 'applications/people/controller/PhabricatorPeopleProfileTasksController.php', 'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php', 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php', 'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', 'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php', 'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', 'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.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', + 'PhabricatorPeopleUsernameMailEngine' => 'applications/people/mail/PhabricatorPeopleUsernameMailEngine.php', 'PhabricatorPeopleWelcomeController' => 'applications/people/controller/PhabricatorPeopleWelcomeController.php', 'PhabricatorPeopleWelcomeMailEngine' => 'applications/people/mail/PhabricatorPeopleWelcomeMailEngine.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', 'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php', 'PhabricatorPhoneNumber' => 'applications/metamta/message/PhabricatorPhoneNumber.php', 'PhabricatorPhoneNumberTestCase' => 'applications/metamta/message/__tests__/PhabricatorPhoneNumberTestCase.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', 'PhabricatorPhortuneTestCase' => 'applications/phortune/__tests__/PhabricatorPhortuneTestCase.php', 'PhabricatorPhragmentApplication' => 'applications/phragment/application/PhabricatorPhragmentApplication.php', 'PhabricatorPhrequentApplication' => 'applications/phrequent/application/PhabricatorPhrequentApplication.php', 'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.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', 'PhabricatorPhurlURLAliasTransaction' => 'applications/phurl/xaction/PhabricatorPhurlURLAliasTransaction.php', 'PhabricatorPhurlURLCreateCapability' => 'applications/phurl/capability/PhabricatorPhurlURLCreateCapability.php', 'PhabricatorPhurlURLDatasource' => 'applications/phurl/typeahead/PhabricatorPhurlURLDatasource.php', 'PhabricatorPhurlURLDescriptionTransaction' => 'applications/phurl/xaction/PhabricatorPhurlURLDescriptionTransaction.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', 'PhabricatorPhurlURLLongURLTransaction' => 'applications/phurl/xaction/PhabricatorPhurlURLLongURLTransaction.php', 'PhabricatorPhurlURLMailReceiver' => 'applications/phurl/mail/PhabricatorPhurlURLMailReceiver.php', 'PhabricatorPhurlURLNameNgrams' => 'applications/phurl/storage/PhabricatorPhurlURLNameNgrams.php', 'PhabricatorPhurlURLNameTransaction' => 'applications/phurl/xaction/PhabricatorPhurlURLNameTransaction.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', 'PhabricatorPhurlURLTransactionType' => 'applications/phurl/xaction/PhabricatorPhurlURLTransactionType.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', 'PhabricatorPointsFact' => 'applications/fact/fact/PhabricatorPointsFact.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', 'PhabricatorPolicyCanInteractCapability' => 'applications/policy/capability/PhabricatorPolicyCanInteractCapability.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', 'PhabricatorPolicyStrengthConstants' => 'applications/policy/constants/PhabricatorPolicyStrengthConstants.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', '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', 'PhabricatorProjectBuiltinsExample' => 'applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php', 'PhabricatorProjectCardView' => 'applications/project/view/PhabricatorProjectCardView.php', 'PhabricatorProjectColorTransaction' => 'applications/project/xaction/PhabricatorProjectColorTransaction.php', 'PhabricatorProjectColorsConfigType' => 'applications/project/config/PhabricatorProjectColorsConfigType.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', 'PhabricatorProjectColumnSearchEngine' => 'applications/project/query/PhabricatorProjectColumnSearchEngine.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', 'PhabricatorProjectDetailsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php', 'PhabricatorProjectEditController' => 'applications/project/controller/PhabricatorProjectEditController.php', 'PhabricatorProjectEditEngine' => 'applications/project/engine/PhabricatorProjectEditEngine.php', 'PhabricatorProjectEditPictureController' => 'applications/project/controller/PhabricatorProjectEditPictureController.php', 'PhabricatorProjectFerretEngine' => 'applications/project/search/PhabricatorProjectFerretEngine.php', 'PhabricatorProjectFilterTransaction' => 'applications/project/xaction/PhabricatorProjectFilterTransaction.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', 'PhabricatorProjectIconTransaction' => 'applications/project/xaction/PhabricatorProjectIconTransaction.php', 'PhabricatorProjectIconsConfigType' => 'applications/project/config/PhabricatorProjectIconsConfigType.php', 'PhabricatorProjectImageTransaction' => 'applications/project/xaction/PhabricatorProjectImageTransaction.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', 'PhabricatorProjectLockTransaction' => 'applications/project/xaction/PhabricatorProjectLockTransaction.php', 'PhabricatorProjectLogicalAncestorDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalAncestorDatasource.php', 'PhabricatorProjectLogicalDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalDatasource.php', 'PhabricatorProjectLogicalOnlyDatasource' => 'applications/project/typeahead/PhabricatorProjectLogicalOnlyDatasource.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', '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', 'PhabricatorProjectMembersProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php', 'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php', 'PhabricatorProjectMembersViewController' => 'applications/project/controller/PhabricatorProjectMembersViewController.php', 'PhabricatorProjectMenuItemController' => 'applications/project/controller/PhabricatorProjectMenuItemController.php', 'PhabricatorProjectMilestoneTransaction' => 'applications/project/xaction/PhabricatorProjectMilestoneTransaction.php', 'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php', 'PhabricatorProjectNameContextFreeGrammar' => 'applications/project/lipsum/PhabricatorProjectNameContextFreeGrammar.php', 'PhabricatorProjectNameTransaction' => 'applications/project/xaction/PhabricatorProjectNameTransaction.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', 'PhabricatorProjectParentTransaction' => 'applications/project/xaction/PhabricatorProjectParentTransaction.php', 'PhabricatorProjectPictureProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php', 'PhabricatorProjectPointsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectPointsProfileMenuItem.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.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', 'PhabricatorProjectSlugsTransaction' => 'applications/project/xaction/PhabricatorProjectSlugsTransaction.php', 'PhabricatorProjectSortTransaction' => 'applications/project/xaction/PhabricatorProjectSortTransaction.php', 'PhabricatorProjectStandardCustomField' => 'applications/project/customfield/PhabricatorProjectStandardCustomField.php', 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectStatusTransaction' => 'applications/project/xaction/PhabricatorProjectStatusTransaction.php', 'PhabricatorProjectSubprojectWarningController' => 'applications/project/controller/PhabricatorProjectSubprojectWarningController.php', 'PhabricatorProjectSubprojectsController' => 'applications/project/controller/PhabricatorProjectSubprojectsController.php', 'PhabricatorProjectSubprojectsProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php', 'PhabricatorProjectSubtypeDatasource' => 'applications/project/typeahead/PhabricatorProjectSubtypeDatasource.php', 'PhabricatorProjectSubtypesConfigType' => 'applications/project/config/PhabricatorProjectSubtypesConfigType.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', 'PhabricatorProjectTransactionType' => 'applications/project/xaction/PhabricatorProjectTransactionType.php', 'PhabricatorProjectTypeTransaction' => 'applications/project/xaction/PhabricatorProjectTypeTransaction.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', 'PhabricatorProjectWorkboardBackgroundTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardBackgroundTransaction.php', 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', 'PhabricatorProjectWorkboardTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardTransaction.php', 'PhabricatorProjectsAllPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php', 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php', 'PhabricatorProjectsBasePolicyRule' => 'applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php', 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', 'PhabricatorProjectsExportEngineExtension' => 'infrastructure/export/engine/PhabricatorProjectsExportEngineExtension.php', 'PhabricatorProjectsFulltextEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsFulltextEngineExtension.php', 'PhabricatorProjectsMailEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMailEngineExtension.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', 'PhabricatorPygmentSetupCheck' => 'applications/config/check/PhabricatorPygmentSetupCheck.php', 'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php', 'PhabricatorQueryConstraint' => 'infrastructure/query/constraint/PhabricatorQueryConstraint.php', 'PhabricatorQueryIterator' => 'infrastructure/storage/lisk/PhabricatorQueryIterator.php', 'PhabricatorQueryOrderItem' => 'infrastructure/query/order/PhabricatorQueryOrderItem.php', 'PhabricatorQueryOrderTestCase' => 'infrastructure/query/order/__tests__/PhabricatorQueryOrderTestCase.php', 'PhabricatorQueryOrderVector' => 'infrastructure/query/order/PhabricatorQueryOrderVector.php', 'PhabricatorQuickSearchEngineExtension' => 'applications/search/engineextension/PhabricatorQuickSearchEngineExtension.php', 'PhabricatorRateLimitRequestExceptionHandler' => 'aphront/handler/PhabricatorRateLimitRequestExceptionHandler.php', 'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php', 'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php', 'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php', 'PhabricatorRegexListConfigType' => 'applications/config/type/PhabricatorRegexListConfigType.php', 'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php', 'PhabricatorReleephApplication' => 'applications/releeph/application/PhabricatorReleephApplication.php', 'PhabricatorReleephApplicationConfigOptions' => 'applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php', 'PhabricatorRemarkupCachePurger' => 'applications/cache/purger/PhabricatorRemarkupCachePurger.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', 'PhabricatorRemarkupDocumentEngine' => 'applications/files/document/PhabricatorRemarkupDocumentEngine.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', 'PhabricatorRepositoryActivateTransaction' => 'applications/repository/xaction/PhabricatorRepositoryActivateTransaction.php', 'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/PhabricatorRepositoryAuditRequest.php', 'PhabricatorRepositoryAutocloseOnlyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryAutocloseOnlyTransaction.php', 'PhabricatorRepositoryAutocloseTransaction' => 'applications/repository/xaction/PhabricatorRepositoryAutocloseTransaction.php', 'PhabricatorRepositoryBlueprintsTransaction' => 'applications/repository/xaction/PhabricatorRepositoryBlueprintsTransaction.php', 'PhabricatorRepositoryBranch' => 'applications/repository/storage/PhabricatorRepositoryBranch.php', 'PhabricatorRepositoryCallsignTransaction' => 'applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.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', 'PhabricatorRepositoryCopyTimeLimitTransaction' => 'applications/repository/xaction/PhabricatorRepositoryCopyTimeLimitTransaction.php', 'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php', 'PhabricatorRepositoryDangerousTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDangerousTransaction.php', 'PhabricatorRepositoryDefaultBranchTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDefaultBranchTransaction.php', 'PhabricatorRepositoryDescriptionTransaction' => 'applications/repository/xaction/PhabricatorRepositoryDescriptionTransaction.php', 'PhabricatorRepositoryDestructibleCodex' => 'applications/repository/codex/PhabricatorRepositoryDestructibleCodex.php', 'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php', 'PhabricatorRepositoryEditor' => 'applications/repository/editor/PhabricatorRepositoryEditor.php', 'PhabricatorRepositoryEncodingTransaction' => 'applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php', 'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php', 'PhabricatorRepositoryEnormousTransaction' => 'applications/repository/xaction/PhabricatorRepositoryEnormousTransaction.php', 'PhabricatorRepositoryFerretEngine' => 'applications/repository/search/PhabricatorRepositoryFerretEngine.php', 'PhabricatorRepositoryFilesizeLimitTransaction' => 'applications/repository/xaction/PhabricatorRepositoryFilesizeLimitTransaction.php', 'PhabricatorRepositoryFulltextEngine' => 'applications/repository/search/PhabricatorRepositoryFulltextEngine.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', 'PhabricatorRepositoryIdentity' => 'applications/repository/storage/PhabricatorRepositoryIdentity.php', 'PhabricatorRepositoryIdentityAssignTransaction' => 'applications/repository/xaction/PhabricatorRepositoryIdentityAssignTransaction.php', 'PhabricatorRepositoryIdentityChangeWorker' => 'applications/repository/worker/PhabricatorRepositoryIdentityChangeWorker.php', 'PhabricatorRepositoryIdentityEditEngine' => 'applications/repository/engine/PhabricatorRepositoryIdentityEditEngine.php', 'PhabricatorRepositoryIdentityFerretEngine' => 'applications/repository/search/PhabricatorRepositoryIdentityFerretEngine.php', 'PhabricatorRepositoryIdentityPHIDType' => 'applications/repository/phid/PhabricatorRepositoryIdentityPHIDType.php', 'PhabricatorRepositoryIdentityQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityQuery.php', 'PhabricatorRepositoryIdentityTransaction' => 'applications/repository/storage/PhabricatorRepositoryIdentityTransaction.php', 'PhabricatorRepositoryIdentityTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryIdentityTransactionQuery.php', 'PhabricatorRepositoryIdentityTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryIdentityTransactionType.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', 'PhabricatorRepositoryManagementRebuildIdentitiesWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementRebuildIdentitiesWorkflow.php', 'PhabricatorRepositoryManagementRefsWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementRefsWorkflow.php', 'PhabricatorRepositoryManagementReparseWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementReparseWorkflow.php', 'PhabricatorRepositoryManagementThawWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php', 'PhabricatorRepositoryManagementUnpublishWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementUnpublishWorkflow.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', 'PhabricatorRepositoryNameTransaction' => 'applications/repository/xaction/PhabricatorRepositoryNameTransaction.php', 'PhabricatorRepositoryNotifyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryNotifyTransaction.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', 'PhabricatorRepositoryPullLocalDaemonModule' => 'applications/repository/daemon/PhabricatorRepositoryPullLocalDaemonModule.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', 'PhabricatorRepositoryPushPolicyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryPushPolicyTransaction.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', 'PhabricatorRepositoryRefPosition' => 'applications/repository/storage/PhabricatorRepositoryRefPosition.php', 'PhabricatorRepositoryRepositoryPHIDType' => 'applications/repository/phid/PhabricatorRepositoryRepositoryPHIDType.php', 'PhabricatorRepositorySVNSubpathTransaction' => 'applications/repository/xaction/PhabricatorRepositorySVNSubpathTransaction.php', 'PhabricatorRepositorySchemaSpec' => 'applications/repository/storage/PhabricatorRepositorySchemaSpec.php', 'PhabricatorRepositorySearchEngine' => 'applications/repository/query/PhabricatorRepositorySearchEngine.php', 'PhabricatorRepositoryServiceTransaction' => 'applications/repository/xaction/PhabricatorRepositoryServiceTransaction.php', 'PhabricatorRepositorySlugTransaction' => 'applications/repository/xaction/PhabricatorRepositorySlugTransaction.php', 'PhabricatorRepositoryStagingURITransaction' => 'applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.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', 'PhabricatorRepositorySymbolLanguagesTransaction' => 'applications/repository/xaction/PhabricatorRepositorySymbolLanguagesTransaction.php', 'PhabricatorRepositorySymbolSourcesTransaction' => 'applications/repository/xaction/PhabricatorRepositorySymbolSourcesTransaction.php', 'PhabricatorRepositorySyncEvent' => 'applications/repository/storage/PhabricatorRepositorySyncEvent.php', 'PhabricatorRepositorySyncEventPHIDType' => 'applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php', 'PhabricatorRepositorySyncEventQuery' => 'applications/repository/query/PhabricatorRepositorySyncEventQuery.php', 'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php', 'PhabricatorRepositoryTouchLimitTransaction' => 'applications/repository/xaction/PhabricatorRepositoryTouchLimitTransaction.php', 'PhabricatorRepositoryTrackOnlyTransaction' => 'applications/repository/xaction/PhabricatorRepositoryTrackOnlyTransaction.php', 'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php', 'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php', 'PhabricatorRepositoryTransactionType' => 'applications/repository/xaction/PhabricatorRepositoryTransactionType.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', 'PhabricatorRepositoryVCSTransaction' => 'applications/repository/xaction/PhabricatorRepositoryVCSTransaction.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', 'PhabricatorSMSAuthFactor' => 'applications/auth/factor/PhabricatorSMSAuthFactor.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', 'PhabricatorSearchConstraintException' => 'applications/search/exception/PhabricatorSearchConstraintException.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', 'PhabricatorSearchDefaultController' => 'applications/search/controller/PhabricatorSearchDefaultController.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', 'PhabricatorSearchFerretNgramGarbageCollector' => 'applications/search/garbagecollector/PhabricatorSearchFerretNgramGarbageCollector.php', 'PhabricatorSearchField' => 'applications/search/field/PhabricatorSearchField.php', 'PhabricatorSearchHost' => 'infrastructure/cluster/search/PhabricatorSearchHost.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', 'PhabricatorSearchManagementNgramsWorkflow' => 'applications/search/management/PhabricatorSearchManagementNgramsWorkflow.php', 'PhabricatorSearchManagementQueryWorkflow' => 'applications/search/management/PhabricatorSearchManagementQueryWorkflow.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', 'PhabricatorSearchService' => 'infrastructure/cluster/search/PhabricatorSearchService.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', 'PhabricatorSessionsSettingsPanel' => 'applications/settings/panel/PhabricatorSessionsSettingsPanel.php', 'PhabricatorSetConfigType' => 'applications/config/type/PhabricatorSetConfigType.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', 'PhabricatorSettingsIssueController' => 'applications/settings/controller/PhabricatorSettingsIssueController.php', 'PhabricatorSettingsListController' => 'applications/settings/controller/PhabricatorSettingsListController.php', 'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php', 'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.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', 'PhabricatorSlowvoteCloseTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteCloseTransaction.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', 'PhabricatorSlowvoteDescriptionTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteDescriptionTransaction.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', 'PhabricatorSlowvoteQuestionTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteQuestionTransaction.php', 'PhabricatorSlowvoteReplyHandler' => 'applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php', 'PhabricatorSlowvoteResponsesTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteResponsesTransaction.php', 'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php', 'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php', 'PhabricatorSlowvoteShuffleTransaction' => 'applications/slowvote/xaction/PhabricatorSlowvoteShuffleTransaction.php', 'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php', 'PhabricatorSlowvoteTransactionComment' => 'applications/slowvote/storage/PhabricatorSlowvoteTransactionComment.php', 'PhabricatorSlowvoteTransactionQuery' => 'applications/slowvote/query/PhabricatorSlowvoteTransactionQuery.php', 'PhabricatorSlowvoteTransactionType' => 'applications/slowvote/xaction/PhabricatorSlowvoteTransactionType.php', 'PhabricatorSlowvoteVoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteVoteController.php', 'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php', 'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php', 'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php', 'PhabricatorSourceDocumentEngine' => 'applications/files/document/PhabricatorSourceDocumentEngine.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', 'PhabricatorSpacesExportEngineExtension' => 'infrastructure/export/engine/PhabricatorSpacesExportEngineExtension.php', 'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php', 'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php', 'PhabricatorSpacesMailEngineExtension' => 'applications/spaces/engineextension/PhabricatorSpacesMailEngineExtension.php', 'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php', 'PhabricatorSpacesNamespaceArchiveTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php', 'PhabricatorSpacesNamespaceDatasource' => 'applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php', 'PhabricatorSpacesNamespaceDefaultTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceDefaultTransaction.php', 'PhabricatorSpacesNamespaceDescriptionTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceDescriptionTransaction.php', 'PhabricatorSpacesNamespaceEditor' => 'applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php', 'PhabricatorSpacesNamespaceNameTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceNameTransaction.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', 'PhabricatorSpacesNamespaceTransactionType' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceTransactionType.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', 'PhabricatorStandardTimelineEngine' => 'applications/transactions/engine/PhabricatorStandardTimelineEngine.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', 'PhabricatorStorageManagementAnalyzeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementAnalyzeWorkflow.php', 'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php', 'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php', 'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php', 'PhabricatorStorageManagementOptimizeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementOptimizeWorkflow.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', 'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php', 'PhabricatorStringExportField' => 'infrastructure/export/field/PhabricatorStringExportField.php', 'PhabricatorStringListConfigType' => 'applications/config/type/PhabricatorStringListConfigType.php', 'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php', 'PhabricatorStringListExportField' => 'infrastructure/export/field/PhabricatorStringListExportField.php', 'PhabricatorStringMailStamp' => 'applications/metamta/stamp/PhabricatorStringMailStamp.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', 'PhabricatorSubscriptionsExportEngineExtension' => 'infrastructure/export/engine/PhabricatorSubscriptionsExportEngineExtension.php', 'PhabricatorSubscriptionsFulltextEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsFulltextEngineExtension.php', 'PhabricatorSubscriptionsHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php', 'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.php', 'PhabricatorSubscriptionsMailEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsMailEngineExtension.php', 'PhabricatorSubscriptionsMuteController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsMuteController.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', 'PhabricatorSubtypeEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorSubtypeEditEngineExtension.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', 'PhabricatorSystemObjectController' => 'applications/system/controller/PhabricatorSystemObjectController.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', 'PhabricatorTaskmasterDaemonModule' => 'infrastructure/daemon/workers/PhabricatorTaskmasterDaemonModule.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', 'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php', 'PhabricatorTextDocumentEngine' => 'applications/files/document/PhabricatorTextDocumentEngine.php', 'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php', 'PhabricatorTextExportFormat' => 'infrastructure/export/format/PhabricatorTextExportFormat.php', 'PhabricatorTextListConfigType' => 'applications/config/type/PhabricatorTextListConfigType.php', 'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php', 'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php', 'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php', 'PhabricatorTimeTestCase' => 'infrastructure/time/__tests__/PhabricatorTimeTestCase.php', 'PhabricatorTimelineEngine' => 'applications/transactions/engine/PhabricatorTimelineEngine.php', 'PhabricatorTimelineInterface' => 'applications/transactions/interface/PhabricatorTimelineInterface.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', 'PhabricatorTransactionChange' => 'applications/transactions/data/PhabricatorTransactionChange.php', 'PhabricatorTransactionFactEngine' => 'applications/fact/engine/PhabricatorTransactionFactEngine.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', 'PhabricatorTwilioFuture' => 'applications/metamta/future/PhabricatorTwilioFuture.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', 'PhabricatorTypeaheadProxyDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadProxyDatasource.php', 'PhabricatorTypeaheadResult' => 'applications/typeahead/storage/PhabricatorTypeaheadResult.php', 'PhabricatorTypeaheadRuntimeCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadRuntimeCompositeDatasource.php', 'PhabricatorTypeaheadTestNumbersDatasource' => 'applications/typeahead/datasource/__tests__/PhabricatorTypeaheadTestNumbersDatasource.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', 'PhabricatorURIExportField' => 'infrastructure/export/field/PhabricatorURIExportField.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', 'PhabricatorUserApproveTransaction' => 'applications/people/xaction/PhabricatorUserApproveTransaction.php', 'PhabricatorUserBadgesCacheType' => 'applications/people/cache/PhabricatorUserBadgesCacheType.php', 'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php', 'PhabricatorUserCache' => 'applications/people/storage/PhabricatorUserCache.php', 'PhabricatorUserCachePurger' => 'applications/cache/purger/PhabricatorUserCachePurger.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', 'PhabricatorUserDisableTransaction' => 'applications/people/xaction/PhabricatorUserDisableTransaction.php', 'PhabricatorUserEditEngine' => 'applications/people/editor/PhabricatorUserEditEngine.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', 'PhabricatorUserEmpowerTransaction' => 'applications/people/xaction/PhabricatorUserEmpowerTransaction.php', 'PhabricatorUserFerretEngine' => 'applications/people/search/PhabricatorUserFerretEngine.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', 'PhabricatorUserNotifyTransaction' => 'applications/people/xaction/PhabricatorUserNotifyTransaction.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', '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', 'PhabricatorUserTransactionEditor' => 'applications/people/editor/PhabricatorUserTransactionEditor.php', 'PhabricatorUserTransactionType' => 'applications/people/xaction/PhabricatorUserTransactionType.php', 'PhabricatorUserUsernameTransaction' => 'applications/people/xaction/PhabricatorUserUsernameTransaction.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', 'PhabricatorVideoDocumentEngine' => 'applications/files/document/PhabricatorVideoDocumentEngine.php', 'PhabricatorViewerDatasource' => 'applications/people/typeahead/PhabricatorViewerDatasource.php', 'PhabricatorVoidDocumentEngine' => 'applications/files/document/PhabricatorVoidDocumentEngine.php', 'PhabricatorWatcherHasObjectEdgeType' => 'applications/transactions/edges/PhabricatorWatcherHasObjectEdgeType.php', 'PhabricatorWebContentSource' => 'infrastructure/contentsource/PhabricatorWebContentSource.php', 'PhabricatorWebServerSetupCheck' => 'applications/config/check/PhabricatorWebServerSetupCheck.php', 'PhabricatorWeekStartDaySetting' => 'applications/settings/setting/PhabricatorWeekStartDaySetting.php', 'PhabricatorWildConfigType' => 'applications/config/type/PhabricatorWildConfigType.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', 'PhabricatorWorkerSingleBulkJobType' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerSingleBulkJobType.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', 'PhabricatorXHProfDropController' => 'applications/xhprof/controller/PhabricatorXHProfDropController.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', 'PhabricatorXHProfSampleQuery' => 'applications/xhprof/query/PhabricatorXHProfSampleQuery.php', 'PhabricatorXHProfSampleSearchEngine' => 'applications/xhprof/query/PhabricatorXHProfSampleSearchEngine.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', 'PhameBlogDescriptionTransaction' => 'applications/phame/xaction/PhameBlogDescriptionTransaction.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', 'PhameBlogFerretEngine' => 'applications/phame/search/PhameBlogFerretEngine.php', 'PhameBlogFullDomainTransaction' => 'applications/phame/xaction/PhameBlogFullDomainTransaction.php', 'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php', 'PhameBlogHeaderImageTransaction' => 'applications/phame/xaction/PhameBlogHeaderImageTransaction.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', 'PhameBlogNameTransaction' => 'applications/phame/xaction/PhameBlogNameTransaction.php', 'PhameBlogParentDomainTransaction' => 'applications/phame/xaction/PhameBlogParentDomainTransaction.php', 'PhameBlogParentSiteTransaction' => 'applications/phame/xaction/PhameBlogParentSiteTransaction.php', 'PhameBlogProfileImageTransaction' => 'applications/phame/xaction/PhameBlogProfileImageTransaction.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', 'PhameBlogStatusTransaction' => 'applications/phame/xaction/PhameBlogStatusTransaction.php', 'PhameBlogSubtitleTransaction' => 'applications/phame/xaction/PhameBlogSubtitleTransaction.php', 'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php', 'PhameBlogTransactionQuery' => 'applications/phame/query/PhameBlogTransactionQuery.php', 'PhameBlogTransactionType' => 'applications/phame/xaction/PhameBlogTransactionType.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', 'PhamePostBlogTransaction' => 'applications/phame/xaction/PhamePostBlogTransaction.php', 'PhamePostBodyTransaction' => 'applications/phame/xaction/PhamePostBodyTransaction.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', 'PhamePostFerretEngine' => 'applications/phame/search/PhamePostFerretEngine.php', 'PhamePostFulltextEngine' => 'applications/phame/search/PhamePostFulltextEngine.php', 'PhamePostHeaderImageTransaction' => 'applications/phame/xaction/PhamePostHeaderImageTransaction.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', 'PhamePostSubtitleTransaction' => 'applications/phame/xaction/PhamePostSubtitleTransaction.php', 'PhamePostTitleTransaction' => 'applications/phame/xaction/PhamePostTitleTransaction.php', 'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php', 'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php', 'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php', 'PhamePostTransactionType' => 'applications/phame/xaction/PhamePostTransactionType.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', 'PhamePostVisibilityTransaction' => 'applications/phame/xaction/PhamePostVisibilityTransaction.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', 'PhluxSchemaSpec' => 'applications/phlux/storage/PhluxSchemaSpec.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', 'PholioImageDescriptionTransaction' => 'applications/pholio/xaction/PholioImageDescriptionTransaction.php', 'PholioImageFileTransaction' => 'applications/pholio/xaction/PholioImageFileTransaction.php', 'PholioImageNameTransaction' => 'applications/pholio/xaction/PholioImageNameTransaction.php', 'PholioImagePHIDType' => 'applications/pholio/phid/PholioImagePHIDType.php', 'PholioImageQuery' => 'applications/pholio/query/PholioImageQuery.php', 'PholioImageReplaceTransaction' => 'applications/pholio/xaction/PholioImageReplaceTransaction.php', 'PholioImageSequenceTransaction' => 'applications/pholio/xaction/PholioImageSequenceTransaction.php', 'PholioImageTransactionType' => 'applications/pholio/xaction/PholioImageTransactionType.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', 'PholioMockDescriptionTransaction' => 'applications/pholio/xaction/PholioMockDescriptionTransaction.php', 'PholioMockEditController' => 'applications/pholio/controller/PholioMockEditController.php', 'PholioMockEditor' => 'applications/pholio/editor/PholioMockEditor.php', 'PholioMockEmbedView' => 'applications/pholio/view/PholioMockEmbedView.php', 'PholioMockFerretEngine' => 'applications/pholio/search/PholioMockFerretEngine.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', 'PholioMockInlineTransaction' => 'applications/pholio/xaction/PholioMockInlineTransaction.php', 'PholioMockListController' => 'applications/pholio/controller/PholioMockListController.php', 'PholioMockMailReceiver' => 'applications/pholio/mail/PholioMockMailReceiver.php', 'PholioMockNameHeraldField' => 'applications/pholio/herald/PholioMockNameHeraldField.php', 'PholioMockNameTransaction' => 'applications/pholio/xaction/PholioMockNameTransaction.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', 'PholioMockStatusTransaction' => 'applications/pholio/xaction/PholioMockStatusTransaction.php', 'PholioMockThumbGridView' => 'applications/pholio/view/PholioMockThumbGridView.php', 'PholioMockTimelineEngine' => 'applications/pholio/engine/PholioMockTimelineEngine.php', 'PholioMockTransactionType' => 'applications/pholio/xaction/PholioMockTransactionType.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', 'PholioTransactionType' => 'applications/pholio/xaction/PholioTransactionType.php', 'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php', 'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php', 'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php', 'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php', 'PhortuneAccountBillingAddressTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingAddressTransaction.php', 'PhortuneAccountBillingController' => 'applications/phortune/controller/account/PhortuneAccountBillingController.php', 'PhortuneAccountBillingNameTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingNameTransaction.php', 'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php', 'PhortuneAccountController' => 'applications/phortune/controller/account/PhortuneAccountController.php', 'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php', 'PhortuneAccountEditEngine' => 'applications/phortune/editor/PhortuneAccountEditEngine.php', 'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php', 'PhortuneAccountHasMemberEdgeType' => 'applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php', 'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php', 'PhortuneAccountManagerController' => 'applications/phortune/controller/account/PhortuneAccountManagerController.php', 'PhortuneAccountNameTransaction' => 'applications/phortune/xaction/PhortuneAccountNameTransaction.php', 'PhortuneAccountPHIDType' => 'applications/phortune/phid/PhortuneAccountPHIDType.php', 'PhortuneAccountProfileController' => 'applications/phortune/controller/account/PhortuneAccountProfileController.php', 'PhortuneAccountQuery' => 'applications/phortune/query/PhortuneAccountQuery.php', 'PhortuneAccountSubscriptionController' => 'applications/phortune/controller/account/PhortuneAccountSubscriptionController.php', 'PhortuneAccountTransaction' => 'applications/phortune/storage/PhortuneAccountTransaction.php', 'PhortuneAccountTransactionQuery' => 'applications/phortune/query/PhortuneAccountTransactionQuery.php', 'PhortuneAccountTransactionType' => 'applications/phortune/xaction/PhortuneAccountTransactionType.php', 'PhortuneAccountViewController' => 'applications/phortune/controller/account/PhortuneAccountViewController.php', 'PhortuneAdHocCart' => 'applications/phortune/cart/PhortuneAdHocCart.php', 'PhortuneAdHocProduct' => 'applications/phortune/product/PhortuneAdHocProduct.php', 'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php', 'PhortuneCartAcceptController' => 'applications/phortune/controller/cart/PhortuneCartAcceptController.php', 'PhortuneCartCancelController' => 'applications/phortune/controller/cart/PhortuneCartCancelController.php', 'PhortuneCartCheckoutController' => 'applications/phortune/controller/cart/PhortuneCartCheckoutController.php', 'PhortuneCartController' => 'applications/phortune/controller/cart/PhortuneCartController.php', 'PhortuneCartEditor' => 'applications/phortune/editor/PhortuneCartEditor.php', 'PhortuneCartImplementation' => 'applications/phortune/cart/PhortuneCartImplementation.php', 'PhortuneCartListController' => 'applications/phortune/controller/cart/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/cart/PhortuneCartUpdateController.php', 'PhortuneCartViewController' => 'applications/phortune/controller/cart/PhortuneCartViewController.php', 'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.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', + 'PhortuneDisplayException' => 'applications/phortune/exception/PhortuneDisplayException.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', 'PhortuneMerchantAddManagerController' => 'applications/phortune/controller/merchant/PhortuneMerchantAddManagerController.php', 'PhortuneMerchantCapability' => 'applications/phortune/capability/PhortuneMerchantCapability.php', 'PhortuneMerchantContactInfoTransaction' => 'applications/phortune/xaction/PhortuneMerchantContactInfoTransaction.php', 'PhortuneMerchantController' => 'applications/phortune/controller/merchant/PhortuneMerchantController.php', 'PhortuneMerchantDescriptionTransaction' => 'applications/phortune/xaction/PhortuneMerchantDescriptionTransaction.php', 'PhortuneMerchantEditController' => 'applications/phortune/controller/merchant/PhortuneMerchantEditController.php', 'PhortuneMerchantEditEngine' => 'applications/phortune/editor/PhortuneMerchantEditEngine.php', 'PhortuneMerchantEditor' => 'applications/phortune/editor/PhortuneMerchantEditor.php', 'PhortuneMerchantHasMemberEdgeType' => 'applications/phortune/edge/PhortuneMerchantHasMemberEdgeType.php', 'PhortuneMerchantInvoiceCreateController' => 'applications/phortune/controller/merchant/PhortuneMerchantInvoiceCreateController.php', 'PhortuneMerchantInvoiceEmailTransaction' => 'applications/phortune/xaction/PhortuneMerchantInvoiceEmailTransaction.php', 'PhortuneMerchantInvoiceFooterTransaction' => 'applications/phortune/xaction/PhortuneMerchantInvoiceFooterTransaction.php', 'PhortuneMerchantListController' => 'applications/phortune/controller/merchant/PhortuneMerchantListController.php', 'PhortuneMerchantManagerController' => 'applications/phortune/controller/merchant/PhortuneMerchantManagerController.php', 'PhortuneMerchantNameTransaction' => 'applications/phortune/xaction/PhortuneMerchantNameTransaction.php', 'PhortuneMerchantPHIDType' => 'applications/phortune/phid/PhortuneMerchantPHIDType.php', 'PhortuneMerchantPictureController' => 'applications/phortune/controller/merchant/PhortuneMerchantPictureController.php', 'PhortuneMerchantPictureTransaction' => 'applications/phortune/xaction/PhortuneMerchantPictureTransaction.php', 'PhortuneMerchantProfileController' => 'applications/phortune/controller/merchant/PhortuneMerchantProfileController.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', 'PhortuneMerchantTransactionType' => 'applications/phortune/xaction/PhortuneMerchantTransactionType.php', 'PhortuneMerchantViewController' => 'applications/phortune/controller/merchant/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/payment/PhortunePaymentMethodCreateController.php', 'PhortunePaymentMethodDisableController' => 'applications/phortune/controller/payment/PhortunePaymentMethodDisableController.php', 'PhortunePaymentMethodEditController' => 'applications/phortune/controller/payment/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/product/PhortuneProductListController.php', 'PhortuneProductPHIDType' => 'applications/phortune/phid/PhortuneProductPHIDType.php', 'PhortuneProductQuery' => 'applications/phortune/query/PhortuneProductQuery.php', 'PhortuneProductViewController' => 'applications/phortune/controller/product/PhortuneProductViewController.php', 'PhortuneProviderActionController' => 'applications/phortune/controller/provider/PhortuneProviderActionController.php', 'PhortuneProviderDisableController' => 'applications/phortune/controller/provider/PhortuneProviderDisableController.php', 'PhortuneProviderEditController' => 'applications/phortune/controller/provider/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/subscription/PhortuneSubscriptionEditController.php', 'PhortuneSubscriptionImplementation' => 'applications/phortune/subscription/PhortuneSubscriptionImplementation.php', 'PhortuneSubscriptionListController' => 'applications/phortune/controller/subscription/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/subscription/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', 'PhrictionContentPHIDType' => 'applications/phriction/phid/PhrictionContentPHIDType.php', 'PhrictionContentQuery' => 'applications/phriction/query/PhrictionContentQuery.php', 'PhrictionContentSearchConduitAPIMethod' => 'applications/phriction/conduit/PhrictionContentSearchConduitAPIMethod.php', 'PhrictionContentSearchEngine' => 'applications/phriction/query/PhrictionContentSearchEngine.php', 'PhrictionContentSearchEngineAttachment' => 'applications/phriction/engineextension/PhrictionContentSearchEngineAttachment.php', 'PhrictionController' => 'applications/phriction/controller/PhrictionController.php', 'PhrictionCreateConduitAPIMethod' => 'applications/phriction/conduit/PhrictionCreateConduitAPIMethod.php', 'PhrictionDAO' => 'applications/phriction/storage/PhrictionDAO.php', 'PhrictionDatasourceEngineExtension' => 'applications/phriction/engineextension/PhrictionDatasourceEngineExtension.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', 'PhrictionDocumentContentTransaction' => 'applications/phriction/xaction/PhrictionDocumentContentTransaction.php', 'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php', 'PhrictionDocumentDatasource' => 'applications/phriction/typeahead/PhrictionDocumentDatasource.php', 'PhrictionDocumentDeleteTransaction' => 'applications/phriction/xaction/PhrictionDocumentDeleteTransaction.php', 'PhrictionDocumentDraftTransaction' => 'applications/phriction/xaction/PhrictionDocumentDraftTransaction.php', 'PhrictionDocumentEditEngine' => 'applications/phriction/editor/PhrictionDocumentEditEngine.php', 'PhrictionDocumentEditTransaction' => 'applications/phriction/xaction/PhrictionDocumentEditTransaction.php', 'PhrictionDocumentFerretEngine' => 'applications/phriction/search/PhrictionDocumentFerretEngine.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', 'PhrictionDocumentMoveAwayTransaction' => 'applications/phriction/xaction/PhrictionDocumentMoveAwayTransaction.php', 'PhrictionDocumentMoveToTransaction' => 'applications/phriction/xaction/PhrictionDocumentMoveToTransaction.php', 'PhrictionDocumentPHIDType' => 'applications/phriction/phid/PhrictionDocumentPHIDType.php', 'PhrictionDocumentPathHeraldField' => 'applications/phriction/herald/PhrictionDocumentPathHeraldField.php', 'PhrictionDocumentPolicyCodex' => 'applications/phriction/codex/PhrictionDocumentPolicyCodex.php', 'PhrictionDocumentPublishTransaction' => 'applications/phriction/xaction/PhrictionDocumentPublishTransaction.php', 'PhrictionDocumentQuery' => 'applications/phriction/query/PhrictionDocumentQuery.php', 'PhrictionDocumentSearchConduitAPIMethod' => 'applications/phriction/conduit/PhrictionDocumentSearchConduitAPIMethod.php', 'PhrictionDocumentSearchEngine' => 'applications/phriction/query/PhrictionDocumentSearchEngine.php', 'PhrictionDocumentStatus' => 'applications/phriction/constants/PhrictionDocumentStatus.php', 'PhrictionDocumentTitleHeraldField' => 'applications/phriction/herald/PhrictionDocumentTitleHeraldField.php', 'PhrictionDocumentTitleTransaction' => 'applications/phriction/xaction/PhrictionDocumentTitleTransaction.php', 'PhrictionDocumentTransactionType' => 'applications/phriction/xaction/PhrictionDocumentTransactionType.php', 'PhrictionDocumentVersionTransaction' => 'applications/phriction/xaction/PhrictionDocumentVersionTransaction.php', 'PhrictionEditConduitAPIMethod' => 'applications/phriction/conduit/PhrictionEditConduitAPIMethod.php', 'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php', 'PhrictionEditEngineController' => 'applications/phriction/controller/PhrictionEditEngineController.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', 'PhrictionPublishController' => 'applications/phriction/controller/PhrictionPublishController.php', 'PhrictionRemarkupRule' => 'applications/phriction/markup/PhrictionRemarkupRule.php', 'PhrictionReplyHandler' => 'applications/phriction/mail/PhrictionReplyHandler.php', 'PhrictionSchemaSpec' => 'applications/phriction/storage/PhrictionSchemaSpec.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', 'PonderAnswerContentTransaction' => 'applications/ponder/xaction/PonderAnswerContentTransaction.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', 'PonderAnswerQuestionIDTransaction' => 'applications/ponder/xaction/PonderAnswerQuestionIDTransaction.php', 'PonderAnswerReplyHandler' => 'applications/ponder/mail/PonderAnswerReplyHandler.php', 'PonderAnswerSaveController' => 'applications/ponder/controller/PonderAnswerSaveController.php', 'PonderAnswerStatus' => 'applications/ponder/constants/PonderAnswerStatus.php', 'PonderAnswerStatusTransaction' => 'applications/ponder/xaction/PonderAnswerStatusTransaction.php', 'PonderAnswerTransaction' => 'applications/ponder/storage/PonderAnswerTransaction.php', 'PonderAnswerTransactionComment' => 'applications/ponder/storage/PonderAnswerTransactionComment.php', 'PonderAnswerTransactionQuery' => 'applications/ponder/query/PonderAnswerTransactionQuery.php', 'PonderAnswerTransactionType' => 'applications/ponder/xaction/PonderAnswerTransactionType.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', 'PonderQuestionAnswerTransaction' => 'applications/ponder/xaction/PonderQuestionAnswerTransaction.php', 'PonderQuestionAnswerWikiTransaction' => 'applications/ponder/xaction/PonderQuestionAnswerWikiTransaction.php', 'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php', 'PonderQuestionContentTransaction' => 'applications/ponder/xaction/PonderQuestionContentTransaction.php', 'PonderQuestionCreateMailReceiver' => 'applications/ponder/mail/PonderQuestionCreateMailReceiver.php', 'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php', 'PonderQuestionEditEngine' => 'applications/ponder/editor/PonderQuestionEditEngine.php', 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 'PonderQuestionFerretEngine' => 'applications/ponder/search/PonderQuestionFerretEngine.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', 'PonderQuestionStatusTransaction' => 'applications/ponder/xaction/PonderQuestionStatusTransaction.php', 'PonderQuestionTitleTransaction' => 'applications/ponder/xaction/PonderQuestionTitleTransaction.php', 'PonderQuestionTransaction' => 'applications/ponder/storage/PonderQuestionTransaction.php', 'PonderQuestionTransactionComment' => 'applications/ponder/storage/PonderQuestionTransactionComment.php', 'PonderQuestionTransactionQuery' => 'applications/ponder/query/PonderQuestionTransactionQuery.php', 'PonderQuestionTransactionType' => 'applications/ponder/xaction/PonderQuestionTransactionType.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', 'ProjectColumnSearchConduitAPIMethod' => 'applications/project/conduit/ProjectColumnSearchConduitAPIMethod.php', 'ProjectConduitAPIMethod' => 'applications/project/conduit/ProjectConduitAPIMethod.php', 'ProjectCreateConduitAPIMethod' => 'applications/project/conduit/ProjectCreateConduitAPIMethod.php', 'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php', 'ProjectDatasourceEngineExtension' => 'applications/project/engineextension/ProjectDatasourceEngineExtension.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', 'TransactionSearchConduitAPIMethod' => 'applications/transactions/conduit/TransactionSearchConduitAPIMethod.php', 'UserConduitAPIMethod' => 'applications/people/conduit/UserConduitAPIMethod.php', 'UserDisableConduitAPIMethod' => 'applications/people/conduit/UserDisableConduitAPIMethod.php', 'UserEditConduitAPIMethod' => 'applications/people/conduit/UserEditConduitAPIMethod.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_datetimezone' => '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', 'PhabricatorConduitResultInterface', ), 'AlmanacBindingDeletePropertyTransaction' => 'AlmanacBindingTransactionType', 'AlmanacBindingDisableController' => 'AlmanacServiceController', 'AlmanacBindingDisableTransaction' => 'AlmanacBindingTransactionType', 'AlmanacBindingEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'AlmanacBindingEditController' => 'AlmanacServiceController', 'AlmanacBindingEditEngine' => 'PhabricatorEditEngine', 'AlmanacBindingEditor' => 'AlmanacEditor', 'AlmanacBindingInterfaceTransaction' => 'AlmanacBindingTransactionType', 'AlmanacBindingPHIDType' => 'PhabricatorPHIDType', 'AlmanacBindingPropertyEditEngine' => 'AlmanacPropertyEditEngine', 'AlmanacBindingQuery' => 'AlmanacQuery', 'AlmanacBindingSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacBindingSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacBindingServiceTransaction' => 'AlmanacBindingTransactionType', 'AlmanacBindingSetPropertyTransaction' => 'AlmanacBindingTransactionType', 'AlmanacBindingTableView' => 'AphrontView', 'AlmanacBindingTransaction' => 'AlmanacModularTransaction', 'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacBindingTransactionType' => 'AlmanacTransactionType', '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', 'AlmanacDeletePropertyEditField' => 'PhabricatorEditField', 'AlmanacDeletePropertyEditType' => 'PhabricatorEditType', 'AlmanacDevice' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'PhabricatorSSHPublicKeyInterface', 'AlmanacPropertyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', 'PhabricatorConduitResultInterface', 'PhabricatorExtendedPolicyInterface', ), 'AlmanacDeviceController' => 'AlmanacController', 'AlmanacDeviceDeletePropertyTransaction' => 'AlmanacDeviceTransactionType', 'AlmanacDeviceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'AlmanacDeviceEditController' => 'AlmanacDeviceController', 'AlmanacDeviceEditEngine' => 'PhabricatorEditEngine', 'AlmanacDeviceEditor' => 'AlmanacEditor', 'AlmanacDeviceListController' => 'AlmanacDeviceController', 'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacDeviceNameTransaction' => 'AlmanacDeviceTransactionType', 'AlmanacDevicePHIDType' => 'PhabricatorPHIDType', 'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine', 'AlmanacDeviceQuery' => 'AlmanacQuery', 'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacDeviceSetPropertyTransaction' => 'AlmanacDeviceTransactionType', 'AlmanacDeviceTransaction' => 'AlmanacModularTransaction', 'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacDeviceTransactionType' => 'AlmanacTransactionType', 'AlmanacDeviceViewController' => 'AlmanacDeviceController', 'AlmanacDrydockPoolServiceType' => 'AlmanacServiceType', 'AlmanacEditor' => 'PhabricatorApplicationTransactionEditor', 'AlmanacInterface' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorConduitResultInterface', ), 'AlmanacInterfaceAddressTransaction' => 'AlmanacInterfaceTransactionType', 'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource', 'AlmanacInterfaceDeleteController' => 'AlmanacDeviceController', 'AlmanacInterfaceDestroyTransaction' => 'AlmanacInterfaceTransactionType', 'AlmanacInterfaceDeviceTransaction' => 'AlmanacInterfaceTransactionType', 'AlmanacInterfaceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'AlmanacInterfaceEditController' => 'AlmanacDeviceController', 'AlmanacInterfaceEditEngine' => 'PhabricatorEditEngine', 'AlmanacInterfaceEditor' => 'AlmanacEditor', 'AlmanacInterfaceNetworkTransaction' => 'AlmanacInterfaceTransactionType', 'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType', 'AlmanacInterfacePortTransaction' => 'AlmanacInterfaceTransactionType', 'AlmanacInterfaceQuery' => 'AlmanacQuery', 'AlmanacInterfaceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacInterfaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacInterfaceTableView' => 'AphrontView', 'AlmanacInterfaceTransaction' => 'AlmanacModularTransaction', 'AlmanacInterfaceTransactionType' => 'AlmanacTransactionType', 'AlmanacKeys' => 'Phobject', 'AlmanacManageClusterServicesCapability' => 'PhabricatorPolicyCapability', 'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow', 'AlmanacManagementTrustKeyWorkflow' => 'AlmanacManagementWorkflow', 'AlmanacManagementUntrustKeyWorkflow' => 'AlmanacManagementWorkflow', 'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow', 'AlmanacModularTransaction' => 'PhabricatorModularTransaction', 'AlmanacNames' => 'Phobject', 'AlmanacNamesTestCase' => 'PhabricatorTestCase', 'AlmanacNamespace' => array( 'AlmanacDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'AlmanacPropertyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', 'PhabricatorConduitResultInterface', ), 'AlmanacNamespaceController' => 'AlmanacController', 'AlmanacNamespaceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'AlmanacNamespaceEditController' => 'AlmanacNamespaceController', 'AlmanacNamespaceEditEngine' => 'PhabricatorEditEngine', 'AlmanacNamespaceEditor' => 'AlmanacEditor', 'AlmanacNamespaceListController' => 'AlmanacNamespaceController', 'AlmanacNamespaceNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacNamespaceNameTransaction' => 'AlmanacNamespaceTransactionType', 'AlmanacNamespacePHIDType' => 'PhabricatorPHIDType', 'AlmanacNamespaceQuery' => 'AlmanacQuery', 'AlmanacNamespaceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacNamespaceTransaction' => 'AlmanacModularTransaction', 'AlmanacNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacNamespaceTransactionType' => 'AlmanacTransactionType', 'AlmanacNamespaceViewController' => 'AlmanacNamespaceController', 'AlmanacNetwork' => array( 'AlmanacDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', 'PhabricatorConduitResultInterface', ), 'AlmanacNetworkController' => 'AlmanacController', 'AlmanacNetworkEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'AlmanacNetworkEditController' => 'AlmanacNetworkController', 'AlmanacNetworkEditEngine' => 'PhabricatorEditEngine', 'AlmanacNetworkEditor' => 'AlmanacEditor', 'AlmanacNetworkListController' => 'AlmanacNetworkController', 'AlmanacNetworkNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacNetworkNameTransaction' => 'AlmanacNetworkTransactionType', 'AlmanacNetworkPHIDType' => 'PhabricatorPHIDType', 'AlmanacNetworkQuery' => 'AlmanacQuery', 'AlmanacNetworkSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacNetworkSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacNetworkTransaction' => 'AlmanacModularTransaction', 'AlmanacNetworkTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacNetworkTransactionType' => 'AlmanacTransactionType', 'AlmanacNetworkViewController' => 'AlmanacNetworkController', 'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'AlmanacPropertiesEditEngineExtension' => 'PhabricatorEditEngineExtension', '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', 'AlmanacServiceDeletePropertyTransaction' => 'AlmanacServiceTransactionType', 'AlmanacServiceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'AlmanacServiceEditController' => 'AlmanacServiceController', 'AlmanacServiceEditEngine' => 'PhabricatorEditEngine', 'AlmanacServiceEditor' => 'AlmanacEditor', 'AlmanacServiceListController' => 'AlmanacServiceController', 'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams', 'AlmanacServiceNameTransaction' => 'AlmanacServiceTransactionType', 'AlmanacServicePHIDType' => 'PhabricatorPHIDType', 'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine', 'AlmanacServiceQuery' => 'AlmanacQuery', 'AlmanacServiceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'AlmanacServiceSetPropertyTransaction' => 'AlmanacServiceTransactionType', 'AlmanacServiceTransaction' => 'AlmanacModularTransaction', 'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'AlmanacServiceTransactionType' => 'AlmanacTransactionType', 'AlmanacServiceType' => 'Phobject', 'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource', 'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase', 'AlmanacServiceTypeTransaction' => 'AlmanacServiceTransactionType', 'AlmanacServiceViewController' => 'AlmanacServiceController', 'AlmanacSetPropertyEditField' => 'PhabricatorEditField', 'AlmanacSetPropertyEditType' => 'PhabricatorEditType', 'AlmanacTransactionType' => 'PhabricatorModularTransactionType', 'AphlictDropdownDataQuery' => 'Phobject', 'Aphront304Response' => 'AphrontResponse', 'Aphront400Response' => 'AphrontResponse', 'Aphront403Response' => 'AphrontHTMLResponse', 'Aphront404Response' => 'AphrontHTMLResponse', 'AphrontAjaxResponse' => 'AphrontResponse', 'AphrontApplicationConfiguration' => 'Phobject', 'AphrontBarView' => 'AphrontView', 'AphrontBoolHTTPParameterType' => 'AphrontHTTPParameterType', 'AphrontCalendarEventView' => 'AphrontView', 'AphrontController' => 'Phobject', 'AphrontCursorPagerView' => 'AphrontView', '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', 'BulkParameterType' => 'Phobject', 'BulkPointsParameterType' => 'BulkParameterType', 'BulkRemarkupParameterType' => 'BulkParameterType', 'BulkSelectParameterType' => 'BulkParameterType', 'BulkStringParameterType' => 'BulkParameterType', 'BulkTokenizerParameterType' => 'BulkParameterType', 'CalendarTimeUtil' => 'Phobject', 'CalendarTimeUtilTestCase' => 'PhabricatorTestCase', 'CelerityAPI' => 'Phobject', 'CelerityDarkModePostprocessor' => 'CelerityPostprocessor', 'CelerityDefaultPostprocessor' => 'CelerityPostprocessor', 'CelerityHighContrastPostprocessor' => 'CelerityPostprocessor', 'CelerityLargeFontPostprocessor' => 'CelerityPostprocessor', 'CelerityManagementMapWorkflow' => 'CelerityManagementWorkflow', 'CelerityManagementSyntaxWorkflow' => 'CelerityManagementWorkflow', 'CelerityManagementWorkflow' => 'PhabricatorManagementWorkflow', 'CelerityPhabricatorResourceController' => 'CelerityResourceController', 'CelerityPhabricatorResources' => 'CelerityResourcesOnDisk', 'CelerityPhysicalResources' => 'CelerityResources', 'CelerityPhysicalResourcesTestCase' => 'PhabricatorTestCase', 'CelerityPostprocessor' => 'Phobject', 'CelerityPostprocessorTestCase' => 'PhabricatorTestCase', 'CelerityRedGreenPostprocessor' => 'CelerityPostprocessor', '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', 'ConduitConstantDescription' => 'Phobject', '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', 'ConpherenceConstants' => 'Phobject', 'ConpherenceController' => 'PhabricatorController', 'ConpherenceCreateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceDAO' => 'PhabricatorLiskDAO', 'ConpherenceDurableColumnView' => 'AphrontTagView', 'ConpherenceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'ConpherenceEditEngine' => 'PhabricatorEditEngine', 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 'ConpherenceFulltextQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceIndex' => 'ConpherenceDAO', 'ConpherenceLayoutView' => 'AphrontTagView', 'ConpherenceListController' => 'ConpherenceController', 'ConpherenceMenuItemView' => 'AphrontTagView', 'ConpherenceNotificationPanelController' => 'ConpherenceController', 'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipantController' => 'ConpherenceController', 'ConpherenceParticipantCountQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipantView' => 'AphrontView', 'ConpherenceQueryThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceQueryTransactionConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler', 'ConpherenceRoomEditController' => 'ConpherenceController', 'ConpherenceRoomListController' => 'ConpherenceController', 'ConpherenceRoomPictureController' => 'ConpherenceController', 'ConpherenceRoomPreferencesController' => 'ConpherenceController', 'ConpherenceRoomSettings' => 'ConpherenceConstants', 'ConpherenceRoomTestCase' => 'ConpherenceTestCase', 'ConpherenceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ConpherenceTestCase' => 'PhabricatorTestCase', 'ConpherenceThread' => array( 'ConpherenceDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorMentionableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorNgramsInterface', ), 'ConpherenceThreadDatasource' => 'PhabricatorTypeaheadDatasource', 'ConpherenceThreadDateMarkerTransaction' => 'ConpherenceThreadTransactionType', 'ConpherenceThreadIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'ConpherenceThreadListView' => 'AphrontView', 'ConpherenceThreadMailReceiver' => 'PhabricatorObjectMailReceiver', 'ConpherenceThreadMembersPolicyRule' => 'PhabricatorPolicyRule', 'ConpherenceThreadParticipantsTransaction' => 'ConpherenceThreadTransactionType', 'ConpherenceThreadPictureTransaction' => 'ConpherenceThreadTransactionType', 'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ConpherenceThreadRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ConpherenceThreadSearchController' => 'ConpherenceController', 'ConpherenceThreadSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ConpherenceThreadTitleNgrams' => 'PhabricatorSearchNgrams', 'ConpherenceThreadTitleTransaction' => 'ConpherenceThreadTransactionType', 'ConpherenceThreadTopicTransaction' => 'ConpherenceThreadTransactionType', 'ConpherenceThreadTransactionType' => 'PhabricatorModularTransactionType', 'ConpherenceTransaction' => 'PhabricatorModularTransaction', 'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ConpherenceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ConpherenceTransactionRenderer' => 'Phobject', 'ConpherenceTransactionView' => 'AphrontView', 'ConpherenceUpdateActions' => 'ConpherenceConstants', 'ConpherenceUpdateController' => 'ConpherenceController', 'ConpherenceUpdateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceViewController' => 'ConpherenceController', 'CountdownEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'CountdownSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DarkConsoleController' => 'PhabricatorController', 'DarkConsoleCore' => 'Phobject', 'DarkConsoleDataController' => 'PhabricatorController', 'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin', 'DarkConsoleErrorLogPluginAPI' => 'Phobject', 'DarkConsoleEventPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPluginAPI' => 'PhabricatorEventListener', 'DarkConsolePlugin' => 'Phobject', 'DarkConsoleRealtimePlugin' => 'DarkConsolePlugin', 'DarkConsoleRequestPlugin' => 'DarkConsolePlugin', 'DarkConsoleServicesPlugin' => 'DarkConsolePlugin', 'DarkConsoleStartupPlugin' => 'DarkConsolePlugin', 'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin', 'DarkConsoleXHProfPluginAPI' => 'Phobject', 'DifferentialAction' => 'Phobject', 'DifferentialActionEmailCommand' => 'MetaMTAEmailTransactionCommand', 'DifferentialAdjustmentMapTestCase' => 'PhutilTestCase', 'DifferentialAffectedPath' => 'DifferentialDAO', 'DifferentialAsanaRepresentationField' => 'DifferentialCustomField', 'DifferentialAuditorsCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialAuditorsField' => 'DifferentialStoredCustomField', 'DifferentialBlameRevisionCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialBlameRevisionField' => 'DifferentialStoredCustomField', 'DifferentialBlockHeraldAction' => 'HeraldAction', 'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialBranchField' => 'DifferentialCustomField', 'DifferentialBuildableEngine' => 'HarbormasterBuildableEngine', 'DifferentialChangeDetailMailView' => 'DifferentialMailView', 'DifferentialChangeHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialChangeType' => 'Phobject', 'DifferentialChangesSinceLastUpdateField' => 'DifferentialCustomField', 'DifferentialChangeset' => array( 'DifferentialDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'DifferentialChangesetDetailView' => 'AphrontView', 'DifferentialChangesetEngine' => 'Phobject', 'DifferentialChangesetFileTreeSideNavBuilder' => 'Phobject', 'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetListController' => 'DifferentialController', 'DifferentialChangesetListView' => 'AphrontView', 'DifferentialChangesetOneUpMailRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetOneUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetParser' => 'Phobject', 'DifferentialChangesetParserTestCase' => 'PhabricatorTestCase', 'DifferentialChangesetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialChangesetRenderer' => 'Phobject', 'DifferentialChangesetSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DifferentialChangesetTestRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetViewController' => 'DifferentialController', 'DifferentialCloseConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCommitMessageCustomField' => 'DifferentialCommitMessageField', 'DifferentialCommitMessageField' => 'Phobject', 'DifferentialCommitMessageFieldTestCase' => 'PhabricatorTestCase', 'DifferentialCommitMessageParser' => 'Phobject', 'DifferentialCommitMessageParserTestCase' => 'PhabricatorTestCase', 'DifferentialCommitsField' => 'DifferentialCustomField', 'DifferentialCommitsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'DifferentialConduitAPIMethod' => 'ConduitAPIMethod', 'DifferentialConflictsCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialController' => 'PhabricatorController', 'DifferentialCoreCustomField' => 'DifferentialCustomField', 'DifferentialCreateCommentConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateInlineConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', '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', 'PhabricatorExtendedPolicyInterface', 'HarbormasterBuildableInterface', 'HarbormasterCircleCIBuildableInterface', 'HarbormasterBuildkiteBuildableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', ), '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', 'DifferentialDiffSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DifferentialDiffSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DifferentialDiffTestCase' => 'PhutilTestCase', 'DifferentialDiffTransaction' => 'PhabricatorApplicationTransaction', 'DifferentialDiffTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher', 'DifferentialDraftField' => 'DifferentialCoreCustomField', 'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialFieldParseException' => 'Exception', 'DifferentialFieldValidationException' => 'Exception', 'DifferentialGetAllDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetCommitPathsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRawDiffConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRevisionCommentsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialGetWorkingCopy' => 'Phobject', 'DifferentialGitSVNIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialHarbormasterField' => 'DifferentialCustomField', 'DifferentialHeraldStateReasons' => 'HeraldStateReasons', 'DifferentialHiddenComment' => 'DifferentialDAO', 'DifferentialHostField' => 'DifferentialCustomField', 'DifferentialHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DifferentialHunk' => array( 'DifferentialDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'DifferentialHunkParser' => 'Phobject', 'DifferentialHunkParserTestCase' => 'PhabricatorTestCase', 'DifferentialHunkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialHunkTestCase' => 'PhutilTestCase', 'DifferentialInlineComment' => array( 'Phobject', 'PhabricatorInlineCommentInterface', ), 'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController', 'DifferentialInlineCommentMailView' => 'DifferentialMailView', 'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery', 'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField', 'DifferentialLegacyQuery' => 'Phobject', 'DifferentialLineAdjustmentMap' => 'Phobject', 'DifferentialLintField' => 'DifferentialHarbormasterField', 'DifferentialLintStatus' => 'Phobject', 'DifferentialLocalCommitsView' => 'AphrontView', 'DifferentialMailEngineExtension' => 'PhabricatorMailEngineExtension', 'DifferentialMailView' => 'Phobject', 'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField', 'DifferentialParseCacheGarbageCollector' => 'PhabricatorGarbageCollector', 'DifferentialParseCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialParseRenderTestCase' => 'PhabricatorTestCase', 'DifferentialPathField' => 'DifferentialCustomField', 'DifferentialProjectReviewersField' => 'DifferentialCustomField', 'DifferentialQueryConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialQueryDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialRawDiffRenderer' => 'Phobject', 'DifferentialReleephRequestFieldSpecification' => 'Phobject', 'DifferentialRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DifferentialReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'DifferentialRepositoryField' => 'DifferentialCoreCustomField', 'DifferentialRepositoryLookup' => 'Phobject', 'DifferentialRequiredSignaturesField' => 'DifferentialCoreCustomField', 'DifferentialResponsibleDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialResponsibleUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialResponsibleViewerFunctionDatasource' => 'PhabricatorTypeaheadDatasource', 'DifferentialRevertPlanCommitMessageField' => 'DifferentialCommitMessageCustomField', 'DifferentialRevertPlanField' => 'DifferentialStoredCustomField', 'DifferentialReviewedByCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialReviewer' => 'DifferentialDAO', 'DifferentialReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialReviewerForRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialReviewerStatus' => 'Phobject', 'DifferentialReviewersAddBlockingReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddBlockingSelfHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddReviewersHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersAddSelfHeraldAction' => 'DifferentialReviewersHeraldAction', 'DifferentialReviewersCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialReviewersField' => 'DifferentialCoreCustomField', 'DifferentialReviewersHeraldAction' => 'HeraldAction', 'DifferentialReviewersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'DifferentialReviewersView' => 'AphrontView', 'DifferentialRevision' => array( 'DifferentialDAO', 'PhabricatorTokenReceiverInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorFlaggableInterface', 'PhrequentTrackableInterface', 'HarbormasterBuildableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTimelineInterface', 'PhabricatorMentionableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorProjectInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'PhabricatorConduitResultInterface', 'PhabricatorDraftInterface', ), 'DifferentialRevisionAbandonTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionAcceptTransaction' => 'DifferentialRevisionReviewTransaction', 'DifferentialRevisionActionTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionAffectedFilesHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionAuthorHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionAuthorProjectsHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionBuildableTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionCloseDetailsController' => 'DifferentialController', 'DifferentialRevisionCloseTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'DifferentialRevisionCommandeerTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionContentAddedHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionContentHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionContentRemovedHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionControlSystem' => 'Phobject', 'DifferentialRevisionDependedOnByRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionDependsOnRevisionEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionDraftEngine' => 'PhabricatorDraftEngine', 'DifferentialRevisionEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DifferentialRevisionEditController' => 'DifferentialController', 'DifferentialRevisionEditEngine' => 'PhabricatorEditEngine', 'DifferentialRevisionFerretEngine' => 'PhabricatorFerretEngine', 'DifferentialRevisionFulltextEngine' => 'PhabricatorFulltextEngine', 'DifferentialRevisionGraph' => 'PhabricatorObjectGraph', 'DifferentialRevisionHasChildRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHasCommitEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionHasCommitRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHasParentRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHasReviewerEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionHasTaskEdgeType' => 'PhabricatorEdgeType', 'DifferentialRevisionHasTaskRelationship' => 'DifferentialRevisionRelationship', 'DifferentialRevisionHeraldField' => 'HeraldField', 'DifferentialRevisionHeraldFieldGroup' => 'HeraldFieldGroup', 'DifferentialRevisionHoldDraftTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionIDCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialRevisionInlineTransaction' => 'PhabricatorModularTransactionType', 'DifferentialRevisionInlinesController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListView' => 'AphrontView', 'DifferentialRevisionMailReceiver' => 'PhabricatorObjectMailReceiver', 'DifferentialRevisionOpenStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'DifferentialRevisionOperationController' => 'DifferentialController', 'DifferentialRevisionPHIDType' => 'PhabricatorPHIDType', 'DifferentialRevisionPackageHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionPackageOwnerHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionPlanChangesTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DifferentialRevisionReclaimTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionRejectTransaction' => 'DifferentialRevisionReviewTransaction', 'DifferentialRevisionRelationship' => 'PhabricatorObjectRelationship', 'DifferentialRevisionRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'DifferentialRevisionReopenTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionRepositoryHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionRepositoryProjectsHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionRepositoryTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionRequestReviewTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionRequiredActionResultBucket' => 'DifferentialRevisionResultBucket', 'DifferentialRevisionResignTransaction' => 'DifferentialRevisionReviewTransaction', 'DifferentialRevisionResultBucket' => 'PhabricatorSearchResultBucket', 'DifferentialRevisionReviewTransaction' => 'DifferentialRevisionActionTransaction', 'DifferentialRevisionReviewersHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionReviewersTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DifferentialRevisionStatus' => 'Phobject', 'DifferentialRevisionStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'DifferentialRevisionStatusFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialRevisionStatusHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionStatusTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionSummaryHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionSummaryTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionTestPlanHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionTestPlanTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionTimelineEngine' => 'PhabricatorTimelineEngine', 'DifferentialRevisionTitleHeraldField' => 'DifferentialRevisionHeraldField', 'DifferentialRevisionTitleTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionTransactionType' => 'PhabricatorModularTransactionType', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionUpdateTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialRevisionVoidTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialRevisionWrongStateTransaction' => 'DifferentialRevisionTransactionType', 'DifferentialSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DifferentialSetDiffPropertyConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DifferentialStoredCustomField' => 'DifferentialCustomField', 'DifferentialSubscribersCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialSummaryCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialSummaryField' => 'DifferentialCoreCustomField', 'DifferentialTagsCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTasksCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanField' => 'DifferentialCoreCustomField', 'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTransaction' => 'PhabricatorModularTransaction', 'DifferentialTransactionComment' => 'PhabricatorApplicationTransactionComment', 'DifferentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'DifferentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DifferentialTransactionView' => 'PhabricatorApplicationTransactionView', 'DifferentialUnitField' => 'DifferentialCustomField', 'DifferentialUnitStatus' => 'Phobject', 'DifferentialUnitTestResult' => 'Phobject', 'DifferentialUpdateRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', 'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionAuditorFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction', 'DiffusionAuditorsAddSelfHeraldAction' => 'DiffusionAuditorsHeraldAction', 'DiffusionAuditorsHeraldAction' => 'HeraldAction', 'DiffusionBlameConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBlameController' => 'DiffusionController', 'DiffusionBlameQuery' => 'DiffusionQuery', 'DiffusionBlockHeraldAction' => 'HeraldAction', 'DiffusionBranchListView' => 'DiffusionView', 'DiffusionBranchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBranchTableController' => 'DiffusionController', 'DiffusionBranchTableView' => 'DiffusionView', 'DiffusionBrowseController' => 'DiffusionController', 'DiffusionBrowseQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionBrowseResultSet' => 'Phobject', 'DiffusionBrowseTableView' => 'DiffusionView', 'DiffusionBuildableEngine' => 'HarbormasterBuildableEngine', 'DiffusionCacheEngineExtension' => 'PhabricatorCacheEngineExtension', 'DiffusionCachedResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionChangeController' => 'DiffusionController', 'DiffusionChangeHeraldFieldGroup' => 'HeraldFieldGroup', 'DiffusionCloneController' => 'DiffusionController', 'DiffusionCloneURIView' => 'AphrontView', 'DiffusionCommandEngine' => 'Phobject', 'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase', 'DiffusionCommitAcceptTransaction' => 'DiffusionCommitAuditTransaction', 'DiffusionCommitActionTransaction' => 'DiffusionCommitTransactionType', 'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitAuditStatus' => 'Phobject', 'DiffusionCommitAuditTransaction' => 'DiffusionCommitActionTransaction', 'DiffusionCommitAuditorsHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitAuditorsTransaction' => 'DiffusionCommitTransactionType', 'DiffusionCommitAuthorHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitAuthorProjectsHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitBranchesController' => 'DiffusionController', 'DiffusionCommitBranchesHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitBuildableTransaction' => 'DiffusionCommitTransactionType', 'DiffusionCommitCommitterHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitCommitterProjectsHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitConcernTransaction' => 'DiffusionCommitAuditTransaction', 'DiffusionCommitController' => 'DiffusionController', 'DiffusionCommitDiffContentAddedHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDiffContentHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDiffContentRemovedHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDiffEnormousHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitDraftEngine' => 'PhabricatorDraftEngine', 'DiffusionCommitEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DiffusionCommitEditController' => 'DiffusionController', 'DiffusionCommitEditEngine' => 'PhabricatorEditEngine', 'DiffusionCommitFerretEngine' => 'PhabricatorFerretEngine', 'DiffusionCommitFulltextEngine' => 'PhabricatorFulltextEngine', 'DiffusionCommitHasPackageEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitHasRevisionEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitHasRevisionRelationship' => 'DiffusionCommitRelationship', 'DiffusionCommitHasTaskEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitHasTaskRelationship' => 'DiffusionCommitRelationship', 'DiffusionCommitHash' => 'Phobject', 'DiffusionCommitHeraldField' => 'HeraldField', 'DiffusionCommitHeraldFieldGroup' => 'HeraldFieldGroup', 'DiffusionCommitHintQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'DiffusionCommitHookEngine' => 'Phobject', 'DiffusionCommitHookRejectException' => 'Exception', 'DiffusionCommitListController' => 'DiffusionController', 'DiffusionCommitListView' => 'AphrontView', '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', 'DiffusionCommitRequiredActionResultBucket' => 'DiffusionCommitResultBucket', 'DiffusionCommitResignTransaction' => 'DiffusionCommitAuditTransaction', 'DiffusionCommitResultBucket' => 'PhabricatorSearchResultBucket', 'DiffusionCommitRevertedByCommitEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitRevertsCommitEdgeType' => 'PhabricatorEdgeType', 'DiffusionCommitReviewerHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionAcceptedHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionAcceptingReviewersHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionReviewersHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitRevisionSubscribersHeraldField' => 'DiffusionCommitHeraldField', 'DiffusionCommitSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DiffusionCommitStateTransaction' => 'DiffusionCommitTransactionType', 'DiffusionCommitTagsController' => 'DiffusionController', 'DiffusionCommitTimelineEngine' => 'PhabricatorTimelineEngine', 'DiffusionCommitTransactionType' => 'PhabricatorModularTransactionType', 'DiffusionCommitVerifyTransaction' => 'DiffusionCommitAuditTransaction', 'DiffusionCompareController' => 'DiffusionController', 'DiffusionConduitAPIMethod' => 'ConduitAPIMethod', 'DiffusionController' => 'PhabricatorController', 'DiffusionCreateRepositoriesCapability' => 'PhabricatorPolicyCapability', 'DiffusionDaemonLockException' => 'Exception', 'DiffusionDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension', 'DiffusionDefaultEditCapability' => 'PhabricatorPolicyCapability', 'DiffusionDefaultPushCapability' => 'PhabricatorPolicyCapability', 'DiffusionDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DiffusionDiffController' => 'DiffusionController', 'DiffusionDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery', 'DiffusionDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionDocumentController' => 'DiffusionController', 'DiffusionDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine', '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', 'DiffusionGraphController' => 'DiffusionController', 'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryListView' => 'DiffusionHistoryView', 'DiffusionHistoryQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionHistoryTableView' => 'DiffusionHistoryView', 'DiffusionHistoryView' => 'DiffusionView', 'DiffusionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'DiffusionIdentityAssigneeDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionIdentityAssigneeEditField' => 'PhabricatorTokenizerEditField', 'DiffusionIdentityAssigneeSearchField' => 'PhabricatorSearchTokenizerField', 'DiffusionIdentityEditController' => 'DiffusionController', 'DiffusionIdentityListController' => 'DiffusionController', 'DiffusionIdentityUnassignedDatasource' => 'PhabricatorTypeaheadDatasource', 'DiffusionIdentityViewController' => 'DiffusionController', 'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', 'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DiffusionInternalAncestorsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionLastModifiedController' => 'DiffusionController', 'DiffusionLastModifiedQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionLintController' => 'DiffusionController', 'DiffusionLintCountQuery' => 'PhabricatorQuery', 'DiffusionLintSaveRunner' => 'Phobject', 'DiffusionLocalRepositoryFilter' => 'Phobject', 'DiffusionLogController' => 'DiffusionController', 'DiffusionLookSoonConduitAPIMethod' => 'DiffusionConduitAPIMethod', 'DiffusionLowLevelCommitFieldsQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelCommitQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelFilesizeQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelGitRefQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelMercurialBranchesQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelMercurialPathsQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelParentsQuery' => 'DiffusionLowLevelQuery', 'DiffusionLowLevelQuery' => 'Phobject', 'DiffusionLowLevelResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionMercurialBlameQuery' => 'DiffusionBlameQuery', 'DiffusionMercurialCommandEngine' => 'DiffusionCommandEngine', 'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionMercurialFlagInjectionException' => 'Exception', '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', 'DiffusionPatternSearchView' => 'DiffusionView', 'DiffusionPhpExternalSymbolsSource' => 'DiffusionExternalSymbolsSource', 'DiffusionPreCommitContentAffectedFilesHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAuthorHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAuthorProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentAuthorRawHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentBranchesHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentCommitterHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentCommitterProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentCommitterRawHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffContentAddedHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffContentHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffContentRemovedHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentDiffEnormousHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentHeraldField' => 'HeraldField', 'DiffusionPreCommitContentMergeHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentMessageHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPackageHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPackageOwnerHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPusherHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPusherIsCommitterHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentPusherProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRepositoryHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRepositoryProjectsHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRevisionAcceptedHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPreCommitContentRevisionAcceptingReviewersHeraldField' => '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', 'DiffusionPreCommitUsesGitLFSHeraldField' => 'DiffusionPreCommitContentHeraldField', 'DiffusionPullEventGarbageCollector' => 'PhabricatorGarbageCollector', 'DiffusionPullLogListController' => 'DiffusionLogController', 'DiffusionPullLogListView' => 'AphrontView', 'DiffusionPullLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DiffusionPushCapability' => 'PhabricatorPolicyCapability', 'DiffusionPushEventViewController' => 'DiffusionLogController', 'DiffusionPushLogListController' => 'DiffusionLogController', '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', 'DiffusionRepositoryEditActivateController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DiffusionRepositoryEditController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditDangerousController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditDeleteController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditEngine' => 'PhabricatorEditEngine', 'DiffusionRepositoryEditEnormousController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor', 'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine', 'DiffusionRepositoryLimitsManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryListController' => 'DiffusionController', 'DiffusionRepositoryManageController' => 'DiffusionController', 'DiffusionRepositoryManagePanelsController' => 'DiffusionRepositoryManageController', 'DiffusionRepositoryManagementBuildsPanelGroup' => 'DiffusionRepositoryManagementPanelGroup', 'DiffusionRepositoryManagementIntegrationsPanelGroup' => 'DiffusionRepositoryManagementPanelGroup', 'DiffusionRepositoryManagementMainPanelGroup' => 'DiffusionRepositoryManagementPanelGroup', 'DiffusionRepositoryManagementOtherPanelGroup' => 'DiffusionRepositoryManagementPanelGroup', 'DiffusionRepositoryManagementPanel' => 'Phobject', 'DiffusionRepositoryManagementPanelGroup' => 'Phobject', 'DiffusionRepositoryPath' => 'Phobject', 'DiffusionRepositoryPoliciesManagementPanel' => 'DiffusionRepositoryManagementPanel', 'DiffusionRepositoryProfilePictureController' => 'DiffusionController', 'DiffusionRepositoryRef' => 'Phobject', 'DiffusionRepositoryRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'DiffusionRepositorySearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DiffusionRepositoryStagingManagementPanel' => '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', 'DiffusionSyncLogListController' => 'DiffusionLogController', 'DiffusionSyncLogListView' => 'AphrontView', 'DiffusionSyncLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DiffusionTagListController' => 'DiffusionController', 'DiffusionTagListView' => 'DiffusionView', 'DiffusionTagTableView' => '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', 'DrydockAcquiredBrokenResourceException' => 'Exception', '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', 'DrydockBlueprintDisableTransaction' => 'DrydockBlueprintTransactionType', 'DrydockBlueprintEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'DrydockBlueprintEditController' => 'DrydockBlueprintController', 'DrydockBlueprintEditEngine' => 'PhabricatorEditEngine', 'DrydockBlueprintEditor' => 'PhabricatorApplicationTransactionEditor', 'DrydockBlueprintImplementation' => 'Phobject', 'DrydockBlueprintImplementationTestCase' => 'PhabricatorTestCase', 'DrydockBlueprintListController' => 'DrydockBlueprintController', 'DrydockBlueprintNameNgrams' => 'PhabricatorSearchNgrams', 'DrydockBlueprintNameTransaction' => 'DrydockBlueprintTransactionType', 'DrydockBlueprintPHIDType' => 'PhabricatorPHIDType', 'DrydockBlueprintQuery' => 'DrydockQuery', 'DrydockBlueprintSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DrydockBlueprintSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockBlueprintTransaction' => 'PhabricatorModularTransaction', 'DrydockBlueprintTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DrydockBlueprintTransactionType' => 'PhabricatorModularTransactionType', 'DrydockBlueprintTypeTransaction' => 'DrydockBlueprintTransactionType', 'DrydockBlueprintViewController' => 'DrydockBlueprintController', 'DrydockCommand' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', ), 'DrydockCommandError' => 'Phobject', 'DrydockCommandInterface' => 'DrydockInterface', 'DrydockCommandQuery' => 'DrydockQuery', 'DrydockConsoleController' => 'DrydockController', 'DrydockController' => 'PhabricatorController', 'DrydockCreateBlueprintsCapability' => 'PhabricatorPolicyCapability', 'DrydockDAO' => 'PhabricatorLiskDAO', 'DrydockDefaultEditCapability' => 'PhabricatorPolicyCapability', 'DrydockDefaultViewCapability' => 'PhabricatorPolicyCapability', 'DrydockFilesystemInterface' => 'DrydockInterface', 'DrydockInterface' => 'Phobject', 'DrydockLandRepositoryOperation' => 'DrydockRepositoryOperationType', 'DrydockLease' => array( 'DrydockDAO', 'PhabricatorPolicyInterface', 'PhabricatorConduitResultInterface', ), 'DrydockLeaseAcquiredLogType' => 'DrydockLogType', 'DrydockLeaseActivatedLogType' => 'DrydockLogType', 'DrydockLeaseActivationFailureLogType' => 'DrydockLogType', 'DrydockLeaseActivationYieldLogType' => 'DrydockLogType', 'DrydockLeaseAllocationFailureLogType' => 'DrydockLogType', 'DrydockLeaseController' => 'DrydockController', 'DrydockLeaseDatasource' => 'PhabricatorTypeaheadDatasource', 'DrydockLeaseDestroyedLogType' => 'DrydockLogType', 'DrydockLeaseListController' => 'DrydockLeaseController', 'DrydockLeaseListView' => 'AphrontView', 'DrydockLeaseNoAuthorizationsLogType' => 'DrydockLogType', 'DrydockLeaseNoBlueprintsLogType' => 'DrydockLogType', 'DrydockLeasePHIDType' => 'PhabricatorPHIDType', 'DrydockLeaseQuery' => 'DrydockQuery', 'DrydockLeaseQueuedLogType' => 'DrydockLogType', 'DrydockLeaseReacquireLogType' => 'DrydockLogType', 'DrydockLeaseReclaimLogType' => 'DrydockLogType', 'DrydockLeaseReleaseController' => 'DrydockLeaseController', 'DrydockLeaseReleasedLogType' => 'DrydockLogType', 'DrydockLeaseSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DrydockLeaseSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockLeaseStatus' => 'PhabricatorObjectStatus', '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', 'DrydockOperationWorkLogType' => 'DrydockLogType', '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', 'DrydockResourceAllocationFailureLogType' => 'DrydockLogType', 'DrydockResourceController' => 'DrydockController', 'DrydockResourceDatasource' => 'PhabricatorTypeaheadDatasource', 'DrydockResourceListController' => 'DrydockResourceController', 'DrydockResourceListView' => 'AphrontView', 'DrydockResourceLockException' => 'Exception', 'DrydockResourcePHIDType' => 'PhabricatorPHIDType', 'DrydockResourceQuery' => 'DrydockQuery', 'DrydockResourceReclaimLogType' => 'DrydockLogType', 'DrydockResourceReleaseController' => 'DrydockResourceController', 'DrydockResourceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'DrydockResourceStatus' => 'PhabricatorObjectStatus', 'DrydockResourceUpdateWorker' => 'DrydockWorker', 'DrydockResourceViewController' => 'DrydockResourceController', 'DrydockSFTPFilesystemInterface' => 'DrydockFilesystemInterface', 'DrydockSSHCommandInterface' => 'DrydockCommandInterface', 'DrydockSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'DrydockSlotLock' => 'DrydockDAO', 'DrydockSlotLockException' => 'Exception', 'DrydockSlotLockFailureLogType' => 'DrydockLogType', 'DrydockTestRepositoryOperation' => 'DrydockRepositoryOperationType', 'DrydockTextLogType' => 'DrydockLogType', 'DrydockWebrootInterface' => 'DrydockInterface', 'DrydockWorker' => 'PhabricatorWorker', 'DrydockWorkingCopyBlueprintImplementation' => 'DrydockBlueprintImplementation', 'EdgeSearchConduitAPIMethod' => 'ConduitAPIMethod', 'FeedConduitAPIMethod' => 'ConduitAPIMethod', 'FeedPublishConduitAPIMethod' => 'FeedConduitAPIMethod', 'FeedPublisherHTTPWorker' => 'FeedPushWorker', 'FeedPublisherWorker' => 'FeedPushWorker', 'FeedPushWorker' => 'PhabricatorWorker', 'FeedQueryConduitAPIMethod' => 'FeedConduitAPIMethod', 'FeedStoryNotificationGarbageCollector' => 'PhabricatorGarbageCollector', 'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod', 'FileConduitAPIMethod' => 'ConduitAPIMethod', 'FileCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', 'FileDeletionWorker' => 'PhabricatorWorker', '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', 'FundBackerRefundTransaction' => 'FundBackerTransactionType', 'FundBackerSearchEngine' => 'PhabricatorApplicationSearchEngine', 'FundBackerStatusTransaction' => 'FundBackerTransactionType', 'FundBackerTransaction' => 'PhabricatorModularTransaction', 'FundBackerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'FundBackerTransactionType' => 'PhabricatorModularTransactionType', 'FundController' => 'PhabricatorController', 'FundCreateInitiativesCapability' => 'PhabricatorPolicyCapability', 'FundDAO' => 'PhabricatorLiskDAO', 'FundDefaultViewCapability' => 'PhabricatorPolicyCapability', 'FundInitiative' => array( 'FundDAO', 'PhabricatorPolicyInterface', 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorMentionableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', ), 'FundInitiativeBackController' => 'FundController', 'FundInitiativeBackerTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeCloseController' => 'FundController', 'FundInitiativeDescriptionTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeEditController' => 'FundController', 'FundInitiativeEditEngine' => 'PhabricatorEditEngine', 'FundInitiativeEditor' => 'PhabricatorApplicationTransactionEditor', 'FundInitiativeFerretEngine' => 'PhabricatorFerretEngine', 'FundInitiativeFulltextEngine' => 'PhabricatorFulltextEngine', 'FundInitiativeListController' => 'FundController', 'FundInitiativeMerchantTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeNameTransaction' => 'FundInitiativeTransactionType', 'FundInitiativePHIDType' => 'PhabricatorPHIDType', 'FundInitiativeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'FundInitiativeRefundTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'FundInitiativeReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'FundInitiativeRisksTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeSearchEngine' => 'PhabricatorApplicationSearchEngine', 'FundInitiativeStatusTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeTransaction' => 'PhabricatorModularTransaction', 'FundInitiativeTransactionComment' => 'PhabricatorApplicationTransactionComment', 'FundInitiativeTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'FundInitiativeTransactionType' => 'PhabricatorModularTransactionType', 'FundInitiativeViewController' => 'FundController', 'FundSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HarbormasterAbortOlderBuildsBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterArcLintBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterArcUnitBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterArtifact' => 'Phobject', 'HarbormasterAutotargetsTestCase' => 'PhabricatorTestCase', 'HarbormasterBuild' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorConduitResultInterface', 'PhabricatorDestructibleInterface', ), 'HarbormasterBuildAbortedException' => 'Exception', 'HarbormasterBuildActionController' => 'HarbormasterController', 'HarbormasterBuildArcanistAutoplan' => 'HarbormasterBuildAutoplan', 'HarbormasterBuildArtifact' => array( 'HarbormasterDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), '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', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', ), 'HarbormasterBuildLogChunk' => 'HarbormasterDAO', 'HarbormasterBuildLogChunkIterator' => 'PhutilBufferedIterator', 'HarbormasterBuildLogDownloadController' => 'HarbormasterController', 'HarbormasterBuildLogPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildLogRenderController' => 'HarbormasterController', 'HarbormasterBuildLogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'HarbormasterBuildLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HarbormasterBuildLogTestCase' => 'PhabricatorTestCase', 'HarbormasterBuildLogView' => 'AphrontView', 'HarbormasterBuildLogViewController' => 'HarbormasterController', 'HarbormasterBuildMessage' => array( 'HarbormasterDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'HarbormasterBuildMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildPlan' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorNgramsInterface', 'PhabricatorConduitResultInterface', 'PhabricatorProjectInterface', ), 'HarbormasterBuildPlanDatasource' => 'PhabricatorTypeaheadDatasource', 'HarbormasterBuildPlanDefaultEditCapability' => 'PhabricatorPolicyCapability', 'HarbormasterBuildPlanDefaultViewCapability' => 'PhabricatorPolicyCapability', 'HarbormasterBuildPlanEditEngine' => 'PhabricatorEditEngine', 'HarbormasterBuildPlanEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildPlanNameNgrams' => 'PhabricatorSearchNgrams', 'HarbormasterBuildPlanPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildPlanQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildPlanSearchAPIMethod' => 'PhabricatorSearchEngineAPIMethod', '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', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', ), 'HarbormasterBuildTargetPHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildTargetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildTargetSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HarbormasterBuildTransaction' => 'PhabricatorApplicationTransaction', 'HarbormasterBuildTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildUnitMessage' => 'HarbormasterDAO', 'HarbormasterBuildViewController' => 'HarbormasterController', 'HarbormasterBuildWorker' => 'HarbormasterWorker', 'HarbormasterBuildable' => array( 'HarbormasterDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'HarbormasterBuildableInterface', 'PhabricatorConduitResultInterface', 'PhabricatorDestructibleInterface', ), 'HarbormasterBuildableActionController' => 'HarbormasterController', 'HarbormasterBuildableEngine' => 'Phobject', 'HarbormasterBuildableListController' => 'HarbormasterController', 'HarbormasterBuildablePHIDType' => 'PhabricatorPHIDType', 'HarbormasterBuildableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HarbormasterBuildableSearchAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'HarbormasterBuildableSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HarbormasterBuildableStatus' => 'Phobject', 'HarbormasterBuildableTransaction' => 'PhabricatorApplicationTransaction', 'HarbormasterBuildableTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'HarbormasterBuildableTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HarbormasterBuildableViewController' => 'HarbormasterController', 'HarbormasterBuildkiteBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterBuildkiteHookController' => 'HarbormasterController', 'HarbormasterBuiltinBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterCircleCIBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterCircleCIHookController' => 'HarbormasterController', 'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod', 'HarbormasterControlBuildStepGroup' => 'HarbormasterBuildStepGroup', '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', 'HarbormasterLogWorker' => 'HarbormasterWorker', 'HarbormasterManagementArchiveLogsWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementPublishWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementRebuildLogWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementRestartWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementUpdateWorkflow' => 'HarbormasterManagementWorkflow', 'HarbormasterManagementWorkflow' => 'PhabricatorManagementWorkflow', 'HarbormasterManagementWriteLogWorkflow' => 'HarbormasterManagementWorkflow', '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', 'HarbormasterTargetSearchAPIMethod' => 'PhabricatorSearchEngineAPIMethod', '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', 'HeraldActingUserField' => 'HeraldField', 'HeraldAction' => 'Phobject', 'HeraldActionGroup' => 'HeraldGroup', 'HeraldActionRecord' => 'HeraldDAO', 'HeraldAdapter' => 'Phobject', 'HeraldAdapterDatasource' => 'PhabricatorTypeaheadDatasource', 'HeraldAlwaysField' => 'HeraldField', 'HeraldAnotherRuleField' => 'HeraldField', 'HeraldApplicationActionGroup' => 'HeraldActionGroup', 'HeraldApplyTranscript' => 'Phobject', 'HeraldBasicFieldGroup' => 'HeraldFieldGroup', 'HeraldBuildableState' => 'HeraldState', 'HeraldCallWebhookAction' => 'HeraldAction', 'HeraldCommentAction' => 'HeraldAction', 'HeraldCommitAdapter' => array( 'HeraldAdapter', 'HarbormasterBuildableAdapterInterface', ), 'HeraldCondition' => 'HeraldDAO', 'HeraldConditionTranscript' => 'Phobject', 'HeraldContentSourceField' => 'HeraldField', 'HeraldController' => 'PhabricatorController', 'HeraldCoreStateReasons' => 'HeraldStateReasons', 'HeraldCreateWebhooksCapability' => 'PhabricatorPolicyCapability', 'HeraldDAO' => 'PhabricatorLiskDAO', 'HeraldDeprecatedFieldGroup' => 'HeraldFieldGroup', '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', 'HeraldMailableState' => 'HeraldState', 'HeraldManageGlobalRulesCapability' => 'PhabricatorPolicyCapability', 'HeraldManagementWorkflow' => 'PhabricatorManagementWorkflow', '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', 'HeraldRemarkupFieldValue' => 'HeraldFieldValue', 'HeraldRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'HeraldRule' => array( 'HeraldDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSubscribableInterface', ), 'HeraldRuleAdapter' => 'HeraldAdapter', 'HeraldRuleAdapterField' => 'HeraldRuleField', 'HeraldRuleController' => 'HeraldController', 'HeraldRuleDatasource' => 'PhabricatorTypeaheadDatasource', 'HeraldRuleEditor' => 'PhabricatorApplicationTransactionEditor', 'HeraldRuleField' => 'HeraldField', 'HeraldRuleFieldGroup' => 'HeraldFieldGroup', 'HeraldRuleListController' => 'HeraldController', 'HeraldRulePHIDType' => 'PhabricatorPHIDType', 'HeraldRuleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HeraldRuleReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'HeraldRuleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HeraldRuleSerializer' => 'Phobject', 'HeraldRuleTestCase' => 'PhabricatorTestCase', 'HeraldRuleTransaction' => 'PhabricatorApplicationTransaction', 'HeraldRuleTransactionComment' => 'PhabricatorApplicationTransactionComment', 'HeraldRuleTranscript' => 'Phobject', 'HeraldRuleTypeConfig' => 'Phobject', 'HeraldRuleTypeDatasource' => 'PhabricatorTypeaheadDatasource', 'HeraldRuleTypeField' => 'HeraldRuleField', 'HeraldRuleViewController' => 'HeraldController', 'HeraldSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HeraldSelectFieldValue' => 'HeraldFieldValue', 'HeraldSpaceField' => 'HeraldField', 'HeraldState' => 'Phobject', 'HeraldStateReasons' => 'Phobject', 'HeraldSubscribersField' => 'HeraldField', 'HeraldSupportActionGroup' => 'HeraldActionGroup', 'HeraldSupportFieldGroup' => 'HeraldFieldGroup', 'HeraldTestConsoleController' => 'HeraldController', 'HeraldTestManagementWorkflow' => 'HeraldManagementWorkflow', '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', 'HeraldWebhook' => array( 'HeraldDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', 'PhabricatorProjectInterface', ), 'HeraldWebhookCallManagementWorkflow' => 'HeraldWebhookManagementWorkflow', 'HeraldWebhookController' => 'HeraldController', 'HeraldWebhookDatasource' => 'PhabricatorTypeaheadDatasource', 'HeraldWebhookEditController' => 'HeraldWebhookController', 'HeraldWebhookEditEngine' => 'PhabricatorEditEngine', 'HeraldWebhookEditor' => 'PhabricatorApplicationTransactionEditor', 'HeraldWebhookKeyController' => 'HeraldWebhookController', 'HeraldWebhookListController' => 'HeraldWebhookController', 'HeraldWebhookManagementWorkflow' => 'PhabricatorManagementWorkflow', 'HeraldWebhookNameTransaction' => 'HeraldWebhookTransactionType', 'HeraldWebhookPHIDType' => 'PhabricatorPHIDType', 'HeraldWebhookQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HeraldWebhookRequest' => array( 'HeraldDAO', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', ), 'HeraldWebhookRequestGarbageCollector' => 'PhabricatorGarbageCollector', 'HeraldWebhookRequestListView' => 'AphrontView', 'HeraldWebhookRequestPHIDType' => 'PhabricatorPHIDType', 'HeraldWebhookRequestQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'HeraldWebhookSearchEngine' => 'PhabricatorApplicationSearchEngine', 'HeraldWebhookStatusTransaction' => 'HeraldWebhookTransactionType', 'HeraldWebhookTestController' => 'HeraldWebhookController', 'HeraldWebhookTransaction' => 'PhabricatorModularTransaction', 'HeraldWebhookTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'HeraldWebhookTransactionType' => 'PhabricatorModularTransactionType', 'HeraldWebhookURITransaction' => 'HeraldWebhookTransactionType', 'HeraldWebhookViewController' => 'HeraldWebhookController', 'HeraldWebhookWorker' => 'PhabricatorWorker', 'Javelin' => 'Phobject', 'LegalpadController' => 'PhabricatorController', 'LegalpadCreateDocumentsCapability' => 'PhabricatorPolicyCapability', 'LegalpadDAO' => 'PhabricatorLiskDAO', 'LegalpadDefaultEditCapability' => 'PhabricatorPolicyCapability', 'LegalpadDefaultViewCapability' => 'PhabricatorPolicyCapability', 'LegalpadDocument' => array( 'LegalpadDAO', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'LegalpadDocumentBody' => array( 'LegalpadDAO', 'PhabricatorMarkupInterface', ), 'LegalpadDocumentDatasource' => 'PhabricatorTypeaheadDatasource', 'LegalpadDocumentDoneController' => 'LegalpadController', 'LegalpadDocumentEditController' => 'LegalpadController', 'LegalpadDocumentEditEngine' => 'PhabricatorEditEngine', 'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor', 'LegalpadDocumentListController' => 'LegalpadController', 'LegalpadDocumentManageController' => 'LegalpadController', 'LegalpadDocumentPreambleTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'LegalpadDocumentRequireSignatureTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'LegalpadDocumentSignController' => 'LegalpadController', 'LegalpadDocumentSignature' => array( 'LegalpadDAO', 'PhabricatorPolicyInterface', ), 'LegalpadDocumentSignatureAddController' => 'LegalpadController', 'LegalpadDocumentSignatureListController' => 'LegalpadController', 'LegalpadDocumentSignatureQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentSignatureSearchEngine' => 'PhabricatorApplicationSearchEngine', 'LegalpadDocumentSignatureTypeTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentSignatureVerificationController' => 'LegalpadController', 'LegalpadDocumentSignatureViewController' => 'LegalpadController', 'LegalpadDocumentTextTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentTitleTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentTransactionType' => 'PhabricatorModularTransactionType', 'LegalpadMailReceiver' => 'PhabricatorObjectMailReceiver', 'LegalpadObjectNeedsSignatureEdgeType' => 'PhabricatorEdgeType', 'LegalpadReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'LegalpadRequireSignatureHeraldAction' => 'HeraldAction', 'LegalpadSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'LegalpadSignatureNeededByObjectEdgeType' => 'PhabricatorEdgeType', 'LegalpadTransaction' => 'PhabricatorModularTransaction', 'LegalpadTransactionComment' => 'PhabricatorApplicationTransactionComment', 'LegalpadTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'LiskChunkTestCase' => 'PhabricatorTestCase', 'LiskDAO' => array( 'Phobject', 'AphrontDatabaseTableRefInterface', ), 'LiskDAOTestCase' => 'PhabricatorTestCase', 'LiskEphemeralObjectException' => 'Exception', 'LiskFixtureTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestDAO' => 'LiskDAO', 'LiskIsolationTestDAOException' => 'Exception', 'LiskMigrationIterator' => 'PhutilBufferedIterator', 'LiskRawMigrationIterator' => 'PhutilBufferedIterator', 'MacroConduitAPIMethod' => 'ConduitAPIMethod', 'MacroCreateMemeConduitAPIMethod' => 'MacroConduitAPIMethod', 'MacroEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'MacroEmojiExample' => 'PhabricatorUIExample', 'MacroQueryConduitAPIMethod' => 'MacroConduitAPIMethod', 'ManiphestAssignEmailCommand' => 'ManiphestEmailCommand', 'ManiphestAssigneeDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'ManiphestBulkEditCapability' => 'PhabricatorPolicyCapability', 'ManiphestBulkEditController' => 'ManiphestController', 'ManiphestClaimEmailCommand' => 'ManiphestEmailCommand', 'ManiphestCloseEmailCommand' => 'ManiphestEmailCommand', 'ManiphestConduitAPIMethod' => 'ConduitAPIMethod', 'ManiphestConfiguredCustomField' => array( 'ManiphestCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'ManiphestConstants' => 'Phobject', 'ManiphestController' => 'PhabricatorController', 'ManiphestCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', 'ManiphestCreateTaskConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestCustomField' => 'PhabricatorCustomField', 'ManiphestCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'ManiphestCustomFieldStatusParser' => 'PhabricatorCustomFieldMonogramParser', 'ManiphestCustomFieldStatusParserTestCase' => 'PhabricatorTestCase', 'ManiphestCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'ManiphestCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestDefaultEditCapability' => 'PhabricatorPolicyCapability', 'ManiphestDefaultViewCapability' => 'PhabricatorPolicyCapability', 'ManiphestEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'ManiphestEditEngine' => 'PhabricatorEditEngine', 'ManiphestEmailCommand' => 'MetaMTAEmailTransactionCommand', 'ManiphestGetTaskTransactionsConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestMailEngineExtension' => 'PhabricatorMailEngineExtension', 'ManiphestNameIndex' => 'ManiphestDAO', 'ManiphestPointsConfigType' => 'PhabricatorJSONConfigType', 'ManiphestPrioritiesConfigType' => 'PhabricatorJSONConfigType', 'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand', 'ManiphestPrioritySearchConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'ManiphestQueryConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestQueryStatusesConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'ManiphestReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'ManiphestReportController' => 'ManiphestController', 'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand', 'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod', 'ManiphestStatusesConfigType' => 'PhabricatorJSONConfigType', 'ManiphestSubpriorityController' => 'ManiphestController', 'ManiphestSubtypesConfigType' => 'PhabricatorJSONConfigType', 'ManiphestTask' => array( 'ManiphestDAO', 'PhabricatorSubscribableInterface', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorMentionableInterface', 'PhrequentTrackableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorProjectInterface', 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'DoorkeeperBridgedObjectInterface', 'PhabricatorEditEngineSubtypeInterface', 'PhabricatorEditEngineLockableInterface', 'PhabricatorEditEngineMFAInterface', ), 'ManiphestTaskAssignHeraldAction' => 'HeraldAction', 'ManiphestTaskAssignOtherHeraldAction' => 'ManiphestTaskAssignHeraldAction', 'ManiphestTaskAssignSelfHeraldAction' => 'ManiphestTaskAssignHeraldAction', 'ManiphestTaskAssigneeHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskAttachTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskAuthorHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskAuthorPolicyRule' => 'PhabricatorPolicyRule', 'ManiphestTaskBulkEngine' => 'PhabricatorBulkEngine', 'ManiphestTaskCloseAsDuplicateRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskClosedStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskCoverImageTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskDependedOnByTaskEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskDependsOnTaskEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskDescriptionHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskDescriptionTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskDetailController' => 'ManiphestController', 'ManiphestTaskEdgeTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskEditController' => 'ManiphestController', 'ManiphestTaskEditEngineLock' => 'PhabricatorEditEngineLock', 'ManiphestTaskFerretEngine' => 'PhabricatorFerretEngine', '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', 'ManiphestTaskMFAEngine' => 'PhabricatorEditEngineMFAEngine', 'ManiphestTaskMailReceiver' => 'PhabricatorObjectMailReceiver', 'ManiphestTaskMergeInRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskMergedFromTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskMergedIntoTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskOpenStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskOwnerTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskPHIDResolver' => 'PhabricatorPHIDResolver', 'ManiphestTaskPHIDType' => 'PhabricatorPHIDType', 'ManiphestTaskParentTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskPoints' => 'Phobject', 'ManiphestTaskPointsTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskPriority' => 'ManiphestConstants', 'ManiphestTaskPriorityDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskPriorityHeraldAction' => 'HeraldAction', 'ManiphestTaskPriorityHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskPriorityTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ManiphestTaskRelationship' => 'PhabricatorObjectRelationship', 'ManiphestTaskRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'ManiphestTaskResultListView' => 'ManiphestView', 'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine', 'ManiphestTaskStatus' => 'ManiphestConstants', 'ManiphestTaskStatusDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskStatusFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'ManiphestTaskStatusHeraldAction' => 'HeraldAction', 'ManiphestTaskStatusHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskStatusTestCase' => 'PhabricatorTestCase', 'ManiphestTaskStatusTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskSubpriorityTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskSubtaskController' => 'ManiphestController', 'ManiphestTaskSubtypeDatasource' => 'PhabricatorTypeaheadDatasource', 'ManiphestTaskTestCase' => 'PhabricatorTestCase', 'ManiphestTaskTitleHeraldField' => 'ManiphestTaskHeraldField', 'ManiphestTaskTitleTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTaskTransactionType' => 'PhabricatorModularTransactionType', 'ManiphestTaskUnblockTransaction' => 'ManiphestTaskTransactionType', 'ManiphestTransaction' => 'PhabricatorModularTransaction', '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', 'NuanceCommandImplementation' => 'Phobject', 'NuanceConduitAPIMethod' => 'ConduitAPIMethod', 'NuanceConsoleController' => 'NuanceController', 'NuanceContentSource' => 'PhabricatorContentSource', 'NuanceController' => 'PhabricatorController', 'NuanceDAO' => 'PhabricatorLiskDAO', 'NuanceFormItemType' => 'NuanceItemType', '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', 'NuanceItemCommandSpec' => 'Phobject', 'NuanceItemCommandTransaction' => 'NuanceItemTransactionType', 'NuanceItemController' => 'NuanceController', 'NuanceItemEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceItemListController' => 'NuanceItemController', 'NuanceItemManageController' => 'NuanceController', 'NuanceItemOwnerTransaction' => 'NuanceItemTransactionType', 'NuanceItemPHIDType' => 'PhabricatorPHIDType', 'NuanceItemPropertyTransaction' => 'NuanceItemTransactionType', 'NuanceItemQuery' => 'NuanceQuery', 'NuanceItemQueueTransaction' => 'NuanceItemTransactionType', 'NuanceItemRequestorTransaction' => 'NuanceItemTransactionType', 'NuanceItemSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceItemSourceTransaction' => 'NuanceItemTransactionType', 'NuanceItemStatusTransaction' => 'NuanceItemTransactionType', 'NuanceItemTransaction' => 'NuanceTransaction', 'NuanceItemTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceItemTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceItemTransactionType' => 'PhabricatorModularTransactionType', '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', 'NuanceQueueNameTransaction' => 'NuanceQueueTransactionType', 'NuanceQueuePHIDType' => 'PhabricatorPHIDType', 'NuanceQueueQuery' => 'NuanceQuery', 'NuanceQueueSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceQueueTransaction' => 'NuanceTransaction', 'NuanceQueueTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceQueueTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceQueueTransactionType' => 'PhabricatorModularTransactionType', 'NuanceQueueViewController' => 'NuanceQueueController', 'NuanceQueueWorkController' => 'NuanceQueueController', 'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'NuanceSource' => array( 'NuanceDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorNgramsInterface', ), 'NuanceSourceActionController' => 'NuanceController', 'NuanceSourceController' => 'NuanceController', 'NuanceSourceDefaultEditCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceDefaultQueueTransaction' => 'NuanceSourceTransactionType', 'NuanceSourceDefaultViewCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceDefinition' => 'Phobject', 'NuanceSourceDefinitionTestCase' => 'PhabricatorTestCase', 'NuanceSourceEditController' => 'NuanceSourceController', 'NuanceSourceEditEngine' => 'PhabricatorEditEngine', 'NuanceSourceEditor' => 'PhabricatorApplicationTransactionEditor', 'NuanceSourceListController' => 'NuanceSourceController', 'NuanceSourceManageCapability' => 'PhabricatorPolicyCapability', 'NuanceSourceNameNgrams' => 'PhabricatorSearchNgrams', 'NuanceSourceNameTransaction' => 'NuanceSourceTransactionType', 'NuanceSourcePHIDType' => 'PhabricatorPHIDType', 'NuanceSourceQuery' => 'NuanceQuery', 'NuanceSourceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'NuanceSourceTransaction' => 'NuanceTransaction', 'NuanceSourceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'NuanceSourceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'NuanceSourceTransactionType' => 'PhabricatorModularTransactionType', 'NuanceSourceViewController' => 'NuanceSourceController', 'NuanceTransaction' => 'PhabricatorModularTransaction', 'NuanceTrashCommand' => 'NuanceCommandImplementation', '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', 'PHUIBigInfoExample' => 'PhabricatorUIExample', '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', 'PHUIDiffInlineCommentPreviewListView' => 'AphrontView', 'PHUIDiffInlineCommentRowScaffold' => 'AphrontView', 'PHUIDiffInlineCommentTableScaffold' => 'AphrontView', 'PHUIDiffInlineCommentUndoView' => 'PHUIDiffInlineCommentView', 'PHUIDiffInlineCommentView' => 'AphrontView', 'PHUIDiffInlineThreader' => 'Phobject', 'PHUIDiffOneUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 'PHUIDiffRevealIconView' => 'AphrontView', 'PHUIDiffTableOfContentsItemView' => 'AphrontView', 'PHUIDiffTableOfContentsListView' => 'AphrontView', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', 'PHUIDocumentSummaryView' => 'AphrontTagView', 'PHUIDocumentView' => 'AphrontTagView', 'PHUIFeedStoryExample' => 'PhabricatorUIExample', 'PHUIFeedStoryView' => 'AphrontView', 'PHUIFormDividerControl' => 'AphrontFormControl', 'PHUIFormFileControl' => 'AphrontFormControl', 'PHUIFormFreeformDateControl' => 'AphrontFormControl', 'PHUIFormIconSetControl' => 'AphrontFormControl', 'PHUIFormInsetView' => 'AphrontView', 'PHUIFormLayoutView' => 'AphrontView', 'PHUIFormNumberControl' => 'AphrontFormControl', 'PHUIFormTimerControl' => 'AphrontFormControl', 'PHUIHandleListView' => 'AphrontTagView', 'PHUIHandleTagListView' => 'AphrontTagView', 'PHUIHandleView' => 'AphrontView', 'PHUIHeadThingView' => 'AphrontTagView', 'PHUIHeaderView' => 'AphrontTagView', 'PHUIHomeView' => 'AphrontTagView', 'PHUIHovercardUIExample' => 'PhabricatorUIExample', 'PHUIHovercardView' => 'AphrontTagView', 'PHUIIconCircleView' => 'AphrontTagView', 'PHUIIconExample' => 'PhabricatorUIExample', 'PHUIIconView' => 'AphrontTagView', 'PHUIImageMaskExample' => 'PhabricatorUIExample', 'PHUIImageMaskView' => 'AphrontTagView', 'PHUIInfoExample' => 'PhabricatorUIExample', 'PHUIInfoView' => 'AphrontTagView', 'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase', 'PHUIInvisibleCharacterView' => 'AphrontView', 'PHUILeftRightExample' => 'PhabricatorUIExample', 'PHUILeftRightView' => 'AphrontTagView', 'PHUIListExample' => 'PhabricatorUIExample', 'PHUIListItemView' => 'AphrontTagView', 'PHUIListView' => 'AphrontTagView', 'PHUIListViewTestCase' => 'PhabricatorTestCase', 'PHUIObjectBoxView' => 'AphrontTagView', 'PHUIObjectItemListExample' => 'PhabricatorUIExample', 'PHUIObjectItemListView' => 'AphrontTagView', 'PHUIObjectItemView' => 'AphrontTagView', 'PHUIPagerView' => 'AphrontView', 'PHUIPinboardItemView' => 'AphrontView', 'PHUIPinboardView' => 'AphrontView', 'PHUIPolicySectionView' => 'AphrontTagView', 'PHUIPropertyGroupView' => 'AphrontTagView', 'PHUIPropertyListExample' => 'PhabricatorUIExample', 'PHUIPropertyListView' => 'AphrontView', 'PHUIRemarkupImageView' => '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', 'PHUIXComponentsExample' => 'PhabricatorUIExample', 'PassphraseAbstractKey' => 'Phobject', 'PassphraseConduitAPIMethod' => 'ConduitAPIMethod', 'PassphraseController' => 'PhabricatorController', 'PassphraseCredential' => array( 'PassphraseDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', ), 'PassphraseCredentialAuthorPolicyRule' => 'PhabricatorPolicyRule', 'PassphraseCredentialConduitController' => 'PassphraseController', 'PassphraseCredentialConduitTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialControl' => 'AphrontFormControl', 'PassphraseCredentialCreateController' => 'PassphraseController', 'PassphraseCredentialDescriptionTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialDestroyController' => 'PassphraseController', 'PassphraseCredentialDestroyTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialEditController' => 'PassphraseController', 'PassphraseCredentialFerretEngine' => 'PhabricatorFerretEngine', 'PassphraseCredentialFulltextEngine' => 'PhabricatorFulltextEngine', 'PassphraseCredentialListController' => 'PassphraseController', 'PassphraseCredentialLockController' => 'PassphraseController', 'PassphraseCredentialLockTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialLookedAtTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialNameTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialPHIDType' => 'PhabricatorPHIDType', 'PassphraseCredentialPublicController' => 'PassphraseController', 'PassphraseCredentialQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PassphraseCredentialRevealController' => 'PassphraseController', 'PassphraseCredentialSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PassphraseCredentialSecretIDTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialTransaction' => 'PhabricatorModularTransaction', 'PassphraseCredentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PassphraseCredentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PassphraseCredentialTransactionType' => 'PhabricatorModularTransactionType', 'PassphraseCredentialType' => 'Phobject', 'PassphraseCredentialTypeTestCase' => 'PhabricatorTestCase', 'PassphraseCredentialUsernameTransaction' => 'PassphraseCredentialTransactionType', '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' => 'PhabricatorApplicationMailReceiver', 'PasteDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PasteDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PasteEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PasteEmbedView' => 'AphrontView', 'PasteInfoConduitAPIMethod' => 'PasteConduitAPIMethod', 'PasteLanguageSelectDatasource' => 'PhabricatorTypeaheadDatasource', 'PasteMailReceiver' => 'PhabricatorObjectMailReceiver', 'PasteQueryConduitAPIMethod' => 'PasteConduitAPIMethod', 'PasteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PasteSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability', 'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability', 'PeopleDisableUsersCapability' => 'PhabricatorPolicyCapability', 'PeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PeopleUserLogGarbageCollector' => 'PhabricatorGarbageCollector', 'Phabricator404Controller' => 'PhabricatorController', 'PhabricatorAWSConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAccessControlTestCase' => 'PhabricatorTestCase', 'PhabricatorAccessLog' => 'Phobject', 'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAccessibilitySetting' => 'PhabricatorSelectSetting', 'PhabricatorActionListView' => 'AphrontTagView', 'PhabricatorActionView' => 'AphrontView', 'PhabricatorActivitySettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorAdministratorsPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorAjaxRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorAlmanacApplication' => 'PhabricatorApplication', 'PhabricatorAmazonAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorAmazonSNSFuture' => 'PhutilAWSFuture', 'PhabricatorAnchorView' => 'AphrontView', 'PhabricatorAphlictManagementDebugWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementNotifyWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementRestartWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementStartWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementStatusWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementStopWorkflow' => 'PhabricatorAphlictManagementWorkflow', 'PhabricatorAphlictManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAphlictSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorAphrontBarUIExample' => 'PhabricatorUIExample', 'PhabricatorAphrontViewTestCase' => 'PhabricatorTestCase', 'PhabricatorAppSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorApplication' => array( 'PhabricatorLiskDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorApplicationApplicationPHIDType' => 'PhabricatorPHIDType', 'PhabricatorApplicationApplicationTransaction' => 'PhabricatorModularTransaction', 'PhabricatorApplicationApplicationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorApplicationConfigOptions' => 'Phobject', 'PhabricatorApplicationConfigurationPanel' => 'Phobject', 'PhabricatorApplicationConfigurationPanelTestCase' => 'PhabricatorTestCase', 'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView', 'PhabricatorApplicationEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationMailReceiver' => 'PhabricatorMailReceiver', 'PhabricatorApplicationObjectMailEngineExtension' => 'PhabricatorMailEngineExtension', 'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationPolicyChangeTransaction' => 'PhabricatorApplicationTransactionType', 'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorApplicationSearchEngine' => 'Phobject', 'PhabricatorApplicationSearchEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorApplicationSearchResultView' => 'Phobject', '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', 'PhabricatorApplicationTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorApplicationTransactionValidationError' => 'Phobject', 'PhabricatorApplicationTransactionValidationException' => 'Exception', 'PhabricatorApplicationTransactionValidationResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionValueController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionView' => 'AphrontView', 'PhabricatorApplicationTransactionWarningException' => 'Exception', 'PhabricatorApplicationTransactionWarningResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationUninstallTransaction' => 'PhabricatorApplicationTransactionType', 'PhabricatorApplicationsApplication' => 'PhabricatorApplication', 'PhabricatorApplicationsController' => 'PhabricatorController', 'PhabricatorApplicationsListController' => 'PhabricatorApplicationsController', 'PhabricatorApplyEditField' => 'PhabricatorEditField', 'PhabricatorAsanaAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorAsanaConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAsanaSubtaskHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorAsanaTaskHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorAudioDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorAuditActionConstants' => 'Phobject', 'PhabricatorAuditApplication' => 'PhabricatorApplication', 'PhabricatorAuditCommentEditor' => 'PhabricatorEditor', 'PhabricatorAuditController' => 'PhabricatorController', 'PhabricatorAuditEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuditInlineComment' => array( 'Phobject', 'PhabricatorInlineCommentInterface', ), 'PhabricatorAuditListView' => 'AphrontView', 'PhabricatorAuditMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow', 'PhabricatorAuditManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuditReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorAuditStatusConstants' => 'Phobject', 'PhabricatorAuditSynchronizeManagementWorkflow' => 'PhabricatorAuditManagementWorkflow', 'PhabricatorAuditTransaction' => 'PhabricatorModularTransaction', 'PhabricatorAuditTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorAuditTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuditTransactionView' => 'PhabricatorApplicationTransactionView', 'PhabricatorAuditUpdateOwnersManagementWorkflow' => 'PhabricatorAuditManagementWorkflow', 'PhabricatorAuthAccountView' => 'AphrontView', 'PhabricatorAuthApplication' => 'PhabricatorApplication', 'PhabricatorAuthAuthFactorPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthAuthFactorProviderPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthAuthProviderPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthCSRFEngine' => 'Phobject', 'PhabricatorAuthChallenge' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthChallengeGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorAuthChallengePHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthChallengeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthChangePasswordAction' => 'PhabricatorSystemAction', 'PhabricatorAuthConduitAPIMethod' => 'ConduitAPIMethod', 'PhabricatorAuthConduitTokenRevoker' => 'PhabricatorAuthRevoker', 'PhabricatorAuthConfirmLinkController' => 'PhabricatorAuthController', 'PhabricatorAuthContactNumber' => array( 'PhabricatorAuthDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorEditEngineMFAInterface', ), 'PhabricatorAuthContactNumberController' => 'PhabricatorAuthController', 'PhabricatorAuthContactNumberDisableController' => 'PhabricatorAuthContactNumberController', 'PhabricatorAuthContactNumberEditController' => 'PhabricatorAuthContactNumberController', 'PhabricatorAuthContactNumberEditEngine' => 'PhabricatorEditEngine', 'PhabricatorAuthContactNumberEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthContactNumberMFAEngine' => 'PhabricatorEditEngineMFAEngine', 'PhabricatorAuthContactNumberNumberTransaction' => 'PhabricatorAuthContactNumberTransactionType', 'PhabricatorAuthContactNumberPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthContactNumberPrimaryController' => 'PhabricatorAuthContactNumberController', 'PhabricatorAuthContactNumberPrimaryTransaction' => 'PhabricatorAuthContactNumberTransactionType', 'PhabricatorAuthContactNumberQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthContactNumberStatusTransaction' => 'PhabricatorAuthContactNumberTransactionType', 'PhabricatorAuthContactNumberTestController' => 'PhabricatorAuthContactNumberController', 'PhabricatorAuthContactNumberTransaction' => 'PhabricatorModularTransaction', 'PhabricatorAuthContactNumberTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthContactNumberTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorAuthContactNumberViewController' => 'PhabricatorAuthContactNumberController', 'PhabricatorAuthController' => 'PhabricatorController', 'PhabricatorAuthDAO' => 'PhabricatorLiskDAO', 'PhabricatorAuthDisableController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthDowngradeSessionController' => 'PhabricatorAuthController', 'PhabricatorAuthEditController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthFactor' => 'Phobject', 'PhabricatorAuthFactorConfig' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorAuthFactorConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthFactorProvider' => array( 'PhabricatorAuthDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorEditEngineMFAInterface', ), 'PhabricatorAuthFactorProviderController' => 'PhabricatorAuthProviderController', 'PhabricatorAuthFactorProviderDuoCredentialTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderDuoEnrollTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderDuoHostnameTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderDuoUsernamesTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderEditController' => 'PhabricatorAuthFactorProviderController', 'PhabricatorAuthFactorProviderEditEngine' => 'PhabricatorEditEngine', 'PhabricatorAuthFactorProviderEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthFactorProviderEnrollMessageTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderListController' => 'PhabricatorAuthProviderController', 'PhabricatorAuthFactorProviderMFAEngine' => 'PhabricatorEditEngineMFAEngine', 'PhabricatorAuthFactorProviderMessageController' => 'PhabricatorAuthFactorProviderController', 'PhabricatorAuthFactorProviderNameTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthFactorProviderStatus' => 'Phobject', 'PhabricatorAuthFactorProviderStatusTransaction' => 'PhabricatorAuthFactorProviderTransactionType', 'PhabricatorAuthFactorProviderTransaction' => 'PhabricatorModularTransaction', 'PhabricatorAuthFactorProviderTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthFactorProviderTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorAuthFactorProviderViewController' => 'PhabricatorAuthFactorProviderController', 'PhabricatorAuthFactorResult' => 'Phobject', 'PhabricatorAuthFactorTestCase' => 'PhabricatorTestCase', 'PhabricatorAuthFinishController' => 'PhabricatorAuthController', 'PhabricatorAuthHMACKey' => 'PhabricatorAuthDAO', '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', 'PhabricatorAuthLoginMessageType' => 'PhabricatorAuthMessageType', 'PhabricatorAuthLogoutConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthMFAEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorAuthMFASyncTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorAuthManagementCachePKCS8Workflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementLDAPWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementListFactorsWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementListMFAProvidersWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementRecoverWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementRefreshWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementRevokeWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementStripWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUnlimitWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuthMessage' => array( 'PhabricatorAuthDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorAuthMessageController' => 'PhabricatorAuthProviderController', 'PhabricatorAuthMessageEditController' => 'PhabricatorAuthMessageController', 'PhabricatorAuthMessageEditEngine' => 'PhabricatorEditEngine', 'PhabricatorAuthMessageEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthMessageListController' => 'PhabricatorAuthProviderController', 'PhabricatorAuthMessagePHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthMessageTextTransaction' => 'PhabricatorAuthMessageTransactionType', 'PhabricatorAuthMessageTransaction' => 'PhabricatorModularTransaction', 'PhabricatorAuthMessageTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthMessageTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorAuthMessageType' => 'Phobject', 'PhabricatorAuthMessageViewController' => 'PhabricatorAuthMessageController', 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', 'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthNewFactorAction' => 'PhabricatorSystemAction', 'PhabricatorAuthOldOAuthRedirectController' => 'PhabricatorAuthController', 'PhabricatorAuthOneTimeLoginController' => 'PhabricatorAuthController', 'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorAuthPassword' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorAuthPasswordEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthPasswordEngine' => 'Phobject', 'PhabricatorAuthPasswordException' => 'Exception', 'PhabricatorAuthPasswordPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthPasswordQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthPasswordResetTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType', 'PhabricatorAuthPasswordRevokeTransaction' => 'PhabricatorAuthPasswordTransactionType', 'PhabricatorAuthPasswordRevoker' => 'PhabricatorAuthRevoker', 'PhabricatorAuthPasswordTestCase' => 'PhabricatorTestCase', 'PhabricatorAuthPasswordTransaction' => 'PhabricatorModularTransaction', 'PhabricatorAuthPasswordTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthPasswordTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorAuthPasswordUpgradeTransaction' => 'PhabricatorAuthPasswordTransactionType', 'PhabricatorAuthProvider' => 'Phobject', 'PhabricatorAuthProviderConfig' => array( 'PhabricatorAuthDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthProviderController', 'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthProviderController' => 'PhabricatorAuthController', + 'PhabricatorAuthProviderViewController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthProvidersGuidanceContext' => 'PhabricatorGuidanceContext', 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'PhabricatorGuidanceEngineExtension', 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthRegisterController' => 'PhabricatorAuthController', 'PhabricatorAuthRevokeTokenController' => 'PhabricatorAuthController', 'PhabricatorAuthRevoker' => 'Phobject', 'PhabricatorAuthSSHKey' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorAuthSSHKeyController' => 'PhabricatorAuthController', 'PhabricatorAuthSSHKeyEditController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthSSHKeyGenerateController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyListController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeyPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthSSHKeyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthSSHKeyReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorAuthSSHKeyRevokeController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHKeySearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorAuthSSHKeyTableView' => 'AphrontView', 'PhabricatorAuthSSHKeyTestCase' => 'PhabricatorTestCase', 'PhabricatorAuthSSHKeyTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorAuthSSHKeyTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthSSHKeyViewController' => 'PhabricatorAuthSSHKeyController', 'PhabricatorAuthSSHPublicKey' => 'Phobject', 'PhabricatorAuthSSHRevoker' => 'PhabricatorAuthRevoker', 'PhabricatorAuthSession' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthSessionEngine' => 'Phobject', 'PhabricatorAuthSessionEngineExtension' => 'Phobject', 'PhabricatorAuthSessionEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorAuthSessionGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorAuthSessionInfo' => 'Phobject', 'PhabricatorAuthSessionPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthSessionRevoker' => 'PhabricatorAuthRevoker', 'PhabricatorAuthSetPasswordController' => 'PhabricatorAuthController', 'PhabricatorAuthSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorAuthStartController' => 'PhabricatorAuthController', 'PhabricatorAuthTemporaryToken' => array( 'PhabricatorAuthDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorAuthTemporaryTokenGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorAuthTemporaryTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthTemporaryTokenRevoker' => 'PhabricatorAuthRevoker', 'PhabricatorAuthTemporaryTokenType' => 'Phobject', 'PhabricatorAuthTemporaryTokenTypeModule' => 'PhabricatorConfigModule', 'PhabricatorAuthTerminateSessionController' => 'PhabricatorAuthController', 'PhabricatorAuthTestSMSAction' => 'PhabricatorSystemAction', 'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction', 'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController', 'PhabricatorAuthValidateController' => 'PhabricatorAuthController', 'PhabricatorAuthWelcomeMailMessageType' => 'PhabricatorAuthMessageType', 'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAutoEventListener' => 'PhabricatorEventListener', 'PhabricatorBadgesApplication' => 'PhabricatorApplication', 'PhabricatorBadgesArchiveController' => 'PhabricatorBadgesController', 'PhabricatorBadgesAward' => array( 'PhabricatorBadgesDAO', 'PhabricatorDestructibleInterface', 'PhabricatorPolicyInterface', ), 'PhabricatorBadgesAwardController' => 'PhabricatorBadgesController', 'PhabricatorBadgesAwardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorBadgesAwardTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorBadgesBadge' => array( 'PhabricatorBadgesDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorBadgesBadgeAwardTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeDescriptionTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeFlavorTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeIconTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorBadgesBadgeNameTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeQualityTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeRevokeTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeStatusTransaction' => 'PhabricatorBadgesBadgeTransactionType', 'PhabricatorBadgesBadgeTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorBadgesBadgeTransactionType' => 'PhabricatorModularTransactionType', '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', 'PhabricatorBadgesLootContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorBadgesMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorBadgesPHIDType' => 'PhabricatorPHIDType', 'PhabricatorBadgesProfileController' => 'PhabricatorController', 'PhabricatorBadgesQuality' => 'Phobject', 'PhabricatorBadgesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorBadgesRecipientsController' => 'PhabricatorBadgesProfileController', 'PhabricatorBadgesRecipientsListView' => 'AphrontView', 'PhabricatorBadgesRemoveRecipientsController' => 'PhabricatorBadgesController', 'PhabricatorBadgesReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorBadgesSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorBadgesSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorBadgesSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorBadgesTransaction' => 'PhabricatorModularTransaction', 'PhabricatorBadgesTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorBadgesTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorBadgesViewController' => 'PhabricatorBadgesProfileController', 'PhabricatorBarePageView' => 'AphrontPageView', 'PhabricatorBaseURISetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorBcryptPasswordHasher' => 'PhabricatorPasswordHasher', 'PhabricatorBinariesSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorBitbucketAuthProvider' => 'PhabricatorOAuth1AuthProvider', 'PhabricatorBoardColumnsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorBoardLayoutEngine' => 'Phobject', 'PhabricatorBoardRenderingEngine' => 'Phobject', 'PhabricatorBoardResponseEngine' => 'Phobject', 'PhabricatorBoolConfigType' => 'PhabricatorTextConfigType', 'PhabricatorBoolEditField' => 'PhabricatorEditField', 'PhabricatorBoolMailStamp' => 'PhabricatorMailStamp', 'PhabricatorBritishEnglishTranslation' => 'PhutilTranslation', 'PhabricatorBuiltinDraftEngine' => 'PhabricatorDraftEngine', 'PhabricatorBuiltinFileCachePurger' => 'PhabricatorCachePurger', 'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList', 'PhabricatorBulkContentSource' => 'PhabricatorContentSource', 'PhabricatorBulkEditGroup' => 'Phobject', 'PhabricatorBulkEngine' => 'Phobject', 'PhabricatorBulkManagementExportWorkflow' => 'PhabricatorBulkManagementWorkflow', 'PhabricatorBulkManagementMakeSilentWorkflow' => 'PhabricatorBulkManagementWorkflow', 'PhabricatorBulkManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorCSVExportFormat' => 'PhabricatorExportFormat', 'PhabricatorCacheDAO' => 'PhabricatorLiskDAO', 'PhabricatorCacheEngine' => 'Phobject', 'PhabricatorCacheEngineExtension' => 'Phobject', 'PhabricatorCacheGeneralGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorCacheManagementPurgeWorkflow' => 'PhabricatorCacheManagementWorkflow', 'PhabricatorCacheManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorCacheMarkupGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorCachePurger' => 'Phobject', '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', 'PhabricatorFerretInterface', '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', 'PhabricatorCalendarEventFerretEngine' => 'PhabricatorFerretEngine', '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', 'PhabricatorCelerityApplication' => 'PhabricatorApplication', 'PhabricatorCelerityTestCase' => 'PhabricatorTestCase', 'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase', 'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger', 'PhabricatorChangesetResponse' => 'AphrontProxyResponse', 'PhabricatorChatLogApplication' => 'PhabricatorApplication', 'PhabricatorChatLogChannel' => array( 'PhabricatorChatLogDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController', 'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController', 'PhabricatorChatLogChannelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorChatLogController' => 'PhabricatorController', 'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO', 'PhabricatorChatLogEvent' => array( 'PhabricatorChatLogDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCheckboxesEditField' => 'PhabricatorEditField', 'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorClassConfigType' => 'PhabricatorTextConfigType', 'PhabricatorClusterConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorClusterDatabasesConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorClusterException' => 'Exception', 'PhabricatorClusterExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorClusterImpossibleWriteException' => 'PhabricatorClusterException', 'PhabricatorClusterImproperWriteException' => 'PhabricatorClusterException', 'PhabricatorClusterMailersConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorClusterNoHostForRoleException' => 'Exception', 'PhabricatorClusterSearchConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorClusterServiceHealthRecord' => 'Phobject', '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', 'PhabricatorConduitCallManagementWorkflow' => 'PhabricatorConduitManagementWorkflow', 'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 'PhabricatorConduitContentSource' => 'PhabricatorContentSource', 'PhabricatorConduitController' => 'PhabricatorController', 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 'PhabricatorConduitEditField' => 'PhabricatorEditField', 'PhabricatorConduitListController' => 'PhabricatorConduitController', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorConduitManagementWorkflow' => 'PhabricatorManagementWorkflow', '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', 'PhabricatorConfigClusterSearchController' => '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' => 'Phobject', 'PhabricatorConfigOptionType' => 'Phobject', 'PhabricatorConfigPHIDModule' => 'PhabricatorConfigModule', 'PhabricatorConfigProxySource' => 'PhabricatorConfigSource', 'PhabricatorConfigPurgeCacheController' => 'PhabricatorConfigController', 'PhabricatorConfigRegexOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorConfigRemarkupRule' => 'PhutilRemarkupRule', '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', 'PhabricatorConfigType' => 'Phobject', 'PhabricatorConfigValidationException' => 'Exception', 'PhabricatorConfigVersionController' => 'PhabricatorConfigController', 'PhabricatorConpherenceApplication' => 'PhabricatorApplication', 'PhabricatorConpherenceColumnMinimizeSetting' => 'PhabricatorInternalSetting', 'PhabricatorConpherenceColumnVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorConpherenceNotificationsSetting' => 'PhabricatorSelectSetting', 'PhabricatorConpherencePreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorConpherenceProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorConpherenceRoomContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorConpherenceRoomTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorConpherenceSoundSetting' => 'PhabricatorSelectSetting', 'PhabricatorConpherenceThreadPHIDType' => 'PhabricatorPHIDType', 'PhabricatorConpherenceWidgetVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorConsoleApplication' => 'PhabricatorApplication', 'PhabricatorConsoleContentSource' => 'PhabricatorContentSource', 'PhabricatorContactNumbersSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorContentSource' => 'Phobject', 'PhabricatorContentSourceModule' => 'PhabricatorConfigModule', 'PhabricatorContentSourceView' => 'AphrontView', 'PhabricatorContributedToObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorController' => 'AphrontController', 'PhabricatorCookies' => 'Phobject', 'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorCoreCreateTransaction' => 'PhabricatorCoreTransactionType', 'PhabricatorCoreTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorCoreVoidTransaction' => 'PhabricatorModularTransactionType', 'PhabricatorCountFact' => 'PhabricatorFact', 'PhabricatorCountdown' => array( 'PhabricatorCountdownDAO', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorSpacesInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorCountdownApplication' => 'PhabricatorApplication', 'PhabricatorCountdownController' => 'PhabricatorController', 'PhabricatorCountdownCountdownPHIDType' => 'PhabricatorPHIDType', 'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO', 'PhabricatorCountdownDefaultEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorCountdownDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorCountdownDescriptionTransaction' => 'PhabricatorCountdownTransactionType', 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditEngine' => 'PhabricatorEditEngine', 'PhabricatorCountdownEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorCountdownEpochTransaction' => 'PhabricatorCountdownTransactionType', 'PhabricatorCountdownListController' => 'PhabricatorCountdownController', 'PhabricatorCountdownMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorCountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorCountdownRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorCountdownReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorCountdownSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorCountdownSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorCountdownTitleTransaction' => 'PhabricatorCountdownTransactionType', 'PhabricatorCountdownTransaction' => 'PhabricatorModularTransaction', 'PhabricatorCountdownTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorCountdownTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorCountdownTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorCountdownView' => 'AphrontView', 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 'PhabricatorCredentialEditField' => 'PhabricatorEditField', 'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorCustomField' => 'Phobject', 'PhabricatorCustomFieldApplicationSearchAnyFunctionDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorCustomFieldApplicationSearchDatasource' => 'PhabricatorTypeaheadProxyDatasource', 'PhabricatorCustomFieldApplicationSearchNoneFunctionDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorCustomFieldAttachment' => 'Phobject', 'PhabricatorCustomFieldConfigOptionType' => 'PhabricatorConfigOptionType', 'PhabricatorCustomFieldDataNotAvailableException' => 'Exception', 'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorCustomFieldEditField' => 'PhabricatorEditField', 'PhabricatorCustomFieldEditType' => 'PhabricatorEditType', 'PhabricatorCustomFieldExportEngineExtension' => 'PhabricatorExportEngineExtension', 'PhabricatorCustomFieldFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorCustomFieldHeraldAction' => 'HeraldAction', 'PhabricatorCustomFieldHeraldActionGroup' => 'HeraldActionGroup', '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', 'PhabricatorCustomUIFooterConfigType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorDaemon' => 'PhutilDaemon', 'PhabricatorDaemonBulkJobController' => 'PhabricatorDaemonController', 'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonBulkJobController', 'PhabricatorDaemonBulkJobMonitorController' => 'PhabricatorDaemonBulkJobController', 'PhabricatorDaemonBulkJobViewController' => 'PhabricatorDaemonBulkJobController', 'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController', 'PhabricatorDaemonContentSource' => 'PhabricatorContentSource', 'PhabricatorDaemonController' => 'PhabricatorController', 'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO', 'PhabricatorDaemonEventListener' => 'PhabricatorEventListener', 'PhabricatorDaemonLockLog' => 'PhabricatorDaemonDAO', 'PhabricatorDaemonLockLogGarbageCollector' => 'PhabricatorGarbageCollector', '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', 'PhabricatorDashboardArrangeController' => 'PhabricatorDashboardProfileController', 'PhabricatorDashboardController' => 'PhabricatorController', 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'PhabricatorEdgeType', 'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType', 'PhabricatorDashboardDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', 'PhabricatorDashboardIconSet' => 'PhabricatorIconSet', 'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO', 'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController', 'PhabricatorDashboardLayoutConfig' => 'Phobject', 'PhabricatorDashboardListController' => 'PhabricatorDashboardController', 'PhabricatorDashboardManageController' => 'PhabricatorDashboardProfileController', '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', 'PhabricatorDashboardProfileController' => 'PhabricatorController', 'PhabricatorDashboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorDashboardQueryPanelInstallController' => 'PhabricatorDashboardController', 'PhabricatorDashboardQueryPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorDashboardRemovePanelController' => 'PhabricatorDashboardController', 'PhabricatorDashboardRenderingEngine' => 'Phobject', 'PhabricatorDashboardSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorDashboardTabsPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardTextPanelType' => 'PhabricatorDashboardPanelType', 'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorDashboardTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorDashboardViewController' => 'PhabricatorDashboardProfileController', 'PhabricatorDataCacheSpec' => 'PhabricatorCacheSpec', 'PhabricatorDataNotAttachedException' => 'Exception', 'PhabricatorDatabaseRef' => 'Phobject', 'PhabricatorDatabaseRefParser' => 'Phobject', 'PhabricatorDatabaseSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorDatasourceApplicationEngineExtension' => 'PhabricatorDatasourceEngineExtension', 'PhabricatorDatasourceEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorDatasourceEditType' => 'PhabricatorPHIDListEditType', 'PhabricatorDatasourceEngine' => 'Phobject', 'PhabricatorDatasourceEngineExtension' => 'Phobject', 'PhabricatorDateFormatSetting' => 'PhabricatorSelectSetting', 'PhabricatorDateTimeSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDebugController' => 'PhabricatorController', 'PhabricatorDefaultRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorDefaultSyntaxStyle' => 'PhabricatorSyntaxStyle', 'PhabricatorDestructibleCodex' => 'Phobject', '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', 'PhabricatorDifferentialMigrateHunkWorkflow' => 'PhabricatorDifferentialManagementWorkflow', 'PhabricatorDifferentialRebuildChangesetsWorkflow' => 'PhabricatorDifferentialManagementWorkflow', 'PhabricatorDifferentialRevisionTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorDiffusionApplication' => 'PhabricatorApplication', 'PhabricatorDiffusionBlameSetting' => 'PhabricatorInternalSetting', 'PhabricatorDiffusionConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDisplayPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorDisqusAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorDividerEditField' => 'PhabricatorEditField', 'PhabricatorDividerProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorDivinerApplication' => 'PhabricatorApplication', 'PhabricatorDocumentEngine' => 'Phobject', 'PhabricatorDocumentRef' => 'Phobject', 'PhabricatorDocumentRenderingEngine' => 'Phobject', 'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication', 'PhabricatorDoubleExportField' => 'PhabricatorExportField', 'PhabricatorDraft' => 'PhabricatorDraftDAO', 'PhabricatorDraftDAO' => 'PhabricatorLiskDAO', 'PhabricatorDraftEngine' => 'Phobject', 'PhabricatorDrydockApplication' => 'PhabricatorApplication', 'PhabricatorDuoAuthFactor' => 'PhabricatorAuthFactor', 'PhabricatorDuoFuture' => 'FutureProxy', 'PhabricatorEdgeChangeRecord' => 'Phobject', 'PhabricatorEdgeChangeRecordTestCase' => 'PhabricatorTestCase', 'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants', 'PhabricatorEdgeConstants' => 'Phobject', 'PhabricatorEdgeCycleException' => 'Exception', 'PhabricatorEdgeEditType' => 'PhabricatorPHIDListEditType', 'PhabricatorEdgeEditor' => 'Phobject', 'PhabricatorEdgeGraph' => 'AbstractDirectedGraph', 'PhabricatorEdgeObject' => array( 'Phobject', 'PhabricatorPolicyInterface', ), 'PhabricatorEdgeObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorEdgeQuery' => 'PhabricatorQuery', 'PhabricatorEdgeTestCase' => 'PhabricatorTestCase', 'PhabricatorEdgeType' => 'Phobject', 'PhabricatorEdgeTypeTestCase' => 'PhabricatorTestCase', 'PhabricatorEdgesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorEditEngine' => array( 'Phobject', 'PhabricatorPolicyInterface', ), 'PhabricatorEditEngineAPIMethod' => 'ConduitAPIMethod', 'PhabricatorEditEngineBulkJobType' => 'PhabricatorWorkerBulkJobType', 'PhabricatorEditEngineCheckboxesCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineColumnsCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineCommentAction' => 'Phobject', 'PhabricatorEditEngineCommentActionGroup' => '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', 'PhabricatorEditEngineConfigurationSubtypeController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineController' => 'PhabricatorApplicationTransactionController', 'PhabricatorEditEngineDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorEditEngineDefaultLock' => 'PhabricatorEditEngineLock', 'PhabricatorEditEngineExtension' => 'Phobject', 'PhabricatorEditEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorEditEngineListController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineLock' => 'Phobject', 'PhabricatorEditEngineMFAEngine' => 'Phobject', 'PhabricatorEditEnginePointsCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorEditEngineQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorEditEngineSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorEditEngineSelectCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorEditEngineStaticCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditEngineSubtype' => 'Phobject', 'PhabricatorEditEngineSubtypeMap' => 'Phobject', 'PhabricatorEditEngineSubtypeTestCase' => 'PhabricatorTestCase', 'PhabricatorEditEngineTokenizerCommentAction' => 'PhabricatorEditEngineCommentAction', 'PhabricatorEditField' => 'Phobject', 'PhabricatorEditPage' => 'Phobject', 'PhabricatorEditType' => 'Phobject', 'PhabricatorEditor' => 'Phobject', 'PhabricatorEditorExtension' => 'Phobject', 'PhabricatorEditorExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorEditorMailEngineExtension' => 'PhabricatorMailEngineExtension', 'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting', 'PhabricatorEditorSetting' => 'PhabricatorStringSetting', 'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', 'PhabricatorElasticsearchHost' => 'PhabricatorSearchHost', 'PhabricatorElasticsearchSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorEmailAddressesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorEmailContentSource' => 'PhabricatorContentSource', 'PhabricatorEmailDeliverySettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorEmailFormatSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailFormatSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorEmailLoginController' => 'PhabricatorAuthController', 'PhabricatorEmailNotificationsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailPreferencesSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorEmailRePrefixSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailSelfActionsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailStampsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailTagsSetting' => 'PhabricatorInternalSetting', 'PhabricatorEmailVarySubjectsSetting' => 'PhabricatorSelectSetting', 'PhabricatorEmailVerificationController' => 'PhabricatorAuthController', 'PhabricatorEmbedFileRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorEmojiDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorEmojiRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorEmojiTranslation' => 'PhutilTranslation', 'PhabricatorEmptyQueryException' => 'Exception', 'PhabricatorEnumConfigType' => 'PhabricatorTextConfigType', 'PhabricatorEnv' => 'Phobject', 'PhabricatorEnvTestCase' => 'PhabricatorTestCase', 'PhabricatorEpochEditField' => 'PhabricatorEditField', 'PhabricatorEpochExportField' => 'PhabricatorExportField', 'PhabricatorEvent' => 'PhutilEvent', 'PhabricatorEventEngine' => 'Phobject', 'PhabricatorEventListener' => 'PhutilEventListener', 'PhabricatorEventType' => 'PhutilEventType', 'PhabricatorExampleEventListener' => 'PhabricatorEventListener', 'PhabricatorExcelExportFormat' => 'PhabricatorExportFormat', 'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource', 'PhabricatorExportEngine' => 'Phobject', 'PhabricatorExportEngineBulkJobType' => 'PhabricatorWorkerSingleBulkJobType', 'PhabricatorExportEngineExtension' => 'Phobject', 'PhabricatorExportField' => 'Phobject', 'PhabricatorExportFormat' => 'Phobject', 'PhabricatorExportFormatSetting' => 'PhabricatorInternalSetting', 'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorExtensionsSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorExternalAccount' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorExternalAccountsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorExtraConfigSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorFacebookAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorFact' => 'Phobject', 'PhabricatorFactAggregate' => 'PhabricatorFactDAO', 'PhabricatorFactApplication' => 'PhabricatorApplication', 'PhabricatorFactChartController' => 'PhabricatorFactController', 'PhabricatorFactController' => 'PhabricatorController', 'PhabricatorFactCursor' => 'PhabricatorFactDAO', 'PhabricatorFactDAO' => 'PhabricatorLiskDAO', 'PhabricatorFactDaemon' => 'PhabricatorDaemon', 'PhabricatorFactDatapointQuery' => 'Phobject', 'PhabricatorFactDimension' => 'PhabricatorFactDAO', 'PhabricatorFactEngine' => 'Phobject', 'PhabricatorFactEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorFactHomeController' => 'PhabricatorFactController', 'PhabricatorFactIntDatapoint' => 'PhabricatorFactDAO', 'PhabricatorFactKeyDimension' => 'PhabricatorFactDimension', 'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementListWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorFactObjectController' => 'PhabricatorFactController', 'PhabricatorFactObjectDimension' => 'PhabricatorFactDimension', 'PhabricatorFactRaw' => 'PhabricatorFactDAO', 'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator', 'PhabricatorFaviconRef' => 'Phobject', 'PhabricatorFaviconRefQuery' => 'Phobject', 'PhabricatorFavoritesApplication' => 'PhabricatorApplication', 'PhabricatorFavoritesController' => 'PhabricatorController', 'PhabricatorFavoritesMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorFavoritesMenuItemController' => 'PhabricatorFavoritesController', 'PhabricatorFavoritesProfileMenuEngine' => 'PhabricatorProfileMenuEngine', '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' => array( 'PhabricatorFeedDAO', 'PhabricatorDestructibleInterface', ), 'PhabricatorFeedStoryNotification' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryPublisher' => 'Phobject', 'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO', 'PhabricatorFerretEngine' => 'Phobject', 'PhabricatorFerretEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorFerretFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorFerretFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', 'PhabricatorFerretMetadata' => 'Phobject', 'PhabricatorFerretSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorFile' => array( 'PhabricatorFileDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', 'PhabricatorIndexableInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorFileAES256StorageFormat' => 'PhabricatorFileStorageFormat', 'PhabricatorFileBundleLoader' => 'Phobject', 'PhabricatorFileChunk' => array( 'PhabricatorFileDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorFileChunkIterator' => array( 'Phobject', 'Iterator', ), 'PhabricatorFileChunkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFileComposeController' => 'PhabricatorFileController', 'PhabricatorFileController' => 'PhabricatorController', 'PhabricatorFileDAO' => 'PhabricatorLiskDAO', 'PhabricatorFileDataController' => 'PhabricatorFileController', 'PhabricatorFileDeleteController' => 'PhabricatorFileController', 'PhabricatorFileDeleteTransaction' => 'PhabricatorFileTransactionType', 'PhabricatorFileDocumentController' => 'PhabricatorFileController', 'PhabricatorFileDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine', 'PhabricatorFileDropUploadController' => 'PhabricatorFileController', 'PhabricatorFileEditController' => 'PhabricatorFileController', 'PhabricatorFileEditEngine' => 'PhabricatorEditEngine', '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', 'PhabricatorFileIntegrityException' => 'Exception', 'PhabricatorFileLightboxController' => 'PhabricatorFileController', 'PhabricatorFileLinkView' => 'AphrontTagView', 'PhabricatorFileListController' => 'PhabricatorFileController', 'PhabricatorFileNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorFileNameTransaction' => 'PhabricatorFileTransactionType', 'PhabricatorFileQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFileROT13StorageFormat' => 'PhabricatorFileStorageFormat', 'PhabricatorFileRawStorageFormat' => 'PhabricatorFileStorageFormat', 'PhabricatorFileSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorFileSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorFileSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO', 'PhabricatorFileStorageConfigurationException' => 'Exception', 'PhabricatorFileStorageEngine' => 'Phobject', 'PhabricatorFileStorageEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorFileStorageFormat' => 'Phobject', 'PhabricatorFileStorageFormatTestCase' => 'PhabricatorTestCase', 'PhabricatorFileTemporaryGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorFileTestCase' => 'PhabricatorTestCase', 'PhabricatorFileTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorFileThumbnailTransform' => 'PhabricatorFileImageTransform', 'PhabricatorFileTransaction' => 'PhabricatorModularTransaction', 'PhabricatorFileTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorFileTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorFileTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorFileTransform' => 'Phobject', 'PhabricatorFileTransformController' => 'PhabricatorFileController', 'PhabricatorFileTransformListController' => 'PhabricatorFileController', 'PhabricatorFileTransformTestCase' => 'PhabricatorTestCase', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadDialogController' => 'PhabricatorFileController', 'PhabricatorFileUploadException' => 'Exception', 'PhabricatorFileUploadSource' => 'Phobject', 'PhabricatorFileUploadSourceByteLimitException' => 'Exception', 'PhabricatorFileViewController' => 'PhabricatorFileController', 'PhabricatorFileinfoSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorFilesApplication' => 'PhabricatorApplication', 'PhabricatorFilesApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel', 'PhabricatorFilesBuiltinFile' => 'Phobject', 'PhabricatorFilesComposeAvatarBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesComposeIconBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFilesManagementCatWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCompactWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementCycleWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementEncodeWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementGenerateKeyWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementIntegrityWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementRebuildWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorFilesOnDiskBuiltinFile' => 'PhabricatorFilesBuiltinFile', 'PhabricatorFilesOutboundRequestAction' => 'PhabricatorSystemAction', 'PhabricatorFiletreeVisibleSetting' => 'PhabricatorInternalSetting', 'PhabricatorFiletreeWidthSetting' => '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', 'PhabricatorFulltextInterface' => 'PhabricatorIndexableInterface', 'PhabricatorFulltextResultSet' => 'Phobject', 'PhabricatorFulltextStorageEngine' => 'Phobject', 'PhabricatorFulltextToken' => 'Phobject', 'PhabricatorFundApplication' => 'PhabricatorApplication', 'PhabricatorGDSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorGarbageCollector' => 'Phobject', 'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow', 'PhabricatorGarbageCollectorManagementCompactEdgesWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow', 'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow', 'PhabricatorGarbageCollectorManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorGeneralCachePurger' => 'PhabricatorCachePurger', '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', 'PhabricatorHMACTestCase' => 'PhabricatorTestCase', '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', 'PhabricatorHeraldApplication' => 'PhabricatorApplication', 'PhabricatorHeraldContentSource' => 'PhabricatorContentSource', 'PhabricatorHexdumpDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorHighSecurityRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorHomeApplication' => 'PhabricatorApplication', 'PhabricatorHomeConstants' => 'PhabricatorHomeController', 'PhabricatorHomeController' => 'PhabricatorController', 'PhabricatorHomeLauncherProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorHomeMenuItemController' => 'PhabricatorHomeController', 'PhabricatorHomeProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 'PhabricatorHomeProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorHovercardEngineExtension' => 'Phobject', 'PhabricatorHovercardEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorIDExportField' => 'PhabricatorExportField', 'PhabricatorIDsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorIDsSearchField' => 'PhabricatorSearchField', 'PhabricatorIconDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorIconRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorIconSet' => 'Phobject', 'PhabricatorIconSetEditField' => 'PhabricatorEditField', 'PhabricatorIconSetIcon' => 'Phobject', 'PhabricatorImageDocumentEngine' => 'PhabricatorDocumentEngine', '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', 'PhabricatorIntConfigType' => 'PhabricatorTextConfigType', 'PhabricatorIntEditField' => 'PhabricatorEditField', 'PhabricatorIntExportField' => 'PhabricatorExportField', 'PhabricatorInternalSetting' => 'PhabricatorSetting', 'PhabricatorInternationalizationManagementExtractWorkflow' => 'PhabricatorInternationalizationManagementWorkflow', 'PhabricatorInternationalizationManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorInvalidConfigSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorIteratedMD5PasswordHasher' => 'PhabricatorPasswordHasher', 'PhabricatorIteratedMD5PasswordHasherTestCase' => 'PhabricatorTestCase', 'PhabricatorIteratorFileUploadSource' => 'PhabricatorFileUploadSource', 'PhabricatorJIRAAuthProvider' => 'PhabricatorOAuth1AuthProvider', 'PhabricatorJSONConfigType' => 'PhabricatorTextConfigType', 'PhabricatorJSONDocumentEngine' => 'PhabricatorTextDocumentEngine', 'PhabricatorJSONExportFormat' => 'PhabricatorExportFormat', 'PhabricatorJavelinLinter' => 'ArcanistLinter', 'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorJupyterDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache', 'PhabricatorKeyValueSerializingCacheProxy' => 'PhutilKeyValueCacheProxy', 'PhabricatorKeyboardRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorKeyring' => 'Phobject', 'PhabricatorKeyringConfigOptionType' => 'PhabricatorConfigJSONOptionType', 'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider', 'PhabricatorLabelProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorLanguageSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorLegalpadApplication' => 'PhabricatorApplication', 'PhabricatorLegalpadDocumentPHIDType' => 'PhabricatorPHIDType', 'PhabricatorLegalpadSignaturePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorLibraryTestCase' => 'PhutilLibraryTestCase', 'PhabricatorLinkProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorLipsumArtist' => 'Phobject', 'PhabricatorLipsumContentSource' => 'PhabricatorContentSource', 'PhabricatorLipsumGenerateWorkflow' => 'PhabricatorLipsumManagementWorkflow', 'PhabricatorLipsumManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorLipsumMondrianArtist' => 'PhabricatorLipsumArtist', 'PhabricatorLiskDAO' => 'LiskDAO', 'PhabricatorLiskExportEngineExtension' => 'PhabricatorExportEngineExtension', 'PhabricatorLiskFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorLiskSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorLiskSerializer' => 'Phobject', 'PhabricatorListExportField' => 'PhabricatorExportField', 'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase', 'PhabricatorLocaleScopeGuard' => 'Phobject', 'PhabricatorLocaleScopeGuardTestCase' => 'PhabricatorTestCase', 'PhabricatorLockLogManagementWorkflow' => 'PhabricatorLockManagementWorkflow', 'PhabricatorLockManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorLogTriggerAction' => 'PhabricatorTriggerAction', 'PhabricatorLogoutController' => 'PhabricatorAuthController', 'PhabricatorLunarPhasePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorMacroApplication' => 'PhabricatorApplication', 'PhabricatorMacroAudioBehaviorTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroAudioController' => 'PhabricatorMacroController', 'PhabricatorMacroAudioTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroController' => 'PhabricatorController', 'PhabricatorMacroDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorMacroDisableController' => 'PhabricatorMacroController', 'PhabricatorMacroDisabledTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroEditController' => 'PhameBlogController', 'PhabricatorMacroEditEngine' => 'PhabricatorEditEngine', 'PhabricatorMacroEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorMacroFileTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroListController' => 'PhabricatorMacroController', 'PhabricatorMacroMacroPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMacroMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorMacroManageCapability' => 'PhabricatorPolicyCapability', 'PhabricatorMacroMemeController' => 'PhabricatorMacroController', 'PhabricatorMacroMemeDialogController' => 'PhabricatorMacroController', 'PhabricatorMacroNameTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMacroReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorMacroSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorMacroTestCase' => 'PhabricatorTestCase', 'PhabricatorMacroTransaction' => 'PhabricatorModularTransaction', 'PhabricatorMacroTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorMacroViewController' => 'PhabricatorMacroController', 'PhabricatorMailAdapter' => 'Phobject', 'PhabricatorMailAmazonSESAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailAmazonSNSAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailAttachment' => 'Phobject', 'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase', 'PhabricatorMailEmailEngine' => 'PhabricatorMailMessageEngine', 'PhabricatorMailEmailHeraldField' => 'HeraldField', 'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorMailEmailMessage' => 'PhabricatorMailExternalMessage', 'PhabricatorMailEmailSubjectHeraldField' => 'PhabricatorMailEmailHeraldField', 'PhabricatorMailEngineExtension' => 'Phobject', 'PhabricatorMailExternalMessage' => 'Phobject', 'PhabricatorMailHeader' => 'Phobject', 'PhabricatorMailMailgunAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementResendWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementSendTestWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorMailMessageEngine' => 'Phobject', 'PhabricatorMailMustEncryptHeraldAction' => 'HeraldAction', 'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter', 'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction', 'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction', 'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction', 'PhabricatorMailOutboundStatus' => 'Phobject', 'PhabricatorMailPostmarkAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorMailReceiver' => 'Phobject', 'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase', 'PhabricatorMailReplyHandler' => 'Phobject', 'PhabricatorMailRoutingRule' => 'Phobject', 'PhabricatorMailSMSEngine' => 'PhabricatorMailMessageEngine', 'PhabricatorMailSMSMessage' => 'PhabricatorMailExternalMessage', 'PhabricatorMailSMTPAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailSendGridAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailSendmailAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorMailStamp' => 'Phobject', 'PhabricatorMailTarget' => 'Phobject', 'PhabricatorMailTestAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailTwilioAdapter' => 'PhabricatorMailAdapter', 'PhabricatorMailUtil' => 'Phobject', 'PhabricatorMainMenuBarExtension' => 'Phobject', 'PhabricatorMainMenuSearchView' => 'AphrontView', 'PhabricatorMainMenuView' => 'AphrontView', 'PhabricatorManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorManiphestApplication' => 'PhabricatorApplication', 'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorManiphestTaskFactEngine' => 'PhabricatorTransactionFactEngine', 'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorManualActivitySetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorMarkupCache' => 'PhabricatorCacheDAO', 'PhabricatorMarkupEngine' => 'Phobject', 'PhabricatorMarkupEngineTestCase' => 'PhabricatorTestCase', 'PhabricatorMarkupOneOff' => array( 'Phobject', 'PhabricatorMarkupInterface', ), 'PhabricatorMarkupPreviewController' => 'PhabricatorController', 'PhabricatorMemeEngine' => 'Phobject', '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', 'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMetaMTAController' => 'PhabricatorController', 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', 'PhabricatorMetaMTAEmailBodyParser' => 'Phobject', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAEmailHeraldAction' => 'HeraldAction', 'PhabricatorMetaMTAEmailOthersHeraldAction' => 'PhabricatorMetaMTAEmailHeraldAction', 'PhabricatorMetaMTAEmailSelfHeraldAction' => 'PhabricatorMetaMTAEmailHeraldAction', 'PhabricatorMetaMTAErrorMailAction' => 'PhabricatorSystemAction', 'PhabricatorMetaMTAMail' => array( 'PhabricatorMetaMTADAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorMetaMTAMailBody' => 'Phobject', 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'PhabricatorEdgeType', 'PhabricatorMetaMTAMailListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMetaMTAMailProperties' => array( 'PhabricatorMetaMTADAO', 'PhabricatorPolicyInterface', ), 'PhabricatorMetaMTAMailPropertiesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMetaMTAMailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMetaMTAMailSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorMetaMTAMailSection' => 'Phobject', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailViewController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailableDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorMetaMTAMailableFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery', 'PhabricatorMetaMTAPermanentFailureException' => 'Exception', 'PhabricatorMetaMTAPostmarkReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception', 'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTASchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAWorker' => 'PhabricatorWorker', + 'PhabricatorMetronome' => 'Phobject', + 'PhabricatorMetronomeTestCase' => 'PhabricatorTestCase', 'PhabricatorMetronomicTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorModularTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorModularTransactionType' => 'Phobject', 'PhabricatorMonogramDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension', 'PhabricatorMonospacedFontSetting' => 'PhabricatorStringSetting', 'PhabricatorMonospacedTextareasSetting' => 'PhabricatorSelectSetting', 'PhabricatorMotivatorProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorMultiColumnUIExample' => 'PhabricatorUIExample', 'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorMultimeterApplication' => 'PhabricatorApplication', 'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController', 'PhabricatorMutedByEdgeType' => 'PhabricatorEdgeType', 'PhabricatorMutedEdgeType' => 'PhabricatorEdgeType', 'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorMySQLSearchHost' => 'PhabricatorSearchHost', 'PhabricatorMySQLSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorNamedQuery' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorNamedQueryConfig' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorNamedQueryConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorNamedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorNavigationRemarkupRule' => 'PhutilRemarkupRule', 'PhabricatorNeverTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorNgramsIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'PhabricatorNgramsInterface' => 'PhabricatorIndexableInterface', 'PhabricatorNotificationBuilder' => 'Phobject', 'PhabricatorNotificationClearController' => 'PhabricatorNotificationController', 'PhabricatorNotificationClient' => 'Phobject', 'PhabricatorNotificationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorNotificationController' => 'PhabricatorController', 'PhabricatorNotificationDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorNotificationIndividualController' => 'PhabricatorNotificationController', 'PhabricatorNotificationListController' => 'PhabricatorNotificationController', 'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController', 'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorNotificationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorNotificationServerRef' => 'Phobject', 'PhabricatorNotificationServersConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorNotificationStatusView' => 'AphrontTagView', 'PhabricatorNotificationTestController' => 'PhabricatorNotificationController', 'PhabricatorNotificationUIExample' => 'PhabricatorUIExample', 'PhabricatorNotificationsApplication' => 'PhabricatorApplication', 'PhabricatorNotificationsSetting' => 'PhabricatorInternalSetting', 'PhabricatorNotificationsSettingsPanel' => 'PhabricatorSettingsPanel', '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', 'PhabricatorObjectHasDraftEdgeType' => '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', 'PhabricatorObjectStatus' => 'Phobject', 'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery', 'PhabricatorOldWorldContentSource' => 'PhabricatorContentSource', 'PhabricatorOlderInlinesSetting' => 'PhabricatorSelectSetting', 'PhabricatorOneTimeTriggerClock' => 'PhabricatorTriggerClock', 'PhabricatorOpcodeCacheSpec' => 'PhabricatorCacheSpec', 'PhabricatorOptionGroupSetting' => 'PhabricatorSetting', 'PhabricatorOwnerPathQuery' => 'Phobject', 'PhabricatorOwnersApplication' => 'PhabricatorApplication', 'PhabricatorOwnersArchiveController' => 'PhabricatorOwnersController', + 'PhabricatorOwnersAuditRule' => 'Phobject', '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', 'PhabricatorOwnersHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PhabricatorOwnersListController' => 'PhabricatorOwnersController', 'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPackage' => array( 'PhabricatorOwnersDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'PhabricatorNgramsInterface', ), 'PhabricatorOwnersPackageAuditingTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageAutoreviewTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorOwnersPackageDescriptionTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageDominionTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageEditEngine' => 'PhabricatorEditEngine', 'PhabricatorOwnersPackageFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorOwnersPackageFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorOwnersPackageFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorOwnersPackageIgnoredTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorOwnersPackageNameTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorOwnersPackageOwnersTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackagePHIDType' => 'PhabricatorPHIDType', 'PhabricatorOwnersPackagePathsTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackagePrimaryTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorOwnersPackageRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorOwnersPackageSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorOwnersPackageStatusTransaction' => 'PhabricatorOwnersPackageTransactionType', 'PhabricatorOwnersPackageTestCase' => 'PhabricatorTestCase', 'PhabricatorOwnersPackageTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorOwnersPackageTransaction' => 'PhabricatorModularTransaction', 'PhabricatorOwnersPackageTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorOwnersPackageTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorOwnersPackageTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPathContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorOwnersPathsController' => 'PhabricatorOwnersController', 'PhabricatorOwnersPathsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorOwnersSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorOwnersSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorPDFDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPHID' => 'Phobject', 'PhabricatorPHIDConstants' => 'Phobject', 'PhabricatorPHIDExportField' => 'PhabricatorExportField', 'PhabricatorPHIDListEditField' => 'PhabricatorEditField', 'PhabricatorPHIDListEditType' => 'PhabricatorEditType', 'PhabricatorPHIDListExportField' => 'PhabricatorListExportField', 'PhabricatorPHIDMailStamp' => 'PhabricatorMailStamp', 'PhabricatorPHIDResolver' => 'Phobject', 'PhabricatorPHIDType' => 'Phobject', 'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase', 'PhabricatorPHIDsSearchField' => 'PhabricatorSearchField', 'PhabricatorPHPASTApplication' => 'PhabricatorApplication', 'PhabricatorPHPConfigSetupCheck' => 'PhabricatorSetupCheck', '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', 'PhabricatorPasswordDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', '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', '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', 'PhabricatorPeopleAvailabilitySearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorPeopleBadgesProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleCommitsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleCreateController' => 'PhabricatorPeopleController', 'PhabricatorPeopleCreateGuidanceContext' => 'PhabricatorGuidanceContext', 'PhabricatorPeopleDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension', 'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController', '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', 'PhabricatorPeopleMailEngine' => 'Phobject', 'PhabricatorPeopleMailEngineException' => 'Exception', 'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorPeopleNewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeoplePictureProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleProfileBadgesController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileCommitsController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileImageWorkflow' => 'PhabricatorPeopleManagementWorkflow', 'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileRevisionsController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileTasksController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', 'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPeopleTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPeopleUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeopleUserPHIDType' => 'PhabricatorPHIDType', + 'PhabricatorPeopleUsernameMailEngine' => 'PhabricatorPeopleMailEngine', 'PhabricatorPeopleWelcomeController' => 'PhabricatorPeopleController', 'PhabricatorPeopleWelcomeMailEngine' => 'PhabricatorPeopleMailEngine', 'PhabricatorPhabricatorAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorPhameApplication' => 'PhabricatorApplication', 'PhabricatorPhameBlogPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhamePostPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhluxApplication' => 'PhabricatorApplication', 'PhabricatorPholioApplication' => 'PhabricatorApplication', 'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPhoneNumber' => 'Phobject', 'PhabricatorPhoneNumberTestCase' => 'PhabricatorTestCase', 'PhabricatorPhortuneApplication' => 'PhabricatorApplication', 'PhabricatorPhortuneContentSource' => 'PhabricatorContentSource', 'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow', 'PhabricatorPhortuneManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorPhortuneTestCase' => 'PhabricatorTestCase', 'PhabricatorPhragmentApplication' => 'PhabricatorApplication', 'PhabricatorPhrequentApplication' => 'PhabricatorApplication', 'PhabricatorPhrictionApplication' => 'PhabricatorApplication', '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', 'PhabricatorPhurlURLAliasTransaction' => 'PhabricatorPhurlURLTransactionType', 'PhabricatorPhurlURLCreateCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPhurlURLDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPhurlURLDescriptionTransaction' => 'PhabricatorPhurlURLTransactionType', 'PhabricatorPhurlURLEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhabricatorPhurlURLEditController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLEditEngine' => 'PhabricatorEditEngine', 'PhabricatorPhurlURLEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorPhurlURLListController' => 'PhabricatorPhurlController', 'PhabricatorPhurlURLLongURLTransaction' => 'PhabricatorPhurlURLTransactionType', 'PhabricatorPhurlURLMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorPhurlURLNameNgrams' => 'PhabricatorSearchNgrams', 'PhabricatorPhurlURLNameTransaction' => 'PhabricatorPhurlURLTransactionType', 'PhabricatorPhurlURLPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhurlURLQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPhurlURLReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorPhurlURLSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhabricatorPhurlURLSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPhurlURLTransaction' => 'PhabricatorModularTransaction', 'PhabricatorPhurlURLTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorPhurlURLTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorPhurlURLTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorPhurlURLViewController' => 'PhabricatorPhurlController', 'PhabricatorPinnedApplicationsSetting' => 'PhabricatorInternalSetting', 'PhabricatorPirateEnglishTranslation' => 'PhutilTranslation', 'PhabricatorPlatformSite' => 'PhabricatorSite', 'PhabricatorPointsEditField' => 'PhabricatorEditField', 'PhabricatorPointsFact' => 'PhabricatorFact', 'PhabricatorPolicies' => 'PhabricatorPolicyConstants', 'PhabricatorPolicy' => array( 'PhabricatorPolicyDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorPolicyApplication' => 'PhabricatorApplication', 'PhabricatorPolicyAwareQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorPolicyAwareTestQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorPolicyCanEditCapability' => 'PhabricatorPolicyCapability', 'PhabricatorPolicyCanInteractCapability' => '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', 'PhabricatorPolicyStrengthConstants' => 'PhabricatorPolicyConstants', 'PhabricatorPolicyTestCase' => 'PhabricatorTestCase', 'PhabricatorPolicyTestObject' => array( 'Phobject', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', ), 'PhabricatorPolicyType' => 'PhabricatorPolicyConstants', 'PhabricatorPonderApplication' => 'PhabricatorApplication', 'PhabricatorProfileMenuEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProfileMenuEngine' => 'Phobject', 'PhabricatorProfileMenuItem' => 'Phobject', 'PhabricatorProfileMenuItemConfiguration' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorProfileMenuItemConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProfileMenuItemConfigurationTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorProfileMenuItemConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProfileMenuItemIconSet' => 'PhabricatorIconSet', 'PhabricatorProfileMenuItemPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProject' => array( 'PhabricatorProjectDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFlaggableInterface', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'PhabricatorConduitResultInterface', 'PhabricatorColumnProxyInterface', 'PhabricatorSpacesInterface', 'PhabricatorEditEngineSubtypeInterface', ), 'PhabricatorProjectAddHeraldAction' => 'PhabricatorProjectHeraldAction', 'PhabricatorProjectApplication' => 'PhabricatorApplication', 'PhabricatorProjectArchiveController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardBackgroundController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardController' => 'PhabricatorProjectController', 'PhabricatorProjectBoardDisableController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardImportController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardManageController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBuiltinsExample' => 'PhabricatorUIExample', 'PhabricatorProjectCardView' => 'AphrontTagView', 'PhabricatorProjectColorTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectColorsConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorProjectColumn' => array( 'PhabricatorProjectDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorExtendedPolicyInterface', 'PhabricatorConduitResultInterface', ), 'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectColumnHideController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectColumnPHIDType' => 'PhabricatorPHIDType', 'PhabricatorProjectColumnPosition' => array( 'PhabricatorProjectDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorProjectColumnPositionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectColumnQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectColumnSearchEngine' => 'PhabricatorApplicationSearchEngine', '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', 'PhabricatorProjectDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectEditController' => 'PhabricatorProjectController', 'PhabricatorProjectEditEngine' => 'PhabricatorEditEngine', 'PhabricatorProjectEditPictureController' => 'PhabricatorProjectController', 'PhabricatorProjectFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorProjectFilterTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorProjectHeraldAction' => 'HeraldAction', 'PhabricatorProjectHeraldAdapter' => 'HeraldAdapter', 'PhabricatorProjectHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorProjectHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PhabricatorProjectIconSet' => 'PhabricatorIconSet', 'PhabricatorProjectIconTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectIconsConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorProjectImageTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListView' => 'AphrontView', 'PhabricatorProjectLockController' => 'PhabricatorProjectController', 'PhabricatorProjectLockTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectLogicalAncestorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalOnlyDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectLogicalOrNotDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectLogicalViewerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectManageController' => 'PhabricatorProjectController', 'PhabricatorProjectManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectMaterializedMemberEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMemberListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectMembersAddController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectMembersProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersViewController' => 'PhabricatorProjectController', 'PhabricatorProjectMenuItemController' => 'PhabricatorProjectController', 'PhabricatorProjectMilestoneTransaction' => 'PhabricatorProjectTypeTransaction', 'PhabricatorProjectMoveController' => 'PhabricatorProjectController', 'PhabricatorProjectNameContextFreeGrammar' => 'PhutilContextFreeGrammar', 'PhabricatorProjectNameTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectNoProjectsDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectObjectHasProjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorProjectOrUserDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectOrUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorProjectParentTransaction' => 'PhabricatorProjectTypeTransaction', 'PhabricatorProjectPictureProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectPointsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', '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', 'PhabricatorProjectSlugsTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectSortTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectStandardCustomField' => array( 'PhabricatorProjectCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorProjectStatus' => 'Phobject', 'PhabricatorProjectStatusTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectSubprojectWarningController' => 'PhabricatorProjectController', 'PhabricatorProjectSubprojectsController' => 'PhabricatorProjectController', 'PhabricatorProjectSubprojectsProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectSubtypeDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorProjectSubtypesConfigType' => 'PhabricatorJSONConfigType', 'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorProjectTransaction' => 'PhabricatorModularTransaction', 'PhabricatorProjectTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProjectTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorProjectTypeTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectUIEventListener' => 'PhabricatorEventListener', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorProjectUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorProjectUserListView' => 'AphrontView', 'PhabricatorProjectViewController' => 'PhabricatorProjectController', 'PhabricatorProjectWatchController' => 'PhabricatorProjectController', 'PhabricatorProjectWatcherListView' => 'PhabricatorProjectUserListView', 'PhabricatorProjectWorkboardBackgroundColor' => 'Phobject', 'PhabricatorProjectWorkboardBackgroundTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectWorkboardTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectsAllPolicyRule' => 'PhabricatorProjectsBasePolicyRule', 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsBasePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorProjectsExportEngineExtension' => 'PhabricatorExportEngineExtension', 'PhabricatorProjectsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorProjectsMailEngineExtension' => 'PhabricatorMailEngineExtension', 'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 'PhabricatorProjectsPolicyRule' => 'PhabricatorProjectsBasePolicyRule', 'PhabricatorProjectsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorProjectsWatchersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorPronounSetting' => 'PhabricatorSelectSetting', 'PhabricatorPygmentSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorQuery' => 'Phobject', 'PhabricatorQueryConstraint' => 'Phobject', 'PhabricatorQueryIterator' => 'PhutilBufferedIterator', 'PhabricatorQueryOrderItem' => 'Phobject', 'PhabricatorQueryOrderTestCase' => 'PhabricatorTestCase', 'PhabricatorQueryOrderVector' => array( 'Phobject', 'Iterator', ), 'PhabricatorQuickSearchEngineExtension' => 'PhabricatorDatasourceEngineExtension', 'PhabricatorRateLimitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRedirectController' => 'PhabricatorController', 'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController', 'PhabricatorRegexListConfigType' => 'PhabricatorTextListConfigType', 'PhabricatorRegistrationProfile' => 'Phobject', 'PhabricatorReleephApplication' => 'PhabricatorApplication', 'PhabricatorReleephApplicationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRemarkupCachePurger' => 'PhabricatorCachePurger', 'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl', 'PhabricatorRemarkupCowsayBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 'PhabricatorRemarkupCustomBlockRule' => 'PhutilRemarkupBlockRule', 'PhabricatorRemarkupCustomInlineRule' => 'PhutilRemarkupRule', 'PhabricatorRemarkupDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorRemarkupEditField' => 'PhabricatorEditField', 'PhabricatorRemarkupFigletBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 'PhabricatorRemarkupUIExample' => 'PhabricatorUIExample', 'PhabricatorRepositoriesSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorRepository' => array( 'PhabricatorRepositoryDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorMarkupInterface', 'PhabricatorDestructibleInterface', 'PhabricatorDestructibleCodexInterface', 'PhabricatorProjectInterface', 'PhabricatorSpacesInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', ), 'PhabricatorRepositoryActivateTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryAuditRequest' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryAutocloseOnlyTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryAutocloseTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryBlueprintsTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCallsignTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryCommit' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorProjectInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorSubscribableInterface', 'PhabricatorMentionableInterface', 'HarbormasterBuildableInterface', 'HarbormasterCircleCIBuildableInterface', 'HarbormasterBuildkiteBuildableInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTimelineInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'PhabricatorConduitResultInterface', 'PhabricatorDraftInterface', ), 'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitHint' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryCommitRef' => 'Phobject', 'PhabricatorRepositoryCommitTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRepositoryCopyTimeLimitTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorRepositoryDangerousTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryDefaultBranchTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryDescriptionTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryDestructibleCodex' => 'PhabricatorDestructibleCodex', 'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorRepositoryEncodingTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryEngine' => 'Phobject', 'PhabricatorRepositoryEnormousTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorRepositoryFilesizeLimitTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryGitLFSRef' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorRepositoryGitLFSRefQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryGraphCache' => 'Phobject', 'PhabricatorRepositoryGraphStream' => 'Phobject', 'PhabricatorRepositoryIdentity' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorRepositoryIdentityAssignTransaction' => 'PhabricatorRepositoryIdentityTransactionType', 'PhabricatorRepositoryIdentityChangeWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryIdentityEditEngine' => 'PhabricatorEditEngine', 'PhabricatorRepositoryIdentityFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorRepositoryIdentityPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryIdentityQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryIdentityTransaction' => 'PhabricatorModularTransaction', 'PhabricatorRepositoryIdentityTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorRepositoryIdentityTransactionType' => 'PhabricatorModularTransactionType', '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', 'PhabricatorRepositoryManagementRebuildIdentitiesWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementRefsWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementReparseWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementThawWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementUnpublishWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementUpdateWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryMirror' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryMirrorEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryNameTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryNotifyTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryOldRef' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryParsedChange' => 'Phobject', 'PhabricatorRepositoryPullEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryPullEvent' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryPullEventPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPullEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorDaemon', 'PhabricatorRepositoryPullLocalDaemonModule' => 'PhutilDaemonOverseerModule', 'PhabricatorRepositoryPushEvent' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryPushEventPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPushEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPushLog' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryPushLogPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryPushLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryPushLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorRepositoryPushMailWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryPushPolicyTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryPushReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryRefCursor' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryRefCursorPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryRefCursorQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryRefEngine' => 'PhabricatorRepositoryEngine', 'PhabricatorRepositoryRefPosition' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryRepositoryPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositorySVNSubpathTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositorySchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorRepositoryServiceTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositorySlugTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryStagingURITransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryStatusMessage' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySymbolLanguagesTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositorySymbolSourcesTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositorySyncEvent' => array( 'PhabricatorRepositoryDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorRepositorySyncEventPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositorySyncEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryTouchLimitTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryTrackOnlyTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryTransaction' => 'PhabricatorModularTransaction', 'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorRepositoryTransactionType' => 'PhabricatorModularTransactionType', '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', 'PhabricatorRepositoryVCSTransaction' => 'PhabricatorRepositoryTransactionType', 'PhabricatorRepositoryWorkingCopyVersion' => 'PhabricatorRepositoryDAO', 'PhabricatorRequestExceptionHandler' => 'AphrontRequestExceptionHandler', 'PhabricatorResourceSite' => 'PhabricatorSite', 'PhabricatorRobotsController' => 'PhabricatorController', 'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorSMSAuthFactor' => 'PhabricatorAuthFactor', 'PhabricatorSQLPatchList' => 'Phobject', 'PhabricatorSSHKeyGenerator' => 'Phobject', 'PhabricatorSSHKeysSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorSSHLog' => 'Phobject', 'PhabricatorSSHPassthruCommand' => 'Phobject', 'PhabricatorSSHWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorSavedQuery' => array( 'PhabricatorSearchDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorSavedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorScheduleTaskTriggerAction' => 'PhabricatorTriggerAction', 'PhabricatorScopedEnv' => 'Phobject', 'PhabricatorSearchAbstractDocument' => 'Phobject', 'PhabricatorSearchApplication' => 'PhabricatorApplication', 'PhabricatorSearchApplicationSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSearchApplicationStorageEnginePanel' => 'PhabricatorApplicationConfigurationPanel', 'PhabricatorSearchBaseController' => 'PhabricatorController', 'PhabricatorSearchCheckboxesField' => 'PhabricatorSearchField', 'PhabricatorSearchConstraintException' => 'Exception', 'PhabricatorSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchCustomFieldProxyField' => 'PhabricatorSearchField', 'PhabricatorSearchDAO' => 'PhabricatorLiskDAO', 'PhabricatorSearchDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorSearchDatasourceField' => 'PhabricatorSearchTokenizerField', 'PhabricatorSearchDateControlField' => 'PhabricatorSearchField', 'PhabricatorSearchDateField' => 'PhabricatorSearchField', 'PhabricatorSearchDefaultController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchDeleteController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchDocument' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentFieldType' => 'Phobject', 'PhabricatorSearchDocumentQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentTypeDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorSearchEditController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchEngineAPIMethod' => 'ConduitAPIMethod', 'PhabricatorSearchEngineAttachment' => 'Phobject', 'PhabricatorSearchEngineExtension' => 'Phobject', 'PhabricatorSearchEngineExtensionModule' => 'PhabricatorConfigModule', 'PhabricatorSearchFerretNgramGarbageCollector' => 'PhabricatorGarbageCollector', 'PhabricatorSearchField' => 'Phobject', 'PhabricatorSearchHost' => 'Phobject', 'PhabricatorSearchHovercardController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchIndexVersion' => 'PhabricatorSearchDAO', 'PhabricatorSearchIndexVersionDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorSearchManagementIndexWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorSearchManagementInitWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorSearchManagementNgramsWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorSearchManagementQueryWorkflow' => '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', 'PhabricatorSearchService' => 'Phobject', 'PhabricatorSearchStringListField' => 'PhabricatorSearchField', 'PhabricatorSearchSubscribersField' => 'PhabricatorSearchTokenizerField', 'PhabricatorSearchTextField' => 'PhabricatorSearchField', 'PhabricatorSearchThreeStateField' => 'PhabricatorSearchField', 'PhabricatorSearchTokenizerField' => 'PhabricatorSearchField', 'PhabricatorSearchWorker' => 'PhabricatorWorker', 'PhabricatorSecurityConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSecuritySetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorSelectEditField' => 'PhabricatorEditField', 'PhabricatorSelectSetting' => 'PhabricatorSetting', 'PhabricatorSessionsSettingsPanel' => 'PhabricatorSettingsPanel', 'PhabricatorSetConfigType' => 'PhabricatorTextConfigType', 'PhabricatorSetting' => 'Phobject', 'PhabricatorSettingsAccountPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsAddEmailAction' => 'PhabricatorSystemAction', 'PhabricatorSettingsAdjustController' => 'PhabricatorController', 'PhabricatorSettingsApplication' => 'PhabricatorApplication', 'PhabricatorSettingsApplicationsPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsAuthenticationPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsDeveloperPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsEditEngine' => 'PhabricatorEditEngine', 'PhabricatorSettingsEmailPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsIssueController' => 'PhabricatorController', 'PhabricatorSettingsListController' => 'PhabricatorController', 'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup', 'PhabricatorSettingsMainController' => 'PhabricatorController', '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', 'PhabricatorSlowvoteCloseTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteController' => 'PhabricatorController', 'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO', 'PhabricatorSlowvoteDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PhabricatorSlowvoteDescriptionTransaction' => 'PhabricatorSlowvoteTransactionType', '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', 'PhabricatorSlowvoteQuestionTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorSlowvoteResponsesTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSlowvoteShuffleTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteTransaction' => 'PhabricatorModularTransaction', 'PhabricatorSlowvoteTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorSlowvoteTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorSlowvoteTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorSlowvoteVoteController' => 'PhabricatorSlowvoteController', 'PhabricatorSlug' => 'Phobject', 'PhabricatorSlugTestCase' => 'PhabricatorTestCase', 'PhabricatorSourceCodeView' => 'AphrontView', 'PhabricatorSourceDocumentEngine' => 'PhabricatorTextDocumentEngine', 'PhabricatorSpaceEditField' => 'PhabricatorEditField', 'PhabricatorSpacesApplication' => 'PhabricatorApplication', 'PhabricatorSpacesArchiveController' => 'PhabricatorSpacesController', 'PhabricatorSpacesCapabilityCreateSpaces' => 'PhabricatorPolicyCapability', 'PhabricatorSpacesCapabilityDefaultEdit' => 'PhabricatorPolicyCapability', 'PhabricatorSpacesCapabilityDefaultView' => 'PhabricatorPolicyCapability', 'PhabricatorSpacesController' => 'PhabricatorController', 'PhabricatorSpacesDAO' => 'PhabricatorLiskDAO', 'PhabricatorSpacesEditController' => 'PhabricatorSpacesController', 'PhabricatorSpacesExportEngineExtension' => 'PhabricatorExportEngineExtension', 'PhabricatorSpacesInterface' => 'PhabricatorPHIDInterface', 'PhabricatorSpacesListController' => 'PhabricatorSpacesController', 'PhabricatorSpacesMailEngineExtension' => 'PhabricatorMailEngineExtension', 'PhabricatorSpacesNamespace' => array( 'PhabricatorSpacesDAO', 'PhabricatorPolicyInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), 'PhabricatorSpacesNamespaceArchiveTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespaceDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorSpacesNamespaceDefaultTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespaceDescriptionTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespaceEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorSpacesNamespaceNameTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespacePHIDType' => 'PhabricatorPHIDType', 'PhabricatorSpacesNamespaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorSpacesNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorModularTransaction', 'PhabricatorSpacesNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorSpacesNamespaceTransactionType' => 'PhabricatorModularTransactionType', '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', 'PhabricatorStandardTimelineEngine' => 'PhabricatorTimelineEngine', 'PhabricatorStaticEditField' => 'PhabricatorEditField', 'PhabricatorStatusController' => 'PhabricatorController', 'PhabricatorStatusUIExample' => 'PhabricatorUIExample', 'PhabricatorStorageFixtureScopeGuard' => 'Phobject', 'PhabricatorStorageManagementAPI' => 'Phobject', 'PhabricatorStorageManagementAdjustWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementAnalyzeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementOptimizeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementPartitionWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementProbeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementQuickstartWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementRenamespaceWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementShellWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorStoragePatch' => 'Phobject', 'PhabricatorStorageSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorStorageSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorStringConfigType' => 'PhabricatorTextConfigType', 'PhabricatorStringExportField' => 'PhabricatorExportField', 'PhabricatorStringListConfigType' => 'PhabricatorTextListConfigType', 'PhabricatorStringListEditField' => 'PhabricatorEditField', 'PhabricatorStringListExportField' => 'PhabricatorListExportField', 'PhabricatorStringMailStamp' => 'PhabricatorMailStamp', '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', 'PhabricatorSubscriptionsExportEngineExtension' => 'PhabricatorExportEngineExtension', 'PhabricatorSubscriptionsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension', 'PhabricatorSubscriptionsHeraldAction' => 'HeraldAction', 'PhabricatorSubscriptionsListController' => 'PhabricatorController', 'PhabricatorSubscriptionsMailEngineExtension' => 'PhabricatorMailEngineExtension', 'PhabricatorSubscriptionsMuteController' => 'PhabricatorController', 'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction', 'PhabricatorSubscriptionsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorSubscriptionsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorSubscriptionsSubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorSubscriptionsSubscribersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorSubscriptionsTransactionController' => 'PhabricatorController', 'PhabricatorSubscriptionsUIEventListener' => 'PhabricatorEventListener', 'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand', 'PhabricatorSubtypeEditEngineExtension' => 'PhabricatorEditEngineExtension', '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', 'PhabricatorSystemObjectController' => 'PhabricatorController', 'PhabricatorSystemReadOnlyController' => 'PhabricatorController', 'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow', 'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow', 'PhabricatorSystemRemoveWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorSystemSelectEncodingController' => 'PhabricatorController', 'PhabricatorSystemSelectHighlightController' => 'PhabricatorController', 'PhabricatorTOTPAuthFactor' => 'PhabricatorAuthFactor', 'PhabricatorTOTPAuthFactorTestCase' => 'PhabricatorTestCase', 'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon', 'PhabricatorTaskmasterDaemonModule' => 'PhutilDaemonOverseerModule', 'PhabricatorTestApplication' => 'PhabricatorApplication', 'PhabricatorTestCase' => 'PhutilTestCase', 'PhabricatorTestController' => 'PhabricatorController', 'PhabricatorTestDataGenerator' => 'Phobject', 'PhabricatorTestNoCycleEdgeType' => 'PhabricatorEdgeType', 'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorTestWorker' => 'PhabricatorWorker', 'PhabricatorTextAreaEditField' => 'PhabricatorEditField', 'PhabricatorTextConfigType' => 'PhabricatorConfigType', 'PhabricatorTextDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorTextEditField' => 'PhabricatorEditField', 'PhabricatorTextExportFormat' => 'PhabricatorExportFormat', 'PhabricatorTextListConfigType' => 'PhabricatorTextConfigType', 'PhabricatorTime' => 'Phobject', 'PhabricatorTimeFormatSetting' => 'PhabricatorSelectSetting', 'PhabricatorTimeGuard' => 'Phobject', 'PhabricatorTimeTestCase' => 'PhabricatorTestCase', 'PhabricatorTimelineEngine' => 'Phobject', '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', ), 'PhabricatorTransactionChange' => 'Phobject', 'PhabricatorTransactionFactEngine' => 'PhabricatorFactEngine', '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', 'PhabricatorTwilioFuture' => 'FutureProxy', 'PhabricatorTwitchAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorTwitterAuthProvider' => 'PhabricatorOAuth1AuthProvider', 'PhabricatorTypeaheadApplication' => 'PhabricatorApplication', 'PhabricatorTypeaheadCompositeDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorTypeaheadDatasource' => 'Phobject', 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 'PhabricatorTypeaheadDatasourceTestCase' => 'PhabricatorTestCase', 'PhabricatorTypeaheadFunctionHelpController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadInvalidTokenException' => 'Exception', 'PhabricatorTypeaheadModularDatasourceController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadMonogramDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorTypeaheadProxyDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorTypeaheadResult' => 'Phobject', 'PhabricatorTypeaheadRuntimeCompositeDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorTypeaheadTestNumbersDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorTypeaheadTokenView' => 'AphrontTagView', 'PhabricatorUIConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorUIExample' => 'Phobject', 'PhabricatorUIExampleRenderController' => 'PhabricatorController', 'PhabricatorUIExamplesApplication' => 'PhabricatorApplication', 'PhabricatorURIExportField' => 'PhabricatorExportField', 'PhabricatorUSEnglishTranslation' => 'PhutilTranslation', 'PhabricatorUnifiedDiffsSetting' => 'PhabricatorSelectSetting', 'PhabricatorUnitTestContentSource' => 'PhabricatorContentSource', 'PhabricatorUnitsTestCase' => 'PhabricatorTestCase', 'PhabricatorUnknownContentSource' => 'PhabricatorContentSource', 'PhabricatorUnsubscribedFromObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorUser' => array( 'PhabricatorUserDAO', 'PhutilPerson', 'PhabricatorPolicyInterface', 'PhabricatorCustomFieldInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSSHPublicKeyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'PhabricatorConduitResultInterface', 'PhabricatorAuthPasswordHashInterface', ), 'PhabricatorUserApproveTransaction' => 'PhabricatorUserTransactionType', 'PhabricatorUserBadgesCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField', 'PhabricatorUserCache' => 'PhabricatorUserDAO', 'PhabricatorUserCachePurger' => 'PhabricatorCachePurger', 'PhabricatorUserCacheType' => 'Phobject', 'PhabricatorUserCardView' => 'AphrontTagView', 'PhabricatorUserConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorUserConfiguredCustomField' => array( 'PhabricatorUserCustomField', 'PhabricatorStandardCustomFieldInterface', ), 'PhabricatorUserConfiguredCustomFieldStorage' => 'PhabricatorCustomFieldStorage', 'PhabricatorUserCustomField' => 'PhabricatorCustomField', 'PhabricatorUserCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', 'PhabricatorUserCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 'PhabricatorUserDisableTransaction' => 'PhabricatorUserTransactionType', 'PhabricatorUserEditEngine' => 'PhabricatorEditEngine', 'PhabricatorUserEditor' => 'PhabricatorEditor', 'PhabricatorUserEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorUserEmail' => 'PhabricatorUserDAO', 'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase', 'PhabricatorUserEmpowerTransaction' => 'PhabricatorUserTransactionType', 'PhabricatorUserFerretEngine' => 'PhabricatorFerretEngine', 'PhabricatorUserFulltextEngine' => 'PhabricatorFulltextEngine', 'PhabricatorUserIconField' => 'PhabricatorUserCustomField', 'PhabricatorUserLog' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorUserLogView' => 'AphrontView', 'PhabricatorUserMessageCountCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserNotificationCountCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserNotifyTransaction' => 'PhabricatorUserTransactionType', 'PhabricatorUserPHIDResolver' => 'PhabricatorPHIDResolver', 'PhabricatorUserPreferences' => array( 'PhabricatorUserDAO', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', ), 'PhabricatorUserPreferencesCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserPreferencesEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorUserPreferencesPHIDType' => 'PhabricatorPHIDType', 'PhabricatorUserPreferencesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorUserPreferencesSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorUserPreferencesTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorUserPreferencesTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorUserProfile' => 'PhabricatorUserDAO', 'PhabricatorUserProfileImageCacheType' => 'PhabricatorUserCacheType', 'PhabricatorUserRealNameField' => 'PhabricatorUserCustomField', 'PhabricatorUserRolesField' => 'PhabricatorUserCustomField', 'PhabricatorUserSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorUserSinceField' => 'PhabricatorUserCustomField', 'PhabricatorUserStatusField' => 'PhabricatorUserCustomField', 'PhabricatorUserTestCase' => 'PhabricatorTestCase', 'PhabricatorUserTitleField' => 'PhabricatorUserCustomField', 'PhabricatorUserTransaction' => 'PhabricatorModularTransaction', 'PhabricatorUserTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorUserTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorUserUsernameTransaction' => 'PhabricatorUserTransactionType', 'PhabricatorUsersEditField' => 'PhabricatorTokenizerEditField', 'PhabricatorUsersPolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorUsersSearchField' => 'PhabricatorSearchTokenizerField', 'PhabricatorVCSResponse' => 'AphrontResponse', 'PhabricatorVersionedDraft' => 'PhabricatorDraftDAO', 'PhabricatorVeryWowEnglishTranslation' => 'PhutilTranslation', 'PhabricatorVideoDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorViewerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorVoidDocumentEngine' => 'PhabricatorDocumentEngine', 'PhabricatorWatcherHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorWebContentSource' => 'PhabricatorContentSource', 'PhabricatorWebServerSetupCheck' => 'PhabricatorSetupCheck', 'PhabricatorWeekStartDaySetting' => 'PhabricatorSelectSetting', 'PhabricatorWildConfigType' => 'PhabricatorJSONConfigType', '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', 'PhabricatorWorkerSingleBulkJobType' => 'PhabricatorWorkerBulkJobType', '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', 'PhabricatorXHProfDropController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileView' => 'AphrontView', 'PhabricatorXHProfSample' => array( 'PhabricatorXHProfDAO', 'PhabricatorPolicyInterface', ), 'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController', 'PhabricatorXHProfSampleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorXHProfSampleSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorYoutubeRemarkupRule' => 'PhutilRemarkupRule', 'Phame404Response' => 'AphrontHTMLResponse', 'PhameBlog' => array( 'PhameDAO', 'PhabricatorPolicyInterface', 'PhabricatorMarkupInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorConduitResultInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', ), 'PhameBlog404Controller' => 'PhameLiveController', 'PhameBlogArchiveController' => 'PhameBlogController', 'PhameBlogController' => 'PhameController', 'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability', 'PhameBlogDatasource' => 'PhabricatorTypeaheadDatasource', 'PhameBlogDescriptionTransaction' => 'PhameBlogTransactionType', 'PhameBlogEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhameBlogEditController' => 'PhameBlogController', 'PhameBlogEditEngine' => 'PhabricatorEditEngine', 'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor', 'PhameBlogFeedController' => 'PhameBlogController', 'PhameBlogFerretEngine' => 'PhabricatorFerretEngine', 'PhameBlogFullDomainTransaction' => 'PhameBlogTransactionType', 'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine', 'PhameBlogHeaderImageTransaction' => 'PhameBlogTransactionType', 'PhameBlogHeaderPictureController' => 'PhameBlogController', 'PhameBlogListController' => 'PhameBlogController', 'PhameBlogListView' => 'AphrontTagView', 'PhameBlogManageController' => 'PhameBlogController', 'PhameBlogNameTransaction' => 'PhameBlogTransactionType', 'PhameBlogParentDomainTransaction' => 'PhameBlogTransactionType', 'PhameBlogParentSiteTransaction' => 'PhameBlogTransactionType', 'PhameBlogProfileImageTransaction' => 'PhameBlogTransactionType', 'PhameBlogProfilePictureController' => 'PhameBlogController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhameBlogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhameBlogSite' => 'PhameSite', 'PhameBlogStatusTransaction' => 'PhameBlogTransactionType', 'PhameBlogSubtitleTransaction' => 'PhameBlogTransactionType', 'PhameBlogTransaction' => 'PhabricatorModularTransaction', 'PhameBlogTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhameBlogTransactionType' => 'PhabricatorModularTransactionType', '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', 'PhabricatorFerretInterface', ), 'PhamePostArchiveController' => 'PhamePostController', 'PhamePostBlogTransaction' => 'PhamePostTransactionType', 'PhamePostBodyTransaction' => 'PhamePostTransactionType', 'PhamePostController' => 'PhameController', 'PhamePostEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhamePostEditController' => 'PhamePostController', 'PhamePostEditEngine' => 'PhabricatorEditEngine', 'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor', 'PhamePostFerretEngine' => 'PhabricatorFerretEngine', 'PhamePostFulltextEngine' => 'PhabricatorFulltextEngine', 'PhamePostHeaderImageTransaction' => 'PhamePostTransactionType', 'PhamePostHeaderPictureController' => 'PhamePostController', 'PhamePostHistoryController' => 'PhamePostController', 'PhamePostListController' => 'PhamePostController', 'PhamePostListView' => 'AphrontTagView', 'PhamePostMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhamePostMoveController' => 'PhamePostController', 'PhamePostPublishController' => 'PhamePostController', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhamePostRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhamePostSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhamePostSubtitleTransaction' => 'PhamePostTransactionType', 'PhamePostTitleTransaction' => 'PhamePostTransactionType', 'PhamePostTransaction' => 'PhabricatorModularTransaction', 'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhamePostTransactionType' => 'PhabricatorModularTransactionType', 'PhamePostViewController' => 'PhameLiveController', 'PhamePostVisibilityTransaction' => 'PhamePostTransactionType', 'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhameSite' => 'PhabricatorSite', 'PhluxController' => 'PhabricatorController', 'PhluxDAO' => 'PhabricatorLiskDAO', 'PhluxEditController' => 'PhluxController', 'PhluxListController' => 'PhluxController', 'PhluxSchemaSpec' => 'PhabricatorConfigSchemaSpec', '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', 'PhabricatorPolicyInterface', 'PhabricatorExtendedPolicyInterface', ), 'PholioImageDescriptionTransaction' => 'PholioImageTransactionType', 'PholioImageFileTransaction' => 'PholioImageTransactionType', 'PholioImageNameTransaction' => 'PholioImageTransactionType', 'PholioImagePHIDType' => 'PhabricatorPHIDType', 'PholioImageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PholioImageReplaceTransaction' => 'PholioImageTransactionType', 'PholioImageSequenceTransaction' => 'PholioImageTransactionType', 'PholioImageTransactionType' => 'PholioTransactionType', 'PholioImageUploadController' => 'PholioController', 'PholioInlineController' => 'PholioController', 'PholioInlineListController' => 'PholioController', 'PholioMock' => array( 'PholioDAO', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorFlaggableInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorTimelineInterface', 'PhabricatorProjectInterface', 'PhabricatorDestructibleInterface', 'PhabricatorSpacesInterface', 'PhabricatorMentionableInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', ), 'PholioMockArchiveController' => 'PholioController', 'PholioMockAuthorHeraldField' => 'PholioMockHeraldField', 'PholioMockCommentController' => 'PholioController', 'PholioMockDescriptionHeraldField' => 'PholioMockHeraldField', 'PholioMockDescriptionTransaction' => 'PholioMockTransactionType', 'PholioMockEditController' => 'PholioController', 'PholioMockEditor' => 'PhabricatorApplicationTransactionEditor', 'PholioMockEmbedView' => 'AphrontView', 'PholioMockFerretEngine' => 'PhabricatorFerretEngine', 'PholioMockFulltextEngine' => 'PhabricatorFulltextEngine', 'PholioMockHasTaskEdgeType' => 'PhabricatorEdgeType', 'PholioMockHasTaskRelationship' => 'PholioMockRelationship', 'PholioMockHeraldField' => 'HeraldField', 'PholioMockHeraldFieldGroup' => 'HeraldFieldGroup', 'PholioMockImagesView' => 'AphrontView', 'PholioMockInlineTransaction' => 'PholioMockTransactionType', 'PholioMockListController' => 'PholioController', 'PholioMockMailReceiver' => 'PhabricatorObjectMailReceiver', 'PholioMockNameHeraldField' => 'PholioMockHeraldField', 'PholioMockNameTransaction' => 'PholioMockTransactionType', 'PholioMockPHIDType' => 'PhabricatorPHIDType', 'PholioMockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PholioMockRelationship' => 'PhabricatorObjectRelationship', 'PholioMockRelationshipSource' => 'PhabricatorObjectRelationshipSource', 'PholioMockSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PholioMockStatusTransaction' => 'PholioMockTransactionType', 'PholioMockThumbGridView' => 'AphrontView', 'PholioMockTimelineEngine' => 'PhabricatorTimelineEngine', 'PholioMockTransactionType' => 'PholioTransactionType', 'PholioMockViewController' => 'PholioController', 'PholioRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PholioReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PholioSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PholioTransaction' => 'PhabricatorModularTransaction', 'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PholioTransactionType' => 'PhabricatorModularTransactionType', 'PholioTransactionView' => 'PhabricatorApplicationTransactionView', 'PholioUploadedImageView' => 'AphrontView', 'PhortuneAccount' => array( 'PhortuneDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhortuneAccountAddManagerController' => 'PhortuneController', 'PhortuneAccountBillingAddressTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountBillingController' => 'PhortuneAccountProfileController', 'PhortuneAccountBillingNameTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountChargeListController' => 'PhortuneController', 'PhortuneAccountController' => 'PhortuneController', 'PhortuneAccountEditController' => 'PhortuneController', 'PhortuneAccountEditEngine' => 'PhabricatorEditEngine', 'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortuneAccountHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhortuneAccountListController' => 'PhortuneController', 'PhortuneAccountManagerController' => 'PhortuneAccountProfileController', 'PhortuneAccountNameTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountPHIDType' => 'PhabricatorPHIDType', 'PhortuneAccountProfileController' => 'PhortuneAccountController', 'PhortuneAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneAccountSubscriptionController' => 'PhortuneAccountProfileController', 'PhortuneAccountTransaction' => 'PhabricatorModularTransaction', 'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhortuneAccountTransactionType' => 'PhabricatorModularTransactionType', 'PhortuneAccountViewController' => 'PhortuneAccountProfileController', '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', ), 'PhortuneChargePHIDType' => 'PhabricatorPHIDType', 'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneChargeTableView' => 'AphrontView', 'PhortuneConstants' => 'Phobject', 'PhortuneController' => 'PhabricatorController', 'PhortuneCreditCardForm' => 'Phobject', 'PhortuneCurrency' => 'Phobject', 'PhortuneCurrencySerializer' => 'PhabricatorLiskSerializer', 'PhortuneCurrencyTestCase' => 'PhabricatorTestCase', 'PhortuneDAO' => 'PhabricatorLiskDAO', + 'PhortuneDisplayException' => 'Exception', 'PhortuneErrCode' => 'PhortuneConstants', 'PhortuneInvoiceView' => 'AphrontTagView', 'PhortuneLandingController' => 'PhortuneController', 'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType', 'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType', 'PhortuneMerchant' => array( 'PhortuneDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorPolicyInterface', ), 'PhortuneMerchantAddManagerController' => 'PhortuneController', 'PhortuneMerchantCapability' => 'PhabricatorPolicyCapability', 'PhortuneMerchantContactInfoTransaction' => 'PhortuneMerchantTransactionType', 'PhortuneMerchantController' => 'PhortuneController', 'PhortuneMerchantDescriptionTransaction' => 'PhortuneMerchantTransactionType', 'PhortuneMerchantEditController' => 'PhortuneMerchantController', 'PhortuneMerchantEditEngine' => 'PhabricatorEditEngine', 'PhortuneMerchantEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortuneMerchantHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhortuneMerchantInvoiceCreateController' => 'PhortuneMerchantProfileController', 'PhortuneMerchantInvoiceEmailTransaction' => 'PhortuneMerchantTransactionType', 'PhortuneMerchantInvoiceFooterTransaction' => 'PhortuneMerchantTransactionType', 'PhortuneMerchantListController' => 'PhortuneMerchantController', 'PhortuneMerchantManagerController' => 'PhortuneMerchantProfileController', 'PhortuneMerchantNameTransaction' => 'PhortuneMerchantTransactionType', 'PhortuneMerchantPHIDType' => 'PhabricatorPHIDType', 'PhortuneMerchantPictureController' => 'PhortuneMerchantProfileController', 'PhortuneMerchantPictureTransaction' => 'PhortuneMerchantTransactionType', 'PhortuneMerchantProfileController' => 'PhortuneController', 'PhortuneMerchantQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneMerchantSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneMerchantTransaction' => 'PhabricatorModularTransaction', 'PhortuneMerchantTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhortuneMerchantTransactionType' => 'PhabricatorModularTransactionType', 'PhortuneMerchantViewController' => 'PhortuneMerchantProfileController', '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', 'PhabricatorPolicyInterface', 'PhabricatorDestructibleInterface', 'PhabricatorConduitResultInterface', ), 'PhrictionContentPHIDType' => 'PhabricatorPHIDType', 'PhrictionContentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhrictionContentSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhrictionContentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhrictionContentSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhrictionController' => 'PhabricatorController', 'PhrictionCreateConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionDAO' => 'PhabricatorLiskDAO', 'PhrictionDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension', 'PhrictionDeleteController' => 'PhrictionController', 'PhrictionDiffController' => 'PhrictionController', 'PhrictionDocument' => array( 'PhrictionDAO', 'PhabricatorPolicyInterface', 'PhabricatorSubscribableInterface', 'PhabricatorFlaggableInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorDestructibleInterface', 'PhabricatorFulltextInterface', 'PhabricatorFerretInterface', 'PhabricatorProjectInterface', 'PhabricatorApplicationTransactionInterface', 'PhabricatorConduitResultInterface', 'PhabricatorPolicyCodexInterface', 'PhabricatorSpacesInterface', ), 'PhrictionDocumentAuthorHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentContentHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentContentTransaction' => 'PhrictionDocumentEditTransaction', 'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentDatasource' => 'PhabricatorTypeaheadDatasource', 'PhrictionDocumentDeleteTransaction' => 'PhrictionDocumentVersionTransaction', 'PhrictionDocumentDraftTransaction' => 'PhrictionDocumentEditTransaction', 'PhrictionDocumentEditEngine' => 'PhabricatorEditEngine', 'PhrictionDocumentEditTransaction' => 'PhrictionDocumentVersionTransaction', 'PhrictionDocumentFerretEngine' => 'PhabricatorFerretEngine', 'PhrictionDocumentFulltextEngine' => 'PhabricatorFulltextEngine', 'PhrictionDocumentHeraldAdapter' => 'HeraldAdapter', 'PhrictionDocumentHeraldField' => 'HeraldField', 'PhrictionDocumentHeraldFieldGroup' => 'HeraldFieldGroup', 'PhrictionDocumentMoveAwayTransaction' => 'PhrictionDocumentVersionTransaction', 'PhrictionDocumentMoveToTransaction' => 'PhrictionDocumentVersionTransaction', 'PhrictionDocumentPHIDType' => 'PhabricatorPHIDType', 'PhrictionDocumentPathHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentPolicyCodex' => 'PhabricatorPolicyCodex', 'PhrictionDocumentPublishTransaction' => 'PhrictionDocumentTransactionType', 'PhrictionDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhrictionDocumentSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhrictionDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhrictionDocumentStatus' => 'PhabricatorObjectStatus', 'PhrictionDocumentTitleHeraldField' => 'PhrictionDocumentHeraldField', 'PhrictionDocumentTitleTransaction' => 'PhrictionDocumentVersionTransaction', 'PhrictionDocumentTransactionType' => 'PhabricatorModularTransactionType', 'PhrictionDocumentVersionTransaction' => 'PhrictionDocumentTransactionType', 'PhrictionEditConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionEditController' => 'PhrictionController', 'PhrictionEditEngineController' => 'PhrictionController', 'PhrictionHistoryConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionHistoryController' => 'PhrictionController', 'PhrictionInfoConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionListController' => 'PhrictionController', 'PhrictionMarkupPreviewController' => 'PhabricatorController', 'PhrictionMoveController' => 'PhrictionController', 'PhrictionNewController' => 'PhrictionController', 'PhrictionPublishController' => 'PhrictionController', 'PhrictionRemarkupRule' => 'PhutilRemarkupRule', 'PhrictionReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhrictionSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhrictionTransaction' => 'PhabricatorModularTransaction', 'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PolicyLockOptionType' => 'PhabricatorConfigJSONOptionType', 'PonderAddAnswerView' => 'AphrontView', 'PonderAnswer' => array( 'PonderDAO', 'PhabricatorApplicationTransactionInterface', 'PhabricatorMarkupInterface', 'PhabricatorPolicyInterface', 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorDestructibleInterface', ), 'PonderAnswerCommentController' => 'PonderController', 'PonderAnswerContentTransaction' => 'PonderAnswerTransactionType', 'PonderAnswerEditController' => 'PonderController', 'PonderAnswerEditor' => 'PonderEditor', 'PonderAnswerHistoryController' => 'PonderController', 'PonderAnswerMailReceiver' => 'PhabricatorObjectMailReceiver', 'PonderAnswerPHIDType' => 'PhabricatorPHIDType', 'PonderAnswerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PonderAnswerQuestionIDTransaction' => 'PonderAnswerTransactionType', 'PonderAnswerReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PonderAnswerSaveController' => 'PonderController', 'PonderAnswerStatus' => 'PonderConstants', 'PonderAnswerStatusTransaction' => 'PonderAnswerTransactionType', 'PonderAnswerTransaction' => 'PhabricatorModularTransaction', 'PonderAnswerTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderAnswerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PonderAnswerTransactionType' => 'PhabricatorModularTransactionType', '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', 'PhabricatorFerretInterface', ), 'PonderQuestionAnswerTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionAnswerWikiTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionCommentController' => 'PonderController', 'PonderQuestionContentTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', 'PonderQuestionEditController' => 'PonderController', 'PonderQuestionEditEngine' => 'PhabricatorEditEngine', 'PonderQuestionEditor' => 'PonderEditor', 'PonderQuestionFerretEngine' => 'PhabricatorFerretEngine', 'PonderQuestionFulltextEngine' => 'PhabricatorFulltextEngine', 'PonderQuestionHistoryController' => 'PonderController', 'PonderQuestionListController' => 'PonderController', 'PonderQuestionMailReceiver' => 'PhabricatorObjectMailReceiver', 'PonderQuestionPHIDType' => 'PhabricatorPHIDType', 'PonderQuestionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PonderQuestionReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PonderQuestionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PonderQuestionStatus' => 'PonderConstants', 'PonderQuestionStatusController' => 'PonderController', 'PonderQuestionStatusTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionTitleTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionTransaction' => 'PhabricatorModularTransaction', 'PonderQuestionTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderQuestionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PonderQuestionTransactionType' => 'PhabricatorModularTransactionType', 'PonderQuestionViewController' => 'PonderController', 'PonderRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PonderSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'ProjectAddProjectsEmailCommand' => 'MetaMTAEmailTransactionCommand', 'ProjectBoardTaskCard' => 'Phobject', 'ProjectCanLockProjectsCapability' => 'PhabricatorPolicyCapability', 'ProjectColumnSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'ProjectConduitAPIMethod' => 'ConduitAPIMethod', 'ProjectCreateConduitAPIMethod' => 'ProjectConduitAPIMethod', 'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability', 'ProjectDatasourceEngineExtension' => 'PhabricatorDatasourceEngineExtension', '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', 'TransactionSearchConduitAPIMethod' => 'ConduitAPIMethod', 'UserConduitAPIMethod' => 'ConduitAPIMethod', 'UserDisableConduitAPIMethod' => 'UserConduitAPIMethod', 'UserEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'UserEnableConduitAPIMethod' => 'UserConduitAPIMethod', 'UserFindConduitAPIMethod' => 'UserConduitAPIMethod', 'UserQueryConduitAPIMethod' => 'UserConduitAPIMethod', 'UserSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'UserWhoAmIConduitAPIMethod' => 'UserConduitAPIMethod', ), )); diff --git a/src/applications/almanac/storage/AlmanacModularTransaction.php b/src/applications/almanac/storage/AlmanacModularTransaction.php index 6497069241..3e2eb0a3ec 100644 --- a/src/applications/almanac/storage/AlmanacModularTransaction.php +++ b/src/applications/almanac/storage/AlmanacModularTransaction.php @@ -1,14 +1,10 @@ getIsAdmin(); } public function getName() { return pht('Auth'); } public function getShortDescription() { return pht('Login/Registration'); } public function getHelpDocumentationArticles(PhabricatorUser $viewer) { // NOTE: Although reasonable help exists for this in "Configuring Accounts // and Registration", specifying help items here means we get the menu // item in all the login/link interfaces, which is confusing and not // helpful. // TODO: Special case this, or split the auth and auth administration // applications? return array(); } public function getApplicationGroup() { return self::GROUP_ADMIN; } public function getRoutes() { return array( '/auth/' => array( '' => 'PhabricatorAuthListController', 'config/' => array( 'new/' => 'PhabricatorAuthNewController', - 'new/(?P[^/]+)/' => 'PhabricatorAuthEditController', - 'edit/(?P\d+)/' => 'PhabricatorAuthEditController', + 'edit/(?:(?P\d+)/)?' => 'PhabricatorAuthEditController', '(?Penable|disable)/(?P\d+)/' => 'PhabricatorAuthDisableController', + 'view/(?P\d+)/' => 'PhabricatorAuthProviderViewController', ), 'login/(?P[^/]+)/(?:(?P[^/]+)/)?' => 'PhabricatorAuthLoginController', '(?Ploggedout)/' => 'PhabricatorAuthStartController', 'invite/(?P[^/]+)/' => 'PhabricatorAuthInviteController', 'register/(?:(?P[^/]+)/)?' => 'PhabricatorAuthRegisterController', 'start/' => 'PhabricatorAuthStartController', 'validate/' => 'PhabricatorAuthValidateController', 'finish/' => 'PhabricatorAuthFinishController', 'unlink/(?P[^/]+)/' => 'PhabricatorAuthUnlinkController', '(?Plink|refresh)/(?P[^/]+)/' => 'PhabricatorAuthLinkController', 'confirmlink/(?P[^/]+)/' => 'PhabricatorAuthConfirmLinkController', 'session/terminate/(?P[^/]+)/' => 'PhabricatorAuthTerminateSessionController', 'token/revoke/(?P[^/]+)/' => 'PhabricatorAuthRevokeTokenController', 'session/downgrade/' => 'PhabricatorAuthDowngradeSessionController', 'enroll/' => array( '(?:(?P[^/]+)/)?(?:(?Psaved)/)?' => 'PhabricatorAuthNeedsMultiFactorController', ), 'sshkey/' => array( $this->getQueryRoutePattern('for/(?P[^/]+)/') => 'PhabricatorAuthSSHKeyListController', 'generate/' => 'PhabricatorAuthSSHKeyGenerateController', 'upload/' => 'PhabricatorAuthSSHKeyEditController', 'edit/(?P\d+)/' => 'PhabricatorAuthSSHKeyEditController', 'revoke/(?P\d+)/' => 'PhabricatorAuthSSHKeyRevokeController', 'view/(?P\d+)/' => 'PhabricatorAuthSSHKeyViewController', ), 'password/' => 'PhabricatorAuthSetPasswordController', 'mfa/' => array( $this->getQueryRoutePattern() => 'PhabricatorAuthFactorProviderListController', $this->getEditRoutePattern('edit/') => 'PhabricatorAuthFactorProviderEditController', '(?P[1-9]\d*)/' => 'PhabricatorAuthFactorProviderViewController', 'message/(?P[1-9]\d*)/' => 'PhabricatorAuthFactorProviderMessageController', ), 'message/' => array( $this->getQueryRoutePattern() => 'PhabricatorAuthMessageListController', $this->getEditRoutePattern('edit/') => 'PhabricatorAuthMessageEditController', '(?P[1-9]\d*)/' => 'PhabricatorAuthMessageViewController', ), 'contact/' => array( $this->getEditRoutePattern('edit/') => 'PhabricatorAuthContactNumberEditController', '(?P[1-9]\d*)/' => 'PhabricatorAuthContactNumberViewController', '(?Pdisable|enable)/(?P[1-9]\d*)/' => 'PhabricatorAuthContactNumberDisableController', 'primary/(?P[1-9]\d*)/' => 'PhabricatorAuthContactNumberPrimaryController', 'test/(?P[1-9]\d*)/' => 'PhabricatorAuthContactNumberTestController', ), ), '/oauth/(?P\w+)/login/' => 'PhabricatorAuthOldOAuthRedirectController', '/login/' => array( '' => 'PhabricatorAuthStartController', 'email/' => 'PhabricatorEmailLoginController', 'once/'. '(?P[^/]+)/'. '(?P\d+)/'. '(?P[^/]+)/'. '(?:(?P\d+)/)?' => 'PhabricatorAuthOneTimeLoginController', 'refresh/' => 'PhabricatorRefreshCSRFController', 'mustverify/' => 'PhabricatorMustVerifyEmailController', ), '/emailverify/(?P[^/]+)/' => 'PhabricatorEmailVerificationController', '/logout/' => 'PhabricatorLogoutController', ); } protected function getCustomCapabilities() { return array( AuthManageProvidersCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, ), ); } } diff --git a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php index 0cac95f53d..f51f379d2b 100644 --- a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php +++ b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php @@ -1,209 +1,233 @@ getViewer(); $id = $request->getURIData('id'); $link_type = $request->getURIData('type'); $key = $request->getURIData('key'); $email_id = $request->getURIData('emailID'); if ($request->getUser()->isLoggedIn()) { return $this->renderError( pht('You are already logged in.')); } $target_user = id(new PhabricatorPeopleQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withIDs(array($id)) ->executeOne(); if (!$target_user) { return new Aphront404Response(); } // NOTE: As a convenience to users, these one-time login URIs may also // be associated with an email address which will be verified when the // URI is used. // This improves the new user experience for users receiving "Welcome" // emails on installs that require verification: if we did not verify the // email, they'd immediately get roadblocked with a "Verify Your Email" // error and have to go back to their email account, wait for a // "Verification" email, and then click that link to actually get access to // their account. This is hugely unwieldy, and if the link was only sent // to the user's email in the first place we can safely verify it as a // side effect of login. // The email hashed into the URI so users can't verify some email they // do not own by doing this: // // - Add some address you do not own; // - request a password reset; // - change the URI in the email to the address you don't own; // - login via the email link; and // - get a "verified" address you don't control. $target_email = null; if ($email_id) { $target_email = id(new PhabricatorUserEmail())->loadOneWhere( 'userPHID = %s AND id = %d', $target_user->getPHID(), $email_id); if (!$target_email) { return new Aphront404Response(); } } $engine = new PhabricatorAuthSessionEngine(); $token = $engine->loadOneTimeLoginKey( $target_user, $target_email, $key); if (!$token) { return $this->newDialog() ->setTitle(pht('Unable to Log In')) ->setShortTitle(pht('Login Failure')) ->appendParagraph( pht( 'The login link you clicked is invalid, out of date, or has '. 'already been used.')) ->appendParagraph( pht( 'Make sure you are copy-and-pasting the entire link into '. 'your browser. Login links are only valid for 24 hours, and '. 'can only be used once.')) ->appendParagraph( pht('You can try again, or request a new link via email.')) ->addCancelButton('/login/email/', pht('Send Another Email')); } if (!$target_user->canEstablishWebSessions()) { return $this->newDialog() ->setTitle(pht('Unable to Establish Web Session')) ->setShortTitle(pht('Login Failure')) ->appendParagraph( pht( 'You are trying to gain access to an account ("%s") that can not '. 'establish a web session.', $target_user->getUsername())) ->appendParagraph( pht( 'Special users like daemons and mailing lists are not permitted '. 'to log in via the web. Log in as a normal user instead.')) ->addCancelButton('/'); } if ($request->isFormPost()) { // If we have an email bound into this URI, verify email so that clicking // the link in the "Welcome" email is good enough, without requiring users // to go through a second round of email verification. $editor = id(new PhabricatorUserEditor()) ->setActor($target_user); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); // Nuke the token and all other outstanding password reset tokens. // There is no particular security benefit to destroying them all, but // it should reduce HackerOne reports of nebulous harm. $editor->revokePasswordResetLinks($target_user); if ($target_email) { $editor->verifyEmail($target_user, $target_email); } unset($unguarded); - $next = '/'; - if (!PhabricatorPasswordAuthProvider::getPasswordProvider()) { - $next = '/settings/panel/external/'; - } else { - - // We're going to let the user reset their password without knowing - // the old one. Generate a one-time token for that. - $key = Filesystem::readRandomCharacters(16); - $password_type = - PhabricatorAuthPasswordResetTemporaryTokenType::TOKENTYPE; - - $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); - id(new PhabricatorAuthTemporaryToken()) - ->setTokenResource($target_user->getPHID()) - ->setTokenType($password_type) - ->setTokenExpires(time() + phutil_units('1 hour in seconds')) - ->setTokenCode(PhabricatorHash::weakDigest($key)) - ->save(); - unset($unguarded); - - $panel_uri = '/auth/password/'; - - $next = (string)id(new PhutilURI($panel_uri)) - ->setQueryParams( - array( - 'key' => $key, - )); - - $request->setTemporaryCookie(PhabricatorCookies::COOKIE_HISEC, 'yes'); - } + $next_uri = $this->getNextStepURI($target_user); - PhabricatorCookies::setNextURICookie($request, $next, $force = true); + PhabricatorCookies::setNextURICookie($request, $next_uri, $force = true); $force_full_session = false; if ($link_type === PhabricatorAuthSessionEngine::ONETIME_RECOVER) { $force_full_session = $token->getShouldForceFullSession(); } return $this->loginUser($target_user, $force_full_session); } // NOTE: We need to CSRF here so attackers can't generate an email link, // then log a user in to an account they control via sneaky invisible // form submissions. switch ($link_type) { case PhabricatorAuthSessionEngine::ONETIME_WELCOME: $title = pht('Welcome to Phabricator'); break; case PhabricatorAuthSessionEngine::ONETIME_RECOVER: $title = pht('Account Recovery'); break; case PhabricatorAuthSessionEngine::ONETIME_USERNAME: case PhabricatorAuthSessionEngine::ONETIME_RESET: default: $title = pht('Log in to Phabricator'); break; } $body = array(); $body[] = pht( 'Use the button below to log in as: %s', phutil_tag('strong', array(), $target_user->getUsername())); if ($target_email && !$target_email->getIsVerified()) { $body[] = pht( 'Logging in will verify %s as an email address you own.', phutil_tag('strong', array(), $target_email->getAddress())); } $body[] = pht( 'After logging in you should set a password for your account, or '. 'link your account to an external account that you can use to '. 'authenticate in the future.'); $dialog = $this->newDialog() ->setTitle($title) ->addSubmitButton(pht('Log In (%s)', $target_user->getUsername())) ->addCancelButton('/'); foreach ($body as $paragraph) { $dialog->appendParagraph($paragraph); } return id(new AphrontDialogResponse())->setDialog($dialog); } + + private function getNextStepURI(PhabricatorUser $user) { + $request = $this->getRequest(); + + // If we have password auth, let the user set or reset their password after + // login. + $have_passwords = PhabricatorPasswordAuthProvider::getPasswordProvider(); + if ($have_passwords) { + // We're going to let the user reset their password without knowing + // the old one. Generate a one-time token for that. + $key = Filesystem::readRandomCharacters(16); + $password_type = + PhabricatorAuthPasswordResetTemporaryTokenType::TOKENTYPE; + + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); + id(new PhabricatorAuthTemporaryToken()) + ->setTokenResource($user->getPHID()) + ->setTokenType($password_type) + ->setTokenExpires(time() + phutil_units('1 hour in seconds')) + ->setTokenCode(PhabricatorHash::weakDigest($key)) + ->save(); + unset($unguarded); + + $panel_uri = '/auth/password/'; + + $request->setTemporaryCookie(PhabricatorCookies::COOKIE_HISEC, 'yes'); + + return (string)id(new PhutilURI($panel_uri)) + ->setQueryParams( + array( + 'key' => $key, + )); + } + + $providers = id(new PhabricatorAuthProviderConfigQuery()) + ->setViewer($user) + ->withIsEnabled(true) + ->execute(); + + // If there are no configured providers and the user is an administrator, + // send them to Auth to configure a provider. This is probably where they + // want to go. You can end up in this state by accidentally losing your + // first session during initial setup, or after restoring exported data + // from a hosted instance. + if (!$providers && $user->getIsAdmin()) { + return '/auth/'; + } + + // If we didn't find anywhere better to send them, give up and just send + // them to the home page. + return '/'; + } + } diff --git a/src/applications/auth/controller/PhabricatorAuthStartController.php b/src/applications/auth/controller/PhabricatorAuthStartController.php index 29fa7e0b9f..0b823098d7 100644 --- a/src/applications/auth/controller/PhabricatorAuthStartController.php +++ b/src/applications/auth/controller/PhabricatorAuthStartController.php @@ -1,332 +1,361 @@ getUser(); if ($viewer->isLoggedIn()) { // Kick the user home if they are already logged in. return id(new AphrontRedirectResponse())->setURI('/'); } if ($request->isAjax()) { return $this->processAjaxRequest(); } if ($request->isConduit()) { return $this->processConduitRequest(); } // If the user gets this far, they aren't logged in, so if they have a // user session token we can conclude that it's invalid: if it was valid, // they'd have been logged in above and never made it here. Try to clear // it and warn the user they may need to nuke their cookies. $session_token = $request->getCookie(PhabricatorCookies::COOKIE_SESSION); $did_clear = $request->getStr('cleared'); if (strlen($session_token)) { $kind = PhabricatorAuthSessionEngine::getSessionKindFromToken( $session_token); switch ($kind) { case PhabricatorAuthSessionEngine::KIND_ANONYMOUS: // If this is an anonymous session. It's expected that they won't // be logged in, so we can just continue. break; default: // The session cookie is invalid, so try to clear it. $request->clearCookie(PhabricatorCookies::COOKIE_USERNAME); $request->clearCookie(PhabricatorCookies::COOKIE_SESSION); // We've previously tried to clear the cookie but we ended up back // here, so it didn't work. Hard fatal instead of trying again. if ($did_clear) { return $this->renderError( pht( 'Your login session is invalid, and clearing the session '. 'cookie was unsuccessful. Try clearing your browser cookies.')); } $redirect_uri = $request->getRequestURI(); $redirect_uri->setQueryParam('cleared', 1); return id(new AphrontRedirectResponse())->setURI($redirect_uri); } } // If we just cleared the session cookie and it worked, clean up after // ourselves by redirecting to get rid of the "cleared" parameter. The // the workflow will continue normally. if ($did_clear) { $redirect_uri = $request->getRequestURI(); $redirect_uri->setQueryParam('cleared', null); return id(new AphrontRedirectResponse())->setURI($redirect_uri); } $providers = PhabricatorAuthProvider::getAllEnabledProviders(); foreach ($providers as $key => $provider) { if (!$provider->shouldAllowLogin()) { unset($providers[$key]); } } + $configs = array(); + foreach ($providers as $provider) { + $configs[] = $provider->getProviderConfig(); + } + if (!$providers) { if ($this->isFirstTimeSetup()) { // If this is a fresh install, let the user register their admin // account. return id(new AphrontRedirectResponse()) ->setURI($this->getApplicationURI('/register/')); } return $this->renderError( pht( 'This Phabricator install is not configured with any enabled '. 'authentication providers which can be used to log in. If you '. 'have accidentally locked yourself out by disabling all providers, '. 'you can use `%s` to recover access to an account.', 'phabricator/bin/auth recover ')); } $next_uri = $request->getStr('next'); if (!strlen($next_uri)) { if ($this->getDelegatingController()) { // Only set a next URI from the request path if this controller was // delegated to, which happens when a user tries to view a page which // requires them to login. // If this controller handled the request directly, we're on the main // login page, and never want to redirect the user back here after they // login. $next_uri = (string)$this->getRequest()->getRequestURI(); } } if (!$request->isFormPost()) { if (strlen($next_uri)) { PhabricatorCookies::setNextURICookie($request, $next_uri); } PhabricatorCookies::setClientIDCookie($request); } $auto_response = $this->tryAutoLogin($providers); if ($auto_response) { return $auto_response; } $invite = $this->loadInvite(); $not_buttons = array(); $are_buttons = array(); $providers = msort($providers, 'getLoginOrder'); foreach ($providers as $provider) { if ($invite) { $form = $provider->buildInviteForm($this); } else { $form = $provider->buildLoginForm($this); } if ($provider->isLoginFormAButton()) { $are_buttons[] = $form; } else { $not_buttons[] = $form; } } $out = array(); $out[] = $not_buttons; if ($are_buttons) { require_celerity_resource('auth-css'); foreach ($are_buttons as $key => $button) { $are_buttons[$key] = phutil_tag( 'div', array( 'class' => 'phabricator-login-button mmb', ), $button); } // If we only have one button, add a second pretend button so that we // always have two columns. This makes it easier to get the alignments // looking reasonable. if (count($are_buttons) == 1) { $are_buttons[] = null; } $button_columns = id(new AphrontMultiColumnView()) ->setFluidLayout(true); $are_buttons = array_chunk($are_buttons, ceil(count($are_buttons) / 2)); foreach ($are_buttons as $column) { $button_columns->addColumn($column); } $out[] = phutil_tag( 'div', array( 'class' => 'phabricator-login-buttons', ), $button_columns); } - $handlers = PhabricatorAuthLoginHandler::getAllHandlers(); - - $delegating_controller = $this->getDelegatingController(); - - $header = array(); - foreach ($handlers as $handler) { - $handler = clone $handler; - - $handler->setRequest($request); - - if ($delegating_controller) { - $handler->setDelegatingController($delegating_controller); - } - - $header[] = $handler->getAuthLoginHeaderContent(); - } - $invite_message = null; if ($invite) { $invite_message = $this->renderInviteHeader($invite); } $custom_message = $this->newCustomStartMessage(); + $email_login = $this->newEmailLoginView($configs); + $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Login')); $crumbs->setBorder(true); $title = pht('Login'); $view = array( - $header, $invite_message, $custom_message, $out, + $email_login, ); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } private function processAjaxRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); // We end up here if the user clicks a workflow link that they need to // login to use. We give them a dialog saying "You need to login...". if ($request->isDialogFormPost()) { return id(new AphrontRedirectResponse())->setURI( $request->getRequestURI()); } // Often, users end up here by clicking a disabled action link in the UI // (for example, they might click "Edit Subtasks" on a Maniphest task // page). After they log in we want to send them back to that main object // page if we can, since it's confusing to end up on a standalone page with // only a dialog (particularly if that dialog is another error, // like a policy exception). $via_header = AphrontRequest::getViaHeaderName(); $via_uri = AphrontRequest::getHTTPHeader($via_header); if (strlen($via_uri)) { PhabricatorCookies::setNextURICookie($request, $via_uri, $force = true); } return $this->newDialog() ->setTitle(pht('Login Required')) ->appendParagraph(pht('You must log in to take this action.')) ->addSubmitButton(pht('Log In')) ->addCancelButton('/'); } private function processConduitRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); // A common source of errors in Conduit client configuration is getting // the request path wrong. The client will end up here, so make some // effort to give them a comprehensible error message. $request_path = $this->getRequest()->getPath(); $conduit_path = '/api/'; $example_path = '/api/conduit.ping'; $message = pht( 'ERROR: You are making a Conduit API request to "%s", but the correct '. 'HTTP request path to use in order to access a COnduit method is "%s" '. '(for example, "%s"). Check your configuration.', $request_path, $conduit_path, $example_path); return id(new AphrontPlainTextResponse())->setContent($message); } protected function renderError($message) { return $this->renderErrorPage( pht('Authentication Failure'), array($message)); } private function tryAutoLogin(array $providers) { $request = $this->getRequest(); // If the user just logged out, don't immediately log them in again. if ($request->getURIData('loggedout')) { return null; } // If we have more than one provider, we can't autologin because we // don't know which one the user wants. if (count($providers) != 1) { return null; } $provider = head($providers); if (!$provider->supportsAutoLogin()) { return null; } $config = $provider->getProviderConfig(); if (!$config->getShouldAutoLogin()) { return null; } $auto_uri = $provider->getAutoLoginURI($request); return id(new AphrontRedirectResponse()) ->setIsExternal(true) ->setURI($auto_uri); } private function newCustomStartMessage() { $viewer = $this->getViewer(); $text = PhabricatorAuthMessage::loadMessageText( $viewer, PhabricatorAuthLoginMessageType::MESSAGEKEY); if (!strlen($text)) { return null; } $remarkup_view = new PHUIRemarkupView($viewer, $text); return phutil_tag( 'div', array( 'class' => 'auth-custom-message', ), $remarkup_view); } + private function newEmailLoginView(array $configs) { + assert_instances_of($configs, 'PhabricatorAuthProviderConfig'); + + // Check if password auth is enabled. If it is, the password login form + // renders a "Forgot password?" link, so we don't need to provide a + // supplemental link. + + $has_password = false; + foreach ($configs as $config) { + $provider = $config->getProvider(); + if ($provider instanceof PhabricatorPasswordAuthProvider) { + $has_password = true; + } + } + + if ($has_password) { + return null; + } + + $view = array( + pht('Trouble logging in?'), + ' ', + phutil_tag( + 'a', + array( + 'href' => '/login/email/', + ), + pht('Send a login link to your email address.')), + ); + + return phutil_tag( + 'div', + array( + 'class' => 'auth-custom-message', + ), + $view); + } + + } diff --git a/src/applications/auth/controller/PhabricatorAuthUnlinkController.php b/src/applications/auth/controller/PhabricatorAuthUnlinkController.php index e6e1493e5a..1e3023e5d2 100644 --- a/src/applications/auth/controller/PhabricatorAuthUnlinkController.php +++ b/src/applications/auth/controller/PhabricatorAuthUnlinkController.php @@ -1,146 +1,154 @@ getViewer(); $this->providerKey = $request->getURIData('pkey'); list($type, $domain) = explode(':', $this->providerKey, 2); // Check that this account link actually exists. We don't require the // provider to exist because we want users to be able to delete links to // dead accounts if they want. $account = id(new PhabricatorExternalAccount())->loadOneWhere( 'accountType = %s AND accountDomain = %s AND userPHID = %s', $type, $domain, $viewer->getPHID()); if (!$account) { return $this->renderNoAccountErrorDialog(); } // Check that the provider (if it exists) allows accounts to be unlinked. $provider_key = $this->providerKey; $provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key); if ($provider) { if (!$provider->shouldAllowAccountUnlink()) { return $this->renderNotUnlinkableErrorDialog($provider); } } - // Check that this account isn't the last account which can be used to - // login. We prevent you from removing the last account. + $confirmations = $request->getStrList('confirmations'); + $confirmations = array_fuse($confirmations); + + if (!$request->isFormPost() || !isset($confirmations['unlink'])) { + return $this->renderConfirmDialog($confirmations); + } + + // Check that this account isn't the only account which can be used to + // login. We warn you when you remove your only login account. if ($account->isUsableForLogin()) { $other_accounts = id(new PhabricatorExternalAccount())->loadAllWhere( 'userPHID = %s', $viewer->getPHID()); $valid_accounts = 0; foreach ($other_accounts as $other_account) { if ($other_account->isUsableForLogin()) { $valid_accounts++; } } if ($valid_accounts < 2) { - return $this->renderLastUsableAccountErrorDialog(); + if (!isset($confirmations['only'])) { + return $this->renderOnlyUsableAccountConfirmDialog($confirmations); + } } } - if ($request->isDialogFormPost()) { - $account->delete(); - - id(new PhabricatorAuthSessionEngine())->terminateLoginSessions( - $viewer, - new PhutilOpaqueEnvelope( - $request->getCookie(PhabricatorCookies::COOKIE_SESSION))); + $account->delete(); - return id(new AphrontRedirectResponse())->setURI($this->getDoneURI()); - } + id(new PhabricatorAuthSessionEngine())->terminateLoginSessions( + $viewer, + new PhutilOpaqueEnvelope( + $request->getCookie(PhabricatorCookies::COOKIE_SESSION))); - return $this->renderConfirmDialog(); + return id(new AphrontRedirectResponse())->setURI($this->getDoneURI()); } private function getDoneURI() { return '/settings/panel/external/'; } private function renderNoAccountErrorDialog() { $dialog = id(new AphrontDialogView()) ->setUser($this->getRequest()->getUser()) ->setTitle(pht('No Such Account')) ->appendChild( pht( 'You can not unlink this account because it is not linked.')) ->addCancelButton($this->getDoneURI()); return id(new AphrontDialogResponse())->setDialog($dialog); } private function renderNotUnlinkableErrorDialog( PhabricatorAuthProvider $provider) { $dialog = id(new AphrontDialogView()) ->setUser($this->getRequest()->getUser()) ->setTitle(pht('Permanent Account Link')) ->appendChild( pht( 'You can not unlink this account because the administrator has '. 'configured Phabricator to make links to %s accounts permanent.', $provider->getProviderName())) ->addCancelButton($this->getDoneURI()); return id(new AphrontDialogResponse())->setDialog($dialog); } - private function renderLastUsableAccountErrorDialog() { - $dialog = id(new AphrontDialogView()) - ->setUser($this->getRequest()->getUser()) - ->setTitle(pht('Last Valid Account')) - ->appendChild( - pht( - 'You can not unlink this account because you have no other '. - 'valid login accounts. If you removed it, you would be unable '. - 'to log in. Add another authentication method before removing '. - 'this one.')) - ->addCancelButton($this->getDoneURI()); + private function renderOnlyUsableAccountConfirmDialog(array $confirmations) { + $confirmations[] = 'only'; - return id(new AphrontDialogResponse())->setDialog($dialog); + return $this->newDialog() + ->setTitle(pht('Unlink Your Only Login Account?')) + ->addHiddenInput('confirmations', implode(',', $confirmations)) + ->appendParagraph( + pht( + 'This is the only external login account linked to your Phabicator '. + 'account. If you remove it, you may no longer be able to log in.')) + ->appendParagraph( + pht( + 'If you lose access to your account, you can recover access by '. + 'sending yourself an email login link from the login screen.')) + ->addCancelButton($this->getDoneURI()) + ->addSubmitButton(pht('Unlink External Account')); } - private function renderConfirmDialog() { + private function renderConfirmDialog(array $confirmations) { + $confirmations[] = 'unlink'; + $provider_key = $this->providerKey; $provider = PhabricatorAuthProvider::getEnabledProviderByKey($provider_key); if ($provider) { $title = pht('Unlink "%s" Account?', $provider->getProviderName()); $body = pht( 'You will no longer be able to use your %s account to '. 'log in to Phabricator.', $provider->getProviderName()); } else { $title = pht('Unlink Account?'); $body = pht( 'You will no longer be able to use this account to log in '. 'to Phabricator.'); } - $dialog = id(new AphrontDialogView()) - ->setUser($this->getRequest()->getUser()) + return $this->newDialog() ->setTitle($title) + ->addHiddenInput('confirmations', implode(',', $confirmations)) ->appendParagraph($body) ->appendParagraph( pht( 'Note: Unlinking an authentication provider will terminate any '. 'other active login sessions.')) ->addSubmitButton(pht('Unlink Account')) ->addCancelButton($this->getDoneURI()); - - return id(new AphrontDialogResponse())->setDialog($dialog); } } diff --git a/src/applications/auth/controller/PhabricatorEmailLoginController.php b/src/applications/auth/controller/PhabricatorEmailLoginController.php index f57a29b11a..eef30e6989 100644 --- a/src/applications/auth/controller/PhabricatorEmailLoginController.php +++ b/src/applications/auth/controller/PhabricatorEmailLoginController.php @@ -1,166 +1,184 @@ getViewer(); $e_email = true; $e_captcha = true; $errors = array(); - $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); - + $v_email = $request->getStr('email'); if ($request->isFormPost()) { $e_email = null; $e_captcha = pht('Again'); $captcha_ok = AphrontFormRecaptchaControl::processCaptcha($request); if (!$captcha_ok) { $errors[] = pht('Captcha response is incorrect, try again.'); $e_captcha = pht('Invalid'); } - $email = $request->getStr('email'); - if (!strlen($email)) { + if (!strlen($v_email)) { $errors[] = pht('You must provide an email address.'); $e_email = pht('Required'); } if (!$errors) { // NOTE: Don't validate the email unless the captcha is good; this makes // it expensive to fish for valid email addresses while giving the user // a better error if they goof their email. $target_email = id(new PhabricatorUserEmail())->loadOneWhere( 'address = %s', - $email); + $v_email); $target_user = null; if ($target_email) { $target_user = id(new PhabricatorUser())->loadOneWhere( 'phid = %s', $target_email->getUserPHID()); } if (!$target_user) { $errors[] = pht('There is no account associated with that email address.'); $e_email = pht('Invalid'); } // If this address is unverified, only send a reset link to it if // the account has no verified addresses. This prevents an opportunistic // attacker from compromising an account if a user adds an email // address but mistypes it and doesn't notice. // (For a newly created account, all the addresses may be unverified, // which is why we'll send to an unverified address in that case.) if ($target_email && !$target_email->getIsVerified()) { $verified_addresses = id(new PhabricatorUserEmail())->loadAllWhere( 'userPHID = %s AND isVerified = 1', $target_email->getUserPHID()); if ($verified_addresses) { $errors[] = pht( 'That email address is not verified, but the account it is '. 'connected to has at least one other verified address. When an '. 'account has at least one verified address, you can only send '. 'password reset links to one of the verified addresses. Try '. 'a verified address instead.'); $e_email = pht('Unverified'); } } if (!$errors) { - $engine = new PhabricatorAuthSessionEngine(); - $uri = $engine->getOneTimeLoginURI( - $target_user, - null, - PhabricatorAuthSessionEngine::ONETIME_RESET); - - if ($is_serious) { - $body = pht( - "You can use this link to reset your Phabricator password:". - "\n\n %s\n", - $uri); - } else { - $body = pht( - "Condolences on forgetting your password. You can use this ". - "link to reset it:\n\n". - " %s\n\n". - "After you set a new password, consider writing it down on a ". - "sticky note and attaching it to your monitor so you don't ". - "forget again! Choosing a very short, easy-to-remember password ". - "like \"cat\" or \"1234\" might also help.\n\n". - "Best Wishes,\nPhabricator\n", - $uri); - - } + $body = $this->newAccountLoginMailBody($target_user); $mail = id(new PhabricatorMetaMTAMail()) - ->setSubject(pht('[Phabricator] Password Reset')) + ->setSubject(pht('[Phabricator] Account Login Link')) ->setForceDelivery(true) ->addRawTos(array($target_email->getAddress())) ->setBody($body) ->saveAndSend(); return $this->newDialog() ->setTitle(pht('Check Your Email')) ->setShortTitle(pht('Email Sent')) ->appendParagraph( pht('An email has been sent with a link you can use to log in.')) ->addCancelButton('/', pht('Done')); } } } - $error_view = null; - if ($errors) { - $error_view = new PHUIInfoView(); - $error_view->setErrors($errors); + $form = id(new AphrontFormView()) + ->setViewer($viewer); + + if ($this->isPasswordAuthEnabled()) { + $form->appendRemarkupInstructions( + pht( + 'To reset your password, provide your email address. An email '. + 'with a login link will be sent to you.')); + } else { + $form->appendRemarkupInstructions( + pht( + 'To access your account, provide your email address. An email '. + 'with a login link will be sent to you.')); } - $email_auth = new PHUIFormLayoutView(); - $email_auth->appendChild($error_view); - $email_auth - ->setUser($request->getUser()) - ->setFullWidth(true) - ->appendChild( + $form + ->appendControl( id(new AphrontFormTextControl()) - ->setLabel(pht('Email')) + ->setLabel(pht('Email Address')) ->setName('email') - ->setValue($request->getStr('email')) + ->setValue($v_email) ->setError($e_email)) - ->appendChild( + ->appendControl( id(new AphrontFormRecaptchaControl()) ->setLabel(pht('Captcha')) ->setError($e_captcha)); - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Reset Password')); - $crumbs->setBorder(true); + if ($this->isPasswordAuthEnabled()) { + $title = pht('Password Reset'); + } else { + $title = pht('Email Login'); + } + + return $this->newDialog() + ->setTitle($title) + ->setErrors($errors) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->appendForm($form) + ->addCancelButton('/auth/start/') + ->addSubmitButton(pht('Send Email')); + } - $dialog = new AphrontDialogView(); - $dialog->setUser($request->getUser()); - $dialog->setTitle(pht('Forgot Password / Email Login')); - $dialog->appendChild($email_auth); - $dialog->addSubmitButton(pht('Send Email')); - $dialog->setSubmitURI('/login/email/'); + private function newAccountLoginMailBody(PhabricatorUser $user) { + $engine = new PhabricatorAuthSessionEngine(); + $uri = $engine->getOneTimeLoginURI( + $user, + null, + PhabricatorAuthSessionEngine::ONETIME_RESET); - return $this->newPage() - ->setTitle(pht('Forgot Password')) - ->setCrumbs($crumbs) - ->appendChild($dialog); + $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); + $have_passwords = $this->isPasswordAuthEnabled(); + + if ($have_passwords) { + if ($is_serious) { + $body = pht( + "You can use this link to reset your Phabricator password:". + "\n\n %s\n", + $uri); + } else { + $body = pht( + "Condolences on forgetting your password. You can use this ". + "link to reset it:\n\n". + " %s\n\n". + "After you set a new password, consider writing it down on a ". + "sticky note and attaching it to your monitor so you don't ". + "forget again! Choosing a very short, easy-to-remember password ". + "like \"cat\" or \"1234\" might also help.\n\n". + "Best Wishes,\nPhabricator\n", + $uri); + } + } else { + $body = pht( + "You can use this login link to regain access to your Phabricator ". + "account:". + "\n\n". + " %s\n", + $uri); + } + + return $body; } + private function isPasswordAuthEnabled() { + return (bool)PhabricatorPasswordAuthProvider::getPasswordProvider(); + } } diff --git a/src/applications/auth/controller/config/PhabricatorAuthDisableController.php b/src/applications/auth/controller/config/PhabricatorAuthDisableController.php index 5863aceca9..252f159ec4 100644 --- a/src/applications/auth/controller/config/PhabricatorAuthDisableController.php +++ b/src/applications/auth/controller/config/PhabricatorAuthDisableController.php @@ -1,90 +1,89 @@ requireApplicationCapability( AuthManageProvidersCapability::CAPABILITY); - $viewer = $request->getUser(); + + $viewer = $this->getViewer(); $config_id = $request->getURIData('id'); $action = $request->getURIData('action'); $config = id(new PhabricatorAuthProviderConfigQuery()) ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->withIDs(array($config_id)) ->executeOne(); if (!$config) { return new Aphront404Response(); } $is_enable = ($action === 'enable'); + $done_uri = $config->getURI(); if ($request->isDialogFormPost()) { $xactions = array(); $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE) ->setNewValue((int)$is_enable); $editor = id(new PhabricatorAuthProviderConfigEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->applyTransactions($config, $xactions); - return id(new AphrontRedirectResponse())->setURI( - $this->getApplicationURI()); + return id(new AphrontRedirectResponse())->setURI($done_uri); } if ($is_enable) { $title = pht('Enable Provider?'); if ($config->getShouldAllowRegistration()) { $body = pht( 'Do you want to enable this provider? Users will be able to use '. 'their existing external accounts to register new Phabricator '. 'accounts and log in using linked accounts.'); } else { $body = pht( 'Do you want to enable this provider? Users will be able to log '. 'in to Phabricator using linked accounts.'); } $button = pht('Enable Provider'); } else { // TODO: We could tailor this a bit more. In particular, we could // check if this is the last provider and either prevent if from // being disabled or force the user through like 35 prompts. We could // also check if it's the last provider linked to the acting user's // account and pop a warning like "YOU WILL NO LONGER BE ABLE TO LOGIN // YOU GOOF, YOU PROBABLY DO NOT MEAN TO DO THIS". None of this is // critical and we can wait to see how users manage to shoot themselves - // in the feet. Shortly, `bin/auth` will be able to recover from these - // types of mistakes. + // in the feet. + + // `bin/auth` can recover from these types of mistakes. $title = pht('Disable Provider?'); $body = pht( 'Do you want to disable this provider? Users will not be able to '. 'register or log in using linked accounts. If there are any users '. 'without other linked authentication mechanisms, they will no longer '. 'be able to log in. If you disable all providers, no one will be '. 'able to log in.'); $button = pht('Disable Provider'); } - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) + return $this->newDialog() ->setTitle($title) ->appendChild($body) - ->addCancelButton($this->getApplicationURI()) + ->addCancelButton($done_uri) ->addSubmitButton($button); - - return id(new AphrontDialogResponse())->setDialog($dialog); } } diff --git a/src/applications/auth/controller/config/PhabricatorAuthEditController.php b/src/applications/auth/controller/config/PhabricatorAuthEditController.php index 6ff0be4383..d3cd2fef98 100644 --- a/src/applications/auth/controller/config/PhabricatorAuthEditController.php +++ b/src/applications/auth/controller/config/PhabricatorAuthEditController.php @@ -1,382 +1,366 @@ requireApplicationCapability( AuthManageProvidersCapability::CAPABILITY); - $viewer = $request->getUser(); - $provider_class = $request->getURIData('className'); + + $viewer = $this->getViewer(); + $provider_class = $request->getStr('provider'); $config_id = $request->getURIData('id'); if ($config_id) { $config = id(new PhabricatorAuthProviderConfigQuery()) ->setViewer($viewer) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->withIDs(array($config_id)) ->executeOne(); if (!$config) { return new Aphront404Response(); } $provider = $config->getProvider(); if (!$provider) { return new Aphront404Response(); } $is_new = false; } else { $provider = null; $providers = PhabricatorAuthProvider::getAllBaseProviders(); foreach ($providers as $candidate_provider) { if (get_class($candidate_provider) === $provider_class) { $provider = $candidate_provider; break; } } if (!$provider) { return new Aphront404Response(); } // TODO: When we have multi-auth providers, support them here. $configs = id(new PhabricatorAuthProviderConfigQuery()) ->setViewer($viewer) ->withProviderClasses(array(get_class($provider))) ->execute(); if ($configs) { $id = head($configs)->getID(); $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->setMethod('GET') ->setSubmitURI($this->getApplicationURI('config/edit/'.$id.'/')) ->setTitle(pht('Provider Already Configured')) ->appendChild( pht( 'This provider ("%s") already exists, and you can not add more '. 'than one instance of it. You can edit the existing provider, '. 'or you can choose a different provider.', $provider->getProviderName())) ->addCancelButton($this->getApplicationURI('config/new/')) ->addSubmitButton(pht('Edit Existing Provider')); return id(new AphrontDialogResponse())->setDialog($dialog); } $config = $provider->getDefaultProviderConfig(); $provider->attachProviderConfig($config); $is_new = true; } $errors = array(); $v_login = $config->getShouldAllowLogin(); $v_registration = $config->getShouldAllowRegistration(); $v_link = $config->getShouldAllowLink(); $v_unlink = $config->getShouldAllowUnlink(); $v_trust_email = $config->getShouldTrustEmails(); $v_auto_login = $config->getShouldAutoLogin(); if ($request->isFormPost()) { $properties = $provider->readFormValuesFromRequest($request); list($errors, $issues, $properties) = $provider->processEditForm( $request, $properties); $xactions = array(); if (!$errors) { if ($is_new) { if (!strlen($config->getProviderType())) { $config->setProviderType($provider->getProviderType()); } if (!strlen($config->getProviderDomain())) { $config->setProviderDomain($provider->getProviderDomain()); } } $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_LOGIN) ->setNewValue($request->getInt('allowLogin', 0)); $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_REGISTRATION) ->setNewValue($request->getInt('allowRegistration', 0)); $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_LINK) ->setNewValue($request->getInt('allowLink', 0)); $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_UNLINK) ->setNewValue($request->getInt('allowUnlink', 0)); $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_TRUST_EMAILS) ->setNewValue($request->getInt('trustEmails', 0)); if ($provider->supportsAutoLogin()) { $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_AUTO_LOGIN) ->setNewValue($request->getInt('autoLogin', 0)); } foreach ($properties as $key => $value) { $xactions[] = id(new PhabricatorAuthProviderConfigTransaction()) ->setTransactionType( PhabricatorAuthProviderConfigTransaction::TYPE_PROPERTY) ->setMetadataValue('auth:property', $key) ->setNewValue($value); } if ($is_new) { $config->save(); } $editor = id(new PhabricatorAuthProviderConfigEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->applyTransactions($config, $xactions); - if ($provider->hasSetupStep() && $is_new) { - $id = $config->getID(); - $next_uri = $this->getApplicationURI('config/edit/'.$id.'/'); - } else { - $next_uri = $this->getApplicationURI(); - } + $next_uri = $config->getURI(); return id(new AphrontRedirectResponse())->setURI($next_uri); } } else { $properties = $provider->readFormValuesFromProvider(); $issues = array(); } if ($is_new) { if ($provider->hasSetupStep()) { $button = pht('Next Step'); } else { $button = pht('Add Provider'); } $crumb = pht('Add Provider'); $title = pht('Add Auth Provider'); $header_icon = 'fa-plus-square'; $cancel_uri = $this->getApplicationURI('/config/new/'); } else { $button = pht('Save'); $crumb = pht('Edit Provider'); $title = pht('Edit Auth Provider'); $header_icon = 'fa-pencil'; - $cancel_uri = $this->getApplicationURI(); + $cancel_uri = $config->getURI(); } $header = id(new PHUIHeaderView()) ->setHeader(pht('%s: %s', $title, $provider->getProviderName())) ->setHeaderIcon($header_icon); if (!$is_new) { if ($config->getIsEnabled()) { $status_name = pht('Enabled'); $status_color = 'green'; $status_icon = 'fa-check'; $header->setStatus($status_icon, $status_color, $status_name); } else { $status_name = pht('Disabled'); $status_color = 'indigo'; $status_icon = 'fa-ban'; $header->setStatus($status_icon, $status_color, $status_name); } } $config_name = 'auth.email-domains'; $config_href = '/config/edit/'.$config_name.'/'; $email_domains = PhabricatorEnv::getEnvConfig($config_name); if ($email_domains) { $registration_warning = pht( 'Users will only be able to register with a verified email address '. 'at one of the configured [[ %s | %s ]] domains: **%s**', $config_href, $config_name, implode(', ', $email_domains)); } else { $registration_warning = pht( "NOTE: Any user who can browse to this install's login page will be ". "able to register a Phabricator account. To restrict who can register ". "an account, configure [[ %s | %s ]].", $config_href, $config_name); } $str_login = array( phutil_tag('strong', array(), pht('Allow Login:')), ' ', pht( 'Allow users to log in using this provider. If you disable login, '. 'users can still use account integrations for this provider.'), ); $str_registration = array( phutil_tag('strong', array(), pht('Allow Registration:')), ' ', pht( 'Allow users to register new Phabricator accounts using this '. 'provider. If you disable registration, users can still use this '. 'provider to log in to existing accounts, but will not be able to '. 'create new accounts.'), ); $str_link = hsprintf( '%s: %s', pht('Allow Linking Accounts'), pht( 'Allow users to link account credentials for this provider to '. 'existing Phabricator accounts. There is normally no reason to '. 'disable this unless you are trying to move away from a provider '. 'and want to stop users from creating new account links.')); $str_unlink = hsprintf( '%s: %s', pht('Allow Unlinking Accounts'), pht( 'Allow users to unlink account credentials for this provider from '. 'existing Phabricator accounts. If you disable this, Phabricator '. 'accounts will be permanently bound to provider accounts.')); $str_trusted_email = hsprintf( '%s: %s', pht('Trust Email Addresses'), pht( 'Phabricator will skip email verification for accounts registered '. 'through this provider.')); $str_auto_login = hsprintf( '%s: %s', pht('Allow Auto Login'), pht( 'Phabricator will automatically login with this provider if it is '. 'the only available provider.')); $form = id(new AphrontFormView()) ->setUser($viewer) + ->addHiddenInput('provider', $provider_class) ->appendChild( id(new AphrontFormCheckboxControl()) ->setLabel(pht('Allow')) ->addCheckbox( 'allowLogin', 1, $str_login, $v_login)) ->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'allowRegistration', 1, $str_registration, $v_registration)) ->appendRemarkupInstructions($registration_warning) ->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'allowLink', 1, $str_link, $v_link)) ->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'allowUnlink', 1, $str_unlink, $v_unlink)); if ($provider->shouldAllowEmailTrustConfiguration()) { $form->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'trustEmails', 1, $str_trusted_email, $v_trust_email)); } if ($provider->supportsAutoLogin()) { $form->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'autoLogin', 1, $str_auto_login, $v_auto_login)); } $provider->extendEditForm($request, $form, $properties, $issues); $form ->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($cancel_uri) ->setValue($button)); $help = $provider->getConfigurationHelp(); if ($help) { $form->appendChild(id(new PHUIFormDividerControl())); $form->appendRemarkupInstructions($help); } $footer = $provider->renderConfigurationFooter(); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($crumb); $crumbs->setBorder(true); - $timeline = null; - if (!$is_new) { - $timeline = $this->buildTransactionTimeline( - $config, - new PhabricatorAuthProviderConfigTransactionQuery()); - $xactions = $timeline->getTransactions(); - foreach ($xactions as $xaction) { - $xaction->setProvider($provider); - } - $timeline->setShouldTerminate(true); - } - $form_box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Provider')) ->setFormErrors($errors) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $form_box, $footer, - $timeline, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } } diff --git a/src/applications/auth/controller/config/PhabricatorAuthListController.php b/src/applications/auth/controller/config/PhabricatorAuthListController.php index bb118d798e..f4b05e8adf 100644 --- a/src/applications/auth/controller/config/PhabricatorAuthListController.php +++ b/src/applications/auth/controller/config/PhabricatorAuthListController.php @@ -1,142 +1,118 @@ getViewer(); $configs = id(new PhabricatorAuthProviderConfigQuery()) ->setViewer($viewer) ->execute(); $list = new PHUIObjectItemListView(); $can_manage = $this->hasApplicationCapability( AuthManageProvidersCapability::CAPABILITY); foreach ($configs as $config) { $item = new PHUIObjectItemView(); $id = $config->getID(); - $edit_uri = $this->getApplicationURI('config/edit/'.$id.'/'); - $enable_uri = $this->getApplicationURI('config/enable/'.$id.'/'); - $disable_uri = $this->getApplicationURI('config/disable/'.$id.'/'); + $view_uri = $config->getURI(); $provider = $config->getProvider(); - if ($provider) { - $name = $provider->getProviderName(); - } else { - $name = $config->getProviderType().' ('.$config->getProviderClass().')'; - } - - $item->setHeader($name); + $name = $provider->getProviderName(); - if ($provider) { - $item->setHref($edit_uri); - } else { - $item->addAttribute(pht('Provider Implementation Missing!')); - } + $item + ->setHeader($name) + ->setHref($view_uri); - $domain = null; - if ($provider) { - $domain = $provider->getProviderDomain(); - if ($domain !== 'self') { - $item->addAttribute($domain); - } + $domain = $provider->getProviderDomain(); + if ($domain !== 'self') { + $item->addAttribute($domain); } if ($config->getShouldAllowRegistration()) { $item->addAttribute(pht('Allows Registration')); } else { $item->addAttribute(pht('Does Not Allow Registration')); } if ($config->getIsEnabled()) { $item->setStatusIcon('fa-check-circle green'); - $item->addAction( - id(new PHUIListItemView()) - ->setIcon('fa-times') - ->setHref($disable_uri) - ->setDisabled(!$can_manage) - ->addSigil('workflow')); } else { $item->setStatusIcon('fa-ban red'); $item->addIcon('fa-ban grey', pht('Disabled')); - $item->addAction( - id(new PHUIListItemView()) - ->setIcon('fa-plus') - ->setHref($enable_uri) - ->setDisabled(!$can_manage) - ->addSigil('workflow')); } $list->addItem($item); } $list->setNoDataString( pht( '%s You have not added authentication providers yet. Use "%s" to add '. 'a provider, which will let users register new Phabricator accounts '. 'and log in.', phutil_tag( 'strong', array(), pht('No Providers Configured:')), phutil_tag( 'a', array( 'href' => $this->getApplicationURI('config/new/'), ), pht('Add Authentication Provider')))); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Login and Registration')); $crumbs->setBorder(true); $guidance_context = new PhabricatorAuthProvidersGuidanceContext(); $guidance = id(new PhabricatorGuidanceEngine()) ->setViewer($viewer) ->setGuidanceContext($guidance_context) ->newInfoView(); $button = id(new PHUIButtonView()) ->setTag('a') ->setButtonType(PHUIButtonView::BUTTONTYPE_SIMPLE) ->setHref($this->getApplicationURI('config/new/')) ->setIcon('fa-plus') ->setDisabled(!$can_manage) ->setText(pht('Add Provider')); $list->setFlush(true); $list = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Providers')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->appendChild($list); $title = pht('Login and Registration Providers'); $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon('fa-key') ->addActionLink($button); $view = id(new PHUITwoColumnView()) ->setHeader($header) - ->setFooter(array( - $guidance, - $list, - )); + ->setFooter( + array( + $guidance, + $list, + )); $nav = $this->newNavigation() ->setCrumbs($crumbs) ->appendChild($view); $nav->selectFilter('login'); return $this->newPage() ->setTitle($title) ->appendChild($nav); } } diff --git a/src/applications/auth/controller/config/PhabricatorAuthNewController.php b/src/applications/auth/controller/config/PhabricatorAuthNewController.php index dbd43f9ea8..c8fd0ad8a5 100644 --- a/src/applications/auth/controller/config/PhabricatorAuthNewController.php +++ b/src/applications/auth/controller/config/PhabricatorAuthNewController.php @@ -1,111 +1,74 @@ requireApplicationCapability( AuthManageProvidersCapability::CAPABILITY); - $request = $this->getRequest(); - $viewer = $request->getUser(); - $providers = PhabricatorAuthProvider::getAllBaseProviders(); - - $e_provider = null; - $errors = array(); - - if ($request->isFormPost()) { - $provider_string = $request->getStr('provider'); - if (!strlen($provider_string)) { - $e_provider = pht('Required'); - $errors[] = pht('You must select an authentication provider.'); - } else { - $found = false; - foreach ($providers as $provider) { - if (get_class($provider) === $provider_string) { - $found = true; - break; - } - } - if (!$found) { - $e_provider = pht('Invalid'); - $errors[] = pht('You must select a valid provider.'); - } - } + $viewer = $this->getViewer(); + $cancel_uri = $this->getApplicationURI(); - if (!$errors) { - return id(new AphrontRedirectResponse())->setURI( - $this->getApplicationURI('/config/new/'.$provider_string.'/')); - } - } - - $options = id(new AphrontFormRadioButtonControl()) - ->setLabel(pht('Provider')) - ->setName('provider') - ->setError($e_provider); + $providers = PhabricatorAuthProvider::getAllBaseProviders(); $configured = PhabricatorAuthProvider::getAllProviders(); $configured_classes = array(); foreach ($configured as $configured_provider) { $configured_classes[get_class($configured_provider)] = true; } // Sort providers by login order, and move disabled providers to the // bottom. $providers = msort($providers, 'getLoginOrder'); $providers = array_diff_key($providers, $configured_classes) + $providers; - foreach ($providers as $provider) { - if (isset($configured_classes[get_class($provider)])) { - $disabled = true; - $description = pht('This provider is already configured.'); + $menu = id(new PHUIObjectItemListView()) + ->setViewer($viewer) + ->setBig(true) + ->setFlush(true); + + foreach ($providers as $provider_key => $provider) { + $provider_class = get_class($provider); + + $provider_uri = id(new PhutilURI('/config/edit/')) + ->setQueryParam('provider', $provider_class); + $provider_uri = $this->getApplicationURI($provider_uri); + + $already_exists = isset($configured_classes[get_class($provider)]); + + $item = id(new PHUIObjectItemView()) + ->setHeader($provider->getNameForCreate()) + ->setImageIcon($provider->newIconView()) + ->addAttribute($provider->getDescriptionForCreate()); + + if (!$already_exists) { + $item + ->setHref($provider_uri) + ->setClickable(true); } else { - $disabled = false; - $description = $provider->getDescriptionForCreate(); + $item->setDisabled(true); } - $options->addButton( - get_class($provider), - $provider->getNameForCreate(), - $description, - $disabled ? 'disabled' : null, - $disabled); - } - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->appendChild($options) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($this->getApplicationURI()) - ->setValue(pht('Continue'))); - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Provider')) - ->setFormErrors($errors) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($form); - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb(pht('Add Provider')); - $crumbs->setBorder(true); - - $title = pht('Add Auth Provider'); - - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon('fa-plus-square'); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter(array( - $form_box, - )); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); + if ($already_exists) { + $messages = array(); + $messages[] = pht('You already have a provider of this type.'); + + $info = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) + ->setErrors($messages); + + $item->appendChild($info); + } + + $menu->addItem($item); + } + return $this->newDialog() + ->setTitle(pht('Add Auth Provider')) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->appendChild($menu) + ->addCancelButton($cancel_uri); } } diff --git a/src/applications/auth/controller/config/PhabricatorAuthProviderViewController.php b/src/applications/auth/controller/config/PhabricatorAuthProviderViewController.php new file mode 100644 index 0000000000..532744001c --- /dev/null +++ b/src/applications/auth/controller/config/PhabricatorAuthProviderViewController.php @@ -0,0 +1,119 @@ +requireApplicationCapability( + AuthManageProvidersCapability::CAPABILITY); + + $viewer = $this->getViewer(); + $id = $request->getURIData('id'); + + $config = id(new PhabricatorAuthProviderConfigQuery()) + ->setViewer($viewer) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->withIDs(array($id)) + ->executeOne(); + if (!$config) { + return new Aphront404Response(); + } + + $header = $this->buildHeaderView($config); + $properties = $this->buildPropertiesView($config); + $curtain = $this->buildCurtain($config); + + $timeline = $this->buildTransactionTimeline( + $config, + new PhabricatorAuthProviderConfigTransactionQuery()); + $timeline->setShouldTerminate(true); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setCurtain($curtain) + ->addPropertySection(pht('Details'), $properties) + ->setMainColumn($timeline); + + $crumbs = $this->buildApplicationCrumbs() + ->addTextCrumb($config->getObjectName()) + ->setBorder(true); + + return $this->newPage() + ->setTitle(pht('Auth Provider: %s', $config->getDisplayName())) + ->setCrumbs($crumbs) + ->appendChild($view); + } + + private function buildHeaderView(PhabricatorAuthProviderConfig $config) { + $viewer = $this->getViewer(); + + $view = id(new PHUIHeaderView()) + ->setViewer($viewer) + ->setHeader($config->getDisplayName()); + + if ($config->getIsEnabled()) { + $view->setStatus('fa-check', 'bluegrey', pht('Enabled')); + } else { + $view->setStatus('fa-ban', 'red', pht('Disabled')); + } + + return $view; + } + + private function buildCurtain(PhabricatorAuthProviderConfig $config) { + $viewer = $this->getViewer(); + $id = $config->getID(); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $config, + PhabricatorPolicyCapability::CAN_EDIT); + + $curtain = $this->newCurtainView($config); + + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Auth Provider')) + ->setIcon('fa-pencil') + ->setHref($this->getApplicationURI("config/edit/{$id}/")) + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit)); + + if ($config->getIsEnabled()) { + $disable_uri = $this->getApplicationURI('config/disable/'.$id.'/'); + $disable_icon = 'fa-ban'; + $disable_text = pht('Disable Provider'); + } else { + $disable_uri = $this->getApplicationURI('config/enable/'.$id.'/'); + $disable_icon = 'fa-check'; + $disable_text = pht('Enable Provider'); + } + + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName($disable_text) + ->setIcon($disable_icon) + ->setHref($disable_uri) + ->setDisabled(!$can_edit) + ->setWorkflow(true)); + + return $curtain; + } + + private function buildPropertiesView(PhabricatorAuthProviderConfig $config) { + $viewer = $this->getViewer(); + + $view = id(new PHUIPropertyListView()) + ->setViewer($viewer); + + $view->addProperty( + pht('Provider Type'), + $config->getProvider()->getProviderName()); + + return $view; + } +} diff --git a/src/applications/auth/factor/PhabricatorAuthFactor.php b/src/applications/auth/factor/PhabricatorAuthFactor.php index ec49f7f748..912a2c31c9 100644 --- a/src/applications/auth/factor/PhabricatorAuthFactor.php +++ b/src/applications/auth/factor/PhabricatorAuthFactor.php @@ -1,566 +1,579 @@ getID().'.'.$name; } public static function getAllFactors() { return id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) ->setUniqueMethod('getFactorKey') ->execute(); } protected function newConfigForUser(PhabricatorUser $user) { return id(new PhabricatorAuthFactorConfig()) ->setUserPHID($user->getPHID()) ->setFactorSecret(''); } protected function newResult() { return new PhabricatorAuthFactorResult(); } public function newIconView() { return id(new PHUIIconView()) ->setIcon('fa-mobile'); } public function canCreateNewProvider() { return true; } public function getProviderCreateDescription() { return null; } public function canCreateNewConfiguration( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { return true; } public function getConfigurationCreateDescription( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { return null; } public function getConfigurationListDetails( PhabricatorAuthFactorConfig $config, PhabricatorAuthFactorProvider $provider, PhabricatorUser $viewer) { return null; } public function newEditEngineFields( PhabricatorEditEngine $engine, PhabricatorAuthFactorProvider $provider) { return array(); } /** * Is this a factor which depends on the user's contact number? * * If a user has a "contact number" factor configured, they can not modify * or switch their primary contact number. * * @return bool True if this factor should lock contact numbers. */ public function isContactNumberFactor() { return false; } abstract public function getEnrollDescription( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user); public function getEnrollButtonText( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { return pht('Continue'); } public function getFactorOrder() { return 1000; } final public function newSortVector() { return id(new PhutilSortVector()) ->addInt($this->canCreateNewProvider() ? 0 : 1) ->addInt($this->getFactorOrder()) ->addString($this->getFactorName()); } protected function newChallenge( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer) { $engine = $config->getSessionEngine(); return PhabricatorAuthChallenge::initializeNewChallenge() ->setUserPHID($viewer->getPHID()) ->setSessionPHID($viewer->getSession()->getPHID()) ->setFactorPHID($config->getPHID()) + ->setIsNewChallenge(true) ->setWorkflowKey($engine->getWorkflowKey()); } abstract public function getRequestHasChallengeResponse( PhabricatorAuthFactorConfig $config, AphrontRequest $response); final public function getNewIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { assert_instances_of($challenges, 'PhabricatorAuthChallenge'); $now = PhabricatorTime::getNow(); // Factor implementations may need to perform writes in order to issue // challenges, particularly push factors like SMS. $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $new_challenges = $this->newIssuedChallenges( $config, $viewer, $challenges); if ($this->isAuthResult($new_challenges)) { unset($unguarded); return $new_challenges; } assert_instances_of($new_challenges, 'PhabricatorAuthChallenge'); foreach ($new_challenges as $new_challenge) { $ttl = $new_challenge->getChallengeTTL(); if (!$ttl) { throw new Exception( pht('Newly issued MFA challenges must have a valid TTL!')); } if ($ttl < $now) { throw new Exception( pht( 'Newly issued MFA challenges must have a future TTL. This '. 'factor issued a bad TTL ("%s"). (Did you use a relative '. 'time instead of an epoch?)', $ttl)); } } foreach ($new_challenges as $challenge) { $challenge->save(); } unset($unguarded); return $new_challenges; } abstract protected function newIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges); final public function getResultFromIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { assert_instances_of($challenges, 'PhabricatorAuthChallenge'); $result = $this->newResultFromIssuedChallenges( $config, $viewer, $challenges); if ($result === null) { return $result; } if (!$this->isAuthResult($result)) { throw new Exception( pht( 'Expected "newResultFromIssuedChallenges()" to return null or '. 'an object of class "%s"; got something else (in "%s").', 'PhabricatorAuthFactorResult', get_class($this))); } $result->setIssuedChallenges($challenges); return $result; } abstract protected function newResultFromIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges); final public function getResultFromChallengeResponse( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, AphrontRequest $request, array $challenges) { assert_instances_of($challenges, 'PhabricatorAuthChallenge'); $result = $this->newResultFromChallengeResponse( $config, $viewer, $request, $challenges); if (!$this->isAuthResult($result)) { throw new Exception( pht( 'Expected "newResultFromChallengeResponse()" to return an object '. 'of class "%s"; got something else (in "%s").', 'PhabricatorAuthFactorResult', get_class($this))); } $result->setIssuedChallenges($challenges); return $result; } abstract protected function newResultFromChallengeResponse( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, AphrontRequest $request, array $challenges); final protected function newAutomaticControl( PhabricatorAuthFactorResult $result) { $is_error = $result->getIsError(); if ($is_error) { return $this->newErrorControl($result); } $is_continue = $result->getIsContinue(); if ($is_continue) { return $this->newContinueControl($result); } $is_answered = (bool)$result->getAnsweredChallenge(); if ($is_answered) { return $this->newAnsweredControl($result); } $is_wait = $result->getIsWait(); if ($is_wait) { return $this->newWaitControl($result); } return null; } private function newWaitControl( PhabricatorAuthFactorResult $result) { $error = $result->getErrorMessage(); - $icon = id(new PHUIIconView()) - ->setIcon('fa-clock-o', 'red'); + $icon = $result->getIcon(); + if (!$icon) { + $icon = id(new PHUIIconView()) + ->setIcon('fa-clock-o', 'red'); + } return id(new PHUIFormTimerControl()) ->setIcon($icon) ->appendChild($error) ->setError(pht('Wait')); } private function newAnsweredControl( PhabricatorAuthFactorResult $result) { - $icon = id(new PHUIIconView()) - ->setIcon('fa-check-circle-o', 'green'); + $icon = $result->getIcon(); + if (!$icon) { + $icon = id(new PHUIIconView()) + ->setIcon('fa-check-circle-o', 'green'); + } return id(new PHUIFormTimerControl()) ->setIcon($icon) ->appendChild( pht('You responded to this challenge correctly.')); } private function newErrorControl( PhabricatorAuthFactorResult $result) { $error = $result->getErrorMessage(); - $icon = id(new PHUIIconView()) - ->setIcon('fa-times', 'red'); + $icon = $result->getIcon(); + if (!$icon) { + $icon = id(new PHUIIconView()) + ->setIcon('fa-times', 'red'); + } return id(new PHUIFormTimerControl()) ->setIcon($icon) ->appendChild($error) ->setError(pht('Error')); } private function newContinueControl( PhabricatorAuthFactorResult $result) { $error = $result->getErrorMessage(); - $icon = id(new PHUIIconView()) - ->setIcon('fa-commenting', 'green'); + $icon = $result->getIcon(); + if (!$icon) { + $icon = id(new PHUIIconView()) + ->setIcon('fa-commenting', 'green'); + } return id(new PHUIFormTimerControl()) ->setIcon($icon) ->appendChild($error); } /* -( Synchronizing New Factors )------------------------------------------ */ final protected function loadMFASyncToken( PhabricatorAuthFactorProvider $provider, AphrontRequest $request, AphrontFormView $form, PhabricatorUser $user) { // If the form included a synchronization key, load the corresponding // token. The user must synchronize to a key we generated because this // raises the barrier to theoretical attacks where an attacker might // provide a known key for factors like TOTP. // (We store and verify the hash of the key, not the key itself, to limit // how useful the data in the table is to an attacker.) $sync_type = PhabricatorAuthMFASyncTemporaryTokenType::TOKENTYPE; $sync_token = null; $sync_key = $request->getStr($this->getMFASyncTokenFormKey()); if (strlen($sync_key)) { $sync_key_digest = PhabricatorHash::digestWithNamedKey( $sync_key, PhabricatorAuthMFASyncTemporaryTokenType::DIGEST_KEY); $sync_token = id(new PhabricatorAuthTemporaryTokenQuery()) ->setViewer($user) ->withTokenResources(array($user->getPHID())) ->withTokenTypes(array($sync_type)) ->withExpired(false) ->withTokenCodes(array($sync_key_digest)) ->executeOne(); } if (!$sync_token) { // Don't generate a new sync token if there are too many outstanding // tokens already. This is mostly relevant for push factors like SMS, // where generating a token has the side effect of sending a user a // message. $outstanding_limit = 10; $outstanding_tokens = id(new PhabricatorAuthTemporaryTokenQuery()) ->setViewer($user) ->withTokenResources(array($user->getPHID())) ->withTokenTypes(array($sync_type)) ->withExpired(false) ->execute(); if (count($outstanding_tokens) > $outstanding_limit) { throw new Exception( pht( 'Your account has too many outstanding, incomplete MFA '. 'synchronization attempts. Wait an hour and try again.')); } $now = PhabricatorTime::getNow(); $sync_key = Filesystem::readRandomCharacters(32); $sync_key_digest = PhabricatorHash::digestWithNamedKey( $sync_key, PhabricatorAuthMFASyncTemporaryTokenType::DIGEST_KEY); $sync_ttl = $this->getMFASyncTokenTTL(); $sync_token = id(new PhabricatorAuthTemporaryToken()) ->setIsNewTemporaryToken(true) ->setTokenResource($user->getPHID()) ->setTokenType($sync_type) ->setTokenCode($sync_key_digest) ->setTokenExpires($now + $sync_ttl); $properties = $this->newMFASyncTokenProperties( $provider, $user); if ($this->isAuthResult($properties)) { return $properties; } foreach ($properties as $key => $value) { $sync_token->setTemporaryTokenProperty($key, $value); } $sync_token->save(); } $form->addHiddenInput($this->getMFASyncTokenFormKey(), $sync_key); return $sync_token; } protected function newMFASyncTokenProperties( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { return array(); } private function getMFASyncTokenFormKey() { return 'sync.key'; } private function getMFASyncTokenTTL() { return phutil_units('1 hour in seconds'); } final protected function getChallengeForCurrentContext( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { $session_phid = $viewer->getSession()->getPHID(); $engine = $config->getSessionEngine(); $workflow_key = $engine->getWorkflowKey(); foreach ($challenges as $challenge) { if ($challenge->getSessionPHID() !== $session_phid) { continue; } if ($challenge->getWorkflowKey() !== $workflow_key) { continue; } if ($challenge->getIsCompleted()) { continue; } if ($challenge->getIsReusedChallenge()) { continue; } return $challenge; } return null; } /** * @phutil-external-symbol class QRcode */ final protected function newQRCode($uri) { $root = dirname(phutil_get_library_root('phabricator')); require_once $root.'/externals/phpqrcode/phpqrcode.php'; $lines = QRcode::text($uri); $total_width = 240; $cell_size = floor($total_width / count($lines)); $rows = array(); foreach ($lines as $line) { $cells = array(); for ($ii = 0; $ii < strlen($line); $ii++) { if ($line[$ii] == '1') { $color = '#000'; } else { $color = '#fff'; } $cells[] = phutil_tag( 'td', array( 'width' => $cell_size, 'height' => $cell_size, 'style' => 'background: '.$color, ), ''); } $rows[] = phutil_tag('tr', array(), $cells); } return phutil_tag( 'table', array( 'style' => 'margin: 24px auto;', ), $rows); } final protected function getInstallDisplayName() { $uri = PhabricatorEnv::getURI('/'); $uri = new PhutilURI($uri); return $uri->getDomain(); } final protected function getChallengeResponseParameterName( PhabricatorAuthFactorConfig $config) { return $this->getParameterName($config, 'mfa.response'); } final protected function getChallengeResponseFromRequest( PhabricatorAuthFactorConfig $config, AphrontRequest $request) { $name = $this->getChallengeResponseParameterName($config); $value = $request->getStr($name); $value = (string)$value; $value = trim($value); return $value; } final protected function hasCSRF(PhabricatorAuthFactorConfig $config) { $engine = $config->getSessionEngine(); $request = $engine->getRequest(); if (!$request->isHTTPPost()) { return false; } return $request->validateCSRF(); } final protected function loadConfigurationsForProvider( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { return id(new PhabricatorAuthFactorConfigQuery()) ->setViewer($user) ->withUserPHIDs(array($user->getPHID())) ->withFactorProviderPHIDs(array($provider->getPHID())) ->execute(); } final protected function isAuthResult($object) { return ($object instanceof PhabricatorAuthFactorResult); } } diff --git a/src/applications/auth/factor/PhabricatorAuthFactorResult.php b/src/applications/auth/factor/PhabricatorAuthFactorResult.php index 2282f162a9..f03c3674da 100644 --- a/src/applications/auth/factor/PhabricatorAuthFactorResult.php +++ b/src/applications/auth/factor/PhabricatorAuthFactorResult.php @@ -1,95 +1,105 @@ getIsAnsweredChallenge()) { throw new PhutilInvalidStateException('markChallengeAsAnswered'); } if ($challenge->getIsCompleted()) { throw new Exception( pht( 'A completed challenge was provided as an answered challenge. '. 'The underlying factor is implemented improperly, challenges '. 'may not be reused.')); } $this->answeredChallenge = $challenge; return $this; } public function getAnsweredChallenge() { return $this->answeredChallenge; } public function getIsValid() { return (bool)$this->getAnsweredChallenge(); } public function setIsWait($is_wait) { $this->isWait = $is_wait; return $this; } public function getIsWait() { return $this->isWait; } public function setIsError($is_error) { $this->isError = $is_error; return $this; } public function getIsError() { return $this->isError; } public function setIsContinue($is_continue) { $this->isContinue = $is_continue; return $this; } public function getIsContinue() { return $this->isContinue; } public function setErrorMessage($error_message) { $this->errorMessage = $error_message; return $this; } public function getErrorMessage() { return $this->errorMessage; } public function setValue($value) { $this->value = $value; return $this; } public function getValue() { return $this->value; } public function setIssuedChallenges(array $issued_challenges) { assert_instances_of($issued_challenges, 'PhabricatorAuthChallenge'); $this->issuedChallenges = $issued_challenges; return $this; } public function getIssuedChallenges() { return $this->issuedChallenges; } + public function setIcon(PHUIIconView $icon) { + $this->icon = $icon; + return $this; + } + + public function getIcon() { + return $this->icon; + } + } diff --git a/src/applications/auth/factor/PhabricatorDuoAuthFactor.php b/src/applications/auth/factor/PhabricatorDuoAuthFactor.php index 187e011953..4be4c15ea8 100644 --- a/src/applications/auth/factor/PhabricatorDuoAuthFactor.php +++ b/src/applications/auth/factor/PhabricatorDuoAuthFactor.php @@ -1,813 +1,793 @@ loadConfigurationsForProvider($provider, $user)) { return false; } return true; } public function getConfigurationCreateDescription( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { $messages = array(); if ($this->loadConfigurationsForProvider($provider, $user)) { $messages[] = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setErrors( array( pht( 'You already have Duo authentication attached to your account '. 'for this provider.'), )); } return $messages; } public function getConfigurationListDetails( PhabricatorAuthFactorConfig $config, PhabricatorAuthFactorProvider $provider, PhabricatorUser $viewer) { $duo_user = $config->getAuthFactorConfigProperty('duo.username'); return pht('Duo Username: %s', $duo_user); } public function newEditEngineFields( PhabricatorEditEngine $engine, PhabricatorAuthFactorProvider $provider) { $viewer = $engine->getViewer(); $credential_phid = $provider->getAuthFactorProviderProperty( self::PROP_CREDENTIAL); $hostname = $provider->getAuthFactorProviderProperty(self::PROP_HOSTNAME); $usernames = $provider->getAuthFactorProviderProperty(self::PROP_USERNAMES); $enroll = $provider->getAuthFactorProviderProperty(self::PROP_ENROLL); $credential_type = PassphrasePasswordCredentialType::CREDENTIAL_TYPE; $provides_type = PassphrasePasswordCredentialType::PROVIDES_TYPE; $credentials = id(new PassphraseCredentialQuery()) ->setViewer($viewer) ->withIsDestroyed(false) ->withProvidesTypes(array($provides_type)) ->execute(); $xaction_hostname = PhabricatorAuthFactorProviderDuoHostnameTransaction::TRANSACTIONTYPE; $xaction_credential = PhabricatorAuthFactorProviderDuoCredentialTransaction::TRANSACTIONTYPE; $xaction_usernames = PhabricatorAuthFactorProviderDuoUsernamesTransaction::TRANSACTIONTYPE; $xaction_enroll = PhabricatorAuthFactorProviderDuoEnrollTransaction::TRANSACTIONTYPE; return array( id(new PhabricatorTextEditField()) ->setLabel(pht('Duo API Hostname')) ->setKey('duo.hostname') ->setValue($hostname) ->setTransactionType($xaction_hostname) ->setIsRequired(true), id(new PhabricatorCredentialEditField()) ->setLabel(pht('Duo API Credential')) ->setKey('duo.credential') ->setValue($credential_phid) ->setTransactionType($xaction_credential) ->setCredentialType($credential_type) ->setCredentials($credentials), id(new PhabricatorSelectEditField()) ->setLabel(pht('Duo Username')) ->setKey('duo.usernames') ->setValue($usernames) ->setTransactionType($xaction_usernames) ->setOptions( array( 'username' => pht('Use Phabricator Username'), 'email' => pht('Use Primary Email Address'), )), id(new PhabricatorSelectEditField()) ->setLabel(pht('Create Accounts')) ->setKey('duo.enroll') ->setValue($enroll) ->setTransactionType($xaction_enroll) ->setOptions( array( 'deny' => pht('Require Existing Duo Account'), 'allow' => pht('Create New Duo Account'), )), ); } public function processAddFactorForm( PhabricatorAuthFactorProvider $provider, AphrontFormView $form, AphrontRequest $request, PhabricatorUser $user) { $token = $this->loadMFASyncToken($provider, $request, $form, $user); if ($this->isAuthResult($token)) { $form->appendChild($this->newAutomaticControl($token)); return; } $enroll = $token->getTemporaryTokenProperty('duo.enroll'); $duo_id = $token->getTemporaryTokenProperty('duo.user-id'); $duo_uri = $token->getTemporaryTokenProperty('duo.uri'); $duo_user = $token->getTemporaryTokenProperty('duo.username'); $is_external = ($enroll === 'external'); $is_auto = ($enroll === 'auto'); $is_blocked = ($enroll === 'blocked'); if (!$token->getIsNewTemporaryToken()) { if ($is_auto) { return $this->newDuoConfig($user, $duo_user); } else if ($is_external || $is_blocked) { $parameters = array( 'username' => $duo_user, ); $result = $this->newDuoFuture($provider) ->setMethod('preauth', $parameters) ->resolve(); $result_code = $result['response']['result']; switch ($result_code) { case 'auth': case 'allow': return $this->newDuoConfig($user, $duo_user); case 'enroll': if ($is_blocked) { // We'll render an equivalent static control below, so skip // rendering here. We explicitly don't want to give the user // an enroll workflow. break; } $duo_uri = $result['response']['enroll_portal_url']; $waiting_icon = id(new PHUIIconView()) ->setIcon('fa-mobile', 'red'); $waiting_control = id(new PHUIFormTimerControl()) ->setIcon($waiting_icon) ->setError(pht('Not Complete')) ->appendChild( pht( 'You have not completed Duo enrollment yet. '. 'Complete enrollment, then click continue.')); $form->appendControl($waiting_control); break; default: case 'deny': break; } } else { $parameters = array( 'user_id' => $duo_id, 'activation_code' => $duo_uri, ); $future = $this->newDuoFuture($provider) ->setMethod('enroll_status', $parameters); $result = $future->resolve(); $response = $result['response']; switch ($response) { case 'success': return $this->newDuoConfig($user, $duo_user); case 'waiting': $waiting_icon = id(new PHUIIconView()) ->setIcon('fa-mobile', 'red'); $waiting_control = id(new PHUIFormTimerControl()) ->setIcon($waiting_icon) ->setError(pht('Not Complete')) ->appendChild( pht( 'You have not activated this enrollment in the Duo '. 'application on your phone yet. Complete activation, then '. 'click continue.')); $form->appendControl($waiting_control); break; case 'invalid': default: throw new Exception( pht( 'This Duo enrollment attempt is invalid or has '. 'expired ("%s"). Cancel the workflow and try again.', $response)); } } } if ($is_blocked) { $blocked_icon = id(new PHUIIconView()) ->setIcon('fa-times', 'red'); $blocked_control = id(new PHUIFormTimerControl()) ->setIcon($blocked_icon) ->appendChild( pht( 'Your Duo account ("%s") has not completed Duo enrollment. '. 'Check your email and complete enrollment to continue.', phutil_tag('strong', array(), $duo_user))); $form->appendControl($blocked_control); } else if ($is_auto) { $auto_icon = id(new PHUIIconView()) ->setIcon('fa-check', 'green'); $auto_control = id(new PHUIFormTimerControl()) ->setIcon($auto_icon) ->appendChild( pht( 'Duo account ("%s") is fully enrolled.', phutil_tag('strong', array(), $duo_user))); $form->appendControl($auto_control); } else { $duo_button = phutil_tag( 'a', array( 'href' => $duo_uri, 'class' => 'button button-grey', 'target' => ($is_external ? '_blank' : null), ), pht('Enroll Duo Account: %s', $duo_user)); $duo_button = phutil_tag( 'div', array( 'class' => 'mfa-form-enroll-button', ), $duo_button); if ($is_external) { $form->appendRemarkupInstructions( pht( 'Complete enrolling your phone with Duo:')); $form->appendControl( id(new AphrontFormMarkupControl()) ->setValue($duo_button)); } else { $form->appendRemarkupInstructions( pht( 'Scan this QR code with the Duo application on your mobile '. 'phone:')); $qr_code = $this->newQRCode($duo_uri); $form->appendChild($qr_code); $form->appendRemarkupInstructions( pht( 'If you are currently using your phone to view this page, '. 'click this button to open the Duo application:')); $form->appendControl( id(new AphrontFormMarkupControl()) ->setValue($duo_button)); } $form->appendRemarkupInstructions( pht( 'Once you have completed setup on your phone, click continue.')); } } protected function newMFASyncTokenProperties( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { $duo_user = $this->getDuoUsername($provider, $user); // Duo automatically normalizes usernames to lowercase. Just do that here // so that our value agrees more closely with Duo. $duo_user = phutil_utf8_strtolower($duo_user); $parameters = array( 'username' => $duo_user, ); $result = $this->newDuoFuture($provider) ->setMethod('preauth', $parameters) ->resolve(); $external_uri = null; $result_code = $result['response']['result']; $status_message = $result['response']['status_msg']; switch ($result_code) { case 'auth': case 'allow': // If the user already has a Duo account, they don't need to do // anything. return array( 'duo.enroll' => 'auto', 'duo.username' => $duo_user, ); case 'enroll': if (!$this->shouldAllowDuoEnrollment($provider)) { return array( 'duo.enroll' => 'blocked', 'duo.username' => $duo_user, ); } $external_uri = $result['response']['enroll_portal_url']; // Otherwise, enrollment is permitted so we're going to continue. break; default: case 'deny': return $this->newResult() ->setIsError(true) ->setErrorMessage( pht( 'Your Duo account ("%s") is not permitted to access this '. 'system. Contact your Duo administrator for help. '. 'The Duo preauth API responded with status message ("%s"): %s', $duo_user, $result_code, $status_message)); } // Duo's "/enroll" API isn't repeatable for the same username. If we're // the first call, great: we can do inline enrollment, which is way more // user friendly. Otherwise, we have to send the user on an adventure. $parameters = array( 'username' => $duo_user, 'valid_secs' => phutil_units('1 hour in seconds'), ); try { $result = $this->newDuoFuture($provider) ->setMethod('enroll', $parameters) ->resolve(); } catch (HTTPFutureHTTPResponseStatus $ex) { return array( 'duo.enroll' => 'external', 'duo.username' => $duo_user, 'duo.uri' => $external_uri, ); } return array( 'duo.enroll' => 'inline', 'duo.uri' => $result['response']['activation_code'], 'duo.username' => $duo_user, 'duo.user-id' => $result['response']['user_id'], ); } protected function newIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { // If we already issued a valid challenge for this workflow and session, // don't issue a new one. $challenge = $this->getChallengeForCurrentContext( $config, $viewer, $challenges); if ($challenge) { return array(); } if (!$this->hasCSRF($config)) { return $this->newResult() ->setIsContinue(true) ->setErrorMessage( pht( 'An authorization request will be pushed to the Duo '. 'application on your phone.')); } $provider = $config->getFactorProvider(); // Otherwise, issue a new challenge. $duo_user = (string)$config->getAuthFactorConfigProperty('duo.username'); $parameters = array( 'username' => $duo_user, ); $response = $this->newDuoFuture($provider) ->setMethod('preauth', $parameters) ->resolve(); $response = $response['response']; $next_step = $response['result']; $status_message = $response['status_msg']; switch ($next_step) { case 'auth': // We're good to go. break; case 'allow': // Duo is telling us to bypass MFA. For now, refuse. return $this->newResult() ->setIsError(true) ->setErrorMessage( pht( 'Duo is not requiring a challenge, which defeats the '. 'purpose of MFA. Duo must be configured to challenge you.')); case 'enroll': return $this->newResult() ->setIsError(true) ->setErrorMessage( pht( 'Your Duo account ("%s") requires enrollment. Contact your '. 'Duo administrator for help. Duo status message: %s', $duo_user, $status_message)); case 'deny': default: return $this->newResult() ->setIsError(true) ->setErrorMessage( pht( 'Your Duo account ("%s") is not permitted to access this '. 'system. Contact your Duo administrator for help. The Duo '. 'preauth API responded with status message ("%s"): %s', $duo_user, $next_step, $status_message)); } $has_push = false; $devices = $response['devices']; foreach ($devices as $device) { $capabilities = array_fuse($device['capabilities']); if (isset($capabilities['push'])) { $has_push = true; break; } } if (!$has_push) { return $this->newResult() ->setIsError(true) ->setErrorMessage( pht( 'This factor has been removed from your device, so Phabricator '. 'can not send you a challenge. To continue, an administrator '. 'must strip this factor from your account.')); } $push_info = array( pht('Domain') => $this->getInstallDisplayName(), ); $push_info = phutil_build_http_querystring($push_info); $parameters = array( 'username' => $duo_user, 'factor' => 'push', 'async' => '1', // Duo allows us to specify a device, or to pass "auto" to have it pick // the first one. For now, just let it pick. 'device' => 'auto', // This is a hard-coded prefix for the word "... request" in the Duo UI, // which defaults to "Login". We could pass richer information from // workflows here, but it's not very flexible anyway. 'type' => 'Authentication', 'display_username' => $viewer->getUsername(), 'pushinfo' => $push_info, ); $result = $this->newDuoFuture($provider) ->setMethod('auth', $parameters) ->resolve(); $duo_xaction = $result['response']['txid']; // The Duo push timeout is 60 seconds. Set our challenge to expire slightly // more quickly so that we'll re-issue a new challenge before Duo times out. // This should keep users away from a dead-end where they can't respond to // Duo but Phabricator won't issue a new challenge yet. $ttl_seconds = 55; return array( $this->newChallenge($config, $viewer) ->setChallengeKey($duo_xaction) ->setChallengeTTL(PhabricatorTime::getNow() + $ttl_seconds), ); } protected function newResultFromIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { $challenge = $this->getChallengeForCurrentContext( $config, $viewer, $challenges); if ($challenge->getIsAnsweredChallenge()) { return $this->newResult() ->setAnsweredChallenge($challenge); } $provider = $config->getFactorProvider(); $duo_xaction = $challenge->getChallengeKey(); $parameters = array( 'txid' => $duo_xaction, ); // This endpoint always long-polls, so use a timeout to force it to act // more asynchronously. try { $result = $this->newDuoFuture($provider) ->setHTTPMethod('GET') ->setMethod('auth_status', $parameters) ->setTimeout(5) ->resolve(); $state = $result['response']['result']; $status = $result['response']['status']; } catch (HTTPFutureCURLResponseStatus $exception) { if ($exception->isTimeout()) { $state = 'waiting'; $status = 'poll'; } else { throw $exception; } } $now = PhabricatorTime::getNow(); switch ($state) { case 'allow': $ttl = PhabricatorTime::getNow() + phutil_units('15 minutes in seconds'); $challenge ->markChallengeAsAnswered($ttl); return $this->newResult() ->setAnsweredChallenge($challenge); case 'waiting': - // No result yet, we'll render a default state later on. + // If we didn't just issue this challenge, give the user a stronger + // hint that they need to follow the instructions. + if (!$challenge->getIsNewChallenge()) { + return $this->newResult() + ->setIsContinue(true) + ->setIcon( + id(new PHUIIconView()) + ->setIcon('fa-exclamation-triangle', 'yellow')) + ->setErrorMessage( + pht( + 'You must approve the challenge which was sent to your '. + 'phone. Open the Duo application and confirm the challenge, '. + 'then continue.')); + } + + // Otherwise, we'll construct a default message later on. break; default: case 'deny': if ($status === 'timeout') { return $this->newResult() ->setIsError(true) ->setErrorMessage( pht( 'This request has timed out because you took too long to '. 'respond.')); } else { $wait_duration = ($challenge->getChallengeTTL() - $now) + 1; return $this->newResult() ->setIsWait(true) ->setErrorMessage( pht( 'You denied this request. Wait %s second(s) to try again.', new PhutilNumber($wait_duration))); } break; } return null; } public function renderValidateFactorForm( PhabricatorAuthFactorConfig $config, AphrontFormView $form, PhabricatorUser $viewer, PhabricatorAuthFactorResult $result) { $control = $this->newAutomaticControl($result); if (!$control) { $result = $this->newResult() ->setIsContinue(true) ->setErrorMessage( pht( 'A challenge has been sent to your phone. Open the Duo '. 'application and confirm the challenge, then continue.')); $control = $this->newAutomaticControl($result); } $control ->setLabel(pht('Duo')) ->setCaption(pht('Factor Name: %s', $config->getFactorName())); $form->appendChild($control); } public function getRequestHasChallengeResponse( PhabricatorAuthFactorConfig $config, AphrontRequest $request) { - $value = $this->getChallengeResponseFromRequest($config, $request); - return (bool)strlen($value); + return false; } protected function newResultFromChallengeResponse( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, AphrontRequest $request, array $challenges) { - - $challenge = $this->getChallengeForCurrentContext( - $config, - $viewer, - $challenges); - - $code = $this->getChallengeResponseFromRequest( - $config, - $request); - - $result = $this->newResult() - ->setValue($code); - - if ($challenge->getIsAnsweredChallenge()) { - return $result->setAnsweredChallenge($challenge); - } - - if (phutil_hashes_are_identical($code, $challenge->getChallengeKey())) { - $ttl = PhabricatorTime::getNow() + phutil_units('15 minutes in seconds'); - - $challenge - ->markChallengeAsAnswered($ttl); - - return $result->setAnsweredChallenge($challenge); - } - - if (strlen($code)) { - $error_message = pht('Invalid'); - } else { - $error_message = pht('Required'); - } - - $result->setErrorMessage($error_message); - - return $result; + return $this->newResult(); } private function newDuoFuture(PhabricatorAuthFactorProvider $provider) { $credential_phid = $provider->getAuthFactorProviderProperty( self::PROP_CREDENTIAL); $omnipotent = PhabricatorUser::getOmnipotentUser(); $credential = id(new PassphraseCredentialQuery()) ->setViewer($omnipotent) ->withPHIDs(array($credential_phid)) ->needSecrets(true) ->executeOne(); if (!$credential) { throw new Exception( pht( 'Unable to load Duo API credential ("%s").', $credential_phid)); } $duo_key = $credential->getUsername(); $duo_secret = $credential->getSecret(); if (!$duo_secret) { throw new Exception( pht( 'Duo API credential ("%s") has no secret key.', $credential_phid)); } $duo_host = $provider->getAuthFactorProviderProperty( self::PROP_HOSTNAME); self::requireDuoAPIHostname($duo_host); return id(new PhabricatorDuoFuture()) ->setIntegrationKey($duo_key) ->setSecretKey($duo_secret) ->setAPIHostname($duo_host) ->setTimeout(10) ->setHTTPMethod('POST'); } private function getDuoUsername( PhabricatorAuthFactorProvider $provider, PhabricatorUser $user) { $mode = $provider->getAuthFactorProviderProperty(self::PROP_USERNAMES); switch ($mode) { case 'username': return $user->getUsername(); case 'email': return $user->loadPrimaryEmailAddress(); default: throw new Exception( pht( 'Duo username pairing mode ("%s") is not supported.', $mode)); } } private function shouldAllowDuoEnrollment( PhabricatorAuthFactorProvider $provider) { $mode = $provider->getAuthFactorProviderProperty(self::PROP_ENROLL); switch ($mode) { case 'deny': return false; case 'allow': return true; default: throw new Exception( pht( 'Duo enrollment mode ("%s") is not supported.', $mode)); } } private function newDuoConfig(PhabricatorUser $user, $duo_user) { $config_properties = array( 'duo.username' => $duo_user, ); $config = $this->newConfigForUser($user) ->setFactorName(pht('Duo (%s)', $duo_user)) ->setProperties($config_properties); return $config; } public static function requireDuoAPIHostname($hostname) { if (preg_match('/\.duosecurity\.com\z/', $hostname)) { return; } throw new Exception( pht( 'Duo API hostname ("%s") is invalid, hostname must be '. '"*.duosecurity.com".', $hostname)); } } diff --git a/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php b/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php index ba6613c014..7e77dfc11a 100644 --- a/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php +++ b/src/applications/auth/factor/PhabricatorTOTPAuthFactor.php @@ -1,452 +1,453 @@ getFactorSecret()) * 8; return pht('%d-Bit Secret', $bits); } public function processAddFactorForm( PhabricatorAuthFactorProvider $provider, AphrontFormView $form, AphrontRequest $request, PhabricatorUser $user) { $sync_token = $this->loadMFASyncToken( $provider, $request, $form, $user); $secret = $sync_token->getTemporaryTokenProperty('secret'); $code = $request->getStr('totpcode'); $e_code = true; if (!$sync_token->getIsNewTemporaryToken()) { $okay = (bool)$this->getTimestepAtWhichResponseIsValid( $this->getAllowedTimesteps($this->getCurrentTimestep()), new PhutilOpaqueEnvelope($secret), $code); if ($okay) { $config = $this->newConfigForUser($user) ->setFactorName(pht('Mobile App (TOTP)')) ->setFactorSecret($secret) ->setMFASyncToken($sync_token); return $config; } else { if (!strlen($code)) { $e_code = pht('Required'); } else { $e_code = pht('Invalid'); } } } $form->appendInstructions( pht( 'Scan the QR code or manually enter the key shown below into the '. 'application.')); $prod_uri = new PhutilURI(PhabricatorEnv::getProductionURI('/')); $issuer = $prod_uri->getDomain(); $uri = urisprintf( 'otpauth://totp/%s:%s?secret=%s&issuer=%s', $issuer, $user->getUsername(), $secret, $issuer); $qrcode = $this->newQRCode($uri); $form->appendChild($qrcode); $form->appendChild( id(new AphrontFormStaticControl()) ->setLabel(pht('Key')) ->setValue(phutil_tag('strong', array(), $secret))); $form->appendInstructions( pht( '(If given an option, select that this key is "Time Based", not '. '"Counter Based".)')); $form->appendInstructions( pht( 'After entering the key, the application should display a numeric '. 'code. Enter that code below to confirm that you have configured '. 'the authenticator correctly:')); $form->appendChild( id(new PHUIFormNumberControl()) ->setLabel(pht('TOTP Code')) ->setName('totpcode') ->setValue($code) + ->setAutofocus(true) ->setError($e_code)); } protected function newIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { $current_step = $this->getCurrentTimestep(); // If we already issued a valid challenge, don't issue a new one. if ($challenges) { return array(); } // Otherwise, generate a new challenge for the current timestep and compute // the TTL. // When computing the TTL, note that we accept codes within a certain // window of the challenge timestep to account for clock skew and users // needing time to enter codes. // We don't want this challenge to expire until after all valid responses // to it are no longer valid responses to any other challenge we might // issue in the future. If the challenge expires too quickly, we may issue // a new challenge which can accept the same TOTP code response. // This means that we need to keep this challenge alive for double the // window size: if we're currently at timestep 3, the user might respond // with the code for timestep 5. This is valid, since timestep 5 is within // the window for timestep 3. // But the code for timestep 5 can be used to respond at timesteps 3, 4, 5, // 6, and 7. To prevent any valid response to this challenge from being // used again, we need to keep this challenge active until timestep 8. $window_size = $this->getTimestepWindowSize(); $step_duration = $this->getTimestepDuration(); $ttl_steps = ($window_size * 2) + 1; $ttl_seconds = ($ttl_steps * $step_duration); return array( $this->newChallenge($config, $viewer) ->setChallengeKey($current_step) ->setChallengeTTL(PhabricatorTime::getNow() + $ttl_seconds), ); } public function renderValidateFactorForm( PhabricatorAuthFactorConfig $config, AphrontFormView $form, PhabricatorUser $viewer, PhabricatorAuthFactorResult $result) { $control = $this->newAutomaticControl($result); if (!$control) { $value = $result->getValue(); $error = $result->getErrorMessage(); $name = $this->getChallengeResponseParameterName($config); $control = id(new PHUIFormNumberControl()) ->setName($name) ->setDisableAutocomplete(true) ->setValue($value) ->setError($error); } $control ->setLabel(pht('App Code')) ->setCaption(pht('Factor Name: %s', $config->getFactorName())); $form->appendChild($control); } public function getRequestHasChallengeResponse( PhabricatorAuthFactorConfig $config, AphrontRequest $request) { $value = $this->getChallengeResponseFromRequest($config, $request); return (bool)strlen($value); } protected function newResultFromIssuedChallenges( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, array $challenges) { // If we've already issued a challenge at the current timestep or any // nearby timestep, require that it was issued to the current session. // This is defusing attacks where you (broadly) look at someone's phone // and type the code in more quickly than they do. $session_phid = $viewer->getSession()->getPHID(); $now = PhabricatorTime::getNow(); $engine = $config->getSessionEngine(); $workflow_key = $engine->getWorkflowKey(); $current_timestep = $this->getCurrentTimestep(); foreach ($challenges as $challenge) { $challenge_timestep = (int)$challenge->getChallengeKey(); $wait_duration = ($challenge->getChallengeTTL() - $now) + 1; if ($challenge->getSessionPHID() !== $session_phid) { return $this->newResult() ->setIsWait(true) ->setErrorMessage( pht( 'This factor recently issued a challenge to a different login '. 'session. Wait %s second(s) for the code to cycle, then try '. 'again.', new PhutilNumber($wait_duration))); } if ($challenge->getWorkflowKey() !== $workflow_key) { return $this->newResult() ->setIsWait(true) ->setErrorMessage( pht( 'This factor recently issued a challenge for a different '. 'workflow. Wait %s second(s) for the code to cycle, then try '. 'again.', new PhutilNumber($wait_duration))); } // If the current realtime timestep isn't a valid response to the current // challenge but the challenge hasn't expired yet, we're locking out // the factor to prevent challenge windows from overlapping. Let the user // know that they should wait for a new challenge. $challenge_timesteps = $this->getAllowedTimesteps($challenge_timestep); if (!isset($challenge_timesteps[$current_timestep])) { return $this->newResult() ->setIsWait(true) ->setErrorMessage( pht( 'This factor recently issued a challenge which has expired. '. 'A new challenge can not be issued yet. Wait %s second(s) for '. 'the code to cycle, then try again.', new PhutilNumber($wait_duration))); } if ($challenge->getIsReusedChallenge()) { return $this->newResult() ->setIsWait(true) ->setErrorMessage( pht( 'You recently provided a response to this factor. Responses '. 'may not be reused. Wait %s second(s) for the code to cycle, '. 'then try again.', new PhutilNumber($wait_duration))); } } return null; } protected function newResultFromChallengeResponse( PhabricatorAuthFactorConfig $config, PhabricatorUser $viewer, AphrontRequest $request, array $challenges) { $code = $this->getChallengeResponseFromRequest( $config, $request); $result = $this->newResult() ->setValue($code); // We expect to reach TOTP validation with exactly one valid challenge. if (count($challenges) !== 1) { throw new Exception( pht( 'Reached TOTP challenge validation with an unexpected number of '. 'unexpired challenges (%d), expected exactly one.', phutil_count($challenges))); } $challenge = head($challenges); // If the client has already provided a valid answer to this challenge and // submitted a token proving they answered it, we're all set. if ($challenge->getIsAnsweredChallenge()) { return $result->setAnsweredChallenge($challenge); } $challenge_timestep = (int)$challenge->getChallengeKey(); $current_timestep = $this->getCurrentTimestep(); $challenge_timesteps = $this->getAllowedTimesteps($challenge_timestep); $current_timesteps = $this->getAllowedTimesteps($current_timestep); // We require responses be both valid for the challenge and valid for the // current timestep. A longer challenge TTL doesn't let you use older // codes for a longer period of time. $valid_timestep = $this->getTimestepAtWhichResponseIsValid( array_intersect_key($challenge_timesteps, $current_timesteps), new PhutilOpaqueEnvelope($config->getFactorSecret()), $code); if ($valid_timestep) { $ttl = PhabricatorTime::getNow() + 60; $challenge ->setProperty('totp.timestep', $valid_timestep) ->markChallengeAsAnswered($ttl); $result->setAnsweredChallenge($challenge); } else { if (strlen($code)) { $error_message = pht('Invalid'); } else { $error_message = pht('Required'); } $result->setErrorMessage($error_message); } return $result; } public static function generateNewTOTPKey() { return strtoupper(Filesystem::readRandomCharacters(32)); } public static function base32Decode($buf) { $buf = strtoupper($buf); $map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; $map = str_split($map); $map = array_flip($map); $out = ''; $len = strlen($buf); $acc = 0; $bits = 0; for ($ii = 0; $ii < $len; $ii++) { $chr = $buf[$ii]; $val = $map[$chr]; $acc = $acc << 5; $acc = $acc + $val; $bits += 5; if ($bits >= 8) { $bits = $bits - 8; $out .= chr(($acc & (0xFF << $bits)) >> $bits); } } return $out; } public static function getTOTPCode(PhutilOpaqueEnvelope $key, $timestamp) { $binary_timestamp = pack('N*', 0).pack('N*', $timestamp); $binary_key = self::base32Decode($key->openEnvelope()); $hash = hash_hmac('sha1', $binary_timestamp, $binary_key, true); // See RFC 4226. $offset = ord($hash[19]) & 0x0F; $code = ((ord($hash[$offset + 0]) & 0x7F) << 24) | ((ord($hash[$offset + 1]) & 0xFF) << 16) | ((ord($hash[$offset + 2]) & 0xFF) << 8) | ((ord($hash[$offset + 3]) ) ); $code = ($code % 1000000); $code = str_pad($code, 6, '0', STR_PAD_LEFT); return $code; } private function getTimestepDuration() { return 30; } private function getCurrentTimestep() { $duration = $this->getTimestepDuration(); return (int)(PhabricatorTime::getNow() / $duration); } private function getAllowedTimesteps($at_timestep) { $window = $this->getTimestepWindowSize(); $range = range($at_timestep - $window, $at_timestep + $window); return array_fuse($range); } private function getTimestepWindowSize() { // The user is allowed to provide a code from the recent past or the // near future to account for minor clock skew between the client // and server, and the time it takes to actually enter a code. return 1; } private function getTimestepAtWhichResponseIsValid( array $timesteps, PhutilOpaqueEnvelope $key, $code) { foreach ($timesteps as $timestep) { $expect_code = self::getTOTPCode($key, $timestep); if (phutil_hashes_are_identical($code, $expect_code)) { return $timestep; } } return null; } protected function newMFASyncTokenProperties( PhabricatorAuthFactorProvider $providerr, PhabricatorUser $user) { return array( 'secret' => self::generateNewTOTPKey(), ); } } diff --git a/src/applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php b/src/applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php index ac3fe4d309..d1f67393ca 100644 --- a/src/applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php +++ b/src/applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php @@ -1,88 +1,108 @@ setViewer(PhabricatorUser::getOmnipotentUser()) + ->withIsEnabled(true) + ->execute(); + + $allows_registration = false; + foreach ($configs as $config) { + $provider = $config->getProvider(); + if ($provider->shouldAllowRegistration()) { + $allows_registration = true; + break; + } + } + + // If no provider allows registration, we don't need provide any warnings + // about registration being too open. + if (!$allows_registration) { + return array(); + } + $domains_key = 'auth.email-domains'; $domains_link = $this->renderConfigLink($domains_key); $domains_value = PhabricatorEnv::getEnvConfig($domains_key); $approval_key = 'auth.require-approval'; $approval_link = $this->renderConfigLink($approval_key); $approval_value = PhabricatorEnv::getEnvConfig($approval_key); $results = array(); if ($domains_value) { $message = pht( 'Phabricator is configured with an email domain whitelist (in %s), so '. 'only users with a verified email address at one of these %s '. 'allowed domain(s) will be able to register an account: %s', $domains_link, phutil_count($domains_value), phutil_tag('strong', array(), implode(', ', $domains_value))); $results[] = $this->newGuidance('core.auth.email-domains.on') ->setMessage($message); } else { $message = pht( 'Anyone who can browse to this Phabricator install will be able to '. 'register an account. To add email domain restrictions, configure '. '%s.', $domains_link); $results[] = $this->newGuidance('core.auth.email-domains.off') ->setMessage($message); } if ($approval_value) { $message = pht( 'Administrative approvals are enabled (in %s), so all new users must '. 'have their accounts approved by an administrator.', $approval_link); $results[] = $this->newGuidance('core.auth.require-approval.on') ->setMessage($message); } else { $message = pht( 'Administrative approvals are disabled, so users who register will '. 'be able to use their accounts immediately. To enable approvals, '. 'configure %s.', $approval_link); $results[] = $this->newGuidance('core.auth.require-approval.off') ->setMessage($message); } if (!$domains_value && !$approval_value) { $message = pht( 'You can safely ignore these warnings if the install itself has '. 'access controls (for example, it is deployed on a VPN) or if all of '. 'the configured providers have access controls (for example, they are '. 'all private LDAP or OAuth servers).'); $results[] = $this->newWarning('core.auth.warning') ->setMessage($message); } return $results; } private function renderConfigLink($key) { return phutil_tag( 'a', array( 'href' => '/config/edit/'.$key.'/', 'target' => '_blank', ), $key); } } diff --git a/src/applications/auth/handler/PhabricatorAuthLoginHandler.php b/src/applications/auth/handler/PhabricatorAuthLoginHandler.php deleted file mode 100644 index eabbf91843..0000000000 --- a/src/applications/auth/handler/PhabricatorAuthLoginHandler.php +++ /dev/null @@ -1,36 +0,0 @@ -delegatingController = $controller; - return $this; - } - - final public function getDelegatingController() { - return $this->delegatingController; - } - - final public function setRequest(AphrontRequest $request) { - $this->request = $request; - return $this; - } - - final public function getRequest() { - return $this->request; - } - - final public static function getAllHandlers() { - return id(new PhutilClassMapQuery()) - ->setAncestorClass(__CLASS__) - ->execute(); - } -} diff --git a/src/applications/auth/provider/PhabricatorAuthProvider.php b/src/applications/auth/provider/PhabricatorAuthProvider.php index 0525edad54..bcccca5121 100644 --- a/src/applications/auth/provider/PhabricatorAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorAuthProvider.php @@ -1,519 +1,525 @@ providerConfig = $config; return $this; } public function hasProviderConfig() { return (bool)$this->providerConfig; } public function getProviderConfig() { if ($this->providerConfig === null) { throw new PhutilInvalidStateException('attachProviderConfig'); } return $this->providerConfig; } public function getConfigurationHelp() { return null; } public function getDefaultProviderConfig() { return id(new PhabricatorAuthProviderConfig()) ->setProviderClass(get_class($this)) ->setIsEnabled(1) ->setShouldAllowLogin(1) ->setShouldAllowRegistration(1) ->setShouldAllowLink(1) ->setShouldAllowUnlink(1); } public function getNameForCreate() { return $this->getProviderName(); } public function getDescriptionForCreate() { return null; } public function getProviderKey() { return $this->getAdapter()->getAdapterKey(); } public function getProviderType() { return $this->getAdapter()->getAdapterType(); } public function getProviderDomain() { return $this->getAdapter()->getAdapterDomain(); } public static function getAllBaseProviders() { return id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) ->execute(); } public static function getAllProviders() { static $providers; if ($providers === null) { $objects = self::getAllBaseProviders(); $configs = id(new PhabricatorAuthProviderConfigQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->execute(); $providers = array(); foreach ($configs as $config) { if (!isset($objects[$config->getProviderClass()])) { // This configuration is for a provider which is not installed. continue; } $object = clone $objects[$config->getProviderClass()]; $object->attachProviderConfig($config); $key = $object->getProviderKey(); if (isset($providers[$key])) { throw new Exception( pht( "Two authentication providers use the same provider key ". "('%s'). Each provider must be identified by a unique key.", $key)); } $providers[$key] = $object; } } return $providers; } public static function getAllEnabledProviders() { $providers = self::getAllProviders(); foreach ($providers as $key => $provider) { if (!$provider->isEnabled()) { unset($providers[$key]); } } return $providers; } public static function getEnabledProviderByKey($provider_key) { return idx(self::getAllEnabledProviders(), $provider_key); } abstract public function getProviderName(); abstract public function getAdapter(); public function isEnabled() { return $this->getProviderConfig()->getIsEnabled(); } public function shouldAllowLogin() { return $this->getProviderConfig()->getShouldAllowLogin(); } public function shouldAllowRegistration() { if (!$this->shouldAllowLogin()) { return false; } return $this->getProviderConfig()->getShouldAllowRegistration(); } public function shouldAllowAccountLink() { return $this->getProviderConfig()->getShouldAllowLink(); } public function shouldAllowAccountUnlink() { return $this->getProviderConfig()->getShouldAllowUnlink(); } public function shouldTrustEmails() { return $this->shouldAllowEmailTrustConfiguration() && $this->getProviderConfig()->getShouldTrustEmails(); } /** * Should we allow the adapter to be marked as "trusted". This is true for * all adapters except those that allow the user to type in emails (see * @{class:PhabricatorPasswordAuthProvider}). */ public function shouldAllowEmailTrustConfiguration() { return true; } public function buildLoginForm(PhabricatorAuthStartController $controller) { return $this->renderLoginForm($controller->getRequest(), $mode = 'start'); } public function buildInviteForm(PhabricatorAuthStartController $controller) { return $this->renderLoginForm($controller->getRequest(), $mode = 'invite'); } abstract public function processLoginRequest( PhabricatorAuthLoginController $controller); public function buildLinkForm(PhabricatorAuthLinkController $controller) { return $this->renderLoginForm($controller->getRequest(), $mode = 'link'); } public function shouldAllowAccountRefresh() { return true; } public function buildRefreshForm( PhabricatorAuthLinkController $controller) { return $this->renderLoginForm($controller->getRequest(), $mode = 'refresh'); } protected function renderLoginForm(AphrontRequest $request, $mode) { throw new PhutilMethodNotImplementedException(); } public function createProviders() { return array($this); } protected function willSaveAccount(PhabricatorExternalAccount $account) { return; } public function willRegisterAccount(PhabricatorExternalAccount $account) { return; } protected function loadOrCreateAccount($account_id) { if (!strlen($account_id)) { throw new Exception(pht('Empty account ID!')); } $adapter = $this->getAdapter(); $adapter_class = get_class($adapter); if (!strlen($adapter->getAdapterType())) { throw new Exception( pht( "AuthAdapter (of class '%s') has an invalid implementation: ". "no adapter type.", $adapter_class)); } if (!strlen($adapter->getAdapterDomain())) { throw new Exception( pht( "AuthAdapter (of class '%s') has an invalid implementation: ". "no adapter domain.", $adapter_class)); } $account = id(new PhabricatorExternalAccount())->loadOneWhere( 'accountType = %s AND accountDomain = %s AND accountID = %s', $adapter->getAdapterType(), $adapter->getAdapterDomain(), $account_id); if (!$account) { $account = id(new PhabricatorExternalAccount()) ->setAccountType($adapter->getAdapterType()) ->setAccountDomain($adapter->getAdapterDomain()) ->setAccountID($account_id); } $account->setUsername($adapter->getAccountName()); $account->setRealName($adapter->getAccountRealName()); $account->setEmail($adapter->getAccountEmail()); $account->setAccountURI($adapter->getAccountURI()); $account->setProfileImagePHID(null); $image_uri = $adapter->getAccountImageURI(); if ($image_uri) { try { $name = PhabricatorSlug::normalize($this->getProviderName()); $name = $name.'-profile.jpg'; // TODO: If the image has not changed, we do not need to make a new // file entry for it, but there's no convenient way to do this with // PhabricatorFile right now. The storage will get shared, so the impact // here is negligible. $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $image_file = PhabricatorFile::newFromFileDownload( $image_uri, array( 'name' => $name, 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, )); if ($image_file->isViewableImage()) { $image_file ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy()) ->setCanCDN(true) ->save(); $account->setProfileImagePHID($image_file->getPHID()); } else { $image_file->delete(); } unset($unguarded); } catch (Exception $ex) { // Log this but proceed, it's not especially important that we // be able to pull profile images. phlog($ex); } } $this->willSaveAccount($account); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $account->save(); unset($unguarded); return $account; } public function getLoginURI() { $app = PhabricatorApplication::getByClass('PhabricatorAuthApplication'); return $app->getApplicationURI('/login/'.$this->getProviderKey().'/'); } public function getSettingsURI() { return '/settings/panel/external/'; } public function getStartURI() { $app = PhabricatorApplication::getByClass('PhabricatorAuthApplication'); $uri = $app->getApplicationURI('/start/'); return $uri; } public function isDefaultRegistrationProvider() { return false; } public function shouldRequireRegistrationPassword() { return false; } public function getDefaultExternalAccount() { throw new PhutilMethodNotImplementedException(); } public function getLoginOrder() { return '500-'.$this->getProviderName(); } protected function getLoginIcon() { return 'Generic'; } + public function newIconView() { + return id(new PHUIIconView()) + ->setSpriteSheet(PHUIIconView::SPRITE_LOGIN) + ->setSpriteIcon($this->getLoginIcon()); + } + public function isLoginFormAButton() { return false; } public function renderConfigPropertyTransactionTitle( PhabricatorAuthProviderConfigTransaction $xaction) { return null; } public function readFormValuesFromProvider() { return array(); } public function readFormValuesFromRequest(AphrontRequest $request) { return array(); } public function processEditForm( AphrontRequest $request, array $values) { $errors = array(); $issues = array(); return array($errors, $issues, $values); } public function extendEditForm( AphrontRequest $request, AphrontFormView $form, array $values, array $issues) { return; } public function willRenderLinkedAccount( PhabricatorUser $viewer, PHUIObjectItemView $item, PhabricatorExternalAccount $account) { $account_view = id(new PhabricatorAuthAccountView()) ->setExternalAccount($account) ->setAuthProvider($this); $item->appendChild( phutil_tag( 'div', array( 'class' => 'mmr mml mst mmb', ), $account_view)); } /** * Return true to use a two-step configuration (setup, configure) instead of * the default single-step configuration. In practice, this means that * creating a new provider instance will redirect back to the edit page * instead of the provider list. * * @return bool True if this provider uses two-step configuration. */ public function hasSetupStep() { return false; } /** * Render a standard login/register button element. * * The `$attributes` parameter takes these keys: * * - `uri`: URI the button should take the user to when clicked. * - `method`: Optional HTTP method the button should use, defaults to GET. * * @param AphrontRequest HTTP request. * @param string Request mode string. * @param map Additional parameters, see above. * @return wild Log in button. */ protected function renderStandardLoginButton( AphrontRequest $request, $mode, array $attributes = array()) { PhutilTypeSpec::checkMap( $attributes, array( 'method' => 'optional string', 'uri' => 'string', 'sigil' => 'optional string', )); $viewer = $request->getUser(); $adapter = $this->getAdapter(); if ($mode == 'link') { $button_text = pht('Link External Account'); } else if ($mode == 'refresh') { $button_text = pht('Refresh Account Link'); } else if ($mode == 'invite') { $button_text = pht('Register Account'); } else if ($this->shouldAllowRegistration()) { $button_text = pht('Log In or Register'); } else { $button_text = pht('Log In'); } $icon = id(new PHUIIconView()) ->setSpriteSheet(PHUIIconView::SPRITE_LOGIN) ->setSpriteIcon($this->getLoginIcon()); $button = id(new PHUIButtonView()) ->setSize(PHUIButtonView::BIG) ->setColor(PHUIButtonView::GREY) ->setIcon($icon) ->setText($button_text) ->setSubtext($this->getProviderName()); $uri = $attributes['uri']; $uri = new PhutilURI($uri); $params = $uri->getQueryParams(); $uri->setQueryParams(array()); $content = array($button); foreach ($params as $key => $value) { $content[] = phutil_tag( 'input', array( 'type' => 'hidden', 'name' => $key, 'value' => $value, )); } $static_response = CelerityAPI::getStaticResourceResponse(); $static_response->addContentSecurityPolicyURI('form-action', (string)$uri); foreach ($this->getContentSecurityPolicyFormActions() as $csp_uri) { $static_response->addContentSecurityPolicyURI('form-action', $csp_uri); } return phabricator_form( $viewer, array( 'method' => idx($attributes, 'method', 'GET'), 'action' => (string)$uri, 'sigil' => idx($attributes, 'sigil'), ), $content); } public function renderConfigurationFooter() { return null; } public function getAuthCSRFCode(AphrontRequest $request) { $phcid = $request->getCookie(PhabricatorCookies::COOKIE_CLIENTID); if (!strlen($phcid)) { throw new AphrontMalformedRequestException( pht('Missing Client ID Cookie'), pht( 'Your browser did not submit a "%s" cookie with client state '. 'information in the request. Check that cookies are enabled. '. 'If this problem persists, you may need to clear your cookies.', PhabricatorCookies::COOKIE_CLIENTID), true); } return PhabricatorHash::weakDigest($phcid); } protected function verifyAuthCSRFCode(AphrontRequest $request, $actual) { $expect = $this->getAuthCSRFCode($request); if (!strlen($actual)) { throw new Exception( pht( 'The authentication provider did not return a client state '. 'parameter in its response, but one was expected. If this '. 'problem persists, you may need to clear your cookies.')); } if (!phutil_hashes_are_identical($actual, $expect)) { throw new Exception( pht( 'The authentication provider did not return the correct client '. 'state parameter in its response. If this problem persists, you may '. 'need to clear your cookies.')); } } public function supportsAutoLogin() { return false; } public function getAutoLoginURI(AphrontRequest $request) { throw new PhutilMethodNotImplementedException(); } protected function getContentSecurityPolicyFormActions() { return array(); } } diff --git a/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php b/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php index 44b58b85ff..4a4babcc12 100644 --- a/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php @@ -1,493 +1,494 @@ setProperty(self::KEY_PORT, 389) ->setProperty(self::KEY_VERSION, 3); } public function getAdapter() { if (!$this->adapter) { $conf = $this->getProviderConfig(); $realname_attributes = $conf->getProperty(self::KEY_REALNAME_ATTRIBUTES); if (!is_array($realname_attributes)) { $realname_attributes = array(); } $search_attributes = $conf->getProperty(self::KEY_SEARCH_ATTRIBUTES); $search_attributes = phutil_split_lines($search_attributes, false); $search_attributes = array_filter($search_attributes); $adapter = id(new PhutilLDAPAuthAdapter()) ->setHostname( $conf->getProperty(self::KEY_HOSTNAME)) ->setPort( $conf->getProperty(self::KEY_PORT)) ->setBaseDistinguishedName( $conf->getProperty(self::KEY_DISTINGUISHED_NAME)) ->setSearchAttributes($search_attributes) ->setUsernameAttribute( $conf->getProperty(self::KEY_USERNAME_ATTRIBUTE)) ->setRealNameAttributes($realname_attributes) ->setLDAPVersion( $conf->getProperty(self::KEY_VERSION)) ->setLDAPReferrals( $conf->getProperty(self::KEY_REFERRALS)) ->setLDAPStartTLS( $conf->getProperty(self::KEY_START_TLS)) ->setAlwaysSearch($conf->getProperty(self::KEY_ALWAYS_SEARCH)) ->setAnonymousUsername( $conf->getProperty(self::KEY_ANONYMOUS_USERNAME)) ->setAnonymousPassword( new PhutilOpaqueEnvelope( $conf->getProperty(self::KEY_ANONYMOUS_PASSWORD))) ->setActiveDirectoryDomain( $conf->getProperty(self::KEY_ACTIVEDIRECTORY_DOMAIN)); $this->adapter = $adapter; } return $this->adapter; } protected function renderLoginForm(AphrontRequest $request, $mode) { $viewer = $request->getUser(); $dialog = id(new AphrontDialogView()) ->setSubmitURI($this->getLoginURI()) ->setUser($viewer); if ($mode == 'link') { $dialog->setTitle(pht('Link LDAP Account')); $dialog->addSubmitButton(pht('Link Accounts')); $dialog->addCancelButton($this->getSettingsURI()); } else if ($mode == 'refresh') { $dialog->setTitle(pht('Refresh LDAP Account')); $dialog->addSubmitButton(pht('Refresh Account')); $dialog->addCancelButton($this->getSettingsURI()); } else { if ($this->shouldAllowRegistration()) { $dialog->setTitle(pht('Log In or Register with LDAP')); $dialog->addSubmitButton(pht('Log In or Register')); } else { $dialog->setTitle(pht('Log In with LDAP')); $dialog->addSubmitButton(pht('Log In')); } if ($mode == 'login') { $dialog->addCancelButton($this->getStartURI()); } } $v_user = $request->getStr('ldap_username'); $e_user = null; $e_pass = null; $errors = array(); if ($request->isHTTPPost()) { // NOTE: This is intentionally vague so as not to disclose whether a // given username exists. $e_user = pht('Invalid'); $e_pass = pht('Invalid'); $errors[] = pht('Username or password are incorrect.'); } $form = id(new PHUIFormLayoutView()) ->setUser($viewer) ->setFullWidth(true) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('LDAP Username')) ->setName('ldap_username') + ->setAutofocus(true) ->setValue($v_user) ->setError($e_user)) ->appendChild( id(new AphrontFormPasswordControl()) ->setLabel(pht('LDAP Password')) ->setName('ldap_password') ->setError($e_pass)); if ($errors) { $errors = id(new PHUIInfoView())->setErrors($errors); } $dialog->appendChild($errors); $dialog->appendChild($form); return $dialog; } public function processLoginRequest( PhabricatorAuthLoginController $controller) { $request = $controller->getRequest(); $viewer = $request->getUser(); $response = null; $account = null; $username = $request->getStr('ldap_username'); $password = $request->getStr('ldap_password'); $has_password = strlen($password); $password = new PhutilOpaqueEnvelope($password); if (!strlen($username) || !$has_password) { $response = $controller->buildProviderPageResponse( $this, $this->renderLoginForm($request, 'login')); return array($account, $response); } if ($request->isFormPost()) { try { if (strlen($username) && $has_password) { $adapter = $this->getAdapter(); $adapter->setLoginUsername($username); $adapter->setLoginPassword($password); // TODO: This calls ldap_bind() eventually, which dumps cleartext // passwords to the error log. See note in PhutilLDAPAuthAdapter. // See T3351. DarkConsoleErrorLogPluginAPI::enableDiscardMode(); $account_id = $adapter->getAccountID(); DarkConsoleErrorLogPluginAPI::disableDiscardMode(); } else { throw new Exception(pht('Username and password are required!')); } } catch (PhutilAuthCredentialException $ex) { $response = $controller->buildProviderPageResponse( $this, $this->renderLoginForm($request, 'login')); return array($account, $response); } catch (Exception $ex) { // TODO: Make this cleaner. throw $ex; } } return array($this->loadOrCreateAccount($account_id), $response); } const KEY_HOSTNAME = 'ldap:host'; const KEY_PORT = 'ldap:port'; const KEY_DISTINGUISHED_NAME = 'ldap:dn'; const KEY_SEARCH_ATTRIBUTES = 'ldap:search-attribute'; const KEY_USERNAME_ATTRIBUTE = 'ldap:username-attribute'; const KEY_REALNAME_ATTRIBUTES = 'ldap:realname-attributes'; const KEY_VERSION = 'ldap:version'; const KEY_REFERRALS = 'ldap:referrals'; const KEY_START_TLS = 'ldap:start-tls'; // TODO: This is misspelled! See T13005. const KEY_ANONYMOUS_USERNAME = 'ldap:anoynmous-username'; const KEY_ANONYMOUS_PASSWORD = 'ldap:anonymous-password'; const KEY_ALWAYS_SEARCH = 'ldap:always-search'; const KEY_ACTIVEDIRECTORY_DOMAIN = 'ldap:activedirectory-domain'; private function getPropertyKeys() { return array_keys($this->getPropertyLabels()); } private function getPropertyLabels() { return array( self::KEY_HOSTNAME => pht('LDAP Hostname'), self::KEY_PORT => pht('LDAP Port'), self::KEY_DISTINGUISHED_NAME => pht('Base Distinguished Name'), self::KEY_SEARCH_ATTRIBUTES => pht('Search Attributes'), self::KEY_ALWAYS_SEARCH => pht('Always Search'), self::KEY_ANONYMOUS_USERNAME => pht('Anonymous Username'), self::KEY_ANONYMOUS_PASSWORD => pht('Anonymous Password'), self::KEY_USERNAME_ATTRIBUTE => pht('Username Attribute'), self::KEY_REALNAME_ATTRIBUTES => pht('Realname Attributes'), self::KEY_VERSION => pht('LDAP Version'), self::KEY_REFERRALS => pht('Enable Referrals'), self::KEY_START_TLS => pht('Use TLS'), self::KEY_ACTIVEDIRECTORY_DOMAIN => pht('ActiveDirectory Domain'), ); } public function readFormValuesFromProvider() { $properties = array(); foreach ($this->getPropertyLabels() as $key => $ignored) { $properties[$key] = $this->getProviderConfig()->getProperty($key); } return $properties; } public function readFormValuesFromRequest(AphrontRequest $request) { $values = array(); foreach ($this->getPropertyKeys() as $key) { switch ($key) { case self::KEY_REALNAME_ATTRIBUTES: $values[$key] = $request->getStrList($key, array()); break; default: $values[$key] = $request->getStr($key); break; } } return $values; } public function processEditForm( AphrontRequest $request, array $values) { $errors = array(); $issues = array(); return array($errors, $issues, $values); } public static function assertLDAPExtensionInstalled() { if (!function_exists('ldap_bind')) { throw new Exception( pht( 'Before you can set up or use LDAP, you need to install the PHP '. 'LDAP extension. It is not currently installed, so PHP can not '. 'talk to LDAP. Usually you can install it with '. '`%s`, `%s`, or a similar package manager command.', 'yum install php-ldap', 'apt-get install php5-ldap')); } } public function extendEditForm( AphrontRequest $request, AphrontFormView $form, array $values, array $issues) { self::assertLDAPExtensionInstalled(); $labels = $this->getPropertyLabels(); $captions = array( self::KEY_HOSTNAME => pht('Example: %s%sFor LDAPS, use: %s', phutil_tag('tt', array(), pht('ldap.example.com')), phutil_tag('br'), phutil_tag('tt', array(), pht('ldaps://ldaps.example.com/'))), self::KEY_DISTINGUISHED_NAME => pht('Example: %s', phutil_tag('tt', array(), pht('ou=People, dc=example, dc=com'))), self::KEY_USERNAME_ATTRIBUTE => pht('Example: %s', phutil_tag('tt', array(), pht('sn'))), self::KEY_REALNAME_ATTRIBUTES => pht('Example: %s', phutil_tag('tt', array(), pht('firstname, lastname'))), self::KEY_REFERRALS => pht('Follow referrals. Disable this for Windows AD 2003.'), self::KEY_START_TLS => pht('Start TLS after binding to the LDAP server.'), self::KEY_ALWAYS_SEARCH => pht('Always bind and search, even without a username and password.'), ); $types = array( self::KEY_REFERRALS => 'checkbox', self::KEY_START_TLS => 'checkbox', self::KEY_SEARCH_ATTRIBUTES => 'textarea', self::KEY_REALNAME_ATTRIBUTES => 'list', self::KEY_ANONYMOUS_PASSWORD => 'password', self::KEY_ALWAYS_SEARCH => 'checkbox', ); $instructions = array( self::KEY_SEARCH_ATTRIBUTES => pht( "When a user types their LDAP username and password into Phabricator, ". "Phabricator can either bind to LDAP with those credentials directly ". "(which is simpler, but not as powerful) or bind to LDAP with ". "anonymous credentials, then search for record matching the supplied ". "credentials (which is more complicated, but more powerful).\n\n". "For many installs, direct binding is sufficient. However, you may ". "want to search first if:\n\n". " - You want users to be able to log in with either their username ". " or their email address.\n". " - The login/username is not part of the distinguished name in ". " your LDAP records.\n". " - You want to restrict logins to a subset of users (like only ". " those in certain departments).\n". " - Your LDAP server is configured in some other way that prevents ". " direct binding from working correctly.\n\n". "**To bind directly**, enter the LDAP attribute corresponding to the ". "login name into the **Search Attributes** box below. Often, this is ". "something like `sn` or `uid`. This is the simplest configuration, ". "but will only work if the username is part of the distinguished ". "name, and won't let you apply complex restrictions to logins.\n\n". " lang=text,name=Simple Direct Binding\n". " sn\n\n". "**To search first**, provide an anonymous username and password ". "below (or check the **Always Search** checkbox), then enter one ". "or more search queries into this field, one per line. ". "After binding, these queries will be used to identify the ". "record associated with the login name the user typed.\n\n". "Searches will be tried in order until a matching record is found. ". "Each query can be a simple attribute name (like `sn` or `mail`), ". "which will search for a matching record, or it can be a complex ". "query that uses the string `\${login}` to represent the login ". "name.\n\n". "A common simple configuration is just an attribute name, like ". "`sn`, which will work the same way direct binding works:\n\n". " lang=text,name=Simple Example\n". " sn\n\n". "A slightly more complex configuration might let the user log in with ". "either their login name or email address:\n\n". " lang=text,name=Match Several Attributes\n". " mail\n". " sn\n\n". "If your LDAP directory is more complex, or you want to perform ". "sophisticated filtering, you can use more complex queries. Depending ". "on your directory structure, this example might allow users to log ". "in with either their email address or username, but only if they're ". "in specific departments:\n\n". " lang=text,name=Complex Example\n". " (&(mail=\${login})(|(departmentNumber=1)(departmentNumber=2)))\n". " (&(sn=\${login})(|(departmentNumber=1)(departmentNumber=2)))\n\n". "All of the attribute names used here are just examples: your LDAP ". "server may use different attribute names."), self::KEY_ALWAYS_SEARCH => pht( 'To search for an LDAP record before authenticating, either check '. 'the **Always Search** checkbox or enter an anonymous '. 'username and password to use to perform the search.'), self::KEY_USERNAME_ATTRIBUTE => pht( 'Optionally, specify a username attribute to use to prefill usernames '. 'when registering a new account. This is purely cosmetic and does not '. 'affect the login process, but you can configure it to make sure '. 'users get the same default username as their LDAP username, so '. 'usernames remain consistent across systems.'), self::KEY_REALNAME_ATTRIBUTES => pht( 'Optionally, specify one or more comma-separated attributes to use to '. 'prefill the "Real Name" field when registering a new account. This '. 'is purely cosmetic and does not affect the login process, but can '. 'make registration a little easier.'), ); foreach ($labels as $key => $label) { $caption = idx($captions, $key); $type = idx($types, $key); $value = idx($values, $key); $control = null; switch ($type) { case 'checkbox': $control = id(new AphrontFormCheckboxControl()) ->addCheckbox( $key, 1, hsprintf('%s: %s', $label, $caption), $value); break; case 'list': $control = id(new AphrontFormTextControl()) ->setName($key) ->setLabel($label) ->setCaption($caption) ->setValue($value ? implode(', ', $value) : null); break; case 'password': $control = id(new AphrontFormPasswordControl()) ->setName($key) ->setLabel($label) ->setCaption($caption) ->setDisableAutocomplete(true) ->setValue($value); break; case 'textarea': $control = id(new AphrontFormTextAreaControl()) ->setName($key) ->setLabel($label) ->setCaption($caption) ->setValue($value); break; default: $control = id(new AphrontFormTextControl()) ->setName($key) ->setLabel($label) ->setCaption($caption) ->setValue($value); break; } $instruction_text = idx($instructions, $key); if (strlen($instruction_text)) { $form->appendRemarkupInstructions($instruction_text); } $form->appendChild($control); } } public function renderConfigPropertyTransactionTitle( PhabricatorAuthProviderConfigTransaction $xaction) { $author_phid = $xaction->getAuthorPHID(); $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $key = $xaction->getMetadataValue( PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY); $labels = $this->getPropertyLabels(); if (isset($labels[$key])) { $label = $labels[$key]; $mask = false; switch ($key) { case self::KEY_ANONYMOUS_PASSWORD: $mask = true; break; } if ($mask) { return pht( '%s updated the "%s" value.', $xaction->renderHandleLink($author_phid), $label); } if ($old === null || $old === '') { return pht( '%s set the "%s" value to "%s".', $xaction->renderHandleLink($author_phid), $label, $new); } else { return pht( '%s changed the "%s" value from "%s" to "%s".', $xaction->renderHandleLink($author_phid), $label, $old, $new); } } return parent::renderConfigPropertyTransactionTitle($xaction); } public static function getLDAPProvider() { $providers = self::getAllEnabledProviders(); foreach ($providers as $provider) { if ($provider instanceof PhabricatorLDAPAuthProvider) { return $provider; } } return null; } } diff --git a/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php b/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php index d841f091aa..ec5720e078 100644 --- a/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorPasswordAuthProvider.php @@ -1,405 +1,406 @@ 'color: #009900', ), pht('Yes')); $no = phutil_tag( 'strong', array( 'style' => 'color: #990000', ), pht('Not Installed')); $best_hasher_name = null; try { $best_hasher = PhabricatorPasswordHasher::getBestHasher(); $best_hasher_name = $best_hasher->getHashName(); } catch (PhabricatorPasswordHasherUnavailableException $ex) { // There are no suitable hashers. The user might be able to enable some, // so we don't want to fatal here. We'll fatal when users try to actually // use this stuff if it isn't fixed before then. Until then, we just // don't highlight a row. In practice, at least one hasher should always // be available. } $rows = array(); $rowc = array(); foreach ($hashers as $hasher) { $is_installed = $hasher->canHashPasswords(); $rows[] = array( $hasher->getHumanReadableName(), $hasher->getHashName(), $hasher->getHumanReadableStrength(), ($is_installed ? $yes : $no), ($is_installed ? null : $hasher->getInstallInstructions()), ); $rowc[] = ($best_hasher_name == $hasher->getHashName()) ? 'highlighted' : null; } $table = new AphrontTableView($rows); $table->setRowClasses($rowc); $table->setHeaders( array( pht('Algorithm'), pht('Name'), pht('Strength'), pht('Installed'), pht('Install Instructions'), )); $table->setColumnClasses( array( '', '', '', '', 'wide', )); $header = id(new PHUIHeaderView()) ->setHeader(pht('Password Hash Algorithms')) ->setSubheader( pht( 'Stronger algorithms are listed first. The highlighted algorithm '. 'will be used when storing new hashes. Older hashes will be '. 'upgraded to the best algorithm over time.')); return id(new PHUIObjectBoxView()) ->setHeader($header) ->setTable($table); } public function getDescriptionForCreate() { return pht( 'Allow users to log in or register using a username and password.'); } public function getAdapter() { if (!$this->adapter) { $adapter = new PhutilEmptyAuthAdapter(); $adapter->setAdapterType('password'); $adapter->setAdapterDomain('self'); $this->adapter = $adapter; } return $this->adapter; } public function getLoginOrder() { // Make sure username/password appears first if it is enabled. return '100-'.$this->getProviderName(); } public function shouldAllowAccountLink() { return false; } public function shouldAllowAccountUnlink() { return false; } public function isDefaultRegistrationProvider() { return true; } public function buildLoginForm( PhabricatorAuthStartController $controller) { $request = $controller->getRequest(); return $this->renderPasswordLoginForm($request); } public function buildInviteForm( PhabricatorAuthStartController $controller) { $request = $controller->getRequest(); $viewer = $request->getViewer(); $form = id(new AphrontFormView()) ->setUser($viewer) ->addHiddenInput('invite', true) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Username')) ->setName('username')); $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->setTitle(pht('Register an Account')) ->appendForm($form) ->setSubmitURI('/auth/register/') ->addSubmitButton(pht('Continue')); return $dialog; } public function buildLinkForm( PhabricatorAuthLinkController $controller) { throw new Exception(pht("Password providers can't be linked.")); } private function renderPasswordLoginForm( AphrontRequest $request, $require_captcha = false, $captcha_valid = false) { $viewer = $request->getUser(); $dialog = id(new AphrontDialogView()) ->setSubmitURI($this->getLoginURI()) ->setUser($viewer) ->setTitle(pht('Log In')) ->addSubmitButton(pht('Log In')); if ($this->shouldAllowRegistration()) { $dialog->addCancelButton( '/auth/register/', pht('Register New Account')); } $dialog->addFooter( phutil_tag( 'a', array( 'href' => '/login/email/', ), pht('Forgot your password?'))); $v_user = nonempty( $request->getStr('username'), $request->getCookie(PhabricatorCookies::COOKIE_USERNAME)); $e_user = null; $e_pass = null; $e_captcha = null; $errors = array(); if ($require_captcha && !$captcha_valid) { if (AphrontFormRecaptchaControl::hasCaptchaResponse($request)) { $e_captcha = pht('Invalid'); $errors[] = pht('CAPTCHA was not entered correctly.'); } else { $e_captcha = pht('Required'); $errors[] = pht( 'Too many login failures recently. You must '. 'submit a CAPTCHA with your login request.'); } } else if ($request->isHTTPPost()) { // NOTE: This is intentionally vague so as not to disclose whether a // given username or email is registered. $e_user = pht('Invalid'); $e_pass = pht('Invalid'); $errors[] = pht('Username or password are incorrect.'); } if ($errors) { $errors = id(new PHUIInfoView())->setErrors($errors); } $form = id(new PHUIFormLayoutView()) ->setFullWidth(true) ->appendChild($errors) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Username or Email')) ->setName('username') + ->setAutofocus(true) ->setValue($v_user) ->setError($e_user)) ->appendChild( id(new AphrontFormPasswordControl()) ->setLabel(pht('Password')) ->setName('password') ->setError($e_pass)); if ($require_captcha) { $form->appendChild( id(new AphrontFormRecaptchaControl()) ->setError($e_captcha)); } $dialog->appendChild($form); return $dialog; } public function processLoginRequest( PhabricatorAuthLoginController $controller) { $request = $controller->getRequest(); $viewer = $request->getUser(); $content_source = PhabricatorContentSource::newFromRequest($request); $captcha_limit = 5; $hard_limit = 32; $limit_window = phutil_units('15 minutes in seconds'); $failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP( PhabricatorUserLog::ACTION_LOGIN_FAILURE, $limit_window); // If the same remote address has submitted several failed login attempts // recently, require they provide a CAPTCHA response for new attempts. $require_captcha = false; $captcha_valid = false; if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) { if (count($failed_attempts) > $captcha_limit) { $require_captcha = true; $captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request); } } // If the user has submitted quite a few failed login attempts recently, // give them a hard limit. if (count($failed_attempts) > $hard_limit) { $guidance = array(); $guidance[] = pht( 'Your remote address has failed too many login attempts recently. '. 'Wait a few minutes before trying again.'); $guidance[] = pht( 'If you are unable to log in to your account, you can '. '[[ /login/email | send a reset link to your email address ]].'); $guidance = implode("\n\n", $guidance); $dialog = $controller->newDialog() ->setTitle(pht('Too Many Login Attempts')) ->appendChild(new PHUIRemarkupView($viewer, $guidance)) ->addCancelButton('/auth/start/', pht('Wait Patiently')); return array(null, $dialog); } $response = null; $account = null; $log_user = null; if ($request->isFormPost()) { if (!$require_captcha || $captcha_valid) { $username_or_email = $request->getStr('username'); if (strlen($username_or_email)) { $user = id(new PhabricatorUser())->loadOneWhere( 'username = %s', $username_or_email); if (!$user) { $user = PhabricatorUser::loadOneWithEmailAddress( $username_or_email); } if ($user) { $envelope = new PhutilOpaqueEnvelope($request->getStr('password')); $engine = id(new PhabricatorAuthPasswordEngine()) ->setViewer($user) ->setContentSource($content_source) ->setPasswordType(PhabricatorAuthPassword::PASSWORD_TYPE_ACCOUNT) ->setObject($user); if ($engine->isValidPassword($envelope)) { $account = $this->loadOrCreateAccount($user->getPHID()); $log_user = $user; } } } } } if (!$account) { if ($request->isFormPost()) { $log = PhabricatorUserLog::initializeNewLog( null, $log_user ? $log_user->getPHID() : null, PhabricatorUserLog::ACTION_LOGIN_FAILURE); $log->save(); } $request->clearCookie(PhabricatorCookies::COOKIE_USERNAME); $response = $controller->buildProviderPageResponse( $this, $this->renderPasswordLoginForm( $request, $require_captcha, $captcha_valid)); } return array($account, $response); } public function shouldRequireRegistrationPassword() { return true; } public function getDefaultExternalAccount() { $adapter = $this->getAdapter(); return id(new PhabricatorExternalAccount()) ->setAccountType($adapter->getAdapterType()) ->setAccountDomain($adapter->getAdapterDomain()); } protected function willSaveAccount(PhabricatorExternalAccount $account) { parent::willSaveAccount($account); $account->setUserPHID($account->getAccountID()); } public function willRegisterAccount(PhabricatorExternalAccount $account) { parent::willRegisterAccount($account); $account->setAccountID($account->getUserPHID()); } public static function getPasswordProvider() { $providers = self::getAllEnabledProviders(); foreach ($providers as $provider) { if ($provider instanceof PhabricatorPasswordAuthProvider) { return $provider; } } return null; } public function willRenderLinkedAccount( PhabricatorUser $viewer, PHUIObjectItemView $item, PhabricatorExternalAccount $account) { return; } public function shouldAllowAccountRefresh() { return false; } public function shouldAllowEmailTrustConfiguration() { return false; } } diff --git a/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php b/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php index 626c80348f..ee073e3ac1 100644 --- a/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php +++ b/src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php @@ -1,103 +1,90 @@ phids = $phids; return $this; } public function withIDs(array $ids) { $this->ids = $ids; return $this; } - public function withStatus($status) { - $this->status = $status; + public function withProviderClasses(array $classes) { + $this->providerClasses = $classes; return $this; } - public function withProviderClasses(array $classes) { - $this->providerClasses = $classes; + public function withIsEnabled($is_enabled) { + $this->isEnabled = $is_enabled; return $this; } - public static function getStatusOptions() { - return array( - self::STATUS_ALL => pht('All Providers'), - self::STATUS_ENABLED => pht('Enabled Providers'), - ); + public function newResultObject() { + return new PhabricatorAuthProviderConfig(); } protected function loadPage() { - $table = new PhabricatorAuthProviderConfig(); - $conn_r = $table->establishConnection('r'); - - $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)); - - return $table->loadAllFromArray($data); + return $this->loadStandardPage($this->newResultObject()); } - protected function buildWhereClause(AphrontDatabaseConnection $conn) { - $where = array(); + 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->providerClasses !== null) { $where[] = qsprintf( $conn, 'providerClass IN (%Ls)', $this->providerClasses); } - $status = $this->status; - switch ($status) { - case self::STATUS_ALL: - break; - case self::STATUS_ENABLED: - $where[] = qsprintf( - $conn, - 'isEnabled = 1'); - break; - default: - throw new Exception(pht("Unknown status '%s'!", $status)); + if ($this->isEnabled !== null) { + $where[] = qsprintf( + $conn, + 'isEnabled = %d', + (int)$this->isEnabled); } - $where[] = $this->buildPagingClause($conn); + return $where; + } + + protected function willFilterPage(array $configs) { + + foreach ($configs as $key => $config) { + $provider = $config->getProvider(); + if (!$provider) { + unset($configs[$key]); + continue; + } + } - return $this->formatWhereClause($conn, $where); + return $configs; } public function getQueryApplicationClass() { return 'PhabricatorAuthApplication'; } } diff --git a/src/applications/auth/query/PhabricatorExternalAccountQuery.php b/src/applications/auth/query/PhabricatorExternalAccountQuery.php index b34199ce60..c4a53c12f8 100644 --- a/src/applications/auth/query/PhabricatorExternalAccountQuery.php +++ b/src/applications/auth/query/PhabricatorExternalAccountQuery.php @@ -1,202 +1,171 @@ userPHIDs = $user_phids; return $this; } public function withAccountIDs(array $account_ids) { $this->accountIDs = $account_ids; return $this; } public function withAccountDomains(array $account_domains) { $this->accountDomains = $account_domains; return $this; } public function withAccountTypes(array $account_types) { $this->accountTypes = $account_types; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withIDs($ids) { $this->ids = $ids; return $this; } public function withAccountSecrets(array $secrets) { $this->accountSecrets = $secrets; return $this; } public function needImages($need) { $this->needImages = $need; return $this; } public function newResultObject() { return new PhabricatorExternalAccount(); } protected function loadPage() { return $this->loadStandardPage($this->newResultObject()); } protected function willFilterPage(array $accounts) { if ($this->needImages) { $file_phids = mpull($accounts, 'getProfileImagePHID'); $file_phids = array_filter($file_phids); if ($file_phids) { // NOTE: We use the omnipotent viewer here because these files are // usually created during registration and can't be associated with // the correct policies, since the relevant user account does not exist // yet. In effect, if you can see an ExternalAccount, you can see its // profile image. $files = id(new PhabricatorFileQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs($file_phids) ->execute(); $files = mpull($files, null, 'getPHID'); } else { $files = array(); } $default_file = null; foreach ($accounts as $account) { $image_phid = $account->getProfileImagePHID(); if ($image_phid && isset($files[$image_phid])) { $account->attachProfileImageFile($files[$image_phid]); } else { if ($default_file === null) { $default_file = PhabricatorFile::loadBuiltin( $this->getViewer(), 'profile.png'); } $account->attachProfileImageFile($default_file); } } } return $accounts; } 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->accountTypes !== null) { $where[] = qsprintf( $conn, 'accountType IN (%Ls)', $this->accountTypes); } if ($this->accountDomains !== null) { $where[] = qsprintf( $conn, 'accountDomain IN (%Ls)', $this->accountDomains); } if ($this->accountIDs !== null) { $where[] = qsprintf( $conn, 'accountID IN (%Ls)', $this->accountIDs); } if ($this->userPHIDs !== null) { $where[] = qsprintf( $conn, 'userPHID IN (%Ls)', $this->userPHIDs); } if ($this->accountSecrets !== null) { $where[] = qsprintf( $conn, 'accountSecret IN (%Ls)', $this->accountSecrets); } return $where; } public function getQueryApplicationClass() { return 'PhabricatorPeopleApplication'; } - /** - * Attempts to find an external account and if none exists creates a new - * external account with a shiny new ID and PHID. - * - * NOTE: This function assumes the first item in various query parameters is - * the correct value to use in creating a new external account. - */ - public function loadOneOrCreate() { - $account = $this->executeOne(); - if (!$account) { - $account = new PhabricatorExternalAccount(); - if ($this->accountIDs) { - $account->setAccountID(reset($this->accountIDs)); - } - if ($this->accountTypes) { - $account->setAccountType(reset($this->accountTypes)); - } - if ($this->accountDomains) { - $account->setAccountDomain(reset($this->accountDomains)); - } - if ($this->accountSecrets) { - $account->setAccountSecret(reset($this->accountSecrets)); - } - if ($this->userPHIDs) { - $account->setUserPHID(reset($this->userPHIDs)); - } - $account->save(); - } - return $account; - } - } diff --git a/src/applications/auth/storage/PhabricatorAuthChallenge.php b/src/applications/auth/storage/PhabricatorAuthChallenge.php index 8fa07d712f..0b740e5fa7 100644 --- a/src/applications/auth/storage/PhabricatorAuthChallenge.php +++ b/src/applications/auth/storage/PhabricatorAuthChallenge.php @@ -1,262 +1,272 @@ setIsCompleted(0); } public static function newHTTPParametersFromChallenges(array $challenges) { assert_instances_of($challenges, __CLASS__); $token_list = array(); foreach ($challenges as $challenge) { $token = $challenge->getResponseToken(); if ($token) { $token_list[] = sprintf( '%s:%s', $challenge->getPHID(), $token->openEnvelope()); } } if (!$token_list) { return array(); } $token_list = implode(' ', $token_list); return array( self::HTTPKEY => $token_list, ); } public static function newChallengeResponsesFromRequest( array $challenges, AphrontRequest $request) { assert_instances_of($challenges, __CLASS__); $token_list = $request->getStr(self::HTTPKEY); $token_list = explode(' ', $token_list); $token_map = array(); foreach ($token_list as $token_element) { $token_element = trim($token_element, ' '); if (!strlen($token_element)) { continue; } // NOTE: This error message is intentionally not printing the token to // avoid disclosing it. As a result, it isn't terribly useful, but no // normal user should ever end up here. if (!preg_match('/^[^:]+:/', $token_element)) { throw new Exception( pht( 'This request included an improperly formatted MFA challenge '. 'token and can not be processed.')); } list($phid, $token) = explode(':', $token_element, 2); if (isset($token_map[$phid])) { throw new Exception( pht( 'This request improperly specifies an MFA challenge token ("%s") '. 'multiple times and can not be processed.', $phid)); } $token_map[$phid] = new PhutilOpaqueEnvelope($token); } $challenges = mpull($challenges, null, 'getPHID'); $now = PhabricatorTime::getNow(); foreach ($challenges as $challenge_phid => $challenge) { // If the response window has expired, don't attach the token. if ($challenge->getResponseTTL() < $now) { continue; } $token = idx($token_map, $challenge_phid); if (!$token) { continue; } $challenge->setResponseToken($token); } } protected function getConfiguration() { return array( self::CONFIG_SERIALIZATION => array( 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'challengeKey' => 'text255', 'challengeTTL' => 'epoch', 'workflowKey' => 'text255', 'responseDigest' => 'text255?', 'responseTTL' => 'epoch?', 'isCompleted' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_issued' => array( 'columns' => array('userPHID', 'challengeTTL'), ), 'key_collection' => array( 'columns' => array('challengeTTL'), ), ), ) + parent::getConfiguration(); } public function getPHIDType() { return PhabricatorAuthChallengePHIDType::TYPECONST; } public function getIsReusedChallenge() { if ($this->getIsCompleted()) { return true; } if (!$this->getIsAnsweredChallenge()) { return false; } // If the challenge has been answered but the client has provided a token // proving that they answered it, this is still a valid response. if ($this->getResponseToken()) { return false; } return true; } public function getIsAnsweredChallenge() { return (bool)$this->getResponseDigest(); } public function markChallengeAsAnswered($ttl) { $token = Filesystem::readRandomCharacters(32); $token = new PhutilOpaqueEnvelope($token); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $this ->setResponseToken($token) ->setResponseTTL($ttl) ->save(); unset($unguarded); return $this; } public function markChallengeAsCompleted() { return $this ->setIsCompleted(true) ->save(); } public function setResponseToken(PhutilOpaqueEnvelope $token) { if (!$this->getUserPHID()) { throw new PhutilInvalidStateException('setUserPHID'); } if ($this->responseToken) { throw new Exception( pht( 'This challenge already has a response token; you can not '. 'set a new response token.')); } if (preg_match('/ /', $token->openEnvelope())) { throw new Exception( pht( 'The response token for this challenge is invalid: response '. 'tokens may not include spaces.')); } $digest = PhabricatorHash::digestWithNamedKey( $token->openEnvelope(), self::TOKEN_DIGEST_KEY); if ($this->responseDigest !== null) { if (!phutil_hashes_are_identical($digest, $this->responseDigest)) { throw new Exception( pht( 'Invalid response token for this challenge: token digest does '. 'not match stored digest.')); } } else { $this->responseDigest = $digest; } $this->responseToken = $token; return $this; } public function getResponseToken() { return $this->responseToken; } public function setResponseDigest($value) { throw new Exception( pht( 'You can not set the response digest for a challenge directly. '. 'Instead, set a response token. A response digest will be computed '. 'automatically.')); } public function setProperty($key, $value) { $this->properties[$key] = $value; return $this; } public function getProperty($key, $default = null) { return $this->properties[$key]; } + public function setIsNewChallenge($is_new_challenge) { + $this->isNewChallenge = $is_new_challenge; + return $this; + } + + public function getIsNewChallenge() { + return $this->isNewChallenge; + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, ); } public function getPolicy($capability) { return PhabricatorPolicies::POLICY_NOONE; } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return ($viewer->getPHID() === $this->getUserPHID()); } } diff --git a/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php b/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php index 9d02112dff..a8cb6d10a3 100644 --- a/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php +++ b/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php @@ -1,21 +1,17 @@ true, self::CONFIG_SERIALIZATION => array( 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'isEnabled' => 'bool', 'providerClass' => 'text128', 'providerType' => 'text32', 'providerDomain' => 'text128', 'shouldAllowLogin' => 'bool', 'shouldAllowRegistration' => 'bool', 'shouldAllowLink' => 'bool', 'shouldAllowUnlink' => 'bool', 'shouldTrustEmails' => 'bool', 'shouldAutoLogin' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_provider' => array( 'columns' => array('providerType', 'providerDomain'), 'unique' => true, ), 'key_class' => array( 'columns' => array('providerClass'), ), ), ) + parent::getConfiguration(); } 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 getProvider() { if (!$this->provider) { $base = PhabricatorAuthProvider::getAllBaseProviders(); $found = null; foreach ($base as $provider) { if (get_class($provider) == $this->providerClass) { $found = $provider; break; } } if ($found) { $this->provider = id(clone $found)->attachProviderConfig($this); } } return $this->provider; } + public function getURI() { + return '/auth/config/view/'.$this->getID().'/'; + } + + public function getObjectName() { + return pht('Auth Provider %d', $this->getID()); + } + + public function getDisplayName() { + return $this->getProvider()->getProviderName(); + } + + public function getSortVector() { + return id(new PhutilSortVector()) + ->addString($this->getDisplayName()); + } + + public function newIconView() { + return $this->getProvider()->newIconView(); + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorAuthProviderConfigEditor(); } public function getApplicationTransactionTemplate() { return new PhabricatorAuthProviderConfigTransaction(); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return PhabricatorPolicies::POLICY_USER; case PhabricatorPolicyCapability::CAN_EDIT: return PhabricatorPolicies::POLICY_ADMIN; } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } } diff --git a/src/applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php b/src/applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php index e1453b4383..d5a3588d59 100644 --- a/src/applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php +++ b/src/applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php @@ -1,178 +1,174 @@ provider = $provider; return $this; } public function getProvider() { return $this->provider; } public function getApplicationName() { return 'auth'; } public function getApplicationTransactionType() { return PhabricatorAuthAuthProviderPHIDType::TYPECONST; } - public function getApplicationTransactionCommentObject() { - return null; - } - public function getIcon() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_ENABLE: if ($new) { return 'fa-check'; } else { return 'fa-ban'; } } return parent::getIcon(); } public function getColor() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_ENABLE: if ($new) { return 'green'; } else { return 'indigo'; } } return parent::getColor(); } public function getTitle() { $author_phid = $this->getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_ENABLE: if ($old === null) { return pht( '%s created this provider.', $this->renderHandleLink($author_phid)); } else if ($new) { return pht( '%s enabled this provider.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled this provider.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_LOGIN: if ($new) { return pht( '%s enabled login.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled login.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_REGISTRATION: if ($new) { return pht( '%s enabled registration.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled registration.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_LINK: if ($new) { return pht( '%s enabled account linking.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled account linking.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_UNLINK: if ($new) { return pht( '%s enabled account unlinking.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled account unlinking.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_TRUST_EMAILS: if ($new) { return pht( '%s enabled email trust.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled email trust.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_AUTO_LOGIN: if ($new) { return pht( '%s enabled auto login.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled auto login.', $this->renderHandleLink($author_phid)); } break; case self::TYPE_PROPERTY: $provider = $this->getProvider(); if ($provider) { $title = $provider->renderConfigPropertyTransactionTitle($this); if (strlen($title)) { return $title; } } return pht( '%s edited a property of this provider.', $this->renderHandleLink($author_phid)); break; } return parent::getTitle(); } } diff --git a/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php b/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php index bb08310cf3..028be1746d 100644 --- a/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php +++ b/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php @@ -1,59 +1,55 @@ getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: return pht( '%s created this key.', $this->renderHandleLink($author_phid)); case self::TYPE_NAME: return pht( '%s renamed this key from "%s" to "%s".', $this->renderHandleLink($author_phid), $old, $new); case self::TYPE_KEY: return pht( '%s updated the public key material for this SSH key.', $this->renderHandleLink($author_phid)); case self::TYPE_DEACTIVATE: if ($new) { return pht( '%s revoked this key.', $this->renderHandleLink($author_phid)); } else { return pht( '%s reinstated this key.', $this->renderHandleLink($author_phid)); } } return parent::getTitle(); } } diff --git a/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php b/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php index 1c8a593a78..932e04db4b 100644 --- a/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php +++ b/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php @@ -1,428 +1,446 @@ newIssue('config.unknown.'.$key) ->setShortName($short) ->setName($name) ->setSummary($summary); $stack = PhabricatorEnv::getConfigSourceStack(); $stack = $stack->getStack(); $found = array(); $found_local = false; $found_database = false; foreach ($stack as $source_key => $source) { $value = $source->getKeys(array($key)); if ($value) { $found[] = $source->getName(); if ($source instanceof PhabricatorConfigDatabaseSource) { $found_database = true; } if ($source instanceof PhabricatorConfigLocalSource) { $found_local = true; } } } $message = $message."\n\n".pht( 'This configuration value is defined in these %d '. 'configuration source(s): %s.', count($found), implode(', ', $found)); $issue->setMessage($message); if ($found_local) { $command = csprintf('phabricator/ $ ./bin/config delete %s', $key); $issue->addCommand($command); } if ($found_database) { $issue->addPhabricatorConfig($key); } } + + + if (PhabricatorEnv::getEnvConfig('feed.http-hooks')) { + $this->newIssue('config.deprecated.feed.http-hooks') + ->setShortName(pht('Feed Hooks Deprecated')) + ->setName(pht('Migrate From "feed.http-hooks" to Webhooks')) + ->addPhabricatorConfig('feed.http-hooks') + ->setMessage( + pht( + 'The "feed.http-hooks" option is deprecated in favor of '. + 'Webhooks. This option will be removed in a future version '. + 'of Phabricator.'. + "\n\n". + 'You can configure Webhooks in Herald.'. + "\n\n". + 'To resolve this issue, remove all URIs from "feed.http-hooks".')); + } + } /** * Return a map of deleted config options. Keys are option keys; values are * explanations of what happened to the option. */ public static function getAncientConfig() { $reason_auth = pht( 'This option has been migrated to the "Auth" application. Your old '. 'configuration is still in effect, but now stored in "Auth" instead of '. 'configuration. Going forward, you can manage authentication from '. 'the web UI.'); $auth_config = array( 'controller.oauth-registration', 'auth.password-auth-enabled', 'facebook.auth-enabled', 'facebook.registration-enabled', 'facebook.auth-permanent', 'facebook.application-id', 'facebook.application-secret', 'facebook.require-https-auth', 'github.auth-enabled', 'github.registration-enabled', 'github.auth-permanent', 'github.application-id', 'github.application-secret', 'google.auth-enabled', 'google.registration-enabled', 'google.auth-permanent', 'google.application-id', 'google.application-secret', 'ldap.auth-enabled', 'ldap.hostname', 'ldap.port', 'ldap.base_dn', 'ldap.search_attribute', 'ldap.search-first', 'ldap.username-attribute', 'ldap.real_name_attributes', 'ldap.activedirectory_domain', 'ldap.version', 'ldap.referrals', 'ldap.anonymous-user-name', 'ldap.anonymous-user-password', 'ldap.start-tls', 'disqus.auth-enabled', 'disqus.registration-enabled', 'disqus.auth-permanent', 'disqus.application-id', 'disqus.application-secret', 'phabricator.oauth-uri', 'phabricator.auth-enabled', 'phabricator.registration-enabled', 'phabricator.auth-permanent', 'phabricator.application-id', 'phabricator.application-secret', ); $ancient_config = array_fill_keys($auth_config, $reason_auth); $markup_reason = pht( 'Custom remarkup rules are now added by subclassing '. '%s or %s.', 'PhabricatorRemarkupCustomInlineRule', 'PhabricatorRemarkupCustomBlockRule'); $session_reason = pht( 'Sessions now expire and are garbage collected rather than having an '. 'arbitrary concurrency limit.'); $differential_field_reason = pht( 'All Differential fields are now managed through the configuration '. 'option "%s". Use that option to configure which fields are shown.', 'differential.fields'); $reply_domain_reason = pht( 'Individual application reply handler domains have been removed. '. 'Configure a reply domain with "%s".', 'metamta.reply-handler-domain'); $reply_handler_reason = pht( 'Reply handlers can no longer be overridden with configuration.'); $monospace_reason = pht( 'Phabricator no longer supports global customization of monospaced '. 'fonts.'); $public_mail_reason = pht( 'Inbound mail addresses are now configured for each application '. 'in the Applications tool.'); $gc_reason = pht( 'Garbage collectors are now configured with "%s".', 'bin/garbage set-policy'); $aphlict_reason = pht( 'Configuration of the notification server has changed substantially. '. 'For discussion, see T10794.'); $stale_reason = pht( 'The Differential revision list view age UI elements have been removed '. 'to simplify the interface.'); $global_settings_reason = pht( 'The "Re: Prefix" and "Vary Subjects" settings are now configured '. 'in global settings.'); $dashboard_reason = pht( 'This option has been removed, you can use Dashboards to provide '. 'homepage customization. See T11533 for more details.'); $elastic_reason = pht( 'Elasticsearch is now configured with "%s".', 'cluster.search'); $mailers_reason = pht( 'Inbound and outbound mail is now configured with "cluster.mailers".'); $prefix_reason = pht( 'Per-application mail subject prefix customization is no longer '. 'directly supported. Prefixes and other strings may be customized with '. '"translation.override".'); $ancient_config += array( 'phid.external-loaders' => pht( 'External loaders have been replaced. Extend `%s` '. 'to implement new PHID and handle types.', 'PhabricatorPHIDType'), 'maniphest.custom-task-extensions-class' => pht( 'Maniphest fields are now loaded automatically. '. 'You can configure them with `%s`.', 'maniphest.fields'), 'maniphest.custom-fields' => pht( 'Maniphest fields are now defined in `%s`. '. 'Existing definitions have been migrated.', 'maniphest.custom-field-definitions'), 'differential.custom-remarkup-rules' => $markup_reason, 'differential.custom-remarkup-block-rules' => $markup_reason, 'auth.sshkeys.enabled' => pht( 'SSH keys are now actually useful, so they are always enabled.'), 'differential.anonymous-access' => pht( 'Phabricator now has meaningful global access controls. See `%s`.', 'policy.allow-public'), 'celerity.resource-path' => pht( 'An alternate resource map is no longer supported. Instead, use '. 'multiple maps. See T4222.'), 'metamta.send-immediately' => pht( 'Mail is now always delivered by the daemons.'), 'auth.sessions.conduit' => $session_reason, 'auth.sessions.web' => $session_reason, 'tokenizer.ondemand' => pht( 'Phabricator now manages typeahead strategies automatically.'), 'differential.revision-custom-detail-renderer' => pht( 'Obsolete; use standard rendering events instead.'), 'differential.show-host-field' => $differential_field_reason, 'differential.show-test-plan-field' => $differential_field_reason, 'differential.field-selector' => $differential_field_reason, 'phabricator.show-beta-applications' => pht( 'This option has been renamed to `%s` to emphasize the '. 'unfinished nature of many prototype applications. '. 'Your existing setting has been migrated.', 'phabricator.show-prototypes'), 'notification.user' => pht( 'The notification server no longer requires root permissions. Start '. 'the server as the user you want it to run under.'), 'notification.debug' => pht( 'Notifications no longer have a dedicated debugging mode.'), 'translation.provider' => pht( 'The translation implementation has changed and providers are no '. 'longer used or supported.'), 'config.mask' => pht( 'Use `%s` instead of this option.', 'config.hide'), 'phd.start-taskmasters' => pht( 'Taskmasters now use an autoscaling pool. You can configure the '. 'pool size with `%s`.', 'phd.taskmasters'), 'storage.engine-selector' => pht( 'Phabricator now automatically discovers available storage engines '. 'at runtime.'), 'storage.upload-size-limit' => pht( 'Phabricator now supports arbitrarily large files. Consult the '. 'documentation for configuration details.'), 'security.allow-outbound-http' => pht( 'This option has been replaced with the more granular option `%s`.', 'security.outbound-blacklist'), 'metamta.reply.show-hints' => pht( 'Phabricator no longer shows reply hints in mail.'), 'metamta.differential.reply-handler-domain' => $reply_domain_reason, 'metamta.diffusion.reply-handler-domain' => $reply_domain_reason, 'metamta.macro.reply-handler-domain' => $reply_domain_reason, 'metamta.maniphest.reply-handler-domain' => $reply_domain_reason, 'metamta.pholio.reply-handler-domain' => $reply_domain_reason, 'metamta.diffusion.reply-handler' => $reply_handler_reason, 'metamta.differential.reply-handler' => $reply_handler_reason, 'metamta.maniphest.reply-handler' => $reply_handler_reason, 'metamta.package.reply-handler' => $reply_handler_reason, 'metamta.precedence-bulk' => pht( 'Phabricator now always sends transaction mail with '. '"Precedence: bulk" to improve deliverability.'), 'style.monospace' => $monospace_reason, 'style.monospace.windows' => $monospace_reason, 'search.engine-selector' => pht( 'Phabricator now automatically discovers available search engines '. 'at runtime.'), 'metamta.files.public-create-email' => $public_mail_reason, 'metamta.maniphest.public-create-email' => $public_mail_reason, 'metamta.maniphest.default-public-author' => $public_mail_reason, 'metamta.paste.public-create-email' => $public_mail_reason, 'security.allow-conduit-act-as-user' => pht( 'Impersonating users over the API is no longer supported.'), 'feed.public' => pht('The framable public feed is no longer supported.'), 'auth.login-message' => pht( 'This configuration option has been replaced with a modular '. 'handler. See T9346.'), 'gcdaemon.ttl.herald-transcripts' => $gc_reason, 'gcdaemon.ttl.daemon-logs' => $gc_reason, 'gcdaemon.ttl.differential-parse-cache' => $gc_reason, 'gcdaemon.ttl.markup-cache' => $gc_reason, 'gcdaemon.ttl.task-archive' => $gc_reason, 'gcdaemon.ttl.general-cache' => $gc_reason, 'gcdaemon.ttl.conduit-logs' => $gc_reason, 'phd.variant-config' => pht( 'This configuration is no longer relevant because daemons '. 'restart automatically on configuration changes.'), 'notification.ssl-cert' => $aphlict_reason, 'notification.ssl-key' => $aphlict_reason, 'notification.pidfile' => $aphlict_reason, 'notification.log' => $aphlict_reason, 'notification.enabled' => $aphlict_reason, 'notification.client-uri' => $aphlict_reason, 'notification.server-uri' => $aphlict_reason, 'metamta.differential.unified-comment-context' => pht( 'Inline comments are now always rendered with a limited amount '. 'of context.'), 'differential.days-fresh' => $stale_reason, 'differential.days-stale' => $stale_reason, 'metamta.re-prefix' => $global_settings_reason, 'metamta.vary-subjects' => $global_settings_reason, 'ui.custom-header' => pht( 'This option has been replaced with `ui.logo`, which provides more '. 'flexible configuration options.'), 'welcome.html' => $dashboard_reason, 'maniphest.priorities.unbreak-now' => $dashboard_reason, 'maniphest.priorities.needs-triage' => $dashboard_reason, 'mysql.implementation' => pht( 'Phabricator now automatically selects the best available '. 'MySQL implementation.'), 'mysql.configuration-provider' => pht( 'Phabricator now has application-level management of partitioning '. 'and replicas.'), 'search.elastic.host' => $elastic_reason, 'search.elastic.namespace' => $elastic_reason, 'metamta.mail-adapter' => $mailers_reason, 'amazon-ses.access-key' => $mailers_reason, 'amazon-ses.secret-key' => $mailers_reason, 'amazon-ses.endpoint' => $mailers_reason, 'mailgun.domain' => $mailers_reason, 'mailgun.api-key' => $mailers_reason, 'phpmailer.mailer' => $mailers_reason, 'phpmailer.smtp-host' => $mailers_reason, 'phpmailer.smtp-port' => $mailers_reason, 'phpmailer.smtp-protocol' => $mailers_reason, 'phpmailer.smtp-user' => $mailers_reason, 'phpmailer.smtp-password' => $mailers_reason, 'phpmailer.smtp-encoding' => $mailers_reason, 'sendgrid.api-user' => $mailers_reason, 'sendgrid.api-key' => $mailers_reason, 'celerity.resource-hash' => pht( 'This option generally did not prove useful. Resource hash keys '. 'are now managed automatically.'), 'celerity.enable-deflate' => pht( 'Resource deflation is now managed automatically.'), 'celerity.minify' => pht( 'Resource minification is now managed automatically.'), 'metamta.domain' => pht( 'Mail thread IDs are now generated automatically.'), 'metamta.placeholder-to-recipient' => pht( 'Placeholder recipients are now generated automatically.'), 'metamta.mail-key' => pht( 'Mail object address hash keys are now generated automatically.'), 'phabricator.csrf-key' => pht( 'CSRF HMAC keys are now managed automatically.'), 'metamta.insecure-auth-with-reply-to' => pht( 'Authenticating users based on "Reply-To" is no longer supported.'), 'phabricator.allow-email-users' => pht( 'Public email is now accepted if the associated address has a '. 'default author, and rejected otherwise.'), 'metamta.conpherence.subject-prefix' => $prefix_reason, 'metamta.differential.subject-prefix' => $prefix_reason, 'metamta.diffusion.subject-prefix' => $prefix_reason, 'metamta.files.subject-prefix' => $prefix_reason, 'metamta.legalpad.subject-prefix' => $prefix_reason, 'metamta.macro.subject-prefix' => $prefix_reason, 'metamta.maniphest.subject-prefix' => $prefix_reason, 'metamta.package.subject-prefix' => $prefix_reason, 'metamta.paste.subject-prefix' => $prefix_reason, 'metamta.pholio.subject-prefix' => $prefix_reason, 'metamta.phriction.subject-prefix' => $prefix_reason, 'aphront.default-application-configuration-class' => pht( 'This ancient extension point has been replaced with other '. 'mechanisms, including "AphrontSite".'), ); return $ancient_config; } } diff --git a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php index ce24d48ead..7e6978dfd8 100644 --- a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php +++ b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php @@ -1,288 +1,309 @@ 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 )); $mailers_description = $this->deformat(pht(<<deformat(pht(<<newOption('cluster.mailers', 'cluster.mailers', array()) ->setHidden(true) ->setDescription($mailers_description), $this->newOption('metamta.default-address', 'string', null) - ->setDescription(pht('Default "From" address.')), + ->setLocked(true) + ->setSummary(pht('Default address used when generating mail.')) + ->setDescription($default_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.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.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' => pht('Short'), 'real' => pht('Real'), 'full' => pht('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/config/storage/PhabricatorConfigTransaction.php b/src/applications/config/storage/PhabricatorConfigTransaction.php index b7cfb6f495..94272bfb1a 100644 --- a/src/applications/config/storage/PhabricatorConfigTransaction.php +++ b/src/applications/config/storage/PhabricatorConfigTransaction.php @@ -1,156 +1,152 @@ getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_EDIT: // TODO: After T2213 show the actual values too; for now, we don't // have the tools to do it without making a bit of a mess of it. $old_del = idx($old, 'deleted'); $new_del = idx($new, 'deleted'); if ($old_del && !$new_del) { return pht( '%s created this configuration entry.', $this->renderHandleLink($author_phid)); } else if (!$old_del && $new_del) { return pht( '%s deleted this configuration entry.', $this->renderHandleLink($author_phid)); } else if ($old_del && $new_del) { // This is a bug. return pht( '%s deleted this configuration entry (again?).', $this->renderHandleLink($author_phid)); } else { return pht( '%s edited this configuration entry.', $this->renderHandleLink($author_phid)); } break; } return parent::getTitle(); } public function getTitleForFeed() { $author_phid = $this->getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_EDIT: $old_del = idx($old, 'deleted'); $new_del = idx($new, 'deleted'); if ($old_del && !$new_del) { return pht( '%s created %s.', $this->renderHandleLink($author_phid), $this->getObject()->getConfigKey()); } else if (!$old_del && $new_del) { return pht( '%s deleted %s.', $this->renderHandleLink($author_phid), $this->getObject()->getConfigKey()); } else if ($old_del && $new_del) { // This is a bug. return pht( '%s deleted %s (again?).', $this->renderHandleLink($author_phid), $this->getObject()->getConfigKey()); } else { return pht( '%s edited %s.', $this->renderHandleLink($author_phid), $this->getObject()->getConfigKey()); } break; } return parent::getTitle(); } public function getIcon() { switch ($this->getTransactionType()) { case self::TYPE_EDIT: return 'fa-pencil'; } return parent::getIcon(); } public function hasChangeDetails() { switch ($this->getTransactionType()) { case self::TYPE_EDIT: return true; } return parent::hasChangeDetails(); } public function renderChangeDetails(PhabricatorUser $viewer) { $old = $this->getOldValue(); $new = $this->getNewValue(); if ($old['deleted']) { $old_text = ''; } else { $old_text = PhabricatorConfigJSON::prettyPrintJSON($old['value']); } if ($new['deleted']) { $new_text = ''; } else { $new_text = PhabricatorConfigJSON::prettyPrintJSON($new['value']); } return $this->renderTextCorpusChangeDetails( $viewer, $old_text, $new_text); } public function getColor() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_EDIT: $old_del = idx($old, 'deleted'); $new_del = idx($new, 'deleted'); if ($old_del && !$new_del) { return PhabricatorTransactions::COLOR_GREEN; } else if (!$old_del && $new_del) { return PhabricatorTransactions::COLOR_RED; } else { return PhabricatorTransactions::COLOR_BLUE; } break; } } } diff --git a/src/applications/differential/controller/DifferentialDiffCreateController.php b/src/applications/differential/controller/DifferentialDiffCreateController.php index 36f0b86202..284edf49d3 100644 --- a/src/applications/differential/controller/DifferentialDiffCreateController.php +++ b/src/applications/differential/controller/DifferentialDiffCreateController.php @@ -1,212 +1,212 @@ getViewer(); // If we're on the "Update Diff" workflow, load the revision we're going // to update. $revision = null; $revision_id = $request->getURIData('revisionID'); if ($revision_id) { $revision = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withIDs(array($revision_id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$revision) { return new Aphront404Response(); } } $diff = null; // This object is just for policy stuff $diff_object = DifferentialDiff::initializeNewDiff($viewer); $repository_phid = null; $errors = array(); $e_diff = null; $e_file = null; $validation_exception = null; if ($request->isFormPost()) { $repository_tokenizer = $request->getArr( id(new DifferentialRepositoryField())->getFieldKey()); if ($repository_tokenizer) { $repository_phid = reset($repository_tokenizer); } if ($request->getFileExists('diff-file')) { $diff = PhabricatorFile::readUploadedFileData($_FILES['diff-file']); } else { $diff = $request->getStr('diff'); } if (!strlen($diff)) { $errors[] = pht( 'You can not create an empty diff. Paste a diff or upload a '. 'file containing a diff.'); $e_diff = pht('Required'); $e_file = pht('Required'); } if (!$errors) { try { $call = new ConduitCall( 'differential.createrawdiff', array( 'diff' => $diff, 'repositoryPHID' => $repository_phid, 'viewPolicy' => $request->getStr('viewPolicy'), )); $call->setUser($viewer); $result = $call->execute(); $diff_id = $result['id']; $uri = $this->getApplicationURI("diff/{$diff_id}/"); $uri = new PhutilURI($uri); if ($revision) { $uri->setQueryParam('revisionID', $revision->getID()); } return id(new AphrontRedirectResponse())->setURI($uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; } } } $form = new AphrontFormView(); $arcanist_href = PhabricatorEnv::getDoclink('Arcanist User Guide'); $arcanist_link = phutil_tag( 'a', array( 'href' => $arcanist_href, 'target' => '_blank', ), pht('Learn More')); $cancel_uri = $this->getApplicationURI(); $policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) ->setObject($diff_object) ->execute(); $info_view = null; if (!$request->isFormPost()) { $info_view = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setErrors( array( array( pht( 'The best way to create a diff is to use the Arcanist '. 'command-line tool.'), ' ', $arcanist_link, ), pht( - 'You can also paste a diff below, or upload a file '. + 'You can also paste a diff above, or upload a file '. 'containing a diff (for example, from %s, %s or %s).', phutil_tag('tt', array(), 'svn diff'), phutil_tag('tt', array(), 'git diff'), phutil_tag('tt', array(), 'hg diff --git')), )); } if ($revision) { $title = pht('Update Diff'); $header = pht('Update Diff'); $button = pht('Continue'); $header_icon = 'fa-upload'; } else { $title = pht('Create Diff'); $header = pht('Create New Diff'); $button = pht('Create Diff'); $header_icon = 'fa-plus-square'; } $form ->setEncType('multipart/form-data') ->setUser($viewer); if ($revision) { $form->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Updating Revision')) ->setValue($viewer->renderHandle($revision->getPHID()))); } if ($repository_phid) { $repository_value = array($repository_phid); } else { $repository_value = array(); } $form ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel(pht('Raw Diff')) ->setName('diff') ->setValue($diff) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) ->setError($e_diff)) ->appendChild( id(new AphrontFormFileControl()) ->setLabel(pht('Raw Diff From File')) ->setName('diff-file') ->setError($e_file)) ->appendControl( id(new AphrontFormTokenizerControl()) ->setName(id(new DifferentialRepositoryField())->getFieldKey()) ->setLabel(pht('Repository')) ->setDatasource(new DiffusionRepositoryDatasource()) ->setValue($repository_value) ->setLimit(1)) ->appendChild( id(new AphrontFormPolicyControl()) ->setUser($viewer) ->setName('viewPolicy') ->setPolicyObject($diff_object) ->setPolicies($policies) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)) ->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($cancel_uri) ->setValue($button)); $form_box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setValidationException($validation_exception) ->setForm($form) ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) ->setFormErrors($errors); $crumbs = $this->buildApplicationCrumbs(); if ($revision) { $crumbs->addTextCrumb( $revision->getMonogram(), '/'.$revision->getMonogram()); } $crumbs->addTextCrumb($title); $crumbs->setBorder(true); $view = id(new PHUITwoColumnView()) ->setFooter(array( $form_box, $info_view, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } } diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php index 54be7dd7f1..6a863a4a92 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseController.php @@ -1,1125 +1,1122 @@ loadDiffusionContext(); if ($response) { return $response; } $drequest = $this->getDiffusionRequest(); // Figure out if we're browsing a directory, a file, or a search result // list. $grep = $request->getStr('grep'); if (strlen($grep)) { return $this->browseSearch(); } $pager = id(new PHUIPagerView()) ->readFromRequest($request); $results = DiffusionBrowseResultSet::newFromConduit( $this->callConduitWithDiffusionRequest( 'diffusion.browsequery', array( 'path' => $drequest->getPath(), 'commit' => $drequest->getStableCommit(), 'offset' => $pager->getOffset(), 'limit' => $pager->getPageSize() + 1, ))); $reason = $results->getReasonForEmptyResultSet(); $is_file = ($reason == DiffusionBrowseResultSet::REASON_IS_FILE); if ($is_file) { return $this->browseFile(); } $paths = $results->getPaths(); $paths = $pager->sliceResults($paths); $results->setPaths($paths); return $this->browseDirectory($results, $pager); } private function browseSearch() { $drequest = $this->getDiffusionRequest(); $header = $this->buildHeaderView($drequest); $path = nonempty(basename($drequest->getPath()), '/'); $search_results = $this->renderSearchResults(); $search_form = $this->renderSearchForm($path); $search_form = phutil_tag( 'div', array( 'class' => 'diffusion-mobile-search-form', ), $search_form); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'browse', )); $crumbs->setBorder(true); $tabs = $this->buildTabsView('code'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setTabs($tabs) ->setFooter( array( $search_form, $search_results, )); return $this->newPage() ->setTitle( array( nonempty(basename($drequest->getPath()), '/'), $drequest->getRepository()->getDisplayName(), )) ->setCrumbs($crumbs) ->appendChild($view); } private function browseFile() { $viewer = $this->getViewer(); $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $before = $request->getStr('before'); if ($before) { return $this->buildBeforeResponse($before); } $path = $drequest->getPath(); $params = array( 'commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), ); $view = $request->getStr('view'); $byte_limit = null; if ($view !== 'raw') { $byte_limit = PhabricatorFileStorageEngine::getChunkThreshold(); $time_limit = 10; $params += array( 'timeout' => $time_limit, 'byteLimit' => $byte_limit, ); } $response = $this->callConduitWithDiffusionRequest( 'diffusion.filecontentquery', $params); $hit_byte_limit = $response['tooHuge']; $hit_time_limit = $response['tooSlow']; $file_phid = $response['filePHID']; $show_editor = false; if ($hit_byte_limit) { $corpus = $this->buildErrorCorpus( pht( 'This file is larger than %s byte(s), and too large to display '. 'in the web UI.', phutil_format_bytes($byte_limit))); } else if ($hit_time_limit) { $corpus = $this->buildErrorCorpus( pht( 'This file took too long to load from the repository (more than '. '%s second(s)).', new PhutilNumber($time_limit))); } else { $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($file_phid)) ->executeOne(); if (!$file) { throw new Exception(pht('Failed to load content file!')); } if ($view === 'raw') { return $file->getRedirectResponse(); } $data = $file->loadFileData(); $lfs_ref = $this->getGitLFSRef($repository, $data); if ($lfs_ref) { if ($view == 'git-lfs') { $file = $this->loadGitLFSFile($lfs_ref); // Rename the file locally so we generate a better vanity URI for // it. In storage, it just has a name like "lfs-13f9a94c0923...", // since we don't get any hints about possible human-readable names // at upload time. $basename = basename($drequest->getPath()); $file->makeEphemeral(); $file->setName($basename); return $file->getRedirectResponse(); } $corpus = $this->buildGitLFSCorpus($lfs_ref); } else { $show_editor = true; $ref = id(new PhabricatorDocumentRef()) ->setFile($file); $engine = id(new DiffusionDocumentRenderingEngine()) ->setRequest($request) ->setDiffusionRequest($drequest); $corpus = $engine->newDocumentView($ref); $this->corpusButtons[] = $this->renderFileButton(); } } $bar = $this->buildButtonBar($drequest, $show_editor); $header = $this->buildHeaderView($drequest); $header->setHeaderIcon('fa-file-code-o'); $follow = $request->getStr('follow'); $follow_notice = null; if ($follow) { $follow_notice = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setTitle(pht('Unable to Continue')); switch ($follow) { case 'first': $follow_notice->appendChild( pht( 'Unable to continue tracing the history of this file because '. 'this commit is the first commit in the repository.')); break; case 'created': $follow_notice->appendChild( pht( 'Unable to continue tracing the history of this file because '. 'this commit created the file.')); break; } } $renamed = $request->getStr('renamed'); $renamed_notice = null; if ($renamed) { $renamed_notice = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setTitle(pht('File Renamed')) ->appendChild( pht( 'File history passes through a rename from "%s" to "%s".', $drequest->getPath(), $renamed)); } $open_revisions = $this->buildOpenRevisions(); $owners_list = $this->buildOwnersList($drequest); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'browse', )); $crumbs->setBorder(true); $basename = basename($this->getDiffusionRequest()->getPath()); $tabs = $this->buildTabsView('code'); $bar->setRight($this->corpusButtons); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setTabs($tabs) ->setFooter(array( $bar, $follow_notice, $renamed_notice, $corpus, $open_revisions, $owners_list, )); $title = array($basename, $repository->getDisplayName()); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild( array( $view, )); } public function browseDirectory( DiffusionBrowseResultSet $results, PHUIPagerView $pager) { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $reason = $results->getReasonForEmptyResultSet(); $this->buildActionButtons($drequest, true); $details = $this->buildPropertyView($drequest); $header = $this->buildHeaderView($drequest); $header->setHeaderIcon('fa-folder-open'); $empty_result = null; $browse_panel = null; $branch_panel = null; if (!$results->isValidResults()) { $empty_result = new DiffusionEmptyResultView(); $empty_result->setDiffusionRequest($drequest); $empty_result->setDiffusionBrowseResultSet($results); $empty_result->setView($request->getStr('view')); } else { $phids = array(); foreach ($results->getPaths() as $result) { $data = $result->getLastCommitData(); if ($data) { if ($data->getCommitDetail('authorPHID')) { $phids[$data->getCommitDetail('authorPHID')] = true; } } } $phids = array_keys($phids); $handles = $this->loadViewerHandles($phids); $browse_table = id(new DiffusionBrowseTableView()) ->setDiffusionRequest($drequest) ->setHandles($handles) ->setPaths($results->getPaths()) ->setUser($request->getUser()); $title = nonempty(basename($drequest->getPath()), '/'); $icon = 'fa-folder-open'; $browse_header = $this->buildPanelHeaderView($title, $icon); $browse_panel = id(new PHUIObjectBoxView()) ->setHeader($browse_header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setTable($browse_table) ->addClass('diffusion-mobile-view') ->setPager($pager); $path = $drequest->getPath(); $is_branch = (!strlen($path) && $repository->supportsBranchComparison()); if ($is_branch) { $branch_panel = $this->buildBranchTable(); } } $open_revisions = $this->buildOpenRevisions(); $readme = $this->renderDirectoryReadme($results); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'browse', )); $crumbs->setBorder(true); $tabs = $this->buildTabsView('code'); $owners_list = $this->buildOwnersList($drequest); $bar = id(new PHUILeftRightView()) ->setRight($this->corpusButtons) ->addClass('diffusion-action-bar'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setTabs($tabs) ->setFooter( array( $bar, $branch_panel, $empty_result, $browse_panel, $open_revisions, $owners_list, $readme, )); if ($details) { $view->addPropertySection(pht('Details'), $details); } return $this->newPage() ->setTitle(array( nonempty(basename($drequest->getPath()), '/'), $repository->getDisplayName(), )) ->setCrumbs($crumbs) ->appendChild( array( $view, )); } private function renderSearchResults() { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $results = array(); $pager = id(new PHUIPagerView()) ->readFromRequest($request); $search_mode = null; switch ($repository->getVersionControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $results = array(); break; default: if (strlen($this->getRequest()->getStr('grep'))) { $search_mode = 'grep'; $query_string = $request->getStr('grep'); $results = $this->callConduitWithDiffusionRequest( 'diffusion.searchquery', array( 'grep' => $query_string, 'commit' => $drequest->getStableCommit(), 'path' => $drequest->getPath(), 'limit' => $pager->getPageSize() + 1, 'offset' => $pager->getOffset(), )); } break; } $results = $pager->sliceResults($results); $table = null; $header = null; if ($search_mode == 'grep') { $table = $this->renderGrepResults($results, $query_string); $title = pht( 'File content matching "%s" under "%s"', $query_string, nonempty($drequest->getPath(), '/')); $header = id(new PHUIHeaderView()) ->setHeader($title) ->addClass('diffusion-search-result-header'); } return array($header, $table, $pager); } private function renderGrepResults(array $results, $pattern) { $drequest = $this->getDiffusionRequest(); require_celerity_resource('phabricator-search-results-css'); if (!$results) { return id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) ->appendChild( pht( 'The pattern you searched for was not found in the content of any '. 'files.')); } $grouped = array(); foreach ($results as $file) { list($path, $line, $string) = $file; $grouped[$path][] = array($line, $string); } $view = array(); foreach ($grouped as $path => $matches) { $view[] = id(new DiffusionPatternSearchView()) ->setPath($path) ->setMatches($matches) ->setPattern($pattern) ->setDiffusionRequest($drequest) ->render(); } return $view; } private function buildButtonBar( DiffusionRequest $drequest, $show_editor) { $viewer = $this->getViewer(); $base_uri = $this->getRequest()->getRequestURI(); $user = $this->getRequest()->getUser(); $repository = $drequest->getRepository(); $path = $drequest->getPath(); $line = nonempty((int)$drequest->getLine(), 1); $buttons = array(); $editor_link = $user->loadEditorLink($path, $line, $repository); $template = $user->loadEditorLink($path, '%l', $repository); $buttons[] = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Last Change')) ->setColor(PHUIButtonView::GREY) ->setHref( $drequest->generateURI( array( 'action' => 'change', ))) ->setIcon('fa-backward'); if ($editor_link) { $buttons[] = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Open File')) ->setHref($editor_link) ->setIcon('fa-pencil') ->setID('editor_link') ->setMetadata(array('link_template' => $template)) ->setDisabled(!$editor_link) ->setColor(PHUIButtonView::GREY); } $bar = id(new PHUILeftRightView()) ->setLeft($buttons) ->addClass('diffusion-action-bar full-mobile-buttons'); return $bar; } private function buildOwnersList(DiffusionRequest $drequest) { $viewer = $this->getViewer(); $have_owners = PhabricatorApplication::isClassInstalledForViewer( 'PhabricatorOwnersApplication', $viewer); if (!$have_owners) { return null; } $repository = $drequest->getRepository(); $package_query = id(new PhabricatorOwnersPackageQuery()) ->setViewer($viewer) ->withStatuses(array(PhabricatorOwnersPackage::STATUS_ACTIVE)) ->withControl( $repository->getPHID(), array( $drequest->getPath(), )); $package_query->execute(); $packages = $package_query->getControllingPackagesForPath( $repository->getPHID(), $drequest->getPath()); $ownership = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setNoDataString(pht('No Owners')); if ($packages) { foreach ($packages as $package) { $item = id(new PHUIObjectItemView()) ->setObject($package) ->setObjectName($package->getMonogram()) ->setHeader($package->getName()) ->setHref($package->getURI()); $owners = $package->getOwners(); if ($owners) { $owner_list = $viewer->renderHandleList( mpull($owners, 'getUserPHID')); } else { $owner_list = phutil_tag('em', array(), pht('None')); } $item->addAttribute(pht('Owners: %s', $owner_list)); $auto = $package->getAutoReview(); $autoreview_map = PhabricatorOwnersPackage::getAutoreviewOptionsMap(); $spec = idx($autoreview_map, $auto, array()); $name = idx($spec, 'name', $auto); $item->addIcon('fa-code', $name); - if ($package->getAuditingEnabled()) { - $item->addIcon('fa-check', pht('Auditing Enabled')); - } else { - $item->addIcon('fa-ban', pht('No Auditing')); - } + $rule = $package->newAuditingRule(); + $item->addIcon($rule->getIconIcon(), $rule->getDisplayName()); if ($package->isArchived()) { $item->setDisabled(true); } $ownership->addItem($item); } } $view = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Owner Packages')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addClass('diffusion-mobile-view') ->setObjectList($ownership); return $view; } private function renderFileButton($file_uri = null, $label = null) { $base_uri = $this->getRequest()->getRequestURI(); if ($file_uri) { $text = pht('Download File'); $href = $file_uri; $icon = 'fa-download'; } else { $text = pht('Raw File'); $href = $base_uri->alter('view', 'raw'); $icon = 'fa-file-text'; } if ($label !== null) { $text = $label; } $button = id(new PHUIButtonView()) ->setTag('a') ->setText($text) ->setHref($href) ->setIcon($icon) ->setColor(PHUIButtonView::GREY); return $button; } private function renderGitLFSButton() { $viewer = $this->getViewer(); $uri = $this->getRequest()->getRequestURI(); $href = $uri->alter('view', 'git-lfs'); $text = pht('Download from Git LFS'); $icon = 'fa-download'; return id(new PHUIButtonView()) ->setTag('a') ->setText($text) ->setHref($href) ->setIcon($icon) ->setColor(PHUIButtonView::GREY); } private function buildErrorCorpus($message) { $text = id(new PHUIBoxView()) ->addPadding(PHUI::PADDING_LARGE) ->appendChild($message); $header = id(new PHUIHeaderView()) ->setHeader(pht('Details')); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->appendChild($text); return $box; } private function buildBeforeResponse($before) { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); // NOTE: We need to get the grandparent so we can capture filename changes // in the parent. $parent = $this->loadParentCommitOf($before); $old_filename = null; $was_created = false; if ($parent) { $grandparent = $this->loadParentCommitOf($parent); if ($grandparent) { $rename_query = new DiffusionRenameHistoryQuery(); $rename_query->setRequest($drequest); $rename_query->setOldCommit($grandparent); $rename_query->setViewer($request->getUser()); $old_filename = $rename_query->loadOldFilename(); $was_created = $rename_query->getWasCreated(); } } $follow = null; if ($was_created) { // If the file was created in history, that means older commits won't // have it. Since we know it existed at 'before', it must have been // created then; jump there. $target_commit = $before; $follow = 'created'; } else if ($parent) { // If we found a parent, jump to it. This is the normal case. $target_commit = $parent; } else { // If there's no parent, this was probably created in the initial commit? // And the "was_created" check will fail because we can't identify the // grandparent. Keep the user at 'before'. $target_commit = $before; $follow = 'first'; } $path = $drequest->getPath(); $renamed = null; if ($old_filename !== null && $old_filename !== '/'.$path) { $renamed = $path; $path = $old_filename; } $line = null; // If there's a follow error, drop the line so the user sees the message. if (!$follow) { $line = $this->getBeforeLineNumber($target_commit); } $before_uri = $drequest->generateURI( array( 'action' => 'browse', 'commit' => $target_commit, 'line' => $line, 'path' => $path, )); $before_uri->setQueryParams($request->getRequestURI()->getQueryParams()); $before_uri = $before_uri->alter('before', null); $before_uri = $before_uri->alter('renamed', $renamed); $before_uri = $before_uri->alter('follow', $follow); return id(new AphrontRedirectResponse())->setURI($before_uri); } private function getBeforeLineNumber($target_commit) { $drequest = $this->getDiffusionRequest(); $viewer = $this->getViewer(); $line = $drequest->getLine(); if (!$line) { return null; } $diff_info = $this->callConduitWithDiffusionRequest( 'diffusion.rawdiffquery', array( 'commit' => $drequest->getCommit(), 'path' => $drequest->getPath(), 'againstCommit' => $target_commit, )); $file_phid = $diff_info['filePHID']; $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($file_phid)) ->executeOne(); if (!$file) { throw new Exception( pht( 'Failed to load file ("%s") returned by "%s".', $file_phid, 'diffusion.rawdiffquery.')); } $raw_diff = $file->loadFileData(); $old_line = 0; $new_line = 0; foreach (explode("\n", $raw_diff) as $text) { if ($text[0] == '-' || $text[0] == ' ') { $old_line++; } if ($text[0] == '+' || $text[0] == ' ') { $new_line++; } if ($new_line == $line) { return $old_line; } } // We didn't find the target line. return $line; } private function loadParentCommitOf($commit) { $drequest = $this->getDiffusionRequest(); $user = $this->getRequest()->getUser(); $before_req = DiffusionRequest::newFromDictionary( array( 'user' => $user, 'repository' => $drequest->getRepository(), 'commit' => $commit, )); $parents = DiffusionQuery::callConduitWithDiffusionRequest( $user, $before_req, 'diffusion.commitparentsquery', array( 'commit' => $commit, )); return head($parents); } protected function markupText($text) { $engine = PhabricatorMarkupEngine::newDiffusionMarkupEngine(); $engine->setConfig('viewer', $this->getRequest()->getUser()); $text = $engine->markupText($text); $text = phutil_tag( 'div', array( 'class' => 'phabricator-remarkup', ), $text); return $text; } protected function buildHeaderView(DiffusionRequest $drequest) { $viewer = $this->getViewer(); $repository = $drequest->getRepository(); $commit_tag = $this->renderCommitHashTag($drequest); $path = nonempty($drequest->getPath(), '/'); $search = $this->renderSearchForm($path); $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($this->renderPathLinks($drequest, $mode = 'browse')) ->addActionItem($search) ->addTag($commit_tag) ->addClass('diffusion-browse-header'); if (!$repository->isSVN()) { $branch_tag = $this->renderBranchTag($drequest); $header->addTag($branch_tag); } return $header; } protected function buildPanelHeaderView($title, $icon) { $header = id(new PHUIHeaderView()) ->setHeader($title) ->setHeaderIcon($icon) ->addClass('diffusion-panel-header-view'); return $header; } protected function buildActionButtons( DiffusionRequest $drequest, $is_directory = false) { $viewer = $this->getViewer(); $repository = $drequest->getRepository(); $history_uri = $drequest->generateURI(array('action' => 'history')); $behind_head = $drequest->getSymbolicCommit(); $compare = null; $head_uri = $drequest->generateURI( array( 'commit' => '', 'action' => 'browse', )); if ($repository->supportsBranchComparison() && $is_directory) { $compare_uri = $drequest->generateURI(array('action' => 'compare')); $compare = id(new PHUIButtonView()) ->setText(pht('Compare')) ->setIcon('fa-code-fork') ->setWorkflow(true) ->setTag('a') ->setHref($compare_uri) ->setColor(PHUIButtonView::GREY); $this->corpusButtons[] = $compare; } $head = null; if ($behind_head) { $head = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Back to HEAD')) ->setHref($head_uri) ->setIcon('fa-home') ->setColor(PHUIButtonView::GREY); $this->corpusButtons[] = $head; } $history = id(new PHUIButtonView()) ->setText(pht('History')) ->setHref($history_uri) ->setTag('a') ->setIcon('fa-history') ->setColor(PHUIButtonView::GREY); $this->corpusButtons[] = $history; } protected function buildPropertyView( DiffusionRequest $drequest) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); if ($drequest->getSymbolicType() == 'tag') { $symbolic = $drequest->getSymbolicCommit(); $view->addProperty(pht('Tag'), $symbolic); $tags = $this->callConduitWithDiffusionRequest( 'diffusion.tagsquery', array( 'names' => array($symbolic), 'needMessages' => true, )); $tags = DiffusionRepositoryTag::newFromConduit($tags); $tags = mpull($tags, null, 'getName'); $tag = idx($tags, $symbolic); if ($tag && strlen($tag->getMessage())) { $view->addSectionHeader( pht('Tag Content'), 'fa-tag'); $view->addTextContent($this->markupText($tag->getMessage())); } } if ($view->hasAnyProperties()) { return $view; } return null; } private function buildOpenRevisions() { $viewer = $this->getViewer(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $path = $drequest->getPath(); $path_map = id(new DiffusionPathIDQuery(array($path)))->loadPathIDs(); $path_id = idx($path_map, $path); if (!$path_id) { return null; } $recent = (PhabricatorTime::getNow() - phutil_units('30 days in seconds')); $revisions = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withPath($repository->getID(), $path_id) ->withIsOpen(true) ->withUpdatedEpochBetween($recent, null) ->setOrder(DifferentialRevisionQuery::ORDER_MODIFIED) ->setLimit(10) ->needReviewers(true) ->needFlags(true) ->needDrafts(true) ->execute(); if (!$revisions) { return null; } $header = id(new PHUIHeaderView()) ->setHeader(pht('Recently Open Revisions')); $list = id(new DifferentialRevisionListView()) ->setViewer($viewer) ->setRevisions($revisions) ->setNoBox(true); $view = id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addClass('diffusion-mobile-view') ->appendChild($list); return $view; } private function getGitLFSRef(PhabricatorRepository $repository, $data) { if (!$repository->canUseGitLFS()) { return null; } $lfs_pattern = '(^version https://git-lfs\\.github\\.com/spec/v1[\r\n])'; if (!preg_match($lfs_pattern, $data)) { return null; } $matches = null; if (!preg_match('(^oid sha256:(.*)$)m', $data, $matches)) { return null; } $hash = $matches[1]; $hash = trim($hash); return id(new PhabricatorRepositoryGitLFSRefQuery()) ->setViewer($this->getViewer()) ->withRepositoryPHIDs(array($repository->getPHID())) ->withObjectHashes(array($hash)) ->executeOne(); } private function buildGitLFSCorpus(PhabricatorRepositoryGitLFSRef $ref) { // TODO: We should probably test if we can load the file PHID here and // show the user an error if we can't, rather than making them click // through to hit an error. $title = basename($this->getDiffusionRequest()->getPath()); $icon = 'fa-archive'; $drequest = $this->getDiffusionRequest(); $this->buildActionButtons($drequest); $header = $this->buildPanelHeaderView($title, $icon); $severity = PHUIInfoView::SEVERITY_NOTICE; $messages = array(); $messages[] = pht( 'This %s file is stored in Git Large File Storage.', phutil_format_bytes($ref->getByteSize())); try { $file = $this->loadGitLFSFile($ref); $this->corpusButtons[] = $this->renderGitLFSButton(); } catch (Exception $ex) { $severity = PHUIInfoView::SEVERITY_ERROR; $messages[] = pht('The data for this file could not be loaded.'); } $this->corpusButtons[] = $this->renderFileButton( null, pht('View Raw LFS Pointer')); $corpus = id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addClass('diffusion-mobile-view') ->setCollapsed(true); if ($messages) { $corpus->setInfoView( id(new PHUIInfoView()) ->setSeverity($severity) ->setErrors($messages)); } return $corpus; } private function loadGitLFSFile(PhabricatorRepositoryGitLFSRef $ref) { $viewer = $this->getViewer(); $file = id(new PhabricatorFileQuery()) ->setViewer($viewer) ->withPHIDs(array($ref->getFilePHID())) ->executeOne(); if (!$file) { throw new Exception( pht( 'Failed to load file object for Git LFS ref "%s"!', $ref->getObjectHash())); } return $file; } private function buildBranchTable() { $viewer = $this->getViewer(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $branch = $drequest->getBranch(); $default_branch = $repository->getDefaultBranch(); if ($branch === $default_branch) { return null; } $pager = id(new PHUIPagerView()) ->setPageSize(10); try { $results = $this->callConduitWithDiffusionRequest( 'diffusion.historyquery', array( 'commit' => $branch, 'against' => $default_branch, 'path' => $drequest->getPath(), 'offset' => $pager->getOffset(), 'limit' => $pager->getPageSize() + 1, )); } catch (Exception $ex) { return null; } $history = DiffusionPathChange::newFromConduit($results['pathChanges']); $history = $pager->sliceResults($history); if (!$history) { return null; } $history_table = id(new DiffusionHistoryTableView()) ->setViewer($viewer) ->setDiffusionRequest($drequest) ->setHistory($history); $history_table->loadRevisions(); $history_table ->setParents($results['parents']) ->setFilterParents(true) ->setIsHead(true) ->setIsTail(!$pager->getHasMorePages()); $header = id(new PHUIHeaderView()) ->setHeader(pht('%s vs %s', $branch, $default_branch)); return id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->addClass('diffusion-mobile-view') ->setTable($history_table); } } diff --git a/src/applications/diffusion/query/DiffusionCommitQuery.php b/src/applications/diffusion/query/DiffusionCommitQuery.php index 05072e07c7..03eb0b9edf 100644 --- a/src/applications/diffusion/query/DiffusionCommitQuery.php +++ b/src/applications/diffusion/query/DiffusionCommitQuery.php @@ -1,938 +1,975 @@ ids = $ids; return $this; } public function withPHIDs(array $phids) { $this->phids = $phids; return $this; } public function withAuthorPHIDs(array $phids) { $this->authorPHIDs = $phids; return $this; } /** * Load commits by partial or full identifiers, e.g. "rXab82393", "rX1234", * or "a9caf12". When an identifier matches multiple commits, they will all * be returned; callers should be prepared to deal with more results than * they queried for. */ public function withIdentifiers(array $identifiers) { // Some workflows (like blame lookups) can pass in large numbers of // duplicate identifiers. We only care about unique identifiers, so // get rid of duplicates immediately. $identifiers = array_fuse($identifiers); $this->identifiers = $identifiers; return $this; } /** * Look up commits in a specific repository. This is a shorthand for calling * @{method:withDefaultRepository} and @{method:withRepositoryIDs}. */ public function withRepository(PhabricatorRepository $repository) { $this->withDefaultRepository($repository); $this->withRepositoryIDs(array($repository->getID())); return $this; } /** * Look up commits in a specific repository. Prefer * @{method:withRepositoryIDs}; the underlying table is keyed by ID such * that this method requires a separate initial query to map PHID to ID. */ public function withRepositoryPHIDs(array $phids) { $this->repositoryPHIDs = $phids; return $this; } /** * If a default repository is provided, ambiguous commit identifiers will * be assumed to belong to the default repository. * * For example, "r123" appearing in a commit message in repository X is * likely to be unambiguously "rX123". Normally the reference would be * considered ambiguous, but if you provide a default repository it will * be correctly resolved. */ public function withDefaultRepository(PhabricatorRepository $repository) { $this->defaultRepository = $repository; return $this; } public function withRepositoryIDs(array $repository_ids) { $this->repositoryIDs = array_unique($repository_ids); return $this; } public function needCommitData($need) { $this->needCommitData = $need; return $this; } public function needDrafts($need) { $this->needDrafts = $need; return $this; } public function needIdentities($need) { $this->needIdentities = $need; return $this; } public function needAuditRequests($need) { $this->needAuditRequests = $need; return $this; } public function needAuditAuthority(array $users) { assert_instances_of($users, 'PhabricatorUser'); $this->needAuditAuthority = $users; return $this; } public function withAuditIDs(array $ids) { $this->auditIDs = $ids; return $this; } public function withAuditorPHIDs(array $auditor_phids) { $this->auditorPHIDs = $auditor_phids; return $this; } public function withResponsiblePHIDs(array $responsible_phids) { $this->responsiblePHIDs = $responsible_phids; return $this; } public function withPackagePHIDs(array $package_phids) { $this->packagePHIDs = $package_phids; return $this; } public function withUnreachable($unreachable) { $this->unreachable = $unreachable; return $this; } public function withStatuses(array $statuses) { $this->statuses = $statuses; return $this; } public function withEpochRange($min, $max) { $this->epochMin = $min; $this->epochMax = $max; return $this; } public function withImporting($importing) { $this->importing = $importing; return $this; } public function withAncestorsOf(array $refs) { $this->ancestorsOf = $refs; return $this; } public function getIdentifierMap() { if ($this->identifierMap === null) { throw new Exception( pht( 'You must %s the query before accessing the identifier map.', 'execute()')); } return $this->identifierMap; } protected function getPrimaryTableAlias() { return 'commit'; } protected function willExecute() { if ($this->identifierMap === null) { $this->identifierMap = array(); } } public function newResultObject() { return new PhabricatorRepositoryCommit(); } protected function loadPage() { $table = $this->newResultObject(); $conn = $table->establishConnection('r'); + $empty_exception = null; $subqueries = array(); if ($this->responsiblePHIDs) { $base_authors = $this->authorPHIDs; $base_auditors = $this->auditorPHIDs; $responsible_phids = $this->responsiblePHIDs; if ($base_authors) { $all_authors = array_merge($base_authors, $responsible_phids); } else { $all_authors = $responsible_phids; } if ($base_auditors) { $all_auditors = array_merge($base_auditors, $responsible_phids); } else { $all_auditors = $responsible_phids; } $this->authorPHIDs = $all_authors; $this->auditorPHIDs = $base_auditors; - $subqueries[] = $this->buildStandardPageQuery( - $conn, - $table->getTableName()); + try { + $subqueries[] = $this->buildStandardPageQuery( + $conn, + $table->getTableName()); + } catch (PhabricatorEmptyQueryException $ex) { + $empty_exception = $ex; + } $this->authorPHIDs = $base_authors; $this->auditorPHIDs = $all_auditors; - $subqueries[] = $this->buildStandardPageQuery( - $conn, - $table->getTableName()); + try { + $subqueries[] = $this->buildStandardPageQuery( + $conn, + $table->getTableName()); + } catch (PhabricatorEmptyQueryException $ex) { + $empty_exception = $ex; + } } else { $subqueries[] = $this->buildStandardPageQuery( $conn, $table->getTableName()); } + if (!$subqueries) { + throw $empty_exception; + } + if (count($subqueries) > 1) { $unions = null; foreach ($subqueries as $subquery) { if (!$unions) { $unions = qsprintf( $conn, '(%Q)', $subquery); continue; } $unions = qsprintf( $conn, '%Q UNION DISTINCT (%Q)', $unions, $subquery); } $query = qsprintf( $conn, '%Q %Q %Q', $unions, $this->buildOrderClause($conn, true), $this->buildLimitClause($conn)); } else { $query = head($subqueries); } $rows = queryfx_all($conn, '%Q', $query); $rows = $this->didLoadRawRows($rows); return $table->loadAllFromArray($rows); } protected function willFilterPage(array $commits) { $repository_ids = mpull($commits, 'getRepositoryID', 'getRepositoryID'); $repos = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()) ->withIDs($repository_ids) ->execute(); $min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH; $result = array(); foreach ($commits as $key => $commit) { $repo = idx($repos, $commit->getRepositoryID()); if ($repo) { $commit->attachRepository($repo); } else { $this->didRejectResult($commit); unset($commits[$key]); continue; } // Build the identifierMap if ($this->identifiers !== null) { $ids = $this->identifiers; $prefixes = array( 'r'.$commit->getRepository()->getCallsign(), 'r'.$commit->getRepository()->getCallsign().':', 'R'.$commit->getRepository()->getID().':', '', // No prefix is valid too and will only match the commitIdentifier ); $suffix = $commit->getCommitIdentifier(); if ($commit->getRepository()->isSVN()) { foreach ($prefixes as $prefix) { if (isset($ids[$prefix.$suffix])) { $result[$prefix.$suffix][] = $commit; } } } else { // This awkward construction is so we can link the commits up in O(N) // time instead of O(N^2). for ($ii = $min_qualified; $ii <= strlen($suffix); $ii++) { $part = substr($suffix, 0, $ii); foreach ($prefixes as $prefix) { if (isset($ids[$prefix.$part])) { $result[$prefix.$part][] = $commit; } } } } } } if ($result) { foreach ($result as $identifier => $matching_commits) { if (count($matching_commits) == 1) { $result[$identifier] = head($matching_commits); } else { // This reference is ambiguous (it matches more than one commit) so // don't link it. unset($result[$identifier]); } } $this->identifierMap += $result; } return $commits; } protected function didFilterPage(array $commits) { $viewer = $this->getViewer(); if ($this->mustFilterRefs) { // If this flag is set, the query has an "Ancestors Of" constraint and // at least one of the constraining refs had too many ancestors for us // to apply the constraint with a big "commitIdentifier IN (%Ls)" clause. // We're going to filter each page and hope we get a full result set // before the query overheats. $ancestor_list = mpull($commits, 'getCommitIdentifier'); $ancestor_list = array_values($ancestor_list); foreach ($this->ancestorsOf as $ref) { try { $ancestor_list = DiffusionQuery::callConduitWithDiffusionRequest( $viewer, DiffusionRequest::newFromDictionary( array( 'repository' => $this->refRepository, 'user' => $viewer, )), 'diffusion.internal.ancestors', array( 'ref' => $ref, 'commits' => $ancestor_list, )); } catch (ConduitClientException $ex) { throw new PhabricatorSearchConstraintException( $ex->getMessage()); } if (!$ancestor_list) { break; } } $ancestor_list = array_fuse($ancestor_list); foreach ($commits as $key => $commit) { $identifier = $commit->getCommitIdentifier(); if (!isset($ancestor_list[$identifier])) { $this->didRejectResult($commit); unset($commits[$key]); } } if (!$commits) { return $commits; } } if ($this->needCommitData) { $data = id(new PhabricatorRepositoryCommitData())->loadAllWhere( 'commitID in (%Ld)', mpull($commits, 'getID')); $data = mpull($data, null, 'getCommitID'); foreach ($commits as $commit) { $commit_data = idx($data, $commit->getID()); if (!$commit_data) { $commit_data = new PhabricatorRepositoryCommitData(); } $commit->attachCommitData($commit_data); } } if ($this->needAuditRequests) { $requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere( 'commitPHID IN (%Ls)', mpull($commits, 'getPHID')); $requests = mgroup($requests, 'getCommitPHID'); foreach ($commits as $commit) { $audit_requests = idx($requests, $commit->getPHID(), array()); $commit->attachAudits($audit_requests); foreach ($audit_requests as $audit_request) { $audit_request->attachCommit($commit); } } } if ($this->needIdentities) { $identity_phids = array_merge( mpull($commits, 'getAuthorIdentityPHID'), mpull($commits, 'getCommitterIdentityPHID')); $data = id(new PhabricatorRepositoryIdentityQuery()) ->withPHIDs($identity_phids) ->setViewer($this->getViewer()) ->execute(); $data = mpull($data, null, 'getPHID'); foreach ($commits as $commit) { $author_identity = idx($data, $commit->getAuthorIdentityPHID()); $committer_identity = idx($data, $commit->getCommitterIdentityPHID()); $commit->attachIdentities($author_identity, $committer_identity); } } if ($this->needDrafts) { PhabricatorDraftEngine::attachDrafts( $viewer, $commits); } if ($this->needAuditAuthority) { $authority_users = $this->needAuditAuthority; // NOTE: This isn't very efficient since we're running two queries per // user, but there's currently no way to figure out authority for // multiple users in one query. Today, we only ever request authority for // a single user and single commit, so this has no practical impact. // NOTE: We're querying with the viewership of query viewer, not the // actual users. If the viewer can't see a project or package, they // won't be able to see who has authority on it. This is safer than // showing them true authority, and should never matter today, but it // also doesn't seem like a significant disclosure and might be // reasonable to adjust later if it causes something weird or confusing // to happen. $authority_map = array(); foreach ($authority_users as $authority_user) { $authority_phid = $authority_user->getPHID(); if (!$authority_phid) { continue; } $result_phids = array(); // Users have authority over themselves. $result_phids[] = $authority_phid; // Users have authority over packages they own. $owned_packages = id(new PhabricatorOwnersPackageQuery()) ->setViewer($viewer) ->withAuthorityPHIDs(array($authority_phid)) ->execute(); foreach ($owned_packages as $package) { $result_phids[] = $package->getPHID(); } // Users have authority over projects they're members of. $projects = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withMemberPHIDs(array($authority_phid)) ->execute(); foreach ($projects as $project) { $result_phids[] = $project->getPHID(); } $result_phids = array_fuse($result_phids); foreach ($commits as $commit) { $attach_phids = $result_phids; // NOTE: When modifying your own commits, you act only on behalf of // yourself, not your packages or projects. The idea here is that you // can't accept your own commits. In the future, this might change or // depend on configuration. $author_phid = $commit->getAuthorPHID(); if ($author_phid == $authority_phid) { $attach_phids = array($author_phid); $attach_phids = array_fuse($attach_phids); } $commit->attachAuditAuthority($authority_user, $attach_phids); } } } return $commits; } protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); if ($this->repositoryPHIDs !== null) { $map_repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()) ->withPHIDs($this->repositoryPHIDs) ->execute(); if (!$map_repositories) { throw new PhabricatorEmptyQueryException(); } $repository_ids = mpull($map_repositories, 'getID'); if ($this->repositoryIDs !== null) { $repository_ids = array_merge($repository_ids, $this->repositoryIDs); } $this->withRepositoryIDs($repository_ids); } if ($this->ancestorsOf !== null) { if (count($this->repositoryIDs) !== 1) { throw new PhabricatorSearchConstraintException( pht( 'To search for commits which are ancestors of particular refs, '. 'you must constrain the search to exactly one repository.')); } $repository_id = head($this->repositoryIDs); $history_limit = $this->getRawResultLimit() * 32; $viewer = $this->getViewer(); $repository = id(new PhabricatorRepositoryQuery()) ->setViewer($viewer) ->withIDs(array($repository_id)) ->executeOne(); if (!$repository) { throw new PhabricatorEmptyQueryException(); } if ($repository->isSVN()) { throw new PhabricatorSearchConstraintException( pht( 'Subversion does not support searching for ancestors of '. 'a particular ref. This operation is not meaningful in '. 'Subversion.')); } if ($repository->isHg()) { throw new PhabricatorSearchConstraintException( pht( 'Mercurial does not currently support searching for ancestors of '. 'a particular ref.')); } $can_constrain = true; $history_identifiers = array(); foreach ($this->ancestorsOf as $key => $ref) { try { $raw_history = DiffusionQuery::callConduitWithDiffusionRequest( $viewer, DiffusionRequest::newFromDictionary( array( 'repository' => $repository, 'user' => $viewer, )), 'diffusion.historyquery', array( 'commit' => $ref, 'limit' => $history_limit, )); } catch (ConduitClientException $ex) { throw new PhabricatorSearchConstraintException( $ex->getMessage()); } $ref_identifiers = array(); foreach ($raw_history['pathChanges'] as $change) { $ref_identifiers[] = $change['commitIdentifier']; } // If this ref had fewer total commits than the limit, we're safe to // apply the constraint as a large `IN (...)` query for a list of // commit identifiers. This is efficient. if ($history_limit) { if (count($ref_identifiers) >= $history_limit) { $can_constrain = false; break; } } $history_identifiers += array_fuse($ref_identifiers); } // If all refs had a small number of ancestors, we can just put the // constraint into the query here and we're done. Otherwise, we need // to filter each page after it comes out of the MySQL layer. if ($can_constrain) { $where[] = qsprintf( $conn, 'commit.commitIdentifier IN (%Ls)', $history_identifiers); } else { $this->mustFilterRefs = true; $this->refRepository = $repository; } } if ($this->ids !== null) { $where[] = qsprintf( $conn, 'commit.id IN (%Ld)', $this->ids); } if ($this->phids !== null) { $where[] = qsprintf( $conn, 'commit.phid IN (%Ls)', $this->phids); } if ($this->repositoryIDs !== null) { $where[] = qsprintf( $conn, 'commit.repositoryID IN (%Ld)', $this->repositoryIDs); } if ($this->authorPHIDs !== null) { + $author_phids = $this->authorPHIDs; + if ($author_phids) { + $author_phids = $this->selectPossibleAuthors($author_phids); + if (!$author_phids) { + throw new PhabricatorEmptyQueryException( + pht('Author PHIDs contain no possible authors.')); + } + } + $where[] = qsprintf( $conn, 'commit.authorPHID IN (%Ls)', - $this->authorPHIDs); + $author_phids); } if ($this->epochMin !== null) { $where[] = qsprintf( $conn, 'commit.epoch >= %d', $this->epochMin); } if ($this->epochMax !== null) { $where[] = qsprintf( $conn, 'commit.epoch <= %d', $this->epochMax); } if ($this->importing !== null) { if ($this->importing) { $where[] = qsprintf( $conn, '(commit.importStatus & %d) != %d', PhabricatorRepositoryCommit::IMPORTED_ALL, PhabricatorRepositoryCommit::IMPORTED_ALL); } else { $where[] = qsprintf( $conn, '(commit.importStatus & %d) = %d', PhabricatorRepositoryCommit::IMPORTED_ALL, PhabricatorRepositoryCommit::IMPORTED_ALL); } } if ($this->identifiers !== null) { $min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH; $min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH; $refs = array(); $bare = array(); foreach ($this->identifiers as $identifier) { $matches = null; preg_match('/^(?:[rR]([A-Z]+:?|[0-9]+:))?(.*)$/', $identifier, $matches); $repo = nonempty(rtrim($matches[1], ':'), null); $commit_identifier = nonempty($matches[2], null); if ($repo === null) { if ($this->defaultRepository) { $repo = $this->defaultRepository->getPHID(); } } if ($repo === null) { if (strlen($commit_identifier) < $min_unqualified) { continue; } $bare[] = $commit_identifier; } else { $refs[] = array( 'repository' => $repo, 'identifier' => $commit_identifier, ); } } $sql = array(); foreach ($bare as $identifier) { $sql[] = qsprintf( $conn, '(commit.commitIdentifier LIKE %> AND '. 'LENGTH(commit.commitIdentifier) = 40)', $identifier); } if ($refs) { $repositories = ipull($refs, 'repository'); $repos = id(new PhabricatorRepositoryQuery()) ->setViewer($this->getViewer()) ->withIdentifiers($repositories); $repos->execute(); $repos = $repos->getIdentifierMap(); foreach ($refs as $key => $ref) { $repo = idx($repos, $ref['repository']); if (!$repo) { continue; } if ($repo->isSVN()) { if (!ctype_digit((string)$ref['identifier'])) { continue; } $sql[] = qsprintf( $conn, '(commit.repositoryID = %d AND commit.commitIdentifier = %s)', $repo->getID(), // NOTE: Because the 'commitIdentifier' column is a string, MySQL // ignores the index if we hand it an integer. Hand it a string. // See T3377. (int)$ref['identifier']); } else { if (strlen($ref['identifier']) < $min_qualified) { continue; } $identifier = $ref['identifier']; if (strlen($identifier) == 40) { // MySQL seems to do slightly better with this version if the // clause, so issue it if we have a full commit hash. $sql[] = qsprintf( $conn, '(commit.repositoryID = %d AND commit.commitIdentifier = %s)', $repo->getID(), $identifier); } else { $sql[] = qsprintf( $conn, '(commit.repositoryID = %d AND commit.commitIdentifier LIKE %>)', $repo->getID(), $identifier); } } } } if (!$sql) { // If we discarded all possible identifiers (e.g., they all referenced // bogus repositories or were all too short), make sure the query finds // nothing. throw new PhabricatorEmptyQueryException( pht('No commit identifiers.')); } $where[] = qsprintf($conn, '%LO', $sql); } if ($this->auditIDs !== null) { $where[] = qsprintf( $conn, 'auditor.id IN (%Ld)', $this->auditIDs); } if ($this->auditorPHIDs !== null) { $where[] = qsprintf( $conn, 'auditor.auditorPHID IN (%Ls)', $this->auditorPHIDs); } if ($this->statuses !== null) { $statuses = DiffusionCommitAuditStatus::newModernKeys( $this->statuses); $where[] = qsprintf( $conn, 'commit.auditStatus IN (%Ls)', $statuses); } if ($this->packagePHIDs !== null) { $where[] = qsprintf( $conn, 'package.dst IN (%Ls)', $this->packagePHIDs); } if ($this->unreachable !== null) { if ($this->unreachable) { $where[] = qsprintf( $conn, '(commit.importStatus & %d) = %d', PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE, PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE); } else { $where[] = qsprintf( $conn, '(commit.importStatus & %d) = 0', PhabricatorRepositoryCommit::IMPORTED_UNREACHABLE); } } return $where; } protected function didFilterResults(array $filtered) { if ($this->identifierMap) { foreach ($this->identifierMap as $name => $commit) { if (isset($filtered[$commit->getPHID()])) { unset($this->identifierMap[$name]); } } } } private function shouldJoinAuditor() { return ($this->auditIDs || $this->auditorPHIDs); } private function shouldJoinOwners() { return (bool)$this->packagePHIDs; } protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { $join = parent::buildJoinClauseParts($conn); $audit_request = new PhabricatorRepositoryAuditRequest(); if ($this->shouldJoinAuditor()) { $join[] = qsprintf( $conn, 'JOIN %T auditor ON commit.phid = auditor.commitPHID', $audit_request->getTableName()); } if ($this->shouldJoinOwners()) { $join[] = qsprintf( $conn, 'JOIN %T package ON commit.phid = package.src AND package.type = %s', PhabricatorEdgeConfig::TABLE_NAME_EDGE, DiffusionCommitHasPackageEdgeType::EDGECONST); } return $join; } protected function shouldGroupQueryResultRows() { if ($this->shouldJoinAuditor()) { return true; } if ($this->shouldJoinOwners()) { return true; } return parent::shouldGroupQueryResultRows(); } public function getQueryApplicationClass() { return 'PhabricatorDiffusionApplication'; } public function getOrderableColumns() { return parent::getOrderableColumns() + array( 'epoch' => array( 'table' => $this->getPrimaryTableAlias(), 'column' => 'epoch', 'type' => 'int', 'reverse' => false, ), ); } protected function getPagingValueMap($cursor, array $keys) { $commit = $this->loadCursorObject($cursor); return array( 'id' => $commit->getID(), 'epoch' => $commit->getEpoch(), ); } public function getBuiltinOrders() { $parent = parent::getBuiltinOrders(); // Rename the default ID-based orders. $parent['importnew'] = array( 'name' => pht('Import Date (Newest First)'), ) + $parent['newest']; $parent['importold'] = array( 'name' => pht('Import Date (Oldest First)'), ) + $parent['oldest']; return array( 'newest' => array( 'vector' => array('epoch', 'id'), 'name' => pht('Commit Date (Newest First)'), ), 'oldest' => array( 'vector' => array('-epoch', '-id'), 'name' => pht('Commit Date (Oldest First)'), ), ) + $parent; } + private function selectPossibleAuthors(array $phids) { + // See PHI1057. Select PHIDs which might possibly be commit authors from + // a larger list of PHIDs. This primarily filters out packages and projects + // from "Responsible Users: ..." queries. Our goal in performing this + // filtering is to improve the performance of the final query. + + foreach ($phids as $key => $phid) { + if (phid_get_type($phid) !== PhabricatorPeopleUserPHIDType::TYPECONST) { + unset($phids[$key]); + } + } + + return $phids; + } + } diff --git a/src/applications/diviner/storage/DivinerLiveBookTransaction.php b/src/applications/diviner/storage/DivinerLiveBookTransaction.php index ae461e751a..f8eb81d1f3 100644 --- a/src/applications/diviner/storage/DivinerLiveBookTransaction.php +++ b/src/applications/diviner/storage/DivinerLiveBookTransaction.php @@ -1,18 +1,14 @@ deformat(pht(<<newOption('feed.http-hooks', 'list', array()) ->setLocked(true) - ->setSummary(pht('POST notifications of feed events.')) - ->setDescription( - pht( - "If you set this to a list of HTTP URIs, when a feed story is ". - "published a task will be created for each URI that posts the ". - "story data to the URI. Daemons automagically retry failures 100 ". - "times, waiting `\$fail_count * 60s` between each subsequent ". - "failure. Be sure to keep the daemon console (`%s`) open ". - "while developing and testing your end points. You may need to". - "restart your daemons to start sending HTTP requests.\n\n". - "NOTE: URIs are not validated, the URI must return HTTP status ". - "200 within 30 seconds, and no permission checks are performed.", - '/daemon/')), + ->setSummary(pht('Deprecated.')) + ->setDescription($hooks_help), ); } } diff --git a/src/applications/feed/worker/FeedPublisherHTTPWorker.php b/src/applications/feed/worker/FeedPublisherHTTPWorker.php index 4742e52a29..27a869ddef 100644 --- a/src/applications/feed/worker/FeedPublisherHTTPWorker.php +++ b/src/applications/feed/worker/FeedPublisherHTTPWorker.php @@ -1,39 +1,44 @@ loadFeedStory(); $data = $story->getStoryData(); $uri = idx($this->getTaskData(), 'uri'); $valid_uris = PhabricatorEnv::getEnvConfig('feed.http-hooks'); if (!in_array($uri, $valid_uris)) { throw new PhabricatorWorkerPermanentFailureException(); } $post_data = array( 'storyID' => $data->getID(), 'storyType' => $data->getStoryType(), 'storyData' => $data->getStoryData(), 'storyAuthorPHID' => $data->getAuthorPHID(), 'storyText' => $story->renderText(), 'epoch' => $data->getEpoch(), ); + // NOTE: We're explicitly using "http_build_query()" here because the + // "storyData" parameter may be a nested object with arbitrary nested + // sub-objects. + $post_data = http_build_query($post_data, '', '&'); + id(new HTTPSFuture($uri, $post_data)) ->setMethod('POST') ->setTimeout(30) ->resolvex(); } public function getWaitBeforeRetry(PhabricatorWorkerTask $task) { return max($task->getFailureCount(), 1) * 60; } } diff --git a/src/applications/fund/storage/FundBacker.php b/src/applications/fund/storage/FundBacker.php index 87ab342e2a..ebdf39ae17 100644 --- a/src/applications/fund/storage/FundBacker.php +++ b/src/applications/fund/storage/FundBacker.php @@ -1,117 +1,120 @@ setBackerPHID($actor->getPHID()) ->setStatus(self::STATUS_NEW); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_APPLICATION_SERIALIZERS => array( 'amountAsCurrency' => new PhortuneCurrencySerializer(), ), self::CONFIG_COLUMN_SCHEMA => array( 'status' => 'text32', 'amountAsCurrency' => 'text64', ), self::CONFIG_KEY_SCHEMA => array( 'key_initiative' => array( 'columns' => array('initiativePHID'), ), 'key_backer' => array( 'columns' => array('backerPHID'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID(FundBackerPHIDType::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 getInitiative() { return $this->assertAttached($this->initiative); } public function attachInitiative(FundInitiative $initiative = null) { $this->initiative = $initiative; return $this; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: // If we have the initiative, use the initiative's policy. // Otherwise, return NOONE. This allows the backer to continue seeing // a backer even if they're no longer allowed to see the initiative. $initiative = $this->getInitiative(); if ($initiative) { return $initiative->getPolicy($capability); } return PhabricatorPolicies::POLICY_NOONE; + case PhabricatorPolicyCapability::CAN_EDIT: + return PhabricatorPolicies::POLICY_NOONE; } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return ($viewer->getPHID() == $this->getBackerPHID()); } public function describeAutomaticCapability($capability) { return pht('A backer can always see what they have backed.'); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new FundBackerEditor(); } public function getApplicationTransactionTemplate() { return new FundBackerTransaction(); } } diff --git a/src/applications/fund/storage/FundBackerTransaction.php b/src/applications/fund/storage/FundBackerTransaction.php index c24e769eb6..c08958a29a 100644 --- a/src/applications/fund/storage/FundBackerTransaction.php +++ b/src/applications/fund/storage/FundBackerTransaction.php @@ -1,22 +1,18 @@ getApplicationTransactionTemplate(); - try { - $comment = $xaction->getApplicationTransactionCommentObject(); - if (!$comment) { - return false; - } - } catch (PhutilMethodNotImplementedException $ex) { + + $comment = $xaction->getApplicationTransactionCommentObject(); + if (!$comment) { return false; } return true; } public function supportsRuleType($rule_type) { return ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL); } public function applyEffect($object, HeraldEffect $effect) { $adapter = $this->getAdapter(); $comment_text = $effect->getTarget(); $xaction = $adapter->newTransaction() ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT); $comment = $xaction->getApplicationTransactionCommentObject() ->setContent($comment_text); $xaction->attachComment($comment); $adapter->queueTransaction($xaction); $this->logEffect(self::DO_COMMENT, $comment_text); } public function getHeraldActionStandardType() { return self::STANDARD_REMARKUP; } protected function getActionEffectMap() { return array( self::DO_COMMENT => array( 'icon' => 'fa-comment', 'color' => 'blue', 'name' => pht('Added Comment'), ), ); } public function renderActionDescription($value) { $summary = PhabricatorMarkupEngine::summarize($value); return pht('Add comment: %s', $summary); } protected function renderActionEffectDescription($type, $data) { $summary = PhabricatorMarkupEngine::summarize($data); return pht('Added a comment: %s', $summary); } } diff --git a/src/applications/herald/storage/HeraldWebhookTransaction.php b/src/applications/herald/storage/HeraldWebhookTransaction.php index 03c8cbb776..4f924cd4bb 100644 --- a/src/applications/herald/storage/HeraldWebhookTransaction.php +++ b/src/applications/herald/storage/HeraldWebhookTransaction.php @@ -1,22 +1,18 @@ getUser(); $document = id(new LegalpadDocumentQuery()) ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->needDocumentBodies(true) ->executeOne(); if (!$document) { return new Aphront404Response(); } $information = $this->readSignerInformation( $document, $request); if ($information instanceof AphrontResponse) { return $information; } list($signer_phid, $signature_data) = $information; $signature = null; $type_individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL; $is_individual = ($document->getSignatureType() == $type_individual); switch ($document->getSignatureType()) { case LegalpadDocument::SIGNATURE_TYPE_NONE: // nothing to sign means this should be true $has_signed = true; // this is a status UI element $signed_status = null; break; case LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL: if ($signer_phid) { // TODO: This is odd and should probably be adjusted after // grey/external accounts work better, but use the omnipotent // viewer to check for a signature so we can pick up // anonymous/grey signatures. $signature = id(new LegalpadDocumentSignatureQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withDocumentPHIDs(array($document->getPHID())) ->withSignerPHIDs(array($signer_phid)) ->executeOne(); if ($signature && !$viewer->isLoggedIn()) { return $this->newDialog() ->setTitle(pht('Already Signed')) ->appendParagraph(pht('You have already signed this document!')) ->addCancelButton('/'.$document->getMonogram(), pht('Okay')); } } $signed_status = null; if (!$signature) { $has_signed = false; $signature = id(new LegalpadDocumentSignature()) ->setSignerPHID($signer_phid) ->setDocumentPHID($document->getPHID()) ->setDocumentVersion($document->getVersions()); // If the user is logged in, show a notice that they haven't signed. // If they aren't logged in, we can't be as sure, so don't show // anything. if ($viewer->isLoggedIn()) { $signed_status = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setErrors( array( pht('You have not signed this document yet.'), )); } } else { $has_signed = true; $signature_data = $signature->getSignatureData(); // In this case, we know they've signed. $signed_at = $signature->getDateCreated(); if ($signature->getIsExemption()) { $exemption_phid = $signature->getExemptionPHID(); $handles = $this->loadViewerHandles(array($exemption_phid)); $exemption_handle = $handles[$exemption_phid]; $signed_text = pht( 'You do not need to sign this document. '. '%s added a signature exemption for you on %s.', $exemption_handle->renderLink(), phabricator_datetime($signed_at, $viewer)); } else { $signed_text = pht( 'You signed this document on %s.', phabricator_datetime($signed_at, $viewer)); } $signed_status = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) ->setErrors(array($signed_text)); } $field_errors = array( 'name' => true, 'email' => true, 'agree' => true, ); $signature->setSignatureData($signature_data); break; case LegalpadDocument::SIGNATURE_TYPE_CORPORATION: $signature = id(new LegalpadDocumentSignature()) ->setDocumentPHID($document->getPHID()) ->setDocumentVersion($document->getVersions()); if ($viewer->isLoggedIn()) { $has_signed = false; $signed_status = null; } else { // This just hides the form. $has_signed = true; $login_text = pht( 'This document requires a corporate signatory. You must log in to '. 'accept this document on behalf of a company you represent.'); $signed_status = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setErrors(array($login_text)); } $field_errors = array( 'name' => true, 'address' => true, 'contact.name' => true, 'email' => true, ); $signature->setSignatureData($signature_data); break; } $errors = array(); $hisec_token = null; if ($request->isFormOrHisecPost() && !$has_signed) { list($form_data, $errors, $field_errors) = $this->readSignatureForm( $document, $request); $signature_data = $form_data + $signature_data; $signature->setSignatureData($signature_data); $signature->setSignatureType($document->getSignatureType()); $signature->setSignerName((string)idx($signature_data, 'name')); $signature->setSignerEmail((string)idx($signature_data, 'email')); $agree = $request->getExists('agree'); if (!$agree) { $errors[] = pht( 'You must check "I agree to the terms laid forth above."'); $field_errors['agree'] = pht('Required'); } if ($viewer->isLoggedIn() && $is_individual) { $verified = LegalpadDocumentSignature::VERIFIED; } else { $verified = LegalpadDocumentSignature::UNVERIFIED; } $signature->setVerified($verified); if (!$errors) { // Require MFA to sign legal documents. if ($viewer->isLoggedIn()) { $workflow_key = sprintf( 'legalpad.sign(%s)', $document->getPHID()); $hisec_token = id(new PhabricatorAuthSessionEngine()) ->setWorkflowKey($workflow_key) ->requireHighSecurityToken( $viewer, $request, $document->getURI()); } $signature->save(); // If the viewer is logged in, signing for themselves, send them to // the document page, which will show that they have signed the // document. Unless of course they were required to sign the // document to use Phabricator; in that case try really hard to // re-direct them to where they wanted to go. // // Otherwise, send them to a completion page. if ($viewer->isLoggedIn() && $is_individual) { $next_uri = '/'.$document->getMonogram(); if ($document->getRequireSignature()) { $request_uri = $request->getRequestURI(); $next_uri = (string)$request_uri; } } else { $this->sendVerifySignatureEmail( $document, $signature); $next_uri = $this->getApplicationURI('done/'); } return id(new AphrontRedirectResponse())->setURI($next_uri); } } $document_body = $document->getDocumentBody(); $engine = id(new PhabricatorMarkupEngine()) ->setViewer($viewer); $engine->addObject( $document_body, LegalpadDocumentBody::MARKUP_FIELD_TEXT); $engine->process(); $document_markup = $engine->getOutput( $document_body, LegalpadDocumentBody::MARKUP_FIELD_TEXT); $title = $document_body->getTitle(); $manage_uri = $this->getApplicationURI('view/'.$document->getID().'/'); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $document, PhabricatorPolicyCapability::CAN_EDIT); // Use the last content update as the modified date. We don't want to // show that a document like a TOS was "updated" by an incidental change // to a field like the preamble or privacy settings which does not actually // affect the content of the agreement. $content_updated = $document_body->getDateCreated(); // NOTE: We're avoiding `setPolicyObject()` here so we don't pick up // extra UI elements that are unnecessary and clutter the signature page. // These details are available on the "Manage" page. $header = id(new PHUIHeaderView()) ->setHeader($title) ->setUser($viewer) ->setEpoch($content_updated) ->addActionLink( id(new PHUIButtonView()) ->setTag('a') ->setIcon('fa-pencil') ->setText(pht('Manage')) ->setHref($manage_uri) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); $preamble_box = null; if (strlen($document->getPreamble())) { $preamble_text = new PHUIRemarkupView($viewer, $document->getPreamble()); // NOTE: We're avoiding `setObject()` here so we don't pick up extra UI // elements like "Subscribers". This information is available on the // "Manage" page, but just clutters up the "Signature" page. $preamble = id(new PHUIPropertyListView()) ->setUser($viewer) ->addSectionHeader(pht('Preamble')) ->addTextContent($preamble_text); $preamble_box = new PHUIPropertyGroupView(); $preamble_box->addPropertyList($preamble); } $content = id(new PHUIDocumentView()) ->addClass('legalpad') ->setHeader($header) ->appendChild( array( $signed_status, $preamble_box, $document_markup, )); $signature_box = null; if (!$has_signed) { $error_view = null; if ($errors) { $error_view = id(new PHUIInfoView()) ->setErrors($errors); } $signature_form = $this->buildSignatureForm( $document, $signature, $field_errors); switch ($document->getSignatureType()) { default: break; case LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL: case LegalpadDocument::SIGNATURE_TYPE_CORPORATION: $box = id(new PHUIObjectBoxView()) ->addClass('document-sign-box') ->setHeaderText(pht('Agree and Sign Document')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($signature_form); if ($error_view) { $box->setInfoView($error_view); } $signature_box = phutil_tag_div( 'phui-document-view-pro-box plt', $box); break; } } $crumbs = $this->buildApplicationCrumbs(); $crumbs->setBorder(true); $crumbs->addTextCrumb($document->getMonogram()); $box = id(new PHUITwoColumnView()) ->setFooter($signature_box); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->setPageObjectPHIDs(array($document->getPHID())) ->appendChild(array( $content, $box, )); } private function readSignerInformation( LegalpadDocument $document, AphrontRequest $request) { $viewer = $request->getUser(); $signer_phid = null; $signature_data = array(); switch ($document->getSignatureType()) { case LegalpadDocument::SIGNATURE_TYPE_NONE: break; case LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL: if ($viewer->isLoggedIn()) { $signer_phid = $viewer->getPHID(); $signature_data = array( 'name' => $viewer->getRealName(), 'email' => $viewer->loadPrimaryEmailAddress(), ); } else if ($request->isFormPost()) { $email = new PhutilEmailAddress($request->getStr('email')); if (strlen($email->getDomainName())) { $email_obj = id(new PhabricatorUserEmail()) ->loadOneWhere('address = %s', $email->getAddress()); if ($email_obj) { return $this->signInResponse(); } - $external_account = id(new PhabricatorExternalAccountQuery()) - ->setViewer($viewer) - ->withAccountTypes(array('email')) - ->withAccountDomains(array($email->getDomainName())) - ->withAccountIDs(array($email->getAddress())) - ->loadOneOrCreate(); - if ($external_account->getUserPHID()) { - return $this->signInResponse(); - } - $signer_phid = $external_account->getPHID(); } } break; case LegalpadDocument::SIGNATURE_TYPE_CORPORATION: $signer_phid = $viewer->getPHID(); if ($signer_phid) { $signature_data = array( 'contact.name' => $viewer->getRealName(), 'email' => $viewer->loadPrimaryEmailAddress(), 'actorPHID' => $viewer->getPHID(), ); } break; } return array($signer_phid, $signature_data); } private function buildSignatureForm( LegalpadDocument $document, LegalpadDocumentSignature $signature, array $errors) { $viewer = $this->getRequest()->getUser(); $data = $signature->getSignatureData(); $form = id(new AphrontFormView()) ->setUser($viewer); $signature_type = $document->getSignatureType(); switch ($signature_type) { case LegalpadDocument::SIGNATURE_TYPE_NONE: // bail out of here quick return; case LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL: $this->buildIndividualSignatureForm( $form, $document, $signature, $errors); break; case LegalpadDocument::SIGNATURE_TYPE_CORPORATION: $this->buildCorporateSignatureForm( $form, $document, $signature, $errors); break; default: throw new Exception( pht( 'This document has an unknown signature type ("%s").', $signature_type)); } $form ->appendChild( id(new AphrontFormCheckboxControl()) ->setError(idx($errors, 'agree', null)) ->addCheckbox( 'agree', 'agree', pht('I agree to the terms laid forth above.'), false)); if ($document->getRequireSignature()) { $cancel_uri = '/logout/'; $cancel_text = pht('Log Out'); } else { $cancel_uri = $this->getApplicationURI(); $cancel_text = pht('Cancel'); } $form ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Sign Document')) ->addCancelButton($cancel_uri, $cancel_text)); return $form; } private function buildIndividualSignatureForm( AphrontFormView $form, LegalpadDocument $document, LegalpadDocumentSignature $signature, array $errors) { $data = $signature->getSignatureData(); $form ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Name')) ->setValue(idx($data, 'name', '')) ->setName('name') ->setError(idx($errors, 'name', null))); $viewer = $this->getRequest()->getUser(); if (!$viewer->isLoggedIn()) { $form->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Email')) ->setValue(idx($data, 'email', '')) ->setName('email') ->setError(idx($errors, 'email', null))); } return $form; } private function buildCorporateSignatureForm( AphrontFormView $form, LegalpadDocument $document, LegalpadDocumentSignature $signature, array $errors) { $data = $signature->getSignatureData(); $form ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Company Name')) ->setValue(idx($data, 'name', '')) ->setName('name') ->setError(idx($errors, 'name', null))) ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel(pht('Company Address')) ->setValue(idx($data, 'address', '')) ->setName('address') ->setError(idx($errors, 'address', null))) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Contact Name')) ->setValue(idx($data, 'contact.name', '')) ->setName('contact.name') ->setError(idx($errors, 'contact.name', null))) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Contact Email')) ->setValue(idx($data, 'email', '')) ->setName('email') ->setError(idx($errors, 'email', null))); return $form; } private function readSignatureForm( LegalpadDocument $document, AphrontRequest $request) { $signature_type = $document->getSignatureType(); switch ($signature_type) { case LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL: $result = $this->readIndividualSignatureForm( $document, $request); break; case LegalpadDocument::SIGNATURE_TYPE_CORPORATION: $result = $this->readCorporateSignatureForm( $document, $request); break; default: throw new Exception( pht( 'This document has an unknown signature type ("%s").', $signature_type)); } return $result; } private function readIndividualSignatureForm( LegalpadDocument $document, AphrontRequest $request) { $signature_data = array(); $errors = array(); $field_errors = array(); $name = $request->getStr('name'); if (!strlen($name)) { $field_errors['name'] = pht('Required'); $errors[] = pht('Name field is required.'); } else { $field_errors['name'] = null; } $signature_data['name'] = $name; $viewer = $request->getUser(); if ($viewer->isLoggedIn()) { $email = $viewer->loadPrimaryEmailAddress(); } else { $email = $request->getStr('email'); $addr_obj = null; if (!strlen($email)) { $field_errors['email'] = pht('Required'); $errors[] = pht('Email field is required.'); } else { $addr_obj = new PhutilEmailAddress($email); $domain = $addr_obj->getDomainName(); if (!$domain) { $field_errors['email'] = pht('Invalid'); $errors[] = pht('A valid email is required.'); } else { $field_errors['email'] = null; } } } $signature_data['email'] = $email; return array($signature_data, $errors, $field_errors); } private function readCorporateSignatureForm( LegalpadDocument $document, AphrontRequest $request) { $viewer = $request->getUser(); if (!$viewer->isLoggedIn()) { throw new Exception( pht( 'You can not sign a document on behalf of a corporation unless '. 'you are logged in.')); } $signature_data = array(); $errors = array(); $field_errors = array(); $name = $request->getStr('name'); if (!strlen($name)) { $field_errors['name'] = pht('Required'); $errors[] = pht('Company name is required.'); } else { $field_errors['name'] = null; } $signature_data['name'] = $name; $address = $request->getStr('address'); if (!strlen($address)) { $field_errors['address'] = pht('Required'); $errors[] = pht('Company address is required.'); } else { $field_errors['address'] = null; } $signature_data['address'] = $address; $contact_name = $request->getStr('contact.name'); if (!strlen($contact_name)) { $field_errors['contact.name'] = pht('Required'); $errors[] = pht('Contact name is required.'); } else { $field_errors['contact.name'] = null; } $signature_data['contact.name'] = $contact_name; $email = $request->getStr('email'); $addr_obj = null; if (!strlen($email)) { $field_errors['email'] = pht('Required'); $errors[] = pht('Contact email is required.'); } else { $addr_obj = new PhutilEmailAddress($email); $domain = $addr_obj->getDomainName(); if (!$domain) { $field_errors['email'] = pht('Invalid'); $errors[] = pht('A valid email is required.'); } else { $field_errors['email'] = null; } } $signature_data['email'] = $email; return array($signature_data, $errors, $field_errors); } private function sendVerifySignatureEmail( LegalpadDocument $doc, LegalpadDocumentSignature $signature) { $signature_data = $signature->getSignatureData(); $email = new PhutilEmailAddress($signature_data['email']); $doc_name = $doc->getTitle(); $doc_link = PhabricatorEnv::getProductionURI('/'.$doc->getMonogram()); $path = $this->getApplicationURI(sprintf( '/verify/%s/', $signature->getSecretKey())); $link = PhabricatorEnv::getProductionURI($path); $name = idx($signature_data, 'name'); $body = pht( "%s:\n\n". "This email address was used to sign a Legalpad document ". "in Phabricator:\n\n". " %s\n\n". "Please verify you own this email address and accept the ". "agreement by clicking this link:\n\n". " %s\n\n". "Your signature is not valid until you complete this ". "verification step.\n\nYou can review the document here:\n\n". " %s\n", $name, $doc_name, $link, $doc_link); id(new PhabricatorMetaMTAMail()) ->addRawTos(array($email->getAddress())) ->setSubject(pht('[Legalpad] Signature Verification')) ->setForceDelivery(true) ->setBody($body) ->setRelatedPHID($signature->getDocumentPHID()) ->saveAndSend(); } private function signInResponse() { return id(new Aphront403Response()) ->setForbiddenText( pht( 'The email address specified is associated with an account. '. 'Please login to that account and sign this document again.')); } } diff --git a/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php b/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php index 9df8d2478d..ea14fd4a2f 100644 --- a/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php +++ b/src/applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php @@ -1,315 +1,315 @@ document = $document; return $this; } public function buildSavedQueryFromRequest(AphrontRequest $request) { $saved = new PhabricatorSavedQuery(); $saved->setParameter( 'signerPHIDs', $this->readUsersFromRequest($request, 'signers')); $saved->setParameter( 'documentPHIDs', $this->readPHIDsFromRequest( $request, 'documents', array( PhabricatorLegalpadDocumentPHIDType::TYPECONST, ))); $saved->setParameter('nameContains', $request->getStr('nameContains')); $saved->setParameter('emailContains', $request->getStr('emailContains')); return $saved; } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { $query = id(new LegalpadDocumentSignatureQuery()); $signer_phids = $saved->getParameter('signerPHIDs', array()); if ($signer_phids) { $query->withSignerPHIDs($signer_phids); } if ($this->document) { $query->withDocumentPHIDs(array($this->document->getPHID())); } else { $document_phids = $saved->getParameter('documentPHIDs', array()); if ($document_phids) { $query->withDocumentPHIDs($document_phids); } } $name_contains = $saved->getParameter('nameContains'); if (strlen($name_contains)) { $query->withNameContains($name_contains); } $email_contains = $saved->getParameter('emailContains'); if (strlen($email_contains)) { $query->withEmailContains($email_contains); } return $query; } public function buildSearchForm( AphrontFormView $form, PhabricatorSavedQuery $saved_query) { $document_phids = $saved_query->getParameter('documentPHIDs', array()); $signer_phids = $saved_query->getParameter('signerPHIDs', array()); if (!$this->document) { $form ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new LegalpadDocumentDatasource()) ->setName('documents') ->setLabel(pht('Documents')) ->setValue($document_phids)); } $name_contains = $saved_query->getParameter('nameContains', ''); $email_contains = $saved_query->getParameter('emailContains', ''); $form ->appendControl( id(new AphrontFormTokenizerControl()) ->setDatasource(new PhabricatorPeopleDatasource()) ->setName('signers') ->setLabel(pht('Signers')) ->setValue($signer_phids)) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Name Contains')) ->setName('nameContains') ->setValue($name_contains)) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Email Contains')) ->setName('emailContains') ->setValue($email_contains)); } protected function getURI($path) { if ($this->document) { return '/legalpad/signatures/'.$this->document->getID().'/'.$path; } else { return '/legalpad/signatures/'.$path; } } protected function getBuiltinQueryNames() { $names = array( 'all' => pht('All Signatures'), ); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query; } return parent::buildSavedQueryFromBuiltin($query_key); } protected function getRequiredHandlePHIDsForResultList( array $signatures, PhabricatorSavedQuery $query) { return array_merge( mpull($signatures, 'getSignerPHID'), mpull($signatures, 'getDocumentPHID')); } protected function renderResultList( array $signatures, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($signatures, 'LegalpadDocumentSignature'); $viewer = $this->requireViewer(); Javelin::initBehavior('phabricator-tooltips'); $sig_good = $this->renderIcon( 'fa-check', null, pht('Verified, Current')); $sig_corp = $this->renderIcon( 'fa-building-o', null, pht('Verified, Corporate')); $sig_old = $this->renderIcon( 'fa-clock-o', 'orange', pht('Signed Older Version')); $sig_unverified = $this->renderIcon( 'fa-envelope', 'red', pht('Unverified Email')); $sig_exemption = $this->renderIcon( 'fa-asterisk', 'indigo', pht('Exemption')); id(new PHUIIconView()) ->setIcon('fa-envelope', 'red') ->addSigil('has-tooltip') ->setMetadata(array('tip' => pht('Unverified Email'))); $type_corporate = LegalpadDocument::SIGNATURE_TYPE_CORPORATION; $rows = array(); foreach ($signatures as $signature) { $name = $signature->getSignerName(); $email = $signature->getSignerEmail(); $document = $signature->getDocument(); if ($signature->getIsExemption()) { $sig_icon = $sig_exemption; } else if (!$signature->isVerified()) { $sig_icon = $sig_unverified; } else if ($signature->getDocumentVersion() != $document->getVersions()) { $sig_icon = $sig_old; } else if ($signature->getSignatureType() == $type_corporate) { $sig_icon = $sig_corp; } else { $sig_icon = $sig_good; } $signature_href = $this->getApplicationURI( 'signature/'.$signature->getID().'/'); $sig_icon = javelin_tag( 'a', array( 'href' => $signature_href, 'sigil' => 'workflow', ), $sig_icon); $signer_phid = $signature->getSignerPHID(); $rows[] = array( $sig_icon, $handles[$document->getPHID()]->renderLink(), $signer_phid ? $handles[$signer_phid]->renderLink() - : null, + : phutil_tag('em', array(), pht('None')), $name, phutil_tag( 'a', array( 'href' => 'mailto:'.$email, ), $email), phabricator_datetime($signature->getDateCreated(), $viewer), ); } $table = id(new AphrontTableView($rows)) ->setNoDataString(pht('No signatures match the query.')) ->setHeaders( array( '', pht('Document'), pht('Account'), pht('Name'), pht('Email'), pht('Signed'), )) ->setColumnVisibility( array( true, // Only show the "Document" column if we aren't scoped to a // particular document. !$this->document, )) ->setColumnClasses( array( '', '', '', '', 'wide', 'right', )); $button = null; if ($this->document) { $document_id = $this->document->getID(); $button = id(new PHUIButtonView()) ->setText(pht('Add Exemption')) ->setTag('a') ->setHref($this->getApplicationURI('addsignature/'.$document_id.'/')) ->setWorkflow(true) ->setIcon('fa-pencil'); } if (!$this->document) { $table->setNotice( pht('NOTE: You can only see your own signatures and signatures on '. 'documents you have permission to edit.')); } $result = new PhabricatorApplicationSearchResultView(); $result->setTable($table); if ($button) { $result->addAction($button); } return $result; } private function renderIcon($icon, $color, $title) { Javelin::initBehavior('phabricator-tooltips'); return array( id(new PHUIIconView()) ->setIcon($icon, $color) ->addSigil('has-tooltip') ->setMetadata(array('tip' => $title)), javelin_tag( 'span', array( 'aural' => true, ), $title), ); } } diff --git a/src/applications/metamta/controller/PhabricatorMetaMTAMailListController.php b/src/applications/metamta/controller/PhabricatorMetaMTAMailListController.php index 0651068550..01d6f1e218 100644 --- a/src/applications/metamta/controller/PhabricatorMetaMTAMailListController.php +++ b/src/applications/metamta/controller/PhabricatorMetaMTAMailListController.php @@ -1,30 +1,34 @@ setQueryKey($request->getURIData('queryKey')) ->setSearchEngine(new PhabricatorMetaMTAMailSearchEngine()) ->setNavigation($this->buildSideNav()); return $this->delegateToController($controller); } public function buildSideNav() { $user = $this->getRequest()->getUser(); $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); id(new PhabricatorMetaMTAMailSearchEngine()) ->setViewer($user) ->addNavigationItems($nav->getMenu()); $nav->selectFilter(null); return $nav; } + public function buildApplicationMenu() { + return $this->buildSideNav()->getMenu(); + } + } diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmailTransaction.php b/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmailTransaction.php index 019adb338d..af6a6fbb88 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmailTransaction.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmailTransaction.php @@ -1,23 +1,19 @@ getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: return pht( '%s created this OAuth application.', $this->renderHandleLink($author_phid)); case self::TYPE_NAME: return pht( '%s renamed this application from "%s" to "%s".', $this->renderHandleLink($author_phid), $old, $new); case self::TYPE_REDIRECT_URI: return pht( '%s changed the application redirect URI from "%s" to "%s".', $this->renderHandleLink($author_phid), $old, $new); case self::TYPE_DISABLED: if ($new) { return pht( '%s disabled this application.', $this->renderHandleLink($author_phid)); } else { return pht( '%s enabled this application.', $this->renderHandleLink($author_phid)); } } return parent::getTitle(); } } diff --git a/src/applications/owners/constants/PhabricatorOwnersAuditRule.php b/src/applications/owners/constants/PhabricatorOwnersAuditRule.php new file mode 100644 index 0000000000..32a9bb804b --- /dev/null +++ b/src/applications/owners/constants/PhabricatorOwnersAuditRule.php @@ -0,0 +1,117 @@ +key = $key; + $rule->spec = $spec; + + return $rule; + } + + public function getKey() { + return $this->key; + } + + public function getDisplayName() { + return idx($this->spec, 'name', $this->key); + } + + public function getIconIcon() { + return idx($this->spec, 'icon.icon'); + } + + public static function newSelectControlMap() { + $specs = self::newSpecifications(); + return ipull($specs, 'name'); + } + + public static function getStorageValueFromAPIValue($value) { + $specs = self::newSpecifications(); + + $map = array(); + foreach ($specs as $key => $spec) { + $deprecated = idx($spec, 'deprecated', array()); + if (isset($deprecated[$value])) { + return $key; + } + } + + return $value; + } + + public static function getModernValueMap() { + $specs = self::newSpecifications(); + + $map = array(); + foreach ($specs as $key => $spec) { + $map[$key] = pht('"%s"', $key); + } + + return $map; + } + + public static function getDeprecatedValueMap() { + $specs = self::newSpecifications(); + + $map = array(); + foreach ($specs as $key => $spec) { + $deprecated_map = idx($spec, 'deprecated', array()); + foreach ($deprecated_map as $deprecated_key => $label) { + $map[$deprecated_key] = $label; + } + } + + return $map; + } + + private static function newSpecifications() { + return array( + self::AUDITING_NONE => array( + 'name' => pht('No Auditing'), + 'icon.icon' => 'fa-ban', + 'deprecated' => array( + '' => pht('"" (empty string)'), + '0' => '"0"', + ), + ), + self::AUDITING_UNREVIEWED => array( + 'name' => pht('Audit Unreviewed Commits'), + 'icon.icon' => 'fa-check', + ), + self::AUDITING_NO_OWNER => array( + 'name' => pht('Audit Commits With No Owner Involvement'), + 'icon.icon' => 'fa-check', + 'deprecated' => array( + '1' => '"1"', + ), + ), + self::AUDITING_NO_OWNER_AND_UNREVIEWED => array( + 'name' => pht( + 'Audit Unreviewed Commits and Commits With No Owner Involvement'), + 'icon.icon' => 'fa-check', + ), + self::AUDITING_ALL => array( + 'name' => pht('Audit All Commits'), + 'icon.icon' => 'fa-check', + ), + ); + } + + + +} diff --git a/src/applications/owners/controller/PhabricatorOwnersDetailController.php b/src/applications/owners/controller/PhabricatorOwnersDetailController.php index f71009cf19..e28ae2b3bb 100644 --- a/src/applications/owners/controller/PhabricatorOwnersDetailController.php +++ b/src/applications/owners/controller/PhabricatorOwnersDetailController.php @@ -1,352 +1,348 @@ getViewer(); $package = id(new PhabricatorOwnersPackageQuery()) ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->needPaths(true) ->executeOne(); if (!$package) { return new Aphront404Response(); } $paths = $package->getPaths(); $repository_phids = array(); foreach ($paths as $path) { $repository_phids[$path->getRepositoryPHID()] = true; } if ($repository_phids) { $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($viewer) ->withPHIDs(array_keys($repository_phids)) ->execute(); $repositories = mpull($repositories, null, 'getPHID'); } else { $repositories = array(); } $field_list = PhabricatorCustomField::getObjectFields( $package, PhabricatorCustomField::ROLE_VIEW); $field_list ->setViewer($viewer) ->readFieldsFromStorage($package); $curtain = $this->buildCurtain($package); $details = $this->buildPackageDetailView($package, $field_list); if ($package->isArchived()) { $header_icon = 'fa-ban'; $header_name = pht('Archived'); $header_color = 'dark'; } else { $header_icon = 'fa-check'; $header_name = pht('Active'); $header_color = 'bluegrey'; } $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setHeader($package->getName()) ->setStatus($header_icon, $header_color, $header_name) ->setPolicyObject($package) ->setHeaderIcon('fa-gift'); $commit_views = array(); $commit_uri = id(new PhutilURI('/diffusion/commit/')) ->setQueryParams( array( 'package' => $package->getPHID(), )); $status_concern = DiffusionCommitAuditStatus::CONCERN_RAISED; $attention_commits = id(new DiffusionCommitQuery()) ->setViewer($request->getUser()) ->withPackagePHIDs(array($package->getPHID())) ->withStatuses( array( $status_concern, )) ->needCommitData(true) ->needAuditRequests(true) ->setLimit(10) ->execute(); $view = id(new PhabricatorAuditListView()) ->setUser($viewer) ->setNoDataString(pht('This package has no open problem commits.')) ->setCommits($attention_commits); $commit_views[] = array( 'view' => $view, 'header' => pht('Needs Attention'), 'icon' => 'fa-warning', 'button' => id(new PHUIButtonView()) ->setTag('a') ->setHref($commit_uri->alter('status', $status_concern)) ->setIcon('fa-list-ul') ->setText(pht('View All')), ); $all_commits = id(new DiffusionCommitQuery()) ->setViewer($request->getUser()) ->withPackagePHIDs(array($package->getPHID())) ->needCommitData(true) ->needAuditRequests(true) ->setLimit(25) ->execute(); $view = id(new PhabricatorAuditListView()) ->setUser($viewer) ->setCommits($all_commits) ->setNoDataString(pht('No commits in this package.')); $commit_views[] = array( 'view' => $view, 'header' => pht('Recent Commits'), 'icon' => 'fa-code', 'button' => id(new PHUIButtonView()) ->setTag('a') ->setHref($commit_uri) ->setIcon('fa-list-ul') ->setText(pht('View All')), ); $commit_panels = array(); foreach ($commit_views as $commit_view) { $commit_panel = id(new PHUIObjectBoxView()) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); $commit_header = id(new PHUIHeaderView()) ->setHeader($commit_view['header']) ->setHeaderIcon($commit_view['icon']); if (isset($commit_view['button'])) { $commit_header->addActionLink($commit_view['button']); } $commit_panel->setHeader($commit_header); $commit_panel->appendChild($commit_view['view']); $commit_panels[] = $commit_panel; } $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($package->getMonogram()); $crumbs->setBorder(true); $timeline = $this->buildTransactionTimeline( $package, new PhabricatorOwnersPackageTransactionQuery()); $timeline->setShouldTerminate(true); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->setMainColumn(array( $this->renderPathsTable($paths, $repositories), $commit_panels, $timeline, )) ->addPropertySection(pht('Details'), $details); return $this->newPage() ->setTitle($package->getName()) ->setCrumbs($crumbs) ->appendChild($view); } private function buildPackageDetailView( PhabricatorOwnersPackage $package, PhabricatorCustomFieldList $field_list) { $viewer = $this->getViewer(); $view = id(new PHUIPropertyListView()) ->setUser($viewer); $owners = $package->getOwners(); if ($owners) { $owner_list = $viewer->renderHandleList(mpull($owners, 'getUserPHID')); } else { $owner_list = phutil_tag('em', array(), pht('None')); } $view->addProperty(pht('Owners'), $owner_list); $dominion = $package->getDominion(); $dominion_map = PhabricatorOwnersPackage::getDominionOptionsMap(); $spec = idx($dominion_map, $dominion, array()); $name = idx($spec, 'short', $dominion); $view->addProperty(pht('Dominion'), $name); $auto = $package->getAutoReview(); $autoreview_map = PhabricatorOwnersPackage::getAutoreviewOptionsMap(); $spec = idx($autoreview_map, $auto, array()); $name = idx($spec, 'name', $auto); $view->addProperty(pht('Auto Review'), $name); - if ($package->getAuditingEnabled()) { - $auditing = pht('Enabled'); - } else { - $auditing = pht('Disabled'); - } - $view->addProperty(pht('Auditing'), $auditing); + $rule = $package->newAuditingRule(); + $view->addProperty(pht('Auditing'), $rule->getDisplayName()); $ignored = $package->getIgnoredPathAttributes(); $ignored = array_keys($ignored); if ($ignored) { $ignored = implode(', ', $ignored); } else { $ignored = phutil_tag('em', array(), pht('None')); } $view->addProperty(pht('Ignored Attributes'), $ignored); $description = $package->getDescription(); if (strlen($description)) { $description = new PHUIRemarkupView($viewer, $description); $view->addSectionHeader(pht('Description')); $view->addTextContent($description); } $field_list->appendFieldsToPropertyList( $package, $viewer, $view); return $view; } private function buildCurtain(PhabricatorOwnersPackage $package) { $viewer = $this->getViewer(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $package, PhabricatorPolicyCapability::CAN_EDIT); $id = $package->getID(); $edit_uri = $this->getApplicationURI("/edit/{$id}/"); $paths_uri = $this->getApplicationURI("/paths/{$id}/"); $curtain = $this->newCurtainView($package); $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Package')) ->setIcon('fa-pencil') ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref($edit_uri)); if ($package->isArchived()) { $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Activate Package')) ->setIcon('fa-check') ->setDisabled(!$can_edit) ->setWorkflow($can_edit) ->setHref($this->getApplicationURI("/archive/{$id}/"))); } else { $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Archive Package')) ->setIcon('fa-ban') ->setDisabled(!$can_edit) ->setWorkflow($can_edit) ->setHref($this->getApplicationURI("/archive/{$id}/"))); } $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Paths')) ->setIcon('fa-folder-open') ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref($paths_uri)); return $curtain; } private function renderPathsTable(array $paths, array $repositories) { $viewer = $this->getViewer(); $rows = array(); foreach ($paths as $path) { $repo = idx($repositories, $path->getRepositoryPHID()); if (!$repo) { continue; } $href = $repo->generateURI( array( 'branch' => $repo->getDefaultBranch(), 'path' => $path->getPathDisplay(), 'action' => 'browse', )); $path_link = phutil_tag( 'a', array( 'href' => (string)$href, ), $path->getPathDisplay()); $rows[] = array( ($path->getExcluded() ? '-' : '+'), $repo->getName(), $path_link, ); } $info = null; if (!$paths) { $info = id(new PHUIInfoView()) ->setSeverity(PHUIInfoView::SEVERITY_WARNING) ->setErrors( array( pht( 'This package does not contain any paths yet. Use '. '"Edit Paths" to add some.'), )); } $table = id(new AphrontTableView($rows)) ->setHeaders( array( null, pht('Repository'), pht('Path'), )) ->setColumnClasses( array( null, null, 'wide', )); if ($info) { $table->setNotice($info); } $header = id(new PHUIHeaderView()) ->setHeader(pht('Paths')) ->setHeaderIcon('fa-folder-open'); $box = id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setTable($table); return $box; } } diff --git a/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php b/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php index 044cb8beda..13f896d3f0 100644 --- a/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php +++ b/src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php @@ -1,190 +1,186 @@ getViewer()); } protected function newObjectQuery() { return id(new PhabricatorOwnersPackageQuery()) ->needPaths(true); } protected function getObjectCreateTitleText($object) { return pht('Create New Package'); } protected function getObjectEditTitleText($object) { return pht('Edit Package: %s', $object->getName()); } protected function getObjectEditShortText($object) { return pht('Package %d', $object->getID()); } protected function getObjectCreateShortText() { return pht('Create Package'); } protected function getObjectName() { return pht('Package'); } protected function getObjectViewURI($object) { return $object->getURI(); } protected function buildCustomEditFields($object) { $paths_help = pht(<<setKey('name') ->setLabel(pht('Name')) ->setDescription(pht('Name of the package.')) ->setTransactionType( PhabricatorOwnersPackageNameTransaction::TRANSACTIONTYPE) ->setIsRequired(true) ->setValue($object->getName()), id(new PhabricatorDatasourceEditField()) ->setKey('owners') ->setLabel(pht('Owners')) ->setDescription(pht('Users and projects which own the package.')) ->setTransactionType( PhabricatorOwnersPackageOwnersTransaction::TRANSACTIONTYPE) ->setDatasource(new PhabricatorProjectOrUserDatasource()) ->setIsCopyable(true) ->setValue($object->getOwnerPHIDs()), id(new PhabricatorSelectEditField()) ->setKey('dominion') ->setLabel(pht('Dominion')) ->setDescription( pht('Change package dominion rules.')) ->setTransactionType( PhabricatorOwnersPackageDominionTransaction::TRANSACTIONTYPE) ->setIsCopyable(true) ->setValue($object->getDominion()) ->setOptions($dominion_map), id(new PhabricatorSelectEditField()) ->setKey('autoReview') ->setLabel(pht('Auto Review')) ->setDescription( pht( 'Automatically trigger reviews for commits affecting files in '. 'this package.')) ->setTransactionType( PhabricatorOwnersPackageAutoreviewTransaction::TRANSACTIONTYPE) ->setIsCopyable(true) ->setValue($object->getAutoReview()) ->setOptions($autoreview_map), id(new PhabricatorSelectEditField()) ->setKey('auditing') ->setLabel(pht('Auditing')) ->setDescription( pht( 'Automatically trigger audits for commits affecting files in '. 'this package.')) ->setTransactionType( PhabricatorOwnersPackageAuditingTransaction::TRANSACTIONTYPE) ->setIsCopyable(true) - ->setValue($object->getAuditingEnabled()) - ->setOptions( - array( - '' => pht('Disabled'), - '1' => pht('Enabled'), - )), + ->setValue($object->getAuditingState()) + ->setOptions(PhabricatorOwnersAuditRule::newSelectControlMap()), id(new PhabricatorRemarkupEditField()) ->setKey('description') ->setLabel(pht('Description')) ->setDescription(pht('Human-readable description of the package.')) ->setTransactionType( PhabricatorOwnersPackageDescriptionTransaction::TRANSACTIONTYPE) ->setValue($object->getDescription()), id(new PhabricatorSelectEditField()) ->setKey('status') ->setLabel(pht('Status')) ->setDescription(pht('Archive or enable the package.')) ->setTransactionType( PhabricatorOwnersPackageStatusTransaction::TRANSACTIONTYPE) ->setIsFormField(false) ->setValue($object->getStatus()) ->setOptions($object->getStatusNameMap()), id(new PhabricatorCheckboxesEditField()) ->setKey('ignored') ->setLabel(pht('Ignored Attributes')) ->setDescription(pht('Ignore paths with any of these attributes.')) ->setTransactionType( PhabricatorOwnersPackageIgnoredTransaction::TRANSACTIONTYPE) ->setValue(array_keys($object->getIgnoredPathAttributes())) ->setOptions( array( 'generated' => pht('Ignore generated files (review only).'), )), id(new PhabricatorConduitEditField()) ->setKey('paths.set') ->setLabel(pht('Paths')) ->setIsFormField(false) ->setTransactionType( PhabricatorOwnersPackagePathsTransaction::TRANSACTIONTYPE) ->setConduitDescription( pht('Overwrite existing package paths with new paths.')) ->setConduitTypeDescription( pht('List of dictionaries, each describing a path.')) ->setConduitDocumentation($paths_help), ); } } diff --git a/src/applications/owners/storage/PhabricatorOwnersPackage.php b/src/applications/owners/storage/PhabricatorOwnersPackage.php index 564fc8a28b..b9e91ef958 100644 --- a/src/applications/owners/storage/PhabricatorOwnersPackage.php +++ b/src/applications/owners/storage/PhabricatorOwnersPackage.php @@ -1,805 +1,803 @@ setViewer($actor) ->withClasses(array('PhabricatorOwnersApplication')) ->executeOne(); $view_policy = $app->getPolicy( PhabricatorOwnersDefaultViewCapability::CAPABILITY); $edit_policy = $app->getPolicy( PhabricatorOwnersDefaultEditCapability::CAPABILITY); return id(new PhabricatorOwnersPackage()) - ->setAuditingEnabled(0) + ->setAuditingState(PhabricatorOwnersAuditRule::AUDITING_NONE) ->setAutoReview(self::AUTOREVIEW_NONE) ->setDominion(self::DOMINION_STRONG) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->attachPaths(array()) ->setStatus(self::STATUS_ACTIVE) ->attachOwners(array()) ->setDescription(''); } public static function getStatusNameMap() { return array( self::STATUS_ACTIVE => pht('Active'), self::STATUS_ARCHIVED => pht('Archived'), ); } public static function getAutoreviewOptionsMap() { return array( self::AUTOREVIEW_NONE => array( 'name' => pht('No Autoreview'), ), self::AUTOREVIEW_REVIEW => array( 'name' => pht('Review Changes With Non-Owner Author'), 'authority' => true, ), self::AUTOREVIEW_BLOCK => array( 'name' => pht('Review Changes With Non-Owner Author (Blocking)'), 'authority' => true, ), self::AUTOREVIEW_SUBSCRIBE => array( 'name' => pht('Subscribe to Changes With Non-Owner Author'), 'authority' => true, ), self::AUTOREVIEW_REVIEW_ALWAYS => array( 'name' => pht('Review All Changes'), ), self::AUTOREVIEW_BLOCK_ALWAYS => array( 'name' => pht('Review All Changes (Blocking)'), ), self::AUTOREVIEW_SUBSCRIBE_ALWAYS => array( 'name' => pht('Subscribe to All Changes'), ), ); } public static function getDominionOptionsMap() { return array( self::DOMINION_STRONG => array( 'name' => pht('Strong (Control All Paths)'), 'short' => pht('Strong'), ), self::DOMINION_WEAK => array( 'name' => pht('Weak (Control Unowned Paths)'), 'short' => pht('Weak'), ), ); } protected function getConfiguration() { return array( // This information is better available from the history table. self::CONFIG_TIMESTAMPS => false, self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'properties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'name' => 'sort', 'description' => 'text', - 'auditingEnabled' => 'bool', + 'auditingState' => 'text32', 'status' => 'text32', 'autoReview' => 'text32', 'dominion' => 'text32', ), ) + parent::getConfiguration(); } public function getPHIDType() { return PhabricatorOwnersPackagePHIDType::TYPECONST; } public function isArchived() { return ($this->getStatus() == self::STATUS_ARCHIVED); } public function getMustMatchUngeneratedPaths() { $ignore_attributes = $this->getIgnoredPathAttributes(); return !empty($ignore_attributes['generated']); } public function getPackageProperty($key, $default = null) { return idx($this->properties, $key, $default); } public function setPackageProperty($key, $value) { $this->properties[$key] = $value; return $this; } public function getIgnoredPathAttributes() { return $this->getPackageProperty(self::PROPERTY_IGNORED, array()); } public function setIgnoredPathAttributes(array $attributes) { return $this->setPackageProperty(self::PROPERTY_IGNORED, $attributes); } public function loadOwners() { if (!$this->getID()) { return array(); } return id(new PhabricatorOwnersOwner())->loadAllWhere( 'packageID = %d', $this->getID()); } public function loadPaths() { if (!$this->getID()) { return array(); } return id(new PhabricatorOwnersPath())->loadAllWhere( 'packageID = %d', $this->getID()); } public static function loadAffectedPackages( PhabricatorRepository $repository, array $paths) { if (!$paths) { return array(); } return self::loadPackagesForPaths($repository, $paths); } public static function loadAffectedPackagesForChangesets( PhabricatorRepository $repository, DifferentialDiff $diff, array $changesets) { assert_instances_of($changesets, 'DifferentialChangeset'); $paths_all = array(); $paths_ungenerated = array(); foreach ($changesets as $changeset) { $path = $changeset->getAbsoluteRepositoryPath($repository, $diff); $paths_all[] = $path; if (!$changeset->isGeneratedChangeset()) { $paths_ungenerated[] = $path; } } if (!$paths_all) { return array(); } $packages_all = self::loadAffectedPackages( $repository, $paths_all); // If there are no generated changesets, we can't possibly need to throw // away any packages for matching only generated paths. Just return the // full set of packages. if ($paths_ungenerated === $paths_all) { return $packages_all; } $must_match_ungenerated = array(); foreach ($packages_all as $package) { if ($package->getMustMatchUngeneratedPaths()) { $must_match_ungenerated[] = $package; } } // If no affected packages have the "Ignore Generated Paths" flag set, we // can't possibly need to throw any away. if (!$must_match_ungenerated) { return $packages_all; } if ($paths_ungenerated) { $packages_ungenerated = self::loadAffectedPackages( $repository, $paths_ungenerated); } else { $packages_ungenerated = array(); } // We have some generated paths, and some packages that ignore generated // paths. Take all the packages which: // // - ignore generated paths; and // - didn't match any ungenerated paths // // ...and remove them from the list. $must_match_ungenerated = mpull($must_match_ungenerated, null, 'getID'); $packages_ungenerated = mpull($packages_ungenerated, null, 'getID'); $packages_all = mpull($packages_all, null, 'getID'); foreach ($must_match_ungenerated as $package_id => $package) { if (!isset($packages_ungenerated[$package_id])) { unset($packages_all[$package_id]); } } return $packages_all; } public static function loadOwningPackages($repository, $path) { if (empty($path)) { return array(); } return self::loadPackagesForPaths($repository, array($path), 1); } private static function loadPackagesForPaths( PhabricatorRepository $repository, array $paths, $limit = 0) { $fragments = array(); foreach ($paths as $path) { foreach (self::splitPath($path) as $fragment) { $fragments[$fragment][$path] = true; } } $package = new PhabricatorOwnersPackage(); $path = new PhabricatorOwnersPath(); $conn = $package->establishConnection('r'); $repository_clause = qsprintf( $conn, 'AND p.repositoryPHID = %s', $repository->getPHID()); // NOTE: The list of $paths may be very large if we're coming from // the OwnersWorker and processing, e.g., an SVN commit which created a new // branch. Break it apart so that it will fit within 'max_allowed_packet', // and then merge results in PHP. $rows = array(); foreach (array_chunk(array_keys($fragments), 1024) as $chunk) { $indexes = array(); foreach ($chunk as $fragment) { $indexes[] = PhabricatorHash::digestForIndex($fragment); } $rows[] = queryfx_all( $conn, 'SELECT pkg.id, pkg.dominion, p.excluded, p.path FROM %T pkg JOIN %T p ON p.packageID = pkg.id WHERE p.pathIndex IN (%Ls) AND pkg.status IN (%Ls) %Q', $package->getTableName(), $path->getTableName(), $indexes, array( self::STATUS_ACTIVE, ), $repository_clause); } $rows = array_mergev($rows); $ids = self::findLongestPathsPerPackage($rows, $fragments); if (!$ids) { return array(); } arsort($ids); if ($limit) { $ids = array_slice($ids, 0, $limit, $preserve_keys = true); } $ids = array_keys($ids); $packages = $package->loadAllWhere('id in (%Ld)', $ids); $packages = array_select_keys($packages, $ids); return $packages; } public static function loadPackagesForRepository($repository) { $package = new PhabricatorOwnersPackage(); $ids = ipull( queryfx_all( $package->establishConnection('r'), 'SELECT DISTINCT packageID FROM %T WHERE repositoryPHID = %s', id(new PhabricatorOwnersPath())->getTableName(), $repository->getPHID()), 'packageID'); return $package->loadAllWhere('id in (%Ld)', $ids); } public static function findLongestPathsPerPackage(array $rows, array $paths) { // Build a map from each path to all the package paths which match it. $path_hits = array(); $weak = array(); foreach ($rows as $row) { $id = $row['id']; $path = $row['path']; $length = strlen($path); $excluded = $row['excluded']; if ($row['dominion'] === self::DOMINION_WEAK) { $weak[$id] = true; } $matches = $paths[$path]; foreach ($matches as $match => $ignored) { $path_hits[$match][] = array( 'id' => $id, 'excluded' => $excluded, 'length' => $length, ); } } // For each path, process the matching package paths to figure out which // packages actually own it. $path_packages = array(); foreach ($path_hits as $match => $hits) { $hits = isort($hits, 'length'); $packages = array(); foreach ($hits as $hit) { $package_id = $hit['id']; if ($hit['excluded']) { unset($packages[$package_id]); } else { $packages[$package_id] = $hit; } } $path_packages[$match] = $packages; } // Remove packages with weak dominion rules that should cede control to // a more specific package. if ($weak) { foreach ($path_packages as $match => $packages) { // Group packages by length. $length_map = array(); foreach ($packages as $package_id => $package) { $length_map[$package['length']][$package_id] = $package; } // For each path length, remove all weak packages if there are any // strong packages of the same length. This makes sure that if there // are one or more strong claims on a particular path, only those // claims stand. foreach ($length_map as $package_list) { $any_strong = false; foreach ($package_list as $package_id => $package) { if (!isset($weak[$package_id])) { $any_strong = true; break; } } if ($any_strong) { foreach ($package_list as $package_id => $package) { if (isset($weak[$package_id])) { unset($packages[$package_id]); } } } } $packages = isort($packages, 'length'); $packages = array_reverse($packages, true); $best_length = null; foreach ($packages as $package_id => $package) { // If this is the first package we've encountered, note its length. // We're iterating over the packages from longest to shortest match, // so packages of this length always have the best claim on the path. if ($best_length === null) { $best_length = $package['length']; } // If this package has the same length as the best length, its claim // stands. if ($package['length'] === $best_length) { continue; } // If this is a weak package and does not have the best length, // cede its claim to the stronger package. if (isset($weak[$package_id])) { unset($packages[$package_id]); } } $path_packages[$match] = $packages; } } // For each package that owns at least one path, identify the longest // path it owns. $package_lengths = array(); foreach ($path_packages as $match => $hits) { foreach ($hits as $hit) { $length = $hit['length']; $id = $hit['id']; if (empty($package_lengths[$id])) { $package_lengths[$id] = $length; } else { $package_lengths[$id] = max($package_lengths[$id], $length); } } } return $package_lengths; } public static function splitPath($path) { $result = array( '/', ); $parts = explode('/', $path); $buffer = '/'; foreach ($parts as $part) { if (!strlen($part)) { continue; } $buffer = $buffer.$part.'/'; $result[] = $buffer; } return $result; } public function attachPaths(array $paths) { assert_instances_of($paths, 'PhabricatorOwnersPath'); $this->paths = $paths; // Drop this cache if we're attaching new paths. $this->pathRepositoryMap = array(); return $this; } public function getPaths() { return $this->assertAttached($this->paths); } public function getPathsForRepository($repository_phid) { if (isset($this->pathRepositoryMap[$repository_phid])) { return $this->pathRepositoryMap[$repository_phid]; } $map = array(); foreach ($this->getPaths() as $path) { if ($path->getRepositoryPHID() == $repository_phid) { $map[] = $path; } } $this->pathRepositoryMap[$repository_phid] = $map; return $this->pathRepositoryMap[$repository_phid]; } public function attachOwners(array $owners) { assert_instances_of($owners, 'PhabricatorOwnersOwner'); $this->owners = $owners; return $this; } public function getOwners() { return $this->assertAttached($this->owners); } public function getOwnerPHIDs() { return mpull($this->getOwners(), 'getUserPHID'); } public function isOwnerPHID($phid) { if (!$phid) { return false; } $owner_phids = $this->getOwnerPHIDs(); $owner_phids = array_fuse($owner_phids); return isset($owner_phids[$phid]); } public function getMonogram() { return 'O'.$this->getID(); } public function getURI() { // TODO: Move these to "/O123" for consistency. return '/owners/package/'.$this->getID().'/'; } + public function newAuditingRule() { + return PhabricatorOwnersAuditRule::newFromState($this->getAuditingState()); + } + /* -( 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) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: if ($this->isOwnerPHID($viewer->getPHID())) { return true; } break; } return false; } public function describeAutomaticCapability($capability) { return pht('Owners of a package may always view it.'); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorOwnersPackageTransactionEditor(); } public function getApplicationTransactionTemplate() { return new PhabricatorOwnersPackageTransaction(); } /* -( PhabricatorCustomFieldInterface )------------------------------------ */ public function getCustomFieldSpecificationForRole($role) { return PhabricatorEnv::getEnvConfig('owners.fields'); } public function getCustomFieldBaseClass() { return 'PhabricatorOwnersCustomField'; } 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(); $conn_w = $this->establishConnection('w'); queryfx( $conn_w, 'DELETE FROM %T WHERE packageID = %d', id(new PhabricatorOwnersPath())->getTableName(), $this->getID()); queryfx( $conn_w, 'DELETE FROM %T WHERE packageID = %d', id(new PhabricatorOwnersOwner())->getTableName(), $this->getID()); $this->delete(); $this->saveTransaction(); } /* -( PhabricatorConduitResultInterface )---------------------------------- */ public function getFieldSpecificationsForConduit() { return array( id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('name') ->setType('string') ->setDescription(pht('The name of the package.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('description') ->setType('string') ->setDescription(pht('The package description.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('status') ->setType('string') ->setDescription(pht('Active or archived status of the package.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('owners') ->setType('list>') ->setDescription(pht('List of package owners.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('review') ->setType('map') ->setDescription(pht('Auto review information.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('audit') ->setType('map') ->setDescription(pht('Auto audit information.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('dominion') ->setType('map') ->setDescription(pht('Dominion setting information.')), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('ignored') ->setType('map') ->setDescription(pht('Ignored attribute information.')), ); } public function getFieldValuesForConduit() { $owner_list = array(); foreach ($this->getOwners() as $owner) { $owner_list[] = array( 'ownerPHID' => $owner->getUserPHID(), ); } $review_map = self::getAutoreviewOptionsMap(); $review_value = $this->getAutoReview(); if (isset($review_map[$review_value])) { $review_label = $review_map[$review_value]['name']; } else { $review_label = pht('Unknown ("%s")', $review_value); } $review = array( 'value' => $review_value, 'label' => $review_label, ); - if ($this->getAuditingEnabled()) { - $audit_value = 'audit'; - $audit_label = pht('Auditing Enabled'); - } else { - $audit_value = 'none'; - $audit_label = pht('No Auditing'); - } + $audit_rule = $this->newAuditingRule(); $audit = array( - 'value' => $audit_value, - 'label' => $audit_label, + 'value' => $audit_rule->getKey(), + 'label' => $audit_rule->getDisplayName(), ); $dominion_value = $this->getDominion(); $dominion_map = self::getDominionOptionsMap(); if (isset($dominion_map[$dominion_value])) { $dominion_label = $dominion_map[$dominion_value]['name']; $dominion_short = $dominion_map[$dominion_value]['short']; } else { $dominion_label = pht('Unknown ("%s")', $dominion_value); $dominion_short = pht('Unknown ("%s")', $dominion_value); } $dominion = array( 'value' => $dominion_value, 'label' => $dominion_label, 'short' => $dominion_short, ); // Force this to always emit as a JSON object even if empty, never as // a JSON list. $ignored = $this->getIgnoredPathAttributes(); if (!$ignored) { $ignored = (object)array(); } return array( 'name' => $this->getName(), 'description' => $this->getDescription(), 'status' => $this->getStatus(), 'owners' => $owner_list, 'review' => $review, 'audit' => $audit, 'dominion' => $dominion, 'ignored' => $ignored, ); } public function getConduitSearchAttachments() { return array( id(new PhabricatorOwnersPathsSearchEngineAttachment()) ->setAttachmentKey('paths'), ); } /* -( PhabricatorFulltextInterface )--------------------------------------- */ public function newFulltextEngine() { return new PhabricatorOwnersPackageFulltextEngine(); } /* -( PhabricatorFerretInterface )----------------------------------------- */ public function newFerretEngine() { return new PhabricatorOwnersPackageFerretEngine(); } /* -( PhabricatorNgramsInterface )----------------------------------------- */ public function newNgrams() { return array( id(new PhabricatorOwnersPackageNameNgrams()) ->setValue($this->getName()), ); } } diff --git a/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php b/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php index 1dfc944f63..66e15b634a 100644 --- a/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php +++ b/src/applications/owners/storage/PhabricatorOwnersPackageTransaction.php @@ -1,22 +1,18 @@ getAuditingEnabled(); + return $object->getAuditingState(); } public function generateNewValue($object, $value) { - return (int)$value; + return PhabricatorOwnersAuditRule::getStorageValueFromAPIValue($value); } public function applyInternalEffects($object, $value) { - $object->setAuditingEnabled($value); + $object->setAuditingState($value); } public function getTitle() { - if ($this->getNewValue()) { - return pht( - '%s enabled auditing for this package.', - $this->renderAuthor()); - } else { - return pht( - '%s disabled auditing for this package.', - $this->renderAuthor()); + $old_value = $this->getOldValue(); + $new_value = $this->getNewValue(); + + $old_rule = PhabricatorOwnersAuditRule::newFromState($old_value); + $new_rule = PhabricatorOwnersAuditRule::newFromState($new_value); + + return pht( + '%s changed the audit rule for this package from %s to %s.', + $this->renderAuthor(), + $this->renderValue($old_rule->getDisplayName()), + $this->renderValue($new_rule->getDisplayName())); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + // See PHI1047. This transaction type accepted some weird stuff. Continue + // supporting it for now, but move toward sensible consistency. + + $modern_options = PhabricatorOwnersAuditRule::getModernValueMap(); + $deprecated_options = PhabricatorOwnersAuditRule::getDeprecatedValueMap(); + + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + + if (isset($modern_options[$new_value])) { + continue; + } + + if (isset($deprecated_options[$new_value])) { + continue; + } + + $errors[] = $this->newInvalidError( + pht( + 'Package auditing value "%s" is not supported. Supported options '. + 'are: %s. Deprecated options are: %s.', + $new_value, + implode(', ', $modern_options), + implode(', ', $deprecated_options)), + $xaction); } + + return $errors; } } diff --git a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php index b7e4f904ef..bbc3b09668 100644 --- a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php +++ b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php @@ -1,22 +1,18 @@ 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( $this->getQueryRoutePattern() => 'PhabricatorPeopleListController', 'logs/' => array( $this->getQueryRoutePattern() => 'PhabricatorPeopleLogsController', ), 'invite/' => array( '(?:query/(?P[^/]+)/)?' => 'PhabricatorPeopleInviteListController', 'send/' => 'PhabricatorPeopleInviteSendController', ), - 'approve/(?P[1-9]\d*)/' => 'PhabricatorPeopleApproveController', + 'approve/(?P[1-9]\d*)/(?:via/(?P[^/]+)/)?' + => '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', 'badges/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileBadgesController', 'tasks/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileTasksController', 'commits/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileCommitsController', 'revisions/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileRevisionsController', 'picture/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfilePictureController', 'manage/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileManageController', ), '/p/(?P[\w._-]+)/' => array( '' => 'PhabricatorPeopleProfileViewController', 'item/' => $this->getProfileMenuRouting( 'PhabricatorPeopleProfileMenuController'), ), ); } public function getRemarkupRules() { return array( new PhabricatorMentionRemarkupRule(), ); } protected function getCustomCapabilities() { return array( PeopleCreateUsersCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, ), PeopleDisableUsersCapability::CAPABILITY => array( 'default' => PhabricatorPolicies::POLICY_ADMIN, ), PeopleBrowseUserDirectoryCapability::CAPABILITY => array(), ); } public function getApplicationSearchDocumentTypes() { return array( PhabricatorPeopleUserPHIDType::TYPECONST, ); } } diff --git a/src/applications/people/controller/PhabricatorPeopleApproveController.php b/src/applications/people/controller/PhabricatorPeopleApproveController.php index 013f4371f6..af08a6fbdc 100644 --- a/src/applications/people/controller/PhabricatorPeopleApproveController.php +++ b/src/applications/people/controller/PhabricatorPeopleApproveController.php @@ -1,52 +1,60 @@ getViewer(); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->executeOne(); if (!$user) { return new Aphront404Response(); } - $done_uri = $this->getApplicationURI('query/approval/'); + $via = $request->getURIData('via'); + switch ($via) { + case 'profile': + $done_uri = urisprintf('/people/manage/%d/', $user->getID()); + break; + default: + $done_uri = $this->getApplicationURI('query/approval/'); + break; + } if ($user->getIsApproved()) { return $this->newDialog() ->setTitle(pht('Already Approved')) ->appendChild(pht('This user has already been approved.')) ->addCancelButton($done_uri); } if ($request->isFormPost()) { $xactions = array(); $xactions[] = id(new PhabricatorUserTransaction()) ->setTransactionType(PhabricatorUserApproveTransaction::TRANSACTIONTYPE) ->setNewValue(true); id(new PhabricatorUserTransactionEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($user, $xactions); return id(new AphrontRedirectResponse())->setURI($done_uri); } return $this->newDialog() ->setTitle(pht('Confirm Approval')) ->appendChild( pht( 'Allow %s to access this Phabricator install?', phutil_tag('strong', array(), $user->getUsername()))) ->addCancelButton($done_uri) ->addSubmitButton(pht('Approve Account')); } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php index 902b21efcc..91afda123b 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php @@ -1,128 +1,141 @@ 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 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; } public function buildProfileHeader() { $user = $this->user; $viewer = $this->getViewer(); $profile = $user->loadUserProfile(); $picture = $user->getProfileImageURI(); $profile_icon = PhabricatorPeopleIconSet::getIconIcon($profile->getIcon()); $profile_title = $profile->getDisplayTitle(); - $roles = array(); + + $tag = id(new PHUITagView()) + ->setType(PHUITagView::TYPE_SHADE); + + $tags = array(); if ($user->getIsAdmin()) { - $roles[] = pht('Administrator'); - } - if ($user->getIsDisabled()) { - $roles[] = pht('Disabled'); + $tags[] = id(clone $tag) + ->setName(pht('Administrator')) + ->setColor('blue'); } + + // "Disabled" gets a stronger status tag below. + if (!$user->getIsApproved()) { - $roles[] = pht('Not Approved'); + $tags[] = id(clone $tag) + ->setName('Not Approved') + ->setColor('yellow'); } + if ($user->getIsSystemAgent()) { - $roles[] = pht('Bot'); + $tags[] = id(clone $tag) + ->setName(pht('Bot')) + ->setColor('orange'); } + if ($user->getIsMailingList()) { - $roles[] = pht('Mailing List'); - } - if (!$user->getIsEmailVerified()) { - $roles[] = pht('Email Not Verified'); + $tags[] = id(clone $tag) + ->setName(pht('Mailing List')) + ->setColor('orange'); } - $tag = null; - if ($roles) { - $tag = id(new PHUITagView()) - ->setName(implode(', ', $roles)) - ->addClass('project-view-header-tag') - ->setType(PHUITagView::TYPE_SHADE); + if (!$user->getIsEmailVerified()) { + $tags[] = id(clone $tag) + ->setName(pht('Email Not Verified')) + ->setColor('violet'); } $header = id(new PHUIHeaderView()) - ->setHeader(array($user->getFullName(), $tag)) + ->setHeader($user->getFullName()) ->setImage($picture) ->setProfileHeader(true) ->addClass('people-profile-header'); + foreach ($tags as $tag) { + $header->addTag($tag); + } + require_celerity_resource('project-view-css'); if ($user->getIsDisabled()) { $header->setStatus('fa-ban', 'red', pht('Disabled')); } else { $header->setStatus($profile_icon, 'bluegrey', $profile_title); } $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $user, PhabricatorPolicyCapability::CAN_EDIT); if ($can_edit) { $id = $user->getID(); $header->setImageEditURL($this->getApplicationURI("picture/{$id}/")); } return $header; } } diff --git a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php index e9faae3d62..835935f775 100644 --- a/src/applications/people/controller/PhabricatorPeopleProfileManageController.php +++ b/src/applications/people/controller/PhabricatorPeopleProfileManageController.php @@ -1,194 +1,211 @@ 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); $header = $this->buildProfileHeader(); $curtain = $this->buildCurtain($user); $properties = $this->buildPropertyView($user); $name = $user->getUsername(); $nav = $this->getProfileMenu(); $nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Manage')); $crumbs->setBorder(true); $timeline = $this->buildTransactionTimeline( $user, new PhabricatorPeopleTransactionQuery()); $timeline->setShouldTerminate(true); $manage = id(new PHUITwoColumnView()) ->setHeader($header) ->addClass('project-view-home') ->addClass('project-view-people-home') ->setCurtain($curtain) ->addPropertySection(pht('Details'), $properties) ->setMainColumn($timeline); return $this->newPage() ->setTitle( array( pht('Manage User'), $user->getUsername(), )) ->setNavigation($nav) ->setCrumbs($crumbs) ->appendChild($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(); $is_self = ($user->getPHID() === $viewer->getPHID()); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $user, PhabricatorPolicyCapability::CAN_EDIT); $is_admin = $viewer->getIsAdmin(); $can_admin = ($is_admin && !$is_self); $has_disable = $this->hasApplicationCapability( PeopleDisableUsersCapability::CAPABILITY); $can_disable = ($has_disable && !$is_self); + $id = $user->getID(); + $welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine()) ->setSender($viewer) ->setRecipient($user); $can_welcome = $welcome_engine->canSendMail(); $curtain = $this->newCurtainView($user); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-pencil') ->setName(pht('Edit Profile')) - ->setHref($this->getApplicationURI('editprofile/'.$user->getID().'/')) + ->setHref($this->getApplicationURI('editprofile/'.$id.'/')) ->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().'/')) + ->setHref($this->getApplicationURI('picture/'.$id.'/')) ->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'); } $curtain->addAction( id(new PhabricatorActionView()) ->setIcon($empower_icon) ->setName($empower_name) ->setDisabled(!$can_admin) ->setWorkflow(true) - ->setHref($this->getApplicationURI('empower/'.$user->getID().'/'))); + ->setHref($this->getApplicationURI('empower/'.$id.'/'))); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-tag') ->setName(pht('Change Username')) ->setDisabled(!$is_admin) ->setWorkflow(true) - ->setHref($this->getApplicationURI('rename/'.$user->getID().'/'))); + ->setHref($this->getApplicationURI('rename/'.$id.'/'))); 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('fa-envelope') ->setName(pht('Send Welcome Email')) ->setWorkflow(true) ->setDisabled(!$can_welcome) - ->setHref($this->getApplicationURI('welcome/'.$user->getID().'/'))); + ->setHref($this->getApplicationURI('welcome/'.$id.'/'))); $curtain->addAction( id(new PhabricatorActionView()) ->setType(PhabricatorActionView::TYPE_DIVIDER)); + if (!$user->getIsApproved()) { + $approve_action = id(new PhabricatorActionView()) + ->setIcon('fa-thumbs-up') + ->setName(pht('Approve User')) + ->setWorkflow(true) + ->setDisabled(!$is_admin) + ->setHref("/people/approve/{$id}/via/profile/"); + + if ($is_admin) { + $approve_action->setColor(PhabricatorActionView::GREEN); + } + + $curtain->addAction($approve_action); + } + $curtain->addAction( id(new PhabricatorActionView()) ->setIcon($disable_icon) ->setName($disable_name) ->setDisabled(!$can_disable) ->setWorkflow(true) - ->setHref($this->getApplicationURI('disable/'.$user->getID().'/'))); + ->setHref($this->getApplicationURI('disable/'.$id.'/'))); $curtain->addAction( id(new PhabricatorActionView()) ->setIcon('fa-times') ->setName(pht('Delete User')) ->setDisabled(!$can_admin) ->setWorkflow(true) - ->setHref($this->getApplicationURI('delete/'.$user->getID().'/'))); + ->setHref($this->getApplicationURI('delete/'.$id.'/'))); $curtain->addAction( id(new PhabricatorActionView()) ->setType(PhabricatorActionView::TYPE_DIVIDER)); return $curtain; } } diff --git a/src/applications/people/mail/PhabricatorPeopleUsernameMailEngine.php b/src/applications/people/mail/PhabricatorPeopleUsernameMailEngine.php new file mode 100644 index 0000000000..c954b7c38e --- /dev/null +++ b/src/applications/people/mail/PhabricatorPeopleUsernameMailEngine.php @@ -0,0 +1,60 @@ +newUsername = $new_username; + return $this; + } + + public function getNewUsername() { + return $this->newUsername; + } + + public function setOldUsername($old_username) { + $this->oldUsername = $old_username; + return $this; + } + + public function getOldUsername() { + return $this->oldUsername; + } + + public function validateMail() { + return; + } + + protected function newMail() { + $sender = $this->getSender(); + $recipient = $this->getRecipient(); + + $sender_username = $sender->getUsername(); + $sender_realname = $sender->getRealName(); + + $old_username = $this->getOldUsername(); + $new_username = $this->getNewUsername(); + + $body = sprintf( + "%s\n\n %s\n %s\n", + pht( + '%s (%s) has changed your Phabricator username.', + $sender_username, + $sender_realname), + pht( + 'Old Username: %s', + $old_username), + pht( + 'New Username: %s', + $new_username)); + + return id(new PhabricatorMetaMTAMail()) + ->addTos(array($recipient->getPHID())) + ->setSubject(pht('[Phabricator] Username Changed')) + ->setBody($body); + } + +} diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php index 0b18c292c2..055df8b79e 100644 --- a/src/applications/people/storage/PhabricatorUser.php +++ b/src/applications/people/storage/PhabricatorUser.php @@ -1,1574 +1,1526 @@ isAdmin; case 'isDisabled': return (bool)$this->isDisabled; case 'isSystemAgent': return (bool)$this->isSystemAgent; case 'isMailingList': return (bool)$this->isMailingList; case 'isEmailVerified': return (bool)$this->isEmailVerified; case 'isApproved': return (bool)$this->isApproved; default: return parent::readField($field); } } /** * Is this a live account which has passed required approvals? Returns true * if this is an enabled, verified (if required), approved (if required) * account, and false otherwise. * * @return bool True if this is a standard, usable account. */ public function isUserActivated() { if (!$this->isLoggedIn()) { return false; } if ($this->isOmnipotent()) { return true; } if ($this->getIsDisabled()) { return false; } if (!$this->getIsApproved()) { return false; } if (PhabricatorUserEmail::isEmailVerificationRequired()) { if (!$this->getIsEmailVerified()) { return false; } } return true; } /** * Is this a user who we can reasonably expect to respond to requests? * * This is used to provide a grey "disabled/unresponsive" dot cue when * rendering handles and tags, so it isn't a surprise if you get ignored * when you ask things of users who will not receive notifications or could * not respond to them (because they are disabled, unapproved, do not have * verified email addresses, etc). * * @return bool True if this user can receive and respond to requests from * other humans. */ public function isResponsive() { if (!$this->isUserActivated()) { return false; } if (!$this->getIsEmailVerified()) { return false; } return true; } public function canEstablishWebSessions() { if ($this->getIsMailingList()) { return false; } if ($this->getIsSystemAgent()) { return false; } return true; } public function canEstablishAPISessions() { if ($this->getIsDisabled()) { return false; } // Intracluster requests are permitted even if the user is logged out: // in particular, public users are allowed to issue intracluster requests // when browsing Diffusion. if (PhabricatorEnv::isClusterRemoteAddress()) { if (!$this->isLoggedIn()) { return true; } } if (!$this->isUserActivated()) { return false; } if ($this->getIsMailingList()) { return false; } return true; } public function canEstablishSSHSessions() { if (!$this->isUserActivated()) { return false; } if ($this->getIsMailingList()) { return false; } return true; } /** * Returns `true` if this is a standard user who is logged in. Returns `false` * for logged out, anonymous, or external users. * * @return bool `true` if the user is a standard user who is logged in with * a normal session. */ public function getIsStandardUser() { $type_user = PhabricatorPeopleUserPHIDType::TYPECONST; return $this->getPHID() && (phid_get_type($this->getPHID()) == $type_user); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'userName' => 'sort64', 'realName' => 'text128', 'profileImagePHID' => 'phid?', 'conduitCertificate' => 'text255', 'isSystemAgent' => 'bool', 'isMailingList' => 'bool', 'isDisabled' => 'bool', 'isAdmin' => 'bool', 'isEmailVerified' => 'uint32', 'isApproved' => 'uint32', 'accountSecret' => 'bytes64', 'isEnrolledInMultiFactor' => 'bool', 'availabilityCache' => 'text255?', 'availabilityCacheTTL' => 'uint32?', 'defaultProfileImagePHID' => 'phid?', 'defaultProfileImageVersion' => 'text64?', ), self::CONFIG_KEY_SCHEMA => array( 'key_phid' => null, 'phid' => array( 'columns' => array('phid'), 'unique' => true, ), 'userName' => array( 'columns' => array('userName'), 'unique' => true, ), 'realName' => array( 'columns' => array('realName'), ), 'key_approved' => array( 'columns' => array('isApproved'), ), ), self::CONFIG_NO_MUTATE => array( 'availabilityCache' => true, 'availabilityCacheTTL' => true, ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPeopleUserPHIDType::TYPECONST); } public function getMonogram() { return '@'.$this->getUsername(); } public function isLoggedIn() { return !($this->getPHID() === null); } public function saveWithoutIndex() { return parent::save(); } public function save() { if (!$this->getConduitCertificate()) { $this->setConduitCertificate($this->generateConduitCertificate()); } if (!strlen($this->getAccountSecret())) { $this->setAccountSecret(Filesystem::readRandomCharacters(64)); } $result = $this->saveWithoutIndex(); if ($this->profile) { $this->profile->save(); } $this->updateNameTokens(); PhabricatorSearchWorker::queueDocumentForIndexing($this->getPHID()); return $result; } public function attachSession(PhabricatorAuthSession $session) { $this->session = $session; return $this; } public function getSession() { return $this->assertAttached($this->session); } public function hasSession() { return ($this->session !== self::ATTACHABLE); } public function hasHighSecuritySession() { if (!$this->hasSession()) { return false; } return $this->getSession()->isHighSecuritySession(); } private function generateConduitCertificate() { return Filesystem::readRandomCharacters(255); } const EMAIL_CYCLE_FREQUENCY = 86400; const EMAIL_TOKEN_LENGTH = 24; public function getUserProfile() { return $this->assertAttached($this->profile); } public function attachUserProfile(PhabricatorUserProfile $profile) { $this->profile = $profile; return $this; } public function loadUserProfile() { if ($this->profile) { return $this->profile; } $profile_dao = new PhabricatorUserProfile(); $this->profile = $profile_dao->loadOneWhere('userPHID = %s', $this->getPHID()); if (!$this->profile) { $this->profile = PhabricatorUserProfile::initializeNewProfile($this); } return $this->profile; } public function loadPrimaryEmailAddress() { $email = $this->loadPrimaryEmail(); if (!$email) { throw new Exception(pht('User has no primary email address!')); } return $email->getAddress(); } public function loadPrimaryEmail() { return id(new PhabricatorUserEmail())->loadOneWhere( 'userPHID = %s AND isPrimary = 1', $this->getPHID()); } /* -( Settings )----------------------------------------------------------- */ public function getUserSetting($key) { // NOTE: We store available keys and cached values separately to make it // faster to check for `null` in the cache, which is common. if (isset($this->settingCacheKeys[$key])) { return $this->settingCache[$key]; } $settings_key = PhabricatorUserPreferencesCacheType::KEY_PREFERENCES; if ($this->getPHID()) { $settings = $this->requireCacheData($settings_key); } else { $settings = $this->loadGlobalSettings(); } if (array_key_exists($key, $settings)) { $value = $settings[$key]; return $this->writeUserSettingCache($key, $value); } $cache = PhabricatorCaches::getRuntimeCache(); $cache_key = "settings.defaults({$key})"; $cache_map = $cache->getKeys(array($cache_key)); if ($cache_map) { $value = $cache_map[$cache_key]; } else { $defaults = PhabricatorSetting::getAllSettings(); if (isset($defaults[$key])) { $value = id(clone $defaults[$key]) ->setViewer($this) ->getSettingDefaultValue(); } else { $value = null; } $cache->setKey($cache_key, $value); } return $this->writeUserSettingCache($key, $value); } /** * Test if a given setting is set to a particular value. * * @param const Setting key. * @param wild Value to compare. * @return bool True if the setting has the specified value. * @task settings */ public function compareUserSetting($key, $value) { $actual = $this->getUserSetting($key); return ($actual == $value); } private function writeUserSettingCache($key, $value) { $this->settingCacheKeys[$key] = true; $this->settingCache[$key] = $value; return $value; } public function getTranslation() { return $this->getUserSetting(PhabricatorTranslationSetting::SETTINGKEY); } public function getTimezoneIdentifier() { return $this->getUserSetting(PhabricatorTimezoneSetting::SETTINGKEY); } public static function getGlobalSettingsCacheKey() { return 'user.settings.globals.v1'; } private function loadGlobalSettings() { $cache_key = self::getGlobalSettingsCacheKey(); $cache = PhabricatorCaches::getMutableStructureCache(); $settings = $cache->getKey($cache_key); if (!$settings) { $preferences = PhabricatorUserPreferences::loadGlobalPreferences($this); $settings = $preferences->getPreferences(); $cache->setKey($cache_key, $settings); } return $settings; } /** * Override the user's timezone identifier. * * This is primarily useful for unit tests. * * @param string New timezone identifier. * @return this * @task settings */ public function overrideTimezoneIdentifier($identifier) { $timezone_key = PhabricatorTimezoneSetting::SETTINGKEY; $this->settingCacheKeys[$timezone_key] = true; $this->settingCache[$timezone_key] = $identifier; return $this; } public function getGender() { return $this->getUserSetting(PhabricatorPronounSetting::SETTINGKEY); } public function loadEditorLink( $path, $line, PhabricatorRepository $repository = null) { $editor = $this->getUserSetting(PhabricatorEditorSetting::SETTINGKEY); if (is_array($path)) { $multi_key = PhabricatorEditorMultipleSetting::SETTINGKEY; $multiedit = $this->getUserSetting($multi_key); switch ($multiedit) { case PhabricatorEditorMultipleSetting::VALUE_SPACES: $path = implode(' ', $path); break; case PhabricatorEditorMultipleSetting::VALUE_SINGLE: default: return null; } } if (!strlen($editor)) { return null; } if ($repository) { $callsign = $repository->getCallsign(); } else { $callsign = null; } $uri = strtr($editor, array( '%%' => '%', '%f' => phutil_escape_uri($path), '%l' => phutil_escape_uri($line), '%r' => phutil_escape_uri($callsign), )); // The resulting URI must have an allowed protocol. Otherwise, we'll return // a link to an error page explaining the misconfiguration. $ok = PhabricatorHelpEditorProtocolController::hasAllowedProtocol($uri); if (!$ok) { return '/help/editorprotocol/'; } return (string)$uri; } /** * Populate the nametoken table, which used to fetch typeahead results. When * a user types "linc", we want to match "Abraham Lincoln" from on-demand * typeahead sources. To do this, we need a separate table of name fragments. */ public function updateNameTokens() { $table = self::NAMETOKEN_TABLE; $conn_w = $this->establishConnection('w'); $tokens = PhabricatorTypeaheadDatasource::tokenizeString( $this->getUserName().' '.$this->getRealName()); $sql = array(); foreach ($tokens as $token) { $sql[] = qsprintf( $conn_w, '(%d, %s)', $this->getID(), $token); } queryfx( $conn_w, 'DELETE FROM %T WHERE userID = %d', $table, $this->getID()); if ($sql) { queryfx( $conn_w, 'INSERT INTO %T (userID, token) VALUES %LQ', $table, $sql); } } - public function sendUsernameChangeEmail( - PhabricatorUser $admin, - $old_username) { - - $admin_username = $admin->getUserName(); - $admin_realname = $admin->getRealName(); - $new_username = $this->getUserName(); - - $password_instructions = null; - if (PhabricatorPasswordAuthProvider::getPasswordProvider()) { - $engine = new PhabricatorAuthSessionEngine(); - $uri = $engine->getOneTimeLoginURI( - $this, - null, - PhabricatorAuthSessionEngine::ONETIME_USERNAME); - $password_instructions = sprintf( - "%s\n\n %s\n\n%s\n", - pht( - "If you use a password to login, you'll need to reset it ". - "before you can login again. You can reset your password by ". - "following this link:"), - $uri, - pht( - "And, of course, you'll need to use your new username to login ". - "from now on. If you use OAuth to login, nothing should change.")); - } - - $body = sprintf( - "%s\n\n %s\n %s\n\n%s", - pht( - '%s (%s) has changed your Phabricator username.', - $admin_username, - $admin_realname), - pht( - 'Old Username: %s', - $old_username), - pht( - 'New Username: %s', - $new_username), - $password_instructions); - - $mail = id(new PhabricatorMetaMTAMail()) - ->addTos(array($this->getPHID())) - ->setForceDelivery(true) - ->setSubject(pht('[Phabricator] Username Changed')) - ->setBody($body) - ->saveAndSend(); - } - public static function describeValidUsername() { return pht( 'Usernames must contain only numbers, letters, period, underscore and '. 'hyphen, and can not end with a period. They must have no more than %d '. 'characters.', new PhutilNumber(self::MAXIMUM_USERNAME_LENGTH)); } public static function validateUsername($username) { // NOTE: If you update this, make sure to update: // // - Remarkup rule for @mentions. // - Routing rule for "/p/username/". // - Unit tests, obviously. // - describeValidUsername() method, above. if (strlen($username) > self::MAXIMUM_USERNAME_LENGTH) { return false; } return (bool)preg_match('/^[a-zA-Z0-9._-]*[a-zA-Z0-9_-]\z/', $username); } public static function getDefaultProfileImageURI() { return celerity_get_resource_uri('/rsrc/image/avatar.png'); } public function getProfileImageURI() { $uri_key = PhabricatorUserProfileImageCacheType::KEY_URI; return $this->requireCacheData($uri_key); } public function getUnreadNotificationCount() { $notification_key = PhabricatorUserNotificationCountCacheType::KEY_COUNT; return $this->requireCacheData($notification_key); } public function getUnreadMessageCount() { $message_key = PhabricatorUserMessageCountCacheType::KEY_COUNT; return $this->requireCacheData($message_key); } public function getRecentBadgeAwards() { $badges_key = PhabricatorUserBadgesCacheType::KEY_BADGES; return $this->requireCacheData($badges_key); } public function getFullName() { if (strlen($this->getRealName())) { return $this->getUsername().' ('.$this->getRealName().')'; } else { return $this->getUsername(); } } public function getTimeZone() { return new DateTimeZone($this->getTimezoneIdentifier()); } public function getTimeZoneOffset() { $timezone = $this->getTimeZone(); $now = new DateTime('@'.PhabricatorTime::getNow()); $offset = $timezone->getOffset($now); // Javascript offsets are in minutes and have the opposite sign. $offset = -(int)($offset / 60); return $offset; } public function getTimeZoneOffsetInHours() { $offset = $this->getTimeZoneOffset(); $offset = (int)round($offset / 60); $offset = -$offset; return $offset; } public function formatShortDateTime($when, $now = null) { if ($now === null) { $now = PhabricatorTime::getNow(); } try { $when = new DateTime('@'.$when); $now = new DateTime('@'.$now); } catch (Exception $ex) { return null; } $zone = $this->getTimeZone(); $when->setTimeZone($zone); $now->setTimeZone($zone); if ($when->format('Y') !== $now->format('Y')) { // Different year, so show "Feb 31 2075". $format = 'M j Y'; } else if ($when->format('Ymd') !== $now->format('Ymd')) { // Same year but different month and day, so show "Feb 31". $format = 'M j'; } else { // Same year, month and day so show a time of day. $pref_time = PhabricatorTimeFormatSetting::SETTINGKEY; $format = $this->getUserSetting($pref_time); } return $when->format($format); } public function __toString() { return $this->getUsername(); } public static function loadOneWithEmailAddress($address) { $email = id(new PhabricatorUserEmail())->loadOneWhere( 'address = %s', $address); if (!$email) { return null; } return id(new PhabricatorUser())->loadOneWhere( 'phid = %s', $email->getUserPHID()); } public function getDefaultSpacePHID() { // TODO: We might let the user switch which space they're "in" later on; // for now just use the global space if one exists. // If the viewer has access to the default space, use that. $spaces = PhabricatorSpacesNamespaceQuery::getViewerActiveSpaces($this); foreach ($spaces as $space) { if ($space->getIsDefaultNamespace()) { return $space->getPHID(); } } // Otherwise, use the space with the lowest ID that they have access to. // This just tends to keep the default stable and predictable over time, // so adding a new space won't change behavior for users. if ($spaces) { $spaces = msort($spaces, 'getID'); return head($spaces)->getPHID(); } return null; } /** * Grant a user a source of authority, to let them bypass policy checks they * could not otherwise. */ public function grantAuthority($authority) { $this->authorities[] = $authority; return $this; } /** * Get authorities granted to the user. */ public function getAuthorities() { return $this->authorities; } public function hasConduitClusterToken() { return ($this->conduitClusterToken !== self::ATTACHABLE); } public function attachConduitClusterToken(PhabricatorConduitToken $token) { $this->conduitClusterToken = $token; return $this; } public function getConduitClusterToken() { return $this->assertAttached($this->conduitClusterToken); } /* -( Availability )------------------------------------------------------- */ /** * @task availability */ public function attachAvailability(array $availability) { $this->availability = $availability; return $this; } /** * Get the timestamp the user is away until, if they are currently away. * * @return int|null Epoch timestamp, or `null` if the user is not away. * @task availability */ public function getAwayUntil() { $availability = $this->availability; $this->assertAttached($availability); if (!$availability) { return null; } return idx($availability, 'until'); } public function getDisplayAvailability() { $availability = $this->availability; $this->assertAttached($availability); if (!$availability) { return null; } $busy = PhabricatorCalendarEventInvitee::AVAILABILITY_BUSY; return idx($availability, 'availability', $busy); } public function getAvailabilityEventPHID() { $availability = $this->availability; $this->assertAttached($availability); if (!$availability) { return null; } return idx($availability, 'eventPHID'); } /** * Get cached availability, if present. * * @return wild|null Cache data, or null if no cache is available. * @task availability */ public function getAvailabilityCache() { $now = PhabricatorTime::getNow(); if ($this->availabilityCacheTTL <= $now) { return null; } try { return phutil_json_decode($this->availabilityCache); } catch (Exception $ex) { return null; } } /** * Write to the availability cache. * * @param wild Availability cache data. * @param int|null Cache TTL. * @return this * @task availability */ public function writeAvailabilityCache(array $availability, $ttl) { if (PhabricatorEnv::isReadOnly()) { return $this; } $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); queryfx( $this->establishConnection('w'), 'UPDATE %T SET availabilityCache = %s, availabilityCacheTTL = %nd WHERE id = %d', $this->getTableName(), phutil_json_encode($availability), $ttl, $this->getID()); unset($unguarded); return $this; } /* -( Multi-Factor Authentication )---------------------------------------- */ /** * Update the flag storing this user's enrollment in multi-factor auth. * * With certain settings, we need to check if a user has MFA on every page, * so we cache MFA enrollment on the user object for performance. Calling this * method synchronizes the cache by examining enrollment records. After * updating the cache, use @{method:getIsEnrolledInMultiFactor} to check if * the user is enrolled. * * This method should be called after any changes are made to a given user's * multi-factor configuration. * * @return void * @task factors */ public function updateMultiFactorEnrollment() { $factors = id(new PhabricatorAuthFactorConfigQuery()) ->setViewer($this) ->withUserPHIDs(array($this->getPHID())) ->withFactorProviderStatuses( array( PhabricatorAuthFactorProviderStatus::STATUS_ACTIVE, PhabricatorAuthFactorProviderStatus::STATUS_DEPRECATED, )) ->execute(); $enrolled = count($factors) ? 1 : 0; if ($enrolled !== $this->isEnrolledInMultiFactor) { $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); queryfx( $this->establishConnection('w'), 'UPDATE %T SET isEnrolledInMultiFactor = %d WHERE id = %d', $this->getTableName(), $enrolled, $this->getID()); unset($unguarded); $this->isEnrolledInMultiFactor = $enrolled; } } /** * Check if the user is enrolled in multi-factor authentication. * * Enrolled users have one or more multi-factor authentication sources * attached to their account. For performance, this value is cached. You * can use @{method:updateMultiFactorEnrollment} to update the cache. * * @return bool True if the user is enrolled. * @task factors */ public function getIsEnrolledInMultiFactor() { return $this->isEnrolledInMultiFactor; } /* -( Omnipotence )-------------------------------------------------------- */ /** * Returns true if this user is omnipotent. Omnipotent users bypass all policy * checks. * * @return bool True if the user bypasses policy checks. */ public function isOmnipotent() { return $this->omnipotent; } /** * Get an omnipotent user object for use in contexts where there is no acting * user, notably daemons. * * @return PhabricatorUser An omnipotent user. */ public static function getOmnipotentUser() { static $user = null; if (!$user) { $user = new PhabricatorUser(); $user->omnipotent = true; $user->makeEphemeral(); } return $user; } /** * Get a scalar string identifying this user. * * This is similar to using the PHID, but distinguishes between omnipotent * and public users explicitly. This allows safe construction of cache keys * or cache buckets which do not conflate public and omnipotent users. * * @return string Scalar identifier. */ public function getCacheFragment() { if ($this->isOmnipotent()) { return 'u.omnipotent'; } $phid = $this->getPHID(); if ($phid) { return 'u.'.$phid; } return 'u.public'; } /* -( Managing Handles )--------------------------------------------------- */ /** * Get a @{class:PhabricatorHandleList} which benefits from this viewer's * internal handle pool. * * @param list List of PHIDs to load. * @return PhabricatorHandleList Handle list object. * @task handle */ public function loadHandles(array $phids) { if ($this->handlePool === null) { $this->handlePool = id(new PhabricatorHandlePool()) ->setViewer($this); } return $this->handlePool->newHandleList($phids); } /** * Get a @{class:PHUIHandleView} for a single handle. * * This benefits from the viewer's internal handle pool. * * @param phid PHID to render a handle for. * @return PHUIHandleView View of the handle. * @task handle */ public function renderHandle($phid) { return $this->loadHandles(array($phid))->renderHandle($phid); } /** * Get a @{class:PHUIHandleListView} for a list of handles. * * This benefits from the viewer's internal handle pool. * * @param list List of PHIDs to render. * @return PHUIHandleListView View of the handles. * @task handle */ public function renderHandleList(array $phids) { return $this->loadHandles($phids)->renderList(); } public function attachBadgePHIDs(array $phids) { $this->badgePHIDs = $phids; return $this; } public function getBadgePHIDs() { return $this->assertAttached($this->badgePHIDs); } /* -( CSRF )--------------------------------------------------------------- */ public function getCSRFToken() { if ($this->isOmnipotent()) { // We may end up here when called from the daemons. The omnipotent user // has no meaningful CSRF token, so just return `null`. return null; } return $this->newCSRFEngine() ->newToken(); } public function validateCSRFToken($token) { return $this->newCSRFengine() ->isValidToken($token); } public function getAlternateCSRFString() { return $this->assertAttached($this->alternateCSRFString); } public function attachAlternateCSRFString($string) { $this->alternateCSRFString = $string; return $this; } private function newCSRFEngine() { if ($this->getPHID()) { $vec = $this->getPHID().$this->getAccountSecret(); } else { $vec = $this->getAlternateCSRFString(); } if ($this->hasSession()) { $vec = $vec.$this->getSession()->getSessionKey(); } $engine = new PhabricatorAuthCSRFEngine(); if ($this->csrfSalt === null) { $this->csrfSalt = $engine->newSalt(); } $engine ->setSalt($this->csrfSalt) ->setSecret(new PhutilOpaqueEnvelope($vec)); return $engine; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return PhabricatorPolicies::POLICY_PUBLIC; case PhabricatorPolicyCapability::CAN_EDIT: if ($this->getIsSystemAgent() || $this->getIsMailingList()) { return PhabricatorPolicies::POLICY_ADMIN; } else { return PhabricatorPolicies::POLICY_NOONE; } } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return $this->getPHID() && ($viewer->getPHID() === $this->getPHID()); } public function describeAutomaticCapability($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_EDIT: return pht('Only you can edit your information.'); default: return null; } } /* -( PhabricatorCustomFieldInterface )------------------------------------ */ public function getCustomFieldSpecificationForRole($role) { return PhabricatorEnv::getEnvConfig('user.fields'); } public function getCustomFieldBaseClass() { return 'PhabricatorUserCustomField'; } 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(); - $externals = id(new PhabricatorExternalAccount())->loadAllWhere( - 'userPHID = %s', - $this->getPHID()); + $externals = id(new PhabricatorExternalAccountQuery()) + ->setViewer($engine->getViewer()) + ->withUserPHIDs(array($this->getPHID())) + ->execute(); foreach ($externals as $external) { $external->delete(); } $prefs = id(new PhabricatorUserPreferencesQuery()) ->setViewer($engine->getViewer()) ->withUsers(array($this)) ->execute(); foreach ($prefs as $pref) { $engine->destroyObject($pref); } $profiles = id(new PhabricatorUserProfile())->loadAllWhere( 'userPHID = %s', $this->getPHID()); foreach ($profiles as $profile) { $profile->delete(); } $keys = id(new PhabricatorAuthSSHKeyQuery()) ->setViewer($engine->getViewer()) ->withObjectPHIDs(array($this->getPHID())) ->execute(); foreach ($keys as $key) { $engine->destroyObject($key); } $emails = id(new PhabricatorUserEmail())->loadAllWhere( 'userPHID = %s', $this->getPHID()); foreach ($emails as $email) { $email->delete(); } $sessions = id(new PhabricatorAuthSession())->loadAllWhere( 'userPHID = %s', $this->getPHID()); foreach ($sessions as $session) { $session->delete(); } $factors = id(new PhabricatorAuthFactorConfig())->loadAllWhere( 'userPHID = %s', $this->getPHID()); foreach ($factors as $factor) { $factor->delete(); } $this->saveTransaction(); } /* -( PhabricatorSSHPublicKeyInterface )----------------------------------- */ public function getSSHPublicKeyManagementURI(PhabricatorUser $viewer) { if ($viewer->getPHID() == $this->getPHID()) { // If the viewer is managing their own keys, take them to the normal // panel. return '/settings/panel/ssh/'; } else { // Otherwise, take them to the administrative panel for this user. return '/settings/user/'.$this->getUsername().'/page/ssh/'; } } public function getSSHKeyDefaultName() { return 'id_rsa_phabricator'; } public function getSSHKeyNotifyPHIDs() { return array( $this->getPHID(), ); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorUserTransactionEditor(); } public function getApplicationTransactionTemplate() { return new PhabricatorUserTransaction(); } /* -( PhabricatorFulltextInterface )--------------------------------------- */ public function newFulltextEngine() { return new PhabricatorUserFulltextEngine(); } /* -( PhabricatorFerretInterface )----------------------------------------- */ public function newFerretEngine() { return new PhabricatorUserFerretEngine(); } /* -( PhabricatorConduitResultInterface )---------------------------------- */ public function getFieldSpecificationsForConduit() { return array( id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('username') ->setType('string') ->setDescription(pht("The user's username.")), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('realName') ->setType('string') ->setDescription(pht("The user's real name.")), id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('roles') ->setType('list') ->setDescription(pht('List of account roles.')), ); } public function getFieldValuesForConduit() { $roles = array(); if ($this->getIsDisabled()) { $roles[] = 'disabled'; } if ($this->getIsSystemAgent()) { $roles[] = 'bot'; } if ($this->getIsMailingList()) { $roles[] = 'list'; } if ($this->getIsAdmin()) { $roles[] = 'admin'; } if ($this->getIsEmailVerified()) { $roles[] = 'verified'; } if ($this->getIsApproved()) { $roles[] = 'approved'; } if ($this->isUserActivated()) { $roles[] = 'activated'; } return array( 'username' => $this->getUsername(), 'realName' => $this->getRealName(), 'roles' => $roles, ); } public function getConduitSearchAttachments() { return array( id(new PhabricatorPeopleAvailabilitySearchEngineAttachment()) ->setAttachmentKey('availability'), ); } /* -( User Cache )--------------------------------------------------------- */ /** * @task cache */ public function attachRawCacheData(array $data) { $this->rawCacheData = $data + $this->rawCacheData; return $this; } public function setAllowInlineCacheGeneration($allow_cache_generation) { $this->allowInlineCacheGeneration = $allow_cache_generation; return $this; } /** * @task cache */ protected function requireCacheData($key) { if (isset($this->usableCacheData[$key])) { return $this->usableCacheData[$key]; } $type = PhabricatorUserCacheType::requireCacheTypeForKey($key); if (isset($this->rawCacheData[$key])) { $raw_value = $this->rawCacheData[$key]; $usable_value = $type->getValueFromStorage($raw_value); $this->usableCacheData[$key] = $usable_value; return $usable_value; } // By default, we throw if a cache isn't available. This is consistent // with the standard `needX()` + `attachX()` + `getX()` interaction. if (!$this->allowInlineCacheGeneration) { throw new PhabricatorDataNotAttachedException($this); } $user_phid = $this->getPHID(); // Try to read the actual cache before we generate a new value. We can // end up here via Conduit, which does not use normal sessions and can // not pick up a free cache load during session identification. if ($user_phid) { $raw_data = PhabricatorUserCache::readCaches( $type, $key, array($user_phid)); if (array_key_exists($user_phid, $raw_data)) { $raw_value = $raw_data[$user_phid]; $usable_value = $type->getValueFromStorage($raw_value); $this->rawCacheData[$key] = $raw_value; $this->usableCacheData[$key] = $usable_value; return $usable_value; } } $usable_value = $type->getDefaultValue(); if ($user_phid) { $map = $type->newValueForUsers($key, array($this)); if (array_key_exists($user_phid, $map)) { $raw_value = $map[$user_phid]; $usable_value = $type->getValueFromStorage($raw_value); $this->rawCacheData[$key] = $raw_value; PhabricatorUserCache::writeCache( $type, $key, $user_phid, $raw_value); } } $this->usableCacheData[$key] = $usable_value; return $usable_value; } /** * @task cache */ public function clearCacheData($key) { unset($this->rawCacheData[$key]); unset($this->usableCacheData[$key]); return $this; } public function getCSSValue($variable_key) { $preference = PhabricatorAccessibilitySetting::SETTINGKEY; $key = $this->getUserSetting($preference); $postprocessor = CelerityPostprocessor::getPostprocessor($key); $variables = $postprocessor->getVariables(); if (!isset($variables[$variable_key])) { throw new Exception( pht( 'Unknown CSS variable "%s"!', $variable_key)); } return $variables[$variable_key]; } /* -( PhabricatorAuthPasswordHashInterface )------------------------------- */ public function newPasswordDigest( PhutilOpaqueEnvelope $envelope, PhabricatorAuthPassword $password) { // Before passwords are hashed, they are digested. The goal of digestion // is twofold: to reduce the length of very long passwords to something // reasonable; and to salt the password in case the best available hasher // does not include salt automatically. // Users may choose arbitrarily long passwords, and attackers may try to // attack the system by probing it with very long passwords. When large // inputs are passed to hashers -- which are intentionally slow -- it // can result in unacceptably long runtimes. The classic attack here is // to try to log in with a 64MB password and see if that locks up the // machine for the next century. By digesting passwords to a standard // length first, the length of the raw input does not impact the runtime // of the hashing algorithm. // Some hashers like bcrypt are self-salting, while other hashers are not. // Applying salt while digesting passwords ensures that hashes are salted // whether we ultimately select a self-salting hasher or not. // For legacy compatibility reasons, old VCS and Account password digest // algorithms are significantly more complicated than necessary to achieve // these goals. This is because they once used a different hashing and // salting process. When we upgraded to the modern modular hasher // infrastructure, we just bolted it onto the end of the existing pipelines // so that upgrading didn't break all users' credentials. // New implementations can (and, generally, should) safely select the // simple HMAC SHA256 digest at the bottom of the function, which does // everything that a digest callback should without any needless legacy // baggage on top. if ($password->getLegacyDigestFormat() == 'v1') { switch ($password->getPasswordType()) { case PhabricatorAuthPassword::PASSWORD_TYPE_VCS: // Old VCS passwords use an iterated HMAC SHA1 as a digest algorithm. // They originally used this as a hasher, but it became a digest // algorithm once hashing was upgraded to include bcrypt. $digest = $envelope->openEnvelope(); $salt = $this->getPHID(); for ($ii = 0; $ii < 1000; $ii++) { $digest = PhabricatorHash::weakDigest($digest, $salt); } return new PhutilOpaqueEnvelope($digest); case PhabricatorAuthPassword::PASSWORD_TYPE_ACCOUNT: // Account passwords previously used this weird mess of salt and did // not digest the input to a standard length. // Beyond this being a weird special case, there are two actual // problems with this, although neither are particularly severe: // First, because we do not normalize the length of passwords, this // algorithm may make us vulnerable to DOS attacks where an attacker // attempts to use a very long input to slow down hashers. // Second, because the username is part of the hash algorithm, // renaming a user breaks their password. This isn't a huge deal but // it's pretty silly. There's no security justification for this // behavior, I just didn't think about the implication when I wrote // it originally. $parts = array( $this->getUsername(), $envelope->openEnvelope(), $this->getPHID(), $password->getPasswordSalt(), ); return new PhutilOpaqueEnvelope(implode('', $parts)); } } // For passwords which do not have some crazy legacy reason to use some // other digest algorithm, HMAC SHA256 is an excellent choice. It satisfies // the digest requirements and is simple. $digest = PhabricatorHash::digestHMACSHA256( $envelope->openEnvelope(), $password->getPasswordSalt()); return new PhutilOpaqueEnvelope($digest); } public function newPasswordBlocklist( PhabricatorUser $viewer, PhabricatorAuthPasswordEngine $engine) { $list = array(); $list[] = $this->getUsername(); $list[] = $this->getRealName(); $emails = id(new PhabricatorUserEmail())->loadAllWhere( 'userPHID = %s', $this->getPHID()); foreach ($emails as $email) { $list[] = $email->getAddress(); } return $list; } } diff --git a/src/applications/people/storage/PhabricatorUserTransaction.php b/src/applications/people/storage/PhabricatorUserTransaction.php index 24edb2f5b5..81ca52a132 100644 --- a/src/applications/people/storage/PhabricatorUserTransaction.php +++ b/src/applications/people/storage/PhabricatorUserTransaction.php @@ -1,22 +1,18 @@ getUsername(); } public function generateNewValue($object, $value) { return $value; } public function applyInternalEffects($object, $value) { $object->setUsername($value); } public function applyExternalEffects($object, $value) { + $actor = $this->getActor(); $user = $object; + $old_username = $this->getOldValue(); + $new_username = $this->getNewValue(); + $this->newUserLog(PhabricatorUserLog::ACTION_CHANGE_USERNAME) - ->setOldValue($this->getOldValue()) - ->setNewValue($value) + ->setOldValue($old_username) + ->setNewValue($new_username) ->save(); // The SSH key cache currently includes usernames, so dirty it. See T12554 // for discussion. PhabricatorAuthSSHKeyQuery::deleteSSHKeyCache(); - $user->sendUsernameChangeEmail($this->getActor(), $this->getOldValue()); + id(new PhabricatorPeopleUsernameMailEngine()) + ->setSender($actor) + ->setRecipient($object) + ->setOldUsername($old_username) + ->setNewUsername($new_username) + ->sendMail(); } public function getTitle() { return pht( '%s renamed this user from %s to %s.', $this->renderAuthor(), $this->renderOldValue(), $this->renderNewValue()); } + public function getTitleForFeed() { + return pht( + '%s renamed %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + public function validateTransactions($object, array $xactions) { $actor = $this->getActor(); $errors = array(); foreach ($xactions as $xaction) { $new = $xaction->getNewValue(); $old = $xaction->getOldValue(); if ($old === $new) { continue; } if (!$actor->getIsAdmin()) { $errors[] = $this->newInvalidError( pht('You must be an administrator to rename users.')); } if (!strlen($new)) { $errors[] = $this->newRequiredError( pht('New username is required.'), $xaction); } else if (!PhabricatorUser::validateUsername($new)) { $errors[] = $this->newInvalidError( PhabricatorUser::describeValidUsername(), $xaction); } $user = id(new PhabricatorPeopleQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withUsernames(array($new)) ->executeOne(); if ($user) { $errors[] = $this->newInvalidError( pht('Another user already has that username.'), $xaction); } } return $errors; } public function getRequiredCapabilities( $object, PhabricatorApplicationTransaction $xaction) { // Unlike normal user edits, renames require admin permissions, which // is enforced by validateTransactions(). return null; } public function shouldTryMFA( $object, PhabricatorApplicationTransaction $xaction) { return true; } } diff --git a/src/applications/phame/storage/PhameBlogTransaction.php b/src/applications/phame/storage/PhameBlogTransaction.php index d3d6a79d0a..c605510d7d 100644 --- a/src/applications/phame/storage/PhameBlogTransaction.php +++ b/src/applications/phame/storage/PhameBlogTransaction.php @@ -1,50 +1,46 @@ getTransactionType()) { case PhabricatorTransactions::TYPE_SUBSCRIBERS: $tags[] = self::MAILTAG_SUBSCRIBERS; break; case PhameBlogNameTransaction::TRANSACTIONTYPE: case PhameBlogSubtitleTransaction::TRANSACTIONTYPE: case PhameBlogDescriptionTransaction::TRANSACTIONTYPE: case PhameBlogFullDomainTransaction::TRANSACTIONTYPE: case PhameBlogParentSiteTransaction::TRANSACTIONTYPE: case PhameBlogParentDomainTransaction::TRANSACTIONTYPE: case PhameBlogProfileImageTransaction::TRANSACTIONTYPE: case PhameBlogHeaderImageTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_DETAILS; break; default: $tags[] = self::MAILTAG_OTHER; break; } return $tags; } } diff --git a/src/applications/phlux/storage/PhluxTransaction.php b/src/applications/phlux/storage/PhluxTransaction.php index 1224caf201..b1624d581a 100644 --- a/src/applications/phlux/storage/PhluxTransaction.php +++ b/src/applications/phlux/storage/PhluxTransaction.php @@ -1,53 +1,49 @@ getAuthorPHID(); switch ($this->getTransactionType()) { case self::TYPE_EDIT_KEY: return pht( '%s created this variable.', $this->renderHandleLink($author_phid)); case self::TYPE_EDIT_VALUE: return pht( '%s updated this variable.', $this->renderHandleLink($author_phid)); } return parent::getTitle(); } public function hasChangeDetails() { switch ($this->getTransactionType()) { case self::TYPE_EDIT_VALUE: return true; } return parent::hasChangeDetails(); } public function renderChangeDetails(PhabricatorUser $viewer) { return $this->renderTextCorpusChangeDetails( $viewer, json_encode($this->getOldValue()), json_encode($this->getNewValue())); } } diff --git a/src/applications/phortune/controller/payment/PhortunePaymentMethodCreateController.php b/src/applications/phortune/controller/payment/PhortunePaymentMethodCreateController.php index 87bddd4d33..521508e0e8 100644 --- a/src/applications/phortune/controller/payment/PhortunePaymentMethodCreateController.php +++ b/src/applications/phortune/controller/payment/PhortunePaymentMethodCreateController.php @@ -1,280 +1,294 @@ getViewer(); $account_id = $request->getURIData('accountID'); $account = id(new PhortuneAccountQuery()) ->setViewer($viewer) ->withIDs(array($account_id)) ->executeOne(); if (!$account) { return new Aphront404Response(); } $account_id = $account->getID(); $merchant = id(new PhortuneMerchantQuery()) ->setViewer($viewer) ->withIDs(array($request->getInt('merchantID'))) ->executeOne(); if (!$merchant) { return new Aphront404Response(); } $cart_id = $request->getInt('cartID'); $subscription_id = $request->getInt('subscriptionID'); if ($cart_id) { $cancel_uri = $this->getApplicationURI("cart/{$cart_id}/checkout/"); } else if ($subscription_id) { $cancel_uri = $this->getApplicationURI( "{$account_id}/subscription/edit/{$subscription_id}/"); } else { $cancel_uri = $this->getApplicationURI($account->getID().'/'); } $providers = $this->loadCreatePaymentMethodProvidersForMerchant($merchant); if (!$providers) { throw new Exception( pht( 'There are no payment providers enabled that can add payment '. 'methods.')); } if (count($providers) == 1) { // If there's only one provider, always choose it. $provider_id = head_key($providers); } else { $provider_id = $request->getInt('providerID'); if (empty($providers[$provider_id])) { $choices = array(); foreach ($providers as $provider) { $choices[] = $this->renderSelectProvider($provider); } $content = phutil_tag( 'div', array( 'class' => 'phortune-payment-method-list', ), $choices); return $this->newDialog() ->setRenderDialogAsDiv(true) ->setTitle(pht('Add Payment Method')) ->appendParagraph(pht('Choose a payment method to add:')) ->appendChild($content) ->addCancelButton($cancel_uri); } } $provider = $providers[$provider_id]; $errors = array(); + $display_exception = null; if ($request->isFormPost() && $request->getBool('isProviderForm')) { $method = id(new PhortunePaymentMethod()) ->setAccountPHID($account->getPHID()) ->setAuthorPHID($viewer->getPHID()) ->setMerchantPHID($merchant->getPHID()) ->setProviderPHID($provider->getProviderConfig()->getPHID()) ->setStatus(PhortunePaymentMethod::STATUS_ACTIVE); if (!$errors) { $errors = $this->processClientErrors( $provider, $request->getStr('errors')); } if (!$errors) { $client_token_raw = $request->getStr('token'); $client_token = null; try { $client_token = phutil_json_decode($client_token_raw); } catch (PhutilJSONParserException $ex) { $errors[] = pht( 'There was an error decoding token information submitted by the '. 'client. Expected a JSON-encoded token dictionary, received: %s.', nonempty($client_token_raw, pht('nothing'))); } if (!$provider->validateCreatePaymentMethodToken($client_token)) { $errors[] = pht( 'There was an error with the payment token submitted by the '. 'client. Expected a valid dictionary, received: %s.', $client_token_raw); } if (!$errors) { - $errors = $provider->createPaymentMethodFromRequest( - $request, - $method, - $client_token); + try { + $provider->createPaymentMethodFromRequest( + $request, + $method, + $client_token); + } catch (PhortuneDisplayException $exception) { + $display_exception = $exception; + } catch (Exception $ex) { + $errors = array( + pht('There was an error adding this payment method:'), + $ex->getMessage(), + ); + } } } - if (!$errors) { + if (!$errors && !$display_exception) { $method->save(); // If we added this method on a cart flow, return to the cart to // check out. if ($cart_id) { $next_uri = $this->getApplicationURI( "cart/{$cart_id}/checkout/?paymentMethodID=".$method->getID()); } else if ($subscription_id) { $next_uri = new PhutilURI($cancel_uri); $next_uri->setQueryParam('added', true); } else { $account_uri = $this->getApplicationURI($account->getID().'/'); $next_uri = new PhutilURI($account_uri); $next_uri->setFragment('payment'); } return id(new AphrontRedirectResponse())->setURI($next_uri); } else { - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) + if ($display_exception) { + $dialog_body = $display_exception->getView(); + } else { + $dialog_body = id(new PHUIInfoView()) + ->setErrors($errors); + } + + return $this->newDialog() ->setTitle(pht('Error Adding Payment Method')) - ->appendChild(id(new PHUIInfoView())->setErrors($errors)) + ->appendChild($dialog_body) ->addCancelButton($request->getRequestURI()); - - return id(new AphrontDialogResponse())->setDialog($dialog); } } $form = $provider->renderCreatePaymentMethodForm($request, $errors); $form ->setUser($viewer) ->setAction($request->getRequestURI()) ->setWorkflow(true) ->addHiddenInput('providerID', $provider_id) ->addHiddenInput('cartID', $request->getInt('cartID')) ->addHiddenInput('subscriptionID', $request->getInt('subscriptionID')) ->addHiddenInput('isProviderForm', true) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Add Payment Method')) ->addCancelButton($cancel_uri)); $box = id(new PHUIObjectBoxView()) ->setHeaderText(pht('Method')) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Add Payment Method')); $crumbs->setBorder(true); $header = id(new PHUIHeaderView()) ->setHeader(pht('Add Payment Method')) ->setHeaderIcon('fa-plus-square'); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( $box, )); return $this->newPage() ->setTitle($provider->getPaymentMethodDescription()) ->setCrumbs($crumbs) ->appendChild($view); } private function renderSelectProvider( PhortunePaymentProvider $provider) { $request = $this->getRequest(); $viewer = $request->getUser(); $description = $provider->getPaymentMethodDescription(); $icon_uri = $provider->getPaymentMethodIcon(); $details = $provider->getPaymentMethodProviderDescription(); $this->requireResource('phortune-css'); $icon = id(new PHUIIconView()) ->setSpriteSheet(PHUIIconView::SPRITE_LOGIN) ->setSpriteIcon($provider->getPaymentMethodIcon()); $button = id(new PHUIButtonView()) ->setSize(PHUIButtonView::BIG) ->setColor(PHUIButtonView::GREY) ->setIcon($icon) ->setText($description) ->setSubtext($details) ->setMetadata(array('disableWorkflow' => true)); $form = id(new AphrontFormView()) ->setUser($viewer) ->setAction($request->getRequestURI()) ->addHiddenInput('providerID', $provider->getProviderConfig()->getID()) ->appendChild($button); return $form; } private function processClientErrors( PhortunePaymentProvider $provider, $client_errors_raw) { $errors = array(); $client_errors = null; try { $client_errors = phutil_json_decode($client_errors_raw); } catch (PhutilJSONParserException $ex) { $errors[] = pht( 'There was an error decoding error information submitted by the '. 'client. Expected a JSON-encoded list of error codes, received: %s.', nonempty($client_errors_raw, pht('nothing'))); } foreach (array_unique($client_errors) as $key => $client_error) { $client_errors[$key] = $provider->translateCreatePaymentMethodErrorCode( $client_error); } foreach (array_unique($client_errors) as $client_error) { switch ($client_error) { case PhortuneErrCode::ERR_CC_INVALID_NUMBER: $message = pht( 'The card number you entered is not a valid card number. Check '. 'that you entered it correctly.'); break; case PhortuneErrCode::ERR_CC_INVALID_CVC: $message = pht( 'The CVC code you entered is not a valid CVC code. Check that '. 'you entered it correctly. The CVC code is a 3-digit or 4-digit '. 'numeric code which usually appears on the back of the card.'); break; case PhortuneErrCode::ERR_CC_INVALID_EXPIRY: $message = pht( 'The card expiration date is not a valid expiration date. Check '. 'that you entered it correctly. You can not add an expired card '. 'as a payment method.'); break; default: $message = $provider->getCreatePaymentMethodErrorMessage( $client_error); if (!$message) { $message = pht( "There was an unexpected error ('%s') processing payment ". "information.", $client_error); phlog($message); } break; } $errors[$client_error] = $message; } return $errors; } } diff --git a/src/applications/phortune/exception/PhortuneDisplayException.php b/src/applications/phortune/exception/PhortuneDisplayException.php new file mode 100644 index 0000000000..7b2bbf6875 --- /dev/null +++ b/src/applications/phortune/exception/PhortuneDisplayException.php @@ -0,0 +1,15 @@ +view = $view; + return $this; + } + + public function getView() { + return $this->view; + } + +} diff --git a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php index bdaa4294b2..0463881016 100644 --- a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php +++ b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php @@ -1,386 +1,470 @@ getPublishableKey()); } public function getName() { return pht('Stripe'); } public function getConfigureName() { return pht('Add Stripe Payments Account'); } public function getConfigureDescription() { return pht( 'Allows you to accept credit or debit card payments with a '. 'stripe.com account.'); } public function getConfigureProvidesDescription() { return pht('This merchant accepts credit and debit cards via Stripe.'); } public function getPaymentMethodDescription() { return pht('Add Credit or Debit Card (US and Canada)'); } public function getPaymentMethodIcon() { return 'Stripe'; } public function getPaymentMethodProviderDescription() { return pht('Processed by Stripe'); } public function getDefaultPaymentMethodDisplayName( PhortunePaymentMethod $method) { return pht('Credit/Debit Card'); } public function getAllConfigurableProperties() { return array( self::STRIPE_PUBLISHABLE_KEY, self::STRIPE_SECRET_KEY, ); } public function getAllConfigurableSecretProperties() { return array( self::STRIPE_SECRET_KEY, ); } public function processEditForm( AphrontRequest $request, array $values) { $errors = array(); $issues = array(); if (!strlen($values[self::STRIPE_SECRET_KEY])) { $errors[] = pht('Stripe Secret Key is required.'); $issues[self::STRIPE_SECRET_KEY] = pht('Required'); } if (!strlen($values[self::STRIPE_PUBLISHABLE_KEY])) { $errors[] = pht('Stripe Publishable Key is required.'); $issues[self::STRIPE_PUBLISHABLE_KEY] = pht('Required'); } return array($errors, $issues, $values); } public function extendEditForm( AphrontRequest $request, AphrontFormView $form, array $values, array $issues) { $form ->appendChild( id(new AphrontFormTextControl()) ->setName(self::STRIPE_SECRET_KEY) ->setValue($values[self::STRIPE_SECRET_KEY]) ->setError(idx($issues, self::STRIPE_SECRET_KEY, true)) ->setLabel(pht('Stripe Secret Key'))) ->appendChild( id(new AphrontFormTextControl()) ->setName(self::STRIPE_PUBLISHABLE_KEY) ->setValue($values[self::STRIPE_PUBLISHABLE_KEY]) ->setError(idx($issues, self::STRIPE_PUBLISHABLE_KEY, true)) ->setLabel(pht('Stripe Publishable Key'))); } public function getConfigureInstructions() { return pht( "To configure Stripe, register or log in to an existing account on ". "[[https://stripe.com | stripe.com]]. Once logged in:\n\n". " - Go to {nav icon=user, name=Your Account > Account Settings ". "> API Keys}\n". " - Copy the **Secret Key** and **Publishable Key** into the fields ". "above.\n\n". "You can either use the test keys to add this provider in test mode, ". "or the live keys to accept live payments."); } public function canRunConfigurationTest() { return true; } public function runConfigurationTest() { $this->loadStripeAPILibraries(); $secret_key = $this->getSecretKey(); $account = Stripe_Account::retrieve($secret_key); } /** * @phutil-external-symbol class Stripe_Charge * @phutil-external-symbol class Stripe_CardError * @phutil-external-symbol class Stripe_Account */ protected function executeCharge( PhortunePaymentMethod $method, PhortuneCharge $charge) { $this->loadStripeAPILibraries(); $price = $charge->getAmountAsCurrency(); $secret_key = $this->getSecretKey(); $params = array( 'amount' => $price->getValueInUSDCents(), 'currency' => $price->getCurrency(), 'customer' => $method->getMetadataValue('stripe.customerID'), 'description' => $charge->getPHID(), 'capture' => true, ); $stripe_charge = Stripe_Charge::create($params, $secret_key); $id = $stripe_charge->id; if (!$id) { throw new Exception(pht('Stripe charge call did not return an ID!')); } $charge->setMetadataValue('stripe.chargeID', $id); $charge->save(); } protected function executeRefund( PhortuneCharge $charge, PhortuneCharge $refund) { $this->loadStripeAPILibraries(); $charge_id = $charge->getMetadataValue('stripe.chargeID'); if (!$charge_id) { throw new Exception( pht('Unable to refund charge; no Stripe chargeID!')); } $refund_cents = $refund ->getAmountAsCurrency() ->negate() ->getValueInUSDCents(); $secret_key = $this->getSecretKey(); $params = array( 'amount' => $refund_cents, ); $stripe_charge = Stripe_Charge::retrieve($charge_id, $secret_key); $stripe_refund = $stripe_charge->refunds->create($params); $id = $stripe_refund->id; if (!$id) { throw new Exception(pht('Stripe refund call did not return an ID!')); } $charge->setMetadataValue('stripe.refundID', $id); $charge->save(); } public function updateCharge(PhortuneCharge $charge) { $this->loadStripeAPILibraries(); $charge_id = $charge->getMetadataValue('stripe.chargeID'); if (!$charge_id) { throw new Exception( pht('Unable to update charge; no Stripe chargeID!')); } $secret_key = $this->getSecretKey(); $stripe_charge = Stripe_Charge::retrieve($charge_id, $secret_key); // TODO: Deal with disputes / chargebacks / surprising refunds. } private function getPublishableKey() { return $this ->getProviderConfig() ->getMetadataValue(self::STRIPE_PUBLISHABLE_KEY); } private function getSecretKey() { return $this ->getProviderConfig() ->getMetadataValue(self::STRIPE_SECRET_KEY); } /* -( Adding Payment Methods )--------------------------------------------- */ public function canCreatePaymentMethods() { return true; } /** * @phutil-external-symbol class Stripe_Token * @phutil-external-symbol class Stripe_Customer */ public function createPaymentMethodFromRequest( AphrontRequest $request, PhortunePaymentMethod $method, array $token) { $this->loadStripeAPILibraries(); - $errors = array(); - $secret_key = $this->getSecretKey(); $stripe_token = $token['stripeCardToken']; // First, make sure the token is valid. $info = id(new Stripe_Token())->retrieve($stripe_token, $secret_key); $account_phid = $method->getAccountPHID(); $author_phid = $method->getAuthorPHID(); $params = array( 'card' => $stripe_token, 'description' => $account_phid.':'.$author_phid, ); // Then, we need to create a Customer in order to be able to charge // the card more than once. We create one Customer for each card; // they do not map to PhortuneAccounts because we allow an account to // have more than one active card. - $customer = Stripe_Customer::create($params, $secret_key); + try { + $customer = Stripe_Customer::create($params, $secret_key); + } catch (Stripe_CardError $ex) { + $display_exception = $this->newDisplayExceptionFromCardError($ex); + if ($display_exception) { + throw $display_exception; + } + throw $ex; + } $card = $info->card; $method ->setBrand($card->brand) ->setLastFourDigits($card->last4) ->setExpires($card->exp_year, $card->exp_month) ->setMetadata( array( 'type' => 'stripe.customer', 'stripe.customerID' => $customer->id, 'stripe.cardToken' => $stripe_token, )); - - return $errors; } public function renderCreatePaymentMethodForm( AphrontRequest $request, array $errors) { $src = 'https://js.stripe.com/v2/'; $ccform = id(new PhortuneCreditCardForm()) ->setSecurityAssurance( pht('Payments are processed securely by Stripe.')) ->setUser($request->getUser()) ->setErrors($errors) ->addScript($src); CelerityAPI::getStaticResourceResponse() ->addContentSecurityPolicyURI('script-src', $src) ->addContentSecurityPolicyURI('frame-src', $src); Javelin::initBehavior( 'stripe-payment-form', array( 'stripePublishableKey' => $this->getPublishableKey(), 'formID' => $ccform->getFormID(), )); return $ccform->buildForm(); } private function getStripeShortErrorCode($error_code) { $prefix = 'cc:stripe:'; if (strncmp($error_code, $prefix, strlen($prefix))) { return null; } return substr($error_code, strlen($prefix)); } public function validateCreatePaymentMethodToken(array $token) { return isset($token['stripeCardToken']); } public function translateCreatePaymentMethodErrorCode($error_code) { $short_code = $this->getStripeShortErrorCode($error_code); if ($short_code) { static $map = array( 'error:invalid_number' => PhortuneErrCode::ERR_CC_INVALID_NUMBER, 'error:invalid_cvc' => PhortuneErrCode::ERR_CC_INVALID_CVC, 'error:invalid_expiry_month' => PhortuneErrCode::ERR_CC_INVALID_EXPIRY, 'error:invalid_expiry_year' => PhortuneErrCode::ERR_CC_INVALID_EXPIRY, ); if (isset($map[$short_code])) { return $map[$short_code]; } } return $error_code; } /** * See https://stripe.com/docs/api#errors for more information on possible * errors. */ public function getCreatePaymentMethodErrorMessage($error_code) { $short_code = $this->getStripeShortErrorCode($error_code); if (!$short_code) { return null; } switch ($short_code) { case 'error:incorrect_number': $error_key = 'number'; $message = pht('Invalid or incorrect credit card number.'); break; case 'error:incorrect_cvc': $error_key = 'cvc'; $message = pht('Card CVC is invalid or incorrect.'); break; $error_key = 'exp'; $message = pht('Card expiration date is invalid or incorrect.'); break; case 'error:invalid_expiry_month': case 'error:invalid_expiry_year': case 'error:invalid_cvc': case 'error:invalid_number': // NOTE: These should be translated into Phortune error codes earlier, // so we don't expect to receive them here. They are listed for clarity // and completeness. If we encounter one, we treat it as an unknown // error. break; case 'error:invalid_amount': case 'error:missing': case 'error:card_declined': case 'error:expired_card': case 'error:duplicate_transaction': case 'error:processing_error': default: // NOTE: These errors currently don't receive a detailed message. // NOTE: We can also end up here with "http:nnn" messages. // TODO: At least some of these should have a better message, or be // translated into common errors above. break; } return null; } private function loadStripeAPILibraries() { $root = dirname(phutil_get_library_root('phabricator')); require_once $root.'/externals/stripe-php/lib/Stripe.php'; } + + private function newDisplayExceptionFromCardError(Stripe_CardError $ex) { + $body = $ex->getJSONBody(); + if (!$body) { + return null; + } + + $map = idx($body, 'error'); + if (!$map) { + return null; + } + + $view = array(); + + $message = idx($map, 'message'); + + $view[] = id(new PHUIInfoView()) + ->setErrors(array($message)); + + $view[] = phutil_tag( + 'div', + array( + 'class' => 'mlt mlb', + ), + pht('Additional details about this error:')); + + $rows = array(); + + $rows[] = array( + pht('Error Code'), + idx($map, 'code'), + ); + + $rows[] = array( + pht('Error Type'), + idx($map, 'type'), + ); + + $param = idx($map, 'param'); + if (strlen($param)) { + $rows[] = array( + pht('Error Param'), + $param, + ); + } + + $decline_code = idx($map, 'decline_code'); + if (strlen($decline_code)) { + $rows[] = array( + pht('Decline Code'), + $decline_code, + ); + } + + $doc_url = idx($map, 'doc_url'); + if ($doc_url) { + $rows[] = array( + pht('Learn More'), + phutil_tag( + 'a', + array( + 'href' => $doc_url, + 'target' => '_blank', + ), + $doc_url), + ); + } + + $view[] = id(new AphrontTableView($rows)) + ->setColumnClasses( + array( + 'header', + 'wide', + )); + + return id(new PhortuneDisplayException(get_class($ex))) + ->setView($view); + } + + } diff --git a/src/applications/phortune/storage/PhortuneAccountTransaction.php b/src/applications/phortune/storage/PhortuneAccountTransaction.php index 6733cbe879..e333ef4a26 100644 --- a/src/applications/phortune/storage/PhortuneAccountTransaction.php +++ b/src/applications/phortune/storage/PhortuneAccountTransaction.php @@ -1,22 +1,18 @@ getTransactionType()) { case self::TYPE_CREATED: return true; } return parent::shouldHideForMail($xactions); } public function getTitle() { $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_CREATED: return pht('This order was created.'); case self::TYPE_HOLD: return pht('This order was put on hold until payment clears.'); case self::TYPE_REVIEW: return pht( 'This order was flagged for manual processing by the merchant.'); case self::TYPE_CANCEL: return pht('This order was cancelled.'); case self::TYPE_REFUND: return pht('This order was refunded.'); case self::TYPE_PURCHASED: return pht('Payment for this order was completed.'); case self::TYPE_INVOICED: return pht('This order was invoiced.'); } return parent::getTitle(); } public function getTitleForMail() { switch ($this->getTransactionType()) { case self::TYPE_INVOICED: return pht('You have a new invoice due.'); } return parent::getTitleForMail(); } public function getActionName() { switch ($this->getTransactionType()) { case self::TYPE_CREATED: return pht('Created'); case self::TYPE_HOLD: return pht('Hold'); case self::TYPE_REVIEW: return pht('Review'); case self::TYPE_CANCEL: return pht('Cancelled'); case self::TYPE_REFUND: return pht('Refunded'); case self::TYPE_PURCHASED: return pht('Complete'); case self::TYPE_INVOICED: return pht('New Invoice'); } return parent::getActionName(); } } diff --git a/src/applications/phortune/storage/PhortuneMerchantTransaction.php b/src/applications/phortune/storage/PhortuneMerchantTransaction.php index 3befb12212..976259c534 100644 --- a/src/applications/phortune/storage/PhortuneMerchantTransaction.php +++ b/src/applications/phortune/storage/PhortuneMerchantTransaction.php @@ -1,22 +1,18 @@ getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); switch ($this->getTransactionType()) { case self::TYPE_CREATE: return pht( '%s created this payment provider.', $this->renderHandleLink($author_phid)); case self::TYPE_ENABLE: if ($new) { return pht( '%s enabled this payment provider.', $this->renderHandleLink($author_phid)); } else { return pht( '%s disabled this payment provider.', $this->renderHandleLink($author_phid)); } case self::TYPE_PROPERTY: // TODO: Allow providers to improve this. return pht( '%s edited a property of this payment provider.', $this->renderHandleLink($author_phid)); break; } return parent::getTitle(); } } diff --git a/src/applications/policy/filter/PhabricatorPolicyFilter.php b/src/applications/policy/filter/PhabricatorPolicyFilter.php index fb03936ec2..a5c9f356f4 100644 --- a/src/applications/policy/filter/PhabricatorPolicyFilter.php +++ b/src/applications/policy/filter/PhabricatorPolicyFilter.php @@ -1,973 +1,974 @@ setViewer($user) ->requireCapabilities(array($capability)) ->raisePolicyExceptions(true) ->apply(array($object)); } /** * Perform a capability check, acting as though an object had a specific * policy. This is primarily used to check if a policy is valid (for example, * to prevent users from editing away their ability to edit an object). * * Specifically, a check like this: * * PhabricatorPolicyFilter::requireCapabilityWithForcedPolicy( * $viewer, * $object, * PhabricatorPolicyCapability::CAN_EDIT, * $potential_new_policy); * * ...will throw a @{class:PhabricatorPolicyException} if the new policy would * remove the user's ability to edit the object. * * @param PhabricatorUser The viewer to perform a policy check for. * @param PhabricatorPolicyInterface The object to perform a policy check on. * @param string Capability to test. * @param string Perform the test as though the object has this * policy instead of the policy it actually has. * @return void */ public static function requireCapabilityWithForcedPolicy( PhabricatorUser $viewer, PhabricatorPolicyInterface $object, $capability, $forced_policy) { id(new PhabricatorPolicyFilter()) ->setViewer($viewer) ->requireCapabilities(array($capability)) ->raisePolicyExceptions(true) ->forcePolicy($forced_policy) ->apply(array($object)); } public static function hasCapability( PhabricatorUser $user, PhabricatorPolicyInterface $object, $capability) { $filter = new PhabricatorPolicyFilter(); $filter->setViewer($user); $filter->requireCapabilities(array($capability)); $result = $filter->apply(array($object)); return (count($result) == 1); } public static function canInteract( PhabricatorUser $user, PhabricatorPolicyInterface $object) { $capabilities = $object->getCapabilities(); $capabilities = array_fuse($capabilities); $can_interact = PhabricatorPolicyCapability::CAN_INTERACT; $can_view = PhabricatorPolicyCapability::CAN_VIEW; $require = array(); // If the object doesn't support a separate "Interact" capability, we // only use the "View" capability: for most objects, you can interact // with them if you can see them. $require[] = $can_view; if (isset($capabilities[$can_interact])) { $require[] = $can_interact; } foreach ($require as $capability) { if (!self::hasCapability($user, $object, $capability)) { return false; } } return true; } public function setViewer(PhabricatorUser $user) { $this->viewer = $user; return $this; } public function requireCapabilities(array $capabilities) { $this->capabilities = $capabilities; return $this; } public function raisePolicyExceptions($raise) { $this->raisePolicyExceptions = $raise; return $this; } public function forcePolicy($forced_policy) { $this->forcedPolicy = $forced_policy; return $this; } public function apply(array $objects) { assert_instances_of($objects, 'PhabricatorPolicyInterface'); $viewer = $this->viewer; $capabilities = $this->capabilities; if (!$viewer || !$capabilities) { throw new PhutilInvalidStateException('setViewer', 'requireCapabilities'); } // If the viewer is omnipotent, short circuit all the checks and just // return the input unmodified. This is an optimization; we know the // result already. if ($viewer->isOmnipotent()) { return $objects; } // Before doing any actual object checks, make sure the viewer can see // the applications that these objects belong to. This is normally enforced // in the Query layer before we reach object filtering, but execution // sometimes reaches policy filtering without running application checks. $objects = $this->applyApplicationChecks($objects); $filtered = array(); $viewer_phid = $viewer->getPHID(); if (empty($this->userProjects[$viewer_phid])) { $this->userProjects[$viewer_phid] = array(); } $need_projects = array(); $need_policies = array(); $need_objpolicies = array(); foreach ($objects as $key => $object) { $object_capabilities = $object->getCapabilities(); foreach ($capabilities as $capability) { if (!in_array($capability, $object_capabilities)) { throw new Exception( pht( - "Testing for capability '%s' on an object which does ". - "not have that capability!", - $capability)); + 'Testing for capability "%s" on an object ("%s") which does '. + 'not support that capability.', + $capability, + get_class($object))); } $policy = $this->getObjectPolicy($object, $capability); if (PhabricatorPolicyQuery::isObjectPolicy($policy)) { $need_objpolicies[$policy][] = $object; continue; } $type = phid_get_type($policy); if ($type == PhabricatorProjectProjectPHIDType::TYPECONST) { $need_projects[$policy] = $policy; continue; } if ($type == PhabricatorPolicyPHIDTypePolicy::TYPECONST) { $need_policies[$policy][] = $object; continue; } } } if ($need_objpolicies) { $this->loadObjectPolicies($need_objpolicies); } if ($need_policies) { $this->loadCustomPolicies($need_policies); } // If we need projects, check if any of the projects we need are also the // objects we're filtering. Because of how project rules work, this is a // common case. if ($need_projects) { foreach ($objects as $object) { if ($object instanceof PhabricatorProject) { $project_phid = $object->getPHID(); if (isset($need_projects[$project_phid])) { $is_member = $object->isUserMember($viewer_phid); $this->userProjects[$viewer_phid][$project_phid] = $is_member; unset($need_projects[$project_phid]); } } } } if ($need_projects) { $need_projects = array_unique($need_projects); // NOTE: We're using the omnipotent user here to avoid a recursive // descent into madness. We don't actually need to know if the user can // see these projects or not, since: the check is "user is member of // project", not "user can see project"; and membership implies // visibility anyway. Without this, we may load other projects and // re-enter the policy filter and generally create a huge mess. $projects = id(new PhabricatorProjectQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withMemberPHIDs(array($viewer->getPHID())) ->withPHIDs($need_projects) ->execute(); foreach ($projects as $project) { $this->userProjects[$viewer_phid][$project->getPHID()] = true; } } foreach ($objects as $key => $object) { foreach ($capabilities as $capability) { if (!$this->checkCapability($object, $capability)) { // If we're missing any capability, move on to the next object. continue 2; } } // If we make it here, we have all of the required capabilities. $filtered[$key] = $object; } // If we survived the primary checks, apply extended checks to objects // with extended policies. $results = array(); $extended = array(); foreach ($filtered as $key => $object) { if ($object instanceof PhabricatorExtendedPolicyInterface) { $extended[$key] = $object; } else { $results[$key] = $object; } } if ($extended) { $results += $this->applyExtendedPolicyChecks($extended); // Put results back in the original order. $results = array_select_keys($results, array_keys($filtered)); } return $results; } private function applyExtendedPolicyChecks(array $extended_objects) { $viewer = $this->viewer; $filter_capabilities = $this->capabilities; // Iterate over the objects we need to filter and pull all the nonempty // policies into a flat, structured list. $all_structs = array(); foreach ($extended_objects as $key => $extended_object) { foreach ($filter_capabilities as $extended_capability) { $extended_policies = $extended_object->getExtendedPolicy( $extended_capability, $viewer); if (!$extended_policies) { continue; } foreach ($extended_policies as $extended_policy) { list($object, $capabilities) = $extended_policy; // Build a description of the capabilities we need to check. This // will be something like `"view"`, or `"edit view"`, or possibly // a longer string with custom capabilities. Later, group the objects // up into groups which need the same capabilities tested. $capabilities = (array)$capabilities; $capabilities = array_fuse($capabilities); ksort($capabilities); $group = implode(' ', $capabilities); $struct = array( 'key' => $key, 'for' => $extended_capability, 'object' => $object, 'capabilities' => $capabilities, 'group' => $group, ); $all_structs[] = $struct; } } } // Extract any bare PHIDs from the structs; we need to load these objects. // These are objects which are required in order to perform an extended // policy check but which the original viewer did not have permission to // see (they presumably had other permissions which let them load the // object in the first place). $all_phids = array(); foreach ($all_structs as $idx => $struct) { $object = $struct['object']; if (is_string($object)) { $all_phids[$object] = $object; } } // If we have some bare PHIDs, we need to load the corresponding objects. if ($all_phids) { // We can pull these with the omnipotent user because we're immediately // filtering them. $ref_objects = id(new PhabricatorObjectQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs($all_phids) ->execute(); $ref_objects = mpull($ref_objects, null, 'getPHID'); } else { $ref_objects = array(); } // Group the list of checks by the capabilities we need to check. $groups = igroup($all_structs, 'group'); foreach ($groups as $structs) { $head = head($structs); // All of the items in each group are checking for the same capabilities. $capabilities = $head['capabilities']; $key_map = array(); $objects_in = array(); foreach ($structs as $struct) { $extended_key = $struct['key']; if (empty($extended_objects[$extended_key])) { // If this object has already been rejected by an earlier filtering // pass, we don't need to do any tests on it. continue; } $object = $struct['object']; if (is_string($object)) { // This is really a PHID, so look it up. $object_phid = $object; if (empty($ref_objects[$object_phid])) { // We weren't able to load the corresponding object, so just // reject this result outright. $reject = $extended_objects[$extended_key]; unset($extended_objects[$extended_key]); // TODO: This could be friendlier. $this->rejectObject($reject, false, ''); continue; } $object = $ref_objects[$object_phid]; } $phid = $object->getPHID(); $key_map[$phid][] = $extended_key; $objects_in[$phid] = $object; } if ($objects_in) { $objects_out = $this->executeExtendedPolicyChecks( $viewer, $capabilities, $objects_in, $key_map); $objects_out = mpull($objects_out, null, 'getPHID'); } else { $objects_out = array(); } // If any objects were removed by filtering, we're going to reject all // of the original objects which needed them. foreach ($objects_in as $phid => $object_in) { if (isset($objects_out[$phid])) { // This object survived filtering, so we don't need to throw any // results away. continue; } foreach ($key_map[$phid] as $extended_key) { if (empty($extended_objects[$extended_key])) { // We've already rejected this object, so we don't need to reject // it again. continue; } $reject = $extended_objects[$extended_key]; unset($extended_objects[$extended_key]); // It's possible that we're rejecting this object for multiple // capability/policy failures, but just pick the first one to show // to the user. $first_capability = head($capabilities); $first_policy = $object_in->getPolicy($first_capability); $this->rejectObject($reject, $first_policy, $first_capability); } } } return $extended_objects; } private function executeExtendedPolicyChecks( PhabricatorUser $viewer, array $capabilities, array $objects, array $key_map) { // Do crude cycle detection by seeing if we have a huge stack depth. // Although more sophisticated cycle detection is possible in theory, // it is difficult with hierarchical objects like subprojects. Many other // checks make it difficult to create cycles normally, so just do a // simple check here to limit damage. static $depth; $depth++; if ($depth > 32) { foreach ($objects as $key => $object) { $this->rejectObject($objects[$key], false, ''); unset($objects[$key]); continue; } } if (!$objects) { return array(); } $caught = null; try { $result = id(new PhabricatorPolicyFilter()) ->setViewer($viewer) ->requireCapabilities($capabilities) ->apply($objects); } catch (Exception $ex) { $caught = $ex; } $depth--; if ($caught) { throw $caught; } return $result; } private function checkCapability( PhabricatorPolicyInterface $object, $capability) { $policy = $this->getObjectPolicy($object, $capability); if (!$policy) { // TODO: Formalize this somehow? $policy = PhabricatorPolicies::POLICY_USER; } if ($policy == PhabricatorPolicies::POLICY_PUBLIC) { // If the object is set to "public" but that policy is disabled for this // install, restrict the policy to "user". if (!PhabricatorEnv::getEnvConfig('policy.allow-public')) { $policy = PhabricatorPolicies::POLICY_USER; } // If the object is set to "public" but the capability is not a public // capability, restrict the policy to "user". $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability); if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) { $policy = PhabricatorPolicies::POLICY_USER; } } $viewer = $this->viewer; if ($viewer->isOmnipotent()) { return true; } if ($object instanceof PhabricatorSpacesInterface) { $space_phid = $object->getSpacePHID(); if (!$this->canViewerSeeObjectsInSpace($viewer, $space_phid)) { $this->rejectObjectFromSpace($object, $space_phid); return false; } } if ($object->hasAutomaticCapability($capability, $viewer)) { return true; } switch ($policy) { case PhabricatorPolicies::POLICY_PUBLIC: return true; case PhabricatorPolicies::POLICY_USER: if ($viewer->getPHID()) { return true; } else { $this->rejectObject($object, $policy, $capability); } break; case PhabricatorPolicies::POLICY_ADMIN: if ($viewer->getIsAdmin()) { return true; } else { $this->rejectObject($object, $policy, $capability); } break; case PhabricatorPolicies::POLICY_NOONE: $this->rejectObject($object, $policy, $capability); break; default: if (PhabricatorPolicyQuery::isObjectPolicy($policy)) { if ($this->checkObjectPolicy($policy, $object)) { return true; } else { $this->rejectObject($object, $policy, $capability); break; } } $type = phid_get_type($policy); if ($type == PhabricatorProjectProjectPHIDType::TYPECONST) { if (!empty($this->userProjects[$viewer->getPHID()][$policy])) { return true; } else { $this->rejectObject($object, $policy, $capability); } } else if ($type == PhabricatorPeopleUserPHIDType::TYPECONST) { if ($viewer->getPHID() == $policy) { return true; } else { $this->rejectObject($object, $policy, $capability); } } else if ($type == PhabricatorPolicyPHIDTypePolicy::TYPECONST) { if ($this->checkCustomPolicy($policy, $object)) { return true; } else { $this->rejectObject($object, $policy, $capability); } } else { // Reject objects with unknown policies. $this->rejectObject($object, false, $capability); } } return false; } public function rejectObject( PhabricatorPolicyInterface $object, $policy, $capability) { if (!$this->raisePolicyExceptions) { return; } if ($this->viewer->isOmnipotent()) { // Never raise policy exceptions for the omnipotent viewer. Although we // will never normally issue a policy rejection for the omnipotent // viewer, we can end up here when queries blanket reject objects that // have failed to load, without distinguishing between nonexistent and // nonvisible objects. return; } $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability); $rejection = null; if ($capobj) { $rejection = $capobj->describeCapabilityRejection(); $capability_name = $capobj->getCapabilityName(); } else { $capability_name = $capability; } if (!$rejection) { // We couldn't find the capability object, or it doesn't provide a // tailored rejection string. $rejection = pht( 'You do not have the required capability ("%s") to do whatever you '. 'are trying to do.', $capability); } $more = PhabricatorPolicy::getPolicyExplanation($this->viewer, $policy); $more = (array)$more; $more = array_filter($more); $exceptions = PhabricatorPolicy::getSpecialRules( $object, $this->viewer, $capability, true); $details = array_filter(array_merge($more, $exceptions)); $access_denied = $this->renderAccessDenied($object); $full_message = pht( '[%s] (%s) %s // %s', $access_denied, $capability_name, $rejection, implode(' ', $details)); $exception = id(new PhabricatorPolicyException($full_message)) ->setTitle($access_denied) ->setObjectPHID($object->getPHID()) ->setRejection($rejection) ->setCapability($capability) ->setCapabilityName($capability_name) ->setMoreInfo($details); throw $exception; } private function loadObjectPolicies(array $map) { $viewer = $this->viewer; $viewer_phid = $viewer->getPHID(); $rules = PhabricatorPolicyQuery::getObjectPolicyRules(null); // Make sure we have clean, empty policy rule objects. foreach ($rules as $key => $rule) { $rules[$key] = clone $rule; } $results = array(); foreach ($map as $key => $object_list) { $rule = idx($rules, $key); if (!$rule) { continue; } foreach ($object_list as $object_key => $object) { if (!$rule->canApplyToObject($object)) { unset($object_list[$object_key]); } } $rule->willApplyRules($viewer, array(), $object_list); $results[$key] = $rule; } $this->objectPolicies[$viewer_phid] = $results; } private function loadCustomPolicies(array $map) { $viewer = $this->viewer; $viewer_phid = $viewer->getPHID(); $custom_policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) ->withPHIDs(array_keys($map)) ->execute(); $custom_policies = mpull($custom_policies, null, 'getPHID'); $classes = array(); $values = array(); $objects = array(); foreach ($custom_policies as $policy_phid => $policy) { foreach ($policy->getCustomRuleClasses() as $class) { $classes[$class] = $class; $values[$class][] = $policy->getCustomRuleValues($class); foreach (idx($map, $policy_phid, array()) as $object) { $objects[$class][] = $object; } } } foreach ($classes as $class => $ignored) { $rule_object = newv($class, array()); // Filter out any objects which the rule can't apply to. $target_objects = idx($objects, $class, array()); foreach ($target_objects as $key => $target_object) { if (!$rule_object->canApplyToObject($target_object)) { unset($target_objects[$key]); } } $rule_object->willApplyRules( $viewer, array_mergev($values[$class]), $target_objects); $classes[$class] = $rule_object; } foreach ($custom_policies as $policy) { $policy->attachRuleObjects($classes); } if (empty($this->customPolicies[$viewer_phid])) { $this->customPolicies[$viewer_phid] = array(); } $this->customPolicies[$viewer->getPHID()] += $custom_policies; } private function checkObjectPolicy( $policy_phid, PhabricatorPolicyInterface $object) { $viewer = $this->viewer; $viewer_phid = $viewer->getPHID(); $rule = idx($this->objectPolicies[$viewer_phid], $policy_phid); if (!$rule) { return false; } if (!$rule->canApplyToObject($object)) { return false; } return $rule->applyRule($viewer, null, $object); } private function checkCustomPolicy( $policy_phid, PhabricatorPolicyInterface $object) { $viewer = $this->viewer; $viewer_phid = $viewer->getPHID(); $policy = idx($this->customPolicies[$viewer_phid], $policy_phid); if (!$policy) { // Reject, this policy is bogus. return false; } $objects = $policy->getRuleObjects(); $action = null; foreach ($policy->getRules() as $rule) { if (!is_array($rule)) { // Reject, this policy rule is invalid. return false; } $rule_object = idx($objects, idx($rule, 'rule')); if (!$rule_object) { // Reject, this policy has a bogus rule. return false; } if (!$rule_object->canApplyToObject($object)) { // Reject, this policy rule can't be applied to the given object. return false; } // If the user matches this rule, use this action. if ($rule_object->applyRule($viewer, idx($rule, 'value'), $object)) { $action = idx($rule, 'action'); break; } } if ($action === null) { $action = $policy->getDefaultAction(); } if ($action === PhabricatorPolicy::ACTION_ALLOW) { return true; } return false; } private function getObjectPolicy( PhabricatorPolicyInterface $object, $capability) { if ($this->forcedPolicy) { return $this->forcedPolicy; } else { return $object->getPolicy($capability); } } private function renderAccessDenied(PhabricatorPolicyInterface $object) { // NOTE: Not every type of policy object has a real PHID; just load an // empty handle if a real PHID isn't available. $phid = nonempty($object->getPHID(), PhabricatorPHIDConstants::PHID_VOID); $handle = id(new PhabricatorHandleQuery()) ->setViewer($this->viewer) ->withPHIDs(array($phid)) ->executeOne(); $object_name = $handle->getObjectName(); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); if ($is_serious) { $access_denied = pht( 'Access Denied: %s', $object_name); } else { $access_denied = pht( 'You Shall Not Pass: %s', $object_name); } return $access_denied; } private function canViewerSeeObjectsInSpace( PhabricatorUser $viewer, $space_phid) { $spaces = PhabricatorSpacesNamespaceQuery::getAllSpaces(); // If there are no spaces, everything exists in an implicit default space // with no policy controls. This is the default state. if (!$spaces) { if ($space_phid !== null) { return false; } else { return true; } } if ($space_phid === null) { $space = PhabricatorSpacesNamespaceQuery::getDefaultSpace(); } else { $space = idx($spaces, $space_phid); } if (!$space) { return false; } // This may be more involved later, but for now being able to see the // space is equivalent to being able to see everything in it. return self::hasCapability( $viewer, $space, PhabricatorPolicyCapability::CAN_VIEW); } private function rejectObjectFromSpace( PhabricatorPolicyInterface $object, $space_phid) { if (!$this->raisePolicyExceptions) { return; } if ($this->viewer->isOmnipotent()) { return; } $access_denied = $this->renderAccessDenied($object); $rejection = pht( 'This object is in a space you do not have permission to access.'); $full_message = pht('[%s] %s', $access_denied, $rejection); $exception = id(new PhabricatorPolicyException($full_message)) ->setTitle($access_denied) ->setObjectPHID($object->getPHID()) ->setRejection($rejection) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW); throw $exception; } private function applyApplicationChecks(array $objects) { $viewer = $this->viewer; foreach ($objects as $key => $object) { // Don't filter handles: users are allowed to see handles from an // application they can't see even if they can not see objects from // that application. Note that the application policies still apply to // the underlying object, so these will be "Restricted Object" handles. // If we don't let these through, PhabricatorHandleQuery will completely // fail to load results for PHIDs that are part of applications which // the viewer can not see, but a fundamental property of handles is that // we always load something and they can safely be assumed to load. if ($object instanceof PhabricatorObjectHandle) { continue; } $phid = $object->getPHID(); if (!$phid) { continue; } $application_class = $this->getApplicationForPHID($phid); if ($application_class === null) { continue; } $can_see = PhabricatorApplication::isClassInstalledForViewer( $application_class, $viewer); if ($can_see) { continue; } unset($objects[$key]); $application = newv($application_class, array()); $this->rejectObject( $application, $application->getPolicy(PhabricatorPolicyCapability::CAN_VIEW), PhabricatorPolicyCapability::CAN_VIEW); } return $objects; } private function getApplicationForPHID($phid) { static $class_map = array(); $phid_type = phid_get_type($phid); if (!isset($class_map[$phid_type])) { $type_objects = PhabricatorPHIDType::getTypes(array($phid_type)); $type_object = idx($type_objects, $phid_type); if (!$type_object) { $class = false; } else { $class = $type_object->getPHIDTypeApplicationClass(); } $class_map[$phid_type] = $class; } $class = $class_map[$phid_type]; if ($class === false) { return null; } return $class; } } diff --git a/src/applications/project/storage/PhabricatorProjectTransaction.php b/src/applications/project/storage/PhabricatorProjectTransaction.php index a8b2bb0d4a..158c2480c0 100644 --- a/src/applications/project/storage/PhabricatorProjectTransaction.php +++ b/src/applications/project/storage/PhabricatorProjectTransaction.php @@ -1,168 +1,164 @@ getOldValue(); $new = $this->getNewValue(); $req_phids = array(); switch ($this->getTransactionType()) { case self::TYPE_MEMBERS: $add = array_diff($new, $old); $rem = array_diff($old, $new); $req_phids = array_merge($add, $rem); break; } return array_merge($req_phids, parent::getRequiredHandlePHIDs()); } public function shouldHide() { switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_EDGE: $edge_type = $this->getMetadataValue('edge:type'); switch ($edge_type) { case PhabricatorProjectSilencedEdgeType::EDGECONST: return true; default: break; } } return parent::shouldHide(); } public function shouldHideForMail(array $xactions) { switch ($this->getTransactionType()) { case PhabricatorProjectWorkboardTransaction::TRANSACTIONTYPE: case PhabricatorProjectSortTransaction::TRANSACTIONTYPE: case PhabricatorProjectFilterTransaction::TRANSACTIONTYPE: case PhabricatorProjectWorkboardBackgroundTransaction::TRANSACTIONTYPE: return true; } return parent::shouldHideForMail($xactions); } public function getIcon() { switch ($this->getTransactionType()) { case self::TYPE_MEMBERS: return 'fa-user'; } return parent::getIcon(); } public function getTitle() { $old = $this->getOldValue(); $new = $this->getNewValue(); $author_phid = $this->getAuthorPHID(); $author_handle = $this->renderHandleLink($author_phid); switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: return pht( '%s created this project.', $this->renderHandleLink($author_phid)); case self::TYPE_MEMBERS: $add = array_diff($new, $old); $rem = array_diff($old, $new); if ($add && $rem) { return pht( '%s changed project member(s), added %d: %s; removed %d: %s.', $author_handle, count($add), $this->renderHandleList($add), count($rem), $this->renderHandleList($rem)); } else if ($add) { if (count($add) == 1 && (head($add) == $this->getAuthorPHID())) { return pht( '%s joined this project.', $author_handle); } else { return pht( '%s added %d project member(s): %s.', $author_handle, count($add), $this->renderHandleList($add)); } } else if ($rem) { if (count($rem) == 1 && (head($rem) == $this->getAuthorPHID())) { return pht( '%s left this project.', $author_handle); } else { return pht( '%s removed %d project member(s): %s.', $author_handle, count($rem), $this->renderHandleList($rem)); } } break; } return parent::getTitle(); } public function getMailTags() { $tags = array(); switch ($this->getTransactionType()) { case PhabricatorProjectNameTransaction::TRANSACTIONTYPE: case PhabricatorProjectSlugsTransaction::TRANSACTIONTYPE: case PhabricatorProjectImageTransaction::TRANSACTIONTYPE: case PhabricatorProjectIconTransaction::TRANSACTIONTYPE: case PhabricatorProjectColorTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_METADATA; break; case PhabricatorTransactions::TYPE_EDGE: $type = $this->getMetadata('edge:type'); $type = head($type); $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST; $type_watcher = PhabricatorObjectHasWatcherEdgeType::EDGECONST; if ($type == $type_member) { $tags[] = self::MAILTAG_MEMBERS; } else if ($type == $type_watcher) { $tags[] = self::MAILTAG_WATCHERS; } else { $tags[] = self::MAILTAG_OTHER; } break; case PhabricatorProjectStatusTransaction::TRANSACTIONTYPE: case PhabricatorProjectLockTransaction::TRANSACTIONTYPE: default: $tags[] = self::MAILTAG_OTHER; break; } return $tags; } } diff --git a/src/applications/repository/storage/PhabricatorRepositoryTransaction.php b/src/applications/repository/storage/PhabricatorRepositoryTransaction.php index 85c354ba67..8729e462a3 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryTransaction.php +++ b/src/applications/repository/storage/PhabricatorRepositoryTransaction.php @@ -1,22 +1,18 @@ shouldSkipImportStep()) { $this->triggerOwnerAudits($repository, $commit); $commit->writeImportStatusFlag($this->getImportStepFlag()); } if ($this->shouldQueueFollowupTasks()) { $this->queueTask( 'PhabricatorRepositoryCommitHeraldWorker', array( 'commitID' => $commit->getID(), )); } } private function triggerOwnerAudits( PhabricatorRepository $repository, PhabricatorRepositoryCommit $commit) { $viewer = PhabricatorUser::getOmnipotentUser(); if (!$repository->shouldPublish()) { return; } $affected_paths = PhabricatorOwnerPathQuery::loadAffectedPaths( $repository, $commit, PhabricatorUser::getOmnipotentUser()); $affected_packages = PhabricatorOwnersPackage::loadAffectedPackages( $repository, $affected_paths); $commit->writeOwnersEdges(mpull($affected_packages, 'getPHID')); if (!$affected_packages) { return; } $commit = id(new DiffusionCommitQuery()) ->setViewer($viewer) ->withPHIDs(array($commit->getPHID())) ->needCommitData(true) ->needAuditRequests(true) ->executeOne(); if (!$commit) { return; } $data = $commit->getCommitData(); $author_phid = $data->getCommitDetail('authorPHID'); $revision_id = $data->getCommitDetail('differential.revisionID'); if ($revision_id) { $revision = id(new DifferentialRevisionQuery()) ->setViewer($viewer) ->withIDs(array($revision_id)) ->needReviewers(true) ->executeOne(); } else { $revision = null; } $requests = $commit->getAudits(); $requests = mpull($requests, null, 'getAuditorPHID'); $auditor_phids = array(); foreach ($affected_packages as $package) { $request = idx($requests, $package->getPHID()); if ($request) { // Don't update request if it exists already. continue; } $should_audit = $this->shouldTriggerAudit( $commit, $package, $author_phid, $revision); if (!$should_audit) { continue; } $auditor_phids[] = $package->getPHID(); } // If none of the packages are triggering audits, we're all done. if (!$auditor_phids) { return; } $audit_type = DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE; $owners_phid = id(new PhabricatorOwnersApplication()) ->getPHID(); $content_source = $this->newContentSource(); $xactions = array(); $xactions[] = $commit->getApplicationTransactionTemplate() ->setTransactionType($audit_type) ->setNewValue( array( '+' => array_fuse($auditor_phids), )); $editor = $commit->getApplicationTransactionEditor() ->setActor($viewer) ->setActingAsPHID($owners_phid) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true) ->setContentSource($content_source); $editor->applyTransactions($commit, $xactions); } private function shouldTriggerAudit( PhabricatorRepositoryCommit $commit, PhabricatorOwnersPackage $package, $author_phid, $revision) { - // Don't trigger an audit if auditing isn't enabled for the package. - if (!$package->getAuditingEnabled()) { - return false; + $audit_uninvolved = false; + $audit_unreviewed = false; + + $rule = $package->newAuditingRule(); + switch ($rule->getKey()) { + case PhabricatorOwnersAuditRule::AUDITING_NONE: + return false; + case PhabricatorOwnersAuditRule::AUDITING_ALL: + return true; + case PhabricatorOwnersAuditRule::AUDITING_NO_OWNER: + $audit_uninvolved = true; + break; + case PhabricatorOwnersAuditRule::AUDITING_UNREVIEWED: + $audit_unreviewed = true; + break; + case PhabricatorOwnersAuditRule::AUDITING_NO_OWNER_AND_UNREVIEWED: + $audit_uninvolved = true; + $audit_unreviewed = true; + break; } - // Trigger an audit if we don't recognize the commit's author. - if (!$author_phid) { - return true; + // If auditing is configured to trigger on unreviewed changes, check if + // the revision was "Accepted" when it landed. If not, trigger an audit. + if ($audit_unreviewed) { + $commit_unreviewed = true; + if ($revision) { + $was_accepted = DifferentialRevision::PROPERTY_CLOSED_FROM_ACCEPTED; + if ($revision->isPublished()) { + if ($revision->getProperty($was_accepted)) { + $commit_unreviewed = false; + } + } + } + + if ($commit_unreviewed) { + return true; + } + } + + // If auditing is configured to trigger on changes with no involved owner, + // check for an owner. If we don't find one, trigger an audit. + if ($audit_uninvolved) { + $commit_uninvolved = $this->isOwnerInvolved( + $commit, + $package, + $author_phid, + $revision); + if ($commit_uninvolved) { + return true; + } } + // We can't find any reason to trigger an audit for this commit. + return false; + } + + private function isOwnerInvolved( + PhabricatorRepositoryCommit $commit, + PhabricatorOwnersPackage $package, + $author_phid, + $revision) { + $owner_phids = PhabricatorOwnersOwner::loadAffiliatedUserPHIDs( array( $package->getID(), )); $owner_phids = array_fuse($owner_phids); - // Don't trigger an audit if the author is a package owner. - if (isset($owner_phids[$author_phid])) { - return false; + // For the purposes of deciding whether the owners were involved in the + // revision or not, consider a review by the package itself to count as + // involvement. This can happen when human reviewers force-accept on + // behalf of packages they don't own but have authority over. + $owner_phids[$package->getPHID()] = $package->getPHID(); + + // If the commit author is identifiable and a package owner, they're + // involved. + if ($author_phid) { + if (isset($owner_phids[$author_phid])) { + return true; + } } - // Trigger an audit of there is no corresponding revision. + // Otherwise, we need to find an owner as a reviewer. + + // If we don't have a revision, this is hopeless: no owners are involved. if (!$revision) { return true; } $accepted_statuses = array( DifferentialReviewerStatus::STATUS_ACCEPTED, DifferentialReviewerStatus::STATUS_ACCEPTED_OLDER, ); $accepted_statuses = array_fuse($accepted_statuses); $found_accept = false; foreach ($revision->getReviewers() as $reviewer) { $reviewer_phid = $reviewer->getReviewerPHID(); - // If this reviewer isn't a package owner, just ignore them. + // If this reviewer isn't a package owner or the package itself, + // just ignore them. if (empty($owner_phids[$reviewer_phid])) { continue; } - // If this reviewer accepted the revision and owns the package, we're - // all clear and do not need to trigger an audit. + // If this reviewer accepted the revision and owns the package (or is + // the package), we've found an involved owner. if (isset($accepted_statuses[$reviewer->getReviewerStatus()])) { $found_accept = true; break; } } - // Don't trigger an audit if a package owner already reviewed the - // revision. if ($found_accept) { - return false; + return true; } - return true; + return false; } } diff --git a/src/applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php b/src/applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php index ab4da88420..126f298f1f 100644 --- a/src/applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php +++ b/src/applications/search/engineextension/PhabricatorFulltextIndexEngineExtension.php @@ -1,116 +1,112 @@ getConfigurationVersion(); if ($object instanceof PhabricatorApplicationTransactionInterface) { // If this is a normal object with transactions, we only need to // reindex it if there are new transactions (or comment edits). $version[] = $this->getTransactionVersion($object); $version[] = $this->getCommentVersion($object); } if (!$version) { return null; } return implode(':', $version); } public function shouldIndexObject($object) { return ($object instanceof PhabricatorFulltextInterface); } public function indexObject( PhabricatorIndexEngine $engine, $object) { $engine = $object->newFulltextEngine(); if (!$engine) { return; } $engine->setObject($object); $engine->buildFulltextIndexes(); } private function getTransactionVersion($object) { $xaction = $object->getApplicationTransactionTemplate(); $xaction_row = queryfx_one( $xaction->establishConnection('r'), 'SELECT id FROM %T WHERE objectPHID = %s ORDER BY id DESC LIMIT 1', $xaction->getTableName(), $object->getPHID()); if (!$xaction_row) { return 'none'; } return $xaction_row['id']; } private function getCommentVersion($object) { $xaction = $object->getApplicationTransactionTemplate(); - try { - $comment = $xaction->getApplicationTransactionCommentObject(); - if (!$comment) { - return 'none'; - } - } catch (Exception $ex) { + $comment = $xaction->getApplicationTransactionCommentObject(); + if (!$comment) { return 'none'; } $comment_row = queryfx_one( $comment->establishConnection('r'), 'SELECT c.id FROM %T x JOIN %T c ON x.phid = c.transactionPHID WHERE x.objectPHID = %s ORDER BY c.id DESC LIMIT 1', $xaction->getTableName(), $comment->getTableName(), $object->getPHID()); if (!$comment_row) { return 'none'; } return $comment_row['id']; } private function getConfigurationVersion() { if ($this->configurationVersion === null) { $this->configurationVersion = $this->newConfigurationVersion(); } return $this->configurationVersion; } private function newConfigurationVersion() { $raw = array( 'services' => PhabricatorEnv::getEnvConfig('cluster.search'), ); $json = phutil_json_encode($raw); return PhabricatorHash::digestForIndex($json); } } diff --git a/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php b/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php index b1d30a5b9d..4624d6f9af 100644 --- a/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php +++ b/src/applications/search/storage/PhabricatorProfileMenuItemConfigurationTransaction.php @@ -1,27 +1,23 @@ getUser(); $providers = PhabricatorAuthProvider::getAllProviders(); $accounts = id(new PhabricatorExternalAccountQuery()) ->setViewer($viewer) ->withUserPHIDs(array($viewer->getPHID())) ->needImages(true) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->execute(); $linked_head = pht('Linked Accounts and Authentication'); $linked = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setNoDataString(pht('You have no linked accounts.')); - $login_accounts = 0; - foreach ($accounts as $account) { - if ($account->isUsableForLogin()) { - $login_accounts++; - } - } - foreach ($accounts as $account) { $item = new PHUIObjectItemView(); $provider = idx($providers, $account->getProviderKey()); if ($provider) { $item->setHeader($provider->getProviderName()); $can_unlink = $provider->shouldAllowAccountUnlink(); if (!$can_unlink) { $item->addAttribute(pht('Permanently Linked')); } } else { $item->setHeader( pht('Unknown Account ("%s")', $account->getProviderKey())); $can_unlink = true; } $can_login = $account->isUsableForLogin(); if (!$can_login) { $item->addAttribute( pht( 'Disabled (an administrator has disabled login for this '. 'account provider).')); } - $can_unlink = $can_unlink && (!$can_login || ($login_accounts > 1)); - $can_refresh = $provider && $provider->shouldAllowAccountRefresh(); if ($can_refresh) { $item->addAction( id(new PHUIListItemView()) ->setIcon('fa-refresh') ->setHref('/auth/refresh/'.$account->getProviderKey().'/')); } $item->addAction( id(new PHUIListItemView()) ->setIcon('fa-times') ->setWorkflow(true) ->setDisabled(!$can_unlink) ->setHref('/auth/unlink/'.$account->getProviderKey().'/')); if ($provider) { $provider->willRenderLinkedAccount($viewer, $item, $account); } $linked->addItem($item); } $linkable_head = pht('Add External Account'); $linkable = id(new PHUIObjectItemListView()) ->setUser($viewer) ->setNoDataString( pht('Your account is linked with all available providers.')); $accounts = mpull($accounts, null, 'getProviderKey'); - $providers = PhabricatorAuthProvider::getAllEnabledProviders(); - $providers = msort($providers, 'getProviderName'); - foreach ($providers as $key => $provider) { - if (isset($accounts[$key])) { + $configs = id(new PhabricatorAuthProviderConfigQuery()) + ->setViewer($viewer) + ->withIsEnabled(true) + ->execute(); + $configs = msort($configs, 'getSortVector'); + + foreach ($configs as $config) { + $provider = $config->getProvider(); + + if (!$provider->shouldAllowAccountLink()) { continue; } - if (!$provider->shouldAllowAccountLink()) { + // Don't show the user providers they already have linked. + $provider_key = $config->getProvider()->getProviderKey(); + if (isset($accounts[$provider_key])) { continue; } $link_uri = '/auth/link/'.$provider->getProviderKey().'/'; + $link_button = id(new PHUIButtonView()) + ->setTag('a') + ->setIcon('fa-link') + ->setHref($link_uri) + ->setColor(PHUIButtonView::GREY) + ->setText(pht('Link External Account')); + $item = id(new PHUIObjectItemView()) - ->setHeader($provider->getProviderName()) + ->setHeader($config->getDisplayName()) ->setHref($link_uri) - ->addAction( - id(new PHUIListItemView()) - ->setIcon('fa-link') - ->setHref($link_uri)); + ->setImageIcon($config->newIconView()) + ->setSideColumn($link_button); $linkable->addItem($item); } $linked_box = $this->newBox($linked_head, $linked); $linkable_box = $this->newBox($linkable_head, $linkable); return array( $linked_box, $linkable_box, ); } } diff --git a/src/applications/settings/storage/PhabricatorUserPreferencesTransaction.php b/src/applications/settings/storage/PhabricatorUserPreferencesTransaction.php index 6378ee29d3..3ef48c01e0 100644 --- a/src/applications/settings/storage/PhabricatorUserPreferencesTransaction.php +++ b/src/applications/settings/storage/PhabricatorUserPreferencesTransaction.php @@ -1,22 +1,18 @@ getViewer(); $id = $request->getURIData('id'); if (!$request->isFormPost()) { return id(new Aphront404Response()); } $poll = id(new PhabricatorSlowvoteQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->needOptions(true) ->needViewerChoices(true) ->executeOne(); if (!$poll) { return new Aphront404Response(); } if ($poll->getIsClosed()) { return new Aphront400Response(); } $options = $poll->getOptions(); $options = mpull($options, null, 'getID'); $old_votes = $poll->getViewerChoices($viewer); $old_votes = mpull($old_votes, null, 'getOptionID'); $votes = $request->getArr('vote'); $votes = array_fuse($votes); $method = $poll->getMethod(); $is_plurality = ($method == PhabricatorSlowvotePoll::METHOD_PLURALITY); + if (!$votes) { + if ($is_plurality) { + $message = pht('You must vote for something.'); + } else { + $message = pht('You must vote for at least one option.'); + } + + return $this->newDialog() + ->setTitle(pht('Stand For Something')) + ->appendParagraph($message) + ->addCancelButton($poll->getURI()); + } + if ($is_plurality && count($votes) > 1) { throw new Exception( pht('In this poll, you may only vote for one option.')); } foreach ($votes as $vote) { if (!isset($options[$vote])) { throw new Exception( pht( 'Option ("%s") is not a valid poll option. You may only '. 'vote for valid options.', $vote)); } } - foreach ($old_votes as $old_vote) { - if (!idx($votes, $old_vote->getOptionID(), false)) { + $poll->openTransaction(); + $poll->beginReadLocking(); + + $poll->reload(); + + $old_votes = id(new PhabricatorSlowvoteChoice())->loadAllWhere( + 'pollID = %d AND authorPHID = %s', + $poll->getID(), + $viewer->getPHID()); + $old_votes = mpull($old_votes, null, 'getOptionID'); + + foreach ($old_votes as $old_vote) { + if (idx($votes, $old_vote->getOptionID())) { + continue; + } + $old_vote->delete(); } - } - foreach ($votes as $vote) { - if (idx($old_votes, $vote, false)) { - continue; + foreach ($votes as $vote) { + if (idx($old_votes, $vote)) { + continue; + } + + id(new PhabricatorSlowvoteChoice()) + ->setAuthorPHID($viewer->getPHID()) + ->setPollID($poll->getID()) + ->setOptionID($vote) + ->save(); } - id(new PhabricatorSlowvoteChoice()) - ->setAuthorPHID($viewer->getPHID()) - ->setPollID($poll->getID()) - ->setOptionID($vote) - ->save(); - } + $poll->endReadLocking(); + $poll->saveTransaction(); return id(new AphrontRedirectResponse()) ->setURI($poll->getURI()); } } diff --git a/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php b/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php index 0f50a870f6..bac0ea636f 100644 --- a/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php +++ b/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php @@ -1,22 +1,18 @@ actingAsPHID = $acting_as_phid; return $this; } public function getActingAsPHID() { if ($this->actingAsPHID) { return $this->actingAsPHID; } return $this->getActor()->getPHID(); } /** * When the editor tries to apply transactions that have no effect, should * it raise an exception (default) or drop them and continue? * * Generally, you will set this flag for edits coming from "Edit" interfaces, * and leave it cleared for edits coming from "Comment" interfaces, so the * user will get a useful error if they try to submit a comment that does * nothing (e.g., empty comment with a status change that has already been * performed by another user). * * @param bool True to drop transactions without effect and continue. * @return this */ public function setContinueOnNoEffect($continue) { $this->continueOnNoEffect = $continue; return $this; } public function getContinueOnNoEffect() { return $this->continueOnNoEffect; } /** * When the editor tries to apply transactions which don't populate all of * an object's required fields, should it raise an exception (default) or * drop them and continue? * * For example, if a user adds a new required custom field (like "Severity") * to a task, all existing tasks won't have it populated. When users * manually edit existing tasks, it's usually desirable to have them provide * a severity. However, other operations (like batch editing just the * owner of a task) will fail by default. * * By setting this flag for edit operations which apply to specific fields * (like the priority, batch, and merge editors in Maniphest), these * operations can continue to function even if an object is outdated. * * @param bool True to continue when transactions don't completely satisfy * all required fields. * @return this */ public function setContinueOnMissingFields($continue_on_missing_fields) { $this->continueOnMissingFields = $continue_on_missing_fields; return $this; } public function getContinueOnMissingFields() { return $this->continueOnMissingFields; } /** * Not strictly necessary, but reply handlers ideally set this value to * make email threading work better. */ public function setParentMessageID($parent_message_id) { $this->parentMessageID = $parent_message_id; return $this; } public function getParentMessageID() { return $this->parentMessageID; } public function getIsNewObject() { return $this->isNewObject; } public function getMentionedPHIDs() { return $this->mentionedPHIDs; } public function setIsPreview($is_preview) { $this->isPreview = $is_preview; return $this; } public function getIsPreview() { return $this->isPreview; } public function setIsSilent($silent) { $this->silent = $silent; return $this; } public function getIsSilent() { return $this->silent; } public function getMustEncrypt() { return $this->mustEncrypt; } public function getHeraldRuleMonograms() { // Convert the stored "<123>, <456>" string into a list: "H123", "H456". $list = $this->heraldHeader; $list = preg_split('/[, ]+/', $list); foreach ($list as $key => $item) { $item = trim($item, '<>'); if (!is_numeric($item)) { unset($list[$key]); continue; } $list[$key] = 'H'.$item; } return $list; } public function setIsInverseEdgeEditor($is_inverse_edge_editor) { $this->isInverseEdgeEditor = $is_inverse_edge_editor; return $this; } public function getIsInverseEdgeEditor() { return $this->isInverseEdgeEditor; } public function setIsHeraldEditor($is_herald_editor) { $this->isHeraldEditor = $is_herald_editor; return $this; } public function getIsHeraldEditor() { return $this->isHeraldEditor; } public function setUnmentionablePHIDMap(array $map) { $this->unmentionablePHIDMap = $map; return $this; } public function getUnmentionablePHIDMap() { return $this->unmentionablePHIDMap; } protected function shouldEnableMentions( PhabricatorLiskDAO $object, array $xactions) { return true; } public function setApplicationEmail( PhabricatorMetaMTAApplicationEmail $email) { $this->applicationEmail = $email; return $this; } public function getApplicationEmail() { return $this->applicationEmail; } public function setRaiseWarnings($raise_warnings) { $this->raiseWarnings = $raise_warnings; return $this; } public function getRaiseWarnings() { return $this->raiseWarnings; } public function setShouldRequireMFA($should_require_mfa) { if ($this->hasRequiredMFA) { throw new Exception( pht( 'Call to setShouldRequireMFA() is too late: this Editor has already '. 'checked for MFA requirements.')); } $this->shouldRequireMFA = $should_require_mfa; return $this; } public function getShouldRequireMFA() { return $this->shouldRequireMFA; } public function getTransactionTypesForObject($object) { $old = $this->object; try { $this->object = $object; $result = $this->getTransactionTypes(); $this->object = $old; } catch (Exception $ex) { $this->object = $old; throw $ex; } return $result; } public function getTransactionTypes() { $types = array(); $types[] = PhabricatorTransactions::TYPE_CREATE; $types[] = PhabricatorTransactions::TYPE_HISTORY; if ($this->object instanceof PhabricatorEditEngineSubtypeInterface) { $types[] = PhabricatorTransactions::TYPE_SUBTYPE; } if ($this->object instanceof PhabricatorSubscribableInterface) { $types[] = PhabricatorTransactions::TYPE_SUBSCRIBERS; } if ($this->object instanceof PhabricatorCustomFieldInterface) { $types[] = PhabricatorTransactions::TYPE_CUSTOMFIELD; } if ($this->object instanceof PhabricatorTokenReceiverInterface) { $types[] = PhabricatorTransactions::TYPE_TOKEN; } if ($this->object instanceof PhabricatorProjectInterface || $this->object instanceof PhabricatorMentionableInterface) { $types[] = PhabricatorTransactions::TYPE_EDGE; } if ($this->object instanceof PhabricatorSpacesInterface) { $types[] = PhabricatorTransactions::TYPE_SPACE; } $types[] = PhabricatorTransactions::TYPE_MFA; $template = $this->object->getApplicationTransactionTemplate(); if ($template instanceof PhabricatorModularTransaction) { $xtypes = $template->newModularTransactionTypes(); foreach ($xtypes as $xtype) { $types[] = $xtype->getTransactionTypeConstant(); } } if ($template) { - try { - $comment = $template->getApplicationTransactionCommentObject(); - } catch (PhutilMethodNotImplementedException $ex) { - $comment = null; - } - + $comment = $template->getApplicationTransactionCommentObject(); if ($comment) { $types[] = PhabricatorTransactions::TYPE_COMMENT; } } return $types; } private function adjustTransactionValues( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { if ($xaction->shouldGenerateOldValue()) { $old = $this->getTransactionOldValue($object, $xaction); $xaction->setOldValue($old); } $new = $this->getTransactionNewValue($object, $xaction); $xaction->setNewValue($new); } private function getTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); return $xtype->generateOldValue($object); } switch ($type) { case PhabricatorTransactions::TYPE_CREATE: case PhabricatorTransactions::TYPE_HISTORY: return null; case PhabricatorTransactions::TYPE_SUBTYPE: return $object->getEditEngineSubtype(); case PhabricatorTransactions::TYPE_MFA: return null; case PhabricatorTransactions::TYPE_SUBSCRIBERS: return array_values($this->subscribers); case PhabricatorTransactions::TYPE_VIEW_POLICY: if ($this->getIsNewObject()) { return null; } return $object->getViewPolicy(); case PhabricatorTransactions::TYPE_EDIT_POLICY: if ($this->getIsNewObject()) { return null; } return $object->getEditPolicy(); case PhabricatorTransactions::TYPE_JOIN_POLICY: if ($this->getIsNewObject()) { return null; } return $object->getJoinPolicy(); case PhabricatorTransactions::TYPE_SPACE: if ($this->getIsNewObject()) { return null; } $space_phid = $object->getSpacePHID(); if ($space_phid === null) { $default_space = PhabricatorSpacesNamespaceQuery::getDefaultSpace(); if ($default_space) { $space_phid = $default_space->getPHID(); } } return $space_phid; case PhabricatorTransactions::TYPE_EDGE: $edge_type = $xaction->getMetadataValue('edge:type'); if (!$edge_type) { throw new Exception( pht( "Edge transaction has no '%s'!", 'edge:type')); } // See T13082. If this is an inverse edit, the parent editor has // already populated the transaction values correctly. if ($this->getIsInverseEdgeEditor()) { return $xaction->getOldValue(); } $old_edges = array(); if ($object->getPHID()) { $edge_src = $object->getPHID(); $old_edges = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(array($edge_src)) ->withEdgeTypes(array($edge_type)) ->needEdgeData(true) ->execute(); $old_edges = $old_edges[$edge_src][$edge_type]; } return $old_edges; case PhabricatorTransactions::TYPE_CUSTOMFIELD: // NOTE: Custom fields have their old value pre-populated when they are // built by PhabricatorCustomFieldList. return $xaction->getOldValue(); case PhabricatorTransactions::TYPE_COMMENT: return null; default: return $this->getCustomTransactionOldValue($object, $xaction); } } private function getTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); return $xtype->generateNewValue($object, $xaction->getNewValue()); } switch ($type) { case PhabricatorTransactions::TYPE_CREATE: return null; case PhabricatorTransactions::TYPE_SUBSCRIBERS: return $this->getPHIDTransactionNewValue($xaction); case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_TOKEN: case PhabricatorTransactions::TYPE_INLINESTATE: case PhabricatorTransactions::TYPE_SUBTYPE: case PhabricatorTransactions::TYPE_HISTORY: return $xaction->getNewValue(); case PhabricatorTransactions::TYPE_MFA: return true; case PhabricatorTransactions::TYPE_SPACE: $space_phid = $xaction->getNewValue(); if (!strlen($space_phid)) { // If an install has no Spaces or the Spaces controls are not visible // to the viewer, we might end up with the empty string here instead // of a strict `null`, because some controller just used `getStr()` // to read the space PHID from the request. // Just make this work like callers might reasonably expect so we // don't need to handle this specially in every EditController. return $this->getActor()->getDefaultSpacePHID(); } else { return $space_phid; } case PhabricatorTransactions::TYPE_EDGE: // See T13082. If this is an inverse edit, the parent editor has // already populated appropriate transaction values. if ($this->getIsInverseEdgeEditor()) { return $xaction->getNewValue(); } $new_value = $this->getEdgeTransactionNewValue($xaction); $edge_type = $xaction->getMetadataValue('edge:type'); $type_project = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; if ($edge_type == $type_project) { $new_value = $this->applyProjectConflictRules($new_value); } return $new_value; case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getCustomFieldForTransaction($object, $xaction); return $field->getNewValueFromApplicationTransactions($xaction); case PhabricatorTransactions::TYPE_COMMENT: return null; default: return $this->getCustomTransactionNewValue($object, $xaction); } } protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { throw new Exception(pht('Capability not supported!')); } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { throw new Exception(pht('Capability not supported!')); } protected function transactionHasEffect( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_CREATE: case PhabricatorTransactions::TYPE_HISTORY: return true; case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getCustomFieldForTransaction($object, $xaction); return $field->getApplicationTransactionHasEffect($xaction); case PhabricatorTransactions::TYPE_EDGE: // A straight value comparison here doesn't always get the right // result, because newly added edges aren't fully populated. Instead, // compare the changes in a more granular way. $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $old_dst = array_keys($old); $new_dst = array_keys($new); // NOTE: For now, we don't consider edge reordering to be a change. // We have very few order-dependent edges and effectively no order // oriented UI. This might change in the future. sort($old_dst); sort($new_dst); if ($old_dst !== $new_dst) { // We've added or removed edges, so this transaction definitely // has an effect. return true; } // We haven't added or removed edges, but we might have changed // edge data. foreach ($old as $key => $old_value) { $new_value = $new[$key]; if ($old_value['data'] !== $new_value['data']) { return true; } } return false; } $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { return $xtype->getTransactionHasEffect( $object, $xaction->getOldValue(), $xaction->getNewValue()); } if ($xaction->hasComment()) { return true; } return ($xaction->getOldValue() !== $xaction->getNewValue()); } protected function shouldApplyInitialEffects( PhabricatorLiskDAO $object, array $xactions) { return false; } protected function applyInitialEffects( PhabricatorLiskDAO $object, array $xactions) { throw new PhutilMethodNotImplementedException(); } private function applyInternalEffects( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); return $xtype->applyInternalEffects($object, $xaction->getNewValue()); } switch ($type) { case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getCustomFieldForTransaction($object, $xaction); return $field->applyApplicationTransactionInternalEffects($xaction); case PhabricatorTransactions::TYPE_CREATE: case PhabricatorTransactions::TYPE_HISTORY: case PhabricatorTransactions::TYPE_SUBTYPE: case PhabricatorTransactions::TYPE_MFA: case PhabricatorTransactions::TYPE_TOKEN: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_SUBSCRIBERS: case PhabricatorTransactions::TYPE_INLINESTATE: case PhabricatorTransactions::TYPE_EDGE: case PhabricatorTransactions::TYPE_SPACE: case PhabricatorTransactions::TYPE_COMMENT: return $this->applyBuiltinInternalTransaction($object, $xaction); } return $this->applyCustomInternalTransaction($object, $xaction); } private function applyExternalEffects( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); return $xtype->applyExternalEffects($object, $xaction->getNewValue()); } switch ($type) { case PhabricatorTransactions::TYPE_SUBSCRIBERS: $subeditor = id(new PhabricatorSubscriptionsEditor()) ->setObject($object) ->setActor($this->requireActor()); $old_map = array_fuse($xaction->getOldValue()); $new_map = array_fuse($xaction->getNewValue()); $subeditor->unsubscribe( array_keys( array_diff_key($old_map, $new_map))); $subeditor->subscribeExplicit( array_keys( array_diff_key($new_map, $old_map))); $subeditor->save(); // for the rest of these edits, subscribers should include those just // added as well as those just removed. $subscribers = array_unique(array_merge( $this->subscribers, $xaction->getOldValue(), $xaction->getNewValue())); $this->subscribers = $subscribers; return $this->applyBuiltinExternalTransaction($object, $xaction); case PhabricatorTransactions::TYPE_CUSTOMFIELD: $field = $this->getCustomFieldForTransaction($object, $xaction); return $field->applyApplicationTransactionExternalEffects($xaction); case PhabricatorTransactions::TYPE_CREATE: case PhabricatorTransactions::TYPE_HISTORY: case PhabricatorTransactions::TYPE_SUBTYPE: case PhabricatorTransactions::TYPE_MFA: case PhabricatorTransactions::TYPE_EDGE: case PhabricatorTransactions::TYPE_TOKEN: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_INLINESTATE: case PhabricatorTransactions::TYPE_SPACE: case PhabricatorTransactions::TYPE_COMMENT: return $this->applyBuiltinExternalTransaction($object, $xaction); } return $this->applyCustomExternalTransaction($object, $xaction); } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); throw new Exception( pht( "Transaction type '%s' is missing an internal apply implementation!", $type)); } protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); throw new Exception( pht( "Transaction type '%s' is missing an external apply implementation!", $type)); } /** * @{class:PhabricatorTransactions} provides many built-in transactions * which should not require much - if any - code in specific applications. * * This method is a hook for the exceedingly-rare cases where you may need * to do **additional** work for built-in transactions. Developers should * extend this method, making sure to return the parent implementation * regardless of handling any transactions. * * See also @{method:applyBuiltinExternalTransaction}. */ protected function applyBuiltinInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_VIEW_POLICY: $object->setViewPolicy($xaction->getNewValue()); break; case PhabricatorTransactions::TYPE_EDIT_POLICY: $object->setEditPolicy($xaction->getNewValue()); break; case PhabricatorTransactions::TYPE_JOIN_POLICY: $object->setJoinPolicy($xaction->getNewValue()); break; case PhabricatorTransactions::TYPE_SPACE: $object->setSpacePHID($xaction->getNewValue()); break; case PhabricatorTransactions::TYPE_SUBTYPE: $object->setEditEngineSubtype($xaction->getNewValue()); break; } } /** * See @{method::applyBuiltinInternalTransaction}. */ protected function applyBuiltinExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_EDGE: if ($this->getIsInverseEdgeEditor()) { // If we're writing an inverse edge transaction, don't actually // do anything. The initiating editor on the other side of the // transaction will take care of the edge writes. break; } $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $src = $object->getPHID(); $const = $xaction->getMetadataValue('edge:type'); foreach ($new as $dst_phid => $edge) { $new[$dst_phid]['src'] = $src; } $editor = new PhabricatorEdgeEditor(); foreach ($old as $dst_phid => $edge) { if (!empty($new[$dst_phid])) { if ($old[$dst_phid]['data'] === $new[$dst_phid]['data']) { continue; } } $editor->removeEdge($src, $const, $dst_phid); } foreach ($new as $dst_phid => $edge) { if (!empty($old[$dst_phid])) { if ($old[$dst_phid]['data'] === $new[$dst_phid]['data']) { continue; } } $data = array( 'data' => $edge['data'], ); $editor->addEdge($src, $const, $dst_phid, $data); } $editor->save(); $this->updateWorkboardColumns($object, $const, $old, $new); break; case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_SPACE: $this->scrambleFileSecrets($object); break; case PhabricatorTransactions::TYPE_HISTORY: $this->sendHistory = true; break; } } /** * Fill in a transaction's common values, like author and content source. */ protected function populateTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $actor = $this->getActor(); // TODO: This needs to be more sophisticated once we have meta-policies. $xaction->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC); if ($actor->isOmnipotent()) { $xaction->setEditPolicy(PhabricatorPolicies::POLICY_NOONE); } else { $xaction->setEditPolicy($this->getActingAsPHID()); } // If the transaction already has an explicit author PHID, allow it to // stand. This is used by applications like Owners that hook into the // post-apply change pipeline. if (!$xaction->getAuthorPHID()) { $xaction->setAuthorPHID($this->getActingAsPHID()); } $xaction->setContentSource($this->getContentSource()); $xaction->attachViewer($actor); $xaction->attachObject($object); if ($object->getPHID()) { $xaction->setObjectPHID($object->getPHID()); } if ($this->getIsSilent()) { $xaction->setIsSilentTransaction(true); } return $xaction; } protected function didApplyInternalEffects( PhabricatorLiskDAO $object, array $xactions) { return $xactions; } protected function applyFinalEffects( PhabricatorLiskDAO $object, array $xactions) { return $xactions; } final protected function didCommitTransactions( PhabricatorLiskDAO $object, array $xactions) { foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); // See T13082. When we're writing edges that imply corresponding inverse // transactions, apply those inverse transactions now. We have to wait // until the object we're editing (with this editor) has committed its // transactions to do this. If we don't, the inverse editor may race, // build a mail before we actually commit this object, and render "alice // added an edge: Unknown Object". if ($type === PhabricatorTransactions::TYPE_EDGE) { // Don't do anything if we're already an inverse edge editor. if ($this->getIsInverseEdgeEditor()) { continue; } $edge_const = $xaction->getMetadataValue('edge:type'); $edge_type = PhabricatorEdgeType::getByConstant($edge_const); if ($edge_type->shouldWriteInverseTransactions()) { $this->applyInverseEdgeTransactions( $object, $xaction, $edge_type->getInverseEdgeConstant()); } continue; } $xtype = $this->getModularTransactionType($type); if (!$xtype) { continue; } $xtype = clone $xtype; $xtype->setStorage($xaction); $xtype->didCommitTransaction($object, $xaction->getNewValue()); } } public function setContentSource(PhabricatorContentSource $content_source) { $this->contentSource = $content_source; return $this; } public function setContentSourceFromRequest(AphrontRequest $request) { $this->setRequest($request); return $this->setContentSource( PhabricatorContentSource::newFromRequest($request)); } public function getContentSource() { return $this->contentSource; } public function setRequest(AphrontRequest $request) { $this->request = $request; return $this; } public function getRequest() { return $this->request; } public function setCancelURI($cancel_uri) { $this->cancelURI = $cancel_uri; return $this; } public function getCancelURI() { return $this->cancelURI; } final public function applyTransactions( PhabricatorLiskDAO $object, array $xactions) { $this->object = $object; $this->xactions = $xactions; $this->isNewObject = ($object->getPHID() === null); $this->validateEditParameters($object, $xactions); $xactions = $this->newMFATransactions($object, $xactions); $actor = $this->requireActor(); // NOTE: Some transaction expansion requires that the edited object be // attached. foreach ($xactions as $xaction) { $xaction->attachObject($object); $xaction->attachViewer($actor); } $xactions = $this->expandTransactions($object, $xactions); $xactions = $this->expandSupportTransactions($object, $xactions); $xactions = $this->combineTransactions($xactions); foreach ($xactions as $xaction) { $xaction = $this->populateTransaction($object, $xaction); } $is_preview = $this->getIsPreview(); $read_locking = false; $transaction_open = false; if (!$is_preview) { $errors = array(); $type_map = mgroup($xactions, 'getTransactionType'); foreach ($this->getTransactionTypes() as $type) { $type_xactions = idx($type_map, $type, array()); $errors[] = $this->validateTransaction($object, $type, $type_xactions); } $errors[] = $this->validateAllTransactions($object, $xactions); $errors[] = $this->validateTransactionsWithExtensions($object, $xactions); $errors = array_mergev($errors); $continue_on_missing = $this->getContinueOnMissingFields(); foreach ($errors as $key => $error) { if ($continue_on_missing && $error->getIsMissingFieldError()) { unset($errors[$key]); } } if ($errors) { throw new PhabricatorApplicationTransactionValidationException($errors); } if ($this->raiseWarnings) { $warnings = array(); foreach ($xactions as $xaction) { if ($this->hasWarnings($object, $xaction)) { $warnings[] = $xaction; } } if ($warnings) { throw new PhabricatorApplicationTransactionWarningException( $warnings); } } } foreach ($xactions as $xaction) { $this->adjustTransactionValues($object, $xaction); } // Now that we've merged and combined transactions, check for required // capabilities. Note that we're doing this before filtering // transactions: if you try to apply an edit which you do not have // permission to apply, we want to give you a permissions error even // if the edit would have no effect. $this->applyCapabilityChecks($object, $xactions); $xactions = $this->filterTransactions($object, $xactions); if (!$is_preview) { $this->hasRequiredMFA = true; if ($this->getShouldRequireMFA()) { $this->requireMFA($object, $xactions); } if ($object->getID()) { $this->buildOldRecipientLists($object, $xactions); $object->openTransaction(); $transaction_open = true; $object->beginReadLocking(); $read_locking = true; $object->reload(); } if ($this->shouldApplyInitialEffects($object, $xactions)) { if (!$transaction_open) { $object->openTransaction(); $transaction_open = true; } } } try { if ($this->shouldApplyInitialEffects($object, $xactions)) { $this->applyInitialEffects($object, $xactions); } // TODO: Once everything is on EditEngine, just use getIsNewObject() to // figure this out instead. $mark_as_create = false; $create_type = PhabricatorTransactions::TYPE_CREATE; foreach ($xactions as $xaction) { if ($xaction->getTransactionType() == $create_type) { $mark_as_create = true; } } if ($mark_as_create) { foreach ($xactions as $xaction) { $xaction->setIsCreateTransaction(true); } } $xactions = $this->sortTransactions($xactions); $file_phids = $this->extractFilePHIDs($object, $xactions); if ($is_preview) { $this->loadHandles($xactions); return $xactions; } $comment_editor = id(new PhabricatorApplicationTransactionCommentEditor()) ->setActor($actor) ->setActingAsPHID($this->getActingAsPHID()) ->setContentSource($this->getContentSource()); if (!$transaction_open) { $object->openTransaction(); $transaction_open = true; } + // We can technically test any object for CAN_INTERACT, but we can + // run into some issues in doing so (for example, in project unit tests). + // For now, only test for CAN_INTERACT if the object is explicitly a + // lockable object. + + $was_locked = false; + if ($object instanceof PhabricatorEditEngineLockableInterface) { + $was_locked = !PhabricatorPolicyFilter::canInteract($actor, $object); + } + foreach ($xactions as $xaction) { $this->applyInternalEffects($object, $xaction); } $xactions = $this->didApplyInternalEffects($object, $xactions); try { $object->save(); } catch (AphrontDuplicateKeyQueryException $ex) { // This callback has an opportunity to throw a better exception, // so execution may end here. $this->didCatchDuplicateKeyException($object, $xactions, $ex); throw $ex; } foreach ($xactions as $xaction) { + if ($was_locked) { + $xaction->setIsLockOverrideTransaction(true); + } + $xaction->setObjectPHID($object->getPHID()); if ($xaction->getComment()) { $xaction->setPHID($xaction->generatePHID()); $comment_editor->applyEdit($xaction, $xaction->getComment()); } else { // TODO: This is a transitional hack to let us migrate edge // transactions to a more efficient storage format. For now, we're // going to write a new slim format to the database but keep the old // bulky format on the objects so we don't have to upgrade all the // edit logic to the new format yet. See T13051. $edge_type = PhabricatorTransactions::TYPE_EDGE; if ($xaction->getTransactionType() == $edge_type) { $bulky_old = $xaction->getOldValue(); $bulky_new = $xaction->getNewValue(); $record = PhabricatorEdgeChangeRecord::newFromTransaction($xaction); $slim_old = $record->getModernOldEdgeTransactionData(); $slim_new = $record->getModernNewEdgeTransactionData(); $xaction->setOldValue($slim_old); $xaction->setNewValue($slim_new); $xaction->save(); $xaction->setOldValue($bulky_old); $xaction->setNewValue($bulky_new); } else { $xaction->save(); } } } if ($file_phids) { $this->attachFiles($object, $file_phids); } foreach ($xactions as $xaction) { $this->applyExternalEffects($object, $xaction); } $xactions = $this->applyFinalEffects($object, $xactions); if ($read_locking) { $object->endReadLocking(); $read_locking = false; } if ($transaction_open) { $object->saveTransaction(); $transaction_open = false; } $this->didCommitTransactions($object, $xactions); } catch (Exception $ex) { if ($read_locking) { $object->endReadLocking(); $read_locking = false; } if ($transaction_open) { $object->killTransaction(); $transaction_open = false; } throw $ex; } // If we need to perform cache engine updates, execute them now. id(new PhabricatorCacheEngine()) ->updateObject($object); // Now that we've completely applied the core transaction set, try to apply // Herald rules. Herald rules are allowed to either take direct actions on // the database (like writing flags), or take indirect actions (like saving // some targets for CC when we generate mail a little later), or return // transactions which we'll apply normally using another Editor. // First, check if *this* is a sub-editor which is itself applying Herald // rules: if it is, stop working and return so we don't descend into // madness. // Otherwise, we're not a Herald editor, so process Herald rules (possibly // using a Herald editor to apply resulting transactions) and then send out // mail, notifications, and feed updates about everything. if ($this->getIsHeraldEditor()) { // We are the Herald editor, so stop work here and return the updated // transactions. return $xactions; } else if ($this->getIsInverseEdgeEditor()) { // Do not run Herald if we're just recording that this object was // mentioned elsewhere. This tends to create Herald side effects which // feel arbitrary, and can really slow down edits which mention a large // number of other objects. See T13114. } else if ($this->shouldApplyHeraldRules($object, $xactions)) { // We are not the Herald editor, so try to apply Herald rules. $herald_xactions = $this->applyHeraldRules($object, $xactions); if ($herald_xactions) { $xscript_id = $this->getHeraldTranscript()->getID(); foreach ($herald_xactions as $herald_xaction) { // Don't set a transcript ID if this is a transaction from another // application or source, like Owners. if ($herald_xaction->getAuthorPHID()) { continue; } $herald_xaction->setMetadataValue('herald:transcriptID', $xscript_id); } // NOTE: We're acting as the omnipotent user because rules deal with // their own policy issues. We use a synthetic author PHID (the // Herald application) as the author of record, so that transactions // will render in a reasonable way ("Herald assigned this task ..."). $herald_actor = PhabricatorUser::getOmnipotentUser(); $herald_phid = id(new PhabricatorHeraldApplication())->getPHID(); // TODO: It would be nice to give transactions a more specific source // which points at the rule which generated them. You can figure this // out from transcripts, but it would be cleaner if you didn't have to. $herald_source = PhabricatorContentSource::newForSource( PhabricatorHeraldContentSource::SOURCECONST); $herald_editor = newv(get_class($this), array()) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true) ->setParentMessageID($this->getParentMessageID()) ->setIsHeraldEditor(true) ->setActor($herald_actor) ->setActingAsPHID($herald_phid) ->setContentSource($herald_source); $herald_xactions = $herald_editor->applyTransactions( $object, $herald_xactions); // Merge the new transactions into the transaction list: we want to // send email and publish feed stories about them, too. $xactions = array_merge($xactions, $herald_xactions); } // If Herald did not generate transactions, we may still need to handle // "Send an Email" rules. $adapter = $this->getHeraldAdapter(); $this->heraldEmailPHIDs = $adapter->getEmailPHIDs(); $this->heraldForcedEmailPHIDs = $adapter->getForcedEmailPHIDs(); $this->webhookMap = $adapter->getWebhookMap(); } $xactions = $this->didApplyTransactions($object, $xactions); if ($object instanceof PhabricatorCustomFieldInterface) { // Maybe this makes more sense to move into the search index itself? For // now I'm putting it here since I think we might end up with things that // need it to be up to date once the next page loads, but if we don't go // there we could move it into search once search moves to the daemons. // It now happens in the search indexer as well, but the search indexer is // always daemonized, so the logic above still potentially holds. We could // possibly get rid of this. The major motivation for putting it in the // indexer was to enable reindexing to work. $fields = PhabricatorCustomField::getObjectFields( $object, PhabricatorCustomField::ROLE_APPLICATIONSEARCH); $fields->readFieldsFromStorage($object); $fields->rebuildIndexes($object); } $herald_xscript = $this->getHeraldTranscript(); if ($herald_xscript) { $herald_header = $herald_xscript->getXHeraldRulesHeader(); $herald_header = HeraldTranscript::saveXHeraldRulesHeader( $object->getPHID(), $herald_header); } else { $herald_header = HeraldTranscript::loadXHeraldRulesHeader( $object->getPHID()); } $this->heraldHeader = $herald_header; // We're going to compute some of the data we'll use to publish these // transactions here, before queueing a worker. // // Primarily, this is more correct: we want to publish the object as it // exists right now. The worker may not execute for some time, and we want // to use the current To/CC list, not respect any changes which may occur // between now and when the worker executes. // // As a secondary benefit, this tends to reduce the amount of state that // Editors need to pass into workers. $object = $this->willPublish($object, $xactions); if (!$this->getIsSilent()) { if ($this->shouldSendMail($object, $xactions)) { $this->mailShouldSend = true; $this->mailToPHIDs = $this->getMailTo($object); $this->mailCCPHIDs = $this->getMailCC($object); $this->mailUnexpandablePHIDs = $this->newMailUnexpandablePHIDs($object); // Add any recipients who were previously on the notification list // but were removed by this change. $this->applyOldRecipientLists(); if ($object instanceof PhabricatorSubscribableInterface) { $this->mailMutedPHIDs = PhabricatorEdgeQuery::loadDestinationPHIDs( $object->getPHID(), PhabricatorMutedByEdgeType::EDGECONST); } else { $this->mailMutedPHIDs = array(); } $mail_xactions = $this->getTransactionsForMail($object, $xactions); $stamps = $this->newMailStamps($object, $xactions); foreach ($stamps as $stamp) { $this->mailStamps[] = $stamp->toDictionary(); } } if ($this->shouldPublishFeedStory($object, $xactions)) { $this->feedShouldPublish = true; $this->feedRelatedPHIDs = $this->getFeedRelatedPHIDs( $object, $xactions); $this->feedNotifyPHIDs = $this->getFeedNotifyPHIDs( $object, $xactions); } } PhabricatorWorker::scheduleTask( 'PhabricatorApplicationTransactionPublishWorker', array( 'objectPHID' => $object->getPHID(), 'actorPHID' => $this->getActingAsPHID(), 'xactionPHIDs' => mpull($xactions, 'getPHID'), 'state' => $this->getWorkerState(), ), array( 'objectPHID' => $object->getPHID(), 'priority' => PhabricatorWorker::PRIORITY_ALERTS, )); $this->flushTransactionQueue($object); return $xactions; } protected function didCatchDuplicateKeyException( PhabricatorLiskDAO $object, array $xactions, Exception $ex) { return; } public function publishTransactions( PhabricatorLiskDAO $object, array $xactions) { $this->object = $object; $this->xactions = $xactions; // Hook for edges or other properties that may need (re-)loading $object = $this->willPublish($object, $xactions); // The object might have changed, so reassign it. $this->object = $object; $messages = array(); if ($this->mailShouldSend) { $messages = $this->buildMail($object, $xactions); } if ($this->supportsSearch()) { PhabricatorSearchWorker::queueDocumentForIndexing( $object->getPHID(), array( 'transactionPHIDs' => mpull($xactions, 'getPHID'), )); } if ($this->feedShouldPublish) { $mailed = array(); foreach ($messages as $mail) { foreach ($mail->buildRecipientList() as $phid) { $mailed[$phid] = $phid; } } $this->publishFeedStory($object, $xactions, $mailed); } if ($this->sendHistory) { $history_mail = $this->buildHistoryMail($object); if ($history_mail) { $messages[] = $history_mail; } } // NOTE: This actually sends the mail. We do this last to reduce the chance // that we send some mail, hit an exception, then send the mail again when // retrying. foreach ($messages as $mail) { $mail->save(); } $this->queueWebhooks($object, $xactions); return $xactions; } protected function didApplyTransactions($object, array $xactions) { // Hook for subclasses. return $xactions; } private function loadHandles(array $xactions) { $phids = array(); foreach ($xactions as $key => $xaction) { $phids[$key] = $xaction->getRequiredHandlePHIDs(); } $handles = array(); $merged = array_mergev($phids); if ($merged) { $handles = id(new PhabricatorHandleQuery()) ->setViewer($this->requireActor()) ->withPHIDs($merged) ->execute(); } foreach ($xactions as $key => $xaction) { $xaction->setHandles(array_select_keys($handles, $phids[$key])); } } private function loadSubscribers(PhabricatorLiskDAO $object) { if ($object->getPHID() && ($object instanceof PhabricatorSubscribableInterface)) { $subs = PhabricatorSubscribersQuery::loadSubscribersForPHID( $object->getPHID()); $this->subscribers = array_fuse($subs); } else { $this->subscribers = array(); } } private function validateEditParameters( PhabricatorLiskDAO $object, array $xactions) { if (!$this->getContentSource()) { throw new PhutilInvalidStateException('setContentSource'); } // Do a bunch of sanity checks that the incoming transactions are fresh. // They should be unsaved and have only "transactionType" and "newValue" // set. $types = array_fill_keys($this->getTransactionTypes(), true); assert_instances_of($xactions, 'PhabricatorApplicationTransaction'); foreach ($xactions as $xaction) { if ($xaction->getPHID() || $xaction->getID()) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht('You can not apply transactions which already have IDs/PHIDs!')); } if ($xaction->getObjectPHID()) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht( 'You can not apply transactions which already have %s!', 'objectPHIDs')); } if ($xaction->getCommentPHID()) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht( 'You can not apply transactions which already have %s!', 'commentPHIDs')); } if ($xaction->getCommentVersion() !== 0) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht( 'You can not apply transactions which already have '. 'commentVersions!')); } $expect_value = !$xaction->shouldGenerateOldValue(); $has_value = $xaction->hasOldValue(); // See T13082. In the narrow case of applying inverse edge edits, we // expect the old value to be populated. if ($this->getIsInverseEdgeEditor()) { $expect_value = true; } if ($expect_value && !$has_value) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht( 'This transaction is supposed to have an %s set, but it does not!', 'oldValue')); } if ($has_value && !$expect_value) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht( 'This transaction should generate its %s automatically, '. 'but has already had one set!', 'oldValue')); } $type = $xaction->getTransactionType(); if (empty($types[$type])) { throw new PhabricatorApplicationTransactionStructureException( $xaction, pht( 'Transaction has type "%s", but that transaction type is not '. 'supported by this editor (%s).', $type, get_class($this))); } } } private function applyCapabilityChecks( PhabricatorLiskDAO $object, array $xactions) { assert_instances_of($xactions, 'PhabricatorApplicationTransaction'); $can_edit = PhabricatorPolicyCapability::CAN_EDIT; if ($this->getIsNewObject()) { // If we're creating a new object, we don't need any special capabilities // on the object. The actor has already made it through creation checks, // and objects which haven't been created yet often can not be // meaningfully tested for capabilities anyway. $required_capabilities = array(); } else { if (!$xactions && !$this->xactions) { // If we aren't doing anything, require CAN_EDIT to improve consistency. $required_capabilities = array($can_edit); } else { $required_capabilities = array(); foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if (!$xtype) { $capabilities = $this->getLegacyRequiredCapabilities($xaction); } else { $capabilities = $xtype->getRequiredCapabilities($object, $xaction); } // For convenience, we allow flexibility in the return types because // it's very unusual that a transaction actually requires multiple // capability checks. if ($capabilities === null) { $capabilities = array(); } else { $capabilities = (array)$capabilities; } foreach ($capabilities as $capability) { $required_capabilities[$capability] = $capability; } } } } $required_capabilities = array_fuse($required_capabilities); $actor = $this->getActor(); if ($required_capabilities) { id(new PhabricatorPolicyFilter()) ->setViewer($actor) ->requireCapabilities($required_capabilities) ->raisePolicyExceptions(true) ->apply(array($object)); } } private function getLegacyRequiredCapabilities( PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); switch ($type) { case PhabricatorTransactions::TYPE_COMMENT: // TODO: Comments technically require CAN_INTERACT, but this is // currently somewhat special and handled through EditEngine. For now, // don't enforce it here. return null; case PhabricatorTransactions::TYPE_SUBSCRIBERS: // TODO: Removing subscribers other than yourself should probably // require CAN_EDIT permission. You can do this via the API but // generally can not via the web interface. return null; case PhabricatorTransactions::TYPE_TOKEN: // TODO: This technically requires CAN_INTERACT, like comments. return null; case PhabricatorTransactions::TYPE_HISTORY: // This is a special magic transaction which sends you history via // email and is only partially supported in the upstream. You don't // need any capabilities to apply it. return null; case PhabricatorTransactions::TYPE_MFA: // Signing a transaction group with MFA does not require permissions // on its own. return null; case PhabricatorTransactions::TYPE_EDGE: return $this->getLegacyRequiredEdgeCapabilities($xaction); default: // For other older (non-modular) transactions, always require exactly // CAN_EDIT. Transactions which do not need CAN_EDIT or need additional // capabilities must move to ModularTransactions. return PhabricatorPolicyCapability::CAN_EDIT; } } private function getLegacyRequiredEdgeCapabilities( PhabricatorApplicationTransaction $xaction) { // You don't need to have edit permission on an object to mention it or // otherwise add a relationship pointing toward it. if ($this->getIsInverseEdgeEditor()) { return null; } $edge_type = $xaction->getMetadataValue('edge:type'); switch ($edge_type) { case PhabricatorMutedByEdgeType::EDGECONST: // At time of writing, you can only write this edge for yourself, so // you don't need permissions. If you can eventually mute an object // for other users, this would need to be revisited. return null; case PhabricatorObjectMentionsObjectEdgeType::EDGECONST: return null; case PhabricatorProjectProjectHasMemberEdgeType::EDGECONST: $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $add = array_keys(array_diff_key($new, $old)); $rem = array_keys(array_diff_key($old, $new)); $actor_phid = $this->requireActor()->getPHID(); $is_join = (($add === array($actor_phid)) && !$rem); $is_leave = (($rem === array($actor_phid)) && !$add); if ($is_join) { // You need CAN_JOIN to join a project. return PhabricatorPolicyCapability::CAN_JOIN; } if ($is_leave) { $object = $this->object; // You usually don't need any capabilities to leave a project... if ($object->getIsMembershipLocked()) { // ...you must be able to edit to leave locked projects, though. return PhabricatorPolicyCapability::CAN_EDIT; } else { return null; } } // You need CAN_EDIT to change members other than yourself. return PhabricatorPolicyCapability::CAN_EDIT; case PhabricatorObjectHasWatcherEdgeType::EDGECONST: // See PHI1024. Watching a project does not require CAN_EDIT. return null; default: return PhabricatorPolicyCapability::CAN_EDIT; } } private function buildSubscribeTransaction( PhabricatorLiskDAO $object, array $xactions, array $changes) { if (!($object instanceof PhabricatorSubscribableInterface)) { return null; } if ($this->shouldEnableMentions($object, $xactions)) { // Identify newly mentioned users. We ignore users who were previously // mentioned so that we don't re-subscribe users after an edit of text // which mentions them. $old_texts = mpull($changes, 'getOldValue'); $new_texts = mpull($changes, 'getNewValue'); $old_phids = PhabricatorMarkupEngine::extractPHIDsFromMentions( $this->getActor(), $old_texts); $new_phids = PhabricatorMarkupEngine::extractPHIDsFromMentions( $this->getActor(), $new_texts); $phids = array_diff($new_phids, $old_phids); } else { $phids = array(); } $this->mentionedPHIDs = $phids; if ($object->getPHID()) { // Don't try to subscribe already-subscribed mentions: we want to generate // a dialog about an action having no effect if the user explicitly adds // existing CCs, but not if they merely mention existing subscribers. $phids = array_diff($phids, $this->subscribers); } if ($phids) { $users = id(new PhabricatorPeopleQuery()) ->setViewer($this->getActor()) ->withPHIDs($phids) ->execute(); $users = mpull($users, null, 'getPHID'); foreach ($phids as $key => $phid) { // Do not subscribe mentioned users // who do not have VIEW Permissions if ($object instanceof PhabricatorPolicyInterface && !PhabricatorPolicyFilter::hasCapability( $users[$phid], $object, PhabricatorPolicyCapability::CAN_VIEW) ) { unset($phids[$key]); } else { if ($object->isAutomaticallySubscribed($phid)) { unset($phids[$key]); } } } $phids = array_values($phids); } // No else here to properly return null should we unset all subscriber if (!$phids) { return null; } $xaction = newv(get_class(head($xactions)), array()); $xaction->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS); $xaction->setNewValue(array('+' => $phids)); return $xaction; } protected function mergeTransactions( PhabricatorApplicationTransaction $u, PhabricatorApplicationTransaction $v) { $type = $u->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $object = $this->object; return $xtype->mergeTransactions($object, $u, $v); } switch ($type) { case PhabricatorTransactions::TYPE_SUBSCRIBERS: return $this->mergePHIDOrEdgeTransactions($u, $v); case PhabricatorTransactions::TYPE_EDGE: $u_type = $u->getMetadataValue('edge:type'); $v_type = $v->getMetadataValue('edge:type'); if ($u_type == $v_type) { return $this->mergePHIDOrEdgeTransactions($u, $v); } return null; } // By default, do not merge the transactions. return null; } /** * Optionally expand transactions which imply other effects. For example, * resigning from a revision in Differential implies removing yourself as * a reviewer. */ protected function expandTransactions( PhabricatorLiskDAO $object, array $xactions) { $results = array(); foreach ($xactions as $xaction) { foreach ($this->expandTransaction($object, $xaction) as $expanded) { $results[] = $expanded; } } return $results; } protected function expandTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { return array($xaction); } public function getExpandedSupportTransactions( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $xactions = array($xaction); $xactions = $this->expandSupportTransactions( $object, $xactions); if (count($xactions) == 1) { return array(); } foreach ($xactions as $index => $cxaction) { if ($cxaction === $xaction) { unset($xactions[$index]); break; } } return $xactions; } private function expandSupportTransactions( PhabricatorLiskDAO $object, array $xactions) { $this->loadSubscribers($object); $xactions = $this->applyImplicitCC($object, $xactions); $changes = $this->getRemarkupChanges($xactions); $subscribe_xaction = $this->buildSubscribeTransaction( $object, $xactions, $changes); if ($subscribe_xaction) { $xactions[] = $subscribe_xaction; } // TODO: For now, this is just a placeholder. $engine = PhabricatorMarkupEngine::getEngine('extract'); $engine->setConfig('viewer', $this->requireActor()); $block_xactions = $this->expandRemarkupBlockTransactions( $object, $xactions, $changes, $engine); foreach ($block_xactions as $xaction) { $xactions[] = $xaction; } return $xactions; } private function getRemarkupChanges(array $xactions) { $changes = array(); foreach ($xactions as $key => $xaction) { foreach ($this->getRemarkupChangesFromTransaction($xaction) as $change) { $changes[] = $change; } } return $changes; } private function getRemarkupChangesFromTransaction( PhabricatorApplicationTransaction $transaction) { return $transaction->getRemarkupChanges(); } private function expandRemarkupBlockTransactions( PhabricatorLiskDAO $object, array $xactions, array $changes, PhutilMarkupEngine $engine) { $block_xactions = $this->expandCustomRemarkupBlockTransactions( $object, $xactions, $changes, $engine); $mentioned_phids = array(); if ($this->shouldEnableMentions($object, $xactions)) { foreach ($changes as $change) { // Here, we don't care about processing only new mentions after an edit // because there is no way for an object to ever "unmention" itself on // another object, so we can ignore the old value. $engine->markupText($change->getNewValue()); $mentioned_phids += $engine->getTextMetadata( PhabricatorObjectRemarkupRule::KEY_MENTIONED_OBJECTS, array()); } } if (!$mentioned_phids) { return $block_xactions; } $mentioned_objects = id(new PhabricatorObjectQuery()) ->setViewer($this->getActor()) ->withPHIDs($mentioned_phids) ->execute(); $mentionable_phids = array(); if ($this->shouldEnableMentions($object, $xactions)) { foreach ($mentioned_objects as $mentioned_object) { if ($mentioned_object instanceof PhabricatorMentionableInterface) { $mentioned_phid = $mentioned_object->getPHID(); if (idx($this->getUnmentionablePHIDMap(), $mentioned_phid)) { continue; } // don't let objects mention themselves if ($object->getPHID() && $mentioned_phid == $object->getPHID()) { continue; } $mentionable_phids[$mentioned_phid] = $mentioned_phid; } } } if ($mentionable_phids) { $edge_type = PhabricatorObjectMentionsObjectEdgeType::EDGECONST; $block_xactions[] = newv(get_class(head($xactions)), array()) ->setIgnoreOnNoEffect(true) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) ->setMetadataValue('edge:type', $edge_type) ->setNewValue(array('+' => $mentionable_phids)); } return $block_xactions; } protected function expandCustomRemarkupBlockTransactions( PhabricatorLiskDAO $object, array $xactions, array $changes, PhutilMarkupEngine $engine) { return array(); } /** * Attempt to combine similar transactions into a smaller number of total * transactions. For example, two transactions which edit the title of an * object can be merged into a single edit. */ private function combineTransactions(array $xactions) { $stray_comments = array(); $result = array(); $types = array(); foreach ($xactions as $key => $xaction) { $type = $xaction->getTransactionType(); if (isset($types[$type])) { foreach ($types[$type] as $other_key) { $other_xaction = $result[$other_key]; // Don't merge transactions with different authors. For example, // don't merge Herald transactions and owners transactions. if ($other_xaction->getAuthorPHID() != $xaction->getAuthorPHID()) { continue; } $merged = $this->mergeTransactions($result[$other_key], $xaction); if ($merged) { $result[$other_key] = $merged; if ($xaction->getComment() && ($xaction->getComment() !== $merged->getComment())) { $stray_comments[] = $xaction->getComment(); } if ($result[$other_key]->getComment() && ($result[$other_key]->getComment() !== $merged->getComment())) { $stray_comments[] = $result[$other_key]->getComment(); } // Move on to the next transaction. continue 2; } } } $result[$key] = $xaction; $types[$type][] = $key; } // If we merged any comments away, restore them. foreach ($stray_comments as $comment) { $xaction = newv(get_class(head($result)), array()); $xaction->setTransactionType(PhabricatorTransactions::TYPE_COMMENT); $xaction->setComment($comment); $result[] = $xaction; } return array_values($result); } public function mergePHIDOrEdgeTransactions( PhabricatorApplicationTransaction $u, PhabricatorApplicationTransaction $v) { $result = $u->getNewValue(); foreach ($v->getNewValue() as $key => $value) { if ($u->getTransactionType() == PhabricatorTransactions::TYPE_EDGE) { if (empty($result[$key])) { $result[$key] = $value; } else { // We're merging two lists of edge adds, sets, or removes. Merge // them by merging individual PHIDs within them. $merged = $result[$key]; foreach ($value as $dst => $v_spec) { if (empty($merged[$dst])) { $merged[$dst] = $v_spec; } else { // Two transactions are trying to perform the same operation on // the same edge. Normalize the edge data and then merge it. This // allows transactions to specify how data merges execute in a // precise way. $u_spec = $merged[$dst]; if (!is_array($u_spec)) { $u_spec = array('dst' => $u_spec); } if (!is_array($v_spec)) { $v_spec = array('dst' => $v_spec); } $ux_data = idx($u_spec, 'data', array()); $vx_data = idx($v_spec, 'data', array()); $merged_data = $this->mergeEdgeData( $u->getMetadataValue('edge:type'), $ux_data, $vx_data); $u_spec['data'] = $merged_data; $merged[$dst] = $u_spec; } } $result[$key] = $merged; } } else { $result[$key] = array_merge($value, idx($result, $key, array())); } } $u->setNewValue($result); // When combining an "ignore" transaction with a normal transaction, make // sure we don't propagate the "ignore" flag. if (!$v->getIgnoreOnNoEffect()) { $u->setIgnoreOnNoEffect(false); } return $u; } protected function mergeEdgeData($type, array $u, array $v) { return $v + $u; } protected function getPHIDTransactionNewValue( PhabricatorApplicationTransaction $xaction, $old = null) { if ($old !== null) { $old = array_fuse($old); } else { $old = array_fuse($xaction->getOldValue()); } return $this->getPHIDList($old, $xaction->getNewValue()); } public function getPHIDList(array $old, array $new) { $new_add = idx($new, '+', array()); unset($new['+']); $new_rem = idx($new, '-', array()); unset($new['-']); $new_set = idx($new, '=', null); if ($new_set !== null) { $new_set = array_fuse($new_set); } unset($new['=']); if ($new) { throw new Exception( pht( "Invalid '%s' value for PHID transaction. Value should contain only ". "keys '%s' (add PHIDs), '%s' (remove PHIDs) and '%s' (set PHIDS).", 'new', '+', '-', '=')); } $result = array(); foreach ($old as $phid) { if ($new_set !== null && empty($new_set[$phid])) { continue; } $result[$phid] = $phid; } if ($new_set !== null) { foreach ($new_set as $phid) { $result[$phid] = $phid; } } foreach ($new_add as $phid) { $result[$phid] = $phid; } foreach ($new_rem as $phid) { unset($result[$phid]); } return array_values($result); } protected function getEdgeTransactionNewValue( PhabricatorApplicationTransaction $xaction) { $new = $xaction->getNewValue(); $new_add = idx($new, '+', array()); unset($new['+']); $new_rem = idx($new, '-', array()); unset($new['-']); $new_set = idx($new, '=', null); unset($new['=']); if ($new) { throw new Exception( pht( "Invalid '%s' value for Edge transaction. Value should contain only ". "keys '%s' (add edges), '%s' (remove edges) and '%s' (set edges).", 'new', '+', '-', '=')); } $old = $xaction->getOldValue(); $lists = array($new_set, $new_add, $new_rem); foreach ($lists as $list) { $this->checkEdgeList($list, $xaction->getMetadataValue('edge:type')); } $result = array(); foreach ($old as $dst_phid => $edge) { if ($new_set !== null && empty($new_set[$dst_phid])) { continue; } $result[$dst_phid] = $this->normalizeEdgeTransactionValue( $xaction, $edge, $dst_phid); } if ($new_set !== null) { foreach ($new_set as $dst_phid => $edge) { $result[$dst_phid] = $this->normalizeEdgeTransactionValue( $xaction, $edge, $dst_phid); } } foreach ($new_add as $dst_phid => $edge) { $result[$dst_phid] = $this->normalizeEdgeTransactionValue( $xaction, $edge, $dst_phid); } foreach ($new_rem as $dst_phid => $edge) { unset($result[$dst_phid]); } return $result; } private function checkEdgeList($list, $edge_type) { if (!$list) { return; } foreach ($list as $key => $item) { if (phid_get_type($key) === PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) { throw new Exception( pht( 'Edge transactions must have destination PHIDs as in edge '. 'lists (found key "%s" on transaction of type "%s").', $key, $edge_type)); } if (!is_array($item) && $item !== $key) { throw new Exception( pht( 'Edge transactions must have PHIDs or edge specs as values '. '(found value "%s" on transaction of type "%s").', $item, $edge_type)); } } } private function normalizeEdgeTransactionValue( PhabricatorApplicationTransaction $xaction, $edge, $dst_phid) { if (!is_array($edge)) { if ($edge != $dst_phid) { throw new Exception( pht( 'Transaction edge data must either be the edge PHID or an edge '. 'specification dictionary.')); } $edge = array(); } else { foreach ($edge as $key => $value) { switch ($key) { case 'src': case 'dst': case 'type': case 'data': case 'dateCreated': case 'dateModified': case 'seq': case 'dataID': break; default: throw new Exception( pht( 'Transaction edge specification contains unexpected key "%s".', $key)); } } } $edge['dst'] = $dst_phid; $edge_type = $xaction->getMetadataValue('edge:type'); if (empty($edge['type'])) { $edge['type'] = $edge_type; } else { if ($edge['type'] != $edge_type) { $this_type = $edge['type']; throw new Exception( pht( "Edge transaction includes edge of type '%s', but ". "transaction is of type '%s'. Each edge transaction ". "must alter edges of only one type.", $this_type, $edge_type)); } } if (!isset($edge['data'])) { $edge['data'] = array(); } return $edge; } protected function sortTransactions(array $xactions) { $head = array(); $tail = array(); // Move bare comments to the end, so the actions precede them. foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); if ($type == PhabricatorTransactions::TYPE_COMMENT) { $tail[] = $xaction; } else { $head[] = $xaction; } } return array_values(array_merge($head, $tail)); } protected function filterTransactions( PhabricatorLiskDAO $object, array $xactions) { $type_comment = PhabricatorTransactions::TYPE_COMMENT; $type_mfa = PhabricatorTransactions::TYPE_MFA; $no_effect = array(); $has_comment = false; $any_effect = false; $meta_xactions = array(); foreach ($xactions as $key => $xaction) { if ($xaction->getTransactionType() === $type_mfa) { $meta_xactions[$key] = $xaction; continue; } if ($this->transactionHasEffect($object, $xaction)) { if ($xaction->getTransactionType() != $type_comment) { $any_effect = true; } } else if ($xaction->getIgnoreOnNoEffect()) { unset($xactions[$key]); } else { $no_effect[$key] = $xaction; } if ($xaction->hasComment()) { $has_comment = true; } } // If every transaction is a meta-transaction applying to the transaction // group, these transactions are junk. if (count($meta_xactions) == count($xactions)) { $no_effect = $xactions; $any_effect = false; } if (!$no_effect) { return $xactions; } // If none of the transactions have an effect, the meta-transactions also // have no effect. Add them to the "no effect" list so we get a full set // of errors for everything. if (!$any_effect) { $no_effect += $meta_xactions; } if (!$this->getContinueOnNoEffect() && !$this->getIsPreview()) { throw new PhabricatorApplicationTransactionNoEffectException( $no_effect, $any_effect, $has_comment); } if (!$any_effect && !$has_comment) { // If we only have empty comment transactions, just drop them all. return array(); } foreach ($no_effect as $key => $xaction) { if ($xaction->hasComment()) { $xaction->setTransactionType($type_comment); $xaction->setOldValue(null); $xaction->setNewValue(null); } else { unset($xactions[$key]); } } return $xactions; } /** * Hook for validating transactions. This callback will be invoked for each * available transaction type, even if an edit does not apply any transactions * of that type. This allows you to raise exceptions when required fields are * missing, by detecting that the object has no field value and there is no * transaction which sets one. * * @param PhabricatorLiskDAO Object being edited. * @param string Transaction type to validate. * @param list Transactions of given type, * which may be empty if the edit does not apply any transactions of the * given type. * @return list List of * validation errors. */ protected function validateTransaction( PhabricatorLiskDAO $object, $type, array $xactions) { $errors = array(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $errors[] = $xtype->validateTransactions($object, $xactions); } switch ($type) { case PhabricatorTransactions::TYPE_VIEW_POLICY: $errors[] = $this->validatePolicyTransaction( $object, $xactions, $type, PhabricatorPolicyCapability::CAN_VIEW); break; case PhabricatorTransactions::TYPE_EDIT_POLICY: $errors[] = $this->validatePolicyTransaction( $object, $xactions, $type, PhabricatorPolicyCapability::CAN_EDIT); break; case PhabricatorTransactions::TYPE_SPACE: $errors[] = $this->validateSpaceTransactions( $object, $xactions, $type); break; case PhabricatorTransactions::TYPE_SUBTYPE: $errors[] = $this->validateSubtypeTransactions( $object, $xactions, $type); break; case PhabricatorTransactions::TYPE_MFA: $errors[] = $this->validateMFATransactions( $object, $xactions, $type); break; case PhabricatorTransactions::TYPE_CUSTOMFIELD: $groups = array(); foreach ($xactions as $xaction) { $groups[$xaction->getMetadataValue('customfield:key')][] = $xaction; } $field_list = PhabricatorCustomField::getObjectFields( $object, PhabricatorCustomField::ROLE_EDIT); $field_list->setViewer($this->getActor()); $role_xactions = PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS; foreach ($field_list->getFields() as $field) { if (!$field->shouldEnableForRole($role_xactions)) { continue; } $errors[] = $field->validateApplicationTransactions( $this, $type, idx($groups, $field->getFieldKey(), array())); } break; } return array_mergev($errors); } public function validatePolicyTransaction( PhabricatorLiskDAO $object, array $xactions, $transaction_type, $capability) { $actor = $this->requireActor(); $errors = array(); // Note $this->xactions is necessary; $xactions is $this->xactions of // $transaction_type $policy_object = $this->adjustObjectForPolicyChecks( $object, $this->xactions); // Make sure the user isn't editing away their ability to $capability this // object. foreach ($xactions as $xaction) { try { PhabricatorPolicyFilter::requireCapabilityWithForcedPolicy( $actor, $policy_object, $capability, $xaction->getNewValue()); } catch (PhabricatorPolicyException $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('Invalid'), pht( 'You can not select this %s policy, because you would no longer '. 'be able to %s the object.', $capability, $capability), $xaction); } } if ($this->getIsNewObject()) { if (!$xactions) { $has_capability = PhabricatorPolicyFilter::hasCapability( $actor, $policy_object, $capability); if (!$has_capability) { $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('Invalid'), pht( 'The selected %s policy excludes you. Choose a %s policy '. 'which allows you to %s the object.', $capability, $capability, $capability)); } } } return $errors; } private function validateSpaceTransactions( PhabricatorLiskDAO $object, array $xactions, $transaction_type) { $errors = array(); $actor = $this->getActor(); $has_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpacesExist($actor); $actor_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($actor); $active_spaces = PhabricatorSpacesNamespaceQuery::getViewerActiveSpaces( $actor); foreach ($xactions as $xaction) { $space_phid = $xaction->getNewValue(); if ($space_phid === null) { if (!$has_spaces) { // The install doesn't have any spaces, so this is fine. continue; } // The install has some spaces, so every object needs to be put // in a valid space. $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('Invalid'), pht('You must choose a space for this object.'), $xaction); continue; } // If the PHID isn't `null`, it needs to be a valid space that the // viewer can see. if (empty($actor_spaces[$space_phid])) { $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('Invalid'), pht( 'You can not shift this object in the selected space, because '. 'the space does not exist or you do not have access to it.'), $xaction); } else if (empty($active_spaces[$space_phid])) { // It's OK to edit objects in an archived space, so just move on if // we aren't adjusting the value. $old_space_phid = $this->getTransactionOldValue($object, $xaction); if ($space_phid == $old_space_phid) { continue; } $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('Archived'), pht( 'You can not shift this object into the selected space, because '. 'the space is archived. Objects can not be created inside (or '. 'moved into) archived spaces.'), $xaction); } } return $errors; } private function validateSubtypeTransactions( PhabricatorLiskDAO $object, array $xactions, $transaction_type) { $errors = array(); $map = $object->newEditEngineSubtypeMap(); $old = $object->getEditEngineSubtype(); foreach ($xactions as $xaction) { $new = $xaction->getNewValue(); if ($old == $new) { continue; } if (!$map->isValidSubtype($new)) { $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('Invalid'), pht( 'The subtype "%s" is not a valid subtype.', $new), $xaction); continue; } } return $errors; } private function validateMFATransactions( PhabricatorLiskDAO $object, array $xactions, $transaction_type) { $errors = array(); $factors = id(new PhabricatorAuthFactorConfigQuery()) ->setViewer($this->getActor()) ->withUserPHIDs(array($this->getActingAsPHID())) ->withFactorProviderStatuses( array( PhabricatorAuthFactorProviderStatus::STATUS_ACTIVE, PhabricatorAuthFactorProviderStatus::STATUS_DEPRECATED, )) ->execute(); foreach ($xactions as $xaction) { if (!$factors) { $errors[] = new PhabricatorApplicationTransactionValidationError( $transaction_type, pht('No MFA'), pht( 'You do not have any MFA factors attached to your account, so '. 'you can not sign this transaction group with MFA. Add MFA to '. 'your account in Settings.'), $xaction); } } if ($xactions) { $this->setShouldRequireMFA(true); } return $errors; } protected function adjustObjectForPolicyChecks( PhabricatorLiskDAO $object, array $xactions) { $copy = clone $object; foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorTransactions::TYPE_SUBSCRIBERS: $clone_xaction = clone $xaction; $clone_xaction->setOldValue(array_values($this->subscribers)); $clone_xaction->setNewValue( $this->getPHIDTransactionNewValue( $clone_xaction)); PhabricatorPolicyRule::passTransactionHintToRule( $copy, new PhabricatorSubscriptionsSubscribersPolicyRule(), array_fuse($clone_xaction->getNewValue())); break; case PhabricatorTransactions::TYPE_SPACE: $space_phid = $this->getTransactionNewValue($object, $xaction); $copy->setSpacePHID($space_phid); break; } } return $copy; } protected function validateAllTransactions( PhabricatorLiskDAO $object, array $xactions) { return array(); } /** * Check for a missing text field. * * A text field is missing if the object has no value and there are no * transactions which set a value, or if the transactions remove the value. * This method is intended to make implementing @{method:validateTransaction} * more convenient: * * $missing = $this->validateIsEmptyTextField( * $object->getName(), * $xactions); * * This will return `true` if the net effect of the object and transactions * is an empty field. * * @param wild Current field value. * @param list Transactions editing the * field. * @return bool True if the field will be an empty text field after edits. */ protected function validateIsEmptyTextField($field_value, array $xactions) { if (strlen($field_value) && empty($xactions)) { return false; } if ($xactions && strlen(last($xactions)->getNewValue())) { return false; } return true; } /* -( Implicit CCs )------------------------------------------------------- */ /** * When a user interacts with an object, we might want to add them to CC. */ final public function applyImplicitCC( PhabricatorLiskDAO $object, array $xactions) { if (!($object instanceof PhabricatorSubscribableInterface)) { // If the object isn't subscribable, we can't CC them. return $xactions; } $actor_phid = $this->getActingAsPHID(); $type_user = PhabricatorPeopleUserPHIDType::TYPECONST; if (phid_get_type($actor_phid) != $type_user) { // Transactions by application actors like Herald, Harbormaster and // Diffusion should not CC the applications. return $xactions; } if ($object->isAutomaticallySubscribed($actor_phid)) { // If they're auto-subscribed, don't CC them. return $xactions; } $should_cc = false; foreach ($xactions as $xaction) { if ($this->shouldImplyCC($object, $xaction)) { $should_cc = true; break; } } if (!$should_cc) { // Only some types of actions imply a CC (like adding a comment). return $xactions; } if ($object->getPHID()) { if (isset($this->subscribers[$actor_phid])) { // If the user is already subscribed, don't implicitly CC them. return $xactions; } $unsub = PhabricatorEdgeQuery::loadDestinationPHIDs( $object->getPHID(), PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST); $unsub = array_fuse($unsub); if (isset($unsub[$actor_phid])) { // If the user has previously unsubscribed from this object explicitly, // don't implicitly CC them. return $xactions; } } $xaction = newv(get_class(head($xactions)), array()); $xaction->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS); $xaction->setNewValue(array('+' => array($actor_phid))); array_unshift($xactions, $xaction); return $xactions; } protected function shouldImplyCC( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { return $xaction->isCommentTransaction(); } /* -( Sending Mail )------------------------------------------------------- */ /** * @task mail */ protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { return false; } /** * @task mail */ private function buildMail( PhabricatorLiskDAO $object, array $xactions) { $email_to = $this->mailToPHIDs; $email_cc = $this->mailCCPHIDs; $email_cc = array_merge($email_cc, $this->heraldEmailPHIDs); $unexpandable = $this->mailUnexpandablePHIDs; if (!is_array($unexpandable)) { $unexpandable = array(); } $messages = $this->buildMailWithRecipients( $object, $xactions, $email_to, $email_cc, $unexpandable); $this->runHeraldMailRules($messages); return $messages; } private function buildMailWithRecipients( PhabricatorLiskDAO $object, array $xactions, array $email_to, array $email_cc, array $unexpandable) { $targets = $this->buildReplyHandler($object) ->setUnexpandablePHIDs($unexpandable) ->getMailTargets($email_to, $email_cc); // Set this explicitly before we start swapping out the effective actor. $this->setActingAsPHID($this->getActingAsPHID()); $messages = array(); foreach ($targets as $target) { $original_actor = $this->getActor(); $viewer = $target->getViewer(); $this->setActor($viewer); $locale = PhabricatorEnv::beginScopedLocale($viewer->getTranslation()); $caught = null; $mail = null; try { // Reload handles for the new viewer. $this->loadHandles($xactions); $mail = $this->buildMailForTarget($object, $xactions, $target); if ($mail) { if ($this->mustEncrypt) { $mail ->setMustEncrypt(true) ->setMustEncryptReasons($this->mustEncrypt); } } } catch (Exception $ex) { $caught = $ex; } $this->setActor($original_actor); unset($locale); if ($caught) { throw $ex; } if ($mail) { $messages[] = $mail; } } return $messages; } protected function getTransactionsForMail( PhabricatorLiskDAO $object, array $xactions) { return $xactions; } private function buildMailForTarget( PhabricatorLiskDAO $object, array $xactions, PhabricatorMailTarget $target) { // Check if any of the transactions are visible for this viewer. If we // don't have any visible transactions, don't send the mail. $any_visible = false; foreach ($xactions as $xaction) { if (!$xaction->shouldHideForMail($xactions)) { $any_visible = true; break; } } if (!$any_visible) { return null; } $mail_xactions = $this->getTransactionsForMail($object, $xactions); $mail = $this->buildMailTemplate($object); $body = $this->buildMailBody($object, $mail_xactions); $mail_tags = $this->getMailTags($object, $mail_xactions); $action = $this->getMailAction($object, $mail_xactions); $stamps = $this->generateMailStamps($object, $this->mailStamps); if (PhabricatorEnv::getEnvConfig('metamta.email-preferences')) { $this->addEmailPreferenceSectionToMailBody( $body, $object, $mail_xactions); } $muted_phids = $this->mailMutedPHIDs; if (!is_array($muted_phids)) { $muted_phids = array(); } $mail ->setSensitiveContent(false) ->setFrom($this->getActingAsPHID()) ->setSubjectPrefix($this->getMailSubjectPrefix()) ->setVarySubjectPrefix('['.$action.']') ->setThreadID($this->getMailThreadID($object), $this->getIsNewObject()) ->setRelatedPHID($object->getPHID()) ->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs()) ->setMutedPHIDs($muted_phids) ->setForceHeraldMailRecipientPHIDs($this->heraldForcedEmailPHIDs) ->setMailTags($mail_tags) ->setIsBulk(true) ->setBody($body->render()) ->setHTMLBody($body->renderHTML()); foreach ($body->getAttachments() as $attachment) { $mail->addAttachment($attachment); } if ($this->heraldHeader) { $mail->addHeader('X-Herald-Rules', $this->heraldHeader); } if ($object instanceof PhabricatorProjectInterface) { $this->addMailProjectMetadata($object, $mail); } if ($this->getParentMessageID()) { $mail->setParentMessageID($this->getParentMessageID()); } // If we have stamps, attach the raw dictionary version (not the actual // objects) to the mail so that debugging tools can see what we used to // render the final list. if ($this->mailStamps) { $mail->setMailStampMetadata($this->mailStamps); } // If we have rendered stamps, attach them to the mail. if ($stamps) { $mail->setMailStamps($stamps); } return $target->willSendMail($mail); } private function addMailProjectMetadata( PhabricatorLiskDAO $object, PhabricatorMetaMTAMail $template) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); if (!$project_phids) { return; } // TODO: This viewer isn't quite right. It would be slightly better to use // the mail recipient, but that's not very easy given the way rendering // works today. $handles = id(new PhabricatorHandleQuery()) ->setViewer($this->requireActor()) ->withPHIDs($project_phids) ->execute(); $project_tags = array(); foreach ($handles as $handle) { if (!$handle->isComplete()) { continue; } $project_tags[] = '<'.$handle->getObjectName().'>'; } if (!$project_tags) { return; } $project_tags = implode(', ', $project_tags); $template->addHeader('X-Phabricator-Projects', $project_tags); } protected function getMailThreadID(PhabricatorLiskDAO $object) { return $object->getPHID(); } /** * @task mail */ protected function getStrongestAction( PhabricatorLiskDAO $object, array $xactions) { return last(msort($xactions, 'getActionStrength')); } /** * @task mail */ protected function buildReplyHandler(PhabricatorLiskDAO $object) { throw new Exception(pht('Capability not supported.')); } /** * @task mail */ protected function getMailSubjectPrefix() { throw new Exception(pht('Capability not supported.')); } /** * @task mail */ protected function getMailTags( PhabricatorLiskDAO $object, array $xactions) { $tags = array(); foreach ($xactions as $xaction) { $tags[] = $xaction->getMailTags(); } return array_mergev($tags); } /** * @task mail */ public function getMailTagsMap() { // TODO: We should move shared mail tags, like "comment", here. return array(); } /** * @task mail */ protected function getMailAction( PhabricatorLiskDAO $object, array $xactions) { return $this->getStrongestAction($object, $xactions)->getActionName(); } /** * @task mail */ protected function buildMailTemplate(PhabricatorLiskDAO $object) { throw new Exception(pht('Capability not supported.')); } /** * @task mail */ protected function getMailTo(PhabricatorLiskDAO $object) { throw new Exception(pht('Capability not supported.')); } protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) { return array(); } /** * @task mail */ protected function getMailCC(PhabricatorLiskDAO $object) { $phids = array(); $has_support = false; if ($object instanceof PhabricatorSubscribableInterface) { $phid = $object->getPHID(); $phids[] = PhabricatorSubscribersQuery::loadSubscribersForPHID($phid); $has_support = true; } if ($object instanceof PhabricatorProjectInterface) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); if ($project_phids) { $projects = id(new PhabricatorProjectQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withPHIDs($project_phids) ->needWatchers(true) ->execute(); $watcher_phids = array(); foreach ($projects as $project) { foreach ($project->getAllAncestorWatcherPHIDs() as $phid) { $watcher_phids[$phid] = $phid; } } if ($watcher_phids) { // We need to do a visibility check for all the watchers, as // watching a project is not a guarantee that you can see objects // associated with it. $users = id(new PhabricatorPeopleQuery()) ->setViewer($this->requireActor()) ->withPHIDs($watcher_phids) ->execute(); $watchers = array(); foreach ($users as $user) { $can_see = PhabricatorPolicyFilter::hasCapability( $user, $object, PhabricatorPolicyCapability::CAN_VIEW); if ($can_see) { $watchers[] = $user->getPHID(); } } $phids[] = $watchers; } } $has_support = true; } if (!$has_support) { throw new Exception( pht('The object being edited does not implement any standard '. 'interfaces (like PhabricatorSubscribableInterface) which allow '. 'CCs to be generated automatically. Override the "getMailCC()" '. 'method and generate CCs explicitly.')); } return array_mergev($phids); } /** * @task mail */ protected function buildMailBody( PhabricatorLiskDAO $object, array $xactions) { $body = id(new PhabricatorMetaMTAMailBody()) ->setViewer($this->requireActor()) ->setContextObject($object); $this->addHeadersAndCommentsToMailBody($body, $xactions); $this->addCustomFieldsToMailBody($body, $object, $xactions); return $body; } /** * @task mail */ protected function addEmailPreferenceSectionToMailBody( PhabricatorMetaMTAMailBody $body, PhabricatorLiskDAO $object, array $xactions) { $href = PhabricatorEnv::getProductionURI( '/settings/panel/emailpreferences/'); $body->addLinkSection(pht('EMAIL PREFERENCES'), $href); } /** * @task mail */ protected function addHeadersAndCommentsToMailBody( PhabricatorMetaMTAMailBody $body, array $xactions, $object_label = null, $object_href = null) { // First, remove transactions which shouldn't be rendered in mail. foreach ($xactions as $key => $xaction) { if ($xaction->shouldHideForMail($xactions)) { unset($xactions[$key]); } } $headers = array(); $headers_html = array(); $comments = array(); $details = array(); $seen_comment = false; foreach ($xactions as $xaction) { // Most mail has zero or one comments. In these cases, we render the // "alice added a comment." transaction in the header, like a normal // transaction. // Some mail, like Differential undraft mail or "!history" mail, may // have two or more comments. In these cases, we'll put the first // "alice added a comment." transaction in the header normally, but // move the other transactions down so they provide context above the // actual comment. $comment = $this->getBodyForTextMail($xaction); if ($comment !== null) { $is_comment = true; $comments[] = array( 'xaction' => $xaction, 'comment' => $comment, 'initial' => !$seen_comment, ); } else { $is_comment = false; } if (!$is_comment || !$seen_comment) { $header = $this->getTitleForTextMail($xaction); if ($header !== null) { $headers[] = $header; } $header_html = $this->getTitleForHTMLMail($xaction); if ($header_html !== null) { $headers_html[] = $header_html; } } if ($xaction->hasChangeDetailsForMail()) { $details[] = $xaction; } if ($is_comment) { $seen_comment = true; } } $headers_text = implode("\n", $headers); $body->addRawPlaintextSection($headers_text); $headers_html = phutil_implode_html(phutil_tag('br'), $headers_html); $header_button = null; if ($object_label !== null) { $button_style = array( 'text-decoration: none;', 'padding: 4px 8px;', 'margin: 0 8px 8px;', 'float: right;', 'color: #464C5C;', 'font-weight: bold;', 'border-radius: 3px;', 'background-color: #F7F7F9;', 'background-image: linear-gradient(to bottom,#fff,#f1f0f1);', 'display: inline-block;', 'border: 1px solid rgba(71,87,120,.2);', ); $header_button = phutil_tag( 'a', array( 'style' => implode(' ', $button_style), 'href' => $object_href, ), $object_label); } $xactions_style = array(); $header_action = phutil_tag( 'td', array(), $header_button); $header_action = phutil_tag( 'td', array( 'style' => implode(' ', $xactions_style), ), array( $headers_html, // Add an extra newline to prevent the "View Object" button from // running into the transaction text in Mail.app text snippet // previews. "\n", )); $headers_html = phutil_tag( 'table', array(), phutil_tag('tr', array(), array($header_action, $header_button))); $body->addRawHTMLSection($headers_html); foreach ($comments as $spec) { $xaction = $spec['xaction']; $comment = $spec['comment']; $is_initial = $spec['initial']; // If this is not the first comment in the mail, add the header showing // who wrote the comment immediately above the comment. if (!$is_initial) { $header = $this->getTitleForTextMail($xaction); if ($header !== null) { $body->addRawPlaintextSection($header); } $header_html = $this->getTitleForHTMLMail($xaction); if ($header_html !== null) { $body->addRawHTMLSection($header_html); } } $body->addRemarkupSection(null, $comment); } foreach ($details as $xaction) { $details = $xaction->renderChangeDetailsForMail($body->getViewer()); if ($details !== null) { $label = $this->getMailDiffSectionHeader($xaction); $body->addHTMLSection($label, $details); } } } private function getMailDiffSectionHeader($xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { return $xtype->getMailDiffSectionHeader(); } return pht('EDIT DETAILS'); } /** * @task mail */ protected function addCustomFieldsToMailBody( PhabricatorMetaMTAMailBody $body, PhabricatorLiskDAO $object, array $xactions) { if ($object instanceof PhabricatorCustomFieldInterface) { $field_list = PhabricatorCustomField::getObjectFields( $object, PhabricatorCustomField::ROLE_TRANSACTIONMAIL); $field_list->setViewer($this->getActor()); $field_list->readFieldsFromStorage($object); foreach ($field_list->getFields() as $field) { $field->updateTransactionMailBody( $body, $this, $xactions); } } } /** * @task mail */ private function runHeraldMailRules(array $messages) { foreach ($messages as $message) { $engine = new HeraldEngine(); $adapter = id(new PhabricatorMailOutboundMailHeraldAdapter()) ->setObject($message); $rules = $engine->loadRulesForAdapter($adapter); $effects = $engine->applyRules($rules, $adapter); $engine->applyEffects($effects, $adapter, $rules); } } /* -( Publishing Feed Stories )-------------------------------------------- */ /** * @task feed */ protected function shouldPublishFeedStory( PhabricatorLiskDAO $object, array $xactions) { return false; } /** * @task feed */ protected function getFeedStoryType() { return 'PhabricatorApplicationTransactionFeedStory'; } /** * @task feed */ protected function getFeedRelatedPHIDs( PhabricatorLiskDAO $object, array $xactions) { $phids = array( $object->getPHID(), $this->getActingAsPHID(), ); if ($object instanceof PhabricatorProjectInterface) { $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $object->getPHID(), PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); foreach ($project_phids as $project_phid) { $phids[] = $project_phid; } } return $phids; } /** * @task feed */ protected function getFeedNotifyPHIDs( PhabricatorLiskDAO $object, array $xactions) { // If some transactions are forcing notification delivery, add the forced // recipients to the notify list. $force_list = array(); foreach ($xactions as $xaction) { $force_phids = $xaction->getForceNotifyPHIDs(); if (!$force_phids) { continue; } foreach ($force_phids as $force_phid) { $force_list[] = $force_phid; } } $to_list = $this->getMailTo($object); $cc_list = $this->getMailCC($object); $full_list = array_merge($force_list, $to_list, $cc_list); $full_list = array_fuse($full_list); return array_keys($full_list); } /** * @task feed */ protected function getFeedStoryData( PhabricatorLiskDAO $object, array $xactions) { $xactions = msort($xactions, 'getActionStrength'); $xactions = array_reverse($xactions); return array( 'objectPHID' => $object->getPHID(), 'transactionPHIDs' => mpull($xactions, 'getPHID'), ); } /** * @task feed */ protected function publishFeedStory( PhabricatorLiskDAO $object, array $xactions, array $mailed_phids) { // Remove transactions which don't publish feed stories or notifications. // These never show up anywhere, so we don't need to do anything with them. foreach ($xactions as $key => $xaction) { if (!$xaction->shouldHideForFeed()) { continue; } if (!$xaction->shouldHideForNotifications()) { continue; } unset($xactions[$key]); } if (!$xactions) { return; } $related_phids = $this->feedRelatedPHIDs; $subscribed_phids = $this->feedNotifyPHIDs; // Remove muted users from the subscription list so they don't get // notifications, either. $muted_phids = $this->mailMutedPHIDs; if (!is_array($muted_phids)) { $muted_phids = array(); } $subscribed_phids = array_fuse($subscribed_phids); foreach ($muted_phids as $muted_phid) { unset($subscribed_phids[$muted_phid]); } $subscribed_phids = array_values($subscribed_phids); $story_type = $this->getFeedStoryType(); $story_data = $this->getFeedStoryData($object, $xactions); $unexpandable_phids = $this->mailUnexpandablePHIDs; if (!is_array($unexpandable_phids)) { $unexpandable_phids = array(); } id(new PhabricatorFeedStoryPublisher()) ->setStoryType($story_type) ->setStoryData($story_data) ->setStoryTime(time()) ->setStoryAuthorPHID($this->getActingAsPHID()) ->setRelatedPHIDs($related_phids) ->setPrimaryObjectPHID($object->getPHID()) ->setSubscribedPHIDs($subscribed_phids) ->setUnexpandablePHIDs($unexpandable_phids) ->setMailRecipientPHIDs($mailed_phids) ->setMailTags($this->getMailTags($object, $xactions)) ->publish(); } /* -( Search Index )------------------------------------------------------- */ /** * @task search */ protected function supportsSearch() { return false; } /* -( Herald Integration )-------------------------------------------------- */ protected function shouldApplyHeraldRules( PhabricatorLiskDAO $object, array $xactions) { return false; } protected function buildHeraldAdapter( PhabricatorLiskDAO $object, array $xactions) { throw new Exception(pht('No herald adapter specified.')); } private function setHeraldAdapter(HeraldAdapter $adapter) { $this->heraldAdapter = $adapter; return $this; } protected function getHeraldAdapter() { return $this->heraldAdapter; } private function setHeraldTranscript(HeraldTranscript $transcript) { $this->heraldTranscript = $transcript; return $this; } protected function getHeraldTranscript() { return $this->heraldTranscript; } private function applyHeraldRules( PhabricatorLiskDAO $object, array $xactions) { $adapter = $this->buildHeraldAdapter($object, $xactions) ->setContentSource($this->getContentSource()) ->setIsNewObject($this->getIsNewObject()) ->setActingAsPHID($this->getActingAsPHID()) ->setAppliedTransactions($xactions); if ($this->getApplicationEmail()) { $adapter->setApplicationEmail($this->getApplicationEmail()); } // If this editor is operating in silent mode, tell Herald that we aren't // going to send any mail. This allows it to skip "the first time this // rule matches, send me an email" rules which would otherwise match even // though we aren't going to send any mail. if ($this->getIsSilent()) { $adapter->setForbiddenAction( HeraldMailableState::STATECONST, HeraldCoreStateReasons::REASON_SILENT); } $xscript = HeraldEngine::loadAndApplyRules($adapter); $this->setHeraldAdapter($adapter); $this->setHeraldTranscript($xscript); if ($adapter instanceof HarbormasterBuildableAdapterInterface) { $buildable_phid = $adapter->getHarbormasterBuildablePHID(); HarbormasterBuildable::applyBuildPlans( $buildable_phid, $adapter->getHarbormasterContainerPHID(), $adapter->getQueuedHarbormasterBuildRequests()); // Whether we queued any builds or not, any automatic buildable for this // object is now done preparing builds and can transition into a // completed status. $buildables = id(new HarbormasterBuildableQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withManualBuildables(false) ->withBuildablePHIDs(array($buildable_phid)) ->execute(); foreach ($buildables as $buildable) { // If this buildable has already moved beyond preparation, we don't // need to nudge it again. if (!$buildable->isPreparing()) { continue; } $buildable->sendMessage( $this->getActor(), HarbormasterMessageType::BUILDABLE_BUILD, true); } } $this->mustEncrypt = $adapter->getMustEncryptReasons(); return array_merge( $this->didApplyHeraldRules($object, $adapter, $xscript), $adapter->getQueuedTransactions()); } protected function didApplyHeraldRules( PhabricatorLiskDAO $object, HeraldAdapter $adapter, HeraldTranscript $transcript) { return array(); } /* -( Custom Fields )------------------------------------------------------ */ /** * @task customfield */ private function getCustomFieldForTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $field_key = $xaction->getMetadataValue('customfield:key'); if (!$field_key) { throw new Exception( pht( "Custom field transaction has no '%s'!", 'customfield:key')); } $field = PhabricatorCustomField::getObjectField( $object, PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS, $field_key); if (!$field) { throw new Exception( pht( "Custom field transaction has invalid '%s'; field '%s' ". "is disabled or does not exist.", 'customfield:key', $field_key)); } if (!$field->shouldAppearInApplicationTransactions()) { throw new Exception( pht( "Custom field transaction '%s' does not implement ". "integration for %s.", $field_key, 'ApplicationTransactions')); } $field->setViewer($this->getActor()); return $field; } /* -( Files )-------------------------------------------------------------- */ /** * Extract the PHIDs of any files which these transactions attach. * * @task files */ private function extractFilePHIDs( PhabricatorLiskDAO $object, array $xactions) { $changes = $this->getRemarkupChanges($xactions); $blocks = mpull($changes, 'getNewValue'); $phids = array(); if ($blocks) { $phids[] = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles( $this->getActor(), $blocks); } foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $phids[] = $xtype->extractFilePHIDs($object, $xaction->getNewValue()); } else { $phids[] = $this->extractFilePHIDsFromCustomTransaction( $object, $xaction); } } $phids = array_unique(array_filter(array_mergev($phids))); if (!$phids) { return array(); } // Only let a user attach files they can actually see, since this would // otherwise let you access any file by attaching it to an object you have // view permission on. $files = id(new PhabricatorFileQuery()) ->setViewer($this->getActor()) ->withPHIDs($phids) ->execute(); return mpull($files, 'getPHID'); } /** * @task files */ protected function extractFilePHIDsFromCustomTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { return array(); } /** * @task files */ private function attachFiles( PhabricatorLiskDAO $object, array $file_phids) { if (!$file_phids) { return; } $editor = new PhabricatorEdgeEditor(); $src = $object->getPHID(); $type = PhabricatorObjectHasFileEdgeType::EDGECONST; foreach ($file_phids as $dst) { $editor->addEdge($src, $type, $dst); } $editor->save(); } private function applyInverseEdgeTransactions( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction, $inverse_type) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $add = array_keys(array_diff_key($new, $old)); $rem = array_keys(array_diff_key($old, $new)); $add = array_fuse($add); $rem = array_fuse($rem); $all = $add + $rem; $nodes = id(new PhabricatorObjectQuery()) ->setViewer($this->requireActor()) ->withPHIDs($all) ->execute(); $object_phid = $object->getPHID(); foreach ($nodes as $node) { if (!($node instanceof PhabricatorApplicationTransactionInterface)) { continue; } if ($node instanceof PhabricatorUser) { // TODO: At least for now, don't record inverse edge transactions // for users (for example, "alincoln joined project X"): Feed fills // this role instead. continue; } $node_phid = $node->getPHID(); $editor = $node->getApplicationTransactionEditor(); $template = $node->getApplicationTransactionTemplate(); // See T13082. We have to build these transactions with synthetic values // because we've already applied the actual edit to the edge database // table. If we try to apply this transaction naturally, it will no-op // itself because it doesn't have any effect. $edge_query = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(array($node_phid)) ->withEdgeTypes(array($inverse_type)); $edge_query->execute(); $edge_phids = $edge_query->getDestinationPHIDs(); $edge_phids = array_fuse($edge_phids); $new_phids = $edge_phids; $old_phids = $edge_phids; if (isset($add[$node_phid])) { unset($old_phids[$object_phid]); } else { $old_phids[$object_phid] = $object_phid; } $template ->setTransactionType($xaction->getTransactionType()) ->setMetadataValue('edge:type', $inverse_type) ->setOldValue($old_phids) ->setNewValue($new_phids); $editor ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true) ->setParentMessageID($this->getParentMessageID()) ->setIsInverseEdgeEditor(true) ->setIsSilent($this->getIsSilent()) ->setActor($this->requireActor()) ->setActingAsPHID($this->getActingAsPHID()) ->setContentSource($this->getContentSource()); $editor->applyTransactions($node, array($template)); } } /* -( Workers )------------------------------------------------------------ */ /** * Load any object state which is required to publish transactions. * * This hook is invoked in the main process before we compute data related * to publishing transactions (like email "To" and "CC" lists), and again in * the worker before publishing occurs. * * @return object Publishable object. * @task workers */ protected function willPublish(PhabricatorLiskDAO $object, array $xactions) { return $object; } /** * Convert the editor state to a serializable dictionary which can be passed * to a worker. * * This data will be loaded with @{method:loadWorkerState} in the worker. * * @return dict Serializable editor state. * @task workers */ final private function getWorkerState() { $state = array(); foreach ($this->getAutomaticStateProperties() as $property) { $state[$property] = $this->$property; } $custom_state = $this->getCustomWorkerState(); $custom_encoding = $this->getCustomWorkerStateEncoding(); $state += array( 'excludeMailRecipientPHIDs' => $this->getExcludeMailRecipientPHIDs(), 'custom' => $this->encodeStateForStorage($custom_state, $custom_encoding), 'custom.encoding' => $custom_encoding, ); return $state; } /** * Hook; return custom properties which need to be passed to workers. * * @return dict Custom properties. * @task workers */ protected function getCustomWorkerState() { return array(); } /** * Hook; return storage encoding for custom properties which need to be * passed to workers. * * This primarily allows binary data to be passed to workers and survive * JSON encoding. * * @return dict Property encodings. * @task workers */ protected function getCustomWorkerStateEncoding() { return array(); } /** * Load editor state using a dictionary emitted by @{method:getWorkerState}. * * This method is used to load state when running worker operations. * * @param dict Editor state, from @{method:getWorkerState}. * @return this * @task workers */ final public function loadWorkerState(array $state) { foreach ($this->getAutomaticStateProperties() as $property) { $this->$property = idx($state, $property); } $exclude = idx($state, 'excludeMailRecipientPHIDs', array()); $this->setExcludeMailRecipientPHIDs($exclude); $custom_state = idx($state, 'custom', array()); $custom_encodings = idx($state, 'custom.encoding', array()); $custom = $this->decodeStateFromStorage($custom_state, $custom_encodings); $this->loadCustomWorkerState($custom); return $this; } /** * Hook; set custom properties on the editor from data emitted by * @{method:getCustomWorkerState}. * * @param dict Custom state, * from @{method:getCustomWorkerState}. * @return this * @task workers */ protected function loadCustomWorkerState(array $state) { return $this; } /** * Get a list of object properties which should be automatically sent to * workers in the state data. * * These properties will be automatically stored and loaded by the editor in * the worker. * * @return list List of properties. * @task workers */ private function getAutomaticStateProperties() { return array( 'parentMessageID', 'isNewObject', 'heraldEmailPHIDs', 'heraldForcedEmailPHIDs', 'heraldHeader', 'mailToPHIDs', 'mailCCPHIDs', 'feedNotifyPHIDs', 'feedRelatedPHIDs', 'feedShouldPublish', 'mailShouldSend', 'mustEncrypt', 'mailStamps', 'mailUnexpandablePHIDs', 'mailMutedPHIDs', 'webhookMap', 'silent', 'sendHistory', ); } /** * Apply encodings prior to storage. * * See @{method:getCustomWorkerStateEncoding}. * * @param map Map of values to encode. * @param map Map of encodings to apply. * @return map Map of encoded values. * @task workers */ final private function encodeStateForStorage( array $state, array $encodings) { foreach ($state as $key => $value) { $encoding = idx($encodings, $key); switch ($encoding) { case self::STORAGE_ENCODING_BINARY: // The mechanics of this encoding (serialize + base64) are a little // awkward, but it allows us encode arrays and still be JSON-safe // with binary data. $value = @serialize($value); if ($value === false) { throw new Exception( pht( 'Failed to serialize() value for key "%s".', $key)); } $value = base64_encode($value); if ($value === false) { throw new Exception( pht( 'Failed to base64 encode value for key "%s".', $key)); } break; } $state[$key] = $value; } return $state; } /** * Undo storage encoding applied when storing state. * * See @{method:getCustomWorkerStateEncoding}. * * @param map Map of encoded values. * @param map Map of encodings. * @return map Map of decoded values. * @task workers */ final private function decodeStateFromStorage( array $state, array $encodings) { foreach ($state as $key => $value) { $encoding = idx($encodings, $key); switch ($encoding) { case self::STORAGE_ENCODING_BINARY: $value = base64_decode($value); if ($value === false) { throw new Exception( pht( 'Failed to base64_decode() value for key "%s".', $key)); } $value = unserialize($value); break; } $state[$key] = $value; } return $state; } /** * Remove conflicts from a list of projects. * * Objects aren't allowed to be tagged with multiple milestones in the same * group, nor projects such that one tag is the ancestor of any other tag. * If the list of PHIDs include mutually exclusive projects, remove the * conflicting projects. * * @param list List of project PHIDs. * @return list List with conflicts removed. */ private function applyProjectConflictRules(array $phids) { if (!$phids) { return array(); } // Overall, the last project in the list wins in cases of conflict (so when // you add something, the thing you just added sticks and removes older // values). // Beyond that, there are two basic cases: // Milestones: An object can't be in "A > Sprint 3" and "A > Sprint 4". // If multiple projects are milestones of the same parent, we only keep the // last one. // Ancestor: You can't be in "A" and "A > B". If "A > B" comes later // in the list, we remove "A" and keep "A > B". If "A" comes later, we // remove "A > B" and keep "A". // Note that it's OK to be in "A > B" and "A > C". There's only a conflict // if one project is an ancestor of another. It's OK to have something // tagged with multiple projects which share a common ancestor, so long as // they are not mutual ancestors. $viewer = PhabricatorUser::getOmnipotentUser(); $projects = id(new PhabricatorProjectQuery()) ->setViewer($viewer) ->withPHIDs(array_keys($phids)) ->execute(); $projects = mpull($projects, null, 'getPHID'); // We're going to build a map from each project with milestones to the last // milestone in the list. This last milestone is the milestone we'll keep. $milestone_map = array(); // We're going to build a set of the projects which have no descendants // later in the list. This allows us to apply both ancestor rules. $ancestor_map = array(); foreach ($phids as $phid => $ignored) { $project = idx($projects, $phid); if (!$project) { continue; } // This is the last milestone we've seen, so set it as the selection for // the project's parent. This might be setting a new value or overwriting // an earlier value. if ($project->isMilestone()) { $parent_phid = $project->getParentProjectPHID(); $milestone_map[$parent_phid] = $phid; } // Since this is the last item in the list we've examined so far, add it // to the set of projects with no later descendants. $ancestor_map[$phid] = $phid; // Remove any ancestors from the set, since this is a later descendant. foreach ($project->getAncestorProjects() as $ancestor) { $ancestor_phid = $ancestor->getPHID(); unset($ancestor_map[$ancestor_phid]); } } // Now that we've built the maps, we can throw away all the projects which // have conflicts. foreach ($phids as $phid => $ignored) { $project = idx($projects, $phid); if (!$project) { // If a PHID is invalid, we just leave it as-is. We could clean it up, // but leaving it untouched is less likely to cause collateral damage. continue; } // If this was a milestone, check if it was the last milestone from its // group in the list. If not, remove it from the list. if ($project->isMilestone()) { $parent_phid = $project->getParentProjectPHID(); if ($milestone_map[$parent_phid] !== $phid) { unset($phids[$phid]); continue; } } // If a later project in the list is a subproject of this one, it will // have removed ancestors from the map. If this project does not point // at itself in the ancestor map, it should be discarded in favor of a // subproject that comes later. if (idx($ancestor_map, $phid) !== $phid) { unset($phids[$phid]); continue; } // If a later project in the list is an ancestor of this one, it will // have added itself to the map. If any ancestor of this project points // at itself in the map, this project should be discarded in favor of // that later ancestor. foreach ($project->getAncestorProjects() as $ancestor) { $ancestor_phid = $ancestor->getPHID(); if (isset($ancestor_map[$ancestor_phid])) { unset($phids[$phid]); continue 2; } } } return $phids; } /** * When the view policy for an object is changed, scramble the secret keys * for attached files to invalidate existing URIs. */ private function scrambleFileSecrets($object) { // If this is a newly created object, we don't need to scramble anything // since it couldn't have been previously published. if ($this->getIsNewObject()) { return; } // If the object is a file itself, scramble it. if ($object instanceof PhabricatorFile) { if ($this->shouldScramblePolicy($object->getViewPolicy())) { $object->scrambleSecret(); $object->save(); } } $phid = $object->getPHID(); $attached_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( $phid, PhabricatorObjectHasFileEdgeType::EDGECONST); if (!$attached_phids) { return; } $omnipotent_viewer = PhabricatorUser::getOmnipotentUser(); $files = id(new PhabricatorFileQuery()) ->setViewer($omnipotent_viewer) ->withPHIDs($attached_phids) ->execute(); foreach ($files as $file) { $view_policy = $file->getViewPolicy(); if ($this->shouldScramblePolicy($view_policy)) { $file->scrambleSecret(); $file->save(); } } } /** * Check if a policy is strong enough to justify scrambling. Objects which * are set to very open policies don't need to scramble their files, and * files with very open policies don't need to be scrambled when associated * objects change. */ private function shouldScramblePolicy($policy) { switch ($policy) { case PhabricatorPolicies::POLICY_PUBLIC: case PhabricatorPolicies::POLICY_USER: return false; } return true; } private function updateWorkboardColumns($object, $const, $old, $new) { // If an object is removed from a project, remove it from any proxy // columns for that project. This allows a task which is moved up from a // milestone to the parent to move back into the "Backlog" column on the // parent workboard. if ($const != PhabricatorProjectObjectHasProjectEdgeType::EDGECONST) { return; } // TODO: This should likely be some future WorkboardInterface. $appears_on_workboards = ($object instanceof ManiphestTask); if (!$appears_on_workboards) { return; } $removed_phids = array_keys(array_diff_key($old, $new)); if (!$removed_phids) { return; } // Find any proxy columns for the removed projects. $proxy_columns = id(new PhabricatorProjectColumnQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withProxyPHIDs($removed_phids) ->execute(); if (!$proxy_columns) { return array(); } $proxy_phids = mpull($proxy_columns, 'getPHID'); $position_table = new PhabricatorProjectColumnPosition(); $conn_w = $position_table->establishConnection('w'); queryfx( $conn_w, 'DELETE FROM %T WHERE objectPHID = %s AND columnPHID IN (%Ls)', $position_table->getTableName(), $object->getPHID(), $proxy_phids); } private function getModularTransactionTypes() { if ($this->modularTypes === null) { $template = $this->object->getApplicationTransactionTemplate(); if ($template instanceof PhabricatorModularTransaction) { $xtypes = $template->newModularTransactionTypes(); foreach ($xtypes as $key => $xtype) { $xtype = clone $xtype; $xtype->setEditor($this); $xtypes[$key] = $xtype; } } else { $xtypes = array(); } $this->modularTypes = $xtypes; } return $this->modularTypes; } private function getModularTransactionType($type) { $types = $this->getModularTransactionTypes(); return idx($types, $type); } public function getCreateObjectTitle($author, $object) { return pht('%s created this object.', $author); } public function getCreateObjectTitleForFeed($author, $object) { return pht('%s created an object: %s.', $author, $object); } /* -( Queue )-------------------------------------------------------------- */ protected function queueTransaction( PhabricatorApplicationTransaction $xaction) { $this->transactionQueue[] = $xaction; return $this; } private function flushTransactionQueue($object) { if (!$this->transactionQueue) { return; } $xactions = $this->transactionQueue; $this->transactionQueue = array(); $editor = $this->newQueueEditor(); return $editor->applyTransactions($object, $xactions); } private function newQueueEditor() { $editor = id(newv(get_class($this), array())) ->setActor($this->getActor()) ->setContentSource($this->getContentSource()) ->setContinueOnNoEffect($this->getContinueOnNoEffect()) ->setContinueOnMissingFields($this->getContinueOnMissingFields()) ->setIsSilent($this->getIsSilent()); if ($this->actingAsPHID !== null) { $editor->setActingAsPHID($this->actingAsPHID); } return $editor; } /* -( Stamps )------------------------------------------------------------- */ public function newMailStampTemplates($object) { $actor = $this->getActor(); $templates = array(); $extensions = $this->newMailExtensions($object); foreach ($extensions as $extension) { $stamps = $extension->newMailStampTemplates($object); foreach ($stamps as $stamp) { $key = $stamp->getKey(); if (isset($templates[$key])) { throw new Exception( pht( 'Mail extension ("%s") defines a stamp template with the '. 'same key ("%s") as another template. Each stamp template '. 'must have a unique key.', get_class($extension), $key)); } $stamp->setViewer($actor); $templates[$key] = $stamp; } } return $templates; } final public function getMailStamp($key) { if (!isset($this->stampTemplates)) { throw new PhutilInvalidStateException('newMailStampTemplates'); } if (!isset($this->stampTemplates[$key])) { throw new Exception( pht( 'Editor ("%s") has no mail stamp template with provided key ("%s").', get_class($this), $key)); } return $this->stampTemplates[$key]; } private function newMailStamps($object, array $xactions) { $actor = $this->getActor(); $this->stampTemplates = $this->newMailStampTemplates($object); $extensions = $this->newMailExtensions($object); $stamps = array(); foreach ($extensions as $extension) { $extension->newMailStamps($object, $xactions); } return $this->stampTemplates; } private function newMailExtensions($object) { $actor = $this->getActor(); $all_extensions = PhabricatorMailEngineExtension::getAllExtensions(); $extensions = array(); foreach ($all_extensions as $key => $template) { $extension = id(clone $template) ->setViewer($actor) ->setEditor($this); if ($extension->supportsObject($object)) { $extensions[$key] = $extension; } } return $extensions; } private function generateMailStamps($object, $data) { if (!$data || !is_array($data)) { return null; } $templates = $this->newMailStampTemplates($object); foreach ($data as $spec) { if (!is_array($spec)) { continue; } $key = idx($spec, 'key'); if (!isset($templates[$key])) { continue; } $type = idx($spec, 'type'); if ($templates[$key]->getStampType() !== $type) { continue; } $value = idx($spec, 'value'); $templates[$key]->setValueFromDictionary($value); } $results = array(); foreach ($templates as $template) { $value = $template->getValueForRendering(); $rendered = $template->renderStamps($value); if ($rendered === null) { continue; } $rendered = (array)$rendered; foreach ($rendered as $stamp) { $results[] = $stamp; } } natcasesort($results); return $results; } public function getRemovedRecipientPHIDs() { return $this->mailRemovedPHIDs; } private function buildOldRecipientLists($object, $xactions) { // See T4776. Before we start making any changes, build a list of the old // recipients. If a change removes a user from the recipient list for an // object we still want to notify the user about that change. This allows // them to respond if they didn't want to be removed. if (!$this->shouldSendMail($object, $xactions)) { return; } $this->oldTo = $this->getMailTo($object); $this->oldCC = $this->getMailCC($object); return $this; } private function applyOldRecipientLists() { $actor_phid = $this->getActingAsPHID(); // If you took yourself off the recipient list (for example, by // unsubscribing or resigning) assume that you know what you did and // don't need to be notified. // If you just moved from "To" to "Cc" (or vice versa), you're still a // recipient so we don't need to add you back in. $map = array_fuse($this->mailToPHIDs) + array_fuse($this->mailCCPHIDs); foreach ($this->oldTo as $phid) { if ($phid === $actor_phid) { continue; } if (isset($map[$phid])) { continue; } $this->mailToPHIDs[] = $phid; $this->mailRemovedPHIDs[] = $phid; } foreach ($this->oldCC as $phid) { if ($phid === $actor_phid) { continue; } if (isset($map[$phid])) { continue; } $this->mailCCPHIDs[] = $phid; $this->mailRemovedPHIDs[] = $phid; } return $this; } private function queueWebhooks($object, array $xactions) { $hook_viewer = PhabricatorUser::getOmnipotentUser(); $webhook_map = $this->webhookMap; if (!is_array($webhook_map)) { $webhook_map = array(); } // Add any "Firehose" hooks to the list of hooks we're going to call. $firehose_hooks = id(new HeraldWebhookQuery()) ->setViewer($hook_viewer) ->withStatuses( array( HeraldWebhook::HOOKSTATUS_FIREHOSE, )) ->execute(); foreach ($firehose_hooks as $firehose_hook) { // This is "the hook itself is the reason this hook is being called", // since we're including it because it's configured as a firehose // hook. $hook_phid = $firehose_hook->getPHID(); $webhook_map[$hook_phid][] = $hook_phid; } if (!$webhook_map) { return; } // NOTE: We're going to queue calls to disabled webhooks, they'll just // immediately fail in the worker queue. This makes the behavior more // visible. $call_hooks = id(new HeraldWebhookQuery()) ->setViewer($hook_viewer) ->withPHIDs(array_keys($webhook_map)) ->execute(); foreach ($call_hooks as $call_hook) { $trigger_phids = idx($webhook_map, $call_hook->getPHID()); $request = HeraldWebhookRequest::initializeNewWebhookRequest($call_hook) ->setObjectPHID($object->getPHID()) ->setTransactionPHIDs(mpull($xactions, 'getPHID')) ->setTriggerPHIDs($trigger_phids) ->setRetryMode(HeraldWebhookRequest::RETRY_FOREVER) ->setIsSilentAction((bool)$this->getIsSilent()) ->setIsSecureAction((bool)$this->getMustEncrypt()) ->save(); $request->queueCall(); } } private function hasWarnings($object, $xaction) { // TODO: For the moment, this is a very un-modular hack to support // exactly one type of warning (mentioning users on a draft revision) // that we want to show. See PHI433. if (!($object instanceof DifferentialRevision)) { return false; } if (!$object->isDraft()) { return false; } $type = $xaction->getTransactionType(); if ($type != PhabricatorTransactions::TYPE_SUBSCRIBERS) { return false; } // NOTE: This will currently warn even if you're only removing // subscribers. return true; } private function buildHistoryMail(PhabricatorLiskDAO $object) { $viewer = $this->requireActor(); $recipient_phid = $this->getActingAsPHID(); // Load every transaction so we can build a mail message with a complete // history for the object. $query = PhabricatorApplicationTransactionQuery::newQueryForObject($object); $xactions = $query ->setViewer($viewer) ->withObjectPHIDs(array($object->getPHID())) ->execute(); $xactions = array_reverse($xactions); $mail_messages = $this->buildMailWithRecipients( $object, $xactions, array($recipient_phid), array(), array()); $mail = head($mail_messages); // Since the user explicitly requested "!history", force delivery of this // message regardless of their other mail settings. $mail->setForceDelivery(true); return $mail; } public function newAutomaticInlineTransactions( PhabricatorLiskDAO $object, array $inlines, $transaction_type, PhabricatorCursorPagedPolicyAwareQuery $query_template) { $xactions = array(); foreach ($inlines as $inline) { $xactions[] = $object->getApplicationTransactionTemplate() ->setTransactionType($transaction_type) ->attachComment($inline); } $state_xaction = $this->newInlineStateTransaction( $object, $query_template); if ($state_xaction) { $xactions[] = $state_xaction; } return $xactions; } protected function newInlineStateTransaction( PhabricatorLiskDAO $object, PhabricatorCursorPagedPolicyAwareQuery $query_template) { $actor_phid = $this->getActingAsPHID(); $author_phid = $object->getAuthorPHID(); $actor_is_author = ($actor_phid == $author_phid); $state_map = PhabricatorTransactions::getInlineStateMap(); $query = id(clone $query_template) ->setViewer($this->getActor()) ->withFixedStates(array_keys($state_map)); $inlines = array(); $inlines[] = id(clone $query) ->withAuthorPHIDs(array($actor_phid)) ->withHasTransaction(false) ->execute(); if ($actor_is_author) { $inlines[] = id(clone $query) ->withHasTransaction(true) ->execute(); } $inlines = array_mergev($inlines); if (!$inlines) { return null; } $old_value = mpull($inlines, 'getFixedState', 'getPHID'); $new_value = array(); foreach ($old_value as $key => $state) { $new_value[$key] = $state_map[$state]; } // See PHI995. Copy some information about the inlines into the transaction // so we can tailor rendering behavior. In particular, we don't want to // render transactions about users marking their own inlines as "Done". $inline_details = array(); foreach ($inlines as $inline) { $inline_details[$inline->getPHID()] = array( 'authorPHID' => $inline->getAuthorPHID(), ); } return $object->getApplicationTransactionTemplate() ->setTransactionType(PhabricatorTransactions::TYPE_INLINESTATE) ->setIgnoreOnNoEffect(true) ->setMetadataValue('inline.details', $inline_details) ->setOldValue($old_value) ->setNewValue($new_value); } private function requireMFA(PhabricatorLiskDAO $object, array $xactions) { $actor = $this->getActor(); // Let omnipotent editors skip MFA. This is mostly aimed at scripts. if ($actor->isOmnipotent()) { return; } $editor_class = get_class($this); $object_phid = $object->getPHID(); if ($object_phid) { $workflow_key = sprintf( 'editor(%s).phid(%s)', $editor_class, $object_phid); } else { $workflow_key = sprintf( 'editor(%s).new()', $editor_class); } $request = $this->getRequest(); if ($request === null) { $source_type = $this->getContentSource()->getSourceTypeConstant(); $conduit_type = PhabricatorConduitContentSource::SOURCECONST; $is_conduit = ($source_type === $conduit_type); if ($is_conduit) { throw new Exception( pht( 'This transaction group requires MFA to apply, but you can not '. 'provide an MFA response via Conduit. Edit this object via the '. 'web UI.')); } else { throw new Exception( pht( 'This transaction group requires MFA to apply, but the Editor was '. 'not configured with a Request. This workflow can not perform an '. 'MFA check.')); } } $cancel_uri = $this->getCancelURI(); if ($cancel_uri === null) { throw new Exception( pht( 'This transaction group requires MFA to apply, but the Editor was '. 'not configured with a Cancel URI. This workflow can not perform '. 'an MFA check.')); } id(new PhabricatorAuthSessionEngine()) ->setWorkflowKey($workflow_key) ->requireHighSecurityToken($actor, $request, $cancel_uri); foreach ($xactions as $xaction) { $xaction->setIsMFATransaction(true); } } private function newMFATransactions( PhabricatorLiskDAO $object, array $xactions) { $has_engine = ($object instanceof PhabricatorEditEngineMFAInterface); if ($has_engine) { $engine = PhabricatorEditEngineMFAEngine::newEngineForObject($object) ->setViewer($this->getActor()); $require_mfa = $engine->shouldRequireMFA(); $try_mfa = $engine->shouldTryMFA(); } else { $require_mfa = false; $try_mfa = false; } // If the user is mentioning an MFA object on another object or creating // a relationship like "parent" or "child" to this object, we always // allow the edit to move forward without requiring MFA. if ($this->getIsInverseEdgeEditor()) { return $xactions; } if (!$require_mfa) { // If the object hasn't already opted into MFA, see if any of the // transactions want it. if (!$try_mfa) { foreach ($xactions as $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); if ($xtype->shouldTryMFA($object, $xaction)) { $try_mfa = true; break; } } } } if ($try_mfa) { $this->setShouldRequireMFA(true); } return $xactions; } $type_mfa = PhabricatorTransactions::TYPE_MFA; $has_mfa = false; foreach ($xactions as $xaction) { if ($xaction->getTransactionType() === $type_mfa) { $has_mfa = true; break; } } if ($has_mfa) { return $xactions; } $template = $object->getApplicationTransactionTemplate(); $mfa_xaction = id(clone $template) ->setTransactionType($type_mfa) ->setNewValue(true); array_unshift($xactions, $mfa_xaction); return $xactions; } private function getTitleForTextMail( PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); $comment = $xtype->getTitleForTextMail(); if ($comment !== false) { return $comment; } } return $xaction->getTitleForTextMail(); } private function getTitleForHTMLMail( PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); $comment = $xtype->getTitleForHTMLMail(); if ($comment !== false) { return $comment; } } return $xaction->getTitleForHTMLMail(); } private function getBodyForTextMail( PhabricatorApplicationTransaction $xaction) { $type = $xaction->getTransactionType(); $xtype = $this->getModularTransactionType($type); if ($xtype) { $xtype = clone $xtype; $xtype->setStorage($xaction); $comment = $xtype->getBodyForTextMail(); if ($comment !== false) { return $comment; } } return $xaction->getBodyForMail(); } /* -( Extensions )--------------------------------------------------------- */ private function validateTransactionsWithExtensions( PhabricatorLiskDAO $object, array $xactions) { $errors = array(); $extensions = $this->getEditorExtensions(); foreach ($extensions as $extension) { $extension_errors = $extension ->setObject($object) ->validateTransactions($object, $xactions); assert_instances_of( $extension_errors, 'PhabricatorApplicationTransactionValidationError'); $errors[] = $extension_errors; } return array_mergev($errors); } private function getEditorExtensions() { if ($this->extensions === null) { $this->extensions = $this->newEditorExtensions(); } return $this->extensions; } private function newEditorExtensions() { $extensions = PhabricatorEditorExtension::getAllExtensions(); $actor = $this->getActor(); $object = $this->object; foreach ($extensions as $key => $extension) { $extension = id(clone $extension) ->setViewer($actor) ->setEditor($this) ->setObject($object); if (!$extension->supportsObject($this, $object)) { unset($extensions[$key]); continue; } $extensions[$key] = $extension; } return $extensions; } } diff --git a/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php b/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php index 0d20533798..7d80082cb2 100644 --- a/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php +++ b/src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php @@ -1,73 +1,68 @@ getApplicationTransactionTemplate(); - - try { - $comment = $xaction->getApplicationTransactionCommentObject(); - } catch (PhutilMethodNotImplementedException $ex) { - $comment = null; - } + $comment = $xaction->getApplicationTransactionCommentObject(); return (bool)$comment; } public function newBulkEditGroups(PhabricatorEditEngine $engine) { return array( id(new PhabricatorBulkEditGroup()) ->setKey('comments') ->setLabel(pht('Comments')), ); } public function buildCustomEditFields( PhabricatorEditEngine $engine, PhabricatorApplicationTransactionInterface $object) { $comment_type = PhabricatorTransactions::TYPE_COMMENT; // Comments have a lot of special behavior which doesn't always check // this flag, but we set it for consistency. $is_interact = true; $comment_field = id(new PhabricatorCommentEditField()) ->setKey(self::EDITKEY) ->setLabel(pht('Comments')) ->setBulkEditLabel(pht('Add comment')) ->setBulkEditGroupKey('comments') ->setAliases(array('comments')) ->setIsFormField(false) ->setCanApplyWithoutEditCapability($is_interact) ->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 6d047fc823..d71728a01f 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -1,1755 +1,1764 @@ ignoreOnNoEffect = $ignore; return $this; } public function getIgnoreOnNoEffect() { return $this->ignoreOnNoEffect; } public function shouldGenerateOldValue() { switch ($this->getTransactionType()) { 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(); + return null; } 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 setIsSilentTransaction($silent) { return $this->setMetadataValue('core.silent', $silent); } public function getIsSilentTransaction() { return (bool)$this->getMetadataValue('core.silent', false); } public function setIsMFATransaction($mfa) { return $this->setMetadataValue('core.mfa', $mfa); } public function getIsMFATransaction() { return (bool)$this->getMetadataValue('core.mfa', false); } + public function setIsLockOverrideTransaction($override) { + return $this->setMetadataValue('core.lock-override', $override); + } + + public function getIsLockOverrideTransaction() { + return (bool)$this->getMetadataValue('core.lock-override', 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; } public function newChronologicalSortVector() { return id(new PhutilSortVector()) ->addInt((int)$this->getDateCreated()) ->addInt((int)$this->getID()); } /* -( 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: $record = PhabricatorEdgeChangeRecord::newFromTransaction($this); $phids[] = $record->getChangedPHIDs(); 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; } 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: switch ($this->getMetadataValue('edge:type')) { case DiffusionCommitRevertedByCommitEdgeType::EDGECONST: return 'fa-undo'; case DiffusionCommitRevertsCommitEdgeType::EDGECONST: return 'fa-ambulance'; } return 'fa-link'; case PhabricatorTransactions::TYPE_TOKEN: return 'fa-trophy'; case PhabricatorTransactions::TYPE_SPACE: return 'fa-th-large'; case PhabricatorTransactions::TYPE_COLUMNS: return 'fa-columns'; case PhabricatorTransactions::TYPE_MFA: return 'fa-vcard'; } 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_EDGE: switch ($this->getMetadataValue('edge:type')) { case DiffusionCommitRevertedByCommitEdgeType::EDGECONST: return 'pink'; case DiffusionCommitRevertsCommitEdgeType::EDGECONST: return 'sky'; } break; case PhabricatorTransactions::TYPE_MFA; return 'pink'; } 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; } $xaction_type = $this->getTransactionType(); // Always hide requests for object history. if ($xaction_type === PhabricatorTransactions::TYPE_HISTORY) { return true; } // Hide creation transactions if the old value is empty. These are // transactions like "alice set the task title to: ...", which are // essentially never interesting. if ($this->getIsCreateTransaction()) { switch ($xaction_type) { case PhabricatorTransactions::TYPE_CREATE: case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_JOIN_POLICY: case PhabricatorTransactions::TYPE_SPACE: break; case PhabricatorTransactions::TYPE_SUBTYPE: return true; 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: case PhabricatorMutedEdgeType::EDGECONST: case PhabricatorMutedByEdgeType::EDGECONST: return true; break; case PhabricatorObjectMentionedByObjectEdgeType::EDGECONST: $record = PhabricatorEdgeChangeRecord::newFromTransaction($this); $add = $record->getAddedPHIDs(); $add_value = reset($add); $add_handle = $this->getHandle($add_value); if ($add_handle->getPolicyFiltered()) { return true; } return false; break; default: break; } break; case PhabricatorTransactions::TYPE_INLINESTATE: list($done, $undone) = $this->getInterestingInlineStateChangeCounts(); if (!$done && !$undone) { return true; } 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_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: case PhabricatorTransactions::TYPE_MFA: 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 shouldHideForNotifications() { return $this->shouldHideForFeed(); } private function getTitleForMailWithRenderingTarget($new_target) { $old_target = $this->getRenderingTarget(); try { $this->setRenderingTarget($new_target); $result = $this->getTitleForMail(); } catch (Exception $ex) { $this->setRenderingTarget($old_target); throw $ex; } $this->setRenderingTarget($old_target); return $result; } public function getTitleForMail() { return $this->getTitle(); } public function getTitleForTextMail() { return $this->getTitleForMailWithRenderingTarget(self::TARGET_TEXT); } public function getTitleForHTMLMail() { // TODO: For now, rendering this with TARGET_HTML generates links with // bad targets ("/x/y/" instead of "https://dev.example.com/x/y/"). Throw // a rug over the issue for the moment. See T12921. $title = $this->getTitleForMailWithRenderingTarget(self::TARGET_TEXT); 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.'); case PhabricatorTransactions::TYPE_MFA: return pht( 'You can not sign a transaction group that has no other '. 'effects.'); } 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: $record = PhabricatorEdgeChangeRecord::newFromTransaction($this); $add = $record->getAddedPHIDs(); $rem = $record->getRemovedPHIDs(); $type = $this->getMetadata('edge:type'); $type = head($type); try { $type_obj = PhabricatorEdgeType::getByConstant($type); } catch (Exception $ex) { // Recover somewhat gracefully from edge transactions which // we don't have the classes for. return pht( '%s edited an edge.', $this->renderHandleLink($author_phid)); } 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 { $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_INLINESTATE: list($done, $undone) = $this->getInterestingInlineStateChangeCounts(); 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; case PhabricatorTransactions::TYPE_MFA: return pht( '%s signed these changes with MFA.', $this->renderHandleLink($author_phid)); 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: if ($this->getIsCreateTransaction()) { return pht( '%s created %s in the %s space.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid), $this->renderHandleLink($new)); } else { 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: $record = PhabricatorEdgeChangeRecord::newFromTransaction($this); $add = $record->getAddedPHIDs(); $rem = $record->getRemovedPHIDs(); $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_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; case PhabricatorTransactions::TYPE_MFA: return null; } 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; case PhabricatorTransactions::TYPE_MFA: // We want MFA signatures to render at the top of transaction groups, // on top of the things they signed. return 10; } 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'); 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(); } $type_mfa = PhabricatorTransactions::TYPE_MFA; 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; } // Don't group silent and nonsilent transactions together. $is_silent = $this->getIsSilentTransaction(); if ($is_silent != $xaction->getIsSilentTransaction()) { return false; } // Don't group MFA and non-MFA transactions together. $is_mfa = $this->getIsMFATransaction(); if ($is_mfa != $xaction->getIsMFATransaction()) { return false; } // Don't group two "Sign with MFA" transactions together. if ($this->getTransactionType() === $type_mfa) { if ($xaction->getTransactionType() === $type_mfa) { return false; } } + + // Don't group lock override and non-override transactions together. + $is_override = $this->getIsLockOverrideTransaction(); + if ($is_override != $xaction->getIsLockOverrideTransaction()) { + 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; } private function getInterestingInlineStateChangeCounts() { // See PHI995. Newer inline state transactions have additional details // which we use to tailor the rendering behavior. These details are not // present on older transactions. $details = $this->getMetadataValue('inline.details', array()); $new = $this->getNewValue(); $done = 0; $undone = 0; foreach ($new as $phid => $state) { $is_done = ($state == PhabricatorInlineCommentInterface::STATE_DONE); // See PHI995. If you're marking your own inline comments as "Done", // don't count them when rendering a timeline story. In the case where // you're only affecting your own comments, this will hide the // "alice marked X comments as done" story entirely. // Usually, this happens when you pre-mark inlines as "done" and submit // them yourself. We'll still generate an "alice added inline comments" // story (in most cases/contexts), but the state change story is largely // just clutter and slightly confusing/misleading. $inline_details = idx($details, $phid, array()); $inline_author_phid = idx($inline_details, 'authorPHID'); if ($inline_author_phid) { if ($inline_author_phid == $this->getAuthorPHID()) { if ($is_done) { continue; } } } if ($is_done) { $done++; } else { $undone++; } } return array($done, $undone); } /* -( 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; } public function setForceNotifyPHIDs(array $phids) { $this->setMetadataValue('notify.force', $phids); return $this; } public function getForceNotifyPHIDs() { return $this->getMetadataValue('notify.force', array()); } /* -( 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. - } + $comment_template = $this->getApplicationTransactionCommentObject(); 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/PhabricatorEditEngineConfigurationTransaction.php b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php index a1c44cc003..8cf7fe5b48 100644 --- a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php @@ -1,157 +1,153 @@ getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $type = $this->getTransactionType(); switch ($type) { case PhabricatorTransactions::TYPE_CREATE: return pht( '%s created this form configuration.', $this->renderHandleLink($author_phid)); case self::TYPE_NAME: if (strlen($old)) { return pht( '%s renamed this form from "%s" to "%s".', $this->renderHandleLink($author_phid), $old, $new); } else { return pht( '%s named this form "%s".', $this->renderHandleLink($author_phid), $new); } case self::TYPE_PREAMBLE: return pht( '%s updated the preamble for this form.', $this->renderHandleLink($author_phid)); case self::TYPE_ORDER: return pht( '%s reordered the fields in this form.', $this->renderHandleLink($author_phid)); case self::TYPE_DEFAULT: $key = $this->getMetadataValue('field.key'); return pht( '%s changed the default value for field "%s".', $this->renderHandleLink($author_phid), $key); case self::TYPE_LOCKS: return pht( '%s changed locked and hidden fields.', $this->renderHandleLink($author_phid)); case self::TYPE_DEFAULTCREATE: if ($new) { return pht( '%s added this form to the "Create" menu.', $this->renderHandleLink($author_phid)); } else { return pht( '%s removed this form from the "Create" menu.', $this->renderHandleLink($author_phid)); } case self::TYPE_ISEDIT: if ($new) { return pht( '%s marked this form as an edit form.', $this->renderHandleLink($author_phid)); } else { return pht( '%s unmarked this form as an edit form.', $this->renderHandleLink($author_phid)); } case self::TYPE_DISABLE: if ($new) { return pht( '%s disabled this form.', $this->renderHandleLink($author_phid)); } else { return pht( '%s enabled this form.', $this->renderHandleLink($author_phid)); } case self::TYPE_SUBTYPE: return pht( '%s changed the subtype of this form from "%s" to "%s".', $this->renderHandleLink($author_phid), $old, $new); } return parent::getTitle(); } public function getColor() { $author_phid = $this->getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $type = $this->getTransactionType(); switch ($type) { case PhabricatorTransactions::TYPE_CREATE: return 'green'; case self::TYPE_DISABLE: if ($new) { return 'indigo'; } else { return 'green'; } } return parent::getColor(); } public function getIcon() { $author_phid = $this->getAuthorPHID(); $old = $this->getOldValue(); $new = $this->getNewValue(); $type = $this->getTransactionType(); switch ($type) { case PhabricatorTransactions::TYPE_CREATE: return 'fa-plus'; case self::TYPE_DISABLE: if ($new) { return 'fa-ban'; } else { return 'fa-check'; } } return parent::getIcon(); } } diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php index c2b32aa190..4d738877b8 100644 --- a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php +++ b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php @@ -1,541 +1,542 @@ renderAsFeed = $feed; return $this; } 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 setObjectPHID($object_phid) { $this->objectPHID = $object_phid; return $this; } public function getObjectPHID() { return $this->objectPHID; } public function setIsPreview($is_preview) { $this->isPreview = $is_preview; return $this; } public function getIsPreview() { return $this->isPreview; } public function setShowEditActions($show_edit_actions) { $this->showEditActions = $show_edit_actions; return $this; } public function getShowEditActions() { return $this->showEditActions; } public function setMarkupEngine(PhabricatorMarkupEngine $engine) { $this->engine = $engine; return $this; } public function setTransactions(array $transactions) { assert_instances_of($transactions, 'PhabricatorApplicationTransaction'); $this->transactions = $transactions; return $this; } public function getTransactions() { return $this->transactions; } public function setShouldTerminate($term) { $this->shouldTerminate = $term; return $this; } public function setPager(AphrontCursorPagerView $pager) { $this->pager = $pager; return $this; } public function getPager() { return $this->pager; } public function setHideCommentOptions($hide_comment_options) { $this->hideCommentOptions = $hide_comment_options; return $this; } public function getHideCommentOptions() { return $this->hideCommentOptions; } public function setViewData(array $view_data) { $this->viewData = $view_data; return $this; } public function getViewData() { return $this->viewData; } public function buildEvents($with_hiding = false) { $user = $this->getUser(); $xactions = $this->transactions; $xactions = $this->filterHiddenTransactions($xactions); $xactions = $this->groupRelatedTransactions($xactions); $groups = $this->groupDisplayTransactions($xactions); // If the viewer has interacted with this object, we hide things from // before their most recent interaction by default. This tends to make // very long threads much more manageable, because you don't have to // scroll through a lot of history and can focus on just new stuff. $show_group = null; if ($with_hiding) { // Find the most recent comment by the viewer. $group_keys = array_keys($groups); $group_keys = array_reverse($group_keys); // If we would only hide a small number of transactions, don't hide // anything. Just don't examine the last few keys. Also, we always // want to show the most recent pieces of activity, so don't examine // the first few keys either. $group_keys = array_slice($group_keys, 2, -2); $type_comment = PhabricatorTransactions::TYPE_COMMENT; foreach ($group_keys as $group_key) { $group = $groups[$group_key]; foreach ($group as $xaction) { if ($xaction->getAuthorPHID() == $user->getPHID() && $xaction->getTransactionType() == $type_comment) { // This is the most recent group where the user commented. $show_group = $group_key; break 2; } } } } $events = array(); $hide_by_default = ($show_group !== null); $set_next_page_id = false; foreach ($groups as $group_key => $group) { if ($hide_by_default && ($show_group === $group_key)) { $hide_by_default = false; $set_next_page_id = true; } $group_event = null; foreach ($group as $xaction) { $event = $this->renderEvent($xaction, $group); $event->setHideByDefault($hide_by_default); if (!$group_event) { $group_event = $event; } else { $group_event->addEventToGroup($event); } if ($set_next_page_id) { $set_next_page_id = false; $pager = $this->getPager(); if ($pager) { $pager->setNextPageID($xaction->getID()); } } } $events[] = $group_event; } return $events; } public function render() { if (!$this->getObjectPHID()) { throw new PhutilInvalidStateException('setObjectPHID'); } $view = $this->buildPHUITimelineView(); if ($this->getShowEditActions()) { Javelin::initBehavior('phabricator-transaction-list'); } return $view->render(); } public function buildPHUITimelineView($with_hiding = true) { if (!$this->getObjectPHID()) { throw new PhutilInvalidStateException('setObjectPHID'); } $view = id(new PHUITimelineView()) ->setViewer($this->getViewer()) ->setShouldTerminate($this->shouldTerminate) ->setQuoteTargetID($this->getQuoteTargetID()) ->setQuoteRef($this->getQuoteRef()) ->setViewData($this->getViewData()); $events = $this->buildEvents($with_hiding); foreach ($events as $event) { $view->addEvent($event); } if ($this->getPager()) { $view->setPager($this->getPager()); } return $view; } public function isTimelineEmpty() { return !count($this->buildEvents(true)); } protected function getOrBuildEngine() { if (!$this->engine) { $field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT; $engine = id(new PhabricatorMarkupEngine()) ->setViewer($this->getViewer()); foreach ($this->transactions as $xaction) { if (!$xaction->hasComment()) { continue; } $engine->addObject($xaction->getComment(), $field); } $engine->process(); $this->engine = $engine; } return $this->engine; } private function buildChangeDetailsLink( PhabricatorApplicationTransaction $xaction) { return javelin_tag( 'a', array( 'href' => $xaction->getChangeDetailsURI(), 'sigil' => 'workflow', ), pht('(Show Details)')); } private function buildExtraInformationLink( PhabricatorApplicationTransaction $xaction) { $link = $xaction->renderExtraInformationLink(); if (!$link) { return null; } return phutil_tag( 'span', array( 'class' => 'phui-timeline-extra-information', ), array(" \xC2\xB7 ", $link)); } protected function shouldGroupTransactions( PhabricatorApplicationTransaction $u, PhabricatorApplicationTransaction $v) { return false; } protected function renderTransactionContent( PhabricatorApplicationTransaction $xaction) { $field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT; $engine = $this->getOrBuildEngine(); $comment = $xaction->getComment(); if ($comment) { if ($comment->getIsRemoved()) { return javelin_tag( 'span', array( 'class' => 'comment-deleted', 'sigil' => 'transaction-comment', 'meta' => array('phid' => $comment->getTransactionPHID()), ), pht( 'This comment was removed by %s.', $xaction->getHandle($comment->getAuthorPHID())->renderLink())); } else if ($comment->getIsDeleted()) { return javelin_tag( 'span', array( 'class' => 'comment-deleted', 'sigil' => 'transaction-comment', 'meta' => array('phid' => $comment->getTransactionPHID()), ), pht('This comment has been deleted.')); } else if ($xaction->hasComment()) { return javelin_tag( 'span', array( 'class' => 'transaction-comment', 'sigil' => 'transaction-comment', 'meta' => array('phid' => $comment->getTransactionPHID()), ), $engine->getOutput($comment, $field)); } else { // This is an empty, non-deleted comment. Usually this happens when // rendering previews. return null; } } return null; } private function filterHiddenTransactions(array $xactions) { foreach ($xactions as $key => $xaction) { if ($xaction->shouldHide()) { unset($xactions[$key]); } } return $xactions; } private function groupRelatedTransactions(array $xactions) { $last = null; $last_key = null; $groups = array(); foreach ($xactions as $key => $xaction) { if ($last && $this->shouldGroupTransactions($last, $xaction)) { $groups[$last_key][] = $xaction; unset($xactions[$key]); } else { $last = $xaction; $last_key = $key; } } foreach ($xactions as $key => $xaction) { $xaction->attachTransactionGroup(idx($groups, $key, array())); } return $xactions; } private function groupDisplayTransactions(array $xactions) { $groups = array(); $group = array(); foreach ($xactions as $xaction) { if ($xaction->shouldDisplayGroupWith($group)) { $group[] = $xaction; } else { if ($group) { $groups[] = $group; } $group = array($xaction); } } if ($group) { $groups[] = $group; } foreach ($groups as $key => $group) { $results = array(); // Sort transactions within the group by action strength, then by // chronological order. This makes sure that multiple actions of the // same type (like a close, then a reopen) render in the order they // were performed. $strength_groups = mgroup($group, 'getActionStrength'); krsort($strength_groups); foreach ($strength_groups as $strength_group) { foreach (msort($strength_group, 'getID') as $xaction) { $results[] = $xaction; } } $groups[$key] = $results; } return $groups; } private function renderEvent( PhabricatorApplicationTransaction $xaction, array $group) { $viewer = $this->getViewer(); $event = id(new PHUITimelineEventView()) ->setViewer($viewer) ->setAuthorPHID($xaction->getAuthorPHID()) ->setTransactionPHID($xaction->getPHID()) ->setUserHandle($xaction->getHandle($xaction->getAuthorPHID())) ->setIcon($xaction->getIcon()) ->setColor($xaction->getColor()) ->setHideCommentOptions($this->getHideCommentOptions()) ->setIsSilent($xaction->getIsSilentTransaction()) - ->setIsMFA($xaction->getIsMFATransaction()); + ->setIsMFA($xaction->getIsMFATransaction()) + ->setIsLockOverride($xaction->getIsLockOverrideTransaction()); list($token, $token_removed) = $xaction->getToken(); if ($token) { $event->setToken($token, $token_removed); } if (!$this->shouldSuppressTitle($xaction, $group)) { if ($this->renderAsFeed) { $title = $xaction->getTitleForFeed(); } else { $title = $xaction->getTitle(); } if ($xaction->hasChangeDetails()) { if (!$this->isPreview) { $details = $this->buildChangeDetailsLink($xaction); $title = array( $title, ' ', $details, ); } } if (!$this->isPreview) { $more = $this->buildExtraInformationLink($xaction); if ($more) { $title = array($title, ' ', $more); } } $event->setTitle($title); } if ($this->isPreview) { $event->setIsPreview(true); } else { $event ->setDateCreated($xaction->getDateCreated()) ->setContentSource($xaction->getContentSource()) ->setAnchor($xaction->getID()); } $transaction_type = $xaction->getTransactionType(); $comment_type = PhabricatorTransactions::TYPE_COMMENT; $is_normal_comment = ($transaction_type == $comment_type); if ($this->getShowEditActions() && !$this->isPreview && $is_normal_comment) { $has_deleted_comment = $xaction->getComment() && $xaction->getComment()->getIsDeleted(); $has_removed_comment = $xaction->getComment() && $xaction->getComment()->getIsRemoved(); if ($xaction->getCommentVersion() > 1 && !$has_removed_comment) { $event->setIsEdited(true); } if (!$has_removed_comment) { $event->setIsNormalComment(true); } // If we have a place for quoted text to go and this is a quotable // comment, pass the quote target ID to the event view. if ($this->getQuoteTargetID()) { if ($xaction->hasComment()) { if (!$has_removed_comment && !$has_deleted_comment) { $event->setQuoteTargetID($this->getQuoteTargetID()); $event->setQuoteRef($this->getQuoteRef()); } } } $can_edit = PhabricatorPolicyCapability::CAN_EDIT; if ($xaction->hasComment() || $has_deleted_comment) { $has_edit_capability = PhabricatorPolicyFilter::hasCapability( $viewer, $xaction, $can_edit); if ($has_edit_capability && !$has_removed_comment) { $event->setIsEditable(true); } if ($has_edit_capability || $viewer->getIsAdmin()) { if (!$has_removed_comment) { $event->setIsRemovable(true); } } } } $comment = $this->renderTransactionContent($xaction); if ($comment) { $event->appendChild($comment); } return $event; } private function shouldSuppressTitle( PhabricatorApplicationTransaction $xaction, array $group) { // This is a little hard-coded, but we don't have any other reasonable // cases for now. Suppress "commented on" if there are other actions in // the display group. if (count($group) > 1) { $type_comment = PhabricatorTransactions::TYPE_COMMENT; if ($xaction->getTransactionType() == $type_comment) { return true; } } return false; } } diff --git a/src/docs/user/configuration/configuring_outbound_email.diviner b/src/docs/user/configuration/configuring_outbound_email.diviner index 4d18ba0eb2..6f5212680e 100644 --- a/src/docs/user/configuration/configuring_outbound_email.diviner +++ b/src/docs/user/configuration/configuring_outbound_email.diviner @@ -1,441 +1,454 @@ @title Configuring Outbound Email @group config Instructions for configuring Phabricator to send email and other types of messages, like text messages. Overview ======== Phabricator sends outbound messages through "mailers". Most mailers send email and most messages are email messages, but mailers may also send other types of messages (like text messages). Phabricator can send outbound messages through multiple different mailers, including a local mailer or various third-party services. Options include: | Send Mail With | Setup | Cost | Inbound | Media | Notes | |----------------|-------|------|---------|-------|-------| | Postmark | Easy | Cheap | Yes | Email | Recommended | | Mailgun | Easy | Cheap | Yes | Email | Recommended | | Amazon SES | Easy | Cheap | No | Email | | | SendGrid | Medium | Cheap | Yes | Email | | | Twilio | Easy | Cheap | No | SMS | Recommended | | Amazon SNS | Easy | Cheap | No | SMS | Recommended | | External SMTP | Medium | Varies | No | Email | Gmail, etc. | | Local SMTP | Hard | Free | No | Email | sendmail, postfix, etc | | Custom | Hard | Free | No | All | Write a custom mailer. | | Drop in a Hole | Easy | Free | No | All | Drops mail in a deep, dark hole. | See below for details on how to select and configure mail delivery for each mailer. For email, Postmark or Mailgun are recommended because they make it easy to set up inbound and outbound mail and have good track records in our production services. Other services will also generally work well, but they may be more difficult to set up. For SMS, Twilio or SNS are recommended. They're also your only upstream options. If you have some internal mail or messaging service you'd like to use you can also write a custom mailer, but this requires digging into the code. Phabricator sends mail in the background, so the daemons need to be running for it to be able to deliver mail. You should receive setup warnings if they are not. For more information on using daemons, see @{article:Managing Daemons with phd}. -Basics -====== - -Before configuring outbound mail, you should first set up -`metamta.default-address` in Configuration. This determines where mail is sent -"From" by default. - -If your domain is `example.org`, set this to something -like `noreply@example.org`. - -Ideally, this should be a valid, deliverable address that doesn't bounce if -users accidentally send mail to it. +Outbound "From" and "To" Addresses +================================== + +When Phabricator sends outbound mail, it must select some "From" address to +send mail from, since mailers require this. + +When mail only has "CC" recipients, Phabricator generates a dummy "To" address, +since some mailers require this and some users write mail rules that depend +on whether they appear in the "To" or "CC" line. + +In both cases, the address should ideally correspond to a valid, deliverable +mailbox that accepts the mail and then simply discards it. If the address is +not valid, some outbound mail will bounce, and users will receive bounces when +they "Reply All" even if the other recipients for the message are valid. In +contrast, if the address is a real user address, that user will receive a lot +of mail they probably don't want. + +If you plan to configure //inbound// mail later, you usually don't need to do +anything. Phabricator will automatically create a `noreply@` mailbox which +works the right way (accepts and discards all mail it receives) and +automatically use it when generating addresses. + +If you don't plan to configure inbound mail, you may need to configure an +address for Phabricator to use. You can do this by setting +`metamta.default-address`. Configuring Mailers =================== Configure one or more mailers by listing them in the the `cluster.mailers` configuration option. Most installs only need to configure one mailer, but you can configure multiple mailers to provide greater availability in the event of a service disruption. A valid `cluster.mailers` configuration looks something like this: ```lang=json [ { "key": "mycompany-mailgun", "type": "mailgun", "options": { "domain": "mycompany.com", "api-key": "..." } }, ... ] ``` The supported keys for each mailer are: - `key`: Required string. A unique name for this mailer. - `type`: Required string. Identifies the type of mailer. See below for options. - `priority`: Optional string. Advanced option which controls load balancing and failover behavior. See below for details. - `options`: Optional map. Additional options for the mailer type. - `inbound`: Optional bool. Use `false` to prevent this mailer from being used to receive inbound mail. - `outbound`: Optional bool. Use `false` to prevent this mailer from being used to send outbound mail. - `media`: Optional list. Some mailers support delivering multiple types of messages (like Email and SMS). If you want to configure a mailer to support only a subset of possible message types, list only those message types. Normally, you do not need to configure this. See below for a list of media types. The `type` field can be used to select these mailer services: - `mailgun`: Use Mailgun. - `ses`: Use Amazon SES. - `sendgrid`: Use SendGrid. - `postmark`: Use Postmark. - `twilio`: Use Twilio. - `sns`: Use Amazon SNS. It also supports these local mailers: - `sendmail`: Use the local `sendmail` binary. - `smtp`: Connect directly to an SMTP server. - `test`: Internal mailer for testing. Does not send mail. You can also write your own mailer by extending `PhabricatorMailAdapter`. The `media` field supports these values: - `email`: Configure this mailer for email. - `sms`: Configure this mailer for SMS. Once you've selected a mailer, find the corresponding section below for instructions on configuring it. Setting Complex Configuration ============================= Mailers can not be edited from the web UI. If mailers could be edited from the web UI, it would give an attacker who compromised an administrator account a lot of power: they could redirect mail to a server they control and then intercept mail for any other account, including password reset mail. For more information about locked configuration options, see @{article:Configuration Guide: Locked and Hidden Configuration}. Setting `cluster.mailers` from the command line using `bin/config set` can be tricky because of shell escaping. The easiest way to do it is to use the `--stdin` flag. First, put your desired configuration in a file like this: ```lang=json, name=mailers.json [ { "key": "test-mailer", "type": "test" } ] ``` Then set the value like this: ``` phabricator/ $ ./bin/config set --stdin cluster.mailers < mailers.json ``` For alternatives and more information on configuration, see @{article:Configuration User Guide: Advanced Configuration} Mailer: Postmark ================ | Media | Email |---------| | Inbound | Yes |---------| Postmark is a third-party email delivery service. You can learn more at . To use this mailer, set `type` to `postmark`, then configure these `options`: - `access-token`: Required string. Your Postmark access token. - `inbound-addresses`: Optional list. Address ranges which you will accept inbound Postmark HTTP webook requests from. The default address list is preconfigured with Postmark's address range, so you generally will not need to set or adjust it. The option accepts a list of CIDR ranges, like `1.2.3.4/16` (IPv4) or `::ffff:0:0/96` (IPv6). The default ranges are: ```lang=json [ "50.31.156.6/32", "50.31.156.77/32", "18.217.206.57/32" ] ``` The default address ranges were last updated in January 2019, and were documented at: Mailer: Mailgun =============== | Media | Email |---------| | Inbound | Yes |---------| Mailgun is a third-party email delivery service. You can learn more at . Mailgun is easy to configure and works well. To use this mailer, set `type` to `mailgun`, then configure these `options`: - `api-key`: Required string. Your Mailgun API key. - `domain`: Required string. Your Mailgun domain. Mailer: Amazon SES ================== | Media | Email |---------| | Inbound | No |---------| Amazon SES is Amazon's cloud email service. You can learn more at . To use this mailer, set `type` to `ses`, then configure these `options`: - `access-key`: Required string. Your Amazon SES access key. - `secret-key`: Required string. Your Amazon SES secret key. - `endpoint`: Required string. Your Amazon SES endpoint. NOTE: Amazon SES **requires you to verify your "From" address**. Configure which "From" address to use by setting `metamta.default-address` in your config, then follow the Amazon SES verification process to verify it. You won't be able to send email until you do this! Mailer: Twilio ================== | Media | SMS |---------| | Inbound | No |---------| Twilio is a third-party notification service. You can learn more at . To use this mailer, set `type` to `twilio`, then configure these options: - `account-sid`: Your Twilio Account SID. - `auth-token`: Your Twilio Auth Token. - `from-number`: Number to send text messages from, in E.164 format (like `+15551237890`). Mailer: Amazon SNS ================== | Media | SMS |---------| | Inbound | No |---------| Amazon SNS is Amazon's cloud notification service. You can learn more at . Note that this mailer is only able to send SMS messages, not emails. To use this mailer, set `type` to `sns`, then configure these options: - `access-key`: Required string. Your Amazon SNS access key. - `secret-key`: Required string. Your Amazon SNS secret key. - `endpoint`: Required string. Your Amazon SNS endpoint. - `region`: Required string. Your Amazon SNS region. You can find the correct `region` value for your endpoint in the SNS documentation. Mailer: SendGrid ================ | Media | Email |---------| | Inbound | Yes |---------| SendGrid is a third-party email delivery service. You can learn more at . You can configure SendGrid in two ways: you can send via SMTP or via the REST API. To use SMTP, configure Phabricator to use an `smtp` mailer. To use the REST API mailer, set `type` to `sendgrid`, then configure these `options`: - `api-key`: Required string. Your SendGrid API key. Older versions of the SendGrid API used different sets of credentials, including an "API User". Make sure you're configuring your "API Key". Mailer: Sendmail ================ | Media | Email |---------| | Inbound | Requires Configuration |---------| This requires a `sendmail` binary to be installed on the system. Most MTAs (e.g., sendmail, qmail, postfix) should install one for you, but your machine may not have one installed by default. For install instructions, consult the documentation for your favorite MTA. Since you'll be sending the mail yourself, you are subject to things like SPF rules, blackholes, and MTA configuration which are beyond the scope of this document. If you can already send outbound email from the command line or know how to configure it, this option is straightforward. If you have no idea how to do any of this, strongly consider using Postmark or Mailgun instead. To use this mailer, set `type` to `sendmail`. There are no `options` to configure. Mailer: SMTP ============ | Media | Email |---------| | Inbound | Requires Configuration |---------| You can use this adapter to send mail via an external SMTP server, like Gmail. To use this mailer, set `type` to `smtp`, then configure these `options`: - `host`: Required string. The hostname of your SMTP server. - `port`: Optional int. The port to connect to on your SMTP server. - `user`: Optional string. Username used for authentication. - `password`: Optional string. Password for authentication. - `protocol`: Optional string. Set to `tls` or `ssl` if necessary. Use `ssl` for Gmail. Disable Mail ============ | Media | All |---------| | Inbound | No |---------| To disable mail, just don't configure any mailers. (You can safely ignore the setup warning reminding you to set up mailers if you don't plan to configure any.) Testing and Debugging Outbound Email ==================================== You can use the `bin/mail` utility to test, debug, and examine outbound mail. In particular: phabricator/ $ ./bin/mail list-outbound # List outbound mail. phabricator/ $ ./bin/mail show-outbound # Show details about messages. phabricator/ $ ./bin/mail send-test # Send test messages. Run `bin/mail help ` for more help on using these commands. By default, `bin/mail send-test` sends email messages, but you can use the `--type` flag to send different types of messages. You can monitor daemons using the Daemon Console (`/daemon/`, or click **Daemon Console** from the homepage). Priorities ========== By default, Phabricator will try each mailer in order: it will try the first mailer first. If that fails (for example, because the service is not available at the moment) it will try the second mailer, and so on. If you want to load balance between multiple mailers instead of using one as a primary, you can set `priority`. Phabricator will start with mailers in the highest priority group and go through them randomly, then fall back to the next group. For example, if you have two SMTP servers and you want to balance requests between them and then fall back to Mailgun if both fail, configure priorities like this: ```lang=json [ { "key": "smtp-uswest", "type": "smtp", "priority": 300, "options": "..." }, { "key": "smtp-useast", "type": "smtp", "priority": 300, "options": "..." }, { "key": "mailgun-fallback", "type": "mailgun", "options": "..." } } ``` Phabricator will start with servers in the highest priority group (the group with the **largest** `priority` number). In this example, the highest group is `300`, which has the two SMTP servers. They'll be tried in random order first. If both fail, Phabricator will move on to the next priority group. In this example, there are no other priority groups. If it still hasn't sent the mail, Phabricator will try servers which are not in any priority group, in the configured order. In this example there is only one such server, so it will try to send via Mailgun. Next Steps ========== Continue by: - @{article:Configuring Inbound Email} so users can reply to email they receive about revisions and tasks to interact with them; or - learning about daemons with @{article:Managing Daemons with phd}; or - returning to the @{article:Configuration Guide}. diff --git a/src/docs/user/userguide/diviner.diviner b/src/docs/user/userguide/diviner.diviner index e94c33d275..01484be14c 100644 --- a/src/docs/user/userguide/diviner.diviner +++ b/src/docs/user/userguide/diviner.diviner @@ -1,84 +1,95 @@ @title Diviner User Guide @group userguide Using Diviner, a documentation generator. -= Overview = +Overview +======== -NOTE: Diviner is new and not yet generally useful. +Diviner is an application for creating technical documentation. -= Generating Documentation = +This article is maintained in a text file in the Phabricator repository and +generated into the display document you are currently reading using Diviner. + +Beyond generating articles, Diviner can also analyze source code and generate +documentation about classes, methods, and other primitives. + + +Generating Documentation +======================== To generate documentation, run: phabricator/ $ ./bin/diviner generate --book -= .book Files = + +Diviner ".book" Files +===================== Diviner documentation books are configured using JSON `.book` files, which look like this: name=example.book { "name" : "example", "title" : "Example Documentation", "short" : "Example Docs", "root" : ".", "uri.source" : "http://example.com/diffusion/X/browse/master/%f$%l", "rules" : { "(\\.diviner$)" : "DivinerArticleAtomizer" }, "exclude" : [ "(^externals/)", "(^scripts/)", "(^support/)" ], "groups" : { "forward" : { "name" : "Doing Stuff" }, "reverse" : { "name" : "Undoing Stuff" } } } The properties in this file are: - `name`: Required. Short, unique name to identify the documentation book. This will be used in URIs, so it should not have special characters. Good names are things like `"example"` or `"libcabin"`. - `root`: Required. The root directory (relative to the `.book` file) which documentation should be generated from. Often this will be a value like `"../../"`, to specify the project root (for example, if the `.book` file is in `project/src/docs/example.book`, the value `"../../"` would generate documentation from the `project/` directory. - `title`: Optional. Full human-readable title of the documentation book. This is used when there's plenty of display space and should completely describe the book. Good titles are things like `"Example Documentation"`, or `"libcabin Developer Documentation"`. - `short`: Optional. Shorter version of the title for use when display space is limited (for example, in navigation breadcrumbs). If omitted, the full title is used. Good short titles are things like `"Example Docs"` or `"libcabin Dev Docs"`. - `uri.source`: Optional. Diviner can link from the documentation to a repository browser so that you can quickly jump to the definition of a class or function. To do this, it uses a URI pattern which you specify here. Normally, this URI should point at a repository browser like Diffusion. For example, `"http://repobrowser.yourcompany.com/%f#%l"`. You can use these conversions in the URI, which will be replaced at runtime: - `%f`: Replaced with the name of the file. - `%l`: Replaced with the line number. - `%%`: Replaced with a literal `%` symbol. - `rules`: Optional. A map of regular expressions to Atomizer classes which controls which documentation generator runs on each file. If omitted, Diviner will use its default ruleset. For example, adding the key `"(\\.diviner$)"` to the map with value `"DivinerArticleAtomizer"` tells Diviner to analyze any file with a name ending in `.diviner` using the "article" atomizer. - `exclude`: Optional. A list of regular expressions matching paths which will be excluded from documentation generation for this book. For example, adding a pattern like `"(^externals/)"` or `"(^vendor/)"` will make Diviner ignore those directories. - `groups`: Optional. Describes top level organizational groups which atoms should be placed into. diff --git a/src/docs/user/userguide/owners.diviner b/src/docs/user/userguide/owners.diviner index 95a3882552..11dee8941a 100644 --- a/src/docs/user/userguide/owners.diviner +++ b/src/docs/user/userguide/owners.diviner @@ -1,174 +1,181 @@ @title Owners User Guide @group userguide Group files in a codebase into packages and define ownership. Overview ======== The Owners application allows you to group files in a codebase (or across codebases) into packages. This can make it easier to reference a module or subsystem in other applications, like Herald. Creating a Package ================== To create a package, choose a name and add some files which belong to the package. For example, you might define an "iOS Application" package by including these paths: /conf/ios/ /src/ios/ /shared/assets/mobile/ Any files in those directories are considered to be part of the package, and you can now conveniently refer to them (for example, in a Herald rule) by referring to the package instead of copy/pasting a huge regular expression into a bunch of places. If new source files are later added, or the scope of the package otherwise expands or contracts, you can edit the package definition to keep things updated. You can use "exclude" paths to ignore subdirectories which would otherwise be considered part of the package. For example, you might exclude a path like this: /conf/ios/generated/ Perhaps that directory contains some generated configuration which frequently changes, and which you aren't concerned about. After creating a package, files the package contains will be identified as belonging to the package when you look at them in Diffusion, or look at changes which affect them in Diffusion or Differential. Dominion ======== The **Dominion** option allows you to control how ownership cascades when multiple packages own a path. The dominion rules are: **Strong Dominion.** This is the default. In this mode, the package will always own all files matching its configured paths, even if another package also owns them. For example, if the package owns `a/`, it will always own `a/b/c.z` even if another package owns `a/b/`. In this case, both packages will own `a/b/c.z`. This mode prevents users from stealing files away from the package by defining more narrow ownership rules in new packages, but enforces hierarchical ownership rules. **Weak Dominion.** In this mode, the package will only own files which do not match a more specific path in another package. For example, if the package owns `a/` but another package owns `a/b/`, the package will no longer consider `a/b/c.z` to be a file it owns because another package matches the path with a more specific rule. This mode lets you to define rules without implicit hierarchical ownership, but allows users to steal files away from a package by defining a more specific package. For more details on files which match multiple packages, see "Files in Multiple Packages", below. Auto Review =========== You can configure **Auto Review** for packages. When a new code review is created in Differential which affects code in a package, the package can automatically be added as a subscriber or reviewer. The available settings allow you to take these actions: - **Review Changes**: This package will be added to reviews as a reviewer. Reviews will appear on the dashboards of package owners. - **Review Changes (Blocking)** This package will be added to reviews as a blocking reviewer. A package owner will be required to accept changes before they may land. - **Subscribe to Changes**: This package will be added to reviews as a subscriber. Owners will be notified of changes, but not required to act. If you select the **With Non-Owner Author** option for these actions, the action will not trigger if the author of the revision is a package owner. This mode may be helpful if you are using Owners mostly to make sure that someone who is qualified is involved in each change to a piece of code. If you select the **All** option for these actions, the action will always trigger even if the author is a package owner. This mode may be helpful if you are using Owners mostly to suggest reviewers. These rules do not trigger if the package has been archived. The intent of this feature is to make it easy to configure simple, reasonable behaviors. If you want more tailored or specific triggers, you can write more powerful rules by using Herald. Auditing ======== You can automatically trigger audits on unreviewed code by configuring -**Auditing**. The available settings are: +**Auditing**. The available settings allow you to select behavior based on +these conditions: - - **Disabled**: Do not trigger audits. - - **Enabled**: Trigger audits. + - **No Owner Involvement**: Triggers an audit when the commit author is not + a package owner, and no package owner reviewed an associated revision in + Differential. + - **Unreviewed Commits**: Triggers an audit when a commit has no associated + revision in Differential, or the associated revision in Differential landed + without being "Accepted". -When enabled, audits are triggered for commits which: +For example, the **Audit Commits With No Owner Involvement** option triggers +audits for commits which: - affect code owned by the package; - were not authored by a package owner; and - - were not accepted by a package owner. + - were not accepted (in Differential) by a package owner or the package + itself. Audits do not trigger if the package has been archived. The intent of this feature is to make it easy to configure simple auditing behavior. If you want more powerful auditing behavior, you can use Herald to write more sophisticated rules. Ignored Attributes ================== You can automatically exclude certain types of files, like generated files, with **Ignored Attributes**. When a package is marked as ignoring files with a particular attribute, and a file in a particular change has that attribute, the file will be ignored when computing ownership. (This feature is currently rough, only works for Differential revisions, and may not always compute the correct set of owning packages in some complex cases where it interacts with dominion rules.) Files in Multiple Packages ========================== Multiple packages may own the same file. For example, both the "Android Application" and the "iOS Application" packages might own a path like this, containing resources used by both: /shared/assets/mobile/ If both packages own this directory, files in the directory are considered to be part of both packages. Packages do not need to have claims of equal specificity to own files. For example, if you have a "Design Assets" package which owns this path: /shared/assets/ ...it will //also// own all of the files in the `mobile/` subdirectory. In this configuration, these files are part of three packages: "iOS Application", "Android Application", and "Design Assets". (You can use an "exclude" rule if you want to make a different package with a more specific claim the owner of a file or subdirectory. You can also change the **Dominion** setting for a package to let it give up ownership of paths owned by another package.) diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php index 5bc83972dd..acbbb4fbda 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php @@ -1,1283 +1,1283 @@ apis = $apis; return $this; } final public function getAnyAPI() { return head($this->getAPIs()); } final public function getMasterAPIs() { $apis = $this->getAPIs(); $results = array(); foreach ($apis as $api) { if ($api->getRef()->getIsMaster()) { $results[] = $api; } } if (!$results) { throw new PhutilArgumentUsageException( pht( 'This command only operates on database masters, but the selected '. 'database hosts do not include any masters.')); } return $results; } final public function getSingleAPI() { $apis = $this->getAPIs(); if (count($apis) == 1) { return head($apis); } throw new PhutilArgumentUsageException( pht( 'Phabricator is configured in cluster mode, with multiple database '. 'hosts. Use "--host" to specify which host you want to operate on.')); } final public function getAPIs() { return $this->apis; } final protected function isDryRun() { return $this->dryRun; } final protected function setDryRun($dry_run) { $this->dryRun = $dry_run; return $this; } final protected function isForce() { return $this->force; } final protected function setForce($force) { $this->force = $force; return $this; } public function getPatches() { return $this->patches; } public function setPatches(array $patches) { assert_instances_of($patches, 'PhabricatorStoragePatch'); $this->patches = $patches; return $this; } protected function isReadOnlyWorkflow() { return false; } public function execute(PhutilArgumentParser $args) { $this->setDryRun($args->getArg('dryrun')); $this->setForce($args->getArg('force')); if (!$this->isReadOnlyWorkflow()) { if (PhabricatorEnv::isReadOnly()) { if ($this->isForce()) { PhabricatorEnv::setReadOnly(false, null); } else { throw new PhutilArgumentUsageException( pht( 'Phabricator is currently in read-only mode. Use --force to '. 'override this mode.')); } } } return $this->didExecute($args); } public function didExecute(PhutilArgumentParser $args) {} private function loadSchemata(PhabricatorStorageManagementAPI $api) { $query = id(new PhabricatorConfigSchemaQuery()); $ref = $api->getRef(); $ref_key = $ref->getRefKey(); $query->setAPIs(array($api)); $query->setRefs(array($ref)); $actual = $query->loadActualSchemata(); $expect = $query->loadExpectedSchemata(); $comp = $query->buildComparisonSchemata($expect, $actual); return array( $comp[$ref_key], $expect[$ref_key], $actual[$ref_key], ); } final protected function adjustSchemata( PhabricatorStorageManagementAPI $api, $unsafe) { $lock = $this->lock($api); try { $err = $this->doAdjustSchemata($api, $unsafe); // Analyze tables if we're not doing a dry run and adjustments are either // all clear or have minor errors like surplus tables. if (!$this->dryRun) { $should_analyze = (($err == 0) || ($err == 2)); if ($should_analyze) { $this->analyzeTables($api); } } } catch (Exception $ex) { $lock->unlock(); throw $ex; } $lock->unlock(); return $err; } final private function doAdjustSchemata( PhabricatorStorageManagementAPI $api, $unsafe) { $console = PhutilConsole::getConsole(); $console->writeOut( "%s\n", pht( 'Verifying database schemata on "%s"...', $api->getRef()->getRefKey())); list($adjustments, $errors) = $this->findAdjustments($api); if (!$adjustments) { $console->writeOut( "%s\n", pht('Found no adjustments for schemata.')); return $this->printErrors($errors, 0); } if (!$this->force && !$api->isCharacterSetAvailable('utf8mb4')) { $message = pht( "You have an old version of MySQL (older than 5.5) which does not ". "support the utf8mb4 character set. We strongly recommend upgrading ". "to 5.5 or newer.\n\n". "If you apply adjustments now and later update MySQL to 5.5 or newer, ". "you'll need to apply adjustments again (and they will take a long ". "time).\n\n". "You can exit this workflow, update MySQL now, and then run this ". "workflow again. This is recommended, but may cause a lot of downtime ". "right now.\n\n". "You can exit this workflow, continue using Phabricator without ". "applying adjustments, update MySQL at a later date, and then run ". "this workflow again. This is also a good approach, and will let you ". "delay downtime until later.\n\n". "You can proceed with this workflow, and then optionally update ". "MySQL at a later date. After you do, you'll need to apply ". "adjustments again.\n\n". "For more information, see \"Managing Storage Adjustments\" in ". "the documentation."); $console->writeOut( "\n** %s **\n\n%s\n", pht('OLD MySQL VERSION'), phutil_console_wrap($message)); $prompt = pht('Continue with old MySQL version?'); if (!phutil_console_confirm($prompt, $default_no = true)) { return; } } $table = id(new PhutilConsoleTable()) ->addColumn('database', array('title' => pht('Database'))) ->addColumn('table', array('title' => pht('Table'))) ->addColumn('name', array('title' => pht('Name'))) ->addColumn('info', array('title' => pht('Issues'))); foreach ($adjustments as $adjust) { $info = array(); foreach ($adjust['issues'] as $issue) { $info[] = PhabricatorConfigStorageSchema::getIssueName($issue); } $table->addRow(array( 'database' => $adjust['database'], 'table' => idx($adjust, 'table'), 'name' => idx($adjust, 'name'), 'info' => implode(', ', $info), )); } $console->writeOut("\n\n"); $table->draw(); if ($this->dryRun) { $console->writeOut( "%s\n", pht('DRYRUN: Would apply adjustments.')); return 0; } else if ($this->didInitialize) { // If we just initialized the database, continue without prompting. This // is nicer for first-time setup and there's no reasonable reason any // user would ever answer "no" to the prompt against an empty schema. } else if (!$this->force) { $console->writeOut( "\n%s\n", pht( "Found %s adjustment(s) to apply, detailed above.\n\n". "You can review adjustments in more detail from the web interface, ". "in Config > Database Status. To better understand the adjustment ". "workflow, see \"Managing Storage Adjustments\" in the ". "documentation.\n\n". "MySQL needs to copy table data to make some adjustments, so these ". "migrations may take some time.", phutil_count($adjustments))); $prompt = pht('Apply these schema adjustments?'); if (!phutil_console_confirm($prompt, $default_no = true)) { return 1; } } $console->writeOut( "%s\n", pht('Applying schema adjustments...')); $conn = $api->getConn(null); if ($unsafe) { queryfx($conn, 'SET SESSION sql_mode = %s', ''); } else { queryfx($conn, 'SET SESSION sql_mode = %s', 'STRICT_ALL_TABLES'); } $failed = array(); // We make changes in several phases. $phases = array( // Drop surplus autoincrements. This allows us to drop primary keys on // autoincrement columns. 'drop_auto', // Drop all keys we're going to adjust. This prevents them from // interfering with column changes. 'drop_keys', // Apply all database, table, and column changes. 'main', // Restore adjusted keys. 'add_keys', // Add missing autoincrements. 'add_auto', ); $bar = id(new PhutilConsoleProgressBar()) ->setTotal(count($adjustments) * count($phases)); foreach ($phases as $phase) { foreach ($adjustments as $adjust) { try { switch ($adjust['kind']) { case 'database': if ($phase == 'main') { queryfx( $conn, 'ALTER DATABASE %T CHARACTER SET = %s COLLATE = %s', $adjust['database'], $adjust['charset'], $adjust['collation']); } break; case 'table': if ($phase == 'main') { queryfx( $conn, 'ALTER TABLE %T.%T COLLATE = %s, ENGINE = %s', $adjust['database'], $adjust['table'], $adjust['collation'], $adjust['engine']); } break; case 'column': $apply = false; $auto = false; $new_auto = idx($adjust, 'auto'); if ($phase == 'drop_auto') { if ($new_auto === false) { $apply = true; $auto = false; } } else if ($phase == 'main') { $apply = true; if ($new_auto === false) { $auto = false; } else { $auto = $adjust['is_auto']; } } else if ($phase == 'add_auto') { if ($new_auto === true) { $apply = true; $auto = true; } } if ($apply) { $parts = array(); if ($auto) { $parts[] = qsprintf( $conn, 'AUTO_INCREMENT'); } if ($adjust['charset']) { switch ($adjust['charset']) { case 'binary': $charset_value = qsprintf($conn, 'binary'); break; case 'utf8': $charset_value = qsprintf($conn, 'utf8'); break; case 'utf8mb4': $charset_value = qsprintf($conn, 'utf8mb4'); break; default: throw new Exception( pht( 'Unsupported character set "%s".', $adjust['charset'])); } switch ($adjust['collation']) { case 'binary': $collation_value = qsprintf($conn, 'binary'); break; case 'utf8_general_ci': $collation_value = qsprintf($conn, 'utf8_general_ci'); break; case 'utf8mb4_bin': $collation_value = qsprintf($conn, 'utf8mb4_bin'); break; case 'utf8mb4_unicode_ci': $collation_value = qsprintf($conn, 'utf8mb4_unicode_ci'); break; default: throw new Exception( pht( 'Unsupported collation set "%s".', $adjust['collation'])); } $parts[] = qsprintf( $conn, 'CHARACTER SET %Q COLLATE %Q', $charset_value, $collation_value); } if ($parts) { $parts = qsprintf($conn, '%LJ', $parts); } else { $parts = qsprintf($conn, ''); } if ($adjust['nullable']) { $nullable = qsprintf($conn, 'NULL'); } else { $nullable = qsprintf($conn, 'NOT NULL'); } // TODO: We're using "%Z" here for the column type, which is // technically unsafe. It would be nice to be able to use "%Q" // instead, but this requires a fair amount of legwork to // enumerate all column types. queryfx( $conn, 'ALTER TABLE %T.%T MODIFY %T %Z %Q %Q', $adjust['database'], $adjust['table'], $adjust['name'], $adjust['type'], $parts, $nullable); } break; case 'key': if (($phase == 'drop_keys') && $adjust['exists']) { if ($adjust['name'] == 'PRIMARY') { - $key_name = 'PRIMARY KEY'; + $key_name = qsprintf($conn, 'PRIMARY KEY'); } else { $key_name = qsprintf($conn, 'KEY %T', $adjust['name']); } queryfx( $conn, 'ALTER TABLE %T.%T DROP %Q', $adjust['database'], $adjust['table'], $key_name); } if (($phase == 'add_keys') && $adjust['keep']) { // Different keys need different creation syntax. Notable // special cases are primary keys and fulltext keys. if ($adjust['name'] == 'PRIMARY') { $key_name = qsprintf($conn, 'PRIMARY KEY'); } else if ($adjust['indexType'] == 'FULLTEXT') { $key_name = qsprintf($conn, 'FULLTEXT %T', $adjust['name']); } else { if ($adjust['unique']) { $key_name = qsprintf( $conn, 'UNIQUE KEY %T', $adjust['name']); } else { $key_name = qsprintf( $conn, '/* NONUNIQUE */ KEY %T', $adjust['name']); } } queryfx( $conn, 'ALTER TABLE %T.%T ADD %Q (%LK)', $adjust['database'], $adjust['table'], $key_name, $adjust['columns']); } break; default: throw new Exception( pht('Unknown schema adjustment kind "%s"!', $adjust['kind'])); } } catch (AphrontQueryException $ex) { $failed[] = array($adjust, $ex); } $bar->update(1); } } $bar->done(); if (!$failed) { $console->writeOut( "%s\n", pht('Completed applying all schema adjustments.')); $err = 0; } else { $table = id(new PhutilConsoleTable()) ->addColumn('target', array('title' => pht('Target'))) ->addColumn('error', array('title' => pht('Error'))); foreach ($failed as $failure) { list($adjust, $ex) = $failure; $pieces = array_select_keys( $adjust, array('database', 'table', 'name')); $pieces = array_filter($pieces); $target = implode('.', $pieces); $table->addRow( array( 'target' => $target, 'error' => $ex->getMessage(), )); } $console->writeOut("\n"); $table->draw(); $console->writeOut( "\n%s\n", pht('Failed to make some schema adjustments, detailed above.')); $console->writeOut( "%s\n", pht( 'For help troubleshooting adjustments, see "Managing Storage '. 'Adjustments" in the documentation.')); $err = 1; } return $this->printErrors($errors, $err); } private function findAdjustments( PhabricatorStorageManagementAPI $api) { list($comp, $expect, $actual) = $this->loadSchemata($api); $issue_charset = PhabricatorConfigStorageSchema::ISSUE_CHARSET; $issue_collation = PhabricatorConfigStorageSchema::ISSUE_COLLATION; $issue_columntype = PhabricatorConfigStorageSchema::ISSUE_COLUMNTYPE; $issue_surpluskey = PhabricatorConfigStorageSchema::ISSUE_SURPLUSKEY; $issue_missingkey = PhabricatorConfigStorageSchema::ISSUE_MISSINGKEY; $issue_columns = PhabricatorConfigStorageSchema::ISSUE_KEYCOLUMNS; $issue_unique = PhabricatorConfigStorageSchema::ISSUE_UNIQUE; $issue_longkey = PhabricatorConfigStorageSchema::ISSUE_LONGKEY; $issue_auto = PhabricatorConfigStorageSchema::ISSUE_AUTOINCREMENT; $issue_engine = PhabricatorConfigStorageSchema::ISSUE_ENGINE; $adjustments = array(); $errors = array(); foreach ($comp->getDatabases() as $database_name => $database) { foreach ($this->findErrors($database) as $issue) { $errors[] = array( 'database' => $database_name, 'issue' => $issue, ); } $expect_database = $expect->getDatabase($database_name); $actual_database = $actual->getDatabase($database_name); if (!$expect_database || !$actual_database) { // If there's a real issue here, skip this stuff. continue; } if ($actual_database->getAccessDenied()) { // If we can't access the database, we can't access the tables either. continue; } $issues = array(); if ($database->hasIssue($issue_charset)) { $issues[] = $issue_charset; } if ($database->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($issues) { $adjustments[] = array( 'kind' => 'database', 'database' => $database_name, 'issues' => $issues, 'charset' => $expect_database->getCharacterSet(), 'collation' => $expect_database->getCollation(), ); } foreach ($database->getTables() as $table_name => $table) { foreach ($this->findErrors($table) as $issue) { $errors[] = array( 'database' => $database_name, 'table' => $table_name, 'issue' => $issue, ); } $expect_table = $expect_database->getTable($table_name); $actual_table = $actual_database->getTable($table_name); if (!$expect_table || !$actual_table) { continue; } $issues = array(); if ($table->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($table->hasIssue($issue_engine)) { $issues[] = $issue_engine; } if ($issues) { $adjustments[] = array( 'kind' => 'table', 'database' => $database_name, 'table' => $table_name, 'issues' => $issues, 'collation' => $expect_table->getCollation(), 'engine' => $expect_table->getEngine(), ); } foreach ($table->getColumns() as $column_name => $column) { foreach ($this->findErrors($column) as $issue) { $errors[] = array( 'database' => $database_name, 'table' => $table_name, 'name' => $column_name, 'issue' => $issue, ); } $expect_column = $expect_table->getColumn($column_name); $actual_column = $actual_table->getColumn($column_name); if (!$expect_column || !$actual_column) { continue; } $issues = array(); if ($column->hasIssue($issue_collation)) { $issues[] = $issue_collation; } if ($column->hasIssue($issue_charset)) { $issues[] = $issue_charset; } if ($column->hasIssue($issue_columntype)) { $issues[] = $issue_columntype; } if ($column->hasIssue($issue_auto)) { $issues[] = $issue_auto; } if ($issues) { if ($expect_column->getCharacterSet() === null) { // For non-text columns, we won't be specifying a collation or // character set. $charset = null; $collation = null; } else { $charset = $expect_column->getCharacterSet(); $collation = $expect_column->getCollation(); } $adjustment = array( 'kind' => 'column', 'database' => $database_name, 'table' => $table_name, 'name' => $column_name, 'issues' => $issues, 'collation' => $collation, 'charset' => $charset, 'type' => $expect_column->getColumnType(), // NOTE: We don't adjust column nullability because it is // dangerous, so always use the current nullability. 'nullable' => $actual_column->getNullable(), // NOTE: This always stores the current value, because we have // to make these updates separately. 'is_auto' => $actual_column->getAutoIncrement(), ); if ($column->hasIssue($issue_auto)) { $adjustment['auto'] = $expect_column->getAutoIncrement(); } $adjustments[] = $adjustment; } } foreach ($table->getKeys() as $key_name => $key) { foreach ($this->findErrors($key) as $issue) { $errors[] = array( 'database' => $database_name, 'table' => $table_name, 'name' => $key_name, 'issue' => $issue, ); } $expect_key = $expect_table->getKey($key_name); $actual_key = $actual_table->getKey($key_name); $issues = array(); $keep_key = true; if ($key->hasIssue($issue_surpluskey)) { $issues[] = $issue_surpluskey; $keep_key = false; } if ($key->hasIssue($issue_missingkey)) { $issues[] = $issue_missingkey; } if ($key->hasIssue($issue_columns)) { $issues[] = $issue_columns; } if ($key->hasIssue($issue_unique)) { $issues[] = $issue_unique; } // NOTE: We can't really fix this, per se, but we may need to remove // the key to change the column type. In the best case, the new // column type won't be overlong and recreating the key really will // fix the issue. In the worst case, we get the right column type and // lose the key, which is still better than retaining the key having // the wrong column type. if ($key->hasIssue($issue_longkey)) { $issues[] = $issue_longkey; } if ($issues) { $adjustment = array( 'kind' => 'key', 'database' => $database_name, 'table' => $table_name, 'name' => $key_name, 'issues' => $issues, 'exists' => (bool)$actual_key, 'keep' => $keep_key, ); if ($keep_key) { $adjustment += array( 'columns' => $expect_key->getColumnNames(), 'unique' => $expect_key->getUnique(), 'indexType' => $expect_key->getIndexType(), ); } $adjustments[] = $adjustment; } } } } return array($adjustments, $errors); } private function findErrors(PhabricatorConfigStorageSchema $schema) { $result = array(); foreach ($schema->getLocalIssues() as $issue) { $status = PhabricatorConfigStorageSchema::getIssueStatus($issue); if ($status == PhabricatorConfigStorageSchema::STATUS_FAIL) { $result[] = $issue; } } return $result; } private function printErrors(array $errors, $default_return) { if (!$errors) { return $default_return; } $console = PhutilConsole::getConsole(); $table = id(new PhutilConsoleTable()) ->addColumn('target', array('title' => pht('Target'))) ->addColumn('error', array('title' => pht('Error'))); $any_surplus = false; $all_surplus = true; $any_access = false; $all_access = true; foreach ($errors as $error) { $pieces = array_select_keys( $error, array('database', 'table', 'name')); $pieces = array_filter($pieces); $target = implode('.', $pieces); $name = PhabricatorConfigStorageSchema::getIssueName($error['issue']); $issue = $error['issue']; if ($issue === PhabricatorConfigStorageSchema::ISSUE_SURPLUS) { $any_surplus = true; } else { $all_surplus = false; } if ($issue === PhabricatorConfigStorageSchema::ISSUE_ACCESSDENIED) { $any_access = true; } else { $all_access = false; } $table->addRow( array( 'target' => $target, 'error' => $name, )); } $console->writeOut("\n"); $table->draw(); $console->writeOut("\n"); $message = array(); if ($all_surplus) { $message[] = pht( 'You have surplus schemata (extra tables or columns which Phabricator '. 'does not expect). For information on resolving these '. 'issues, see the "Surplus Schemata" section in the "Managing Storage '. 'Adjustments" article in the documentation.'); } else if ($all_access) { $message[] = pht( 'The user you are connecting to MySQL with does not have the correct '. 'permissions, and can not access some databases or tables that it '. 'needs to be able to access. GRANT the user additional permissions.'); } else { $message[] = pht( 'The schemata have errors (detailed above) which the adjustment '. 'workflow can not fix.'); if ($any_access) { $message[] = pht( 'Some of these errors are caused by access control problems. '. 'The user you are connecting with does not have permission to see '. 'all of the database or tables that Phabricator uses. You need to '. 'GRANT the user more permission, or use a different user.'); } if ($any_surplus) { $message[] = pht( 'Some of these errors are caused by surplus schemata (extra '. 'tables or columns which Phabricator does not expect). These are '. 'not serious. For information on resolving these issues, see the '. '"Surplus Schemata" section in the "Managing Storage Adjustments" '. 'article in the documentation.'); } $message[] = pht( 'If you are not developing Phabricator itself, report this issue to '. 'the upstream.'); $message[] = pht( 'If you are developing Phabricator, these errors usually indicate '. 'that your schema specifications do not agree with the schemata your '. 'code actually builds.'); } $message = implode("\n\n", $message); if ($all_surplus) { $console->writeOut( "** %s **\n\n%s\n", pht('SURPLUS SCHEMATA'), phutil_console_wrap($message)); } else if ($all_access) { $console->writeOut( "** %s **\n\n%s\n", pht('ACCESS DENIED'), phutil_console_wrap($message)); } else { $console->writeOut( "** %s **\n\n%s\n", pht('SCHEMATA ERRORS'), phutil_console_wrap($message)); } return 2; } final protected function upgradeSchemata( array $apis, $apply_only = null, $no_quickstart = false, $init_only = false) { $locks = array(); foreach ($apis as $api) { $locks[] = $this->lock($api); } try { $this->doUpgradeSchemata($apis, $apply_only, $no_quickstart, $init_only); } catch (Exception $ex) { foreach ($locks as $lock) { $lock->unlock(); } throw $ex; } foreach ($locks as $lock) { $lock->unlock(); } } final private function doUpgradeSchemata( array $apis, $apply_only, $no_quickstart, $init_only) { $patches = $this->patches; $is_dryrun = $this->dryRun; $api_map = array(); foreach ($apis as $api) { $api_map[$api->getRef()->getRefKey()] = $api; } foreach ($api_map as $ref_key => $api) { $applied = $api->getAppliedPatches(); $needs_init = ($applied === null); if (!$needs_init) { continue; } if ($is_dryrun) { echo tsprintf( "%s\n", pht( 'DRYRUN: Storage on host "%s" does not exist yet, so it '. 'would be created.', $ref_key)); continue; } if ($apply_only) { throw new PhutilArgumentUsageException( pht( 'Storage on host "%s" has not been initialized yet. You must '. 'initialize storage before selectively applying patches.', $ref_key)); } // If we're initializing storage for the first time on any host, track // it so that we can give the user a nicer experience during the // subsequent adjustment phase. $this->didInitialize = true; $legacy = $api->getLegacyPatches($patches); if ($legacy || $no_quickstart || $init_only) { // If we have legacy patches, we can't quickstart. $api->createDatabase('meta_data'); $api->createTable( 'meta_data', 'patch_status', array( 'patch VARCHAR(255) NOT NULL PRIMARY KEY COLLATE utf8_general_ci', 'applied INT UNSIGNED NOT NULL', )); foreach ($legacy as $patch) { $api->markPatchApplied($patch); } } else { echo tsprintf( "%s\n", pht( 'Loading quickstart template onto "%s"...', $ref_key)); $root = dirname(phutil_get_library_root('phabricator')); $sql = $root.'/resources/sql/quickstart.sql'; $api->applyPatchSQL($sql); } } if ($init_only) { echo pht('Storage initialized.')."\n"; return 0; } $applied_map = array(); $state_map = array(); foreach ($api_map as $ref_key => $api) { $applied = $api->getAppliedPatches(); // If we still have nothing applied, this is a dry run and we didn't // actually initialize storage. Here, just do nothing. if ($applied === null) { if ($is_dryrun) { continue; } else { throw new Exception( pht( 'Database initialization on host "%s" applied no patches!', $ref_key)); } } $applied = array_fuse($applied); $state_map[$ref_key] = $applied; if ($apply_only) { if (isset($applied[$apply_only])) { if (!$this->force && !$is_dryrun) { echo phutil_console_wrap( pht( 'Patch "%s" has already been applied on host "%s". Are you '. 'sure you want to apply it again? This may put your storage '. 'in a state that the upgrade scripts can not automatically '. 'manage.', $apply_only, $ref_key)); if (!phutil_console_confirm(pht('Apply patch again?'))) { echo pht('Cancelled.')."\n"; return 1; } } // Mark this patch as not yet applied on this host. unset($applied[$apply_only]); } } $applied_map[$ref_key] = $applied; } // If we're applying only a specific patch, select just that patch. if ($apply_only) { $patches = array_select_keys($patches, array($apply_only)); } // Apply each patch to each database. We apply patches patch-by-patch, // not database-by-database: for each patch we apply it to every database, // then move to the next patch. // We must do this because ".php" patches may depend on ".sql" patches // being up to date on all masters, and that will work fine if we put each // patch on every host before moving on. If we try to bring database hosts // up to date one at a time we can end up in a big mess. $duration_map = array(); // First, find any global patches which have been applied to ANY database. // We are just going to mark these as applied without actually running // them. Otherwise, adding new empty masters to an existing cluster will // try to apply them against invalid states. foreach ($patches as $key => $patch) { if ($patch->getIsGlobalPatch()) { foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$key])) { $duration_map[$key] = 1; } } } } while (true) { $applied_something = false; foreach ($patches as $key => $patch) { // First, check if any databases need this patch. We can just skip it // if it has already been applied everywhere. $need_patch = array(); foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$key])) { continue; } $need_patch[] = $ref_key; } if (!$need_patch) { unset($patches[$key]); continue; } // Check if we can apply this patch yet. Before we can apply a patch, // all of the dependencies for the patch must have been applied on all // databases. Requiring that all databases stay in sync prevents one // database from racing ahead if it happens to get a patch that nothing // else has yet. $missing_patch = null; foreach ($patch->getAfter() as $after) { foreach ($applied_map as $ref_key => $applied) { if (isset($applied[$after])) { // This database already has the patch. We can apply it to // other databases but don't need to apply it here. continue; } $missing_patch = $after; break 2; } } if ($missing_patch) { if ($apply_only) { echo tsprintf( "%s\n", pht( 'Unable to apply patch "%s" because it depends on patch '. '"%s", which has not been applied on some hosts: %s.', $apply_only, $missing_patch, implode(', ', $need_patch))); return 1; } else { // Some databases are missing the dependencies, so keep trying // other patches instead. If everything goes right, we'll apply the // dependencies and then come back and apply this patch later. continue; } } $is_global = $patch->getIsGlobalPatch(); $patch_apis = array_select_keys($api_map, $need_patch); foreach ($patch_apis as $ref_key => $api) { if ($is_global) { // If this is a global patch which we previously applied, just // read the duration from the map without actually applying // the patch. $duration = idx($duration_map, $key); } else { $duration = null; } if ($duration === null) { if ($is_dryrun) { echo tsprintf( "%s\n", pht( 'DRYRUN: Would apply patch "%s" to host "%s".', $key, $ref_key)); } else { echo tsprintf( "%s\n", pht( 'Applying patch "%s" to host "%s"...', $key, $ref_key)); } $t_begin = microtime(true); if (!$is_dryrun) { $api->applyPatch($patch); } $t_end = microtime(true); $duration = ($t_end - $t_begin); $duration_map[$key] = $duration; } // If we're explicitly reapplying this patch, we don't need to // mark it as applied. if (!isset($state_map[$ref_key][$key])) { if (!$is_dryrun) { $api->markPatchApplied($key, ($t_end - $t_begin)); } $applied_map[$ref_key][$key] = true; } } // We applied this everywhere, so we're done with the patch. unset($patches[$key]); $applied_something = true; } if (!$applied_something) { if ($patches) { throw new Exception( pht( 'Some patches could not be applied: %s', implode(', ', array_keys($patches)))); } else if (!$is_dryrun && !$apply_only) { echo pht( 'Storage is up to date. Use "%s" for details.', 'storage status')."\n"; } break; } } } final protected function getBareHostAndPort($host) { // Split out port information, since the command-line client requires a // separate flag for the port. $uri = new PhutilURI('mysql://'.$host); if ($uri->getPort()) { $port = $uri->getPort(); $bare_hostname = $uri->getDomain(); } else { $port = null; $bare_hostname = $host; } return array($bare_hostname, $port); } /** * Acquires a @{class:PhabricatorGlobalLock}. * * @return PhabricatorGlobalLock */ final protected function lock(PhabricatorStorageManagementAPI $api) { // Although we're holding this lock on different databases so it could // have the same name on each as far as the database is concerned, the // locks would be the same within this process. $parameters = array( 'refKey' => $api->getRef()->getRefKey(), ); // We disable logging for this lock because we may not have created the // log table yet, or may need to adjust it. return PhabricatorGlobalLock::newLock('adjust', $parameters) ->useSpecificConnection($api->getConn(null)) ->setDisableLogging(true) ->lock(); } final protected function analyzeTables( PhabricatorStorageManagementAPI $api) { // Analyzing tables can sometimes have a significant effect on query // performance, particularly for the fulltext ngrams tables. See T12819 // for some specific examples. $conn = $api->getConn(null); $patches = $this->getPatches(); $databases = $api->getDatabaseList($patches, true); $this->logInfo( pht('ANALYZE'), pht('Analyzing tables...')); $targets = array(); foreach ($databases as $database) { queryfx($conn, 'USE %C', $database); $tables = queryfx_all($conn, 'SHOW TABLE STATUS'); foreach ($tables as $table) { $table_name = $table['Name']; $targets[] = array( 'database' => $database, 'table' => $table_name, ); } } $bar = id(new PhutilConsoleProgressBar()) ->setTotal(count($targets)); foreach ($targets as $target) { queryfx( $conn, 'ANALYZE TABLE %T.%T', $target['database'], $target['table']); $bar->update(1); } $bar->done(); $this->logOkay( pht('ANALYZED'), pht( 'Analyzed %d table(s).', count($targets))); } } diff --git a/src/infrastructure/util/PhabricatorMetronome.php b/src/infrastructure/util/PhabricatorMetronome.php new file mode 100644 index 0000000000..24f58127f6 --- /dev/null +++ b/src/infrastructure/util/PhabricatorMetronome.php @@ -0,0 +1,92 @@ +offset = $offset; + + return $this; + } + + public function setFrequency($frequency) { + if (!is_int($frequency)) { + throw new Exception(pht('Metronome frequency must be an integer.')); + } + + if ($frequency < 1) { + throw new Exception(pht('Metronome frequency must be 1 or more.')); + } + + $this->frequency = $frequency; + + return $this; + } + + public function setOffsetFromSeed($seed) { + $offset = PhabricatorHash::digestToRange($seed, 0, PHP_INT_MAX); + return $this->setOffset($offset); + } + + public function getFrequency() { + if ($this->frequency === null) { + throw new PhutilInvalidStateException('setFrequency'); + } + return $this->frequency; + } + + public function getOffset() { + $frequency = $this->getFrequency(); + return ($this->offset % $frequency); + } + + public function getNextTickAfter($epoch) { + $frequency = $this->getFrequency(); + $offset = $this->getOffset(); + + $remainder = ($epoch % $frequency); + + if ($remainder < $offset) { + return ($epoch - $remainder) + $offset; + } else { + return ($epoch - $remainder) + $frequency + $offset; + } + } + + public function didTickBetween($min, $max) { + if ($max < $min) { + throw new Exception( + pht( + 'Maximum tick window must not be smaller than minimum tick window.')); + } + + $next = $this->getNextTickAfter($min); + return ($next <= $max); + } + +} diff --git a/src/infrastructure/util/__tests__/PhabricatorMetronomeTestCase.php b/src/infrastructure/util/__tests__/PhabricatorMetronomeTestCase.php new file mode 100644 index 0000000000..9ad74e2b90 --- /dev/null +++ b/src/infrastructure/util/__tests__/PhabricatorMetronomeTestCase.php @@ -0,0 +1,61 @@ + 44, + 'web002.example.net' => 36, + 'web003.example.net' => 25, + 'web004.example.net' => 25, + 'web005.example.net' => 16, + 'web006.example.net' => 26, + 'web007.example.net' => 35, + 'web008.example.net' => 14, + ); + + $metronome = id(new PhabricatorMetronome()) + ->setFrequency(60); + + foreach ($cases as $input => $expect) { + $metronome->setOffsetFromSeed($input); + + $this->assertEqual( + $expect, + $metronome->getOffset(), + pht('Offset for: %s', $input)); + } + } + + public function testMetronomeTicks() { + $metronome = id(new PhabricatorMetronome()) + ->setFrequency(60) + ->setOffset(13); + + $tick_epoch = strtotime('2000-01-01 11:11:13 AM UTC'); + + // Since the epoch is at "0:13" on the clock, the metronome should tick + // then. + $this->assertEqual( + $tick_epoch, + $metronome->getNextTickAfter($tick_epoch - 1), + pht('Tick at 11:11:13 AM.')); + + // The next tick should be a minute later. + $this->assertEqual( + $tick_epoch + 60, + $metronome->getNextTickAfter($tick_epoch), + pht('Tick at 11:12:13 AM.')); + + + // There's no tick in the next 59 seconds. + $this->assertFalse( + $metronome->didTickBetween($tick_epoch, $tick_epoch + 59)); + + $this->assertTrue( + $metronome->didTickBetween($tick_epoch, $tick_epoch + 60)); + } + + +} diff --git a/src/view/form/control/AphrontFormTextControl.php b/src/view/form/control/AphrontFormTextControl.php index 581f22682d..f7fd117cfd 100644 --- a/src/view/form/control/AphrontFormTextControl.php +++ b/src/view/form/control/AphrontFormTextControl.php @@ -1,55 +1,66 @@ disableAutocomplete = $disable; return $this; } private function getDisableAutocomplete() { return $this->disableAutocomplete; } public function getPlaceholder() { return $this->placeholder; } public function setPlaceholder($placeholder) { $this->placeholder = $placeholder; return $this; } + public function setAutofocus($autofocus) { + $this->autofocus = $autofocus; + return $this; + } + + public function getAutofocus() { + return $this->autofocus; + } + public function getSigil() { return $this->sigil; } public function setSigil($sigil) { $this->sigil = $sigil; return $this; } protected function getCustomControlClass() { return 'aphront-form-control-text'; } protected function renderInput() { return javelin_tag( 'input', array( 'type' => 'text', 'name' => $this->getName(), 'value' => $this->getValue(), 'disabled' => $this->getDisabled() ? 'disabled' : null, 'autocomplete' => $this->getDisableAutocomplete() ? 'off' : null, 'id' => $this->getID(), 'sigil' => $this->getSigil(), 'placeholder' => $this->getPlaceholder(), + 'autofocus' => ($this->getAutofocus() ? 'autofocus' : null), )); } } diff --git a/src/view/form/control/PHUIFormNumberControl.php b/src/view/form/control/PHUIFormNumberControl.php index 26e7e03955..c577bebbd0 100644 --- a/src/view/form/control/PHUIFormNumberControl.php +++ b/src/view/form/control/PHUIFormNumberControl.php @@ -1,40 +1,51 @@ disableAutocomplete = $disable_autocomplete; return $this; } public function getDisableAutocomplete() { return $this->disableAutocomplete; } + public function setAutofocus($autofocus) { + $this->autofocus = $autofocus; + return $this; + } + + public function getAutofocus() { + return $this->autofocus; + } + protected function getCustomControlClass() { return 'phui-form-number'; } protected function renderInput() { if ($this->getDisableAutocomplete()) { $autocomplete = 'off'; } else { $autocomplete = null; } return javelin_tag( 'input', array( 'type' => 'text', 'pattern' => '\d*', 'name' => $this->getName(), 'value' => $this->getValue(), 'disabled' => $this->getDisabled() ? 'disabled' : null, 'autocomplete' => $autocomplete, 'id' => $this->getID(), + 'autofocus' => ($this->getAutofocus() ? 'autofocus' : null), )); } } diff --git a/src/view/layout/PhabricatorActionView.php b/src/view/layout/PhabricatorActionView.php index a1d8fe2664..3de60a2374 100644 --- a/src/view/layout/PhabricatorActionView.php +++ b/src/view/layout/PhabricatorActionView.php @@ -1,374 +1,375 @@ 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 setColor($color) { $this->color = $color; 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 setID($id) { $this->id = $id; return $this; } public function getID() { if (!$this->id) { $this->id = celerity_generate_unique_node_id(); } return $this->id; } public function setOrder($order) { $this->order = $order; return $this; } public function getOrder() { return $this->order; } public function setType($type) { $this->type = $type; return $this; } public function getType() { return $this->type; } 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); } $sigils = array(); if ($this->workflow) { $sigils[] = 'workflow'; } if ($this->download) { $sigils[] = 'download'; } if ($this->submenu) { $sigils[] = 'keep-open'; } if ($this->sigils) { $sigils = array_merge($sigils, $this->sigils); } $sigils = $sigils ? implode(' ', $sigils) : null; if ($this->href) { 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'; $rel = 'noreferrer'; } else { $target = null; $rel = 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, 'rel' => $rel, 'sigil' => $sigils, 'meta' => $this->metadata, ), array($icon, $this->name, $caret)); } } else { $item = javelin_tag( 'span', array( 'class' => 'phabricator-action-view-item', 'sigil' => $sigils, ), array($icon, $this->name, $this->renderChildren())); } $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'; } if ($this->icon) { $classes[] = 'action-has-icon'; } if ($this->color) { $classes[] = $this->color; } if ($this->type) { $classes[] = 'phabricator-action-view-'.$this->type; } $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/PHUIIconView.php b/src/view/phui/PHUIIconView.php index 8cc61ba2eb..d907cb3343 100644 --- a/src/view/phui/PHUIIconView.php +++ b/src/view/phui/PHUIIconView.php @@ -1,888 +1,902 @@ href = $href; return $this; } public function setImage($image) { $this->image = $image; return $this; } public function setText($text) { $this->text = $text; return $this; } public function setHeadSize($size) { $this->headSize = $size; return $this; } public function setSpriteIcon($sprite) { $this->spriteIcon = $sprite; return $this; } public function setSpriteSheet($sheet) { $this->spriteSheet = $sheet; return $this; } public function setIcon($icon, $color = null) { $this->iconFont = $icon; $this->iconColor = $color; return $this; } public function setBackground($color) { $this->iconBackground = $color; return $this; } public function setTooltip($text) { $this->tooltip = $text; return $this; } + public function setEmblemColor($emblem_color) { + $this->emblemColor = $emblem_color; + return $this; + } + + public function getEmblemColor() { + return $this->emblemColor; + } + protected function getTagName() { $tag = 'span'; if ($this->href) { $tag = 'a'; } return $tag; } protected function getTagAttributes() { require_celerity_resource('phui-icon-view-css'); $style = null; $classes = array(); $classes[] = 'phui-icon-view'; if ($this->spriteIcon) { require_celerity_resource('sprite-'.$this->spriteSheet.'-css'); $classes[] = 'sprite-'.$this->spriteSheet; $classes[] = $this->spriteSheet.'-'.$this->spriteIcon; } else if ($this->iconFont) { require_celerity_resource('phui-font-icon-base-css'); require_celerity_resource('font-fontawesome'); $classes[] = 'phui-font-fa'; $classes[] = $this->iconFont; if ($this->iconColor) { $classes[] = $this->iconColor; } if ($this->iconBackground) { $classes[] = 'phui-icon-square'; $classes[] = $this->iconBackground; } } else { if ($this->headSize) { $classes[] = $this->headSize; } $style = 'background-image: url('.$this->image.');'; } if ($this->text) { $classes[] = 'phui-icon-has-text'; $this->appendChild($this->text); } + if ($this->emblemColor) { + $classes[] = 'phui-icon-emblem phui-icon-emblem-'.$this->emblemColor; + } + $sigil = null; $meta = array(); if ($this->tooltip) { Javelin::initBehavior('phabricator-tooltips'); require_celerity_resource('aphront-tooltip-css'); $sigil = 'has-tooltip'; $meta = array( 'tip' => $this->tooltip, ); } return array( 'href' => $this->href, 'style' => $style, 'aural' => false, 'class' => $classes, 'sigil' => $sigil, 'meta' => $meta, ); } public static function getSheetManifest($sheet) { $root = dirname(phutil_get_library_root('phabricator')); $path = $root.'/resources/sprite/manifest/'.$sheet.'.json'; $data = Filesystem::readFile($path); return idx(phutil_json_decode($data), 'sprites'); } public static function getIcons() { return array( 'fa-glass', 'fa-music', 'fa-search', 'fa-envelope-o', 'fa-heart', 'fa-star', 'fa-star-o', 'fa-user', 'fa-film', 'fa-th-large', 'fa-th', 'fa-th-list', 'fa-check', 'fa-times', 'fa-search-plus', 'fa-search-minus', 'fa-power-off', 'fa-signal', 'fa-cog', 'fa-trash-o', 'fa-home', 'fa-file-o', 'fa-clock-o', 'fa-road', 'fa-download', 'fa-arrow-circle-o-down', 'fa-arrow-circle-o-up', 'fa-inbox', 'fa-play-circle-o', 'fa-repeat', 'fa-refresh', 'fa-list-alt', 'fa-lock', 'fa-flag', 'fa-headphones', 'fa-volume-off', 'fa-volume-down', 'fa-volume-up', 'fa-qrcode', 'fa-barcode', 'fa-tag', 'fa-tags', 'fa-book', 'fa-bookmark', 'fa-print', 'fa-camera', 'fa-font', 'fa-bold', 'fa-italic', 'fa-text-height', 'fa-text-width', 'fa-align-left', 'fa-align-center', 'fa-align-right', 'fa-align-justify', 'fa-list', 'fa-outdent', 'fa-indent', 'fa-video-camera', 'fa-picture-o', 'fa-pencil', 'fa-map-marker', 'fa-adjust', 'fa-tint', 'fa-pencil-square-o', 'fa-share-square-o', 'fa-check-square-o', 'fa-arrows', 'fa-step-backward', 'fa-fast-backward', 'fa-backward', 'fa-play', 'fa-pause', 'fa-stop', 'fa-forward', 'fa-fast-forward', 'fa-step-forward', 'fa-eject', 'fa-chevron-left', 'fa-chevron-right', 'fa-plus-circle', 'fa-minus-circle', 'fa-times-circle', 'fa-check-circle', 'fa-question-circle', 'fa-info-circle', 'fa-crosshairs', 'fa-times-circle-o', 'fa-check-circle-o', 'fa-ban', 'fa-arrow-left', 'fa-arrow-right', 'fa-arrow-up', 'fa-arrow-down', 'fa-share', 'fa-expand', 'fa-compress', 'fa-plus', 'fa-minus', 'fa-asterisk', 'fa-exclamation-circle', 'fa-gift', 'fa-leaf', 'fa-fire', 'fa-eye', 'fa-eye-slash', 'fa-exclamation-triangle', 'fa-plane', 'fa-calendar', 'fa-random', 'fa-comment', 'fa-magnet', 'fa-chevron-up', 'fa-chevron-down', 'fa-retweet', 'fa-shopping-cart', 'fa-folder', 'fa-folder-open', 'fa-arrows-v', 'fa-arrows-h', 'fa-bar-chart-o', 'fa-twitter-square', 'fa-facebook-square', 'fa-camera-retro', 'fa-key', 'fa-cogs', 'fa-comments', 'fa-thumbs-o-up', 'fa-thumbs-o-down', 'fa-star-half', 'fa-heart-o', 'fa-sign-out', 'fa-linkedin-square', 'fa-thumb-tack', 'fa-external-link', 'fa-sign-in', 'fa-trophy', 'fa-github-square', 'fa-upload', 'fa-lemon-o', 'fa-phone', 'fa-square-o', 'fa-bookmark-o', 'fa-phone-square', 'fa-twitter', 'fa-facebook', 'fa-github', 'fa-unlock', 'fa-credit-card', 'fa-rss', 'fa-hdd-o', 'fa-bullhorn', 'fa-bell', 'fa-certificate', 'fa-hand-o-right', 'fa-hand-o-left', 'fa-hand-o-up', 'fa-hand-o-down', 'fa-arrow-circle-left', 'fa-arrow-circle-right', 'fa-arrow-circle-up', 'fa-arrow-circle-down', 'fa-globe', 'fa-wrench', 'fa-tasks', 'fa-filter', 'fa-briefcase', 'fa-arrows-alt', 'fa-users', 'fa-link', 'fa-cloud', 'fa-flask', 'fa-scissors', 'fa-files-o', 'fa-paperclip', 'fa-floppy-o', 'fa-square', 'fa-bars', 'fa-list-ul', 'fa-list-ol', 'fa-strikethrough', 'fa-underline', 'fa-table', 'fa-magic', 'fa-truck', 'fa-pinterest', 'fa-pinterest-square', 'fa-google-plus-square', 'fa-google-plus', 'fa-money', 'fa-caret-down', 'fa-caret-up', 'fa-caret-left', 'fa-caret-right', 'fa-columns', 'fa-sort', 'fa-sort-asc', 'fa-sort-desc', 'fa-envelope', 'fa-linkedin', 'fa-undo', 'fa-gavel', 'fa-tachometer', 'fa-comment-o', 'fa-comments-o', 'fa-bolt', 'fa-sitemap', 'fa-umbrella', 'fa-clipboard', 'fa-lightbulb-o', 'fa-exchange', 'fa-cloud-download', 'fa-cloud-upload', 'fa-user-md', 'fa-stethoscope', 'fa-suitcase', 'fa-bell-o', 'fa-coffee', 'fa-cutlery', 'fa-file-text-o', 'fa-building-o', 'fa-hospital-o', 'fa-ambulance', 'fa-medkit', 'fa-fighter-jet', 'fa-beer', 'fa-h-square', 'fa-plus-square', 'fa-angle-double-left', 'fa-angle-double-right', 'fa-angle-double-up', 'fa-angle-double-down', 'fa-angle-left', 'fa-angle-right', 'fa-angle-up', 'fa-angle-down', 'fa-desktop', 'fa-laptop', 'fa-tablet', 'fa-mobile', 'fa-circle-o', 'fa-quote-left', 'fa-quote-right', 'fa-spinner', 'fa-circle', 'fa-reply', 'fa-github-alt', 'fa-folder-o', 'fa-folder-open-o', 'fa-smile-o', 'fa-frown-o', 'fa-meh-o', 'fa-gamepad', 'fa-keyboard-o', 'fa-flag-o', 'fa-flag-checkered', 'fa-terminal', 'fa-code', 'fa-reply-all', 'fa-mail-reply-all', 'fa-star-half-o', 'fa-location-arrow', 'fa-crop', 'fa-code-fork', 'fa-chain-broken', 'fa-question', 'fa-info', 'fa-exclamation', 'fa-superscript', 'fa-subscript', 'fa-eraser', 'fa-puzzle-piece', 'fa-microphone', 'fa-microphone-slash', 'fa-shield', 'fa-calendar-o', 'fa-fire-extinguisher', 'fa-rocket', 'fa-maxcdn', 'fa-chevron-circle-left', 'fa-chevron-circle-right', 'fa-chevron-circle-up', 'fa-chevron-circle-down', 'fa-html5', 'fa-css3', 'fa-anchor', 'fa-unlock-alt', 'fa-bullseye', 'fa-ellipsis-h', 'fa-ellipsis-v', 'fa-rss-square', 'fa-play-circle', 'fa-ticket', 'fa-minus-square', 'fa-minus-square-o', 'fa-level-up', 'fa-level-down', 'fa-check-square', 'fa-pencil-square', 'fa-external-link-square', 'fa-share-square', 'fa-compass', 'fa-caret-square-o-down', 'fa-caret-square-o-up', 'fa-caret-square-o-right', 'fa-eur', 'fa-gbp', 'fa-usd', 'fa-inr', 'fa-jpy', 'fa-rub', 'fa-krw', 'fa-btc', 'fa-file', 'fa-file-text', 'fa-sort-alpha-asc', 'fa-sort-alpha-desc', 'fa-sort-amount-asc', 'fa-sort-amount-desc', 'fa-sort-numeric-asc', 'fa-sort-numeric-desc', 'fa-thumbs-up', 'fa-thumbs-down', 'fa-youtube-square', 'fa-youtube', 'fa-xing', 'fa-xing-square', 'fa-youtube-play', 'fa-dropbox', 'fa-stack-overflow', 'fa-instagram', 'fa-flickr', 'fa-adn', 'fa-bitbucket', 'fa-bitbucket-square', 'fa-tumblr', 'fa-tumblr-square', 'fa-long-arrow-down', 'fa-long-arrow-up', 'fa-long-arrow-left', 'fa-long-arrow-right', 'fa-apple', 'fa-windows', 'fa-android', 'fa-linux', 'fa-dribbble', 'fa-skype', 'fa-foursquare', 'fa-trello', 'fa-female', 'fa-male', 'fa-gittip', 'fa-sun-o', 'fa-moon-o', 'fa-archive', 'fa-bug', 'fa-vk', 'fa-weibo', 'fa-renren', 'fa-pagelines', 'fa-stack-exchange', 'fa-arrow-circle-o-right', 'fa-arrow-circle-o-left', 'fa-caret-square-o-left', 'fa-dot-circle-o', 'fa-wheelchair', 'fa-vimeo-square', 'fa-try', 'fa-plus-square-o', 'fa-space-shuttle', 'fa-slack', 'fa-envelope-square', 'fa-wordpress', 'fa-openid', 'fa-institution', 'fa-bank', 'fa-university', 'fa-mortar-board', 'fa-graduation-cap', 'fa-yahoo', 'fa-google', 'fa-reddit', 'fa-reddit-square', 'fa-stumbleupon-circle', 'fa-stumbleupon', 'fa-delicious', 'fa-digg', 'fa-pied-piper-square', 'fa-pied-piper', 'fa-pied-piper-alt', 'fa-pied-piper-pp', 'fa-drupal', 'fa-joomla', 'fa-language', 'fa-fax', 'fa-building', 'fa-child', 'fa-paw', 'fa-spoon', 'fa-cube', 'fa-cubes', 'fa-behance', 'fa-behance-square', 'fa-steam', 'fa-steam-square', 'fa-recycle', 'fa-automobile', 'fa-car', 'fa-cab', 'fa-tree', 'fa-spotify', 'fa-deviantart', 'fa-soundcloud', 'fa-database', 'fa-file-pdf-o', 'fa-file-word-o', 'fa-file-excel-o', 'fa-file-powerpoint-o', 'fa-file-photo-o', 'fa-file-picture-o', 'fa-file-image-o', 'fa-file-zip-o', 'fa-file-archive-o', 'fa-file-sound-o', 'fa-file-movie-o', 'fa-file-code-o', 'fa-vine', 'fa-codepen', 'fa-jsfiddle', 'fa-life-bouy', 'fa-support', 'fa-life-ring', 'fa-circle-o-notch', 'fa-rebel', 'fa-empire', 'fa-git-square', 'fa-git', 'fa-hacker-news', 'fa-tencent-weibo', 'fa-qq', 'fa-wechat', 'fa-send', 'fa-paper-plane', 'fa-send-o', 'fa-paper-plane-o', 'fa-history', 'fa-circle-thin', 'fa-header', 'fa-paragraph', 'fa-sliders', 'fa-share-alt', 'fa-share-alt-square', 'fa-bomb', 'fa-soccer-ball', 'fa-futbol-o', 'fa-tty', 'fa-binoculars', 'fa-plug', 'fa-slideshare', 'fa-twitch', 'fa-yelp', 'fa-newspaper-o', 'fa-wifi', 'fa-calculator', 'fa-paypal', 'fa-google-wallet', 'fa-cc-visa', 'fa-cc-mastercard', 'fa-cc-discover', 'fa-cc-amex', 'fa-cc-paypal', 'fa-cc-stripe', 'fa-bell-slash', 'fa-bell-slash-o', 'fa-trash', 'fa-copyright', 'fa-at', 'fa-eyedropper', 'fa-paint-brush', 'fa-birthday-cake', 'fa-area-chart', 'fa-pie-chart', 'fa-line-chart', 'fa-lastfm', 'fa-lastfm-square', 'fa-toggle-off', 'fa-toggle-on', 'fa-bicycle', 'fa-bus', 'fa-ioxhost', 'fa-angellist', 'fa-cc', 'fa-shekel', 'fa-sheqel', 'fa-ils', 'fa-meanpath', 'fa-buysellads', 'fa-connectdevelop', 'fa-dashcube', 'fa-forumbee', 'fa-leanpub', 'fa-sellsy', 'fa-shirtsinbulk', 'fa-simplybuilt', 'fa-skyatlas', 'fa-cart-plus', 'fa-cart-arrow-down', 'fa-diamond', 'fa-ship', 'fa-user-secret', 'fa-motorcycle', 'fa-street-view', 'fa-heartbeat', 'fa-venus', 'fa-mars', 'fa-mercury', 'fa-transgender', 'fa-transgender-alt', 'fa-venus-double', 'fa-mars-double', 'fa-venus-mars', 'fa-mars-stroke', 'fa-mars-stroke-v', 'fa-mars-stroke-h', 'fa-neuter', 'fa-facebook-official', 'fa-pinterest-p', 'fa-whatsapp', 'fa-server', 'fa-user-plus', 'fa-user-times', 'fa-hotel', 'fa-bed', 'fa-viacoin', 'fa-train', 'fa-subway', 'fa-medium', 'fa-git', 'fa-y-combinator-square', 'fa-yc-square', 'fa-hacker-news', 'fa-yc', 'fa-y-combinator', 'fa-optin-monster', 'fa-opencart', 'fa-expeditedssl', 'fa-battery-4', 'fa-battery-full', 'fa-battery-3', 'fa-battery-three-quarters', 'fa-battery-2', 'fa-battery-half', 'fa-battery-1', 'fa-battery-quarter', 'fa-battery-0', 'fa-battery-empty', 'fa-mouse-pointer', 'fa-i-cursor', 'fa-object-group', 'fa-object-ungroup', 'fa-sticky-note', 'fa-sticky-note-o', 'fa-cc-jcb', 'fa-cc-diners-club', 'fa-clone', 'fa-balance-scale', 'fa-hourglass-o', 'fa-hourglass-1', 'fa-hourglass-start', 'fa-hourglass-2', 'fa-hourglass-half', 'fa-hourglass-3', 'fa-hourglass-end', 'fa-hourglass', 'fa-hand-grab-o', 'fa-hand-rock-o', 'fa-hand-stop-o', 'fa-hand-paper-o', 'fa-hand-scissors-o', 'fa-hand-lizard-o', 'fa-hand-spock-o', 'fa-hand-pointer-o', 'fa-hand-peace-o', 'fa-trademark', 'fa-registered', 'fa-creative-commons', 'fa-gg', 'fa-gg-circle', 'fa-tripadvisor', 'fa-odnoklassniki', 'fa-odnoklassniki-square', 'fa-get-pocket', 'fa-wikipedia-w', 'fa-safari', 'fa-chrome', 'fa-firefox', 'fa-opera', 'fa-internet-explorer', 'fa-tv', 'fa-television', 'fa-contao', 'fa-500px', 'fa-amazon', 'fa-calendar-plus-o', 'fa-calendar-minus-o', 'fa-calendar-times-o', 'fa-calendar-check-o', 'fa-industry', 'fa-map-pin', 'fa-map-signs', 'fa-map-o', 'fa-map', 'fa-commenting', 'fa-commenting-o', 'fa-houzz', 'fa-vimeo', 'fa-black-tie', 'fa-fonticons', 'fa-reddit-alien', 'fa-edge', 'fa-credit-card-alt', 'fa-codiepie:before', 'fa-modx', 'fa-fort-awesome', 'fa-usb', 'fa-product-hunt', 'fa-mixcloud', 'fa-scribd', 'fa-pause-circle', 'fa-pause-circle-o', 'fa-stop-circle', 'fa-stop-circle-o', 'fa-shopping-bag', 'fa-shopping-basket', 'fa-hashtag', 'fa-bluetooth', 'fa-bluetooth-b', 'fa-percent', 'fa-gitlab', 'fa-wpbeginner', 'fa-wpforms', 'fa-envira', 'fa-universal-access', 'fa-wheelchair-alt', 'fa-question-circle-o', 'fa-blind', 'fa-audio-description', 'fa-volume-control-phone', 'fa-braille', 'fa-assistive-listening-systems', 'fa-asl-interpreting', 'fa-american-sign-language-interpreting', 'fa-deafness', 'fa-hard-of-hearing', 'fa-deaf', 'fa-glide', 'fa-glide-g', 'fa-signing', 'fa-sign-language', 'fa-low-vision', 'fa-viadeo', 'fa-viadeo-square', 'fa-snapchat', 'fa-snapchat-ghost', 'fa-snapchat-square', 'fa-first-order', 'fa-yoast', 'fa-themeisle', 'fa-google-plus-circle', 'fa-google-plus-official', 'fa-fa', 'fa-font-awesome', 'fa-handshake-o', 'fa-envelope-open', 'fa-envelope-open-o', 'fa-linode', 'fa-address-book', 'fa-address-book-o', 'fa-vcard', 'fa-address-card', 'fa-vcard-o', 'fa-address-card-o', 'fa-user-circle', 'fa-user-circle-o', 'fa-user-o:before', 'fa-id-badge', 'fa-drivers-license', 'fa-id-card', 'fa-drivers-license-o', 'fa-id-card-o', 'fa-quora', 'fa-free-code-camp', 'fa-telegram', 'fa-thermometer-4', 'fa-thermometer', 'fa-thermometer-full', 'fa-thermometer-3', 'fa-thermometer-three-quarters', 'fa-thermometer-2', 'fa-thermometer-half', 'fa-thermometer-1', 'fa-thermometer-quarter', 'fa-thermometer-0:', 'fa-thermometer-empty', 'fa-shower', 'fa-bathtub', 'fa-s15', 'fa-bath', 'fa-podcast', 'fa-window-maximize', 'fa-window-minimize', 'fa-window-restore', 'fa-times-rectangle', 'fa-window-close', 'fa-times-rectangle-o', 'fa-window-close-o', 'fa-bandcamp', 'fa-grav', 'fa-etsy', 'fa-imdb', 'fa-ravelry', 'fa-eercast', 'fa-microchip', 'fa-snowflake-o', 'fa-superpowers', 'fa-wpexplorer', 'fa-meetup', ); } public static function getIconColors() { return array( 'bluegrey', 'white', 'red', 'orange', 'yellow', 'green', 'blue', 'sky', 'indigo', 'violet', 'pink', 'lightgreytext', 'lightbluetext', ); } } diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php index 86628058fe..78a75a2063 100644 --- a/src/view/phui/PHUITimelineEventView.php +++ b/src/view/phui/PHUITimelineEventView.php @@ -1,726 +1,745 @@ 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 setIsSilent($is_silent) { $this->isSilent = $is_silent; return $this; } public function getIsSilent() { return $this->isSilent; } public function setIsMFA($is_mfa) { $this->isMFA = $is_mfa; return $this; } public function getIsMFA() { return $this->isMFA; } + public function setIsLockOverride($is_override) { + $this->isLockOverride = $is_override; + return $this; + } + + public function getIsLockOverride() { + return $this->isLockOverride; + } + 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 addPinboardItem(PHUIPinboardItemView $item) { $this->pinboardItems[] = $item; return $this; } 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(); if (!$this->getIsPreview() && !$this->getHideCommentOptions()) { foreach ($this->getEventGroup() as $event) { $items[] = $event->getMenuItems($this->anchor); } $items = array_mergev($items); } if ($items) { $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; } else { $has_menu = false; } // 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', '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 visual-only', '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', ), $content); // Image Events $pinboard = null; if ($this->pinboardItems) { $pinboard = new PHUIPinboardView(); foreach ($this->pinboardItems as $item) { $pinboard->addItem($item); } } $content = phutil_tag( 'div', array( 'class' => implode(' ', $content_classes), ), array($image, $badges, $wedge, $content, $pinboard)); $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'); $date = array( javelin_tag( 'a', array( 'href' => '#'.$this->anchor, 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $content_source, ), ), $date), ); } $extra[] = $date; } // If this edit was applied silently, give user a hint that they should // not expect to have received any mail or notifications. if ($this->getIsSilent()) { $extra[] = id(new PHUIIconView()) - ->setIcon('fa-bell-slash', 'red') + ->setIcon('fa-bell-slash', 'white') + ->setEmblemColor('red') ->setTooltip(pht('Silent Edit')); } // If this edit was applied while the actor was in high-security mode, // provide a hint that it was extra authentic. if ($this->getIsMFA()) { $extra[] = id(new PHUIIconView()) - ->setIcon('fa-vcard', 'pink') + ->setIcon('fa-vcard', 'white') + ->setEmblemColor('pink') ->setTooltip(pht('MFA Authenticated')); } + + if ($this->getIsLockOverride()) { + $extra[] = id(new PHUIIconView()) + ->setIcon('fa-chain-broken', 'white') + ->setEmblemColor('violet') + ->setTooltip(pht('Lock Overridden')); + } } $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') ->setName(pht('Quote Comment')) ->setHref('#') ->addSigil('transaction-quote') ->setMetadata( array( 'targetID' => $this->getQuoteTargetID(), 'uri' => '/transactions/quote/'.$xaction_phid.'/', 'ref' => $ref, )); } if ($this->getIsNormalComment()) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-code') ->setHref('/transactions/raw/'.$xaction_phid.'/') ->setName(pht('View Remarkup')) ->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->getIsEdited()) { $items[] = id(new PhabricatorActionView()) ->setIcon('fa-list') ->setHref('/transactions/history/'.$xaction_phid.'/') ->setName(pht('View Edit History')) ->setWorkflow(true); } if ($this->getIsRemovable()) { $items[] = id(new PhabricatorActionView()) ->setType(PhabricatorActionView::TYPE_DIVIDER); $items[] = id(new PhabricatorActionView()) ->setIcon('fa-trash-o') ->setHref('/transactions/remove/'.$xaction_phid.'/') ->setName(pht('Remove Comment')) ->setColor(PhabricatorActionView::RED) ->addSigil('transaction-remove') ->setMetadata( array( 'anchor' => $anchor, )); } return $items; } } diff --git a/webroot/rsrc/css/aphront/table-view.css b/webroot/rsrc/css/aphront/table-view.css index 1a7d2eb215..9bc8536054 100644 --- a/webroot/rsrc/css/aphront/table-view.css +++ b/webroot/rsrc/css/aphront/table-view.css @@ -1,329 +1,329 @@ /** * @provides aphront-table-view-css */ .aphront-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; } .aphront-table-view { width: 100%; border-collapse: collapse; background: {$page.content}; border: 1px solid {$lightblueborder}; border-bottom: 1px solid {$blueborder}; } .aphront-table-view-fixed { table-layout: fixed; } .aphront-table-view-fixed th { box-sizing: border-box; } .aphront-table-notice { padding: 12px 16px; color: {$darkbluetext}; border-bottom: 1px solid {$thinblueborder}; } .phui-two-column-view .aphront-table-notice .phui-info-view { margin: 0; } .aphront-table-view tr.alt { background: {$lightgreybackground}; } .device-desktop .aphront-table-view tr:hover { background: {$bluebackground}; } .device-desktop .aphront-table-view tr.no-data:hover { background: inherit; } -.aphront-table-view th { +.aphront-table-view th, +.aphront-table-view td.header { font-weight: bold; white-space: nowrap; color: {$bluetext}; - text-shadow: 0 1px 0 white; font-weight: bold; - border-bottom: 1px solid {$thinblueborder}; + text-shadow: 0 1px 0 white; background-color: {$lightbluebackground}; } +.aphront-table-view th { + border-bottom: 1px solid {$thinblueborder}; +} + th.aphront-table-view-sortable-selected { background-color: {$greybackground}; } .aphront-table-view th a, .aphront-table-view th a:hover, .aphront-table-view th a:link { color: {$bluetext}; text-shadow: 0 1px 0 white; display: block; text-decoration: none; } .aphront-table-view th a:hover { text-decoration: underline; color: {$darkbluetext}; } .aphront-table-view td.header { - padding: 4px 8px; - white-space: nowrap; text-align: right; - color: {$bluetext}; - font-weight: bold; - vertical-align: top; + border-right: 1px solid {$thinblueborder}; } .aphront-table-view td { white-space: nowrap; vertical-align: middle; color: {$darkbluetext}; } .aphront-table-down-sort { display: inline-block; margin-top: 5px; width: 0; height: 0; vertical-align: top; border-top: 4px solid {$bluetext}; border-right: 4px solid transparent; border-left: 4px solid transparent; content: ""; } .aphront-table-up-sort { display: inline-block; margin-top: 5px; width: 0; height: 0; vertical-align: top; border-bottom: 4px solid {$bluetext}; border-right: 4px solid transparent; border-left: 4px solid transparent; content: ""; } /* - Padding ------------------------------------------------------------------- On desktops, we have more horizontal space and use it to space columns out. On devices, we make each row slightly taller to create a larger hit target for links. */ .aphront-table-view th { padding: 8px 10px; } .aphront-table-view td { padding: 8px 10px; } .device-tablet .aphront-table-view th, .device-phone .aphront-table-view th { overflow: hidden; } .aphront-table-view td.sorted-column { background: {$lightbluebackground}; } .aphront-table-view tr.alt td.sorted-column { background: {$greybackground}; } .aphront-table-view td.action { padding-top: 1px; padding-bottom: 1px; } .aphront-table-view td.larger { font-size: {$biggerfontsize}; } .aphront-table-view td.pri { font-weight: bold; color: {$darkbluetext}; } .aphront-table-view td.top { vertical-align: top; } .aphront-table-view td.wide { white-space: normal; width: 100%; } .aphront-table-view th.right, .aphront-table-view td.right { text-align: right; } .aphront-table-view td.mono { font-family: "Monaco", monospace; font-size: {$smallestfontsize}; } .aphront-table-view td.n { font-family: "Monaco", monospace; font-size: {$smallestfontsize}; text-align: right; } .aphront-table-view td.nudgeright, .aphront-table-view th.nudgeright { padding-right: 0; } .aphront-table-view td.wrap { white-space: normal; } .aphront-table-view td.prewrap { font-family: "Monaco", monospace; font-size: {$smallestfontsize}; white-space: pre-wrap; } .aphront-table-view td.narrow { width: 1px; } .aphront-table-view td.icon, .aphront-table-view th.icon { width: 1px; padding: 0px; } .aphront-table-view td.icon + td.icon { padding-left: 8px; } div.single-display-line-bounds { width: 100%; position: relative; overflow: hidden; } span.single-display-line-content { white-space: pre; position: absolute; } .device-phone span.single-display-line-content { white-space: nowrap; position: static; } .aphront-table-view td.object-link { white-space: nowrap; word-wrap: break-word; overflow: hidden; text-overflow: ellipsis; max-width: 0; } .aphront-table-view tr.closed td.object-link .object-name, .aphront-table-view tr.alt-closed td.object-link .object-name { text-decoration: line-through; color: rgba({$alphablack}, 0.5); } .aphront-table-view tr.closed td.object-link a, .aphront-table-view tr.alt-closed td.object-link a { color: rgba({$alphablack}, 0.5); } .aphront-table-view tr.closed td.graph-status, .aphront-table-view tr.alt-closed td.graph-status, .object-graph-table em { color: {$lightgreytext}; } .aphront-table-view tr.highlighted { background: #fdf9e4; } .aphront-table-view tr.alt-highlighted { background: {$sh-yellowbackground}; } .aphront-table-view tr.diff-removed, .aphront-table-view tr.alt-diff-removed { background: {$lightred} } .aphront-table-view tr.diff-added, .aphront-table-view tr.alt-diff-added { background: {$lightgreen} } .aphront-table-view tr.no-data td { padding: 16px; text-align: center; color: {$lightgreytext}; font-style: italic; } .aphront-table-view td.thumb img { max-width: 64px; max-height: 64px; } .aphront-table-view td.threads { font-family: monospace; white-space: pre; padding: 0 0 0 8px; } .aphront-table-view td.threads canvas { display: block; } .aphront-table-view td.radio { text-align: center; padding: 2px 4px 0px; } .aphront-table-view th.center, .aphront-table-view td.center { text-align: center; } .device .aphront-table-view td + td.center, .device .aphront-table-view th + th.center { padding-left: 3px; padding-right: 3px; } .device-desktop .aphront-table-view-device { display: none; } .device-tablet .aphront-table-view-nodevice, .device-phone .aphront-table-view-nodevice { display: none; } .aphront-table-view td.link { padding: 0; } .aphront-table-view td.link a { display: block; padding: 6px 8px; font-weight: bold; } .phui-object-box .aphront-table-view { border: none; } diff --git a/webroot/rsrc/css/phui/phui-action-list.css b/webroot/rsrc/css/phui/phui-action-list.css index e7ee38a8bf..3df4ff1b78 100644 --- a/webroot/rsrc/css/phui/phui-action-list.css +++ b/webroot/rsrc/css/phui/phui-action-list.css @@ -1,198 +1,215 @@ /** * @provides phabricator-action-list-view-css */ .device .phabricator-action-list-view { padding: 4px 0; display: none; } !print .phabricator-action-list-view { padding: 4px 0; display: none; } .device .phuix-dropdown-menu .phabricator-action-list-view { /* When an action list view appears inside a dropdown menu, don't hide it by default. */ display: block; padding: 0; } .device .phabricator-action-list-view.phabricator-action-list-toggle, .device-desktop .phui-document-content .phabricator-action-list-view.phabricator-action-list-toggle { display: block; width: 200px; border: 1px solid {$lightgreyborder}; border-radius: 3px; position: absolute; right: 16px; top: 42px; background: #fff; box-shadow: {$dropshadow}; padding: 4px 0; } .device-phone .phabricator-action-list-view.phabricator-action-list-toggle { right: 8px; top: 38px; } .phabricator-action-view { position: relative; } .phabricator-action-view button.phabricator-action-view-item { border: none; background: transparent; box-shadow: none; outline: 0; padding: 0; margin: 0; font-weight: normal; width: 100%; text-align: left; text-shadow: none; border-radius: 0; color: {$anchor}; font: inherit; display: inline; min-width: 0; } .phabricator-action-view button.phabricator-action-view-item .phui-icon-view { color: {$darkbluetext}; } .phabricator-action-view button.phabricator-action-view-item, .phabricator-action-view-item { padding: 4px 8px 6px 8px; display: block; text-decoration: none; color: {$darkbluetext}; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } .action-has-icon button.phabricator-action-view-item, .action-has-icon .phabricator-action-view-item { padding: 4px 4px 4px 28px; } .device-desktop .phabricator-action-view-href:hover .phabricator-action-view-item { text-decoration: none; background: rgba({$alphablue}, .08); color: {$sky}; border-radius: 3px; } .device-desktop .phabricator-action-view-href:hover .phabricator-action-view-icon { color: {$sky}; } .phabricator-action-view.action-item-red { background-color: {$sh-redbackground}; } +.phabricator-action-view.action-item-green { + background-color: {$sh-greenbackground}; +} + .phabricator-action-view.action-item-red .phabricator-action-view-item, .phabricator-action-view.action-item-red .phabricator-action-view-icon { color: {$sh-redtext}; } +.phabricator-action-view.action-item-green .phabricator-action-view-item, +.phabricator-action-view.action-item-green .phabricator-action-view-icon { + color: {$sh-greentext}; +} + .device-desktop .phabricator-action-view.action-item-red:hover .phabricator-action-view-item, .device-desktop .phabricator-action-view.action-item-red:hover .phabricator-action-view-icon { color: {$red}; } +.device-desktop .phabricator-action-view.action-item-green:hover + .phabricator-action-view-item, +.device-desktop .phabricator-action-view.action-item-green:hover + .phabricator-action-view-icon { + color: {$green}; +} + + .phabricator-action-view-label .phabricator-action-view-item, .phabricator-action-view-type-label .phabricator-action-view-item { font-size: {$smallerfontsize}; font-weight: bold; color: {$bluetext}; padding: 4px 8px 6px 8px; display: block; text-transform: uppercase; -webkit-font-smoothing: antialiased; } .phabricator-action-view + .phabricator-action-view-label { padding-top: 8px; } .phabricator-action-view-icon { width: 14px; height: 14px; position: absolute; top: 7px; left: 8px; text-align: center; } .phabricator-action-view-disabled .phabricator-action-view-item, .phabricator-action-view-disabled button.phabricator-action-view-item { color: {$lightgreytext}; } .phabricator-action-view-selected { background: {$sh-violetbackground}; border-radius: 3px; } .phabricator-action-view-selected:hover a { text-decoration: none; } .phabricator-action-view button[disabled] { opacity: 1.0; } .device-desktop .phabricator-action-view-disabled:hover .phabricator-action-view-item, .device-desktop .phabricator-action-view-disabled:hover button.phabricator-action-view-item, .device-desktop .phabricator-action-view-disabled:hover .phabricator-action-view-icon, .device-desktop .phabricator-action-view-disabled:hover button.phabricator-action-view-icon { color: {$lightgreytext}; } .phabricator-action-view-type-divider { margin-top: 8px; border-top: 1px solid {$thinblueborder}; } /******* Sub Menu *************************************************************/ .phabricator-action-view-submenu .caret-right { position: absolute; top: 8px; right: 8px; border-left-color: {$alphablue}; } .phabricator-action-view-submenu .caret { position: absolute; top: 10px; right: 8px; 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}; } diff --git a/webroot/rsrc/css/phui/phui-icon.css b/webroot/rsrc/css/phui/phui-icon.css index 4108074b08..5436bb04b1 100644 --- a/webroot/rsrc/css/phui/phui-icon.css +++ b/webroot/rsrc/css/phui/phui-icon.css @@ -1,185 +1,206 @@ /** * @provides phui-icon-view-css */ .phui-icon-example .phui-icon-view { display: inline-block; vertical-align: top; } .phui-icon-view.sprite-tokens { height: 18px; width: 18px; display: inline-block; vertical-align: top; } .phui-icon-view.sprite-login { height: 28px; width: 28px; } .phui-icon-view.phuihead-medium { height: 50px; width: 50px; } .phui-icon-view.phuihead-small { height: 35px; width: 35px; background-size: 35px; } .phui-icon-has-text:before { margin-right: 6px; } a.phui-icon-view:hover { text-decoration: none; color: {$sky}; } img.phui-image-disabled { opacity: .8; -webkit-filter: grayscale(100%); filter: grayscale(100%); } .phui-icon-view.bluetext { color: {$bluetext}; } .phui-icon-view.invisible { visibility: hidden; } /* - Icon in a Circle ------------------------------------------------------- */ .phui-icon-circle { border: 1px solid {$lightblueborder}; border-radius: 24px; height: 24px; width: 24px; text-align: center; display: inline-block; cursor: pointer; background: transparent; padding: 0; position: relative; } .phui-icon-circle.circle-medium { height: 36px; width: 36px; border-radius: 36px; } .phui-icon-circle.phui-icon-circle-state { border-color: transparent; background-color: {$bluebackground}; } .phui-icon-circle.phui-icon-circle-state .phui-icon-circle-icon { color: {$bluetext}; font-size: 16px; } a.phui-icon-circle.phui-icon-circle-state:hover { border-color: transparent !important; } .phui-icon-circle .phui-icon-circle-icon { height: 24px; width: 24px; font-size: 11px; line-height: 24px; color: {$lightblueborder}; cursor: pointer; } .phui-icon-circle.circle-medium .phui-icon-circle-icon { font-size: 18px; line-height: 36px; } a.phui-icon-circle.hover-sky:hover { text-decoration: none; border-color: {$sky}; cursor: pointer; } a.phui-icon-circle.hover-sky:hover .phui-icon-view { color: {$sky}; } a.phui-icon-circle.hover-violet:hover { text-decoration: none; border-color: {$violet}; cursor: pointer; } a.phui-icon-circle.hover-violet:hover .phui-icon-view { color: {$violet}; } a.phui-icon-circle.hover-pink:hover { text-decoration: none; border-color: {$pink}; cursor: pointer; } a.phui-icon-circle.hover-pink:hover .phui-icon-view { color: {$pink}; } a.phui-icon-circle.hover-green:hover { text-decoration: none; border-color: {$green}; cursor: pointer; } a.phui-icon-circle.hover-green:hover .phui-icon-view { color: {$green}; } a.phui-icon-circle.hover-red:hover { text-decoration: none; border-color: {$red}; cursor: pointer; } a.phui-icon-circle.hover-red:hover .phui-icon-view { color: {$red}; } .phui-icon-circle .phui-icon-view.phui-icon-circle-state-icon { position: absolute; width: 14px; height: 14px; display: inline-block; font-size: 12px; right: -3px; top: -4px; text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff; } /* - Icon in a Square ------------------------------------------------------- */ .phui-icon-view.phui-icon-square { height: 40px; width: 40px; color: #fff; font-size: 26px; text-align: center; line-height: 38px; border-radius: 3px; } a.phui-icon-view.phui-icon-square:hover { text-decoration: none; color: #fff; } + + +.phui-icon-emblem { + border-radius: 4px; +} + +.phui-timeline-extra .phui-icon-emblem { + padding: 4px 6px; +} + +.phui-icon-emblem-violet { + background-color: {$violet}; +} + +.phui-icon-emblem-red { + background-color: {$red}; +} + +.phui-icon-emblem-pink { + background-color: {$pink}; +}