Merge branch 'master' into blender-tweaks
This commit is contained in:
1
bin/conduit
Symbolic link
1
bin/conduit
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../scripts/setup/manage_conduit.php
|
||||||
@@ -9,11 +9,11 @@ return array(
|
|||||||
'names' => array(
|
'names' => array(
|
||||||
'conpherence.pkg.css' => 'e68cf1fa',
|
'conpherence.pkg.css' => 'e68cf1fa',
|
||||||
'conpherence.pkg.js' => '15191c65',
|
'conpherence.pkg.js' => '15191c65',
|
||||||
'core.pkg.css' => '144d9932',
|
'core.pkg.css' => '07cdfee8',
|
||||||
'core.pkg.js' => '4c79d74f',
|
'core.pkg.js' => '3ac6e174',
|
||||||
'darkconsole.pkg.js' => '1f9a31bc',
|
'darkconsole.pkg.js' => '1f9a31bc',
|
||||||
'differential.pkg.css' => '45951e9e',
|
'differential.pkg.css' => '113e692c',
|
||||||
'differential.pkg.js' => '19ee9979',
|
'differential.pkg.js' => '5d53d5ce',
|
||||||
'diffusion.pkg.css' => 'a2d17c7d',
|
'diffusion.pkg.css' => 'a2d17c7d',
|
||||||
'diffusion.pkg.js' => '6134c5a1',
|
'diffusion.pkg.js' => '6134c5a1',
|
||||||
'favicon.ico' => '4d48ee79',
|
'favicon.ico' => '4d48ee79',
|
||||||
@@ -31,7 +31,7 @@ return array(
|
|||||||
'rsrc/css/aphront/multi-column.css' => '84cc6640',
|
'rsrc/css/aphront/multi-column.css' => '84cc6640',
|
||||||
'rsrc/css/aphront/notification.css' => '457861ec',
|
'rsrc/css/aphront/notification.css' => '457861ec',
|
||||||
'rsrc/css/aphront/panel-view.css' => '8427b78d',
|
'rsrc/css/aphront/panel-view.css' => '8427b78d',
|
||||||
'rsrc/css/aphront/phabricator-nav-view.css' => 'faf6a6fc',
|
'rsrc/css/aphront/phabricator-nav-view.css' => '028126f6',
|
||||||
'rsrc/css/aphront/table-view.css' => '8c9bbafe',
|
'rsrc/css/aphront/table-view.css' => '8c9bbafe',
|
||||||
'rsrc/css/aphront/tokenizer.css' => '15d5ff71',
|
'rsrc/css/aphront/tokenizer.css' => '15d5ff71',
|
||||||
'rsrc/css/aphront/tooltip.css' => '173b9431',
|
'rsrc/css/aphront/tooltip.css' => '173b9431',
|
||||||
@@ -121,7 +121,7 @@ return array(
|
|||||||
'rsrc/css/font/font-awesome.css' => 'e838e088',
|
'rsrc/css/font/font-awesome.css' => 'e838e088',
|
||||||
'rsrc/css/font/font-lato.css' => 'c7ccd872',
|
'rsrc/css/font/font-lato.css' => 'c7ccd872',
|
||||||
'rsrc/css/font/phui-font-icon-base.css' => '870a7360',
|
'rsrc/css/font/phui-font-icon-base.css' => '870a7360',
|
||||||
'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82',
|
'rsrc/css/layout/phabricator-filetree-view.css' => 'b912ad97',
|
||||||
'rsrc/css/layout/phabricator-source-code-view.css' => 'aea41829',
|
'rsrc/css/layout/phabricator-source-code-view.css' => 'aea41829',
|
||||||
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
|
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
|
||||||
'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68',
|
'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68',
|
||||||
@@ -136,7 +136,7 @@ return array(
|
|||||||
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6',
|
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6',
|
||||||
'rsrc/css/phui/object-item/phui-oi-list-view.css' => '6ae18df0',
|
'rsrc/css/phui/object-item/phui-oi-list-view.css' => '6ae18df0',
|
||||||
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea',
|
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea',
|
||||||
'rsrc/css/phui/phui-action-list.css' => 'f7f61a34',
|
'rsrc/css/phui/phui-action-list.css' => '0bcd9a45',
|
||||||
'rsrc/css/phui/phui-action-panel.css' => 'b4798122',
|
'rsrc/css/phui/phui-action-panel.css' => 'b4798122',
|
||||||
'rsrc/css/phui/phui-badge.css' => '22c0cf4f',
|
'rsrc/css/phui/phui-badge.css' => '22c0cf4f',
|
||||||
'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3',
|
'rsrc/css/phui/phui-basic-nav-view.css' => '98c11ab3',
|
||||||
@@ -176,7 +176,7 @@ return array(
|
|||||||
'rsrc/css/phui/phui-spacing.css' => '042804d6',
|
'rsrc/css/phui/phui-spacing.css' => '042804d6',
|
||||||
'rsrc/css/phui/phui-status.css' => 'd5263e49',
|
'rsrc/css/phui/phui-status.css' => 'd5263e49',
|
||||||
'rsrc/css/phui/phui-tag-view.css' => 'b4719c50',
|
'rsrc/css/phui/phui-tag-view.css' => 'b4719c50',
|
||||||
'rsrc/css/phui/phui-timeline-view.css' => 'e2ef62b1',
|
'rsrc/css/phui/phui-timeline-view.css' => '6ddf8126',
|
||||||
'rsrc/css/phui/phui-two-column-view.css' => '44ec4951',
|
'rsrc/css/phui/phui-two-column-view.css' => '44ec4951',
|
||||||
'rsrc/css/phui/workboards/phui-workboard-color.css' => '783cdff5',
|
'rsrc/css/phui/workboards/phui-workboard-color.css' => '783cdff5',
|
||||||
'rsrc/css/phui/workboards/phui-workboard.css' => '3bc85455',
|
'rsrc/css/phui/workboards/phui-workboard.css' => '3bc85455',
|
||||||
@@ -397,8 +397,8 @@ return array(
|
|||||||
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '408bf173',
|
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '408bf173',
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375',
|
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375',
|
||||||
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
|
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
|
||||||
'rsrc/js/application/diff/DiffChangeset.js' => '99abf4cd',
|
'rsrc/js/application/diff/DiffChangeset.js' => 'b49b59d6',
|
||||||
'rsrc/js/application/diff/DiffChangesetList.js' => '3b77efdd',
|
'rsrc/js/application/diff/DiffChangesetList.js' => '1f2e5265',
|
||||||
'rsrc/js/application/diff/DiffInline.js' => 'e83d28f3',
|
'rsrc/js/application/diff/DiffInline.js' => 'e83d28f3',
|
||||||
'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832',
|
'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832',
|
||||||
'rsrc/js/application/differential/behavior-comment-preview.js' => '51c5ad07',
|
'rsrc/js/application/differential/behavior-comment-preview.js' => '51c5ad07',
|
||||||
@@ -500,7 +500,7 @@ return array(
|
|||||||
'rsrc/js/core/behavior-more.js' => 'a80d0378',
|
'rsrc/js/core/behavior-more.js' => 'a80d0378',
|
||||||
'rsrc/js/core/behavior-object-selector.js' => '77c1f0b0',
|
'rsrc/js/core/behavior-object-selector.js' => '77c1f0b0',
|
||||||
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
|
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
|
||||||
'rsrc/js/core/behavior-phabricator-nav.js' => '947753e0',
|
'rsrc/js/core/behavior-phabricator-nav.js' => '81144dfa',
|
||||||
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'acd29eee',
|
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'acd29eee',
|
||||||
'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207',
|
'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207',
|
||||||
'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b',
|
'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b',
|
||||||
@@ -534,7 +534,7 @@ return array(
|
|||||||
'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac',
|
'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac',
|
||||||
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03',
|
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03',
|
||||||
'rsrc/js/phuix/PHUIXExample.js' => '68af71ca',
|
'rsrc/js/phuix/PHUIXExample.js' => '68af71ca',
|
||||||
'rsrc/js/phuix/PHUIXFormControl.js' => '1dd0870c',
|
'rsrc/js/phuix/PHUIXFormControl.js' => '16ad6224',
|
||||||
'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b',
|
'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b',
|
||||||
),
|
),
|
||||||
'symbols' => array(
|
'symbols' => array(
|
||||||
@@ -659,7 +659,7 @@ return array(
|
|||||||
'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0',
|
'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0',
|
||||||
'javelin-behavior-phabricator-keyboard-shortcuts' => '01fca1f0',
|
'javelin-behavior-phabricator-keyboard-shortcuts' => '01fca1f0',
|
||||||
'javelin-behavior-phabricator-line-linker' => '1499a8cb',
|
'javelin-behavior-phabricator-line-linker' => '1499a8cb',
|
||||||
'javelin-behavior-phabricator-nav' => '947753e0',
|
'javelin-behavior-phabricator-nav' => '81144dfa',
|
||||||
'javelin-behavior-phabricator-notification-example' => '8ce821c5',
|
'javelin-behavior-phabricator-notification-example' => '8ce821c5',
|
||||||
'javelin-behavior-phabricator-object-selector' => '77c1f0b0',
|
'javelin-behavior-phabricator-object-selector' => '77c1f0b0',
|
||||||
'javelin-behavior-phabricator-oncopy' => '2926fff2',
|
'javelin-behavior-phabricator-oncopy' => '2926fff2',
|
||||||
@@ -768,7 +768,7 @@ return array(
|
|||||||
'path-typeahead' => 'f7fc67ec',
|
'path-typeahead' => 'f7fc67ec',
|
||||||
'people-picture-menu-item-css' => 'a06f7f34',
|
'people-picture-menu-item-css' => 'a06f7f34',
|
||||||
'people-profile-css' => '4df76faf',
|
'people-profile-css' => '4df76faf',
|
||||||
'phabricator-action-list-view-css' => 'f7f61a34',
|
'phabricator-action-list-view-css' => '0bcd9a45',
|
||||||
'phabricator-busy' => '59a7976a',
|
'phabricator-busy' => '59a7976a',
|
||||||
'phabricator-chatlog-css' => 'd295b020',
|
'phabricator-chatlog-css' => 'd295b020',
|
||||||
'phabricator-content-source-view-css' => '4b8b05d4',
|
'phabricator-content-source-view-css' => '4b8b05d4',
|
||||||
@@ -777,8 +777,8 @@ return array(
|
|||||||
'phabricator-darklog' => 'c8e1ffe3',
|
'phabricator-darklog' => 'c8e1ffe3',
|
||||||
'phabricator-darkmessage' => 'c48cccdd',
|
'phabricator-darkmessage' => 'c48cccdd',
|
||||||
'phabricator-dashboard-css' => 'fe5b1869',
|
'phabricator-dashboard-css' => 'fe5b1869',
|
||||||
'phabricator-diff-changeset' => '99abf4cd',
|
'phabricator-diff-changeset' => 'b49b59d6',
|
||||||
'phabricator-diff-changeset-list' => '3b77efdd',
|
'phabricator-diff-changeset-list' => '1f2e5265',
|
||||||
'phabricator-diff-inline' => 'e83d28f3',
|
'phabricator-diff-inline' => 'e83d28f3',
|
||||||
'phabricator-drag-and-drop-file-upload' => '58dea2fa',
|
'phabricator-drag-and-drop-file-upload' => '58dea2fa',
|
||||||
'phabricator-draggable-list' => 'bea6e7f4',
|
'phabricator-draggable-list' => 'bea6e7f4',
|
||||||
@@ -786,12 +786,12 @@ return array(
|
|||||||
'phabricator-favicon' => '1fe2510c',
|
'phabricator-favicon' => '1fe2510c',
|
||||||
'phabricator-feed-css' => 'ecd4ec57',
|
'phabricator-feed-css' => 'ecd4ec57',
|
||||||
'phabricator-file-upload' => '680ea2c8',
|
'phabricator-file-upload' => '680ea2c8',
|
||||||
'phabricator-filetree-view-css' => 'fccf9f82',
|
'phabricator-filetree-view-css' => 'b912ad97',
|
||||||
'phabricator-flag-css' => 'bba8f811',
|
'phabricator-flag-css' => 'bba8f811',
|
||||||
'phabricator-keyboard-shortcut' => '1ae869f2',
|
'phabricator-keyboard-shortcut' => '1ae869f2',
|
||||||
'phabricator-keyboard-shortcut-manager' => 'c19dd9b9',
|
'phabricator-keyboard-shortcut-manager' => 'c19dd9b9',
|
||||||
'phabricator-main-menu-view' => '7821ca89',
|
'phabricator-main-menu-view' => '7821ca89',
|
||||||
'phabricator-nav-view-css' => 'faf6a6fc',
|
'phabricator-nav-view-css' => '028126f6',
|
||||||
'phabricator-notification' => '008faf9c',
|
'phabricator-notification' => '008faf9c',
|
||||||
'phabricator-notification-css' => '457861ec',
|
'phabricator-notification-css' => '457861ec',
|
||||||
'phabricator-notification-menu-css' => '10685bd4',
|
'phabricator-notification-menu-css' => '10685bd4',
|
||||||
@@ -876,7 +876,7 @@ return array(
|
|||||||
'phui-status-list-view-css' => 'd5263e49',
|
'phui-status-list-view-css' => 'd5263e49',
|
||||||
'phui-tag-view-css' => 'b4719c50',
|
'phui-tag-view-css' => 'b4719c50',
|
||||||
'phui-theme-css' => '9f261c6b',
|
'phui-theme-css' => '9f261c6b',
|
||||||
'phui-timeline-view-css' => 'e2ef62b1',
|
'phui-timeline-view-css' => '6ddf8126',
|
||||||
'phui-two-column-view-css' => '44ec4951',
|
'phui-two-column-view-css' => '44ec4951',
|
||||||
'phui-workboard-color-css' => '783cdff5',
|
'phui-workboard-color-css' => '783cdff5',
|
||||||
'phui-workboard-view-css' => '3bc85455',
|
'phui-workboard-view-css' => '3bc85455',
|
||||||
@@ -887,7 +887,7 @@ return array(
|
|||||||
'phuix-autocomplete' => 'e0731603',
|
'phuix-autocomplete' => 'e0731603',
|
||||||
'phuix-button-view' => '8a91e1ac',
|
'phuix-button-view' => '8a91e1ac',
|
||||||
'phuix-dropdown-menu' => '04b2ae03',
|
'phuix-dropdown-menu' => '04b2ae03',
|
||||||
'phuix-form-control-view' => '1dd0870c',
|
'phuix-form-control-view' => '16ad6224',
|
||||||
'phuix-icon-view' => 'bff6884b',
|
'phuix-icon-view' => 'bff6884b',
|
||||||
'policy-css' => '957ea14c',
|
'policy-css' => '957ea14c',
|
||||||
'policy-edit-css' => '815c66f7',
|
'policy-edit-css' => '815c66f7',
|
||||||
@@ -998,6 +998,10 @@ return array(
|
|||||||
'aphront-typeahead-control-css',
|
'aphront-typeahead-control-css',
|
||||||
'phui-tag-view-css',
|
'phui-tag-view-css',
|
||||||
),
|
),
|
||||||
|
'16ad6224' => array(
|
||||||
|
'javelin-install',
|
||||||
|
'javelin-dom',
|
||||||
|
),
|
||||||
'17bb8539' => array(
|
'17bb8539' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
@@ -1029,10 +1033,6 @@ return array(
|
|||||||
'javelin-request',
|
'javelin-request',
|
||||||
'javelin-uri',
|
'javelin-uri',
|
||||||
),
|
),
|
||||||
'1dd0870c' => array(
|
|
||||||
'javelin-install',
|
|
||||||
'javelin-dom',
|
|
||||||
),
|
|
||||||
'1e911d0f' => array(
|
'1e911d0f' => array(
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
'javelin-request',
|
'javelin-request',
|
||||||
@@ -1044,6 +1044,10 @@ return array(
|
|||||||
'javelin-uri',
|
'javelin-uri',
|
||||||
'javelin-routable',
|
'javelin-routable',
|
||||||
),
|
),
|
||||||
|
'1f2e5265' => array(
|
||||||
|
'javelin-install',
|
||||||
|
'phuix-button-view',
|
||||||
|
),
|
||||||
'1f6794f6' => array(
|
'1f6794f6' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
@@ -1143,10 +1147,6 @@ return array(
|
|||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
'javelin-magical-init',
|
'javelin-magical-init',
|
||||||
),
|
),
|
||||||
'3b77efdd' => array(
|
|
||||||
'javelin-install',
|
|
||||||
'phuix-button-view',
|
|
||||||
),
|
|
||||||
'3cb0b2fc' => array(
|
'3cb0b2fc' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
@@ -1564,6 +1564,16 @@ return array(
|
|||||||
'7f243deb' => array(
|
'7f243deb' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
),
|
),
|
||||||
|
'81144dfa' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-behavior-device',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-magical-init',
|
||||||
|
'javelin-vector',
|
||||||
|
'javelin-request',
|
||||||
|
'javelin-util',
|
||||||
|
),
|
||||||
'834a1173' => array(
|
'834a1173' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-scrollbar',
|
'javelin-scrollbar',
|
||||||
@@ -1651,16 +1661,6 @@ return array(
|
|||||||
'javelin-workflow',
|
'javelin-workflow',
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
),
|
),
|
||||||
'947753e0' => array(
|
|
||||||
'javelin-behavior',
|
|
||||||
'javelin-behavior-device',
|
|
||||||
'javelin-stratcom',
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-magical-init',
|
|
||||||
'javelin-vector',
|
|
||||||
'javelin-request',
|
|
||||||
'javelin-util',
|
|
||||||
),
|
|
||||||
'949c0fe5' => array(
|
'949c0fe5' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
),
|
),
|
||||||
@@ -1681,17 +1681,6 @@ return array(
|
|||||||
'javelin-mask',
|
'javelin-mask',
|
||||||
'phabricator-drag-and-drop-file-upload',
|
'phabricator-drag-and-drop-file-upload',
|
||||||
),
|
),
|
||||||
'99abf4cd' => array(
|
|
||||||
'javelin-dom',
|
|
||||||
'javelin-util',
|
|
||||||
'javelin-stratcom',
|
|
||||||
'javelin-install',
|
|
||||||
'javelin-workflow',
|
|
||||||
'javelin-router',
|
|
||||||
'javelin-behavior-device',
|
|
||||||
'javelin-vector',
|
|
||||||
'phabricator-diff-inline',
|
|
||||||
),
|
|
||||||
'9a6dd75c' => array(
|
'9a6dd75c' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
@@ -1840,6 +1829,17 @@ return array(
|
|||||||
'b3e7d692' => array(
|
'b3e7d692' => array(
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
),
|
),
|
||||||
|
'b49b59d6' => array(
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-util',
|
||||||
|
'javelin-stratcom',
|
||||||
|
'javelin-install',
|
||||||
|
'javelin-workflow',
|
||||||
|
'javelin-router',
|
||||||
|
'javelin-behavior-device',
|
||||||
|
'javelin-vector',
|
||||||
|
'phabricator-diff-inline',
|
||||||
|
),
|
||||||
'b59e1e96' => array(
|
'b59e1e96' => array(
|
||||||
'javelin-behavior',
|
'javelin-behavior',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
|
|||||||
@@ -1622,5 +1622,9 @@
|
|||||||
"zipper_mouth": "\ud83e\udd10",
|
"zipper_mouth": "\ud83e\udd10",
|
||||||
"zzz": "\ud83d\udca4",
|
"zzz": "\ud83d\udca4",
|
||||||
"100": "\ud83d\udcaf",
|
"100": "\ud83d\udcaf",
|
||||||
"1234": "\ud83d\udd22"
|
"1234": "\ud83d\udd22",
|
||||||
|
|
||||||
|
"party": "\ud83c\udf89",
|
||||||
|
"celebration": "\ud83c\udf89",
|
||||||
|
"confetti": "\ud83c\udf89"
|
||||||
}
|
}
|
||||||
|
|||||||
2
resources/sql/autopatches/20180207.mail.01.task.sql
Normal file
2
resources/sql/autopatches/20180207.mail.01.task.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
|
||||||
|
DROP originalTitle;
|
||||||
2
resources/sql/autopatches/20180207.mail.02.revision.sql
Normal file
2
resources/sql/autopatches/20180207.mail.02.revision.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE {$NAMESPACE}_differential.differential_revision
|
||||||
|
DROP originalTitle;
|
||||||
2
resources/sql/autopatches/20180207.mail.03.mock.sql
Normal file
2
resources/sql/autopatches/20180207.mail.03.mock.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE {$NAMESPACE}_pholio.pholio_mock
|
||||||
|
DROP originalName;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
|
||||||
|
ADD closedEpoch INT UNSIGNED;
|
||||||
|
|
||||||
|
ALTER TABLE {$NAMESPACE}_maniphest.maniphest_task
|
||||||
|
ADD closerPHID VARBINARY(64);
|
||||||
65
resources/sql/autopatches/20180208.maniphest.02.populate.php
Normal file
65
resources/sql/autopatches/20180208.maniphest.02.populate.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$table = new ManiphestTask();
|
||||||
|
$conn = $table->establishConnection('w');
|
||||||
|
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||||
|
|
||||||
|
foreach (new LiskMigrationIterator($table) as $task) {
|
||||||
|
if ($task->getClosedEpoch()) {
|
||||||
|
// Task already has a closed date.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = $task->getStatus();
|
||||||
|
if (!ManiphestTaskStatus::isClosedStatus($status)) {
|
||||||
|
// Task isn't closed.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look through the transactions from newest to oldest until we find one
|
||||||
|
// where the task was closed. A merge also counts as a close, even though
|
||||||
|
// it doesn't currently produce a separate transaction.
|
||||||
|
|
||||||
|
$type_merge = ManiphestTaskStatusTransaction::TRANSACTIONTYPE;
|
||||||
|
$type_status = ManiphestTaskMergedIntoTransaction::TRANSACTIONTYPE;
|
||||||
|
|
||||||
|
$xactions = id(new ManiphestTransactionQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withObjectPHIDs(array($task->getPHID()))
|
||||||
|
->withTransactionTypes(
|
||||||
|
array(
|
||||||
|
$type_merge,
|
||||||
|
$type_status,
|
||||||
|
))
|
||||||
|
->execute();
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
$old = $xaction->getOldValue();
|
||||||
|
$new = $xaction->getNewValue();
|
||||||
|
|
||||||
|
$type = $xaction->getTransactionType();
|
||||||
|
|
||||||
|
// If this is a status change, but is not a close, don't use it.
|
||||||
|
// (We always use merges, even though it's possible to merge a task which
|
||||||
|
// was previously closed: we can't tell when this happens very easily.)
|
||||||
|
if ($type === $type_status) {
|
||||||
|
if (!ManiphestTaskStatus::isClosedStatus($new)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($old && ManiphestTaskStatus::isClosedStatus($old)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queryfx(
|
||||||
|
$conn,
|
||||||
|
'UPDATE %T SET closedEpoch = %d, closerPHID = %ns
|
||||||
|
WHERE id = %d',
|
||||||
|
$table->getTableName(),
|
||||||
|
$xaction->getDateCreated(),
|
||||||
|
$xaction->getAuthorPHID(),
|
||||||
|
$task->getID());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
scripts/setup/manage_conduit.php
Executable file
21
scripts/setup/manage_conduit.php
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$root = dirname(dirname(dirname(__FILE__)));
|
||||||
|
require_once $root.'/scripts/init/init-script.php';
|
||||||
|
|
||||||
|
$args = new PhutilArgumentParser($argv);
|
||||||
|
$args->setTagline(pht('manage Conduit'));
|
||||||
|
$args->setSynopsis(<<<EOSYNOPSIS
|
||||||
|
**conduit** __command__ [__options__]
|
||||||
|
Manage Conduit.
|
||||||
|
|
||||||
|
EOSYNOPSIS
|
||||||
|
);
|
||||||
|
$args->parseStandardArguments();
|
||||||
|
|
||||||
|
$workflows = id(new PhutilClassMapQuery())
|
||||||
|
->setAncestorClass('PhabricatorConduitManagementWorkflow')
|
||||||
|
->execute();
|
||||||
|
$workflows[] = new PhutilHelpArgumentWorkflow();
|
||||||
|
$args->parseWorkflows($workflows);
|
||||||
@@ -487,6 +487,7 @@ phutil_register_library_map(array(
|
|||||||
'DifferentialLintField' => 'applications/differential/customfield/DifferentialLintField.php',
|
'DifferentialLintField' => 'applications/differential/customfield/DifferentialLintField.php',
|
||||||
'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php',
|
'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php',
|
||||||
'DifferentialLocalCommitsView' => 'applications/differential/view/DifferentialLocalCommitsView.php',
|
'DifferentialLocalCommitsView' => 'applications/differential/view/DifferentialLocalCommitsView.php',
|
||||||
|
'DifferentialMailEngineExtension' => 'applications/differential/engineextension/DifferentialMailEngineExtension.php',
|
||||||
'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php',
|
'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php',
|
||||||
'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php',
|
'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php',
|
||||||
'DifferentialModernHunk' => 'applications/differential/storage/DifferentialModernHunk.php',
|
'DifferentialModernHunk' => 'applications/differential/storage/DifferentialModernHunk.php',
|
||||||
@@ -1345,6 +1346,7 @@ phutil_register_library_map(array(
|
|||||||
'HarbormasterWaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php',
|
'HarbormasterWaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php',
|
||||||
'HarbormasterWorker' => 'applications/harbormaster/worker/HarbormasterWorker.php',
|
'HarbormasterWorker' => 'applications/harbormaster/worker/HarbormasterWorker.php',
|
||||||
'HarbormasterWorkingCopyArtifact' => 'applications/harbormaster/artifact/HarbormasterWorkingCopyArtifact.php',
|
'HarbormasterWorkingCopyArtifact' => 'applications/harbormaster/artifact/HarbormasterWorkingCopyArtifact.php',
|
||||||
|
'HeraldActingUserField' => 'applications/herald/field/HeraldActingUserField.php',
|
||||||
'HeraldAction' => 'applications/herald/action/HeraldAction.php',
|
'HeraldAction' => 'applications/herald/action/HeraldAction.php',
|
||||||
'HeraldActionGroup' => 'applications/herald/action/HeraldActionGroup.php',
|
'HeraldActionGroup' => 'applications/herald/action/HeraldActionGroup.php',
|
||||||
'HeraldActionRecord' => 'applications/herald/storage/HeraldActionRecord.php',
|
'HeraldActionRecord' => 'applications/herald/storage/HeraldActionRecord.php',
|
||||||
@@ -1525,13 +1527,10 @@ phutil_register_library_map(array(
|
|||||||
'ManiphestEditProjectsCapability' => 'applications/maniphest/capability/ManiphestEditProjectsCapability.php',
|
'ManiphestEditProjectsCapability' => 'applications/maniphest/capability/ManiphestEditProjectsCapability.php',
|
||||||
'ManiphestEditStatusCapability' => 'applications/maniphest/capability/ManiphestEditStatusCapability.php',
|
'ManiphestEditStatusCapability' => 'applications/maniphest/capability/ManiphestEditStatusCapability.php',
|
||||||
'ManiphestEmailCommand' => 'applications/maniphest/command/ManiphestEmailCommand.php',
|
'ManiphestEmailCommand' => 'applications/maniphest/command/ManiphestEmailCommand.php',
|
||||||
'ManiphestExcelDefaultFormat' => 'applications/maniphest/export/ManiphestExcelDefaultFormat.php',
|
|
||||||
'ManiphestExcelFormat' => 'applications/maniphest/export/ManiphestExcelFormat.php',
|
|
||||||
'ManiphestExcelFormatTestCase' => 'applications/maniphest/export/__tests__/ManiphestExcelFormatTestCase.php',
|
|
||||||
'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php',
|
|
||||||
'ManiphestGetTaskTransactionsConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestGetTaskTransactionsConduitAPIMethod.php',
|
'ManiphestGetTaskTransactionsConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestGetTaskTransactionsConduitAPIMethod.php',
|
||||||
'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php',
|
'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php',
|
||||||
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
|
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
|
||||||
|
'ManiphestMailEngineExtension' => 'applications/maniphest/engineextension/ManiphestMailEngineExtension.php',
|
||||||
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
|
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
|
||||||
'ManiphestPointsConfigType' => 'applications/maniphest/config/ManiphestPointsConfigType.php',
|
'ManiphestPointsConfigType' => 'applications/maniphest/config/ManiphestPointsConfigType.php',
|
||||||
'ManiphestPrioritiesConfigType' => 'applications/maniphest/config/ManiphestPrioritiesConfigType.php',
|
'ManiphestPrioritiesConfigType' => 'applications/maniphest/config/ManiphestPrioritiesConfigType.php',
|
||||||
@@ -1965,6 +1964,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
|
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
|
||||||
'PhabricatorApplicationEditor' => 'applications/meta/editor/PhabricatorApplicationEditor.php',
|
'PhabricatorApplicationEditor' => 'applications/meta/editor/PhabricatorApplicationEditor.php',
|
||||||
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
|
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
|
||||||
|
'PhabricatorApplicationObjectMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorApplicationObjectMailEngineExtension.php',
|
||||||
'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php',
|
'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php',
|
||||||
'PhabricatorApplicationPolicyChangeTransaction' => 'applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php',
|
'PhabricatorApplicationPolicyChangeTransaction' => 'applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php',
|
||||||
'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php',
|
'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php',
|
||||||
@@ -2226,6 +2226,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorBoardResponseEngine' => 'applications/project/engine/PhabricatorBoardResponseEngine.php',
|
'PhabricatorBoardResponseEngine' => 'applications/project/engine/PhabricatorBoardResponseEngine.php',
|
||||||
'PhabricatorBoolConfigType' => 'applications/config/type/PhabricatorBoolConfigType.php',
|
'PhabricatorBoolConfigType' => 'applications/config/type/PhabricatorBoolConfigType.php',
|
||||||
'PhabricatorBoolEditField' => 'applications/transactions/editfield/PhabricatorBoolEditField.php',
|
'PhabricatorBoolEditField' => 'applications/transactions/editfield/PhabricatorBoolEditField.php',
|
||||||
|
'PhabricatorBoolMailStamp' => 'applications/metamta/stamp/PhabricatorBoolMailStamp.php',
|
||||||
'PhabricatorBritishEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorBritishEnglishTranslation.php',
|
'PhabricatorBritishEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorBritishEnglishTranslation.php',
|
||||||
'PhabricatorBuildbotController' => 'extensions/buildbot/controller/PhabricatorBuildbotController.php',
|
'PhabricatorBuildbotController' => 'extensions/buildbot/controller/PhabricatorBuildbotController.php',
|
||||||
'PhabricatorBuiltinDraftEngine' => 'applications/transactions/draft/PhabricatorBuiltinDraftEngine.php',
|
'PhabricatorBuiltinDraftEngine' => 'applications/transactions/draft/PhabricatorBuiltinDraftEngine.php',
|
||||||
@@ -2234,9 +2235,10 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php',
|
'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php',
|
||||||
'PhabricatorBulkEditGroup' => 'applications/transactions/bulk/PhabricatorBulkEditGroup.php',
|
'PhabricatorBulkEditGroup' => 'applications/transactions/bulk/PhabricatorBulkEditGroup.php',
|
||||||
'PhabricatorBulkEngine' => 'applications/transactions/bulk/PhabricatorBulkEngine.php',
|
'PhabricatorBulkEngine' => 'applications/transactions/bulk/PhabricatorBulkEngine.php',
|
||||||
|
'PhabricatorBulkManagementExportWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementExportWorkflow.php',
|
||||||
'PhabricatorBulkManagementMakeSilentWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementMakeSilentWorkflow.php',
|
'PhabricatorBulkManagementMakeSilentWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementMakeSilentWorkflow.php',
|
||||||
'PhabricatorBulkManagementWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementWorkflow.php',
|
'PhabricatorBulkManagementWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementWorkflow.php',
|
||||||
'PhabricatorCSVExportFormat' => 'infrastructure/export/PhabricatorCSVExportFormat.php',
|
'PhabricatorCSVExportFormat' => 'infrastructure/export/format/PhabricatorCSVExportFormat.php',
|
||||||
'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php',
|
'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php',
|
||||||
'PhabricatorCacheEngine' => 'applications/system/engine/PhabricatorCacheEngine.php',
|
'PhabricatorCacheEngine' => 'applications/system/engine/PhabricatorCacheEngine.php',
|
||||||
'PhabricatorCacheEngineExtension' => 'applications/system/engine/PhabricatorCacheEngineExtension.php',
|
'PhabricatorCacheEngineExtension' => 'applications/system/engine/PhabricatorCacheEngineExtension.php',
|
||||||
@@ -2414,6 +2416,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorClusterExceptionHandler' => 'infrastructure/cluster/exception/PhabricatorClusterExceptionHandler.php',
|
'PhabricatorClusterExceptionHandler' => 'infrastructure/cluster/exception/PhabricatorClusterExceptionHandler.php',
|
||||||
'PhabricatorClusterImpossibleWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImpossibleWriteException.php',
|
'PhabricatorClusterImpossibleWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImpossibleWriteException.php',
|
||||||
'PhabricatorClusterImproperWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImproperWriteException.php',
|
'PhabricatorClusterImproperWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImproperWriteException.php',
|
||||||
|
'PhabricatorClusterMailersConfigType' => 'infrastructure/cluster/config/PhabricatorClusterMailersConfigType.php',
|
||||||
'PhabricatorClusterNoHostForRoleException' => 'infrastructure/cluster/exception/PhabricatorClusterNoHostForRoleException.php',
|
'PhabricatorClusterNoHostForRoleException' => 'infrastructure/cluster/exception/PhabricatorClusterNoHostForRoleException.php',
|
||||||
'PhabricatorClusterSearchConfigType' => 'infrastructure/cluster/config/PhabricatorClusterSearchConfigType.php',
|
'PhabricatorClusterSearchConfigType' => 'infrastructure/cluster/config/PhabricatorClusterSearchConfigType.php',
|
||||||
'PhabricatorClusterServiceHealthRecord' => 'infrastructure/cluster/PhabricatorClusterServiceHealthRecord.php',
|
'PhabricatorClusterServiceHealthRecord' => 'infrastructure/cluster/PhabricatorClusterServiceHealthRecord.php',
|
||||||
@@ -2432,6 +2435,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorCommonPasswords' => 'applications/auth/constants/PhabricatorCommonPasswords.php',
|
'PhabricatorCommonPasswords' => 'applications/auth/constants/PhabricatorCommonPasswords.php',
|
||||||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
||||||
'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php',
|
'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php',
|
||||||
|
'PhabricatorConduitCallManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitCallManagementWorkflow.php',
|
||||||
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
||||||
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
||||||
'PhabricatorConduitContentSource' => 'infrastructure/contentsource/PhabricatorConduitContentSource.php',
|
'PhabricatorConduitContentSource' => 'infrastructure/contentsource/PhabricatorConduitContentSource.php',
|
||||||
@@ -2442,6 +2446,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php',
|
'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php',
|
||||||
'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php',
|
'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php',
|
||||||
'PhabricatorConduitLogSearchEngine' => 'applications/conduit/query/PhabricatorConduitLogSearchEngine.php',
|
'PhabricatorConduitLogSearchEngine' => 'applications/conduit/query/PhabricatorConduitLogSearchEngine.php',
|
||||||
|
'PhabricatorConduitManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitManagementWorkflow.php',
|
||||||
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php',
|
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php',
|
||||||
'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php',
|
'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php',
|
||||||
'PhabricatorConduitRequestExceptionHandler' => 'aphront/handler/PhabricatorConduitRequestExceptionHandler.php',
|
'PhabricatorConduitRequestExceptionHandler' => 'aphront/handler/PhabricatorConduitRequestExceptionHandler.php',
|
||||||
@@ -2587,6 +2592,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorCustomFieldEditEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php',
|
'PhabricatorCustomFieldEditEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php',
|
||||||
'PhabricatorCustomFieldEditField' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php',
|
'PhabricatorCustomFieldEditField' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php',
|
||||||
'PhabricatorCustomFieldEditType' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php',
|
'PhabricatorCustomFieldEditType' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php',
|
||||||
|
'PhabricatorCustomFieldExportEngineExtension' => 'infrastructure/export/engine/PhabricatorCustomFieldExportEngineExtension.php',
|
||||||
'PhabricatorCustomFieldFulltextEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldFulltextEngineExtension.php',
|
'PhabricatorCustomFieldFulltextEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldFulltextEngineExtension.php',
|
||||||
'PhabricatorCustomFieldHeraldAction' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldAction.php',
|
'PhabricatorCustomFieldHeraldAction' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldAction.php',
|
||||||
'PhabricatorCustomFieldHeraldActionGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldActionGroup.php',
|
'PhabricatorCustomFieldHeraldActionGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldActionGroup.php',
|
||||||
@@ -2751,6 +2757,8 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorDraftEngine' => 'applications/transactions/draft/PhabricatorDraftEngine.php',
|
'PhabricatorDraftEngine' => 'applications/transactions/draft/PhabricatorDraftEngine.php',
|
||||||
'PhabricatorDraftInterface' => 'applications/transactions/draft/PhabricatorDraftInterface.php',
|
'PhabricatorDraftInterface' => 'applications/transactions/draft/PhabricatorDraftInterface.php',
|
||||||
'PhabricatorDrydockApplication' => 'applications/drydock/application/PhabricatorDrydockApplication.php',
|
'PhabricatorDrydockApplication' => 'applications/drydock/application/PhabricatorDrydockApplication.php',
|
||||||
|
'PhabricatorEdgeChangeRecord' => 'infrastructure/edges/util/PhabricatorEdgeChangeRecord.php',
|
||||||
|
'PhabricatorEdgeChangeRecordTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeChangeRecordTestCase.php',
|
||||||
'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php',
|
'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php',
|
||||||
'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php',
|
'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php',
|
||||||
'PhabricatorEdgeCycleException' => 'infrastructure/edges/exception/PhabricatorEdgeCycleException.php',
|
'PhabricatorEdgeCycleException' => 'infrastructure/edges/exception/PhabricatorEdgeCycleException.php',
|
||||||
@@ -2814,6 +2822,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorEditPage' => 'applications/transactions/editengine/PhabricatorEditPage.php',
|
'PhabricatorEditPage' => 'applications/transactions/editengine/PhabricatorEditPage.php',
|
||||||
'PhabricatorEditType' => 'applications/transactions/edittype/PhabricatorEditType.php',
|
'PhabricatorEditType' => 'applications/transactions/edittype/PhabricatorEditType.php',
|
||||||
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
|
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
|
||||||
|
'PhabricatorEditorMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditorMailEngineExtension.php',
|
||||||
'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php',
|
'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php',
|
||||||
'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php',
|
'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php',
|
||||||
'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php',
|
'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php',
|
||||||
@@ -2830,6 +2839,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorEmailPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailPreferencesSettingsPanel.php',
|
'PhabricatorEmailPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailPreferencesSettingsPanel.php',
|
||||||
'PhabricatorEmailRePrefixSetting' => 'applications/settings/setting/PhabricatorEmailRePrefixSetting.php',
|
'PhabricatorEmailRePrefixSetting' => 'applications/settings/setting/PhabricatorEmailRePrefixSetting.php',
|
||||||
'PhabricatorEmailSelfActionsSetting' => 'applications/settings/setting/PhabricatorEmailSelfActionsSetting.php',
|
'PhabricatorEmailSelfActionsSetting' => 'applications/settings/setting/PhabricatorEmailSelfActionsSetting.php',
|
||||||
|
'PhabricatorEmailStampsSetting' => 'applications/settings/setting/PhabricatorEmailStampsSetting.php',
|
||||||
'PhabricatorEmailTagsSetting' => 'applications/settings/setting/PhabricatorEmailTagsSetting.php',
|
'PhabricatorEmailTagsSetting' => 'applications/settings/setting/PhabricatorEmailTagsSetting.php',
|
||||||
'PhabricatorEmailVarySubjectsSetting' => 'applications/settings/setting/PhabricatorEmailVarySubjectsSetting.php',
|
'PhabricatorEmailVarySubjectsSetting' => 'applications/settings/setting/PhabricatorEmailVarySubjectsSetting.php',
|
||||||
'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php',
|
'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php',
|
||||||
@@ -2842,15 +2852,20 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php',
|
'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php',
|
||||||
'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php',
|
'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php',
|
||||||
'PhabricatorEpochEditField' => 'applications/transactions/editfield/PhabricatorEpochEditField.php',
|
'PhabricatorEpochEditField' => 'applications/transactions/editfield/PhabricatorEpochEditField.php',
|
||||||
'PhabricatorEpochExportField' => 'infrastructure/export/PhabricatorEpochExportField.php',
|
'PhabricatorEpochExportField' => 'infrastructure/export/field/PhabricatorEpochExportField.php',
|
||||||
'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php',
|
'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php',
|
||||||
'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php',
|
'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php',
|
||||||
'PhabricatorEventListener' => 'infrastructure/events/PhabricatorEventListener.php',
|
'PhabricatorEventListener' => 'infrastructure/events/PhabricatorEventListener.php',
|
||||||
'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php',
|
'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php',
|
||||||
'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php',
|
'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php',
|
||||||
|
'PhabricatorExcelExportFormat' => 'infrastructure/export/format/PhabricatorExcelExportFormat.php',
|
||||||
'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php',
|
'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php',
|
||||||
'PhabricatorExportField' => 'infrastructure/export/PhabricatorExportField.php',
|
'PhabricatorExportEngine' => 'infrastructure/export/engine/PhabricatorExportEngine.php',
|
||||||
'PhabricatorExportFormat' => 'infrastructure/export/PhabricatorExportFormat.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',
|
'PhabricatorExtendedPolicyInterface' => 'applications/policy/interface/PhabricatorExtendedPolicyInterface.php',
|
||||||
'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php',
|
'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php',
|
||||||
'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php',
|
'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php',
|
||||||
@@ -3020,6 +3035,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorGDSetupCheck' => 'applications/config/check/PhabricatorGDSetupCheck.php',
|
'PhabricatorGDSetupCheck' => 'applications/config/check/PhabricatorGDSetupCheck.php',
|
||||||
'PhabricatorGarbageCollector' => 'infrastructure/daemon/garbagecollector/PhabricatorGarbageCollector.php',
|
'PhabricatorGarbageCollector' => 'infrastructure/daemon/garbagecollector/PhabricatorGarbageCollector.php',
|
||||||
'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCollectWorkflow.php',
|
'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCollectWorkflow.php',
|
||||||
|
'PhabricatorGarbageCollectorManagementCompactEdgesWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCompactEdgesWorkflow.php',
|
||||||
'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementSetPolicyWorkflow.php',
|
'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementSetPolicyWorkflow.php',
|
||||||
'PhabricatorGarbageCollectorManagementWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementWorkflow.php',
|
'PhabricatorGarbageCollectorManagementWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementWorkflow.php',
|
||||||
'PhabricatorGeneralCachePurger' => 'applications/cache/purger/PhabricatorGeneralCachePurger.php',
|
'PhabricatorGeneralCachePurger' => 'applications/cache/purger/PhabricatorGeneralCachePurger.php',
|
||||||
@@ -3070,7 +3086,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorHomeProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeProfileMenuItem.php',
|
'PhabricatorHomeProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeProfileMenuItem.php',
|
||||||
'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php',
|
'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php',
|
||||||
'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php',
|
'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php',
|
||||||
'PhabricatorIDExportField' => 'infrastructure/export/PhabricatorIDExportField.php',
|
'PhabricatorIDExportField' => 'infrastructure/export/field/PhabricatorIDExportField.php',
|
||||||
'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php',
|
'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php',
|
||||||
'PhabricatorIDsSearchField' => 'applications/search/field/PhabricatorIDsSearchField.php',
|
'PhabricatorIDsSearchField' => 'applications/search/field/PhabricatorIDsSearchField.php',
|
||||||
'PhabricatorIconDatasource' => 'applications/files/typeahead/PhabricatorIconDatasource.php',
|
'PhabricatorIconDatasource' => 'applications/files/typeahead/PhabricatorIconDatasource.php',
|
||||||
@@ -3094,7 +3110,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
|
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
|
||||||
'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php',
|
'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php',
|
||||||
'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php',
|
'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php',
|
||||||
'PhabricatorIntExportField' => 'infrastructure/export/PhabricatorIntExportField.php',
|
'PhabricatorIntExportField' => 'infrastructure/export/field/PhabricatorIntExportField.php',
|
||||||
'PhabricatorInternalSetting' => 'applications/settings/setting/PhabricatorInternalSetting.php',
|
'PhabricatorInternalSetting' => 'applications/settings/setting/PhabricatorInternalSetting.php',
|
||||||
'PhabricatorInternationalizationManagementExtractWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php',
|
'PhabricatorInternationalizationManagementExtractWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php',
|
||||||
'PhabricatorInternationalizationManagementWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementWorkflow.php',
|
'PhabricatorInternationalizationManagementWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementWorkflow.php',
|
||||||
@@ -3104,7 +3120,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorIteratorFileUploadSource' => 'applications/files/uploadsource/PhabricatorIteratorFileUploadSource.php',
|
'PhabricatorIteratorFileUploadSource' => 'applications/files/uploadsource/PhabricatorIteratorFileUploadSource.php',
|
||||||
'PhabricatorJIRAAuthProvider' => 'applications/auth/provider/PhabricatorJIRAAuthProvider.php',
|
'PhabricatorJIRAAuthProvider' => 'applications/auth/provider/PhabricatorJIRAAuthProvider.php',
|
||||||
'PhabricatorJSONConfigType' => 'applications/config/type/PhabricatorJSONConfigType.php',
|
'PhabricatorJSONConfigType' => 'applications/config/type/PhabricatorJSONConfigType.php',
|
||||||
'PhabricatorJSONExportFormat' => 'infrastructure/export/PhabricatorJSONExportFormat.php',
|
'PhabricatorJSONExportFormat' => 'infrastructure/export/format/PhabricatorJSONExportFormat.php',
|
||||||
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
|
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
|
||||||
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
|
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
|
||||||
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
|
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
|
||||||
@@ -3127,9 +3143,11 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php',
|
'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php',
|
||||||
'PhabricatorLipsumMondrianArtist' => 'applications/lipsum/image/PhabricatorLipsumMondrianArtist.php',
|
'PhabricatorLipsumMondrianArtist' => 'applications/lipsum/image/PhabricatorLipsumMondrianArtist.php',
|
||||||
'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php',
|
'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php',
|
||||||
|
'PhabricatorLiskExportEngineExtension' => 'infrastructure/export/engine/PhabricatorLiskExportEngineExtension.php',
|
||||||
'PhabricatorLiskFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorLiskFulltextEngineExtension.php',
|
'PhabricatorLiskFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorLiskFulltextEngineExtension.php',
|
||||||
'PhabricatorLiskSearchEngineExtension' => 'applications/search/engineextension/PhabricatorLiskSearchEngineExtension.php',
|
'PhabricatorLiskSearchEngineExtension' => 'applications/search/engineextension/PhabricatorLiskSearchEngineExtension.php',
|
||||||
'PhabricatorLiskSerializer' => 'infrastructure/storage/lisk/PhabricatorLiskSerializer.php',
|
'PhabricatorLiskSerializer' => 'infrastructure/storage/lisk/PhabricatorLiskSerializer.php',
|
||||||
|
'PhabricatorListExportField' => 'infrastructure/export/field/PhabricatorListExportField.php',
|
||||||
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php',
|
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php',
|
||||||
'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php',
|
'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php',
|
||||||
'PhabricatorLocaleScopeGuard' => 'infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php',
|
'PhabricatorLocaleScopeGuard' => 'infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php',
|
||||||
@@ -3165,14 +3183,17 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
|
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
|
||||||
'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php',
|
'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php',
|
||||||
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
|
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
|
||||||
|
'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php',
|
||||||
'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php',
|
'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php',
|
||||||
'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php',
|
'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php',
|
||||||
'PhabricatorMailEmailSubjectHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailSubjectHeraldField.php',
|
'PhabricatorMailEmailSubjectHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailSubjectHeraldField.php',
|
||||||
|
'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php',
|
||||||
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php',
|
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php',
|
||||||
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php',
|
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php',
|
||||||
'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php',
|
'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php',
|
||||||
'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php',
|
'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php',
|
||||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
|
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
|
||||||
|
'PhabricatorMailImplementationPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPostmarkAdapter.php',
|
||||||
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
|
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
|
||||||
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php',
|
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php',
|
||||||
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
|
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
|
||||||
@@ -3185,6 +3206,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php',
|
'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php',
|
||||||
'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php',
|
'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php',
|
||||||
'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php',
|
'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php',
|
||||||
|
'PhabricatorMailMustEncryptHeraldAction' => 'applications/metamta/herald/PhabricatorMailMustEncryptHeraldAction.php',
|
||||||
'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php',
|
'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php',
|
||||||
'PhabricatorMailOutboundRoutingHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingHeraldAction.php',
|
'PhabricatorMailOutboundRoutingHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingHeraldAction.php',
|
||||||
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
|
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
|
||||||
@@ -3195,6 +3217,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
||||||
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
||||||
'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php',
|
'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php',
|
||||||
|
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
|
||||||
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
||||||
'PhabricatorMailgunConfigOptions' => 'applications/config/option/PhabricatorMailgunConfigOptions.php',
|
'PhabricatorMailgunConfigOptions' => 'applications/config/option/PhabricatorMailgunConfigOptions.php',
|
||||||
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
||||||
@@ -3254,6 +3277,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php',
|
'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php',
|
||||||
'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php',
|
'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php',
|
||||||
'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php',
|
'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php',
|
||||||
|
'PhabricatorMetaMTAPostmarkReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php',
|
||||||
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php',
|
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php',
|
||||||
'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php',
|
'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php',
|
||||||
'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php',
|
'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php',
|
||||||
@@ -3271,6 +3295,8 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php',
|
'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php',
|
||||||
'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php',
|
'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php',
|
||||||
'PhabricatorMustVerifyEmailController' => 'applications/auth/controller/PhabricatorMustVerifyEmailController.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',
|
'PhabricatorMySQLConfigOptions' => 'applications/config/option/PhabricatorMySQLConfigOptions.php',
|
||||||
'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php',
|
'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php',
|
||||||
'PhabricatorMySQLSearchHost' => 'infrastructure/cluster/search/PhabricatorMySQLSearchHost.php',
|
'PhabricatorMySQLSearchHost' => 'infrastructure/cluster/search/PhabricatorMySQLSearchHost.php',
|
||||||
@@ -3424,10 +3450,12 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php',
|
'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php',
|
||||||
'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php',
|
'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php',
|
||||||
'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php',
|
'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php',
|
||||||
'PhabricatorPHIDExportField' => 'infrastructure/export/PhabricatorPHIDExportField.php',
|
'PhabricatorPHIDExportField' => 'infrastructure/export/field/PhabricatorPHIDExportField.php',
|
||||||
'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php',
|
'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php',
|
||||||
'PhabricatorPHIDListEditField' => 'applications/transactions/editfield/PhabricatorPHIDListEditField.php',
|
'PhabricatorPHIDListEditField' => 'applications/transactions/editfield/PhabricatorPHIDListEditField.php',
|
||||||
'PhabricatorPHIDListEditType' => 'applications/transactions/edittype/PhabricatorPHIDListEditType.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',
|
'PhabricatorPHIDResolver' => 'applications/phid/resolver/PhabricatorPHIDResolver.php',
|
||||||
'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php',
|
'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php',
|
||||||
'PhabricatorPHIDTypeTestCase' => 'applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php',
|
'PhabricatorPHIDTypeTestCase' => 'applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php',
|
||||||
@@ -3836,7 +3864,9 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php',
|
'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php',
|
||||||
'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php',
|
'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php',
|
||||||
'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php',
|
'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php',
|
||||||
|
'PhabricatorProjectsExportEngineExtension' => 'infrastructure/export/engine/PhabricatorProjectsExportEngineExtension.php',
|
||||||
'PhabricatorProjectsFulltextEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsFulltextEngineExtension.php',
|
'PhabricatorProjectsFulltextEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsFulltextEngineExtension.php',
|
||||||
|
'PhabricatorProjectsMailEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMailEngineExtension.php',
|
||||||
'PhabricatorProjectsMembersSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsMembersSearchEngineAttachment.php',
|
'PhabricatorProjectsMembersSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsMembersSearchEngineAttachment.php',
|
||||||
'PhabricatorProjectsMembershipIndexEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMembershipIndexEngineExtension.php',
|
'PhabricatorProjectsMembershipIndexEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMembershipIndexEngineExtension.php',
|
||||||
'PhabricatorProjectsPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsPolicyRule.php',
|
'PhabricatorProjectsPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsPolicyRule.php',
|
||||||
@@ -4128,8 +4158,10 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorSpacesController' => 'applications/spaces/controller/PhabricatorSpacesController.php',
|
'PhabricatorSpacesController' => 'applications/spaces/controller/PhabricatorSpacesController.php',
|
||||||
'PhabricatorSpacesDAO' => 'applications/spaces/storage/PhabricatorSpacesDAO.php',
|
'PhabricatorSpacesDAO' => 'applications/spaces/storage/PhabricatorSpacesDAO.php',
|
||||||
'PhabricatorSpacesEditController' => 'applications/spaces/controller/PhabricatorSpacesEditController.php',
|
'PhabricatorSpacesEditController' => 'applications/spaces/controller/PhabricatorSpacesEditController.php',
|
||||||
|
'PhabricatorSpacesExportEngineExtension' => 'infrastructure/export/engine/PhabricatorSpacesExportEngineExtension.php',
|
||||||
'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php',
|
'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php',
|
||||||
'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php',
|
'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php',
|
||||||
|
'PhabricatorSpacesMailEngineExtension' => 'applications/spaces/engineextension/PhabricatorSpacesMailEngineExtension.php',
|
||||||
'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php',
|
'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php',
|
||||||
'PhabricatorSpacesNamespaceArchiveTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php',
|
'PhabricatorSpacesNamespaceArchiveTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php',
|
||||||
'PhabricatorSpacesNamespaceDatasource' => 'applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php',
|
'PhabricatorSpacesNamespaceDatasource' => 'applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php',
|
||||||
@@ -4191,9 +4223,11 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php',
|
'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php',
|
||||||
'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php',
|
'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php',
|
||||||
'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php',
|
'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php',
|
||||||
'PhabricatorStringExportField' => 'infrastructure/export/PhabricatorStringExportField.php',
|
'PhabricatorStringExportField' => 'infrastructure/export/field/PhabricatorStringExportField.php',
|
||||||
'PhabricatorStringListConfigType' => 'applications/config/type/PhabricatorStringListConfigType.php',
|
'PhabricatorStringListConfigType' => 'applications/config/type/PhabricatorStringListConfigType.php',
|
||||||
'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.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',
|
'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php',
|
||||||
'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php',
|
'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php',
|
||||||
'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php',
|
'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php',
|
||||||
@@ -4208,9 +4242,12 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php',
|
'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php',
|
||||||
'PhabricatorSubscriptionsEditEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php',
|
'PhabricatorSubscriptionsEditEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php',
|
||||||
'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php',
|
'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php',
|
||||||
|
'PhabricatorSubscriptionsExportEngineExtension' => 'infrastructure/export/engine/PhabricatorSubscriptionsExportEngineExtension.php',
|
||||||
'PhabricatorSubscriptionsFulltextEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsFulltextEngineExtension.php',
|
'PhabricatorSubscriptionsFulltextEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsFulltextEngineExtension.php',
|
||||||
'PhabricatorSubscriptionsHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php',
|
'PhabricatorSubscriptionsHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php',
|
||||||
'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.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',
|
'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php',
|
||||||
'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php',
|
'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php',
|
||||||
'PhabricatorSubscriptionsSearchEngineAttachment' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsSearchEngineAttachment.php',
|
'PhabricatorSubscriptionsSearchEngineAttachment' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsSearchEngineAttachment.php',
|
||||||
@@ -4255,7 +4292,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php',
|
'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php',
|
||||||
'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php',
|
'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php',
|
||||||
'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php',
|
'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php',
|
||||||
'PhabricatorTextExportFormat' => 'infrastructure/export/PhabricatorTextExportFormat.php',
|
'PhabricatorTextExportFormat' => 'infrastructure/export/format/PhabricatorTextExportFormat.php',
|
||||||
'PhabricatorTextListConfigType' => 'applications/config/type/PhabricatorTextListConfigType.php',
|
'PhabricatorTextListConfigType' => 'applications/config/type/PhabricatorTextListConfigType.php',
|
||||||
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
|
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
|
||||||
'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php',
|
'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php',
|
||||||
@@ -4320,6 +4357,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php',
|
'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php',
|
||||||
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/PhabricatorUIExampleRenderController.php',
|
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/PhabricatorUIExampleRenderController.php',
|
||||||
'PhabricatorUIExamplesApplication' => 'applications/uiexample/application/PhabricatorUIExamplesApplication.php',
|
'PhabricatorUIExamplesApplication' => 'applications/uiexample/application/PhabricatorUIExamplesApplication.php',
|
||||||
|
'PhabricatorURIExportField' => 'infrastructure/export/field/PhabricatorURIExportField.php',
|
||||||
'PhabricatorUSEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php',
|
'PhabricatorUSEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php',
|
||||||
'PhabricatorUnifiedDiffsSetting' => 'applications/settings/setting/PhabricatorUnifiedDiffsSetting.php',
|
'PhabricatorUnifiedDiffsSetting' => 'applications/settings/setting/PhabricatorUnifiedDiffsSetting.php',
|
||||||
'PhabricatorUnitTestContentSource' => 'infrastructure/contentsource/PhabricatorUnitTestContentSource.php',
|
'PhabricatorUnitTestContentSource' => 'infrastructure/contentsource/PhabricatorUnitTestContentSource.php',
|
||||||
@@ -4413,6 +4451,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorWorkerManagementWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php',
|
'PhabricatorWorkerManagementWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php',
|
||||||
'PhabricatorWorkerPermanentFailureException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerPermanentFailureException.php',
|
'PhabricatorWorkerPermanentFailureException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerPermanentFailureException.php',
|
||||||
'PhabricatorWorkerSchemaSpec' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerSchemaSpec.php',
|
'PhabricatorWorkerSchemaSpec' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerSchemaSpec.php',
|
||||||
|
'PhabricatorWorkerSingleBulkJobType' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerSingleBulkJobType.php',
|
||||||
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTask.php',
|
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTask.php',
|
||||||
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTaskData.php',
|
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTaskData.php',
|
||||||
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php',
|
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php',
|
||||||
@@ -5588,6 +5627,7 @@ phutil_register_library_map(array(
|
|||||||
'DifferentialLintField' => 'DifferentialHarbormasterField',
|
'DifferentialLintField' => 'DifferentialHarbormasterField',
|
||||||
'DifferentialLintStatus' => 'Phobject',
|
'DifferentialLintStatus' => 'Phobject',
|
||||||
'DifferentialLocalCommitsView' => 'AphrontView',
|
'DifferentialLocalCommitsView' => 'AphrontView',
|
||||||
|
'DifferentialMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
'DifferentialMailView' => 'Phobject',
|
'DifferentialMailView' => 'Phobject',
|
||||||
'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField',
|
'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField',
|
||||||
'DifferentialModernHunk' => 'DifferentialHunk',
|
'DifferentialModernHunk' => 'DifferentialHunk',
|
||||||
@@ -6560,6 +6600,7 @@ phutil_register_library_map(array(
|
|||||||
'HarbormasterWaitForPreviousBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
'HarbormasterWaitForPreviousBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
||||||
'HarbormasterWorker' => 'PhabricatorWorker',
|
'HarbormasterWorker' => 'PhabricatorWorker',
|
||||||
'HarbormasterWorkingCopyArtifact' => 'HarbormasterDrydockLeaseArtifact',
|
'HarbormasterWorkingCopyArtifact' => 'HarbormasterDrydockLeaseArtifact',
|
||||||
|
'HeraldActingUserField' => 'HeraldField',
|
||||||
'HeraldAction' => 'Phobject',
|
'HeraldAction' => 'Phobject',
|
||||||
'HeraldActionGroup' => 'HeraldGroup',
|
'HeraldActionGroup' => 'HeraldGroup',
|
||||||
'HeraldActionRecord' => 'HeraldDAO',
|
'HeraldActionRecord' => 'HeraldDAO',
|
||||||
@@ -6772,13 +6813,10 @@ phutil_register_library_map(array(
|
|||||||
'ManiphestEditProjectsCapability' => 'PhabricatorPolicyCapability',
|
'ManiphestEditProjectsCapability' => 'PhabricatorPolicyCapability',
|
||||||
'ManiphestEditStatusCapability' => 'PhabricatorPolicyCapability',
|
'ManiphestEditStatusCapability' => 'PhabricatorPolicyCapability',
|
||||||
'ManiphestEmailCommand' => 'MetaMTAEmailTransactionCommand',
|
'ManiphestEmailCommand' => 'MetaMTAEmailTransactionCommand',
|
||||||
'ManiphestExcelDefaultFormat' => 'ManiphestExcelFormat',
|
|
||||||
'ManiphestExcelFormat' => 'Phobject',
|
|
||||||
'ManiphestExcelFormatTestCase' => 'PhabricatorTestCase',
|
|
||||||
'ManiphestExportController' => 'ManiphestController',
|
|
||||||
'ManiphestGetTaskTransactionsConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
'ManiphestGetTaskTransactionsConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||||
'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
|
'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
|
||||||
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||||
|
'ManiphestMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
'ManiphestNameIndex' => 'ManiphestDAO',
|
'ManiphestNameIndex' => 'ManiphestDAO',
|
||||||
'ManiphestPointsConfigType' => 'PhabricatorJSONConfigType',
|
'ManiphestPointsConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'ManiphestPrioritiesConfigType' => 'PhabricatorJSONConfigType',
|
'ManiphestPrioritiesConfigType' => 'PhabricatorJSONConfigType',
|
||||||
@@ -7265,6 +7303,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
|
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
|
||||||
'PhabricatorApplicationEditor' => 'PhabricatorApplicationTransactionEditor',
|
'PhabricatorApplicationEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
|
||||||
|
'PhabricatorApplicationObjectMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
||||||
'PhabricatorApplicationPolicyChangeTransaction' => 'PhabricatorApplicationTransactionType',
|
'PhabricatorApplicationPolicyChangeTransaction' => 'PhabricatorApplicationTransactionType',
|
||||||
'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
||||||
@@ -7572,6 +7611,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorBoardResponseEngine' => 'Phobject',
|
'PhabricatorBoardResponseEngine' => 'Phobject',
|
||||||
'PhabricatorBoolConfigType' => 'PhabricatorTextConfigType',
|
'PhabricatorBoolConfigType' => 'PhabricatorTextConfigType',
|
||||||
'PhabricatorBoolEditField' => 'PhabricatorEditField',
|
'PhabricatorBoolEditField' => 'PhabricatorEditField',
|
||||||
|
'PhabricatorBoolMailStamp' => 'PhabricatorMailStamp',
|
||||||
'PhabricatorBritishEnglishTranslation' => 'PhutilTranslation',
|
'PhabricatorBritishEnglishTranslation' => 'PhutilTranslation',
|
||||||
'PhabricatorBuildbotController' => 'PhabricatorController',
|
'PhabricatorBuildbotController' => 'PhabricatorController',
|
||||||
'PhabricatorBuiltinDraftEngine' => 'PhabricatorDraftEngine',
|
'PhabricatorBuiltinDraftEngine' => 'PhabricatorDraftEngine',
|
||||||
@@ -7580,6 +7620,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorBulkContentSource' => 'PhabricatorContentSource',
|
'PhabricatorBulkContentSource' => 'PhabricatorContentSource',
|
||||||
'PhabricatorBulkEditGroup' => 'Phobject',
|
'PhabricatorBulkEditGroup' => 'Phobject',
|
||||||
'PhabricatorBulkEngine' => 'Phobject',
|
'PhabricatorBulkEngine' => 'Phobject',
|
||||||
|
'PhabricatorBulkManagementExportWorkflow' => 'PhabricatorBulkManagementWorkflow',
|
||||||
'PhabricatorBulkManagementMakeSilentWorkflow' => 'PhabricatorBulkManagementWorkflow',
|
'PhabricatorBulkManagementMakeSilentWorkflow' => 'PhabricatorBulkManagementWorkflow',
|
||||||
'PhabricatorBulkManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorBulkManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
'PhabricatorCSVExportFormat' => 'PhabricatorExportFormat',
|
'PhabricatorCSVExportFormat' => 'PhabricatorExportFormat',
|
||||||
@@ -7803,6 +7844,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorClusterExceptionHandler' => 'PhabricatorRequestExceptionHandler',
|
'PhabricatorClusterExceptionHandler' => 'PhabricatorRequestExceptionHandler',
|
||||||
'PhabricatorClusterImpossibleWriteException' => 'PhabricatorClusterException',
|
'PhabricatorClusterImpossibleWriteException' => 'PhabricatorClusterException',
|
||||||
'PhabricatorClusterImproperWriteException' => 'PhabricatorClusterException',
|
'PhabricatorClusterImproperWriteException' => 'PhabricatorClusterException',
|
||||||
|
'PhabricatorClusterMailersConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'PhabricatorClusterNoHostForRoleException' => 'Exception',
|
'PhabricatorClusterNoHostForRoleException' => 'Exception',
|
||||||
'PhabricatorClusterSearchConfigType' => 'PhabricatorJSONConfigType',
|
'PhabricatorClusterSearchConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'PhabricatorClusterServiceHealthRecord' => 'Phobject',
|
'PhabricatorClusterServiceHealthRecord' => 'Phobject',
|
||||||
@@ -7820,6 +7862,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorCommonPasswords' => 'Phobject',
|
'PhabricatorCommonPasswords' => 'Phobject',
|
||||||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||||
'PhabricatorConduitApplication' => 'PhabricatorApplication',
|
'PhabricatorConduitApplication' => 'PhabricatorApplication',
|
||||||
|
'PhabricatorConduitCallManagementWorkflow' => 'PhabricatorConduitManagementWorkflow',
|
||||||
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
||||||
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
||||||
'PhabricatorConduitContentSource' => 'PhabricatorContentSource',
|
'PhabricatorConduitContentSource' => 'PhabricatorContentSource',
|
||||||
@@ -7830,6 +7873,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
|
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
|
||||||
'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'PhabricatorConduitManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
'PhabricatorConduitMethodCallLog' => array(
|
'PhabricatorConduitMethodCallLog' => array(
|
||||||
'PhabricatorConduitDAO',
|
'PhabricatorConduitDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
@@ -7999,6 +8043,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||||
'PhabricatorCustomFieldEditField' => 'PhabricatorEditField',
|
'PhabricatorCustomFieldEditField' => 'PhabricatorEditField',
|
||||||
'PhabricatorCustomFieldEditType' => 'PhabricatorEditType',
|
'PhabricatorCustomFieldEditType' => 'PhabricatorEditType',
|
||||||
|
'PhabricatorCustomFieldExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||||
'PhabricatorCustomFieldFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
'PhabricatorCustomFieldFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||||
'PhabricatorCustomFieldHeraldAction' => 'HeraldAction',
|
'PhabricatorCustomFieldHeraldAction' => 'HeraldAction',
|
||||||
'PhabricatorCustomFieldHeraldActionGroup' => 'HeraldActionGroup',
|
'PhabricatorCustomFieldHeraldActionGroup' => 'HeraldActionGroup',
|
||||||
@@ -8181,6 +8226,8 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorDraftEngine' => 'Phobject',
|
'PhabricatorDraftEngine' => 'Phobject',
|
||||||
'PhabricatorDrydockApplication' => 'PhabricatorApplication',
|
'PhabricatorDrydockApplication' => 'PhabricatorApplication',
|
||||||
|
'PhabricatorEdgeChangeRecord' => 'Phobject',
|
||||||
|
'PhabricatorEdgeChangeRecordTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
|
'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
|
||||||
'PhabricatorEdgeConstants' => 'Phobject',
|
'PhabricatorEdgeConstants' => 'Phobject',
|
||||||
'PhabricatorEdgeCycleException' => 'Exception',
|
'PhabricatorEdgeCycleException' => 'Exception',
|
||||||
@@ -8252,6 +8299,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorEditPage' => 'Phobject',
|
'PhabricatorEditPage' => 'Phobject',
|
||||||
'PhabricatorEditType' => 'Phobject',
|
'PhabricatorEditType' => 'Phobject',
|
||||||
'PhabricatorEditor' => 'Phobject',
|
'PhabricatorEditor' => 'Phobject',
|
||||||
|
'PhabricatorEditorMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorEditorSetting' => 'PhabricatorStringSetting',
|
'PhabricatorEditorSetting' => 'PhabricatorStringSetting',
|
||||||
'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine',
|
'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine',
|
||||||
@@ -8267,6 +8315,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorEmailPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
'PhabricatorEmailPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorEmailRePrefixSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorEmailRePrefixSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorEmailSelfActionsSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorEmailSelfActionsSetting' => 'PhabricatorSelectSetting',
|
||||||
|
'PhabricatorEmailStampsSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorEmailTagsSetting' => 'PhabricatorInternalSetting',
|
'PhabricatorEmailTagsSetting' => 'PhabricatorInternalSetting',
|
||||||
'PhabricatorEmailVarySubjectsSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorEmailVarySubjectsSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorEmailVerificationController' => 'PhabricatorAuthController',
|
'PhabricatorEmailVerificationController' => 'PhabricatorAuthController',
|
||||||
@@ -8285,9 +8334,14 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorEventListener' => 'PhutilEventListener',
|
'PhabricatorEventListener' => 'PhutilEventListener',
|
||||||
'PhabricatorEventType' => 'PhutilEventType',
|
'PhabricatorEventType' => 'PhutilEventType',
|
||||||
'PhabricatorExampleEventListener' => 'PhabricatorEventListener',
|
'PhabricatorExampleEventListener' => 'PhabricatorEventListener',
|
||||||
|
'PhabricatorExcelExportFormat' => 'PhabricatorExportFormat',
|
||||||
'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource',
|
'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource',
|
||||||
|
'PhabricatorExportEngine' => 'Phobject',
|
||||||
|
'PhabricatorExportEngineBulkJobType' => 'PhabricatorWorkerSingleBulkJobType',
|
||||||
|
'PhabricatorExportEngineExtension' => 'Phobject',
|
||||||
'PhabricatorExportField' => 'Phobject',
|
'PhabricatorExportField' => 'Phobject',
|
||||||
'PhabricatorExportFormat' => 'Phobject',
|
'PhabricatorExportFormat' => 'Phobject',
|
||||||
|
'PhabricatorExportFormatSetting' => 'PhabricatorInternalSetting',
|
||||||
'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorExtensionsSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorExtensionsSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorExternalAccount' => array(
|
'PhabricatorExternalAccount' => array(
|
||||||
@@ -8493,6 +8547,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorGDSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorGDSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorGarbageCollector' => 'Phobject',
|
'PhabricatorGarbageCollector' => 'Phobject',
|
||||||
'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
||||||
|
'PhabricatorGarbageCollectorManagementCompactEdgesWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
||||||
'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
||||||
'PhabricatorGarbageCollectorManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorGarbageCollectorManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
'PhabricatorGeneralCachePurger' => 'PhabricatorCachePurger',
|
'PhabricatorGeneralCachePurger' => 'PhabricatorCachePurger',
|
||||||
@@ -8604,9 +8659,11 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorLipsumManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorLipsumManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
'PhabricatorLipsumMondrianArtist' => 'PhabricatorLipsumArtist',
|
'PhabricatorLipsumMondrianArtist' => 'PhabricatorLipsumArtist',
|
||||||
'PhabricatorLiskDAO' => 'LiskDAO',
|
'PhabricatorLiskDAO' => 'LiskDAO',
|
||||||
|
'PhabricatorLiskExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||||
'PhabricatorLiskFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
'PhabricatorLiskFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||||
'PhabricatorLiskSearchEngineExtension' => 'PhabricatorSearchEngineExtension',
|
'PhabricatorLiskSearchEngineExtension' => 'PhabricatorSearchEngineExtension',
|
||||||
'PhabricatorLiskSerializer' => 'Phobject',
|
'PhabricatorLiskSerializer' => 'Phobject',
|
||||||
|
'PhabricatorListExportField' => 'PhabricatorExportField',
|
||||||
'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||||
'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase',
|
'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorLocaleScopeGuard' => 'Phobject',
|
'PhabricatorLocaleScopeGuard' => 'Phobject',
|
||||||
@@ -8642,14 +8699,17 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
|
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
|
||||||
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
|
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
|
||||||
|
'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorMailEmailHeraldField' => 'HeraldField',
|
'PhabricatorMailEmailHeraldField' => 'HeraldField',
|
||||||
'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup',
|
'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup',
|
||||||
'PhabricatorMailEmailSubjectHeraldField' => 'PhabricatorMailEmailHeraldField',
|
'PhabricatorMailEmailSubjectHeraldField' => 'PhabricatorMailEmailHeraldField',
|
||||||
|
'PhabricatorMailEngineExtension' => 'Phobject',
|
||||||
'PhabricatorMailImplementationAdapter' => 'Phobject',
|
'PhabricatorMailImplementationAdapter' => 'Phobject',
|
||||||
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
|
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
|
||||||
'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
|
'PhabricatorMailImplementationPostmarkAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||||
@@ -8662,6 +8722,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow',
|
'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||||
'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow',
|
'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||||
'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
|
'PhabricatorMailMustEncryptHeraldAction' => 'HeraldAction',
|
||||||
'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter',
|
'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter',
|
||||||
'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction',
|
'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction',
|
||||||
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
||||||
@@ -8672,6 +8733,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMailReplyHandler' => 'Phobject',
|
'PhabricatorMailReplyHandler' => 'Phobject',
|
||||||
'PhabricatorMailRoutingRule' => 'Phobject',
|
'PhabricatorMailRoutingRule' => 'Phobject',
|
||||||
'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
|
'PhabricatorMailStamp' => 'Phobject',
|
||||||
'PhabricatorMailTarget' => 'Phobject',
|
'PhabricatorMailTarget' => 'Phobject',
|
||||||
'PhabricatorMailgunConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorMailgunConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
||||||
@@ -8725,6 +8787,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMetaMTAMail' => array(
|
'PhabricatorMetaMTAMail' => array(
|
||||||
'PhabricatorMetaMTADAO',
|
'PhabricatorMetaMTADAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
|
'PhabricatorDestructibleInterface',
|
||||||
),
|
),
|
||||||
'PhabricatorMetaMTAMailBody' => 'Phobject',
|
'PhabricatorMetaMTAMailBody' => 'Phobject',
|
||||||
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
|
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
|
||||||
@@ -8741,6 +8804,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController',
|
'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController',
|
||||||
'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery',
|
'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery',
|
||||||
'PhabricatorMetaMTAPermanentFailureException' => 'Exception',
|
'PhabricatorMetaMTAPermanentFailureException' => 'Exception',
|
||||||
|
'PhabricatorMetaMTAPostmarkReceiveController' => 'PhabricatorMetaMTAController',
|
||||||
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
|
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
|
||||||
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
|
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
|
||||||
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',
|
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',
|
||||||
@@ -8758,6 +8822,8 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel',
|
'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorMultimeterApplication' => 'PhabricatorApplication',
|
'PhabricatorMultimeterApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController',
|
'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController',
|
||||||
|
'PhabricatorMutedByEdgeType' => 'PhabricatorEdgeType',
|
||||||
|
'PhabricatorMutedEdgeType' => 'PhabricatorEdgeType',
|
||||||
'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||||
'PhabricatorMySQLSearchHost' => 'PhabricatorSearchHost',
|
'PhabricatorMySQLSearchHost' => 'PhabricatorSearchHost',
|
||||||
@@ -8944,6 +9010,8 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorPHIDExportField' => 'PhabricatorExportField',
|
'PhabricatorPHIDExportField' => 'PhabricatorExportField',
|
||||||
'PhabricatorPHIDListEditField' => 'PhabricatorEditField',
|
'PhabricatorPHIDListEditField' => 'PhabricatorEditField',
|
||||||
'PhabricatorPHIDListEditType' => 'PhabricatorEditType',
|
'PhabricatorPHIDListEditType' => 'PhabricatorEditType',
|
||||||
|
'PhabricatorPHIDListExportField' => 'PhabricatorListExportField',
|
||||||
|
'PhabricatorPHIDMailStamp' => 'PhabricatorMailStamp',
|
||||||
'PhabricatorPHIDResolver' => 'Phobject',
|
'PhabricatorPHIDResolver' => 'Phobject',
|
||||||
'PhabricatorPHIDType' => 'Phobject',
|
'PhabricatorPHIDType' => 'Phobject',
|
||||||
'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase',
|
'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase',
|
||||||
@@ -9444,7 +9512,9 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension',
|
'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension',
|
||||||
'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||||
'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField',
|
'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField',
|
||||||
|
'PhabricatorProjectsExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||||
'PhabricatorProjectsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
'PhabricatorProjectsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||||
|
'PhabricatorProjectsMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||||
'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension',
|
'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension',
|
||||||
'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule',
|
'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule',
|
||||||
@@ -9812,8 +9882,10 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorSpacesController' => 'PhabricatorController',
|
'PhabricatorSpacesController' => 'PhabricatorController',
|
||||||
'PhabricatorSpacesDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorSpacesDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorSpacesEditController' => 'PhabricatorSpacesController',
|
'PhabricatorSpacesEditController' => 'PhabricatorSpacesController',
|
||||||
|
'PhabricatorSpacesExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||||
'PhabricatorSpacesInterface' => 'PhabricatorPHIDInterface',
|
'PhabricatorSpacesInterface' => 'PhabricatorPHIDInterface',
|
||||||
'PhabricatorSpacesListController' => 'PhabricatorSpacesController',
|
'PhabricatorSpacesListController' => 'PhabricatorSpacesController',
|
||||||
|
'PhabricatorSpacesMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
'PhabricatorSpacesNamespace' => array(
|
'PhabricatorSpacesNamespace' => array(
|
||||||
'PhabricatorSpacesDAO',
|
'PhabricatorSpacesDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
@@ -9885,6 +9957,8 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorStringExportField' => 'PhabricatorExportField',
|
'PhabricatorStringExportField' => 'PhabricatorExportField',
|
||||||
'PhabricatorStringListConfigType' => 'PhabricatorTextListConfigType',
|
'PhabricatorStringListConfigType' => 'PhabricatorTextListConfigType',
|
||||||
'PhabricatorStringListEditField' => 'PhabricatorEditField',
|
'PhabricatorStringListEditField' => 'PhabricatorEditField',
|
||||||
|
'PhabricatorStringListExportField' => 'PhabricatorListExportField',
|
||||||
|
'PhabricatorStringMailStamp' => 'PhabricatorMailStamp',
|
||||||
'PhabricatorStringSetting' => 'PhabricatorSetting',
|
'PhabricatorStringSetting' => 'PhabricatorSetting',
|
||||||
'PhabricatorSubmitEditField' => 'PhabricatorEditField',
|
'PhabricatorSubmitEditField' => 'PhabricatorEditField',
|
||||||
'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType',
|
'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType',
|
||||||
@@ -9898,9 +9972,12 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorSubscriptionsEditController' => 'PhabricatorController',
|
'PhabricatorSubscriptionsEditController' => 'PhabricatorController',
|
||||||
'PhabricatorSubscriptionsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
'PhabricatorSubscriptionsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||||
'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor',
|
'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor',
|
||||||
|
'PhabricatorSubscriptionsExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||||
'PhabricatorSubscriptionsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
'PhabricatorSubscriptionsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||||
'PhabricatorSubscriptionsHeraldAction' => 'HeraldAction',
|
'PhabricatorSubscriptionsHeraldAction' => 'HeraldAction',
|
||||||
'PhabricatorSubscriptionsListController' => 'PhabricatorController',
|
'PhabricatorSubscriptionsListController' => 'PhabricatorController',
|
||||||
|
'PhabricatorSubscriptionsMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||||
|
'PhabricatorSubscriptionsMuteController' => 'PhabricatorController',
|
||||||
'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction',
|
'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction',
|
||||||
'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction',
|
'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction',
|
||||||
'PhabricatorSubscriptionsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
'PhabricatorSubscriptionsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||||
@@ -10021,6 +10098,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorUIExample' => 'Phobject',
|
'PhabricatorUIExample' => 'Phobject',
|
||||||
'PhabricatorUIExampleRenderController' => 'PhabricatorController',
|
'PhabricatorUIExampleRenderController' => 'PhabricatorController',
|
||||||
'PhabricatorUIExamplesApplication' => 'PhabricatorApplication',
|
'PhabricatorUIExamplesApplication' => 'PhabricatorApplication',
|
||||||
|
'PhabricatorURIExportField' => 'PhabricatorExportField',
|
||||||
'PhabricatorUSEnglishTranslation' => 'PhutilTranslation',
|
'PhabricatorUSEnglishTranslation' => 'PhutilTranslation',
|
||||||
'PhabricatorUnifiedDiffsSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorUnifiedDiffsSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorUnitTestContentSource' => 'PhabricatorContentSource',
|
'PhabricatorUnitTestContentSource' => 'PhabricatorContentSource',
|
||||||
@@ -10144,6 +10222,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorWorkerManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
'PhabricatorWorkerManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||||
'PhabricatorWorkerPermanentFailureException' => 'Exception',
|
'PhabricatorWorkerPermanentFailureException' => 'Exception',
|
||||||
'PhabricatorWorkerSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'PhabricatorWorkerSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
|
'PhabricatorWorkerSingleBulkJobType' => 'PhabricatorWorkerBulkJobType',
|
||||||
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
|
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
|
||||||
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
|
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
|
||||||
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
|
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
|
||||||
|
|||||||
@@ -358,9 +358,17 @@ final class PhabricatorAuditEditor
|
|||||||
array $changes,
|
array $changes,
|
||||||
PhutilMarkupEngine $engine) {
|
PhutilMarkupEngine $engine) {
|
||||||
|
|
||||||
// we are only really trying to find unmentionable phids here...
|
$actor = $this->getActor();
|
||||||
// don't bother with this outside initial commit (i.e. create)
|
$result = array();
|
||||||
// transaction
|
|
||||||
|
// Some interactions (like "Fixes Txxx" interacting with Maniphest) have
|
||||||
|
// already been processed, so we're only re-parsing them here to avoid
|
||||||
|
// generating an extra redundant mention. Other interactions are being
|
||||||
|
// processed for the first time.
|
||||||
|
|
||||||
|
// We're only recognizing magic in the commit message itself, not in
|
||||||
|
// audit comments.
|
||||||
|
|
||||||
$is_commit = false;
|
$is_commit = false;
|
||||||
foreach ($xactions as $xaction) {
|
foreach ($xactions as $xaction) {
|
||||||
switch ($xaction->getTransactionType()) {
|
switch ($xaction->getTransactionType()) {
|
||||||
@@ -370,8 +378,6 @@ final class PhabricatorAuditEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "result" is always an array....
|
|
||||||
$result = array();
|
|
||||||
if (!$is_commit) {
|
if (!$is_commit) {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
@@ -403,6 +409,46 @@ final class PhabricatorAuditEditor
|
|||||||
->withNames($monograms)
|
->withNames($monograms)
|
||||||
->execute();
|
->execute();
|
||||||
$phid_map[] = mpull($objects, 'getPHID', 'getPHID');
|
$phid_map[] = mpull($objects, 'getPHID', 'getPHID');
|
||||||
|
|
||||||
|
|
||||||
|
$reverts_refs = id(new DifferentialCustomFieldRevertsParser())
|
||||||
|
->parseCorpus($huge_block);
|
||||||
|
$reverts = array_mergev(ipull($reverts_refs, 'monograms'));
|
||||||
|
if ($reverts) {
|
||||||
|
// Only allow commits to revert other commits in the same repository.
|
||||||
|
$reverted_commits = id(new DiffusionCommitQuery())
|
||||||
|
->setViewer($actor)
|
||||||
|
->withRepository($object->getRepository())
|
||||||
|
->withIdentifiers($reverts)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$reverted_revisions = id(new PhabricatorObjectQuery())
|
||||||
|
->setViewer($actor)
|
||||||
|
->withNames($reverts)
|
||||||
|
->withTypes(
|
||||||
|
array(
|
||||||
|
DifferentialRevisionPHIDType::TYPECONST,
|
||||||
|
))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$reverted_phids =
|
||||||
|
mpull($reverted_commits, 'getPHID', 'getPHID') +
|
||||||
|
mpull($reverted_revisions, 'getPHID', 'getPHID');
|
||||||
|
|
||||||
|
// NOTE: Skip any write attempts if a user cleverly implies a commit
|
||||||
|
// reverts itself, although this would be exceptionally clever in Git
|
||||||
|
// or Mercurial.
|
||||||
|
unset($reverted_phids[$object->getPHID()]);
|
||||||
|
|
||||||
|
$reverts_edge = DiffusionCommitRevertsCommitEdgeType::EDGECONST;
|
||||||
|
$result[] = id(new PhabricatorAuditTransaction())
|
||||||
|
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
|
||||||
|
->setMetadataValue('edge:type', $reverts_edge)
|
||||||
|
->setNewValue(array('+' => $reverted_phids));
|
||||||
|
|
||||||
|
$phid_map[] = $reverted_phids;
|
||||||
|
}
|
||||||
|
|
||||||
$phid_map = array_mergev($phid_map);
|
$phid_map = array_mergev($phid_map);
|
||||||
$this->setUnmentionablePHIDMap($phid_map);
|
$this->setUnmentionablePHIDMap($phid_map);
|
||||||
|
|
||||||
@@ -427,17 +473,14 @@ final class PhabricatorAuditEditor
|
|||||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
$identifier = $object->getCommitIdentifier();
|
$identifier = $object->getCommitIdentifier();
|
||||||
$repository = $object->getRepository();
|
$repository = $object->getRepository();
|
||||||
$monogram = $repository->getMonogram();
|
|
||||||
|
|
||||||
$summary = $object->getSummary();
|
$summary = $object->getSummary();
|
||||||
$name = $repository->formatCommitName($identifier);
|
$name = $repository->formatCommitName($identifier);
|
||||||
|
|
||||||
$subject = "{$name}: {$summary}";
|
$subject = "{$name}: {$summary}";
|
||||||
$thread_topic = "Commit {$monogram}{$identifier}";
|
|
||||||
|
|
||||||
$template = id(new PhabricatorMetaMTAMail())
|
$template = id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject($subject)
|
->setSubject($subject);
|
||||||
->addHeader('Thread-Topic', $thread_topic);
|
|
||||||
|
|
||||||
$this->attachPatch(
|
$this->attachPatch(
|
||||||
$template,
|
$template,
|
||||||
@@ -453,7 +496,6 @@ final class PhabricatorAuditEditor
|
|||||||
$phids[] = $object->getAuthorPHID();
|
$phids[] = $object->getAuthorPHID();
|
||||||
}
|
}
|
||||||
|
|
||||||
$status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
|
|
||||||
foreach ($object->getAudits() as $audit) {
|
foreach ($object->getAudits() as $audit) {
|
||||||
if (!$audit->isInteresting()) {
|
if (!$audit->isInteresting()) {
|
||||||
// Don't send mail to uninteresting auditors, like packages which
|
// Don't send mail to uninteresting auditors, like packages which
|
||||||
@@ -461,7 +503,7 @@ final class PhabricatorAuditEditor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($audit->getAuditStatus() != $status_resigned) {
|
if (!$audit->isResigned()) {
|
||||||
$phids[] = $audit->getAuditorPHID();
|
$phids[] = $audit->getAuditorPHID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,6 +513,18 @@ final class PhabricatorAuditEditor
|
|||||||
return $phids;
|
return $phids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) {
|
||||||
|
$phids = array();
|
||||||
|
|
||||||
|
foreach ($object->getAudits() as $auditor) {
|
||||||
|
if ($auditor->isResigned()) {
|
||||||
|
$phids[] = $auditor->getAuditorPHID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $phids;
|
||||||
|
}
|
||||||
|
|
||||||
protected function buildMailBody(
|
protected function buildMailBody(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
array $xactions) {
|
array $xactions) {
|
||||||
|
|||||||
@@ -255,11 +255,9 @@ final class PhabricatorAuthSSHKeyEditor
|
|||||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
$id = $object->getID();
|
$id = $object->getID();
|
||||||
$name = $object->getName();
|
$name = $object->getName();
|
||||||
$phid = $object->getPHID();
|
|
||||||
|
|
||||||
$mail = id(new PhabricatorMetaMTAMail())
|
$mail = id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject(pht('SSH Key %d: %s', $id, $name))
|
->setSubject(pht('SSH Key %d: %s', $id, $name));
|
||||||
->addHeader('Thread-Topic', $phid);
|
|
||||||
|
|
||||||
// The primary value of this mail is alerting users to account compromises,
|
// The primary value of this mail is alerting users to account compromises,
|
||||||
// so force delivery. In particular, this mail should still be delivered
|
// so force delivery. In particular, this mail should still be delivered
|
||||||
|
|||||||
@@ -87,12 +87,10 @@ final class PhabricatorBadgesEditor
|
|||||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
$name = $object->getName();
|
$name = $object->getName();
|
||||||
$id = $object->getID();
|
$id = $object->getID();
|
||||||
$topic = pht('Badge %d', $id);
|
|
||||||
$subject = pht('Badge %d: %s', $id, $name);
|
$subject = pht('Badge %d: %s', $id, $name);
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject($subject)
|
->setSubject($subject);
|
||||||
->addHeader('Thread-Topic', $topic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
|||||||
@@ -309,13 +309,11 @@ final class PhabricatorCalendarEventEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
$id = $object->getID();
|
|
||||||
$name = $object->getName();
|
$name = $object->getName();
|
||||||
$monogram = $object->getMonogram();
|
$monogram = $object->getMonogram();
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("{$monogram}: {$name}")
|
->setSubject("{$monogram}: {$name}");
|
||||||
->addHeader('Thread-Topic', $monogram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMailBody(
|
protected function buildMailBody(
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConduitCallManagementWorkflow
|
||||||
|
extends PhabricatorConduitManagementWorkflow {
|
||||||
|
|
||||||
|
protected function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('call')
|
||||||
|
->setSynopsis(pht('Call a Conduit method..'))
|
||||||
|
->setArguments(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'method',
|
||||||
|
'param' => 'method',
|
||||||
|
'help' => pht('Method to call.'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'input',
|
||||||
|
'param' => 'input',
|
||||||
|
'help' => pht(
|
||||||
|
'File to read parameters from, or "-" to read from '.
|
||||||
|
'stdin.'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$method = $args->getArg('method');
|
||||||
|
if (!strlen($method)) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht('Specify a method to call with "--method".'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = $args->getArg('input');
|
||||||
|
if (!strlen($input)) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht('Specify a file to read parameters from with "--input".'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($input === '-') {
|
||||||
|
fprintf(STDERR, tsprintf("%s\n", pht('Reading input from stdin...')));
|
||||||
|
$input_json = file_get_contents('php://stdin');
|
||||||
|
} else {
|
||||||
|
$input_json = Filesystem::readFile($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = phutil_json_decode($input_json);
|
||||||
|
|
||||||
|
$result = id(new ConduitCall($method, $params))
|
||||||
|
->setUser($viewer)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$output = array(
|
||||||
|
'result' => $result,
|
||||||
|
);
|
||||||
|
|
||||||
|
echo tsprintf(
|
||||||
|
"%B\n",
|
||||||
|
id(new PhutilJSON())->encodeFormatted($output));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorConduitManagementWorkflow
|
||||||
|
extends PhabricatorManagementWorkflow {}
|
||||||
@@ -3,9 +3,26 @@
|
|||||||
final class ConduitPHIDParameterType
|
final class ConduitPHIDParameterType
|
||||||
extends ConduitParameterType {
|
extends ConduitParameterType {
|
||||||
|
|
||||||
|
private $isNullable;
|
||||||
|
|
||||||
|
public function setIsNullable($is_nullable) {
|
||||||
|
$this->isNullable = $is_nullable;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIsNullable() {
|
||||||
|
return $this->isNullable;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getParameterValue(array $request, $key, $strict) {
|
protected function getParameterValue(array $request, $key, $strict) {
|
||||||
$value = parent::getParameterValue($request, $key, $strict);
|
$value = parent::getParameterValue($request, $key, $strict);
|
||||||
|
|
||||||
|
if ($this->getIsNullable()) {
|
||||||
|
if ($value === null) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_string($value)) {
|
if (!is_string($value)) {
|
||||||
$this->raiseValidationException(
|
$this->raiseValidationException(
|
||||||
$request,
|
$request,
|
||||||
@@ -17,8 +34,12 @@ final class ConduitPHIDParameterType
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function getParameterTypeName() {
|
protected function getParameterTypeName() {
|
||||||
|
if ($this->getIsNullable()) {
|
||||||
|
return 'phid|null';
|
||||||
|
} else {
|
||||||
return 'phid';
|
return 'phid';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function getParameterFormatDescriptions() {
|
protected function getParameterFormatDescriptions() {
|
||||||
return array(
|
return array(
|
||||||
@@ -27,9 +48,15 @@ final class ConduitPHIDParameterType
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function getParameterExamples() {
|
protected function getParameterExamples() {
|
||||||
return array(
|
$examples = array(
|
||||||
'"PHID-WXYZ-1111222233334444"',
|
'"PHID-WXYZ-1111222233334444"',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($this->getIsNullable()) {
|
||||||
|
$examples[] = 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $examples;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ final class PhabricatorMailSetupCheck extends PhabricatorSetupCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function executeChecks() {
|
protected function executeChecks() {
|
||||||
|
if (PhabricatorEnv::getEnvConfig('cluster.mailers')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter');
|
$adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter');
|
||||||
|
|
||||||
switch ($adapter) {
|
switch ($adapter) {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ final class PhabricatorConfigManagementSetWorkflow
|
|||||||
protected function didConstruct() {
|
protected function didConstruct() {
|
||||||
$this
|
$this
|
||||||
->setName('set')
|
->setName('set')
|
||||||
->setExamples('**set** __key__ __value__')
|
->setExamples(
|
||||||
|
"**set** __key__ __value__\n".
|
||||||
|
"**set** __key__ --stdin < value.json")
|
||||||
->setSynopsis(pht('Set a local configuration value.'))
|
->setSynopsis(pht('Set a local configuration value.'))
|
||||||
->setArguments(
|
->setArguments(
|
||||||
array(
|
array(
|
||||||
@@ -16,6 +18,10 @@ final class PhabricatorConfigManagementSetWorkflow
|
|||||||
'Update configuration in the database instead of '.
|
'Update configuration in the database instead of '.
|
||||||
'in local configuration.'),
|
'in local configuration.'),
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'stdin',
|
||||||
|
'help' => pht('Read option value from stdin.'),
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'args',
|
'name' => 'args',
|
||||||
'wildcard' => true,
|
'wildcard' => true,
|
||||||
@@ -31,8 +37,20 @@ final class PhabricatorConfigManagementSetWorkflow
|
|||||||
pht('Specify a configuration key and a value to set it to.'));
|
pht('Specify a configuration key and a value to set it to.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$is_stdin = $args->getArg('stdin');
|
||||||
|
|
||||||
$key = $argv[0];
|
$key = $argv[0];
|
||||||
|
|
||||||
|
if ($is_stdin) {
|
||||||
|
if (count($argv) > 1) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'Too many arguments: expected only a key when using "--stdin".'));
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(STDERR, tsprintf("%s\n", pht('Reading value from stdin...')));
|
||||||
|
$value = file_get_contents('php://stdin');
|
||||||
|
} else {
|
||||||
if (count($argv) == 1) {
|
if (count($argv) == 1) {
|
||||||
throw new PhutilArgumentUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
pht(
|
pht(
|
||||||
@@ -40,14 +58,16 @@ final class PhabricatorConfigManagementSetWorkflow
|
|||||||
$key));
|
$key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $argv[1];
|
|
||||||
|
|
||||||
if (count($argv) > 2) {
|
if (count($argv) > 2) {
|
||||||
throw new PhutilArgumentUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
pht(
|
pht(
|
||||||
'Too many arguments: expected one key and one value.'));
|
'Too many arguments: expected one key and one value.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$value = $argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
||||||
if (empty($options[$key])) {
|
if (empty($options[$key])) {
|
||||||
throw new PhutilArgumentUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
|
|||||||
@@ -66,7 +66,9 @@ of each approach are:
|
|||||||
received a similar message, but can not prevent all stray email arising
|
received a similar message, but can not prevent all stray email arising
|
||||||
from "Reply All".
|
from "Reply All".
|
||||||
- Not supported with a private reply-to address.
|
- Not supported with a private reply-to address.
|
||||||
- Mails are sent in the server default translation.
|
- Mail messages are sent in the server default translation.
|
||||||
|
- Mail that must be delivered over secure channels will leak the recipient
|
||||||
|
list in the "To" and "Cc" headers.
|
||||||
- One mail to each user:
|
- One mail to each user:
|
||||||
- Policy controls work correctly and are enforced per-user.
|
- Policy controls work correctly and are enforced per-user.
|
||||||
- Recipients need to look in the mail body to see To/Cc.
|
- Recipients need to look in the mail body to see To/Cc.
|
||||||
@@ -77,7 +79,7 @@ of each approach are:
|
|||||||
- "Reply All" will never send extra mail to other users involved in the
|
- "Reply All" will never send extra mail to other users involved in the
|
||||||
thread.
|
thread.
|
||||||
- Required if private reply-to addresses are configured.
|
- Required if private reply-to addresses are configured.
|
||||||
- Mails are sent in the language of user preference.
|
- Mail messages are sent in the language of user preference.
|
||||||
|
|
||||||
EODOC
|
EODOC
|
||||||
));
|
));
|
||||||
@@ -138,24 +140,19 @@ EODOC
|
|||||||
,
|
,
|
||||||
'metamta.public-replies'));
|
'metamta.public-replies'));
|
||||||
|
|
||||||
$adapter_doc_href = PhabricatorEnv::getDoclink(
|
|
||||||
'Configuring Outbound Email');
|
|
||||||
$adapter_doc_name = pht('Configuring Outbound Email');
|
|
||||||
$adapter_description = $this->deformat(pht(<<<EODOC
|
$adapter_description = $this->deformat(pht(<<<EODOC
|
||||||
Adapter class to use to transmit mail to the MTA. The default uses
|
Adapter class to use to transmit mail to the MTA. The default uses
|
||||||
PHPMailerLite, which will invoke "sendmail". This is appropriate if sendmail
|
PHPMailerLite, which will invoke "sendmail". This is appropriate if sendmail
|
||||||
actually works on your host, but if you haven't configured mail it may not be so
|
actually works on your host, but if you haven't configured mail it may not be so
|
||||||
great. A number of other mailers are available (e.g., SES, SendGrid, SMTP,
|
great. A number of other mailers are available (e.g., SES, SendGrid, SMTP,
|
||||||
custom mailers) - consult [[ %s | %s ]] for details.
|
custom mailers). This option is deprecated in favor of 'cluster.mailers'.
|
||||||
EODOC
|
EODOC
|
||||||
,
|
));
|
||||||
$adapter_doc_href,
|
|
||||||
$adapter_doc_name));
|
|
||||||
|
|
||||||
$placeholder_description = $this->deformat(pht(<<<EODOC
|
$placeholder_description = $this->deformat(pht(<<<EODOC
|
||||||
When sending a message that has no To recipient (i.e. all recipients are CC'd,
|
When sending a message that has no To recipient (i.e. all recipients are CC'd),
|
||||||
for example when multiplexing mail), set the To field to the following value. If
|
set the To field to the following value. If no value is set, messages with no
|
||||||
no value is set, messages with no To will have their CCs upgraded to To.
|
To will have their CCs upgraded to To.
|
||||||
EODOC
|
EODOC
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -197,7 +194,18 @@ The default is `full`.
|
|||||||
EODOC
|
EODOC
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$mailers_description = $this->deformat(pht(<<<EODOC
|
||||||
|
Define one or more mail transmission services. For help with configuring
|
||||||
|
mailers, see **[[ %s | %s ]]** in the documentation.
|
||||||
|
EODOC
|
||||||
|
,
|
||||||
|
PhabricatorEnv::getDoclink('Configuring Outbound Email'),
|
||||||
|
pht('Configuring Outbound Email')));
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
$this->newOption('cluster.mailers', 'cluster.mailers', null)
|
||||||
|
->setHidden(true)
|
||||||
|
->setDescription($mailers_description),
|
||||||
$this->newOption(
|
$this->newOption(
|
||||||
'metamta.default-address',
|
'metamta.default-address',
|
||||||
'string',
|
'string',
|
||||||
|
|||||||
@@ -227,11 +227,9 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
|
|||||||
'%s sent you a message.',
|
'%s sent you a message.',
|
||||||
$this->getActor()->getUserName());
|
$this->getActor()->getUserName());
|
||||||
}
|
}
|
||||||
$phid = $object->getPHID();
|
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("Z{$id}: {$title}")
|
->setSubject("Z{$id}: {$title}");
|
||||||
->addHeader('Thread-Topic', "Z{$id}: {$phid}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ final class PhabricatorCountdownEditor
|
|||||||
$name = $object->getTitle();
|
$name = $object->getTitle();
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("{$monogram}: {$name}")
|
->setSubject("{$monogram}: {$name}");
|
||||||
->addHeader('Thread-Topic', $monogram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMailBody(
|
protected function buildMailBody(
|
||||||
|
|||||||
@@ -71,18 +71,10 @@ final class PhabricatorDaemonBulkJobViewController
|
|||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$curtain = $this->newCurtainView($job);
|
$curtain = $this->newCurtainView($job);
|
||||||
|
|
||||||
if ($job->isConfirming()) {
|
foreach ($job->getCurtainActions($viewer) as $action) {
|
||||||
$continue_uri = $job->getMonitorURI();
|
$curtain->addAction($action);
|
||||||
} else {
|
|
||||||
$continue_uri = $job->getDoneURI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$curtain->addAction(
|
|
||||||
id(new PhabricatorActionView())
|
|
||||||
->setHref($continue_uri)
|
|
||||||
->setIcon('fa-arrow-circle-o-right')
|
|
||||||
->setName(pht('Continue')));
|
|
||||||
|
|
||||||
return $curtain;
|
return $curtain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -632,6 +632,8 @@ final class DifferentialTransactionEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
$this->requireReviewers($object);
|
||||||
|
|
||||||
$phids = array();
|
$phids = array();
|
||||||
$phids[] = $object->getAuthorPHID();
|
$phids[] = $object->getAuthorPHID();
|
||||||
foreach ($object->getReviewers() as $reviewer) {
|
foreach ($object->getReviewers() as $reviewer) {
|
||||||
@@ -644,6 +646,20 @@ final class DifferentialTransactionEditor
|
|||||||
return $phids;
|
return $phids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) {
|
||||||
|
$this->requireReviewers($object);
|
||||||
|
|
||||||
|
$phids = array();
|
||||||
|
|
||||||
|
foreach ($object->getReviewers() as $reviewer) {
|
||||||
|
if ($reviewer->isResigned()) {
|
||||||
|
$phids[] = $reviewer->getReviewerPHID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $phids;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getMailAction(
|
protected function getMailAction(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
array $xactions) {
|
array $xactions) {
|
||||||
@@ -689,15 +705,10 @@ final class DifferentialTransactionEditor
|
|||||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
$id = $object->getID();
|
$id = $object->getID();
|
||||||
$title = $object->getTitle();
|
$title = $object->getTitle();
|
||||||
|
|
||||||
$original_title = $object->getOriginalTitle();
|
|
||||||
|
|
||||||
$subject = "D{$id}: {$title}";
|
$subject = "D{$id}: {$title}";
|
||||||
$thread_topic = "D{$id}: {$original_title}";
|
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject($subject)
|
->setSubject($subject);
|
||||||
->addHeader('Thread-Topic', $thread_topic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getTransactionsForMail(
|
protected function getTransactionsForMail(
|
||||||
@@ -919,7 +930,44 @@ final class DifferentialTransactionEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setUnmentionablePHIDMap(array_merge($task_phids, $rev_phids));
|
$revert_refs = id(new DifferentialCustomFieldRevertsParser())
|
||||||
|
->parseCorpus($content_block);
|
||||||
|
|
||||||
|
$revert_monograms = array();
|
||||||
|
foreach ($revert_refs as $match) {
|
||||||
|
foreach ($match['monograms'] as $monogram) {
|
||||||
|
$revert_monograms[] = $monogram;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($revert_monograms) {
|
||||||
|
$revert_objects = id(new PhabricatorObjectQuery())
|
||||||
|
->setViewer($this->getActor())
|
||||||
|
->withNames($revert_monograms)
|
||||||
|
->withTypes(
|
||||||
|
array(
|
||||||
|
DifferentialRevisionPHIDType::TYPECONST,
|
||||||
|
PhabricatorRepositoryCommitPHIDType::TYPECONST,
|
||||||
|
))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$revert_phids = mpull($revert_objects, 'getPHID', 'getPHID');
|
||||||
|
|
||||||
|
// Don't let an object revert itself, although other silly stuff like
|
||||||
|
// cycles of objects reverting each other is not prevented.
|
||||||
|
unset($revert_phids[$object->getPHID()]);
|
||||||
|
|
||||||
|
$revert_type = DiffusionCommitRevertsCommitEdgeType::EDGECONST;
|
||||||
|
$edges[$revert_type] = $revert_phids;
|
||||||
|
} else {
|
||||||
|
$revert_phids = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setUnmentionablePHIDMap(
|
||||||
|
array_merge(
|
||||||
|
$task_phids,
|
||||||
|
$rev_phids,
|
||||||
|
$revert_phids));
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach ($edges as $type => $specs) {
|
foreach ($edges as $type => $specs) {
|
||||||
@@ -1693,4 +1741,25 @@ final class DifferentialTransactionEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function requireReviewers(DifferentialRevision $revision) {
|
||||||
|
if ($revision->hasAttachedReviewers()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$with_reviewers = id(new DifferentialRevisionQuery())
|
||||||
|
->setViewer($this->getActor())
|
||||||
|
->needReviewers(true)
|
||||||
|
->withPHIDs(array($revision->getPHID()))
|
||||||
|
->executeOne();
|
||||||
|
if (!$with_reviewers) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Failed to reload revision ("%s").',
|
||||||
|
$revision->getPHID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
$revision->attachReviewers($with_reviewers->getReviewers());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class DifferentialMailEngineExtension
|
||||||
|
extends PhabricatorMailEngineExtension {
|
||||||
|
|
||||||
|
const EXTENSIONKEY = 'differential';
|
||||||
|
|
||||||
|
public function supportsObject($object) {
|
||||||
|
return ($object instanceof DifferentialRevision);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newMailStampTemplates($object) {
|
||||||
|
return array(
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('author')
|
||||||
|
->setLabel(pht('Author')),
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('reviewer')
|
||||||
|
->setLabel(pht('Reviewer')),
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('blocking-reviewer')
|
||||||
|
->setLabel(pht('Reviewer')),
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('resigned-reviewer')
|
||||||
|
->setLabel(pht('Reviewer')),
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('revision-repository')
|
||||||
|
->setLabel(pht('Revision Repository')),
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('revision-status')
|
||||||
|
->setLabel(pht('Revision Status')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newMailStamps($object, array $xactions) {
|
||||||
|
$editor = $this->getEditor();
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$revision = id(new DifferentialRevisionQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->needReviewers(true)
|
||||||
|
->withPHIDs(array($object->getPHID()))
|
||||||
|
->executeOne();
|
||||||
|
|
||||||
|
$reviewers = array();
|
||||||
|
$blocking = array();
|
||||||
|
$resigned = array();
|
||||||
|
foreach ($revision->getReviewers() as $reviewer) {
|
||||||
|
$reviewer_phid = $reviewer->getReviewerPHID();
|
||||||
|
|
||||||
|
if ($reviewer->isResigned()) {
|
||||||
|
$resigned[] = $reviewer_phid;
|
||||||
|
} else {
|
||||||
|
$reviewers[] = $reviewer_phid;
|
||||||
|
if ($reviewer->isBlocking()) {
|
||||||
|
$reviewers[] = $blocking;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->getMailStamp('author')
|
||||||
|
->setValue($revision->getAuthorPHID());
|
||||||
|
|
||||||
|
$this->getMailStamp('reviewer')
|
||||||
|
->setValue($reviewers);
|
||||||
|
|
||||||
|
$this->getMailStamp('blocking-reviewer')
|
||||||
|
->setValue($blocking);
|
||||||
|
|
||||||
|
$this->getMailStamp('resigned-reviewer')
|
||||||
|
->setValue($resigned);
|
||||||
|
|
||||||
|
$this->getMailStamp('revision-repository')
|
||||||
|
->setValue($revision->getRepositoryPHID());
|
||||||
|
|
||||||
|
$this->getMailStamp('revision-status')
|
||||||
|
->setValue($revision->getModernRevisionStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -221,6 +221,51 @@ final class DifferentialChangeset
|
|||||||
return $this->assertAttached($this->diff);
|
return $this->assertAttached($this->diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function newFileTreeIcon() {
|
||||||
|
$file_type = $this->getFileType();
|
||||||
|
$change_type = $this->getChangeType();
|
||||||
|
|
||||||
|
$change_icons = array(
|
||||||
|
DifferentialChangeType::TYPE_DELETE => 'fa-file-o',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($change_icons[$change_type])) {
|
||||||
|
$icon = $change_icons[$change_type];
|
||||||
|
} else {
|
||||||
|
$icon = DifferentialChangeType::getIconForFileType($file_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
$change_colors = array(
|
||||||
|
DifferentialChangeType::TYPE_ADD => 'green',
|
||||||
|
DifferentialChangeType::TYPE_DELETE => 'red',
|
||||||
|
DifferentialChangeType::TYPE_MOVE_AWAY => 'orange',
|
||||||
|
DifferentialChangeType::TYPE_MOVE_HERE => 'orange',
|
||||||
|
DifferentialChangeType::TYPE_COPY_HERE => 'orange',
|
||||||
|
DifferentialChangeType::TYPE_MULTICOPY => 'orange',
|
||||||
|
);
|
||||||
|
|
||||||
|
$color = idx($change_colors, $change_type, 'bluetext');
|
||||||
|
|
||||||
|
return id(new PHUIIconView())
|
||||||
|
->setIcon($icon.' '.$color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFileTreeClass() {
|
||||||
|
switch ($this->getChangeType()) {
|
||||||
|
case DifferentialChangeType::TYPE_ADD:
|
||||||
|
return 'filetree-added';
|
||||||
|
case DifferentialChangeType::TYPE_DELETE:
|
||||||
|
return 'filetree-deleted';
|
||||||
|
case DifferentialChangeType::TYPE_MOVE_AWAY:
|
||||||
|
case DifferentialChangeType::TYPE_MOVE_HERE:
|
||||||
|
case DifferentialChangeType::TYPE_COPY_HERE:
|
||||||
|
case DifferentialChangeType::TYPE_MULTICOPY:
|
||||||
|
return 'filetree-movecopy';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ final class DifferentialReviewer
|
|||||||
return ($this->getReviewerStatus() == $status_resigned);
|
return ($this->getReviewerStatus() == $status_resigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isBlocking() {
|
||||||
|
$status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING;
|
||||||
|
return ($this->getReviewerStatus() == $status_blocking);
|
||||||
|
}
|
||||||
|
|
||||||
public function isRejected($diff_phid) {
|
public function isRejected($diff_phid) {
|
||||||
$status_rejected = DifferentialReviewerStatus::STATUS_REJECTED;
|
$status_rejected = DifferentialReviewerStatus::STATUS_REJECTED;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ final class DifferentialRevision extends DifferentialDAO
|
|||||||
PhabricatorDraftInterface {
|
PhabricatorDraftInterface {
|
||||||
|
|
||||||
protected $title = '';
|
protected $title = '';
|
||||||
protected $originalTitle;
|
|
||||||
protected $status;
|
protected $status;
|
||||||
|
|
||||||
protected $summary = '';
|
protected $summary = '';
|
||||||
@@ -98,7 +97,6 @@ final class DifferentialRevision extends DifferentialDAO
|
|||||||
),
|
),
|
||||||
self::CONFIG_COLUMN_SCHEMA => array(
|
self::CONFIG_COLUMN_SCHEMA => array(
|
||||||
'title' => 'text255',
|
'title' => 'text255',
|
||||||
'originalTitle' => 'text255',
|
|
||||||
'status' => 'text32',
|
'status' => 'text32',
|
||||||
'summary' => 'text',
|
'summary' => 'text',
|
||||||
'testPlan' => 'text',
|
'testPlan' => 'text',
|
||||||
@@ -155,14 +153,6 @@ final class DifferentialRevision extends DifferentialDAO
|
|||||||
return '/'.$this->getMonogram();
|
return '/'.$this->getMonogram();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTitle($title) {
|
|
||||||
$this->title = $title;
|
|
||||||
if (!$this->getID()) {
|
|
||||||
$this->originalTitle = $title;
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadIDsByCommitPHIDs($phids) {
|
public function loadIDsByCommitPHIDs($phids) {
|
||||||
if (!$phids) {
|
if (!$phids) {
|
||||||
return array();
|
return array();
|
||||||
@@ -593,6 +583,10 @@ final class DifferentialRevision extends DifferentialDAO
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasAttachedReviewers() {
|
||||||
|
return ($this->reviewerStatus !== self::ATTACHABLE);
|
||||||
|
}
|
||||||
|
|
||||||
public function getReviewerPHIDs() {
|
public function getReviewerPHIDs() {
|
||||||
$reviewers = $this->getReviewers();
|
$reviewers = $this->getReviewers();
|
||||||
return mpull($reviewers, 'getReviewerPHID');
|
return mpull($reviewers, 'getReviewerPHID');
|
||||||
@@ -830,9 +824,15 @@ final class DifferentialRevision extends DifferentialDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($reviewers as $reviewer) {
|
foreach ($reviewers as $reviewer) {
|
||||||
if ($reviewer->getReviewerPHID() == $phid) {
|
if ($reviewer->getReviewerPHID() !== $phid) {
|
||||||
return true;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($reviewer->isResigned()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -87,19 +87,6 @@ final class DifferentialTransaction
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PhabricatorTransactions::TYPE_EDGE:
|
|
||||||
$add = array_diff_key($new, $old);
|
|
||||||
$rem = array_diff_key($old, $new);
|
|
||||||
|
|
||||||
// Hide metadata-only edge transactions. These correspond to users
|
|
||||||
// accepting or rejecting revisions, but the change is always explicit
|
|
||||||
// because of the TYPE_ACTION transaction. Rendering these transactions
|
|
||||||
// just creates clutter.
|
|
||||||
|
|
||||||
if (!$add && !$rem) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE:
|
case DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE:
|
||||||
// Don't hide the initial "X requested review: ..." transaction from
|
// Don't hide the initial "X requested review: ..." transaction from
|
||||||
// mail or feed even when it occurs during creation. We need this
|
// mail or feed even when it occurs during creation. We need this
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ final class DifferentialChangesetDetailView extends AphrontView {
|
|||||||
'displayPath' => hsprintf('%s', $display_parts),
|
'displayPath' => hsprintf('%s', $display_parts),
|
||||||
'path' => $display_filename,
|
'path' => $display_filename,
|
||||||
'icon' => $display_icon,
|
'icon' => $display_icon,
|
||||||
|
'treeNodeID' => 'tree-node-'.$changeset->getAnchorName(),
|
||||||
),
|
),
|
||||||
'class' => $class,
|
'class' => $class,
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ final class DifferentialChangesetFileTreeSideNavBuilder extends Phobject {
|
|||||||
while (($path = $path->getNextNode())) {
|
while (($path = $path->getNextNode())) {
|
||||||
$data = $path->getData();
|
$data = $path->getData();
|
||||||
|
|
||||||
|
$classes = array();
|
||||||
|
$classes[] = 'phabricator-filetree-item';
|
||||||
|
|
||||||
$name = $path->getName();
|
$name = $path->getName();
|
||||||
$style = 'padding-left: '.(2 + (3 * $path->getDepth())).'px';
|
$style = 'padding-left: '.(2 + (3 * $path->getDepth())).'px';
|
||||||
|
|
||||||
@@ -90,13 +93,23 @@ final class DifferentialChangesetFileTreeSideNavBuilder extends Phobject {
|
|||||||
if ($data) {
|
if ($data) {
|
||||||
$href = '#'.$data->getAnchorName();
|
$href = '#'.$data->getAnchorName();
|
||||||
$title = $name;
|
$title = $name;
|
||||||
$icon = id(new PHUIIconView())
|
|
||||||
->setIcon('fa-file-text-o bluetext');
|
$icon = $data->newFileTreeIcon();
|
||||||
|
$classes[] = $data->getFileTreeClass();
|
||||||
|
|
||||||
|
$count = phutil_tag(
|
||||||
|
'span',
|
||||||
|
array(
|
||||||
|
'class' => 'filetree-progress-hint',
|
||||||
|
'id' => 'tree-node-'.$data->getAnchorName(),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
$name .= '/';
|
$name .= '/';
|
||||||
$title = $path->getFullPath().'/';
|
$title = $path->getFullPath().'/';
|
||||||
$icon = id(new PHUIIconView())
|
$icon = id(new PHUIIconView())
|
||||||
->setIcon('fa-folder-open blue');
|
->setIcon('fa-folder-open blue');
|
||||||
|
|
||||||
|
$count = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$name_element = phutil_tag(
|
$name_element = phutil_tag(
|
||||||
@@ -106,15 +119,16 @@ final class DifferentialChangesetFileTreeSideNavBuilder extends Phobject {
|
|||||||
),
|
),
|
||||||
$name);
|
$name);
|
||||||
|
|
||||||
|
|
||||||
$filetree[] = javelin_tag(
|
$filetree[] = javelin_tag(
|
||||||
$href ? 'a' : 'span',
|
$href ? 'a' : 'span',
|
||||||
array(
|
array(
|
||||||
'href' => $href,
|
'href' => $href,
|
||||||
'style' => $style,
|
'style' => $style,
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'class' => 'phabricator-filetree-item',
|
'class' => implode(' ', $classes),
|
||||||
),
|
),
|
||||||
array($icon, $name_element));
|
array($count, $icon, $name_element));
|
||||||
}
|
}
|
||||||
$tree->destroy();
|
$tree->destroy();
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
|||||||
$this->getEditRoutePattern('edit/') =>
|
$this->getEditRoutePattern('edit/') =>
|
||||||
'DiffusionRepositoryEditController',
|
'DiffusionRepositoryEditController',
|
||||||
'pushlog/' => array(
|
'pushlog/' => array(
|
||||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DiffusionPushLogListController',
|
$this->getQueryRoutePattern() => 'DiffusionPushLogListController',
|
||||||
'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController',
|
'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController',
|
||||||
),
|
),
|
||||||
'pulllog/' => array(
|
'pulllog/' => array(
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ final class DiffusionQueryPathsConduitAPIMethod
|
|||||||
$commit = $request->getValue('commit');
|
$commit = $request->getValue('commit');
|
||||||
$repository = $drequest->getRepository();
|
$repository = $drequest->getRepository();
|
||||||
|
|
||||||
// http://comments.gmane.org/gmane.comp.version-control.git/197735
|
// Recent versions of Git don't work if you pass the empty string, and
|
||||||
|
// require "." to list everything.
|
||||||
|
if (!strlen($path)) {
|
||||||
|
$path = '.';
|
||||||
|
}
|
||||||
|
|
||||||
$future = $repository->getLocalCommandFuture(
|
$future = $repository->getLocalCommandFuture(
|
||||||
'ls-tree --name-only -r -z %s -- %s',
|
'ls-tree --name-only -r -z %s -- %s',
|
||||||
|
|||||||
@@ -9,4 +9,9 @@ final class DiffusionPullLogListController
|
|||||||
->buildResponse();
|
->buildResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function buildApplicationCrumbs() {
|
||||||
|
return parent::buildApplicationCrumbs()
|
||||||
|
->addTextCrumb(pht('Pull Logs'), $this->getApplicationURI('pulllog/'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,9 @@ final class DiffusionPushLogListController
|
|||||||
->buildResponse();
|
->buildResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function buildApplicationCrumbs() {
|
||||||
|
return parent::buildApplicationCrumbs()
|
||||||
|
->addTextCrumb(pht('Push Logs'), $this->getApplicationURI('pushlog/'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,10 @@ final class DiffusionRepositoryURIViewController
|
|||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For display, reload the URI by loading it through the repository. This
|
// For display, access the URI by loading it through the repository. This
|
||||||
// may adjust builtin URIs for repository configuration, so we may end up
|
// may adjust builtin URIs for repository configuration, so we may end up
|
||||||
// with a different view of builtin URIs than we'd see if we loaded them
|
// with a different view of builtin URIs than we'd see if we loaded them
|
||||||
// directly from the database. See T12884.
|
// directly from the database. See T12884.
|
||||||
$repository_with_uris = id(new PhabricatorRepositoryQuery())
|
|
||||||
->setViewer($viewer)
|
|
||||||
->needURIs(true)
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
$repository_uris = $repository->getURIs();
|
$repository_uris = $repository->getURIs();
|
||||||
$repository_uris = mpull($repository_uris, null, 'getID');
|
$repository_uris = mpull($repository_uris, null, 'getID');
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
|||||||
$add_edges) {
|
$add_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s added %s reverting commit(s): %s.',
|
'%s added %s reverting change(s): %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$add_count,
|
$add_count,
|
||||||
$add_edges);
|
$add_edges);
|
||||||
@@ -31,7 +31,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s removed %s reverting commit(s): %s.',
|
'%s removed %s reverting change(s): %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$rem_count,
|
$rem_count,
|
||||||
$rem_edges);
|
$rem_edges);
|
||||||
@@ -46,7 +46,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s edited reverting commit(s), added %s: %s; removed %s: %s.',
|
'%s edited reverting change(s), added %s: %s; removed %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$add_count,
|
$add_count,
|
||||||
$add_edges,
|
$add_edges,
|
||||||
@@ -61,7 +61,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
|||||||
$add_edges) {
|
$add_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s added %s reverting commit(s) for %s: %s.',
|
'%s added %s reverting change(s) for %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$add_count,
|
$add_count,
|
||||||
$object,
|
$object,
|
||||||
@@ -75,7 +75,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s removed %s reverting commit(s) for %s: %s.',
|
'%s removed %s reverting change(s) for %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$rem_count,
|
$rem_count,
|
||||||
$object,
|
$object,
|
||||||
@@ -92,7 +92,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s edited reverting commit(s) for %s, added %s: %s; removed %s: %s.',
|
'%s edited reverting change(s) for %s, added %s: %s; removed %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$object,
|
$object,
|
||||||
$add_count,
|
$add_count,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
|||||||
$add_edges) {
|
$add_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s added %s reverted commit(s): %s.',
|
'%s added %s reverted change(s): %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$add_count,
|
$add_count,
|
||||||
$add_edges);
|
$add_edges);
|
||||||
@@ -34,7 +34,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s removed %s reverted commit(s): %s.',
|
'%s removed %s reverted change(s): %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$rem_count,
|
$rem_count,
|
||||||
$rem_edges);
|
$rem_edges);
|
||||||
@@ -49,7 +49,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s edited reverted commit(s), added %s: %s; removed %s: %s.',
|
'%s edited reverted change(s), added %s: %s; removed %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$add_count,
|
$add_count,
|
||||||
$add_edges,
|
$add_edges,
|
||||||
@@ -64,7 +64,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
|||||||
$add_edges) {
|
$add_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s added %s reverted commit(s) for %s: %s.',
|
'%s added %s reverted change(s) for %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$add_count,
|
$add_count,
|
||||||
$object,
|
$object,
|
||||||
@@ -78,7 +78,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s removed %s reverted commit(s) for %s: %s.',
|
'%s removed %s reverted change(s) for %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$rem_count,
|
$rem_count,
|
||||||
$object,
|
$object,
|
||||||
@@ -95,7 +95,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
|||||||
$rem_edges) {
|
$rem_edges) {
|
||||||
|
|
||||||
return pht(
|
return pht(
|
||||||
'%s edited reverted commit(s) for %s, added %s: %s; removed %s: %s.',
|
'%s edited reverted change(s) for %s, added %s: %s; removed %s: %s.',
|
||||||
$actor,
|
$actor,
|
||||||
$object,
|
$object,
|
||||||
$add_count,
|
$add_count,
|
||||||
|
|||||||
@@ -297,7 +297,11 @@ final class DiffusionCommitHookEngine extends Phobject {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$adapter_template->setHookEngine($this);
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$adapter_template
|
||||||
|
->setHookEngine($this)
|
||||||
|
->setActingAsPHID($viewer->getPHID());
|
||||||
|
|
||||||
$engine = new HeraldEngine();
|
$engine = new HeraldEngine();
|
||||||
$rules = null;
|
$rules = null;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ final class DiffusionGitLFSAuthenticateWorkflow
|
|||||||
// This works even if normal HTTP repository operations are not available
|
// This works even if normal HTTP repository operations are not available
|
||||||
// on this host, and does not require the user to have a VCS password.
|
// on this host, and does not require the user to have a VCS password.
|
||||||
|
|
||||||
$user = $this->getUser();
|
$user = $this->getSSHUser();
|
||||||
|
|
||||||
$authorization = DiffusionGitLFSTemporaryTokenType::newHTTPAuthorization(
|
$authorization = DiffusionGitLFSTemporaryTokenType::newHTTPAuthorization(
|
||||||
$repository,
|
$repository,
|
||||||
|
|||||||
@@ -135,13 +135,16 @@ final class HeraldCommitAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function loadAffectedPaths() {
|
public function loadAffectedPaths() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
if ($this->affectedPaths === null) {
|
if ($this->affectedPaths === null) {
|
||||||
$result = PhabricatorOwnerPathQuery::loadAffectedPaths(
|
$result = PhabricatorOwnerPathQuery::loadAffectedPaths(
|
||||||
$this->getRepository(),
|
$this->getRepository(),
|
||||||
$this->commit,
|
$this->commit,
|
||||||
PhabricatorUser::getOmnipotentUser());
|
$viewer);
|
||||||
$this->affectedPaths = $result;
|
$this->affectedPaths = $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->affectedPaths;
|
return $this->affectedPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +175,8 @@ final class HeraldCommitAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function loadDifferentialRevision() {
|
public function loadDifferentialRevision() {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
if ($this->affectedRevision === null) {
|
if ($this->affectedRevision === null) {
|
||||||
$this->affectedRevision = false;
|
$this->affectedRevision = false;
|
||||||
|
|
||||||
@@ -189,7 +194,7 @@ final class HeraldCommitAdapter
|
|||||||
|
|
||||||
$revision = id(new DifferentialRevisionQuery())
|
$revision = id(new DifferentialRevisionQuery())
|
||||||
->withIDs(array($revision_id))
|
->withIDs(array($revision_id))
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer($viewer)
|
||||||
->needReviewers(true)
|
->needReviewers(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if ($revision) {
|
if ($revision) {
|
||||||
@@ -197,6 +202,7 @@ final class HeraldCommitAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->affectedRevision;
|
return $this->affectedRevision;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +329,7 @@ final class HeraldCommitAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function callConduit($method, array $params) {
|
private function callConduit($method, array $params) {
|
||||||
$viewer = PhabricatorUser::getOmnipotentUser();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
$drequest = DiffusionRequest::newFromDictionary(
|
$drequest = DiffusionRequest::newFromDictionary(
|
||||||
array(
|
array(
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ final class DiffusionPullLogSearchEngine
|
|||||||
$query->withPullerPHIDs($map['pullerPHIDs']);
|
$query->withPullerPHIDs($map['pullerPHIDs']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($map['createdStart'] || $map['createdEnd']) {
|
||||||
|
$query->withEpochBetween(
|
||||||
|
$map['createdStart'],
|
||||||
|
$map['createdEnd']);
|
||||||
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,17 +50,19 @@ final class DiffusionPullLogSearchEngine
|
|||||||
->setLabel(pht('Pullers'))
|
->setLabel(pht('Pullers'))
|
||||||
->setDescription(
|
->setDescription(
|
||||||
pht('Search for pull logs by specific users.')),
|
pht('Search for pull logs by specific users.')),
|
||||||
|
id(new PhabricatorSearchDateField())
|
||||||
|
->setLabel(pht('Created After'))
|
||||||
|
->setKey('createdStart'),
|
||||||
|
id(new PhabricatorSearchDateField())
|
||||||
|
->setLabel(pht('Created Before'))
|
||||||
|
->setKey('createdEnd'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function newExportFields() {
|
protected function newExportFields() {
|
||||||
return array(
|
$viewer = $this->requireViewer();
|
||||||
id(new PhabricatorIDExportField())
|
|
||||||
->setKey('id')
|
$fields = array(
|
||||||
->setLabel(pht('ID')),
|
|
||||||
id(new PhabricatorPHIDExportField())
|
|
||||||
->setKey('phid')
|
|
||||||
->setLabel(pht('PHID')),
|
|
||||||
id(new PhabricatorPHIDExportField())
|
id(new PhabricatorPHIDExportField())
|
||||||
->setKey('repositoryPHID')
|
->setKey('repositoryPHID')
|
||||||
->setLabel(pht('Repository PHID')),
|
->setLabel(pht('Repository PHID')),
|
||||||
@@ -80,9 +88,17 @@ final class DiffusionPullLogSearchEngine
|
|||||||
->setKey('date')
|
->setKey('date')
|
||||||
->setLabel(pht('Date')),
|
->setLabel(pht('Date')),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($viewer->getIsAdmin()) {
|
||||||
|
$fields[] = id(new PhabricatorStringExportField())
|
||||||
|
->setKey('remoteAddress')
|
||||||
|
->setLabel(pht('Remote Address'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newExport(array $events) {
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newExportData(array $events) {
|
||||||
$viewer = $this->requireViewer();
|
$viewer = $this->requireViewer();
|
||||||
|
|
||||||
$phids = array();
|
$phids = array();
|
||||||
@@ -111,9 +127,7 @@ final class DiffusionPullLogSearchEngine
|
|||||||
$puller_name = null;
|
$puller_name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$export[] = array(
|
$map = array(
|
||||||
'id' => $event->getID(),
|
|
||||||
'phid' => $event->getPHID(),
|
|
||||||
'repositoryPHID' => $repository_phid,
|
'repositoryPHID' => $repository_phid,
|
||||||
'repository' => $repository_name,
|
'repository' => $repository_name,
|
||||||
'pullerPHID' => $puller_phid,
|
'pullerPHID' => $puller_phid,
|
||||||
@@ -123,6 +137,12 @@ final class DiffusionPullLogSearchEngine
|
|||||||
'code' => $event->getResultCode(),
|
'code' => $event->getResultCode(),
|
||||||
'date' => $event->getEpoch(),
|
'date' => $event->getEpoch(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($viewer->getIsAdmin()) {
|
||||||
|
$map['remoteAddress'] = $event->getRemoteAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
$export[] = $map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $export;
|
return $export;
|
||||||
|
|||||||
@@ -22,24 +22,10 @@ final class DiffusionPullLogListView extends AphrontView {
|
|||||||
}
|
}
|
||||||
$handles = $viewer->loadHandles($handle_phids);
|
$handles = $viewer->loadHandles($handle_phids);
|
||||||
|
|
||||||
// Figure out which repositories are editable. We only let you see remote
|
// Only administrators can view remote addresses.
|
||||||
// IPs if you have edit capability on a repository.
|
$remotes_visible = $viewer->getIsAdmin();
|
||||||
$editable_repos = array();
|
|
||||||
if ($events) {
|
|
||||||
$editable_repos = id(new PhabricatorRepositoryQuery())
|
|
||||||
->setViewer($viewer)
|
|
||||||
->requireCapabilities(
|
|
||||||
array(
|
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
|
||||||
PhabricatorPolicyCapability::CAN_EDIT,
|
|
||||||
))
|
|
||||||
->withPHIDs(mpull($events, 'getRepositoryPHID'))
|
|
||||||
->execute();
|
|
||||||
$editable_repos = mpull($editable_repos, null, 'getPHID');
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$any_host = false;
|
|
||||||
foreach ($events as $event) {
|
foreach ($events as $event) {
|
||||||
if ($event->getRepositoryPHID()) {
|
if ($event->getRepositoryPHID()) {
|
||||||
$repository = $event->getRepository();
|
$repository = $event->getRepository();
|
||||||
@@ -47,13 +33,10 @@ final class DiffusionPullLogListView extends AphrontView {
|
|||||||
$repository = null;
|
$repository = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reveal this if it's valid and the user can edit the repository. For
|
if ($remotes_visible) {
|
||||||
// invalid requests you currently have to go fishing in the database.
|
|
||||||
$remote_address = '-';
|
|
||||||
if ($repository) {
|
|
||||||
if (isset($editable_repos[$event->getRepositoryPHID()])) {
|
|
||||||
$remote_address = $event->getRemoteAddress();
|
$remote_address = $event->getRemoteAddress();
|
||||||
}
|
} else {
|
||||||
|
$remote_address = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$event_id = $event->getID();
|
$event_id = $event->getID();
|
||||||
@@ -107,6 +90,13 @@ final class DiffusionPullLogListView extends AphrontView {
|
|||||||
'',
|
'',
|
||||||
'n',
|
'n',
|
||||||
'right',
|
'right',
|
||||||
|
))
|
||||||
|
->setColumnVisibility(
|
||||||
|
array(
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
$remotes_visible,
|
||||||
));
|
));
|
||||||
|
|
||||||
return $table;
|
return $table;
|
||||||
|
|||||||
@@ -25,31 +25,21 @@ final class DiffusionPushLogListView extends AphrontView {
|
|||||||
|
|
||||||
$handles = $viewer->loadHandles($handle_phids);
|
$handles = $viewer->loadHandles($handle_phids);
|
||||||
|
|
||||||
// Figure out which repositories are editable. We only let you see remote
|
// Only administrators can view remote addresses.
|
||||||
// IPs if you have edit capability on a repository.
|
$remotes_visible = $viewer->getIsAdmin();
|
||||||
$editable_repos = array();
|
|
||||||
if ($logs) {
|
$flag_map = PhabricatorRepositoryPushLog::getFlagDisplayNames();
|
||||||
$editable_repos = id(new PhabricatorRepositoryQuery())
|
$reject_map = PhabricatorRepositoryPushLog::getRejectCodeDisplayNames();
|
||||||
->setViewer($viewer)
|
|
||||||
->requireCapabilities(
|
|
||||||
array(
|
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
|
||||||
PhabricatorPolicyCapability::CAN_EDIT,
|
|
||||||
))
|
|
||||||
->withPHIDs(mpull($logs, 'getRepositoryPHID'))
|
|
||||||
->execute();
|
|
||||||
$editable_repos = mpull($editable_repos, null, 'getPHID');
|
|
||||||
}
|
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$any_host = false;
|
$any_host = false;
|
||||||
foreach ($logs as $log) {
|
foreach ($logs as $log) {
|
||||||
$repository = $log->getRepository();
|
$repository = $log->getRepository();
|
||||||
|
|
||||||
// Reveal this if it's valid and the user can edit the repository.
|
if ($remotes_visible) {
|
||||||
$remote_address = '-';
|
|
||||||
if (isset($editable_repos[$log->getRepositoryPHID()])) {
|
|
||||||
$remote_address = $log->getPushEvent()->getRemoteAddress();
|
$remote_address = $log->getPushEvent()->getRemoteAddress();
|
||||||
|
} else {
|
||||||
|
$remote_address = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$event_id = $log->getPushEvent()->getID();
|
$event_id = $log->getPushEvent()->getID();
|
||||||
@@ -72,6 +62,23 @@ final class DiffusionPushLogListView extends AphrontView {
|
|||||||
$device = null;
|
$device = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$flags = $log->getChangeFlags();
|
||||||
|
$flag_names = array();
|
||||||
|
foreach ($flag_map as $flag_key => $flag_name) {
|
||||||
|
if (($flags & $flag_key) === $flag_key) {
|
||||||
|
$flag_names[] = $flag_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$flag_names = phutil_implode_html(
|
||||||
|
phutil_tag('br'),
|
||||||
|
$flag_names);
|
||||||
|
|
||||||
|
$reject_code = $log->getPushEvent()->getRejectCode();
|
||||||
|
$reject_label = idx(
|
||||||
|
$reject_map,
|
||||||
|
$reject_code,
|
||||||
|
pht('Unknown ("%s")', $reject_code));
|
||||||
|
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
@@ -98,10 +105,8 @@ final class DiffusionPushLogListView extends AphrontView {
|
|||||||
'href' => $repository->getCommitURI($log->getRefNew()),
|
'href' => $repository->getCommitURI($log->getRefNew()),
|
||||||
),
|
),
|
||||||
$log->getRefNewShort()),
|
$log->getRefNewShort()),
|
||||||
|
$flag_names,
|
||||||
// TODO: Make these human-readable.
|
$reject_label,
|
||||||
$log->getChangeFlags(),
|
|
||||||
$log->getPushEvent()->getRejectCode(),
|
|
||||||
$viewer->formatShortDateTime($log->getEpoch()),
|
$viewer->formatShortDateTime($log->getEpoch()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -120,7 +125,7 @@ final class DiffusionPushLogListView extends AphrontView {
|
|||||||
pht('Old'),
|
pht('Old'),
|
||||||
pht('New'),
|
pht('New'),
|
||||||
pht('Flags'),
|
pht('Flags'),
|
||||||
pht('Code'),
|
pht('Result'),
|
||||||
pht('Date'),
|
pht('Date'),
|
||||||
))
|
))
|
||||||
->setColumnClasses(
|
->setColumnClasses(
|
||||||
@@ -135,6 +140,8 @@ final class DiffusionPushLogListView extends AphrontView {
|
|||||||
'wide',
|
'wide',
|
||||||
'n',
|
'n',
|
||||||
'n',
|
'n',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
'right',
|
'right',
|
||||||
))
|
))
|
||||||
->setColumnVisibility(
|
->setColumnVisibility(
|
||||||
@@ -142,7 +149,7 @@ final class DiffusionPushLogListView extends AphrontView {
|
|||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
$remotes_visible,
|
||||||
true,
|
true,
|
||||||
$any_host,
|
$any_host,
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ final class PhabricatorFileEditor
|
|||||||
$name = $object->getName();
|
$name = $object->getName();
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("F{$id}: {$name}")
|
->setSubject("F{$id}: {$name}");
|
||||||
->addHeader('Thread-Topic', "F{$id}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMailBody(
|
protected function buildMailBody(
|
||||||
|
|||||||
@@ -272,8 +272,12 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||||||
$file->setByteSize($length);
|
$file->setByteSize($length);
|
||||||
|
|
||||||
// NOTE: Once we receive the first chunk, we'll detect its MIME type and
|
// NOTE: Once we receive the first chunk, we'll detect its MIME type and
|
||||||
// update the parent file. This matters for large media files like video.
|
// update the parent file if a MIME type hasn't been provided. This matters
|
||||||
|
// for large media files like video.
|
||||||
|
$mime_type = idx($params, 'mime-type');
|
||||||
|
if (!strlen($mime_type)) {
|
||||||
$file->setMimeType('application/octet-stream');
|
$file->setMimeType('application/octet-stream');
|
||||||
|
}
|
||||||
|
|
||||||
$chunked_hash = idx($params, 'chunkedHash');
|
$chunked_hash = idx($params, 'chunkedHash');
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ abstract class PhabricatorFileUploadSource
|
|||||||
private $name;
|
private $name;
|
||||||
private $relativeTTL;
|
private $relativeTTL;
|
||||||
private $viewPolicy;
|
private $viewPolicy;
|
||||||
|
private $mimeType;
|
||||||
|
private $authorPHID;
|
||||||
|
|
||||||
private $rope;
|
private $rope;
|
||||||
private $data;
|
private $data;
|
||||||
@@ -51,6 +53,24 @@ abstract class PhabricatorFileUploadSource
|
|||||||
return $this->byteLimit;
|
return $this->byteLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setMIMEType($mime_type) {
|
||||||
|
$this->mimeType = $mime_type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMIMEType() {
|
||||||
|
return $this->mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAuthorPHID($author_phid) {
|
||||||
|
$this->authorPHID = $author_phid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthorPHID() {
|
||||||
|
return $this->authorPHID;
|
||||||
|
}
|
||||||
|
|
||||||
public function uploadFile() {
|
public function uploadFile() {
|
||||||
if (!$this->shouldChunkFile()) {
|
if (!$this->shouldChunkFile()) {
|
||||||
return $this->writeSingleFile();
|
return $this->writeSingleFile();
|
||||||
@@ -245,6 +265,16 @@ abstract class PhabricatorFileUploadSource
|
|||||||
$parameters['ttl.relative'] = $ttl;
|
$parameters['ttl.relative'] = $ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mime_type = $this->getMimeType();
|
||||||
|
if ($mime_type !== null) {
|
||||||
|
$parameters['mime-type'] = $mime_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
$author_phid = $this->getAuthorPHID();
|
||||||
|
if ($author_phid !== null) {
|
||||||
|
$parameters['authorPHID'] = $author_phid;
|
||||||
|
}
|
||||||
|
|
||||||
return $parameters;
|
return $parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ final class FundInitiativeEditor
|
|||||||
$name = $object->getName();
|
$name = $object->getName();
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("{$monogram}: {$name}")
|
->setSubject("{$monogram}: {$name}");
|
||||||
->addHeader('Thread-Topic', $monogram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMailBody(
|
protected function buildMailBody(
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ abstract class HeraldAdapter extends Phobject {
|
|||||||
private $edgeCache = array();
|
private $edgeCache = array();
|
||||||
private $forbiddenActions = array();
|
private $forbiddenActions = array();
|
||||||
private $viewer;
|
private $viewer;
|
||||||
|
private $mustEncryptReasons = array();
|
||||||
|
private $actingAsPHID;
|
||||||
|
|
||||||
public function getEmailPHIDs() {
|
public function getEmailPHIDs() {
|
||||||
return array_values($this->emailPHIDs);
|
return array_values($this->emailPHIDs);
|
||||||
@@ -48,6 +50,15 @@ abstract class HeraldAdapter extends Phobject {
|
|||||||
return array_values($this->forcedEmailPHIDs);
|
return array_values($this->forcedEmailPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public function setActingAsPHID($acting_as_phid) {
|
||||||
|
$this->actingAsPHID = $acting_as_phid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getActingAsPHID() {
|
||||||
|
return $this->actingAsPHID;
|
||||||
|
}
|
||||||
|
|
||||||
public function addEmailPHID($phid, $force) {
|
public function addEmailPHID($phid, $force) {
|
||||||
$this->emailPHIDs[$phid] = $phid;
|
$this->emailPHIDs[$phid] = $phid;
|
||||||
if ($force) {
|
if ($force) {
|
||||||
@@ -1182,4 +1193,17 @@ abstract class HeraldAdapter extends Phobject {
|
|||||||
return $this->forbiddenActions[$action];
|
return $this->forbiddenActions[$action];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Must Encrypt )------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
final public function addMustEncryptReason($reason) {
|
||||||
|
$this->mustEncryptReasons[] = $reason;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getMustEncryptReasons() {
|
||||||
|
return $this->mustEncryptReasons;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,7 +265,15 @@ final class HeraldRuleController extends HeraldController {
|
|||||||
$new_name = $request->getStr('name');
|
$new_name = $request->getStr('name');
|
||||||
$match_all = ($request->getStr('must_match') == 'all');
|
$match_all = ($request->getStr('must_match') == 'all');
|
||||||
|
|
||||||
$repetition_policy_param = $request->getStr('repetition_policy');
|
$repetition_policy = $request->getStr('repetition_policy');
|
||||||
|
|
||||||
|
// If the user selected an invalid policy, or there's only one possible
|
||||||
|
// value so we didn't render a control, adjust the value to the first
|
||||||
|
// valid policy value.
|
||||||
|
$repetition_options = $this->getRepetitionOptionMap($adapter);
|
||||||
|
if (!isset($repetition_options[$repetition_policy])) {
|
||||||
|
$repetition_policy = head_key($repetition_options);
|
||||||
|
}
|
||||||
|
|
||||||
$e_name = true;
|
$e_name = true;
|
||||||
$errors = array();
|
$errors = array();
|
||||||
@@ -348,7 +356,7 @@ final class HeraldRuleController extends HeraldController {
|
|||||||
$match_all,
|
$match_all,
|
||||||
$conditions,
|
$conditions,
|
||||||
$actions,
|
$actions,
|
||||||
$repetition_policy_param);
|
$repetition_policy);
|
||||||
|
|
||||||
$xactions = array();
|
$xactions = array();
|
||||||
$xactions[] = id(new HeraldRuleTransaction())
|
$xactions[] = id(new HeraldRuleTransaction())
|
||||||
@@ -373,7 +381,7 @@ final class HeraldRuleController extends HeraldController {
|
|||||||
// mutate current rule, so it would be sent to the client in the right state
|
// mutate current rule, so it would be sent to the client in the right state
|
||||||
$rule->setMustMatchAll((int)$match_all);
|
$rule->setMustMatchAll((int)$match_all);
|
||||||
$rule->setName($new_name);
|
$rule->setName($new_name);
|
||||||
$rule->setRepetitionPolicyStringConstant($repetition_policy_param);
|
$rule->setRepetitionPolicyStringConstant($repetition_policy);
|
||||||
$rule->attachConditions($conditions);
|
$rule->attachConditions($conditions);
|
||||||
$rule->attachActions($actions);
|
$rule->attachActions($actions);
|
||||||
|
|
||||||
@@ -594,13 +602,9 @@ final class HeraldRuleController extends HeraldController {
|
|||||||
*/
|
*/
|
||||||
private function renderRepetitionSelector($rule, HeraldAdapter $adapter) {
|
private function renderRepetitionSelector($rule, HeraldAdapter $adapter) {
|
||||||
$repetition_policy = $rule->getRepetitionPolicyStringConstant();
|
$repetition_policy = $rule->getRepetitionPolicyStringConstant();
|
||||||
|
$repetition_map = $this->getRepetitionOptionMap($adapter);
|
||||||
$repetition_options = $adapter->getRepetitionOptions();
|
|
||||||
$repetition_names = HeraldRule::getRepetitionPolicySelectOptionMap();
|
|
||||||
$repetition_map = array_select_keys($repetition_names, $repetition_options);
|
|
||||||
|
|
||||||
if (count($repetition_map) < 2) {
|
if (count($repetition_map) < 2) {
|
||||||
return head($repetition_names);
|
return head($repetition_map);
|
||||||
} else {
|
} else {
|
||||||
return AphrontFormSelectControl::renderSelectTag(
|
return AphrontFormSelectControl::renderSelectTag(
|
||||||
$repetition_policy,
|
$repetition_policy,
|
||||||
@@ -611,6 +615,11 @@ final class HeraldRuleController extends HeraldController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getRepetitionOptionMap(HeraldAdapter $adapter) {
|
||||||
|
$repetition_options = $adapter->getRepetitionOptions();
|
||||||
|
$repetition_names = HeraldRule::getRepetitionPolicySelectOptionMap();
|
||||||
|
return array_select_keys($repetition_names, $repetition_options);
|
||||||
|
}
|
||||||
|
|
||||||
protected function buildTokenizerTemplates() {
|
protected function buildTokenizerTemplates() {
|
||||||
$template = new AphrontTokenizerTemplateView();
|
$template = new AphrontTokenizerTemplateView();
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ final class HeraldTestConsoleController extends HeraldController {
|
|||||||
|
|
||||||
$adapter
|
$adapter
|
||||||
->setIsNewObject(false)
|
->setIsNewObject(false)
|
||||||
|
->setActingAsPHID($viewer->getPHID())
|
||||||
->setViewer($viewer);
|
->setViewer($viewer);
|
||||||
|
|
||||||
$rules = id(new HeraldRuleQuery())
|
$rules = id(new HeraldRuleQuery())
|
||||||
|
|||||||
32
src/applications/herald/field/HeraldActingUserField.php
Normal file
32
src/applications/herald/field/HeraldActingUserField.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class HeraldActingUserField
|
||||||
|
extends HeraldField {
|
||||||
|
|
||||||
|
const FIELDCONST = 'herald.acting-user';
|
||||||
|
|
||||||
|
public function getHeraldFieldName() {
|
||||||
|
return pht('Acting user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeraldFieldValue($object) {
|
||||||
|
return $this->getAdapter()->getActingAsPHID();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getHeraldFieldStandardType() {
|
||||||
|
return self::STANDARD_PHID;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDatasource() {
|
||||||
|
return new PhabricatorPeopleDatasource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsObject($object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFieldGroupKey() {
|
||||||
|
return HeraldEditFieldGroup::FIELDGROUPKEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -124,12 +124,10 @@ final class LegalpadDocumentEditor
|
|||||||
|
|
||||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||||
$id = $object->getID();
|
$id = $object->getID();
|
||||||
$phid = $object->getPHID();
|
|
||||||
$title = $object->getDocumentBody()->getTitle();
|
$title = $object->getDocumentBody()->getTitle();
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("L{$id}: {$title}")
|
->setSubject("L{$id}: {$title}");
|
||||||
->addHeader('Thread-Topic', "L{$id}: {$phid}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ final class LegalpadDocumentSearchEngine
|
|||||||
$create_button = id(new PHUIButtonView())
|
$create_button = id(new PHUIButtonView())
|
||||||
->setTag('a')
|
->setTag('a')
|
||||||
->setText(pht('Create a Document'))
|
->setText(pht('Create a Document'))
|
||||||
->setHref('/legalpad/create/')
|
->setHref('/legalpad/edit/')
|
||||||
->setColor(PHUIButtonView::GREEN);
|
->setColor(PHUIButtonView::GREEN);
|
||||||
|
|
||||||
$icon = $this->getApplication()->getIcon();
|
$icon = $this->getApplication()->getIcon();
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ final class PhabricatorMacroEditor
|
|||||||
$name = 'Image Macro "'.$name.'"';
|
$name = 'Image Macro "'.$name.'"';
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject($name)
|
->setSubject($name);
|
||||||
->addHeader('Thread-Topic', $name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
|
|||||||
'/T(?P<id>[1-9]\d*)' => 'ManiphestTaskDetailController',
|
'/T(?P<id>[1-9]\d*)' => 'ManiphestTaskDetailController',
|
||||||
'/maniphest/' => array(
|
'/maniphest/' => array(
|
||||||
'(?:project/(?P<projectKey>[^/]+)/)?(?:type/(?P<taskTypeKey>[^/]+)/)?(?:query/(?P<queryKey>[^/]+)/)?' => 'ManiphestTaskListController',
|
'(?:project/(?P<projectKey>[^/]+)/)?(?:type/(?P<taskTypeKey>[^/]+)/)?(?:query/(?P<queryKey>[^/]+)/)?' => 'ManiphestTaskListController',
|
||||||
|
$this->getQueryRoutePattern() => 'ManiphestTaskListController',
|
||||||
'report/(?:(?P<view>\w+)/)?' => 'ManiphestReportController',
|
'report/(?:(?P<view>\w+)/)?' => 'ManiphestReportController',
|
||||||
$this->getBulkRoutePattern('bulk/') => 'ManiphestBulkEditController',
|
$this->getBulkRoutePattern('bulk/') => 'ManiphestBulkEditController',
|
||||||
'task/' => array(
|
'task/' => array(
|
||||||
$this->getEditRoutePattern('edit/')
|
$this->getEditRoutePattern('edit/')
|
||||||
=> 'ManiphestTaskEditController',
|
=> 'ManiphestTaskEditController',
|
||||||
),
|
),
|
||||||
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
|
|
||||||
'subpriority/' => 'ManiphestSubpriorityController',
|
'subpriority/' => 'ManiphestSubpriorityController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestExportController extends ManiphestController {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @phutil-external-symbol class PHPExcel
|
|
||||||
* @phutil-external-symbol class PHPExcel_IOFactory
|
|
||||||
* @phutil-external-symbol class PHPExcel_Style_NumberFormat
|
|
||||||
* @phutil-external-symbol class PHPExcel_Cell_DataType
|
|
||||||
*/
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
|
||||||
$viewer = $this->getViewer();
|
|
||||||
$key = $request->getURIData('key');
|
|
||||||
|
|
||||||
$ok = @include_once 'PHPExcel.php';
|
|
||||||
if (!$ok) {
|
|
||||||
$dialog = $this->newDialog();
|
|
||||||
|
|
||||||
$inst1 = pht(
|
|
||||||
'This system does not have PHPExcel installed. This software '.
|
|
||||||
'component is required to export tasks to Excel. Have your system '.
|
|
||||||
'administrator install it from:');
|
|
||||||
|
|
||||||
$inst2 = pht(
|
|
||||||
'Your PHP "%s" needs to be updated to include the '.
|
|
||||||
'PHPExcel Classes directory.',
|
|
||||||
'include_path');
|
|
||||||
|
|
||||||
$dialog->setTitle(pht('Excel Export Not Configured'));
|
|
||||||
$dialog->appendChild(hsprintf(
|
|
||||||
'<p>%s</p>'.
|
|
||||||
'<br />'.
|
|
||||||
'<p>'.
|
|
||||||
'<a href="https://github.com/PHPOffice/PHPExcel">'.
|
|
||||||
'https://github.com/PHPOffice/PHPExcel'.
|
|
||||||
'</a>'.
|
|
||||||
'</p>'.
|
|
||||||
'<br />'.
|
|
||||||
'<p>%s</p>',
|
|
||||||
$inst1,
|
|
||||||
$inst2));
|
|
||||||
|
|
||||||
$dialog->addCancelButton('/maniphest/');
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: PHPExcel has a dependency on the PHP zip extension. We should test
|
|
||||||
// for that here, since it fatals if we don't have the ZipArchive class.
|
|
||||||
|
|
||||||
$saved = id(new PhabricatorSavedQueryQuery())
|
|
||||||
->setViewer($viewer)
|
|
||||||
->withQueryKeys(array($key))
|
|
||||||
->executeOne();
|
|
||||||
if (!$saved) {
|
|
||||||
$engine = id(new ManiphestTaskSearchEngine())
|
|
||||||
->setViewer($viewer)
|
|
||||||
->setProjectKey($this->projectKey)
|
|
||||||
->setTaskTypeKey($this->taskTypeKey);
|
|
||||||
if ($engine->isBuiltinQuery($key)) {
|
|
||||||
$saved = $engine->buildSavedQueryFromBuiltin($key);
|
|
||||||
}
|
|
||||||
if (!$saved) {
|
|
||||||
return new Aphront404Response();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$formats = ManiphestExcelFormat::loadAllFormats();
|
|
||||||
$export_formats = array();
|
|
||||||
foreach ($formats as $format_class => $format_object) {
|
|
||||||
$export_formats[$format_class] = $format_object->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$request->isDialogFormPost()) {
|
|
||||||
$dialog = new AphrontDialogView();
|
|
||||||
$dialog->setUser($viewer);
|
|
||||||
|
|
||||||
$dialog->setTitle(pht('Export Tasks to Excel'));
|
|
||||||
$dialog->appendChild(
|
|
||||||
phutil_tag(
|
|
||||||
'p',
|
|
||||||
array(),
|
|
||||||
pht('Do you want to export the query results to Excel?')));
|
|
||||||
|
|
||||||
$form = id(new PHUIFormLayoutView())
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormSelectControl())
|
|
||||||
->setLabel(pht('Format:'))
|
|
||||||
->setName('excel-format')
|
|
||||||
->setOptions($export_formats));
|
|
||||||
|
|
||||||
$dialog->appendChild($form);
|
|
||||||
|
|
||||||
$dialog->addCancelButton('/maniphest/');
|
|
||||||
$dialog->addSubmitButton(pht('Export to Excel'));
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
$format = idx($formats, $request->getStr('excel-format'));
|
|
||||||
if ($format === null) {
|
|
||||||
throw new Exception(pht('Excel format object not found.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$saved->makeEphemeral();
|
|
||||||
$saved->setParameter('limit', PHP_INT_MAX);
|
|
||||||
|
|
||||||
$engine = id(new ManiphestTaskSearchEngine())
|
|
||||||
->setViewer($viewer);
|
|
||||||
|
|
||||||
$query = $engine->buildQueryFromSavedQuery($saved);
|
|
||||||
$query->setViewer($viewer);
|
|
||||||
$tasks = $query->execute();
|
|
||||||
|
|
||||||
$all_projects = array_mergev(mpull($tasks, 'getProjectPHIDs'));
|
|
||||||
$all_assigned = mpull($tasks, 'getOwnerPHID');
|
|
||||||
|
|
||||||
$handles = id(new PhabricatorHandleQuery())
|
|
||||||
->setViewer($viewer)
|
|
||||||
->withPHIDs(array_merge($all_projects, $all_assigned))
|
|
||||||
->execute();
|
|
||||||
|
|
||||||
$workbook = new PHPExcel();
|
|
||||||
$format->buildWorkbook($workbook, $tasks, $handles, $viewer);
|
|
||||||
$writer = PHPExcel_IOFactory::createWriter($workbook, 'Excel2007');
|
|
||||||
|
|
||||||
ob_start();
|
|
||||||
$writer->save('php://output');
|
|
||||||
$data = ob_get_clean();
|
|
||||||
|
|
||||||
$mime = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|
||||||
|
|
||||||
return id(new AphrontFileResponse())
|
|
||||||
->setMimeType($mime)
|
|
||||||
->setDownload($format->getFileName().'.xlsx')
|
|
||||||
->setContent($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -196,6 +196,7 @@ EODOCS
|
|||||||
pht('New task owner, or `null` to unassign.'))
|
pht('New task owner, or `null` to unassign.'))
|
||||||
->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE)
|
->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE)
|
||||||
->setIsCopyable(true)
|
->setIsCopyable(true)
|
||||||
|
->setIsNullable(true)
|
||||||
->setSingleValue($object->getOwnerPHID())
|
->setSingleValue($object->getOwnerPHID())
|
||||||
->setCommentActionLabel(pht('Assign / Claim'))
|
->setCommentActionLabel(pht('Assign / Claim'))
|
||||||
->setCommentActionValue($owner_value)
|
->setCommentActionValue($owner_value)
|
||||||
|
|||||||
@@ -206,8 +206,7 @@ final class ManiphestTransactionEditor
|
|||||||
$title = $object->getTitle();
|
$title = $object->getTitle();
|
||||||
|
|
||||||
return id(new PhabricatorMetaMTAMail())
|
return id(new PhabricatorMetaMTAMail())
|
||||||
->setSubject("T{$id}: {$title}")
|
->setSubject("T{$id}: {$title}");
|
||||||
->addHeader('Thread-Topic', "T{$id}: ".$object->getOriginalTitle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildMailBody(
|
protected function buildMailBody(
|
||||||
@@ -534,7 +533,6 @@ final class ManiphestTransactionEditor
|
|||||||
'status' => '""',
|
'status' => '""',
|
||||||
'priority' => 0,
|
'priority' => 0,
|
||||||
'title' => '""',
|
'title' => '""',
|
||||||
'originalTitle' => '""',
|
|
||||||
'description' => '""',
|
'description' => '""',
|
||||||
'dateCreated' => 0,
|
'dateCreated' => 0,
|
||||||
'dateModified' => 0,
|
'dateModified' => 0,
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestMailEngineExtension
|
||||||
|
extends PhabricatorMailEngineExtension {
|
||||||
|
|
||||||
|
const EXTENSIONKEY = 'maniphest';
|
||||||
|
|
||||||
|
public function supportsObject($object) {
|
||||||
|
return ($object instanceof ManiphestTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newMailStampTemplates($object) {
|
||||||
|
return array(
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('author')
|
||||||
|
->setLabel(pht('Author')),
|
||||||
|
id(new PhabricatorPHIDMailStamp())
|
||||||
|
->setKey('task-owner')
|
||||||
|
->setLabel(pht('Task Owner')),
|
||||||
|
id(new PhabricatorBoolMailStamp())
|
||||||
|
->setKey('task-unassigned')
|
||||||
|
->setLabel(pht('Task Unassigned')),
|
||||||
|
id(new PhabricatorStringMailStamp())
|
||||||
|
->setKey('task-priority')
|
||||||
|
->setLabel(pht('Task Priority')),
|
||||||
|
id(new PhabricatorStringMailStamp())
|
||||||
|
->setKey('task-status')
|
||||||
|
->setLabel(pht('Task Status')),
|
||||||
|
id(new PhabricatorStringMailStamp())
|
||||||
|
->setKey('subtype')
|
||||||
|
->setLabel(pht('Subtype')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newMailStamps($object, array $xactions) {
|
||||||
|
$editor = $this->getEditor();
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$this->getMailStamp('author')
|
||||||
|
->setValue($object->getAuthorPHID());
|
||||||
|
|
||||||
|
$this->getMailStamp('task-owner')
|
||||||
|
->setValue($object->getOwnerPHID());
|
||||||
|
|
||||||
|
$this->getMailStamp('task-unassigned')
|
||||||
|
->setValue(!$object->getOwnerPHID());
|
||||||
|
|
||||||
|
$this->getMailStamp('task-priority')
|
||||||
|
->setValue($object->getPriority());
|
||||||
|
|
||||||
|
$this->getMailStamp('task-status')
|
||||||
|
->setValue($object->getStatus());
|
||||||
|
|
||||||
|
$this->getMailStamp('subtype')
|
||||||
|
->setValue($object->getSubtype());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestExcelDefaultFormat extends ManiphestExcelFormat {
|
|
||||||
|
|
||||||
public function getName() {
|
|
||||||
return pht('Default');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFileName() {
|
|
||||||
return 'maniphest_tasks_'.date('Ymd');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @phutil-external-symbol class PHPExcel
|
|
||||||
* @phutil-external-symbol class PHPExcel_IOFactory
|
|
||||||
* @phutil-external-symbol class PHPExcel_Style_NumberFormat
|
|
||||||
* @phutil-external-symbol class PHPExcel_Cell_DataType
|
|
||||||
*/
|
|
||||||
public function buildWorkbook(
|
|
||||||
PHPExcel $workbook,
|
|
||||||
array $tasks,
|
|
||||||
array $handles,
|
|
||||||
PhabricatorUser $user) {
|
|
||||||
|
|
||||||
$sheet = $workbook->setActiveSheetIndex(0);
|
|
||||||
$sheet->setTitle(pht('Tasks'));
|
|
||||||
|
|
||||||
$widths = array(
|
|
||||||
null,
|
|
||||||
15,
|
|
||||||
null,
|
|
||||||
10,
|
|
||||||
15,
|
|
||||||
15,
|
|
||||||
60,
|
|
||||||
30,
|
|
||||||
20,
|
|
||||||
100,
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($widths as $col => $width) {
|
|
||||||
if ($width !== null) {
|
|
||||||
$sheet->getColumnDimension($this->col($col))->setWidth($width);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$status_map = ManiphestTaskStatus::getTaskStatusMap();
|
|
||||||
$pri_map = ManiphestTaskPriority::getTaskPriorityMap();
|
|
||||||
|
|
||||||
$date_format = null;
|
|
||||||
|
|
||||||
$rows = array();
|
|
||||||
$rows[] = array(
|
|
||||||
pht('ID'),
|
|
||||||
pht('Owner'),
|
|
||||||
pht('Status'),
|
|
||||||
pht('Priority'),
|
|
||||||
pht('Date Created'),
|
|
||||||
pht('Date Updated'),
|
|
||||||
pht('Title'),
|
|
||||||
pht('Tags'),
|
|
||||||
pht('URI'),
|
|
||||||
pht('Description'),
|
|
||||||
);
|
|
||||||
|
|
||||||
$is_date = array(
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
$header_format = array(
|
|
||||||
'font' => array(
|
|
||||||
'bold' => true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($tasks as $task) {
|
|
||||||
$task_owner = null;
|
|
||||||
if ($task->getOwnerPHID()) {
|
|
||||||
$task_owner = $handles[$task->getOwnerPHID()]->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
$projects = array();
|
|
||||||
foreach ($task->getProjectPHIDs() as $phid) {
|
|
||||||
$projects[] = $handles[$phid]->getName();
|
|
||||||
}
|
|
||||||
$projects = implode(', ', $projects);
|
|
||||||
|
|
||||||
$rows[] = array(
|
|
||||||
'T'.$task->getID(),
|
|
||||||
$task_owner,
|
|
||||||
idx($status_map, $task->getStatus(), '?'),
|
|
||||||
idx($pri_map, $task->getPriority(), '?'),
|
|
||||||
$this->computeExcelDate($task->getDateCreated()),
|
|
||||||
$this->computeExcelDate($task->getDateModified()),
|
|
||||||
$task->getTitle(),
|
|
||||||
$projects,
|
|
||||||
PhabricatorEnv::getProductionURI('/T'.$task->getID()),
|
|
||||||
id(new PhutilUTF8StringTruncator())
|
|
||||||
->setMaximumBytes(512)
|
|
||||||
->truncateString($task->getDescription()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($rows as $row => $cols) {
|
|
||||||
foreach ($cols as $col => $spec) {
|
|
||||||
$cell_name = $this->col($col).($row + 1);
|
|
||||||
$cell = $sheet
|
|
||||||
->setCellValue($cell_name, $spec, $return_cell = true);
|
|
||||||
|
|
||||||
if ($row == 0) {
|
|
||||||
$sheet->getStyle($cell_name)->applyFromArray($header_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($is_date[$col]) {
|
|
||||||
$code = PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2;
|
|
||||||
$sheet
|
|
||||||
->getStyle($cell_name)
|
|
||||||
->getNumberFormat()
|
|
||||||
->setFormatCode($code);
|
|
||||||
} else {
|
|
||||||
$cell->setDataType(PHPExcel_Cell_DataType::TYPE_STRING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function col($n) {
|
|
||||||
return chr(ord('A') + $n);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
abstract class ManiphestExcelFormat extends Phobject {
|
|
||||||
|
|
||||||
final public static function loadAllFormats() {
|
|
||||||
return id(new PhutilClassMapQuery())
|
|
||||||
->setAncestorClass(__CLASS__)
|
|
||||||
->setSortMethod('getOrder')
|
|
||||||
->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract public function getName();
|
|
||||||
abstract public function getFileName();
|
|
||||||
|
|
||||||
public function getOrder() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function computeExcelDate($epoch) {
|
|
||||||
$seconds_per_day = (60 * 60 * 24);
|
|
||||||
$offset = ($seconds_per_day * 25569);
|
|
||||||
|
|
||||||
return ($epoch + $offset) / $seconds_per_day;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @phutil-external-symbol class PHPExcel
|
|
||||||
*/
|
|
||||||
abstract public function buildWorkbook(
|
|
||||||
PHPExcel $workbook,
|
|
||||||
array $tasks,
|
|
||||||
array $handles,
|
|
||||||
PhabricatorUser $user);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestExcelFormatTestCase extends PhabricatorTestCase {
|
|
||||||
|
|
||||||
public function testLoadAllFormats() {
|
|
||||||
ManiphestExcelFormat::loadAllFormats();
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -23,6 +23,9 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
private $parentTaskIDs;
|
private $parentTaskIDs;
|
||||||
private $subtaskIDs;
|
private $subtaskIDs;
|
||||||
private $subtypes;
|
private $subtypes;
|
||||||
|
private $closedEpochMin;
|
||||||
|
private $closedEpochMax;
|
||||||
|
private $closerPHIDs;
|
||||||
|
|
||||||
private $status = 'status-any';
|
private $status = 'status-any';
|
||||||
const STATUS_ANY = 'status-any';
|
const STATUS_ANY = 'status-any';
|
||||||
@@ -179,6 +182,17 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withClosedEpochBetween($min, $max) {
|
||||||
|
$this->closedEpochMin = $min;
|
||||||
|
$this->closedEpochMax = $max;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withCloserPHIDs(array $phids) {
|
||||||
|
$this->closerPHIDs = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function needSubscriberPHIDs($bool) {
|
public function needSubscriberPHIDs($bool) {
|
||||||
$this->needSubscriberPHIDs = $bool;
|
$this->needSubscriberPHIDs = $bool;
|
||||||
return $this;
|
return $this;
|
||||||
@@ -411,6 +425,27 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
$this->dateModifiedBefore);
|
$this->dateModifiedBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->closedEpochMin !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'task.closedEpoch >= %d',
|
||||||
|
$this->closedEpochMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->closedEpochMax !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'task.closedEpoch <= %d',
|
||||||
|
$this->closedEpochMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->closerPHIDs !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'task.closerPHID IN (%Ls)',
|
||||||
|
$this->closerPHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->priorities !== null) {
|
if ($this->priorities !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
@@ -755,6 +790,10 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
'vector' => array('-updated', '-id'),
|
'vector' => array('-updated', '-id'),
|
||||||
'name' => pht('Date Updated (Oldest First)'),
|
'name' => pht('Date Updated (Oldest First)'),
|
||||||
),
|
),
|
||||||
|
'closed' => array(
|
||||||
|
'vector' => array('closed', 'id'),
|
||||||
|
'name' => pht('Date Closed (Latest First)'),
|
||||||
|
),
|
||||||
'title' => array(
|
'title' => array(
|
||||||
'vector' => array('title', 'id'),
|
'vector' => array('title', 'id'),
|
||||||
'name' => pht('Title'),
|
'name' => pht('Title'),
|
||||||
@@ -773,6 +812,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
'outdated',
|
'outdated',
|
||||||
'newest',
|
'newest',
|
||||||
'oldest',
|
'oldest',
|
||||||
|
'closed',
|
||||||
'title',
|
'title',
|
||||||
)) + $orders;
|
)) + $orders;
|
||||||
|
|
||||||
@@ -822,6 +862,12 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
'column' => 'dateModified',
|
'column' => 'dateModified',
|
||||||
'type' => 'int',
|
'type' => 'int',
|
||||||
),
|
),
|
||||||
|
'closed' => array(
|
||||||
|
'table' => 'task',
|
||||||
|
'column' => 'closedEpoch',
|
||||||
|
'type' => 'int',
|
||||||
|
'null' => 'tail',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,6 +886,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||||||
'status' => $task->getStatus(),
|
'status' => $task->getStatus(),
|
||||||
'title' => $task->getTitle(),
|
'title' => $task->getTitle(),
|
||||||
'updated' => $task->getDateModified(),
|
'updated' => $task->getDateModified(),
|
||||||
|
'closed' => $task->getClosedEpoch(),
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($keys as $key) {
|
foreach ($keys as $key) {
|
||||||
|
|||||||
@@ -128,6 +128,17 @@ final class ManiphestTaskSearchEngine
|
|||||||
id(new PhabricatorSearchDateField())
|
id(new PhabricatorSearchDateField())
|
||||||
->setLabel(pht('Updated Before'))
|
->setLabel(pht('Updated Before'))
|
||||||
->setKey('modifiedEnd'),
|
->setKey('modifiedEnd'),
|
||||||
|
id(new PhabricatorSearchDateField())
|
||||||
|
->setLabel(pht('Closed After'))
|
||||||
|
->setKey('closedStart'),
|
||||||
|
id(new PhabricatorSearchDateField())
|
||||||
|
->setLabel(pht('Closed Before'))
|
||||||
|
->setKey('closedEnd'),
|
||||||
|
id(new PhabricatorUsersSearchField())
|
||||||
|
->setLabel(pht('Closed By'))
|
||||||
|
->setKey('closerPHIDs')
|
||||||
|
->setAliases(array('closer', 'closerPHID', 'closers'))
|
||||||
|
->setDescription(pht('Search for tasks closed by certain users.')),
|
||||||
id(new PhabricatorSearchTextField())
|
id(new PhabricatorSearchTextField())
|
||||||
->setLabel(pht('Page Size'))
|
->setLabel(pht('Page Size'))
|
||||||
->setKey('limit'),
|
->setKey('limit'),
|
||||||
@@ -155,6 +166,9 @@ final class ManiphestTaskSearchEngine
|
|||||||
'createdEnd',
|
'createdEnd',
|
||||||
'modifiedStart',
|
'modifiedStart',
|
||||||
'modifiedEnd',
|
'modifiedEnd',
|
||||||
|
'closedStart',
|
||||||
|
'closedEnd',
|
||||||
|
'closerPHIDs',
|
||||||
'limit',
|
'limit',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -210,6 +224,14 @@ final class ManiphestTaskSearchEngine
|
|||||||
$query->withDateModifiedBefore($map['modifiedEnd']);
|
$query->withDateModifiedBefore($map['modifiedEnd']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($map['closedStart'] || $map['closedEnd']) {
|
||||||
|
$query->withClosedEpochBetween($map['closedStart'], $map['closedEnd']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($map['closerPHIDs']) {
|
||||||
|
$query->withCloserPHIDs($map['closerPHIDs']);
|
||||||
|
}
|
||||||
|
|
||||||
if ($map['hasParents'] !== null) {
|
if ($map['hasParents'] !== null) {
|
||||||
$query->withOpenParents($map['hasParents']);
|
$query->withOpenParents($map['hasParents']);
|
||||||
}
|
}
|
||||||
@@ -485,4 +507,131 @@ final class ManiphestTaskSearchEngine
|
|||||||
return $view;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function newExportFields() {
|
||||||
|
$fields = array(
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('monogram')
|
||||||
|
->setLabel(pht('Monogram')),
|
||||||
|
id(new PhabricatorPHIDExportField())
|
||||||
|
->setKey('authorPHID')
|
||||||
|
->setLabel(pht('Author PHID')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('author')
|
||||||
|
->setLabel(pht('Author')),
|
||||||
|
id(new PhabricatorPHIDExportField())
|
||||||
|
->setKey('ownerPHID')
|
||||||
|
->setLabel(pht('Owner PHID')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('owner')
|
||||||
|
->setLabel(pht('Owner')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('status')
|
||||||
|
->setLabel(pht('Status')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('statusName')
|
||||||
|
->setLabel(pht('Status Name')),
|
||||||
|
id(new PhabricatorEpochExportField())
|
||||||
|
->setKey('dateClosed')
|
||||||
|
->setLabel(pht('Date Closed')),
|
||||||
|
id(new PhabricatorPHIDExportField())
|
||||||
|
->setKey('closerPHID')
|
||||||
|
->setLabel(pht('Closer PHID')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('closer')
|
||||||
|
->setLabel(pht('Closer')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('priority')
|
||||||
|
->setLabel(pht('Priority')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('priorityName')
|
||||||
|
->setLabel(pht('Priority Name')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('subtype')
|
||||||
|
->setLabel('Subtype'),
|
||||||
|
id(new PhabricatorURIExportField())
|
||||||
|
->setKey('uri')
|
||||||
|
->setLabel(pht('URI')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('title')
|
||||||
|
->setLabel(pht('Title')),
|
||||||
|
id(new PhabricatorStringExportField())
|
||||||
|
->setKey('description')
|
||||||
|
->setLabel(pht('Description')),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ManiphestTaskPoints::getIsEnabled()) {
|
||||||
|
$fields[] = id(new PhabricatorIntExportField())
|
||||||
|
->setKey('points')
|
||||||
|
->setLabel('Points');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newExportData(array $tasks) {
|
||||||
|
$viewer = $this->requireViewer();
|
||||||
|
|
||||||
|
$phids = array();
|
||||||
|
foreach ($tasks as $task) {
|
||||||
|
$phids[] = $task->getAuthorPHID();
|
||||||
|
$phids[] = $task->getOwnerPHID();
|
||||||
|
$phids[] = $task->getCloserPHID();
|
||||||
|
}
|
||||||
|
$handles = $viewer->loadHandles($phids);
|
||||||
|
|
||||||
|
$export = array();
|
||||||
|
foreach ($tasks as $task) {
|
||||||
|
|
||||||
|
$author_phid = $task->getAuthorPHID();
|
||||||
|
if ($author_phid) {
|
||||||
|
$author_name = $handles[$author_phid]->getName();
|
||||||
|
} else {
|
||||||
|
$author_name = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$owner_phid = $task->getOwnerPHID();
|
||||||
|
if ($owner_phid) {
|
||||||
|
$owner_name = $handles[$owner_phid]->getName();
|
||||||
|
} else {
|
||||||
|
$owner_name = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$closer_phid = $task->getCloserPHID();
|
||||||
|
if ($closer_phid) {
|
||||||
|
$closer_name = $handles[$closer_phid]->getName();
|
||||||
|
} else {
|
||||||
|
$closer_name = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status_value = $task->getStatus();
|
||||||
|
$status_name = ManiphestTaskStatus::getTaskStatusName($status_value);
|
||||||
|
|
||||||
|
$priority_value = $task->getPriority();
|
||||||
|
$priority_name = ManiphestTaskPriority::getTaskPriorityName(
|
||||||
|
$priority_value);
|
||||||
|
|
||||||
|
$export[] = array(
|
||||||
|
'monogram' => $task->getMonogram(),
|
||||||
|
'authorPHID' => $author_phid,
|
||||||
|
'author' => $author_name,
|
||||||
|
'ownerPHID' => $owner_phid,
|
||||||
|
'owner' => $owner_name,
|
||||||
|
'status' => $status_value,
|
||||||
|
'statusName' => $status_name,
|
||||||
|
'priority' => $priority_value,
|
||||||
|
'priorityName' => $priority_name,
|
||||||
|
'points' => $task->getPoints(),
|
||||||
|
'subtype' => $task->getSubtype(),
|
||||||
|
'title' => $task->getTitle(),
|
||||||
|
'uri' => PhabricatorEnv::getProductionURI($task->getURI()),
|
||||||
|
'description' => $task->getDescription(),
|
||||||
|
'dateClosed' => $task->getClosedEpoch(),
|
||||||
|
'closerPHID' => $closer_phid,
|
||||||
|
'closer' => $closer_name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $export;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
protected $subpriority = 0;
|
protected $subpriority = 0;
|
||||||
|
|
||||||
protected $title = '';
|
protected $title = '';
|
||||||
protected $originalTitle = '';
|
|
||||||
protected $description = '';
|
protected $description = '';
|
||||||
protected $originalEmailSource;
|
protected $originalEmailSource;
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
@@ -45,6 +44,9 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
protected $points;
|
protected $points;
|
||||||
protected $subtype;
|
protected $subtype;
|
||||||
|
|
||||||
|
protected $closedEpoch;
|
||||||
|
protected $closerPHID;
|
||||||
|
|
||||||
private $subscriberPHIDs = self::ATTACHABLE;
|
private $subscriberPHIDs = self::ATTACHABLE;
|
||||||
private $groupByProjectPHID = self::ATTACHABLE;
|
private $groupByProjectPHID = self::ATTACHABLE;
|
||||||
private $customFields = self::ATTACHABLE;
|
private $customFields = self::ATTACHABLE;
|
||||||
@@ -83,7 +85,6 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
'status' => 'text64',
|
'status' => 'text64',
|
||||||
'priority' => 'uint32',
|
'priority' => 'uint32',
|
||||||
'title' => 'sort',
|
'title' => 'sort',
|
||||||
'originalTitle' => 'text',
|
|
||||||
'description' => 'text',
|
'description' => 'text',
|
||||||
'mailKey' => 'bytes20',
|
'mailKey' => 'bytes20',
|
||||||
'ownerOrdering' => 'text64?',
|
'ownerOrdering' => 'text64?',
|
||||||
@@ -92,6 +93,8 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
'points' => 'double?',
|
'points' => 'double?',
|
||||||
'bridgedObjectPHID' => 'phid?',
|
'bridgedObjectPHID' => 'phid?',
|
||||||
'subtype' => 'text64',
|
'subtype' => 'text64',
|
||||||
|
'closedEpoch' => 'epoch?',
|
||||||
|
'closerPHID' => 'phid?',
|
||||||
),
|
),
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
'key_phid' => null,
|
'key_phid' => null,
|
||||||
@@ -133,6 +136,12 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
'key_subtype' => array(
|
'key_subtype' => array(
|
||||||
'columns' => array('subtype'),
|
'columns' => array('subtype'),
|
||||||
),
|
),
|
||||||
|
'key_closed' => array(
|
||||||
|
'columns' => array('closedEpoch'),
|
||||||
|
),
|
||||||
|
'key_closer' => array(
|
||||||
|
'columns' => array('closerPHID', 'closedEpoch'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
@@ -176,14 +185,6 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTitle($title) {
|
|
||||||
$this->title = $title;
|
|
||||||
if (!$this->getID()) {
|
|
||||||
$this->originalTitle = $title;
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMonogram() {
|
public function getMonogram() {
|
||||||
return 'T'.$this->getID();
|
return 'T'.$this->getID();
|
||||||
}
|
}
|
||||||
@@ -512,6 +513,16 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
->setKey('subtype')
|
->setKey('subtype')
|
||||||
->setType('string')
|
->setType('string')
|
||||||
->setDescription(pht('Subtype of the task.')),
|
->setDescription(pht('Subtype of the task.')),
|
||||||
|
id(new PhabricatorConduitSearchFieldSpecification())
|
||||||
|
->setKey('closerPHID')
|
||||||
|
->setType('phid?')
|
||||||
|
->setDescription(
|
||||||
|
pht('User who closed the task, if the task is closed.')),
|
||||||
|
id(new PhabricatorConduitSearchFieldSpecification())
|
||||||
|
->setKey('dateClosed')
|
||||||
|
->setType('int?')
|
||||||
|
->setDescription(
|
||||||
|
pht('Epoch timestamp when the task was closed.')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,6 +542,11 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
'color' => ManiphestTaskPriority::getTaskPriorityColor($priority_value),
|
'color' => ManiphestTaskPriority::getTaskPriorityColor($priority_value),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$closed_epoch = $this->getClosedEpoch();
|
||||||
|
if ($closed_epoch !== null) {
|
||||||
|
$closed_epoch = (int)$closed_epoch;
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'name' => $this->getTitle(),
|
'name' => $this->getTitle(),
|
||||||
'description' => array(
|
'description' => array(
|
||||||
@@ -542,6 +558,8 @@ final class ManiphestTask extends ManiphestDAO
|
|||||||
'priority' => $priority_info,
|
'priority' => $priority_info,
|
||||||
'points' => $this->getPoints(),
|
'points' => $this->getPoints(),
|
||||||
'subtype' => $this->getSubtype(),
|
'subtype' => $this->getSubtype(),
|
||||||
|
'closerPHID' => $this->getCloserPHID(),
|
||||||
|
'dateClosed' => $closed_epoch,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ final class ManiphestTaskListView extends ManiphestView {
|
|||||||
->setHeader($task->getTitle())
|
->setHeader($task->getTitle())
|
||||||
->setHref('/T'.$task->getID());
|
->setHref('/T'.$task->getID());
|
||||||
|
|
||||||
|
if ($task->getAuthorPHID()) {
|
||||||
|
$author = $handles[$task->getAuthorPHID()];
|
||||||
|
$item->addByline(pht('By: %s', $author->renderLink()));
|
||||||
|
}
|
||||||
|
|
||||||
if ($task->getOwnerPHID()) {
|
if ($task->getOwnerPHID()) {
|
||||||
$owner = $handles[$task->getOwnerPHID()];
|
$owner = $handles[$task->getOwnerPHID()];
|
||||||
$item->addByline(pht('Assigned: %s', $owner->renderLink()));
|
$item->addByline(pht('Assigned: %s', $owner->renderLink()));
|
||||||
@@ -87,19 +92,24 @@ final class ManiphestTaskListView extends ManiphestView {
|
|||||||
|
|
||||||
$item->setStatusIcon($icon.' '.$color, $tooltip);
|
$item->setStatusIcon($icon.' '.$color, $tooltip);
|
||||||
|
|
||||||
$date = phabricator_datetime($task->getDateModified(), $this->getUser());
|
if ($task->isClosed()) {
|
||||||
|
$closed_epoch = $task->getClosedEpoch();
|
||||||
|
|
||||||
if ($task->getAuthorPHID()) {
|
// We don't expect a task to be closed without a closed epoch, but
|
||||||
$author = idx($handles, $task->getAuthorPHID());
|
// recover if we find one. This can happen with older objects or with
|
||||||
// TODO: This should be guaranteed, see T3817.
|
// lipsum test data.
|
||||||
if ($author) {
|
if (!$closed_epoch) {
|
||||||
$date = array($date, " by ", $author->renderLink());
|
$closed_epoch = $task->getDateModified();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$item->addIcon(
|
||||||
|
'fa-check-square-o grey',
|
||||||
|
phabricator_datetime($closed_epoch, $this->getUser()));
|
||||||
|
} else {
|
||||||
$item->addIcon(
|
$item->addIcon(
|
||||||
'none',
|
'none',
|
||||||
$date);
|
phabricator_datetime($task->getDateModified(), $this->getUser()));
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->showSubpriorityControls) {
|
if ($this->showSubpriorityControls) {
|
||||||
$item->setGrippable(true);
|
$item->setGrippable(true);
|
||||||
|
|||||||
@@ -175,8 +175,7 @@ final class ManiphestTaskResultListView extends ManiphestView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$user->isLoggedIn()) {
|
if (!$user->isLoggedIn()) {
|
||||||
// Don't show the batch editor or excel export for logged-out users.
|
// Don't show the batch editor for logged-out users.
|
||||||
// Technically we //could// let them export, but ehh.
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,14 +219,6 @@ final class ManiphestTaskResultListView extends ManiphestView {
|
|||||||
),
|
),
|
||||||
pht("Bulk Edit Selected \xC2\xBB"));
|
pht("Bulk Edit Selected \xC2\xBB"));
|
||||||
|
|
||||||
$export = javelin_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => '/maniphest/export/'.$saved_query->getQueryKey().'/',
|
|
||||||
'class' => 'button button-grey',
|
|
||||||
),
|
|
||||||
pht('Export to Excel'));
|
|
||||||
|
|
||||||
$hidden = phutil_tag(
|
$hidden = phutil_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
@@ -239,14 +230,12 @@ final class ManiphestTaskResultListView extends ManiphestView {
|
|||||||
'<table class="maniphest-batch-editor-layout">'.
|
'<table class="maniphest-batch-editor-layout">'.
|
||||||
'<tr>'.
|
'<tr>'.
|
||||||
'<td>%s%s</td>'.
|
'<td>%s%s</td>'.
|
||||||
'<td>%s</td>'.
|
|
||||||
'<td id="batch-select-status-cell">%s</td>'.
|
'<td id="batch-select-status-cell">%s</td>'.
|
||||||
'<td class="batch-select-submit-cell">%s%s</td>'.
|
'<td class="batch-select-submit-cell">%s%s</td>'.
|
||||||
'</tr>'.
|
'</tr>'.
|
||||||
'</table>',
|
'</table>',
|
||||||
$select_all,
|
$select_all,
|
||||||
$select_none,
|
$select_none,
|
||||||
$export,
|
|
||||||
'',
|
'',
|
||||||
$submit,
|
$submit,
|
||||||
$hidden);
|
$hidden);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ final class ManiphestTaskMergedIntoTransaction
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function applyInternalEffects($object, $value) {
|
public function applyInternalEffects($object, $value) {
|
||||||
$object->setStatus(ManiphestTaskStatus::getDuplicateStatus());
|
$this->updateStatus($object, ManiphestTaskStatus::getDuplicateStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getActionName() {
|
public function getActionName() {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ final class ManiphestTaskStatusTransaction
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function applyInternalEffects($object, $value) {
|
public function applyInternalEffects($object, $value) {
|
||||||
$object->setStatus($value);
|
$this->updateStatus($object, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shouldHide() {
|
public function shouldHide() {
|
||||||
|
|||||||
@@ -3,4 +3,27 @@
|
|||||||
abstract class ManiphestTaskTransactionType
|
abstract class ManiphestTaskTransactionType
|
||||||
extends PhabricatorModularTransactionType {
|
extends PhabricatorModularTransactionType {
|
||||||
|
|
||||||
|
protected function updateStatus($object, $new_value) {
|
||||||
|
$old_value = $object->getStatus();
|
||||||
|
$object->setStatus($new_value);
|
||||||
|
|
||||||
|
// If this status change closes or opens the task, update the closed
|
||||||
|
// date and actor PHID.
|
||||||
|
$old_closed = ManiphestTaskStatus::isClosedStatus($old_value);
|
||||||
|
$new_closed = ManiphestTaskStatus::isClosedStatus($new_value);
|
||||||
|
|
||||||
|
$is_close = ($new_closed && !$old_closed);
|
||||||
|
$is_open = (!$new_closed && $old_closed);
|
||||||
|
|
||||||
|
if ($is_close) {
|
||||||
|
$object
|
||||||
|
->setClosedEpoch(PhabricatorTime::getNow())
|
||||||
|
->setCloserPHID($this->getActingAsPHID());
|
||||||
|
} else if ($is_open) {
|
||||||
|
$object
|
||||||
|
->setClosedEpoch(null)
|
||||||
|
->setCloserPHID(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,22 @@
|
|||||||
|
|
||||||
abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||||
|
|
||||||
|
private $key;
|
||||||
|
private $priority;
|
||||||
|
private $options = array();
|
||||||
|
|
||||||
|
final public function getAdapterType() {
|
||||||
|
return $this->getPhobjectClassConstant('ADAPTERTYPE');
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function getAllAdapters() {
|
||||||
|
return id(new PhutilClassMapQuery())
|
||||||
|
->setAncestorClass(__CLASS__)
|
||||||
|
->setUniqueMethod('getAdapterType')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
abstract public function setFrom($email, $name = '');
|
abstract public function setFrom($email, $name = '');
|
||||||
abstract public function addReplyTo($email, $name = '');
|
abstract public function addReplyTo($email, $name = '');
|
||||||
abstract public function addTos(array $emails);
|
abstract public function addTos(array $emails);
|
||||||
@@ -12,6 +28,7 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
|||||||
abstract public function setHTMLBody($html_body);
|
abstract public function setHTMLBody($html_body);
|
||||||
abstract public function setSubject($subject);
|
abstract public function setSubject($subject);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some mailers, notably Amazon SES, do not support us setting a specific
|
* Some mailers, notably Amazon SES, do not support us setting a specific
|
||||||
* Message-ID header.
|
* Message-ID header.
|
||||||
@@ -32,4 +49,59 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
|||||||
*/
|
*/
|
||||||
abstract public function send();
|
abstract public function send();
|
||||||
|
|
||||||
|
final public function setKey($key) {
|
||||||
|
$this->key = $key;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getKey() {
|
||||||
|
return $this->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setPriority($priority) {
|
||||||
|
$this->priority = $priority;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getPriority() {
|
||||||
|
return $this->priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getOption($key) {
|
||||||
|
if (!array_key_exists($key, $this->options)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Mailer ("%s") is attempting to access unknown option ("%s").',
|
||||||
|
get_class($this),
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->options[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setOptions(array $options) {
|
||||||
|
$this->validateOptions($options);
|
||||||
|
$this->options = $options;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function validateOptions(array $options);
|
||||||
|
|
||||||
|
abstract public function newDefaultOptions();
|
||||||
|
abstract public function newLegacyOptions();
|
||||||
|
|
||||||
|
public function prepareForSend() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderAddress($email, $name = null) {
|
||||||
|
if (strlen($name)) {
|
||||||
|
return (string)id(new PhutilEmailAddress())
|
||||||
|
->setDisplayName($name)
|
||||||
|
->setAddress($email);
|
||||||
|
} else {
|
||||||
|
return $email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,13 @@
|
|||||||
final class PhabricatorMailImplementationAmazonSESAdapter
|
final class PhabricatorMailImplementationAmazonSESAdapter
|
||||||
extends PhabricatorMailImplementationPHPMailerLiteAdapter {
|
extends PhabricatorMailImplementationPHPMailerLiteAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'ses';
|
||||||
|
|
||||||
private $message;
|
private $message;
|
||||||
private $isHTML;
|
private $isHTML;
|
||||||
|
|
||||||
public function __construct() {
|
public function prepareForSend() {
|
||||||
parent::__construct();
|
parent::prepareForSend();
|
||||||
$this->mailer->Mailer = 'amazon-ses';
|
$this->mailer->Mailer = 'amazon-ses';
|
||||||
$this->mailer->customMailer = $this;
|
$this->mailer->customMailer = $this;
|
||||||
}
|
}
|
||||||
@@ -17,13 +19,39 @@ final class PhabricatorMailImplementationAmazonSESAdapter
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'access-key' => 'string',
|
||||||
|
'secret-key' => 'string',
|
||||||
|
'endpoint' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'access-key' => null,
|
||||||
|
'secret-key' => null,
|
||||||
|
'endpoint' => null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array(
|
||||||
|
'access-key' => PhabricatorEnv::getEnvConfig('amazon-ses.access-key'),
|
||||||
|
'secret-key' => PhabricatorEnv::getEnvConfig('amazon-ses.secret-key'),
|
||||||
|
'endpoint' => PhabricatorEnv::getEnvConfig('amazon-ses.endpoint'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phutil-external-symbol class SimpleEmailService
|
* @phutil-external-symbol class SimpleEmailService
|
||||||
*/
|
*/
|
||||||
public function executeSend($body) {
|
public function executeSend($body) {
|
||||||
$key = PhabricatorEnv::getEnvConfig('amazon-ses.access-key');
|
$key = $this->getOption('access-key');
|
||||||
$secret = PhabricatorEnv::getEnvConfig('amazon-ses.secret-key');
|
$secret = $this->getOption('secret-key');
|
||||||
$endpoint = PhabricatorEnv::getEnvConfig('amazon-ses.endpoint');
|
$endpoint = $this->getOption('endpoint');
|
||||||
|
|
||||||
$root = phutil_get_library_root('phabricator');
|
$root = phutil_get_library_root('phabricator');
|
||||||
$root = dirname($root);
|
$root = dirname($root);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
final class PhabricatorMailImplementationMailgunAdapter
|
final class PhabricatorMailImplementationMailgunAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailImplementationAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'mailgun';
|
||||||
|
|
||||||
private $params = array();
|
private $params = array();
|
||||||
private $attachments = array();
|
private $attachments = array();
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ final class PhabricatorMailImplementationMailgunAdapter
|
|||||||
if (empty($this->params['reply-to'])) {
|
if (empty($this->params['reply-to'])) {
|
||||||
$this->params['reply-to'] = array();
|
$this->params['reply-to'] = array();
|
||||||
}
|
}
|
||||||
$this->params['reply-to'][] = "{$name} <{$email}>";
|
$this->params['reply-to'][] = $this->renderAddress($email, $name);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +73,32 @@ final class PhabricatorMailImplementationMailgunAdapter
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'api-key' => 'string',
|
||||||
|
'domain' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'api-key' => null,
|
||||||
|
'domain' => null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array(
|
||||||
|
'api-key' => PhabricatorEnv::getEnvConfig('mailgun.api-key'),
|
||||||
|
'domain' => PhabricatorEnv::getEnvConfig('mailgun.domain'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function send() {
|
public function send() {
|
||||||
$key = PhabricatorEnv::getEnvConfig('mailgun.api-key');
|
$key = $this->getOption('api-key');
|
||||||
$domain = PhabricatorEnv::getEnvConfig('mailgun.domain');
|
$domain = $this->getOption('domain');
|
||||||
$params = array();
|
$params = array();
|
||||||
|
|
||||||
$params['to'] = implode(', ', idx($this->params, 'tos', array()));
|
$params['to'] = implode(', ', idx($this->params, 'tos', array()));
|
||||||
@@ -85,11 +110,8 @@ final class PhabricatorMailImplementationMailgunAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
$from = idx($this->params, 'from');
|
$from = idx($this->params, 'from');
|
||||||
if (idx($this->params, 'from-name')) {
|
$from_name = idx($this->params, 'from-name');
|
||||||
$params['from'] = "\"{$this->params['from-name']}\" <{$from}>";
|
$params['from'] = $this->renderAddress($from, $from_name);
|
||||||
} else {
|
|
||||||
$params['from'] = $from;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx($this->params, 'reply-to')) {
|
if (idx($this->params, 'reply-to')) {
|
||||||
$replyto = $this->params['reply-to'];
|
$replyto = $this->params['reply-to'];
|
||||||
|
|||||||
@@ -3,40 +3,79 @@
|
|||||||
final class PhabricatorMailImplementationPHPMailerAdapter
|
final class PhabricatorMailImplementationPHPMailerAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailImplementationAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'smtp';
|
||||||
|
|
||||||
private $mailer;
|
private $mailer;
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'host' => 'string|null',
|
||||||
|
'port' => 'int',
|
||||||
|
'user' => 'string|null',
|
||||||
|
'password' => 'string|null',
|
||||||
|
'protocol' => 'string|null',
|
||||||
|
'encoding' => 'string',
|
||||||
|
'mailer' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'host' => null,
|
||||||
|
'port' => 25,
|
||||||
|
'user' => null,
|
||||||
|
'password' => null,
|
||||||
|
'protocol' => null,
|
||||||
|
'encoding' => 'base64',
|
||||||
|
'mailer' => 'smtp',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array(
|
||||||
|
'host' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-host'),
|
||||||
|
'port' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-port'),
|
||||||
|
'user' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-user'),
|
||||||
|
'password' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-passsword'),
|
||||||
|
'protocol' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-protocol'),
|
||||||
|
'encoding' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding'),
|
||||||
|
'mailer' => PhabricatorEnv::getEnvConfig('phpmailer.mailer'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phutil-external-symbol class PHPMailer
|
* @phutil-external-symbol class PHPMailer
|
||||||
*/
|
*/
|
||||||
public function __construct() {
|
public function prepareForSend() {
|
||||||
$root = phutil_get_library_root('phabricator');
|
$root = phutil_get_library_root('phabricator');
|
||||||
$root = dirname($root);
|
$root = dirname($root);
|
||||||
require_once $root.'/externals/phpmailer/class.phpmailer.php';
|
require_once $root.'/externals/phpmailer/class.phpmailer.php';
|
||||||
$this->mailer = new PHPMailer($use_exceptions = true);
|
$this->mailer = new PHPMailer($use_exceptions = true);
|
||||||
$this->mailer->CharSet = 'utf-8';
|
$this->mailer->CharSet = 'utf-8';
|
||||||
|
|
||||||
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding');
|
$encoding = $this->getOption('encoding');
|
||||||
$this->mailer->Encoding = $encoding;
|
$this->mailer->Encoding = $encoding;
|
||||||
|
|
||||||
// By default, PHPMailer sends one mail per recipient. We handle
|
// By default, PHPMailer sends one mail per recipient. We handle
|
||||||
// multiplexing higher in the stack, so tell it to send mail exactly
|
// combining or separating To and Cc higher in the stack, so tell it to
|
||||||
// like we ask.
|
// send mail exactly like we ask.
|
||||||
$this->mailer->SingleTo = false;
|
$this->mailer->SingleTo = false;
|
||||||
|
|
||||||
$mailer = PhabricatorEnv::getEnvConfig('phpmailer.mailer');
|
$mailer = $this->getOption('mailer');
|
||||||
if ($mailer == 'smtp') {
|
if ($mailer == 'smtp') {
|
||||||
$this->mailer->IsSMTP();
|
$this->mailer->IsSMTP();
|
||||||
$this->mailer->Host = PhabricatorEnv::getEnvConfig('phpmailer.smtp-host');
|
$this->mailer->Host = $this->getOption('host');
|
||||||
$this->mailer->Port = PhabricatorEnv::getEnvConfig('phpmailer.smtp-port');
|
$this->mailer->Port = $this->getOption('port');
|
||||||
$user = PhabricatorEnv::getEnvConfig('phpmailer.smtp-user');
|
$user = $this->getOption('user');
|
||||||
if ($user) {
|
if ($user) {
|
||||||
$this->mailer->SMTPAuth = true;
|
$this->mailer->SMTPAuth = true;
|
||||||
$this->mailer->Username = $user;
|
$this->mailer->Username = $user;
|
||||||
$this->mailer->Password =
|
$this->mailer->Password = $this->getOption('password');
|
||||||
PhabricatorEnv::getEnvConfig('phpmailer.smtp-password');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$protocol = PhabricatorEnv::getEnvConfig('phpmailer.smtp-protocol');
|
$protocol = $this->getOption('protocol');
|
||||||
if ($protocol) {
|
if ($protocol) {
|
||||||
$protocol = phutil_utf8_strtolower($protocol);
|
$protocol = phutil_utf8_strtolower($protocol);
|
||||||
$this->mailer->SMTPSecure = $protocol;
|
$this->mailer->SMTPSecure = $protocol;
|
||||||
|
|||||||
@@ -6,24 +6,46 @@
|
|||||||
class PhabricatorMailImplementationPHPMailerLiteAdapter
|
class PhabricatorMailImplementationPHPMailerLiteAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailImplementationAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'sendmail';
|
||||||
|
|
||||||
protected $mailer;
|
protected $mailer;
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'encoding' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'encoding' => 'base64',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array(
|
||||||
|
'encoding' => PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phutil-external-symbol class PHPMailerLite
|
* @phutil-external-symbol class PHPMailerLite
|
||||||
*/
|
*/
|
||||||
public function __construct() {
|
public function prepareForSend() {
|
||||||
$root = phutil_get_library_root('phabricator');
|
$root = phutil_get_library_root('phabricator');
|
||||||
$root = dirname($root);
|
$root = dirname($root);
|
||||||
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
|
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
|
||||||
$this->mailer = new PHPMailerLite($use_exceptions = true);
|
$this->mailer = new PHPMailerLite($use_exceptions = true);
|
||||||
$this->mailer->CharSet = 'utf-8';
|
$this->mailer->CharSet = 'utf-8';
|
||||||
|
|
||||||
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding');
|
$encoding = $this->getOption('encoding');
|
||||||
$this->mailer->Encoding = $encoding;
|
$this->mailer->Encoding = $encoding;
|
||||||
|
|
||||||
// By default, PHPMailerLite sends one mail per recipient. We handle
|
// By default, PHPMailerLite sends one mail per recipient. We handle
|
||||||
// multiplexing higher in the stack, so tell it to send mail exactly
|
// combining or separating To and Cc higher in the stack, so tell it to
|
||||||
// like we ask.
|
// send mail exactly like we ask.
|
||||||
$this->mailer->SingleTo = false;
|
$this->mailer->SingleTo = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMailImplementationPostmarkAdapter
|
||||||
|
extends PhabricatorMailImplementationAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'postmark';
|
||||||
|
|
||||||
|
private $parameters = array();
|
||||||
|
|
||||||
|
public function setFrom($email, $name = '') {
|
||||||
|
$this->parameters['From'] = $this->renderAddress($email, $name);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addReplyTo($email, $name = '') {
|
||||||
|
$this->parameters['ReplyTo'] = $this->renderAddress($email, $name);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addTos(array $emails) {
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
$this->parameters['To'][] = $email;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addCCs(array $emails) {
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
$this->parameters['Cc'][] = $email;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addAttachment($data, $filename, $mimetype) {
|
||||||
|
$this->parameters['Attachments'][] = array(
|
||||||
|
'Name' => $filename,
|
||||||
|
'ContentType' => $mimetype,
|
||||||
|
'Content' => base64_encode($data),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addHeader($header_name, $header_value) {
|
||||||
|
$this->parameters['Headers'][] = array(
|
||||||
|
'Name' => $header_name,
|
||||||
|
'Value' => $header_value,
|
||||||
|
);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBody($body) {
|
||||||
|
$this->parameters['TextBody'] = $body;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHTMLBody($html_body) {
|
||||||
|
$this->parameters['HtmlBody'] = $html_body;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSubject($subject) {
|
||||||
|
$this->parameters['Subject'] = $subject;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsMessageIDHeader() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'access-token' => 'string',
|
||||||
|
'inbound-addresses' => 'list<string>',
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make sure this is properly formatted.
|
||||||
|
PhutilCIDRList::newList($options['inbound-addresses']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'access-token' => null,
|
||||||
|
'inbound-addresses' => array(
|
||||||
|
// Via Postmark support circa February 2018, see:
|
||||||
|
//
|
||||||
|
// https://postmarkapp.com/support/article/800-ips-for-firewalls
|
||||||
|
//
|
||||||
|
// "Configuring Outbound Email" should be updated if this changes.
|
||||||
|
'50.31.156.6/32',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send() {
|
||||||
|
$access_token = $this->getOption('access-token');
|
||||||
|
|
||||||
|
$parameters = $this->parameters;
|
||||||
|
$flatten = array(
|
||||||
|
'To',
|
||||||
|
'Cc',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($flatten as $key) {
|
||||||
|
if (isset($parameters[$key])) {
|
||||||
|
$parameters[$key] = implode(', ', $parameters[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id(new PhutilPostmarkFuture())
|
||||||
|
->setAccessToken($access_token)
|
||||||
|
->setMethod('email', $parameters)
|
||||||
|
->resolve();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,8 +6,33 @@
|
|||||||
final class PhabricatorMailImplementationSendGridAdapter
|
final class PhabricatorMailImplementationSendGridAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailImplementationAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'sendgrid';
|
||||||
|
|
||||||
private $params = array();
|
private $params = array();
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'api-user' => 'string',
|
||||||
|
'api-key' => 'string',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'api-user' => null,
|
||||||
|
'api-key' => null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array(
|
||||||
|
'api-user' => PhabricatorEnv::getEnvConfig('sendgrid.api-user'),
|
||||||
|
'api-key' => PhabricatorEnv::getEnvConfig('sendgrid.api-key'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function setFrom($email, $name = '') {
|
public function setFrom($email, $name = '') {
|
||||||
$this->params['from'] = $email;
|
$this->params['from'] = $email;
|
||||||
$this->params['from-name'] = $name;
|
$this->params['from-name'] = $name;
|
||||||
@@ -73,8 +98,8 @@ final class PhabricatorMailImplementationSendGridAdapter
|
|||||||
|
|
||||||
public function send() {
|
public function send() {
|
||||||
|
|
||||||
$user = PhabricatorEnv::getEnvConfig('sendgrid.api-user');
|
$user = $this->getOption('api-user');
|
||||||
$key = PhabricatorEnv::getEnvConfig('sendgrid.api-key');
|
$key = $this->getOption('api-key');
|
||||||
|
|
||||||
if (!$user || !$key) {
|
if (!$user || !$key) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
|
|||||||
@@ -7,10 +7,26 @@
|
|||||||
final class PhabricatorMailImplementationTestAdapter
|
final class PhabricatorMailImplementationTestAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailImplementationAdapter {
|
||||||
|
|
||||||
private $guts = array();
|
const ADAPTERTYPE = 'test';
|
||||||
private $config;
|
|
||||||
|
|
||||||
public function __construct(array $config = array()) {
|
private $guts = array();
|
||||||
|
private $config = array();
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newLegacyOptions() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareForSend(array $config = array()) {
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ final class PhabricatorMetaMTAApplication extends PhabricatorApplication {
|
|||||||
'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController',
|
'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController',
|
||||||
'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController',
|
'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController',
|
||||||
'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController',
|
'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController',
|
||||||
|
'postmark/' => 'PhabricatorMetaMTAPostmarkReceiveController',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,23 @@ final class PhabricatorMetaMTAMailViewController
|
|||||||
$color = PhabricatorMailOutboundStatus::getStatusColor($status);
|
$color = PhabricatorMailOutboundStatus::getStatusColor($status);
|
||||||
$header->setStatus($icon, $color, $name);
|
$header->setStatus($icon, $color, $name);
|
||||||
|
|
||||||
|
if ($mail->getMustEncrypt()) {
|
||||||
|
Javelin::initBehavior('phabricator-tooltips');
|
||||||
|
$header->addTag(
|
||||||
|
id(new PHUITagView())
|
||||||
|
->setType(PHUITagView::TYPE_SHADE)
|
||||||
|
->setColor('blue')
|
||||||
|
->setName(pht('Must Encrypt'))
|
||||||
|
->setIcon('fa-shield blue')
|
||||||
|
->addSigil('has-tooltip')
|
||||||
|
->setMetadata(
|
||||||
|
array(
|
||||||
|
'tip' => pht(
|
||||||
|
'Message content can only be transmitted over secure '.
|
||||||
|
'channels.'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs()
|
$crumbs = $this->buildApplicationCrumbs()
|
||||||
->addTextCrumb(pht('Mail %d', $mail->getID()))
|
->addTextCrumb(pht('Mail %d', $mail->getID()))
|
||||||
->setBorder(true);
|
->setBorder(true);
|
||||||
@@ -58,8 +75,26 @@ final class PhabricatorMetaMTAMailViewController
|
|||||||
->setKey('metadata')
|
->setKey('metadata')
|
||||||
->appendChild($this->buildMetadataProperties($mail)));
|
->appendChild($this->buildMetadataProperties($mail)));
|
||||||
|
|
||||||
|
$header_view = id(new PHUIHeaderView())
|
||||||
|
->setHeader(pht('Mail'));
|
||||||
|
|
||||||
|
$object_phid = $mail->getRelatedPHID();
|
||||||
|
if ($object_phid) {
|
||||||
|
$handles = $viewer->loadHandles(array($object_phid));
|
||||||
|
$handle = $handles[$object_phid];
|
||||||
|
if ($handle->isComplete() && $handle->getURI()) {
|
||||||
|
$view_button = id(new PHUIButtonView())
|
||||||
|
->setTag('a')
|
||||||
|
->setText(pht('View Object'))
|
||||||
|
->setIcon('fa-chevron-right')
|
||||||
|
->setHref($handle->getURI());
|
||||||
|
|
||||||
|
$header_view->addActionLink($view_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$object_box = id(new PHUIObjectBoxView())
|
$object_box = id(new PHUIObjectBoxView())
|
||||||
->setHeaderText(pht('Mail'))
|
->setHeader($header_view)
|
||||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||||
->addTabGroup($tab_group);
|
->addTabGroup($tab_group);
|
||||||
|
|
||||||
@@ -134,6 +169,12 @@ final class PhabricatorMetaMTAMailViewController
|
|||||||
|
|
||||||
$properties->addTextContent($body);
|
$properties->addTextContent($body);
|
||||||
|
|
||||||
|
$file_phids = $mail->getAttachmentFilePHIDs();
|
||||||
|
if ($file_phids) {
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Attached Files'),
|
||||||
|
$viewer->loadHandles($file_phids)->renderList());
|
||||||
|
}
|
||||||
|
|
||||||
return $properties;
|
return $properties;
|
||||||
}
|
}
|
||||||
@@ -158,6 +199,15 @@ final class PhabricatorMetaMTAMailViewController
|
|||||||
$properties->addProperty($key, $value);
|
$properties->addProperty($key, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$encrypt_phids = $mail->getMustEncryptReasons();
|
||||||
|
if ($encrypt_phids) {
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Must Encrypt'),
|
||||||
|
$viewer->loadHandles($encrypt_phids)
|
||||||
|
->renderList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return $properties;
|
return $properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,28 @@ final class PhabricatorMetaMTAMailgunReceiveController
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function verifyMessage() {
|
private function verifyMessage() {
|
||||||
$api_key = PhabricatorEnv::getEnvConfig('mailgun.api-key');
|
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$timestamp = $request->getStr('timestamp');
|
$timestamp = $request->getStr('timestamp');
|
||||||
$token = $request->getStr('token');
|
$token = $request->getStr('token');
|
||||||
$sig = $request->getStr('signature');
|
$sig = $request->getStr('signature');
|
||||||
$hash = hash_hmac('sha256', $timestamp.$token, $api_key);
|
|
||||||
|
|
||||||
return phutil_hashes_are_identical($sig, $hash);
|
// An install may configure multiple Mailgun mailers, and we might receive
|
||||||
|
// inbound mail from any of them. Test the signature to see if it matches
|
||||||
|
// any configured Mailgun mailer.
|
||||||
|
|
||||||
|
$mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
|
||||||
|
array(
|
||||||
|
PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE,
|
||||||
|
));
|
||||||
|
foreach ($mailers as $mailer) {
|
||||||
|
$api_key = $mailer->getOption('api-key');
|
||||||
|
$hash = hash_hmac('sha256', $timestamp.$token, $api_key);
|
||||||
|
if (phutil_hashes_are_identical($sig, $hash)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMetaMTAPostmarkReceiveController
|
||||||
|
extends PhabricatorMetaMTAController {
|
||||||
|
|
||||||
|
public function shouldRequireLogin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phutil-external-symbol class PhabricatorStartup
|
||||||
|
*/
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
// Don't process requests if we don't have a configured Postmark adapter.
|
||||||
|
$mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
|
||||||
|
array(
|
||||||
|
PhabricatorMailImplementationPostmarkAdapter::ADAPTERTYPE,
|
||||||
|
));
|
||||||
|
if (!$mailers) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote_address = $request->getRemoteAddress();
|
||||||
|
$any_remote_match = false;
|
||||||
|
foreach ($mailers as $mailer) {
|
||||||
|
$inbound_addresses = $mailer->getOption('inbound-addresses');
|
||||||
|
$cidr_list = PhutilCIDRList::newList($inbound_addresses);
|
||||||
|
if ($cidr_list->containsAddress($remote_address)) {
|
||||||
|
$any_remote_match = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$any_remote_match) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
|
$raw_input = PhabricatorStartup::getRawInput();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$data = phutil_json_decode($raw_input);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw_headers = array();
|
||||||
|
$header_items = idx($data, 'Headers', array());
|
||||||
|
foreach ($header_items as $header_item) {
|
||||||
|
$name = idx($header_item, 'Name');
|
||||||
|
$value = idx($header_item, 'Value');
|
||||||
|
$raw_headers[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = array(
|
||||||
|
'to' => idx($data, 'To'),
|
||||||
|
'from' => idx($data, 'From'),
|
||||||
|
'cc' => idx($data, 'Cc'),
|
||||||
|
'subject' => idx($data, 'Subject'),
|
||||||
|
) + $raw_headers;
|
||||||
|
|
||||||
|
|
||||||
|
$received = id(new PhabricatorMetaMTAReceivedMail())
|
||||||
|
->setHeaders($headers)
|
||||||
|
->setBodies(
|
||||||
|
array(
|
||||||
|
'text' => idx($data, 'TextBody'),
|
||||||
|
'html' => idx($data, 'HtmlBody'),
|
||||||
|
));
|
||||||
|
|
||||||
|
$file_phids = array();
|
||||||
|
$attachments = idx($data, 'Attachments', array());
|
||||||
|
foreach ($attachments as $attachment) {
|
||||||
|
$file_data = idx($attachment, 'Content');
|
||||||
|
$file_data = base64_decode($file_data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$file = PhabricatorFile::newFromFileData(
|
||||||
|
$file_data,
|
||||||
|
array(
|
||||||
|
'name' => idx($attachment, 'Name'),
|
||||||
|
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
|
||||||
|
));
|
||||||
|
$file_phids[] = $file->getPHID();
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
phlog($ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$received->setAttachments($file_phids);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$received->save();
|
||||||
|
$received->processReceivedMail();
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
phlog($ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new AphrontWebpageResponse())
|
||||||
|
->setContent(pht("Got it! Thanks, Postmark!\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,16 @@ final class PhabricatorMetaMTASendGridReceiveController
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function handleRequest(AphrontRequest $request) {
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
// SendGrid doesn't sign payloads so we can't be sure that SendGrid
|
||||||
|
// actually sent this request, but require a configured SendGrid mailer
|
||||||
|
// before we activate this endpoint.
|
||||||
|
$mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
|
||||||
|
array(
|
||||||
|
PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE,
|
||||||
|
));
|
||||||
|
if (!$mailers) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
// No CSRF for SendGrid.
|
// No CSRF for SendGrid.
|
||||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorMailEngineExtension
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $viewer;
|
||||||
|
private $editor;
|
||||||
|
|
||||||
|
final public function getExtensionKey() {
|
||||||
|
return $this->getPhobjectClassConstant('EXTENSIONKEY');
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setViewer($viewer) {
|
||||||
|
$this->viewer = $viewer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getViewer() {
|
||||||
|
return $this->viewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setEditor(
|
||||||
|
PhabricatorApplicationTransactionEditor $editor) {
|
||||||
|
$this->editor = $editor;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getEditor() {
|
||||||
|
return $this->editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public function supportsObject($object);
|
||||||
|
abstract public function newMailStampTemplates($object);
|
||||||
|
abstract public function newMailStamps($object, array $xactions);
|
||||||
|
|
||||||
|
final public static function getAllExtensions() {
|
||||||
|
return id(new PhutilClassMapQuery())
|
||||||
|
->setAncestorClass(__CLASS__)
|
||||||
|
->setUniqueMethod('getExtensionKey')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function getMailStamp($key) {
|
||||||
|
return $this->getEditor()->getMailStamp($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,8 +18,9 @@ final class MetaMTAMailSentGarbageCollector
|
|||||||
'dateCreated < %d LIMIT 100',
|
'dateCreated < %d LIMIT 100',
|
||||||
$this->getGarbageEpoch());
|
$this->getGarbageEpoch());
|
||||||
|
|
||||||
|
$engine = new PhabricatorDestructionEngine();
|
||||||
foreach ($mails as $mail) {
|
foreach ($mails as $mail) {
|
||||||
$mail->delete();
|
$engine->destroyObject($mail);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (count($mails) == 100);
|
return (count($mails) == 100);
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMailMustEncryptHeraldAction
|
||||||
|
extends HeraldAction {
|
||||||
|
|
||||||
|
const DO_MUST_ENCRYPT = 'do.must-encrypt';
|
||||||
|
|
||||||
|
const ACTIONCONST = 'email.must-encrypt';
|
||||||
|
|
||||||
|
public function getHeraldActionName() {
|
||||||
|
return pht('Require secure email');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderActionDescription($value) {
|
||||||
|
return pht(
|
||||||
|
'Require mail content be transmitted only over secure channels.');
|
||||||
|
}
|
||||||
|
public function supportsObject($object) {
|
||||||
|
return PhabricatorMetaMTAEmailHeraldAction::isMailGeneratingObject($object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getActionGroupKey() {
|
||||||
|
return HeraldUtilityActionGroup::ACTIONGROUPKEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsRuleType($rule_type) {
|
||||||
|
return ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_PERSONAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeraldActionStandardType() {
|
||||||
|
return self::STANDARD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyEffect($object, HeraldEffect $effect) {
|
||||||
|
$rule_phid = $effect->getRule()->getPHID();
|
||||||
|
|
||||||
|
$adapter = $this->getAdapter();
|
||||||
|
$adapter->addMustEncryptReason($rule_phid);
|
||||||
|
|
||||||
|
$this->logEffect(self::DO_MUST_ENCRYPT, array($rule_phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getActionEffectMap() {
|
||||||
|
return array(
|
||||||
|
self::DO_MUST_ENCRYPT => array(
|
||||||
|
'icon' => 'fa-shield',
|
||||||
|
'color' => 'blue',
|
||||||
|
'name' => pht('Must Encrypt'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderActionEffectDescription($type, $data) {
|
||||||
|
switch ($type) {
|
||||||
|
case self::DO_MUST_ENCRYPT:
|
||||||
|
return pht(
|
||||||
|
'Made it a requirement that mail content be transmitted only '.
|
||||||
|
'over secure channels.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ abstract class PhabricatorMetaMTAEmailHeraldAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function supportsObject($object) {
|
public function supportsObject($object) {
|
||||||
|
return self::isMailGeneratingObject($object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isMailGeneratingObject($object) {
|
||||||
// NOTE: This implementation lacks generality, but there's no great way to
|
// NOTE: This implementation lacks generality, but there's no great way to
|
||||||
// figure out if something generates email right now.
|
// figure out if something generates email right now.
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ final class PhabricatorMailManagementListOutboundWorkflow
|
|||||||
$table = id(new PhutilConsoleTable())
|
$table = id(new PhutilConsoleTable())
|
||||||
->setShowHeader(false)
|
->setShowHeader(false)
|
||||||
->addColumn('id', array('title' => pht('ID')))
|
->addColumn('id', array('title' => pht('ID')))
|
||||||
|
->addColumn('encrypt', array('title' => pht('#')))
|
||||||
->addColumn('status', array('title' => pht('Status')))
|
->addColumn('status', array('title' => pht('Status')))
|
||||||
->addColumn('subject', array('title' => pht('Subject')));
|
->addColumn('subject', array('title' => pht('Subject')));
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ final class PhabricatorMailManagementListOutboundWorkflow
|
|||||||
|
|
||||||
$table->addRow(array(
|
$table->addRow(array(
|
||||||
'id' => $mail->getID(),
|
'id' => $mail->getID(),
|
||||||
|
'encrypt' => ($mail->getMustEncrypt() ? '#' : ' '),
|
||||||
'status' => PhabricatorMailOutboundStatus::getStatusName($status),
|
'status' => PhabricatorMailOutboundStatus::getStatusName($status),
|
||||||
'subject' => $mail->getSubject(),
|
'subject' => $mail->getSubject(),
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ final class PhabricatorMailManagementSendTestWorkflow
|
|||||||
'help' => pht('Attach a file.'),
|
'help' => pht('Attach a file.'),
|
||||||
'repeat' => true,
|
'repeat' => true,
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'mailer',
|
||||||
|
'param' => 'key',
|
||||||
|
'help' => pht('Send with a specific configured mailer.'),
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'html',
|
'name' => 'html',
|
||||||
'help' => pht('Send as HTML mail.'),
|
'help' => pht('Send as HTML mail.'),
|
||||||
@@ -161,6 +166,21 @@ final class PhabricatorMailManagementSendTestWorkflow
|
|||||||
$mail->setFrom($from->getPHID());
|
$mail->setFrom($from->getPHID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mailer_key = $args->getArg('mailer');
|
||||||
|
if ($mailer_key !== null) {
|
||||||
|
$mailers = PhabricatorMetaMTAMail::newMailers();
|
||||||
|
$mailers = mpull($mailers, null, 'getKey');
|
||||||
|
if (!isset($mailers[$mailer_key])) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'Mailer key ("%s") is not configured. Available keys are: %s.',
|
||||||
|
$mailer_key,
|
||||||
|
implode(', ', array_keys($mailers))));
|
||||||
|
}
|
||||||
|
|
||||||
|
$mail->setTryMailers(array($mailer_key));
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($attach as $attachment) {
|
foreach ($attach as $attachment) {
|
||||||
$data = Filesystem::readFile($attachment);
|
$data = Filesystem::readFile($attachment);
|
||||||
$name = basename($attachment);
|
$name = basename($attachment);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||||||
|
|
||||||
$info = array();
|
$info = array();
|
||||||
|
|
||||||
$info[] = pht('PROPERTIES');
|
$info[] = $this->newSectionHeader(pht('PROPERTIES'));
|
||||||
$info[] = pht('ID: %d', $message->getID());
|
$info[] = pht('ID: %d', $message->getID());
|
||||||
$info[] = pht('Status: %s', $message->getStatus());
|
$info[] = pht('Status: %s', $message->getStatus());
|
||||||
$info[] = pht('Related PHID: %s', $message->getRelatedPHID());
|
$info[] = pht('Related PHID: %s', $message->getRelatedPHID());
|
||||||
@@ -87,15 +87,17 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||||||
|
|
||||||
$ignore = array(
|
$ignore = array(
|
||||||
'body' => true,
|
'body' => true,
|
||||||
|
'body.sent' => true,
|
||||||
'html-body' => true,
|
'html-body' => true,
|
||||||
'headers' => true,
|
'headers' => true,
|
||||||
'attachments' => true,
|
'attachments' => true,
|
||||||
'headers.sent' => true,
|
'headers.sent' => true,
|
||||||
|
'headers.unfiltered' => true,
|
||||||
'authors.sent' => true,
|
'authors.sent' => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
$info[] = pht('PARAMETERS');
|
$info[] = $this->newSectionHeader(pht('PARAMETERS'));
|
||||||
$parameters = $message->getParameters();
|
$parameters = $message->getParameters();
|
||||||
foreach ($parameters as $key => $value) {
|
foreach ($parameters as $key => $value) {
|
||||||
if (isset($ignore[$key])) {
|
if (isset($ignore[$key])) {
|
||||||
@@ -110,22 +112,40 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||||||
}
|
}
|
||||||
|
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
$info[] = pht('HEADERS');
|
$info[] = $this->newSectionHeader(pht('HEADERS'));
|
||||||
|
|
||||||
$headers = $message->getDeliveredHeaders();
|
$headers = $message->getDeliveredHeaders();
|
||||||
if (!$headers) {
|
$unfiltered = $message->getUnfilteredHeaders();
|
||||||
|
if (!$unfiltered) {
|
||||||
$headers = $message->generateHeaders();
|
$headers = $message->generateHeaders();
|
||||||
|
$unfiltered = $headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$header_map = array();
|
||||||
foreach ($headers as $header) {
|
foreach ($headers as $header) {
|
||||||
list($name, $value) = $header;
|
list($name, $value) = $header;
|
||||||
$info[] = "{$name}: {$value}";
|
$header_map[$name.':'.$value] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($unfiltered as $header) {
|
||||||
|
list($name, $value) = $header;
|
||||||
|
$was_sent = isset($header_map[$name.':'.$value]);
|
||||||
|
|
||||||
|
if ($was_sent) {
|
||||||
|
$marker = ' ';
|
||||||
|
} else {
|
||||||
|
$marker = '#';
|
||||||
|
}
|
||||||
|
|
||||||
|
$info[] = "{$marker} {$name}: {$value}";
|
||||||
}
|
}
|
||||||
|
|
||||||
$attachments = idx($parameters, 'attachments');
|
$attachments = idx($parameters, 'attachments');
|
||||||
if ($attachments) {
|
if ($attachments) {
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
$info[] = pht('ATTACHMENTS');
|
|
||||||
|
$info[] = $this->newSectionHeader(pht('ATTACHMENTS'));
|
||||||
|
|
||||||
foreach ($attachments as $attachment) {
|
foreach ($attachments as $attachment) {
|
||||||
$info[] = idx($attachment, 'filename', pht('Unnamed File'));
|
$info[] = idx($attachment, 'filename', pht('Unnamed File'));
|
||||||
}
|
}
|
||||||
@@ -136,7 +156,9 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||||||
$actors = $message->getDeliveredActors();
|
$actors = $message->getDeliveredActors();
|
||||||
if ($actors) {
|
if ($actors) {
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
$info[] = pht('RECIPIENTS');
|
|
||||||
|
$info[] = $this->newSectionHeader(pht('RECIPIENTS'));
|
||||||
|
|
||||||
foreach ($actors as $actor_phid => $actor_info) {
|
foreach ($actors as $actor_phid => $actor_info) {
|
||||||
$actor = idx($all_actors, $actor_phid);
|
$actor = idx($all_actors, $actor_phid);
|
||||||
if ($actor) {
|
if ($actor) {
|
||||||
@@ -162,15 +184,22 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||||||
}
|
}
|
||||||
|
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
$info[] = pht('TEXT BODY');
|
$info[] = $this->newSectionHeader(pht('TEXT BODY'));
|
||||||
if (strlen($message->getBody())) {
|
if (strlen($message->getBody())) {
|
||||||
$info[] = $message->getBody();
|
$info[] = tsprintf('%B', $message->getBody());
|
||||||
} else {
|
} else {
|
||||||
$info[] = pht('(This message has no text body.)');
|
$info[] = pht('(This message has no text body.)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$delivered_body = $message->getDeliveredBody();
|
||||||
|
if ($delivered_body !== null) {
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
$info[] = pht('HTML BODY');
|
$info[] = $this->newSectionHeader(pht('BODY AS DELIVERED'), true);
|
||||||
|
$info[] = tsprintf('%B', $delivered_body);
|
||||||
|
}
|
||||||
|
|
||||||
|
$info[] = null;
|
||||||
|
$info[] = $this->newSectionHeader(pht('HTML BODY'));
|
||||||
if (strlen($message->getHTMLBody())) {
|
if (strlen($message->getHTMLBody())) {
|
||||||
$info[] = $message->getHTMLBody();
|
$info[] = $message->getHTMLBody();
|
||||||
$info[] = null;
|
$info[] = null;
|
||||||
@@ -186,4 +215,12 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function newSectionHeader($label, $emphasize = false) {
|
||||||
|
if ($emphasize) {
|
||||||
|
return tsprintf('**<bg:yellow> %s </bg>**', $label);
|
||||||
|
} else {
|
||||||
|
return tsprintf('**<bg:blue> %s </bg>**', $label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
|||||||
const REASON_ROUTE_AS_NOTIFICATION = 'route-as-notification';
|
const REASON_ROUTE_AS_NOTIFICATION = 'route-as-notification';
|
||||||
const REASON_ROUTE_AS_MAIL = 'route-as-mail';
|
const REASON_ROUTE_AS_MAIL = 'route-as-mail';
|
||||||
const REASON_UNVERIFIED = 'unverified';
|
const REASON_UNVERIFIED = 'unverified';
|
||||||
|
const REASON_MUTED = 'muted';
|
||||||
|
|
||||||
private $phid;
|
private $phid;
|
||||||
private $emailAddress;
|
private $emailAddress;
|
||||||
@@ -116,6 +117,7 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
|||||||
self::REASON_ROUTE_AS_NOTIFICATION => pht('Route as Notification'),
|
self::REASON_ROUTE_AS_NOTIFICATION => pht('Route as Notification'),
|
||||||
self::REASON_ROUTE_AS_MAIL => pht('Route as Mail'),
|
self::REASON_ROUTE_AS_MAIL => pht('Route as Mail'),
|
||||||
self::REASON_UNVERIFIED => pht('Address Not Verified'),
|
self::REASON_UNVERIFIED => pht('Address Not Verified'),
|
||||||
|
self::REASON_MUTED => pht('Muted'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return idx($names, $reason, pht('Unknown ("%s")', $reason));
|
return idx($names, $reason, pht('Unknown ("%s")', $reason));
|
||||||
@@ -172,6 +174,8 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
|||||||
'in Herald.'),
|
'in Herald.'),
|
||||||
self::REASON_UNVERIFIED => pht(
|
self::REASON_UNVERIFIED => pht(
|
||||||
'This recipient does not have a verified primary email address.'),
|
'This recipient does not have a verified primary email address.'),
|
||||||
|
self::REASON_MUTED => pht(
|
||||||
|
'This recipient has muted notifications for this object.'),
|
||||||
);
|
);
|
||||||
|
|
||||||
return idx($descriptions, $reason, pht('Unknown Reason ("%s")', $reason));
|
return idx($descriptions, $reason, pht('Unknown Reason ("%s")', $reason));
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
|||||||
private $applicationEmail;
|
private $applicationEmail;
|
||||||
private $actor;
|
private $actor;
|
||||||
private $excludePHIDs = array();
|
private $excludePHIDs = array();
|
||||||
|
private $unexpandablePHIDs = array();
|
||||||
|
|
||||||
final public function setMailReceiver($mail_receiver) {
|
final public function setMailReceiver($mail_receiver) {
|
||||||
$this->validateMailReceiver($mail_receiver);
|
$this->validateMailReceiver($mail_receiver);
|
||||||
@@ -45,6 +46,15 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
|||||||
return $this->excludePHIDs;
|
return $this->excludePHIDs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUnexpandablePHIDs(array $phids) {
|
||||||
|
$this->unexpandablePHIDs = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUnexpandablePHIDs() {
|
||||||
|
return $this->unexpandablePHIDs;
|
||||||
|
}
|
||||||
|
|
||||||
abstract public function validateMailReceiver($mail_receiver);
|
abstract public function validateMailReceiver($mail_receiver);
|
||||||
abstract public function getPrivateReplyHandlerEmailAddress(
|
abstract public function getPrivateReplyHandlerEmailAddress(
|
||||||
PhabricatorUser $user);
|
PhabricatorUser $user);
|
||||||
@@ -297,6 +307,16 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
|||||||
$to_result = array();
|
$to_result = array();
|
||||||
$cc_result = array();
|
$cc_result = array();
|
||||||
|
|
||||||
|
// "Unexpandable" users have disengaged from an object (for example,
|
||||||
|
// by resigning from a revision).
|
||||||
|
|
||||||
|
// If such a user is still a direct recipient (for example, they're still
|
||||||
|
// on the Subscribers list) they're fair game, but group targets (like
|
||||||
|
// projects) will no longer include them when expanded.
|
||||||
|
|
||||||
|
$unexpandable = $this->getUnexpandablePHIDs();
|
||||||
|
$unexpandable = array_fuse($unexpandable);
|
||||||
|
|
||||||
$all_phids = array_merge($to, $cc);
|
$all_phids = array_merge($to, $cc);
|
||||||
if ($all_phids) {
|
if ($all_phids) {
|
||||||
$map = id(new PhabricatorMetaMTAMemberQuery())
|
$map = id(new PhabricatorMetaMTAMemberQuery())
|
||||||
@@ -305,11 +325,21 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
|||||||
->execute();
|
->execute();
|
||||||
foreach ($to as $phid) {
|
foreach ($to as $phid) {
|
||||||
foreach ($map[$phid] as $expanded) {
|
foreach ($map[$phid] as $expanded) {
|
||||||
|
if ($expanded !== $phid) {
|
||||||
|
if (isset($unexpandable[$expanded])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
$to_result[$expanded] = $expanded;
|
$to_result[$expanded] = $expanded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($cc as $phid) {
|
foreach ($cc as $phid) {
|
||||||
foreach ($map[$phid] as $expanded) {
|
foreach ($map[$phid] as $expanded) {
|
||||||
|
if ($expanded !== $phid) {
|
||||||
|
if (isset($unexpandable[$expanded])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
$cc_result[$expanded] = $expanded;
|
$cc_result[$expanded] = $expanded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,23 +58,55 @@ final class PhabricatorMailTarget extends Phobject {
|
|||||||
public function willSendMail(PhabricatorMetaMTAMail $mail) {
|
public function willSendMail(PhabricatorMetaMTAMail $mail) {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$show_stamps = $mail->shouldRenderMailStampsInBody($viewer);
|
||||||
|
|
||||||
|
$body = $mail->getBody();
|
||||||
|
$html_body = $mail->getHTMLBody();
|
||||||
|
$has_html = (strlen($html_body) > 0);
|
||||||
|
|
||||||
|
if ($show_stamps) {
|
||||||
|
$stamps = $mail->getMailStamps();
|
||||||
|
if ($stamps) {
|
||||||
|
$body .= "\n";
|
||||||
|
$body .= pht('STAMPS');
|
||||||
|
$body .= "\n";
|
||||||
|
$body .= implode(' ', $stamps);
|
||||||
|
$body .= "\n";
|
||||||
|
|
||||||
|
if ($has_html) {
|
||||||
|
$html = array();
|
||||||
|
$html[] = phutil_tag('strong', array(), pht('STAMPS'));
|
||||||
|
$html[] = phutil_tag('br');
|
||||||
|
$html[] = phutil_tag(
|
||||||
|
'span',
|
||||||
|
array(
|
||||||
|
'style' => 'font-size: smaller; color: #92969D',
|
||||||
|
),
|
||||||
|
phutil_implode_html(' ', $stamps));
|
||||||
|
$html[] = phutil_tag('br');
|
||||||
|
$html[] = phutil_tag('br');
|
||||||
|
$html = phutil_tag('div', array(), $html);
|
||||||
|
$html_body .= hsprintf('%s', $html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$mail->addPHIDHeaders('X-Phabricator-To', $this->rawToPHIDs);
|
$mail->addPHIDHeaders('X-Phabricator-To', $this->rawToPHIDs);
|
||||||
$mail->addPHIDHeaders('X-Phabricator-Cc', $this->rawCCPHIDs);
|
$mail->addPHIDHeaders('X-Phabricator-Cc', $this->rawCCPHIDs);
|
||||||
|
|
||||||
$to_handles = $viewer->loadHandles($this->rawToPHIDs);
|
$to_handles = $viewer->loadHandles($this->rawToPHIDs);
|
||||||
$cc_handles = $viewer->loadHandles($this->rawCCPHIDs);
|
$cc_handles = $viewer->loadHandles($this->rawCCPHIDs);
|
||||||
|
|
||||||
$body = $mail->getBody();
|
|
||||||
$body .= "\n";
|
$body .= "\n";
|
||||||
$body .= $this->getRecipientsSummary($to_handles, $cc_handles);
|
$body .= $this->getRecipientsSummary($to_handles, $cc_handles);
|
||||||
$mail->setBody($body);
|
|
||||||
|
|
||||||
$html_body = $mail->getHTMLBody();
|
if ($has_html) {
|
||||||
if (strlen($html_body)) {
|
|
||||||
$html_body .= hsprintf(
|
$html_body .= hsprintf(
|
||||||
'%s',
|
'%s',
|
||||||
$this->getRecipientsSummaryHTML($to_handles, $cc_handles));
|
$this->getRecipientsSummaryHTML($to_handles, $cc_handles));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mail->setBody($body);
|
||||||
$mail->setHTMLBody($html_body);
|
$mail->setHTMLBody($html_body);
|
||||||
|
|
||||||
$reply_to = $this->getReplyTo();
|
$reply_to = $this->getReplyTo();
|
||||||
|
|||||||
16
src/applications/metamta/stamp/PhabricatorBoolMailStamp.php
Normal file
16
src/applications/metamta/stamp/PhabricatorBoolMailStamp.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorBoolMailStamp
|
||||||
|
extends PhabricatorMailStamp {
|
||||||
|
|
||||||
|
const STAMPTYPE = 'bool';
|
||||||
|
|
||||||
|
public function renderStamps($value) {
|
||||||
|
if (!$value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->renderStamp($this->getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
88
src/applications/metamta/stamp/PhabricatorMailStamp.php
Normal file
88
src/applications/metamta/stamp/PhabricatorMailStamp.php
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorMailStamp
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $key;
|
||||||
|
private $value;
|
||||||
|
private $label;
|
||||||
|
private $viewer;
|
||||||
|
|
||||||
|
final public function getStampType() {
|
||||||
|
return $this->getPhobjectClassConstant('STAMPTYPE');
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setKey($key) {
|
||||||
|
$this->key = $key;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getKey() {
|
||||||
|
return $this->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function setRawValue($value) {
|
||||||
|
$this->value = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function getRawValue() {
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setViewer(PhabricatorUser $viewer) {
|
||||||
|
$this->viewer = $viewer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getViewer() {
|
||||||
|
return $this->viewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function setLabel($label) {
|
||||||
|
$this->label = $label;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getLabel() {
|
||||||
|
return $this->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue($value) {
|
||||||
|
return $this->setRawValue($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function toDictionary() {
|
||||||
|
return array(
|
||||||
|
'type' => $this->getStampType(),
|
||||||
|
'key' => $this->getKey(),
|
||||||
|
'value' => $this->getValueForDictionary(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function getAllStamps() {
|
||||||
|
return id(new PhutilClassMapQuery())
|
||||||
|
->setAncestorClass(__CLASS__)
|
||||||
|
->setUniqueMethod('getStampType')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getValueForDictionary() {
|
||||||
|
return $this->getRawValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValueFromDictionary($value) {
|
||||||
|
return $this->setRawValue($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValueForRendering() {
|
||||||
|
return $this->getRawValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public function renderStamps($value);
|
||||||
|
|
||||||
|
final protected function renderStamp($key, $value = null) {
|
||||||
|
return $key.'('.$value.')';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
36
src/applications/metamta/stamp/PhabricatorPHIDMailStamp.php
Normal file
36
src/applications/metamta/stamp/PhabricatorPHIDMailStamp.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorPHIDMailStamp
|
||||||
|
extends PhabricatorMailStamp {
|
||||||
|
|
||||||
|
const STAMPTYPE = 'phid';
|
||||||
|
|
||||||
|
public function renderStamps($value) {
|
||||||
|
if ($value === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = (array)$value;
|
||||||
|
if (!$value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$handles = $viewer->loadHandles($value);
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($value as $phid) {
|
||||||
|
$handle = $handles[$phid];
|
||||||
|
|
||||||
|
$mail_name = $handle->getMailStampName();
|
||||||
|
if ($mail_name === null) {
|
||||||
|
$mail_name = $handle->getPHID();
|
||||||
|
}
|
||||||
|
|
||||||
|
$results[] = $this->renderStamp($this->getKey(), $mail_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorStringMailStamp
|
||||||
|
extends PhabricatorMailStamp {
|
||||||
|
|
||||||
|
const STAMPTYPE = 'string';
|
||||||
|
|
||||||
|
public function renderStamps($value) {
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = (array)$value;
|
||||||
|
if (!$value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($value as $v) {
|
||||||
|
$results[] = $this->renderStamp($this->getKey(), $v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorMetaMTAAttachment extends Phobject {
|
final class PhabricatorMetaMTAAttachment extends Phobject {
|
||||||
protected $data;
|
|
||||||
protected $filename;
|
private $data;
|
||||||
protected $mimetype;
|
private $filename;
|
||||||
|
private $mimetype;
|
||||||
|
private $file;
|
||||||
|
private $filePHID;
|
||||||
|
|
||||||
public function __construct($data, $filename, $mimetype) {
|
public function __construct($data, $filename, $mimetype) {
|
||||||
$this->setData($data);
|
$this->setData($data);
|
||||||
@@ -39,18 +42,49 @@ final class PhabricatorMetaMTAAttachment extends Phobject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function toDictionary() {
|
public function toDictionary() {
|
||||||
|
if (!$this->file) {
|
||||||
|
$iterator = new ArrayIterator(array($this->getData()));
|
||||||
|
|
||||||
|
$source = id(new PhabricatorIteratorFileUploadSource())
|
||||||
|
->setName($this->getFilename())
|
||||||
|
->setViewPolicy(PhabricatorPolicies::POLICY_NOONE)
|
||||||
|
->setMIMEType($this->getMimeType())
|
||||||
|
->setIterator($iterator);
|
||||||
|
|
||||||
|
$this->file = $source->uploadFile();
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'filename' => $this->getFilename(),
|
'filename' => $this->getFilename(),
|
||||||
'mimetype' => $this->getMimeType(),
|
'mimetype' => $this->getMimeType(),
|
||||||
'data' => $this->getData(),
|
'filePHID' => $this->file->getPHID(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function newFromDictionary(array $dict) {
|
public static function newFromDictionary(array $dict) {
|
||||||
return new PhabricatorMetaMTAAttachment(
|
$file = null;
|
||||||
|
|
||||||
|
$file_phid = idx($dict, 'filePHID');
|
||||||
|
if ($file_phid) {
|
||||||
|
$file = id(new PhabricatorFileQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withPHIDs(array($file_phid))
|
||||||
|
->executeOne();
|
||||||
|
if ($file) {
|
||||||
|
$dict['data'] = $file->loadFileData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$attachment = new self(
|
||||||
idx($dict, 'data'),
|
idx($dict, 'data'),
|
||||||
idx($dict, 'filename'),
|
idx($dict, 'filename'),
|
||||||
idx($dict, 'mimetype'));
|
idx($dict, 'mimetype'));
|
||||||
|
|
||||||
|
if ($file) {
|
||||||
|
$attachment->file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
final class PhabricatorMetaMTAMail
|
final class PhabricatorMetaMTAMail
|
||||||
extends PhabricatorMetaMTADAO
|
extends PhabricatorMetaMTADAO
|
||||||
implements PhabricatorPolicyInterface {
|
implements
|
||||||
|
PhabricatorPolicyInterface,
|
||||||
|
PhabricatorDestructibleInterface {
|
||||||
|
|
||||||
const RETRY_DELAY = 5;
|
const RETRY_DELAY = 5;
|
||||||
|
|
||||||
@@ -21,7 +23,10 @@ final class PhabricatorMetaMTAMail
|
|||||||
public function __construct() {
|
public function __construct() {
|
||||||
|
|
||||||
$this->status = PhabricatorMailOutboundStatus::STATUS_QUEUE;
|
$this->status = PhabricatorMailOutboundStatus::STATUS_QUEUE;
|
||||||
$this->parameters = array('sensitive' => true);
|
$this->parameters = array(
|
||||||
|
'sensitive' => true,
|
||||||
|
'mustEncrypt' => false,
|
||||||
|
);
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
@@ -155,6 +160,15 @@ final class PhabricatorMetaMTAMail
|
|||||||
return $this->getParam('exclude', array());
|
return $this->getParam('exclude', array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setMutedPHIDs(array $muted) {
|
||||||
|
$this->setParam('muted', $muted);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMutedPHIDs() {
|
||||||
|
return $this->getParam('muted', array());
|
||||||
|
}
|
||||||
|
|
||||||
public function setForceHeraldMailRecipientPHIDs(array $force) {
|
public function setForceHeraldMailRecipientPHIDs(array $force) {
|
||||||
$this->setParam('herald-force-recipients', $force);
|
$this->setParam('herald-force-recipients', $force);
|
||||||
return $this;
|
return $this;
|
||||||
@@ -192,6 +206,35 @@ final class PhabricatorMetaMTAMail
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAttachmentFilePHIDs() {
|
||||||
|
$file_phids = array();
|
||||||
|
|
||||||
|
$dictionaries = $this->getParam('attachments');
|
||||||
|
if ($dictionaries) {
|
||||||
|
foreach ($dictionaries as $dictionary) {
|
||||||
|
$file_phid = idx($dictionary, 'filePHID');
|
||||||
|
if ($file_phid) {
|
||||||
|
$file_phids[] = $file_phid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file_phids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadAttachedFiles(PhabricatorUser $viewer) {
|
||||||
|
$file_phids = $this->getAttachmentFilePHIDs();
|
||||||
|
|
||||||
|
if (!$file_phids) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PhabricatorFileQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs($file_phids)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
public function setAttachments(array $attachments) {
|
public function setAttachments(array $attachments) {
|
||||||
assert_instances_of($attachments, 'PhabricatorMetaMTAAttachment');
|
assert_instances_of($attachments, 'PhabricatorMetaMTAAttachment');
|
||||||
$this->setParam('attachments', mpull($attachments, 'toDictionary'));
|
$this->setParam('attachments', mpull($attachments, 'toDictionary'));
|
||||||
@@ -247,6 +290,48 @@ final class PhabricatorMetaMTAMail
|
|||||||
return $this->getParam('sensitive', true);
|
return $this->getParam('sensitive', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setMustEncrypt($bool) {
|
||||||
|
$this->setParam('mustEncrypt', $bool);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMustEncrypt() {
|
||||||
|
return $this->getParam('mustEncrypt', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMustEncryptReasons(array $reasons) {
|
||||||
|
$this->setParam('mustEncryptReasons', $reasons);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMustEncryptReasons() {
|
||||||
|
return $this->getParam('mustEncryptReasons', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMailStamps(array $stamps) {
|
||||||
|
return $this->setParam('stamps', $stamps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailStamps() {
|
||||||
|
return $this->getParam('stamps', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMailStampMetadata($metadata) {
|
||||||
|
return $this->setParam('stampMetadata', $metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailStampMetadata() {
|
||||||
|
return $this->getParam('stampMetadata', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailerKey() {
|
||||||
|
return $this->getParam('mailer.key');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTryMailers(array $mailers) {
|
||||||
|
return $this->setParam('mailers.try', $mailers);
|
||||||
|
}
|
||||||
|
|
||||||
public function setHTMLBody($html) {
|
public function setHTMLBody($html) {
|
||||||
$this->setParam('html-body', $html);
|
$this->setParam('html-body', $html);
|
||||||
return $this;
|
return $this;
|
||||||
@@ -385,36 +470,196 @@ final class PhabricatorMetaMTAMail
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildDefaultMailer() {
|
|
||||||
return PhabricatorEnv::newObjectFromConfig('metamta.mail-adapter');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to deliver an email immediately, in this process.
|
* Attempt to deliver an email immediately, in this process.
|
||||||
*
|
*
|
||||||
* @param bool Try to deliver this email even if it has already been
|
|
||||||
* delivered or is in backoff after a failed delivery attempt.
|
|
||||||
* @param PhabricatorMailImplementationAdapter Use a specific mail adapter,
|
|
||||||
* instead of the default.
|
|
||||||
*
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function sendNow(
|
public function sendNow() {
|
||||||
$force_send = false,
|
|
||||||
PhabricatorMailImplementationAdapter $mailer = null) {
|
|
||||||
|
|
||||||
if ($mailer === null) {
|
|
||||||
$mailer = $this->buildDefaultMailer();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$force_send) {
|
|
||||||
if ($this->getStatus() != PhabricatorMailOutboundStatus::STATUS_QUEUE) {
|
if ($this->getStatus() != PhabricatorMailOutboundStatus::STATUS_QUEUE) {
|
||||||
throw new Exception(pht('Trying to send an already-sent mail!'));
|
throw new Exception(pht('Trying to send an already-sent mail!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mailers = self::newMailers();
|
||||||
|
|
||||||
|
$try_mailers = $this->getParam('mailers.try');
|
||||||
|
if ($try_mailers) {
|
||||||
|
$mailers = mpull($mailers, null, 'getKey');
|
||||||
|
$mailers = array_select_keys($mailers, $try_mailers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendWithMailers($mailers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function newMailersWithTypes(array $types) {
|
||||||
|
$mailers = self::newMailers();
|
||||||
|
$types = array_fuse($types);
|
||||||
|
|
||||||
|
foreach ($mailers as $key => $mailer) {
|
||||||
|
$mailer_type = $mailer->getAdapterType();
|
||||||
|
if (!isset($types[$mailer_type])) {
|
||||||
|
unset($mailers[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values($mailers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function newMailers() {
|
||||||
|
$mailers = array();
|
||||||
|
|
||||||
|
$config = PhabricatorEnv::getEnvConfig('cluster.mailers');
|
||||||
|
if ($config === null) {
|
||||||
|
$mailer = PhabricatorEnv::newObjectFromConfig('metamta.mail-adapter');
|
||||||
|
|
||||||
|
$defaults = $mailer->newDefaultOptions();
|
||||||
|
$options = $mailer->newLegacyOptions();
|
||||||
|
|
||||||
|
$options = $options + $defaults;
|
||||||
|
|
||||||
|
$mailer
|
||||||
|
->setKey('default')
|
||||||
|
->setPriority(-1)
|
||||||
|
->setOptions($options);
|
||||||
|
|
||||||
|
$mailers[] = $mailer;
|
||||||
|
} else {
|
||||||
|
$adapters = PhabricatorMailImplementationAdapter::getAllAdapters();
|
||||||
|
$next_priority = -1;
|
||||||
|
|
||||||
|
foreach ($config as $spec) {
|
||||||
|
$type = $spec['type'];
|
||||||
|
if (!isset($adapters[$type])) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Unknown mailer ("%s")!',
|
||||||
|
$type));
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = $spec['key'];
|
||||||
|
$mailer = id(clone $adapters[$type])
|
||||||
|
->setKey($key);
|
||||||
|
|
||||||
|
$priority = idx($spec, 'priority');
|
||||||
|
if (!$priority) {
|
||||||
|
$priority = $next_priority;
|
||||||
|
$next_priority--;
|
||||||
|
}
|
||||||
|
$mailer->setPriority($priority);
|
||||||
|
|
||||||
|
$defaults = $mailer->newDefaultOptions();
|
||||||
|
$options = idx($spec, 'options', array()) + $defaults;
|
||||||
|
$mailer->setOptions($options);
|
||||||
|
|
||||||
|
$mailers[] = $mailer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sorted = array();
|
||||||
|
$groups = mgroup($mailers, 'getPriority');
|
||||||
|
krsort($groups);
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
// Reorder services within the same priority group randomly.
|
||||||
|
shuffle($group);
|
||||||
|
foreach ($group as $mailer) {
|
||||||
|
$sorted[] = $mailer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($sorted as $mailer) {
|
||||||
|
$mailer->prepareForSend();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendWithMailers(array $mailers) {
|
||||||
|
if (!$mailers) {
|
||||||
|
return $this
|
||||||
|
->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID)
|
||||||
|
->setMessage(pht('No mailers are configured.'))
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$exceptions = array();
|
||||||
|
foreach ($mailers as $template_mailer) {
|
||||||
|
$mailer = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$mailer = $this->buildMailer($template_mailer);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$exceptions[] = $ex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$mailer) {
|
||||||
|
// If we don't get a mailer back, that means the mail doesn't
|
||||||
|
// actually need to be sent (for example, because recipients have
|
||||||
|
// declined to receive the mail). Void it and return.
|
||||||
|
return $this
|
||||||
|
->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID)
|
||||||
|
->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$ok = $mailer->send();
|
||||||
|
if (!$ok) {
|
||||||
|
// TODO: At some point, we should clean this up and make all mailers
|
||||||
|
// throw.
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Mail adapter encountered an unexpected, unspecified '.
|
||||||
|
'failure.'));
|
||||||
|
}
|
||||||
|
} catch (PhabricatorMetaMTAPermanentFailureException $ex) {
|
||||||
|
// If any mailer raises a permanent failure, stop trying to send the
|
||||||
|
// mail with other mailers.
|
||||||
|
$this
|
||||||
|
->setStatus(PhabricatorMailOutboundStatus::STATUS_FAIL)
|
||||||
|
->setMessage($ex->getMessage())
|
||||||
|
->save();
|
||||||
|
|
||||||
|
throw $ex;
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$exceptions[] = $ex;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of which mailer actually ended up accepting the message.
|
||||||
|
$mailer_key = $mailer->getKey();
|
||||||
|
if ($mailer_key !== null) {
|
||||||
|
$this->setParam('mailer.key', $mailer_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->setStatus(PhabricatorMailOutboundStatus::STATUS_SENT)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we make it here, no mailer could send the mail but no mailer failed
|
||||||
|
// permanently either. We update the error message for the mail, but leave
|
||||||
|
// it in the current status (usually, STATUS_QUEUE) and try again later.
|
||||||
|
|
||||||
|
$messages = array();
|
||||||
|
foreach ($exceptions as $ex) {
|
||||||
|
$messages[] = $ex->getMessage();
|
||||||
|
}
|
||||||
|
$messages = implode("\n\n", $messages);
|
||||||
|
|
||||||
|
$this
|
||||||
|
->setMessage($messages)
|
||||||
|
->save();
|
||||||
|
|
||||||
|
if (count($exceptions) === 1) {
|
||||||
|
throw head($exceptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PhutilAggregateException(
|
||||||
|
pht('Encountered multiple exceptions while transmitting mail.'),
|
||||||
|
$exceptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildMailer(PhabricatorMailImplementationAdapter $mailer) {
|
||||||
$headers = $this->generateHeaders();
|
$headers = $this->generateHeaders();
|
||||||
|
|
||||||
$params = $this->parameters;
|
$params = $this->parameters;
|
||||||
@@ -431,6 +676,7 @@ final class PhabricatorMetaMTAMail
|
|||||||
unset($params['is-first-message']);
|
unset($params['is-first-message']);
|
||||||
|
|
||||||
$is_threaded = (bool)idx($params, 'thread-id');
|
$is_threaded = (bool)idx($params, 'thread-id');
|
||||||
|
$must_encrypt = $this->getMustEncrypt();
|
||||||
|
|
||||||
$reply_to_name = idx($params, 'reply-to-name', '');
|
$reply_to_name = idx($params, 'reply-to-name', '');
|
||||||
unset($params['reply-to-name']);
|
unset($params['reply-to-name']);
|
||||||
@@ -438,8 +684,8 @@ final class PhabricatorMetaMTAMail
|
|||||||
$add_cc = array();
|
$add_cc = array();
|
||||||
$add_to = array();
|
$add_to = array();
|
||||||
|
|
||||||
// If multiplexing is enabled, some recipients will be in "Cc"
|
// If we're sending one mail to everyone, some recipients will be in
|
||||||
// rather than "To". We'll move them to "To" later (or supply a
|
// "Cc" rather than "To". We'll move them to "To" later (or supply a
|
||||||
// dummy "To") but need to look for the recipient in either the
|
// dummy "To") but need to look for the recipient in either the
|
||||||
// "To" or "Cc" fields here.
|
// "To" or "Cc" fields here.
|
||||||
$target_phid = head(idx($params, 'to', array()));
|
$target_phid = head(idx($params, 'to', array()));
|
||||||
@@ -456,6 +702,12 @@ final class PhabricatorMetaMTAMail
|
|||||||
$mailer->setFrom($from_email, $from_name);
|
$mailer->setFrom($from_email, $from_name);
|
||||||
break;
|
break;
|
||||||
case 'from':
|
case 'from':
|
||||||
|
// If the mail content must be encrypted, disguise the sender.
|
||||||
|
if ($must_encrypt) {
|
||||||
|
$mailer->setFrom($default_from, pht('Phabricator'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$from = $value;
|
$from = $value;
|
||||||
$actor_email = null;
|
$actor_email = null;
|
||||||
$actor_name = null;
|
$actor_name = null;
|
||||||
@@ -502,6 +754,17 @@ final class PhabricatorMetaMTAMail
|
|||||||
mpull($cc_actors, 'getEmailAddress'));
|
mpull($cc_actors, 'getEmailAddress'));
|
||||||
break;
|
break;
|
||||||
case 'attachments':
|
case 'attachments':
|
||||||
|
$attached_viewer = PhabricatorUser::getOmnipotentUser();
|
||||||
|
$files = $this->loadAttachedFiles($attached_viewer);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$file->attachToObject($this->getPHID());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the mail content must be encrypted, don't add attachments.
|
||||||
|
if ($must_encrypt) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$value = $this->getAttachments();
|
$value = $this->getAttachments();
|
||||||
foreach ($value as $attachment) {
|
foreach ($value as $attachment) {
|
||||||
$mailer->addAttachment(
|
$mailer->addAttachment(
|
||||||
@@ -521,6 +784,11 @@ final class PhabricatorMetaMTAMail
|
|||||||
|
|
||||||
$subject[] = trim(idx($params, 'subject-prefix'));
|
$subject[] = trim(idx($params, 'subject-prefix'));
|
||||||
|
|
||||||
|
// If mail content must be encrypted, we replace the subject with
|
||||||
|
// a generic one.
|
||||||
|
if ($must_encrypt) {
|
||||||
|
$subject[] = pht('Object Updated');
|
||||||
|
} else {
|
||||||
$vary_prefix = idx($params, 'vary-subject-prefix');
|
$vary_prefix = idx($params, 'vary-subject-prefix');
|
||||||
if ($vary_prefix != '') {
|
if ($vary_prefix != '') {
|
||||||
if ($this->shouldVarySubject($preferences)) {
|
if ($this->shouldVarySubject($preferences)) {
|
||||||
@@ -529,6 +797,7 @@ final class PhabricatorMetaMTAMail
|
|||||||
}
|
}
|
||||||
|
|
||||||
$subject[] = $value;
|
$subject[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
$mailer->setSubject(implode(' ', array_filter($subject)));
|
$mailer->setSubject(implode(' ', array_filter($subject)));
|
||||||
break;
|
break;
|
||||||
@@ -567,7 +836,27 @@ final class PhabricatorMetaMTAMail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$body = idx($params, 'body', '');
|
$stamps = $this->getMailStamps();
|
||||||
|
if ($stamps) {
|
||||||
|
$headers[] = array('X-Phabricator-Stamps', implode(' ', $stamps));
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw_body = idx($params, 'body', '');
|
||||||
|
$body = $raw_body;
|
||||||
|
if ($must_encrypt) {
|
||||||
|
$parts = array();
|
||||||
|
$parts[] = pht(
|
||||||
|
'The content for this message can only be transmitted over a '.
|
||||||
|
'secure channel. To view the message content, follow this '.
|
||||||
|
'link:');
|
||||||
|
|
||||||
|
$parts[] = PhabricatorEnv::getProductionURI($this->getURI());
|
||||||
|
|
||||||
|
$body = implode("\n\n", $parts);
|
||||||
|
} else {
|
||||||
|
$body = $raw_body;
|
||||||
|
}
|
||||||
|
|
||||||
$max = PhabricatorEnv::getEnvConfig('metamta.email-body-limit');
|
$max = PhabricatorEnv::getEnvConfig('metamta.email-body-limit');
|
||||||
if (strlen($body) > $max) {
|
if (strlen($body) > $max) {
|
||||||
$body = id(new PhutilUTF8StringTruncator())
|
$body = id(new PhutilUTF8StringTruncator())
|
||||||
@@ -578,18 +867,32 @@ final class PhabricatorMetaMTAMail
|
|||||||
}
|
}
|
||||||
$mailer->setBody($body);
|
$mailer->setBody($body);
|
||||||
|
|
||||||
$html_emails = $this->shouldSendHTML($preferences);
|
// If we sent a different message body than we were asked to, record
|
||||||
if ($html_emails && isset($params['html-body'])) {
|
// what we actually sent to make debugging and diagnostics easier.
|
||||||
|
if ($body !== $raw_body) {
|
||||||
|
$this->setParam('body.sent', $body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($must_encrypt) {
|
||||||
|
$send_html = false;
|
||||||
|
} else {
|
||||||
|
$send_html = $this->shouldSendHTML($preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($send_html && isset($params['html-body'])) {
|
||||||
$mailer->setHTMLBody($params['html-body']);
|
$mailer->setHTMLBody($params['html-body']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass the headers to the mailer, then save the state so we can show
|
// Pass the headers to the mailer, then save the state so we can show
|
||||||
// them in the web UI.
|
// them in the web UI. If the mail must be encrypted, we remove headers
|
||||||
foreach ($headers as $header) {
|
// which are not on a strict whitelist to avoid disclosing information.
|
||||||
|
$filtered_headers = $this->filterHeaders($headers, $must_encrypt);
|
||||||
|
foreach ($filtered_headers as $header) {
|
||||||
list($header_key, $header_value) = $header;
|
list($header_key, $header_value) = $header;
|
||||||
$mailer->addHeader($header_key, $header_value);
|
$mailer->addHeader($header_key, $header_value);
|
||||||
}
|
}
|
||||||
$this->setParam('headers.sent', $headers);
|
$this->setParam('headers.unfiltered', $headers);
|
||||||
|
$this->setParam('headers.sent', $filtered_headers);
|
||||||
|
|
||||||
// Save the final deliverability outcomes and reasoning so we can
|
// Save the final deliverability outcomes and reasoning so we can
|
||||||
// explain why things happened the way they did.
|
// explain why things happened the way they did.
|
||||||
@@ -606,35 +909,35 @@ final class PhabricatorMetaMTAMail
|
|||||||
$this->setParam('routingmap.sent', $this->getRoutingRuleMap());
|
$this->setParam('routingmap.sent', $this->getRoutingRuleMap());
|
||||||
|
|
||||||
if (!$add_to && !$add_cc) {
|
if (!$add_to && !$add_cc) {
|
||||||
$this->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID);
|
|
||||||
$this->setMessage(
|
$this->setMessage(
|
||||||
pht(
|
pht(
|
||||||
'Message has no valid recipients: all To/Cc are disabled, '.
|
'Message has no valid recipients: all To/Cc are disabled, '.
|
||||||
'invalid, or configured not to receive this mail.'));
|
'invalid, or configured not to receive this mail.'));
|
||||||
return $this->save();
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->getIsErrorEmail()) {
|
if ($this->getIsErrorEmail()) {
|
||||||
$all_recipients = array_merge($add_to, $add_cc);
|
$all_recipients = array_merge($add_to, $add_cc);
|
||||||
if ($this->shouldRateLimitMail($all_recipients)) {
|
if ($this->shouldRateLimitMail($all_recipients)) {
|
||||||
$this->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID);
|
|
||||||
$this->setMessage(
|
$this->setMessage(
|
||||||
pht(
|
pht(
|
||||||
'This is an error email, but one or more recipients have '.
|
'This is an error email, but one or more recipients have '.
|
||||||
'exceeded the error email rate limit. Declining to deliver '.
|
'exceeded the error email rate limit. Declining to deliver '.
|
||||||
'message.'));
|
'message.'));
|
||||||
return $this->save();
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
|
if (PhabricatorEnv::getEnvConfig('phabricator.silent')) {
|
||||||
$this->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID);
|
|
||||||
$this->setMessage(
|
$this->setMessage(
|
||||||
pht(
|
pht(
|
||||||
'Phabricator is running in silent mode. See `%s` '.
|
'Phabricator is running in silent mode. See `%s` '.
|
||||||
'in the configuration to change this setting.',
|
'in the configuration to change this setting.',
|
||||||
'phabricator.silent'));
|
'phabricator.silent'));
|
||||||
return $this->save();
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some mailers require a valid "To:" in order to deliver mail. If we
|
// Some mailers require a valid "To:" in order to deliver mail. If we
|
||||||
@@ -658,42 +961,8 @@ final class PhabricatorMetaMTAMail
|
|||||||
if ($add_cc) {
|
if ($add_cc) {
|
||||||
$mailer->addCCs($add_cc);
|
$mailer->addCCs($add_cc);
|
||||||
}
|
}
|
||||||
} catch (Exception $ex) {
|
|
||||||
$this
|
|
||||||
->setStatus(PhabricatorMailOutboundStatus::STATUS_FAIL)
|
|
||||||
->setMessage($ex->getMessage())
|
|
||||||
->save();
|
|
||||||
|
|
||||||
throw $ex;
|
return $mailer;
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$ok = $mailer->send();
|
|
||||||
if (!$ok) {
|
|
||||||
// TODO: At some point, we should clean this up and make all mailers
|
|
||||||
// throw.
|
|
||||||
throw new Exception(
|
|
||||||
pht('Mail adapter encountered an unexpected, unspecified failure.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->setStatus(PhabricatorMailOutboundStatus::STATUS_SENT);
|
|
||||||
$this->save();
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
} catch (PhabricatorMetaMTAPermanentFailureException $ex) {
|
|
||||||
$this
|
|
||||||
->setStatus(PhabricatorMailOutboundStatus::STATUS_FAIL)
|
|
||||||
->setMessage($ex->getMessage())
|
|
||||||
->save();
|
|
||||||
|
|
||||||
throw $ex;
|
|
||||||
} catch (Exception $ex) {
|
|
||||||
$this
|
|
||||||
->setMessage($ex->getMessage()."\n".$ex->getTraceAsString())
|
|
||||||
->save();
|
|
||||||
|
|
||||||
throw $ex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateThreadIndex($seed, $is_first_mail) {
|
private function generateThreadIndex($seed, $is_first_mail) {
|
||||||
@@ -727,7 +996,7 @@ final class PhabricatorMetaMTAMail
|
|||||||
return base64_encode($base);
|
return base64_encode($base);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function shouldMultiplexAllMail() {
|
public static function shouldMailEachRecipient() {
|
||||||
return PhabricatorEnv::getEnvConfig('metamta.one-mail-per-recipient');
|
return PhabricatorEnv::getEnvConfig('metamta.one-mail-per-recipient');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,6 +1122,18 @@ final class PhabricatorMetaMTAMail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exclude muted recipients. We're doing this after saving deliverability
|
||||||
|
// so that Herald "Send me an email" actions can still punch through a
|
||||||
|
// mute.
|
||||||
|
|
||||||
|
foreach ($this->getMutedPHIDs() as $muted_phid) {
|
||||||
|
$muted_actor = idx($actors, $muted_phid);
|
||||||
|
if (!$muted_actor) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$muted_actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_MUTED);
|
||||||
|
}
|
||||||
|
|
||||||
// For the rest of the rules, order matters. We're going to run all the
|
// For the rest of the rules, order matters. We're going to run all the
|
||||||
// possible rules in order from weakest to strongest, and let the strongest
|
// possible rules in order from weakest to strongest, and let the strongest
|
||||||
// matching rule win. The weaker rules leave annotations behind which help
|
// matching rule win. The weaker rules leave annotations behind which help
|
||||||
@@ -979,20 +1260,6 @@ final class PhabricatorMetaMTAMail
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
|
||||||
$this->openTransaction();
|
|
||||||
queryfx(
|
|
||||||
$this->establishConnection('w'),
|
|
||||||
'DELETE FROM %T WHERE src = %s AND type = %d',
|
|
||||||
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
|
|
||||||
$this->getPHID(),
|
|
||||||
PhabricatorMetaMTAMailHasRecipientEdgeType::EDGECONST);
|
|
||||||
$ret = parent::delete();
|
|
||||||
$this->saveTransaction();
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generateHeaders() {
|
public function generateHeaders() {
|
||||||
$headers = array();
|
$headers = array();
|
||||||
|
|
||||||
@@ -1002,8 +1269,6 @@ final class PhabricatorMetaMTAMail
|
|||||||
// Some clients respect this to suppress OOF and other auto-responses.
|
// Some clients respect this to suppress OOF and other auto-responses.
|
||||||
$headers[] = array('X-Auto-Response-Suppress', 'All');
|
$headers[] = array('X-Auto-Response-Suppress', 'All');
|
||||||
|
|
||||||
// If the message has mailtags, filter out any recipients who don't want
|
|
||||||
// to receive this type of mail.
|
|
||||||
$mailtags = $this->getParam('mailtags');
|
$mailtags = $this->getParam('mailtags');
|
||||||
if ($mailtags) {
|
if ($mailtags) {
|
||||||
$tag_header = array();
|
$tag_header = array();
|
||||||
@@ -1028,6 +1293,15 @@ final class PhabricatorMetaMTAMail
|
|||||||
$headers[] = array('Precedence', 'bulk');
|
$headers[] = array('Precedence', 'bulk');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->getMustEncrypt()) {
|
||||||
|
$headers[] = array('X-Phabricator-Must-Encrypt', 'Yes');
|
||||||
|
}
|
||||||
|
|
||||||
|
$related_phid = $this->getRelatedPHID();
|
||||||
|
if ($related_phid) {
|
||||||
|
$headers[] = array('Thread-Topic', $related_phid);
|
||||||
|
}
|
||||||
|
|
||||||
return $headers;
|
return $headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,6 +1309,19 @@ final class PhabricatorMetaMTAMail
|
|||||||
return $this->getParam('headers.sent');
|
return $this->getParam('headers.sent');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUnfilteredHeaders() {
|
||||||
|
$unfiltered = $this->getParam('headers.unfiltered');
|
||||||
|
|
||||||
|
if ($unfiltered === null) {
|
||||||
|
// Older versions of Phabricator did not filter headers, and thus did
|
||||||
|
// not record unfiltered headers. If we don't have unfiltered header
|
||||||
|
// data just return the delivered headers for compatibility.
|
||||||
|
return $this->getDeliveredHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $unfiltered;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDeliveredActors() {
|
public function getDeliveredActors() {
|
||||||
return $this->getParam('actors.sent');
|
return $this->getParam('actors.sent');
|
||||||
}
|
}
|
||||||
@@ -1047,6 +1334,55 @@ final class PhabricatorMetaMTAMail
|
|||||||
return $this->getParam('routingmap.sent');
|
return $this->getParam('routingmap.sent');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDeliveredBody() {
|
||||||
|
return $this->getParam('body.sent');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function filterHeaders(array $headers, $must_encrypt) {
|
||||||
|
if (!$must_encrypt) {
|
||||||
|
return $headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
$whitelist = array(
|
||||||
|
'In-Reply-To',
|
||||||
|
'Message-ID',
|
||||||
|
'Precedence',
|
||||||
|
'References',
|
||||||
|
'Thread-Index',
|
||||||
|
'Thread-Topic',
|
||||||
|
|
||||||
|
'X-Mail-Transport-Agent',
|
||||||
|
'X-Auto-Response-Suppress',
|
||||||
|
|
||||||
|
'X-Phabricator-Sent-This-Message',
|
||||||
|
'X-Phabricator-Must-Encrypt',
|
||||||
|
);
|
||||||
|
|
||||||
|
// NOTE: The major header we want to drop is "X-Phabricator-Mail-Tags".
|
||||||
|
// This header contains a significant amount of meaningful information
|
||||||
|
// about the object.
|
||||||
|
|
||||||
|
$whitelist_map = array();
|
||||||
|
foreach ($whitelist as $term) {
|
||||||
|
$whitelist_map[phutil_utf8_strtolower($term)] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($headers as $key => $header) {
|
||||||
|
list($name, $value) = $header;
|
||||||
|
$name = phutil_utf8_strtolower($name);
|
||||||
|
|
||||||
|
if (!isset($whitelist_map[$name])) {
|
||||||
|
unset($headers[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getURI() {
|
||||||
|
return '/mail/detail/'.$this->getID().'/';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Routing )------------------------------------------------------------ */
|
/* -( Routing )------------------------------------------------------------ */
|
||||||
|
|
||||||
@@ -1121,7 +1457,7 @@ final class PhabricatorMetaMTAMail
|
|||||||
private function loadPreferences($target_phid) {
|
private function loadPreferences($target_phid) {
|
||||||
$viewer = PhabricatorUser::getOmnipotentUser();
|
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||||
|
|
||||||
if (self::shouldMultiplexAllMail()) {
|
if (self::shouldMailEachRecipient()) {
|
||||||
$preferences = id(new PhabricatorUserPreferencesQuery())
|
$preferences = id(new PhabricatorUserPreferencesQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withUserPHIDs(array($target_phid))
|
->withUserPHIDs(array($target_phid))
|
||||||
@@ -1156,6 +1492,14 @@ final class PhabricatorMetaMTAMail
|
|||||||
return ($value == PhabricatorEmailFormatSetting::VALUE_HTML_EMAIL);
|
return ($value == PhabricatorEmailFormatSetting::VALUE_HTML_EMAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function shouldRenderMailStampsInBody($viewer) {
|
||||||
|
$preferences = $this->loadPreferences($viewer->getPHID());
|
||||||
|
$value = $preferences->getSettingValue(
|
||||||
|
PhabricatorEmailStampsSetting::SETTINGKEY);
|
||||||
|
|
||||||
|
return ($value == PhabricatorEmailStampsSetting::VALUE_BODY_STAMPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
@@ -1181,4 +1525,18 @@ final class PhabricatorMetaMTAMail
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function destroyObjectPermanently(
|
||||||
|
PhabricatorDestructionEngine $engine) {
|
||||||
|
|
||||||
|
$files = $this->loadAttachedFiles($engine->getViewer());
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$engine->destroyObject($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->delete();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user