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(
|
||||
'conpherence.pkg.css' => 'e68cf1fa',
|
||||
'conpherence.pkg.js' => '15191c65',
|
||||
'core.pkg.css' => '144d9932',
|
||||
'core.pkg.js' => '4c79d74f',
|
||||
'core.pkg.css' => '07cdfee8',
|
||||
'core.pkg.js' => '3ac6e174',
|
||||
'darkconsole.pkg.js' => '1f9a31bc',
|
||||
'differential.pkg.css' => '45951e9e',
|
||||
'differential.pkg.js' => '19ee9979',
|
||||
'differential.pkg.css' => '113e692c',
|
||||
'differential.pkg.js' => '5d53d5ce',
|
||||
'diffusion.pkg.css' => 'a2d17c7d',
|
||||
'diffusion.pkg.js' => '6134c5a1',
|
||||
'favicon.ico' => '4d48ee79',
|
||||
@@ -31,7 +31,7 @@ return array(
|
||||
'rsrc/css/aphront/multi-column.css' => '84cc6640',
|
||||
'rsrc/css/aphront/notification.css' => '457861ec',
|
||||
'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/tokenizer.css' => '15d5ff71',
|
||||
'rsrc/css/aphront/tooltip.css' => '173b9431',
|
||||
@@ -121,7 +121,7 @@ return array(
|
||||
'rsrc/css/font/font-awesome.css' => 'e838e088',
|
||||
'rsrc/css/font/font-lato.css' => 'c7ccd872',
|
||||
'rsrc/css/font/phui-font-icon-base.css' => '870a7360',
|
||||
'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82',
|
||||
'rsrc/css/layout/phabricator-filetree-view.css' => 'b912ad97',
|
||||
'rsrc/css/layout/phabricator-source-code-view.css' => 'aea41829',
|
||||
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
|
||||
'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-list-view.css' => '6ae18df0',
|
||||
'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-badge.css' => '22c0cf4f',
|
||||
'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-status.css' => 'd5263e49',
|
||||
'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/workboards/phui-workboard-color.css' => '783cdff5',
|
||||
'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-query-panel-select.js' => '453c5375',
|
||||
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
|
||||
'rsrc/js/application/diff/DiffChangeset.js' => '99abf4cd',
|
||||
'rsrc/js/application/diff/DiffChangesetList.js' => '3b77efdd',
|
||||
'rsrc/js/application/diff/DiffChangeset.js' => 'b49b59d6',
|
||||
'rsrc/js/application/diff/DiffChangesetList.js' => '1f2e5265',
|
||||
'rsrc/js/application/diff/DiffInline.js' => 'e83d28f3',
|
||||
'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832',
|
||||
'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-object-selector.js' => '77c1f0b0',
|
||||
'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-read-only-warning.js' => 'ba158207',
|
||||
'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b',
|
||||
@@ -534,7 +534,7 @@ return array(
|
||||
'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac',
|
||||
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03',
|
||||
'rsrc/js/phuix/PHUIXExample.js' => '68af71ca',
|
||||
'rsrc/js/phuix/PHUIXFormControl.js' => '1dd0870c',
|
||||
'rsrc/js/phuix/PHUIXFormControl.js' => '16ad6224',
|
||||
'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b',
|
||||
),
|
||||
'symbols' => array(
|
||||
@@ -659,7 +659,7 @@ return array(
|
||||
'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0',
|
||||
'javelin-behavior-phabricator-keyboard-shortcuts' => '01fca1f0',
|
||||
'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-object-selector' => '77c1f0b0',
|
||||
'javelin-behavior-phabricator-oncopy' => '2926fff2',
|
||||
@@ -768,7 +768,7 @@ return array(
|
||||
'path-typeahead' => 'f7fc67ec',
|
||||
'people-picture-menu-item-css' => 'a06f7f34',
|
||||
'people-profile-css' => '4df76faf',
|
||||
'phabricator-action-list-view-css' => 'f7f61a34',
|
||||
'phabricator-action-list-view-css' => '0bcd9a45',
|
||||
'phabricator-busy' => '59a7976a',
|
||||
'phabricator-chatlog-css' => 'd295b020',
|
||||
'phabricator-content-source-view-css' => '4b8b05d4',
|
||||
@@ -777,8 +777,8 @@ return array(
|
||||
'phabricator-darklog' => 'c8e1ffe3',
|
||||
'phabricator-darkmessage' => 'c48cccdd',
|
||||
'phabricator-dashboard-css' => 'fe5b1869',
|
||||
'phabricator-diff-changeset' => '99abf4cd',
|
||||
'phabricator-diff-changeset-list' => '3b77efdd',
|
||||
'phabricator-diff-changeset' => 'b49b59d6',
|
||||
'phabricator-diff-changeset-list' => '1f2e5265',
|
||||
'phabricator-diff-inline' => 'e83d28f3',
|
||||
'phabricator-drag-and-drop-file-upload' => '58dea2fa',
|
||||
'phabricator-draggable-list' => 'bea6e7f4',
|
||||
@@ -786,12 +786,12 @@ return array(
|
||||
'phabricator-favicon' => '1fe2510c',
|
||||
'phabricator-feed-css' => 'ecd4ec57',
|
||||
'phabricator-file-upload' => '680ea2c8',
|
||||
'phabricator-filetree-view-css' => 'fccf9f82',
|
||||
'phabricator-filetree-view-css' => 'b912ad97',
|
||||
'phabricator-flag-css' => 'bba8f811',
|
||||
'phabricator-keyboard-shortcut' => '1ae869f2',
|
||||
'phabricator-keyboard-shortcut-manager' => 'c19dd9b9',
|
||||
'phabricator-main-menu-view' => '7821ca89',
|
||||
'phabricator-nav-view-css' => 'faf6a6fc',
|
||||
'phabricator-nav-view-css' => '028126f6',
|
||||
'phabricator-notification' => '008faf9c',
|
||||
'phabricator-notification-css' => '457861ec',
|
||||
'phabricator-notification-menu-css' => '10685bd4',
|
||||
@@ -876,7 +876,7 @@ return array(
|
||||
'phui-status-list-view-css' => 'd5263e49',
|
||||
'phui-tag-view-css' => 'b4719c50',
|
||||
'phui-theme-css' => '9f261c6b',
|
||||
'phui-timeline-view-css' => 'e2ef62b1',
|
||||
'phui-timeline-view-css' => '6ddf8126',
|
||||
'phui-two-column-view-css' => '44ec4951',
|
||||
'phui-workboard-color-css' => '783cdff5',
|
||||
'phui-workboard-view-css' => '3bc85455',
|
||||
@@ -887,7 +887,7 @@ return array(
|
||||
'phuix-autocomplete' => 'e0731603',
|
||||
'phuix-button-view' => '8a91e1ac',
|
||||
'phuix-dropdown-menu' => '04b2ae03',
|
||||
'phuix-form-control-view' => '1dd0870c',
|
||||
'phuix-form-control-view' => '16ad6224',
|
||||
'phuix-icon-view' => 'bff6884b',
|
||||
'policy-css' => '957ea14c',
|
||||
'policy-edit-css' => '815c66f7',
|
||||
@@ -998,6 +998,10 @@ return array(
|
||||
'aphront-typeahead-control-css',
|
||||
'phui-tag-view-css',
|
||||
),
|
||||
'16ad6224' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
),
|
||||
'17bb8539' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
@@ -1029,10 +1033,6 @@ return array(
|
||||
'javelin-request',
|
||||
'javelin-uri',
|
||||
),
|
||||
'1dd0870c' => array(
|
||||
'javelin-install',
|
||||
'javelin-dom',
|
||||
),
|
||||
'1e911d0f' => array(
|
||||
'javelin-stratcom',
|
||||
'javelin-request',
|
||||
@@ -1044,6 +1044,10 @@ return array(
|
||||
'javelin-uri',
|
||||
'javelin-routable',
|
||||
),
|
||||
'1f2e5265' => array(
|
||||
'javelin-install',
|
||||
'phuix-button-view',
|
||||
),
|
||||
'1f6794f6' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
@@ -1143,10 +1147,6 @@ return array(
|
||||
'javelin-dom',
|
||||
'javelin-magical-init',
|
||||
),
|
||||
'3b77efdd' => array(
|
||||
'javelin-install',
|
||||
'phuix-button-view',
|
||||
),
|
||||
'3cb0b2fc' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-dom',
|
||||
@@ -1564,6 +1564,16 @@ return array(
|
||||
'7f243deb' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
'81144dfa' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-behavior-device',
|
||||
'javelin-stratcom',
|
||||
'javelin-dom',
|
||||
'javelin-magical-init',
|
||||
'javelin-vector',
|
||||
'javelin-request',
|
||||
'javelin-util',
|
||||
),
|
||||
'834a1173' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-scrollbar',
|
||||
@@ -1651,16 +1661,6 @@ return array(
|
||||
'javelin-workflow',
|
||||
'javelin-dom',
|
||||
),
|
||||
'947753e0' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-behavior-device',
|
||||
'javelin-stratcom',
|
||||
'javelin-dom',
|
||||
'javelin-magical-init',
|
||||
'javelin-vector',
|
||||
'javelin-request',
|
||||
'javelin-util',
|
||||
),
|
||||
'949c0fe5' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
@@ -1681,17 +1681,6 @@ return array(
|
||||
'javelin-mask',
|
||||
'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(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
@@ -1840,6 +1829,17 @@ return array(
|
||||
'b3e7d692' => array(
|
||||
'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(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
|
||||
@@ -1622,5 +1622,9 @@
|
||||
"zipper_mouth": "\ud83e\udd10",
|
||||
"zzz": "\ud83d\udca4",
|
||||
"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',
|
||||
'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php',
|
||||
'DifferentialLocalCommitsView' => 'applications/differential/view/DifferentialLocalCommitsView.php',
|
||||
'DifferentialMailEngineExtension' => 'applications/differential/engineextension/DifferentialMailEngineExtension.php',
|
||||
'DifferentialMailView' => 'applications/differential/mail/DifferentialMailView.php',
|
||||
'DifferentialManiphestTasksField' => 'applications/differential/customfield/DifferentialManiphestTasksField.php',
|
||||
'DifferentialModernHunk' => 'applications/differential/storage/DifferentialModernHunk.php',
|
||||
@@ -1345,6 +1346,7 @@ phutil_register_library_map(array(
|
||||
'HarbormasterWaitForPreviousBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterWaitForPreviousBuildStepImplementation.php',
|
||||
'HarbormasterWorker' => 'applications/harbormaster/worker/HarbormasterWorker.php',
|
||||
'HarbormasterWorkingCopyArtifact' => 'applications/harbormaster/artifact/HarbormasterWorkingCopyArtifact.php',
|
||||
'HeraldActingUserField' => 'applications/herald/field/HeraldActingUserField.php',
|
||||
'HeraldAction' => 'applications/herald/action/HeraldAction.php',
|
||||
'HeraldActionGroup' => 'applications/herald/action/HeraldActionGroup.php',
|
||||
'HeraldActionRecord' => 'applications/herald/storage/HeraldActionRecord.php',
|
||||
@@ -1525,13 +1527,10 @@ phutil_register_library_map(array(
|
||||
'ManiphestEditProjectsCapability' => 'applications/maniphest/capability/ManiphestEditProjectsCapability.php',
|
||||
'ManiphestEditStatusCapability' => 'applications/maniphest/capability/ManiphestEditStatusCapability.php',
|
||||
'ManiphestEmailCommand' => 'applications/maniphest/command/ManiphestEmailCommand.php',
|
||||
'ManiphestExcelDefaultFormat' => 'applications/maniphest/export/ManiphestExcelDefaultFormat.php',
|
||||
'ManiphestExcelFormat' => 'applications/maniphest/export/ManiphestExcelFormat.php',
|
||||
'ManiphestExcelFormatTestCase' => 'applications/maniphest/export/__tests__/ManiphestExcelFormatTestCase.php',
|
||||
'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php',
|
||||
'ManiphestGetTaskTransactionsConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestGetTaskTransactionsConduitAPIMethod.php',
|
||||
'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php',
|
||||
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
|
||||
'ManiphestMailEngineExtension' => 'applications/maniphest/engineextension/ManiphestMailEngineExtension.php',
|
||||
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
|
||||
'ManiphestPointsConfigType' => 'applications/maniphest/config/ManiphestPointsConfigType.php',
|
||||
'ManiphestPrioritiesConfigType' => 'applications/maniphest/config/ManiphestPrioritiesConfigType.php',
|
||||
@@ -1965,6 +1964,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
|
||||
'PhabricatorApplicationEditor' => 'applications/meta/editor/PhabricatorApplicationEditor.php',
|
||||
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
|
||||
'PhabricatorApplicationObjectMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorApplicationObjectMailEngineExtension.php',
|
||||
'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php',
|
||||
'PhabricatorApplicationPolicyChangeTransaction' => 'applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php',
|
||||
'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php',
|
||||
@@ -2226,6 +2226,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorBoardResponseEngine' => 'applications/project/engine/PhabricatorBoardResponseEngine.php',
|
||||
'PhabricatorBoolConfigType' => 'applications/config/type/PhabricatorBoolConfigType.php',
|
||||
'PhabricatorBoolEditField' => 'applications/transactions/editfield/PhabricatorBoolEditField.php',
|
||||
'PhabricatorBoolMailStamp' => 'applications/metamta/stamp/PhabricatorBoolMailStamp.php',
|
||||
'PhabricatorBritishEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorBritishEnglishTranslation.php',
|
||||
'PhabricatorBuildbotController' => 'extensions/buildbot/controller/PhabricatorBuildbotController.php',
|
||||
'PhabricatorBuiltinDraftEngine' => 'applications/transactions/draft/PhabricatorBuiltinDraftEngine.php',
|
||||
@@ -2234,9 +2235,10 @@ phutil_register_library_map(array(
|
||||
'PhabricatorBulkContentSource' => 'infrastructure/daemon/contentsource/PhabricatorBulkContentSource.php',
|
||||
'PhabricatorBulkEditGroup' => 'applications/transactions/bulk/PhabricatorBulkEditGroup.php',
|
||||
'PhabricatorBulkEngine' => 'applications/transactions/bulk/PhabricatorBulkEngine.php',
|
||||
'PhabricatorBulkManagementExportWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementExportWorkflow.php',
|
||||
'PhabricatorBulkManagementMakeSilentWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementMakeSilentWorkflow.php',
|
||||
'PhabricatorBulkManagementWorkflow' => 'applications/transactions/bulk/management/PhabricatorBulkManagementWorkflow.php',
|
||||
'PhabricatorCSVExportFormat' => 'infrastructure/export/PhabricatorCSVExportFormat.php',
|
||||
'PhabricatorCSVExportFormat' => 'infrastructure/export/format/PhabricatorCSVExportFormat.php',
|
||||
'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php',
|
||||
'PhabricatorCacheEngine' => 'applications/system/engine/PhabricatorCacheEngine.php',
|
||||
'PhabricatorCacheEngineExtension' => 'applications/system/engine/PhabricatorCacheEngineExtension.php',
|
||||
@@ -2414,6 +2416,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorClusterExceptionHandler' => 'infrastructure/cluster/exception/PhabricatorClusterExceptionHandler.php',
|
||||
'PhabricatorClusterImpossibleWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImpossibleWriteException.php',
|
||||
'PhabricatorClusterImproperWriteException' => 'infrastructure/cluster/exception/PhabricatorClusterImproperWriteException.php',
|
||||
'PhabricatorClusterMailersConfigType' => 'infrastructure/cluster/config/PhabricatorClusterMailersConfigType.php',
|
||||
'PhabricatorClusterNoHostForRoleException' => 'infrastructure/cluster/exception/PhabricatorClusterNoHostForRoleException.php',
|
||||
'PhabricatorClusterSearchConfigType' => 'infrastructure/cluster/config/PhabricatorClusterSearchConfigType.php',
|
||||
'PhabricatorClusterServiceHealthRecord' => 'infrastructure/cluster/PhabricatorClusterServiceHealthRecord.php',
|
||||
@@ -2432,6 +2435,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorCommonPasswords' => 'applications/auth/constants/PhabricatorCommonPasswords.php',
|
||||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
||||
'PhabricatorConduitApplication' => 'applications/conduit/application/PhabricatorConduitApplication.php',
|
||||
'PhabricatorConduitCallManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitCallManagementWorkflow.php',
|
||||
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
||||
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
||||
'PhabricatorConduitContentSource' => 'infrastructure/contentsource/PhabricatorConduitContentSource.php',
|
||||
@@ -2442,6 +2446,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php',
|
||||
'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php',
|
||||
'PhabricatorConduitLogSearchEngine' => 'applications/conduit/query/PhabricatorConduitLogSearchEngine.php',
|
||||
'PhabricatorConduitManagementWorkflow' => 'applications/conduit/management/PhabricatorConduitManagementWorkflow.php',
|
||||
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php',
|
||||
'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php',
|
||||
'PhabricatorConduitRequestExceptionHandler' => 'aphront/handler/PhabricatorConduitRequestExceptionHandler.php',
|
||||
@@ -2587,6 +2592,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorCustomFieldEditEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldEditEngineExtension.php',
|
||||
'PhabricatorCustomFieldEditField' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditField.php',
|
||||
'PhabricatorCustomFieldEditType' => 'infrastructure/customfield/editor/PhabricatorCustomFieldEditType.php',
|
||||
'PhabricatorCustomFieldExportEngineExtension' => 'infrastructure/export/engine/PhabricatorCustomFieldExportEngineExtension.php',
|
||||
'PhabricatorCustomFieldFulltextEngineExtension' => 'infrastructure/customfield/engineextension/PhabricatorCustomFieldFulltextEngineExtension.php',
|
||||
'PhabricatorCustomFieldHeraldAction' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldAction.php',
|
||||
'PhabricatorCustomFieldHeraldActionGroup' => 'infrastructure/customfield/herald/PhabricatorCustomFieldHeraldActionGroup.php',
|
||||
@@ -2751,6 +2757,8 @@ phutil_register_library_map(array(
|
||||
'PhabricatorDraftEngine' => 'applications/transactions/draft/PhabricatorDraftEngine.php',
|
||||
'PhabricatorDraftInterface' => 'applications/transactions/draft/PhabricatorDraftInterface.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',
|
||||
'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php',
|
||||
'PhabricatorEdgeCycleException' => 'infrastructure/edges/exception/PhabricatorEdgeCycleException.php',
|
||||
@@ -2814,6 +2822,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorEditPage' => 'applications/transactions/editengine/PhabricatorEditPage.php',
|
||||
'PhabricatorEditType' => 'applications/transactions/edittype/PhabricatorEditType.php',
|
||||
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
|
||||
'PhabricatorEditorMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditorMailEngineExtension.php',
|
||||
'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php',
|
||||
'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php',
|
||||
'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php',
|
||||
@@ -2830,6 +2839,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorEmailPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorEmailPreferencesSettingsPanel.php',
|
||||
'PhabricatorEmailRePrefixSetting' => 'applications/settings/setting/PhabricatorEmailRePrefixSetting.php',
|
||||
'PhabricatorEmailSelfActionsSetting' => 'applications/settings/setting/PhabricatorEmailSelfActionsSetting.php',
|
||||
'PhabricatorEmailStampsSetting' => 'applications/settings/setting/PhabricatorEmailStampsSetting.php',
|
||||
'PhabricatorEmailTagsSetting' => 'applications/settings/setting/PhabricatorEmailTagsSetting.php',
|
||||
'PhabricatorEmailVarySubjectsSetting' => 'applications/settings/setting/PhabricatorEmailVarySubjectsSetting.php',
|
||||
'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php',
|
||||
@@ -2842,15 +2852,20 @@ phutil_register_library_map(array(
|
||||
'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php',
|
||||
'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php',
|
||||
'PhabricatorEpochEditField' => 'applications/transactions/editfield/PhabricatorEpochEditField.php',
|
||||
'PhabricatorEpochExportField' => 'infrastructure/export/PhabricatorEpochExportField.php',
|
||||
'PhabricatorEpochExportField' => 'infrastructure/export/field/PhabricatorEpochExportField.php',
|
||||
'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php',
|
||||
'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php',
|
||||
'PhabricatorEventListener' => 'infrastructure/events/PhabricatorEventListener.php',
|
||||
'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php',
|
||||
'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php',
|
||||
'PhabricatorExcelExportFormat' => 'infrastructure/export/format/PhabricatorExcelExportFormat.php',
|
||||
'PhabricatorExecFutureFileUploadSource' => 'applications/files/uploadsource/PhabricatorExecFutureFileUploadSource.php',
|
||||
'PhabricatorExportField' => 'infrastructure/export/PhabricatorExportField.php',
|
||||
'PhabricatorExportFormat' => 'infrastructure/export/PhabricatorExportFormat.php',
|
||||
'PhabricatorExportEngine' => 'infrastructure/export/engine/PhabricatorExportEngine.php',
|
||||
'PhabricatorExportEngineBulkJobType' => 'infrastructure/export/engine/PhabricatorExportEngineBulkJobType.php',
|
||||
'PhabricatorExportEngineExtension' => 'infrastructure/export/engine/PhabricatorExportEngineExtension.php',
|
||||
'PhabricatorExportField' => 'infrastructure/export/field/PhabricatorExportField.php',
|
||||
'PhabricatorExportFormat' => 'infrastructure/export/format/PhabricatorExportFormat.php',
|
||||
'PhabricatorExportFormatSetting' => 'infrastructure/export/engine/PhabricatorExportFormatSetting.php',
|
||||
'PhabricatorExtendedPolicyInterface' => 'applications/policy/interface/PhabricatorExtendedPolicyInterface.php',
|
||||
'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php',
|
||||
'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php',
|
||||
@@ -3020,6 +3035,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorGDSetupCheck' => 'applications/config/check/PhabricatorGDSetupCheck.php',
|
||||
'PhabricatorGarbageCollector' => 'infrastructure/daemon/garbagecollector/PhabricatorGarbageCollector.php',
|
||||
'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCollectWorkflow.php',
|
||||
'PhabricatorGarbageCollectorManagementCompactEdgesWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementCompactEdgesWorkflow.php',
|
||||
'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementSetPolicyWorkflow.php',
|
||||
'PhabricatorGarbageCollectorManagementWorkflow' => 'infrastructure/daemon/garbagecollector/management/PhabricatorGarbageCollectorManagementWorkflow.php',
|
||||
'PhabricatorGeneralCachePurger' => 'applications/cache/purger/PhabricatorGeneralCachePurger.php',
|
||||
@@ -3070,7 +3086,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorHomeProfileMenuItem' => 'applications/home/menuitem/PhabricatorHomeProfileMenuItem.php',
|
||||
'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php',
|
||||
'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php',
|
||||
'PhabricatorIDExportField' => 'infrastructure/export/PhabricatorIDExportField.php',
|
||||
'PhabricatorIDExportField' => 'infrastructure/export/field/PhabricatorIDExportField.php',
|
||||
'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php',
|
||||
'PhabricatorIDsSearchField' => 'applications/search/field/PhabricatorIDsSearchField.php',
|
||||
'PhabricatorIconDatasource' => 'applications/files/typeahead/PhabricatorIconDatasource.php',
|
||||
@@ -3094,7 +3110,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
|
||||
'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php',
|
||||
'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php',
|
||||
'PhabricatorIntExportField' => 'infrastructure/export/PhabricatorIntExportField.php',
|
||||
'PhabricatorIntExportField' => 'infrastructure/export/field/PhabricatorIntExportField.php',
|
||||
'PhabricatorInternalSetting' => 'applications/settings/setting/PhabricatorInternalSetting.php',
|
||||
'PhabricatorInternationalizationManagementExtractWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php',
|
||||
'PhabricatorInternationalizationManagementWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementWorkflow.php',
|
||||
@@ -3104,7 +3120,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorIteratorFileUploadSource' => 'applications/files/uploadsource/PhabricatorIteratorFileUploadSource.php',
|
||||
'PhabricatorJIRAAuthProvider' => 'applications/auth/provider/PhabricatorJIRAAuthProvider.php',
|
||||
'PhabricatorJSONConfigType' => 'applications/config/type/PhabricatorJSONConfigType.php',
|
||||
'PhabricatorJSONExportFormat' => 'infrastructure/export/PhabricatorJSONExportFormat.php',
|
||||
'PhabricatorJSONExportFormat' => 'infrastructure/export/format/PhabricatorJSONExportFormat.php',
|
||||
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
|
||||
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
|
||||
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
|
||||
@@ -3127,9 +3143,11 @@ phutil_register_library_map(array(
|
||||
'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php',
|
||||
'PhabricatorLipsumMondrianArtist' => 'applications/lipsum/image/PhabricatorLipsumMondrianArtist.php',
|
||||
'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php',
|
||||
'PhabricatorLiskExportEngineExtension' => 'infrastructure/export/engine/PhabricatorLiskExportEngineExtension.php',
|
||||
'PhabricatorLiskFulltextEngineExtension' => 'applications/search/engineextension/PhabricatorLiskFulltextEngineExtension.php',
|
||||
'PhabricatorLiskSearchEngineExtension' => 'applications/search/engineextension/PhabricatorLiskSearchEngineExtension.php',
|
||||
'PhabricatorLiskSerializer' => 'infrastructure/storage/lisk/PhabricatorLiskSerializer.php',
|
||||
'PhabricatorListExportField' => 'infrastructure/export/field/PhabricatorListExportField.php',
|
||||
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php',
|
||||
'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php',
|
||||
'PhabricatorLocaleScopeGuard' => 'infrastructure/internationalization/scope/PhabricatorLocaleScopeGuard.php',
|
||||
@@ -3165,14 +3183,17 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
|
||||
'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php',
|
||||
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
|
||||
'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php',
|
||||
'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php',
|
||||
'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php',
|
||||
'PhabricatorMailEmailSubjectHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailSubjectHeraldField.php',
|
||||
'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php',
|
||||
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php',
|
||||
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php',
|
||||
'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php',
|
||||
'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php',
|
||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
|
||||
'PhabricatorMailImplementationPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPostmarkAdapter.php',
|
||||
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
|
||||
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php',
|
||||
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
|
||||
@@ -3185,6 +3206,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php',
|
||||
'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php',
|
||||
'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php',
|
||||
'PhabricatorMailMustEncryptHeraldAction' => 'applications/metamta/herald/PhabricatorMailMustEncryptHeraldAction.php',
|
||||
'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php',
|
||||
'PhabricatorMailOutboundRoutingHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingHeraldAction.php',
|
||||
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
|
||||
@@ -3195,6 +3217,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
||||
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
||||
'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php',
|
||||
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
|
||||
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
||||
'PhabricatorMailgunConfigOptions' => 'applications/config/option/PhabricatorMailgunConfigOptions.php',
|
||||
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
||||
@@ -3254,6 +3277,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php',
|
||||
'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php',
|
||||
'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php',
|
||||
'PhabricatorMetaMTAPostmarkReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php',
|
||||
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php',
|
||||
'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php',
|
||||
'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php',
|
||||
@@ -3271,6 +3295,8 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php',
|
||||
'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php',
|
||||
'PhabricatorMustVerifyEmailController' => 'applications/auth/controller/PhabricatorMustVerifyEmailController.php',
|
||||
'PhabricatorMutedByEdgeType' => 'applications/transactions/edges/PhabricatorMutedByEdgeType.php',
|
||||
'PhabricatorMutedEdgeType' => 'applications/transactions/edges/PhabricatorMutedEdgeType.php',
|
||||
'PhabricatorMySQLConfigOptions' => 'applications/config/option/PhabricatorMySQLConfigOptions.php',
|
||||
'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php',
|
||||
'PhabricatorMySQLSearchHost' => 'infrastructure/cluster/search/PhabricatorMySQLSearchHost.php',
|
||||
@@ -3424,10 +3450,12 @@ phutil_register_library_map(array(
|
||||
'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php',
|
||||
'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php',
|
||||
'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php',
|
||||
'PhabricatorPHIDExportField' => 'infrastructure/export/PhabricatorPHIDExportField.php',
|
||||
'PhabricatorPHIDExportField' => 'infrastructure/export/field/PhabricatorPHIDExportField.php',
|
||||
'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php',
|
||||
'PhabricatorPHIDListEditField' => 'applications/transactions/editfield/PhabricatorPHIDListEditField.php',
|
||||
'PhabricatorPHIDListEditType' => 'applications/transactions/edittype/PhabricatorPHIDListEditType.php',
|
||||
'PhabricatorPHIDListExportField' => 'infrastructure/export/field/PhabricatorPHIDListExportField.php',
|
||||
'PhabricatorPHIDMailStamp' => 'applications/metamta/stamp/PhabricatorPHIDMailStamp.php',
|
||||
'PhabricatorPHIDResolver' => 'applications/phid/resolver/PhabricatorPHIDResolver.php',
|
||||
'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php',
|
||||
'PhabricatorPHIDTypeTestCase' => 'applications/phid/type/__tests__/PhabricatorPHIDTypeTestCase.php',
|
||||
@@ -3836,7 +3864,9 @@ phutil_register_library_map(array(
|
||||
'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php',
|
||||
'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php',
|
||||
'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php',
|
||||
'PhabricatorProjectsExportEngineExtension' => 'infrastructure/export/engine/PhabricatorProjectsExportEngineExtension.php',
|
||||
'PhabricatorProjectsFulltextEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsFulltextEngineExtension.php',
|
||||
'PhabricatorProjectsMailEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMailEngineExtension.php',
|
||||
'PhabricatorProjectsMembersSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsMembersSearchEngineAttachment.php',
|
||||
'PhabricatorProjectsMembershipIndexEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsMembershipIndexEngineExtension.php',
|
||||
'PhabricatorProjectsPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsPolicyRule.php',
|
||||
@@ -4128,8 +4158,10 @@ phutil_register_library_map(array(
|
||||
'PhabricatorSpacesController' => 'applications/spaces/controller/PhabricatorSpacesController.php',
|
||||
'PhabricatorSpacesDAO' => 'applications/spaces/storage/PhabricatorSpacesDAO.php',
|
||||
'PhabricatorSpacesEditController' => 'applications/spaces/controller/PhabricatorSpacesEditController.php',
|
||||
'PhabricatorSpacesExportEngineExtension' => 'infrastructure/export/engine/PhabricatorSpacesExportEngineExtension.php',
|
||||
'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php',
|
||||
'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php',
|
||||
'PhabricatorSpacesMailEngineExtension' => 'applications/spaces/engineextension/PhabricatorSpacesMailEngineExtension.php',
|
||||
'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php',
|
||||
'PhabricatorSpacesNamespaceArchiveTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php',
|
||||
'PhabricatorSpacesNamespaceDatasource' => 'applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php',
|
||||
@@ -4191,9 +4223,11 @@ phutil_register_library_map(array(
|
||||
'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php',
|
||||
'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php',
|
||||
'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php',
|
||||
'PhabricatorStringExportField' => 'infrastructure/export/PhabricatorStringExportField.php',
|
||||
'PhabricatorStringExportField' => 'infrastructure/export/field/PhabricatorStringExportField.php',
|
||||
'PhabricatorStringListConfigType' => 'applications/config/type/PhabricatorStringListConfigType.php',
|
||||
'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php',
|
||||
'PhabricatorStringListExportField' => 'infrastructure/export/field/PhabricatorStringListExportField.php',
|
||||
'PhabricatorStringMailStamp' => 'applications/metamta/stamp/PhabricatorStringMailStamp.php',
|
||||
'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php',
|
||||
'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php',
|
||||
'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php',
|
||||
@@ -4208,9 +4242,12 @@ phutil_register_library_map(array(
|
||||
'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php',
|
||||
'PhabricatorSubscriptionsEditEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsEditEngineExtension.php',
|
||||
'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php',
|
||||
'PhabricatorSubscriptionsExportEngineExtension' => 'infrastructure/export/engine/PhabricatorSubscriptionsExportEngineExtension.php',
|
||||
'PhabricatorSubscriptionsFulltextEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsFulltextEngineExtension.php',
|
||||
'PhabricatorSubscriptionsHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsHeraldAction.php',
|
||||
'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.php',
|
||||
'PhabricatorSubscriptionsMailEngineExtension' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsMailEngineExtension.php',
|
||||
'PhabricatorSubscriptionsMuteController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsMuteController.php',
|
||||
'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSelfHeraldAction.php',
|
||||
'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'applications/subscriptions/herald/PhabricatorSubscriptionsRemoveSubscribersHeraldAction.php',
|
||||
'PhabricatorSubscriptionsSearchEngineAttachment' => 'applications/subscriptions/engineextension/PhabricatorSubscriptionsSearchEngineAttachment.php',
|
||||
@@ -4255,7 +4292,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php',
|
||||
'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php',
|
||||
'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php',
|
||||
'PhabricatorTextExportFormat' => 'infrastructure/export/PhabricatorTextExportFormat.php',
|
||||
'PhabricatorTextExportFormat' => 'infrastructure/export/format/PhabricatorTextExportFormat.php',
|
||||
'PhabricatorTextListConfigType' => 'applications/config/type/PhabricatorTextListConfigType.php',
|
||||
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
|
||||
'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php',
|
||||
@@ -4320,6 +4357,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php',
|
||||
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/PhabricatorUIExampleRenderController.php',
|
||||
'PhabricatorUIExamplesApplication' => 'applications/uiexample/application/PhabricatorUIExamplesApplication.php',
|
||||
'PhabricatorURIExportField' => 'infrastructure/export/field/PhabricatorURIExportField.php',
|
||||
'PhabricatorUSEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php',
|
||||
'PhabricatorUnifiedDiffsSetting' => 'applications/settings/setting/PhabricatorUnifiedDiffsSetting.php',
|
||||
'PhabricatorUnitTestContentSource' => 'infrastructure/contentsource/PhabricatorUnitTestContentSource.php',
|
||||
@@ -4413,6 +4451,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorWorkerManagementWorkflow' => 'infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php',
|
||||
'PhabricatorWorkerPermanentFailureException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerPermanentFailureException.php',
|
||||
'PhabricatorWorkerSchemaSpec' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerSchemaSpec.php',
|
||||
'PhabricatorWorkerSingleBulkJobType' => 'infrastructure/daemon/workers/bulk/PhabricatorWorkerSingleBulkJobType.php',
|
||||
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTask.php',
|
||||
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTaskData.php',
|
||||
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php',
|
||||
@@ -5588,6 +5627,7 @@ phutil_register_library_map(array(
|
||||
'DifferentialLintField' => 'DifferentialHarbormasterField',
|
||||
'DifferentialLintStatus' => 'Phobject',
|
||||
'DifferentialLocalCommitsView' => 'AphrontView',
|
||||
'DifferentialMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'DifferentialMailView' => 'Phobject',
|
||||
'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField',
|
||||
'DifferentialModernHunk' => 'DifferentialHunk',
|
||||
@@ -6560,6 +6600,7 @@ phutil_register_library_map(array(
|
||||
'HarbormasterWaitForPreviousBuildStepImplementation' => 'HarbormasterBuildStepImplementation',
|
||||
'HarbormasterWorker' => 'PhabricatorWorker',
|
||||
'HarbormasterWorkingCopyArtifact' => 'HarbormasterDrydockLeaseArtifact',
|
||||
'HeraldActingUserField' => 'HeraldField',
|
||||
'HeraldAction' => 'Phobject',
|
||||
'HeraldActionGroup' => 'HeraldGroup',
|
||||
'HeraldActionRecord' => 'HeraldDAO',
|
||||
@@ -6772,13 +6813,10 @@ phutil_register_library_map(array(
|
||||
'ManiphestEditProjectsCapability' => 'PhabricatorPolicyCapability',
|
||||
'ManiphestEditStatusCapability' => 'PhabricatorPolicyCapability',
|
||||
'ManiphestEmailCommand' => 'MetaMTAEmailTransactionCommand',
|
||||
'ManiphestExcelDefaultFormat' => 'ManiphestExcelFormat',
|
||||
'ManiphestExcelFormat' => 'Phobject',
|
||||
'ManiphestExcelFormatTestCase' => 'PhabricatorTestCase',
|
||||
'ManiphestExportController' => 'ManiphestController',
|
||||
'ManiphestGetTaskTransactionsConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||
'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
|
||||
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||
'ManiphestMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'ManiphestNameIndex' => 'ManiphestDAO',
|
||||
'ManiphestPointsConfigType' => 'PhabricatorJSONConfigType',
|
||||
'ManiphestPrioritiesConfigType' => 'PhabricatorJSONConfigType',
|
||||
@@ -7265,6 +7303,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
|
||||
'PhabricatorApplicationEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationObjectMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationPolicyChangeTransaction' => 'PhabricatorApplicationTransactionType',
|
||||
'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
||||
@@ -7572,6 +7611,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorBoardResponseEngine' => 'Phobject',
|
||||
'PhabricatorBoolConfigType' => 'PhabricatorTextConfigType',
|
||||
'PhabricatorBoolEditField' => 'PhabricatorEditField',
|
||||
'PhabricatorBoolMailStamp' => 'PhabricatorMailStamp',
|
||||
'PhabricatorBritishEnglishTranslation' => 'PhutilTranslation',
|
||||
'PhabricatorBuildbotController' => 'PhabricatorController',
|
||||
'PhabricatorBuiltinDraftEngine' => 'PhabricatorDraftEngine',
|
||||
@@ -7580,6 +7620,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorBulkContentSource' => 'PhabricatorContentSource',
|
||||
'PhabricatorBulkEditGroup' => 'Phobject',
|
||||
'PhabricatorBulkEngine' => 'Phobject',
|
||||
'PhabricatorBulkManagementExportWorkflow' => 'PhabricatorBulkManagementWorkflow',
|
||||
'PhabricatorBulkManagementMakeSilentWorkflow' => 'PhabricatorBulkManagementWorkflow',
|
||||
'PhabricatorBulkManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorCSVExportFormat' => 'PhabricatorExportFormat',
|
||||
@@ -7803,6 +7844,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorClusterExceptionHandler' => 'PhabricatorRequestExceptionHandler',
|
||||
'PhabricatorClusterImpossibleWriteException' => 'PhabricatorClusterException',
|
||||
'PhabricatorClusterImproperWriteException' => 'PhabricatorClusterException',
|
||||
'PhabricatorClusterMailersConfigType' => 'PhabricatorJSONConfigType',
|
||||
'PhabricatorClusterNoHostForRoleException' => 'Exception',
|
||||
'PhabricatorClusterSearchConfigType' => 'PhabricatorJSONConfigType',
|
||||
'PhabricatorClusterServiceHealthRecord' => 'Phobject',
|
||||
@@ -7820,6 +7862,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorCommonPasswords' => 'Phobject',
|
||||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorConduitCallManagementWorkflow' => 'PhabricatorConduitManagementWorkflow',
|
||||
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
||||
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitContentSource' => 'PhabricatorContentSource',
|
||||
@@ -7830,6 +7873,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorConduitLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorConduitManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorConduitMethodCallLog' => array(
|
||||
'PhabricatorConduitDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
@@ -7999,6 +8043,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorCustomFieldEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||
'PhabricatorCustomFieldEditField' => 'PhabricatorEditField',
|
||||
'PhabricatorCustomFieldEditType' => 'PhabricatorEditType',
|
||||
'PhabricatorCustomFieldExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||
'PhabricatorCustomFieldFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||
'PhabricatorCustomFieldHeraldAction' => 'HeraldAction',
|
||||
'PhabricatorCustomFieldHeraldActionGroup' => 'HeraldActionGroup',
|
||||
@@ -8181,6 +8226,8 @@ phutil_register_library_map(array(
|
||||
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorDraftEngine' => 'Phobject',
|
||||
'PhabricatorDrydockApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorEdgeChangeRecord' => 'Phobject',
|
||||
'PhabricatorEdgeChangeRecordTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
|
||||
'PhabricatorEdgeConstants' => 'Phobject',
|
||||
'PhabricatorEdgeCycleException' => 'Exception',
|
||||
@@ -8252,6 +8299,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorEditPage' => 'Phobject',
|
||||
'PhabricatorEditType' => 'Phobject',
|
||||
'PhabricatorEditor' => 'Phobject',
|
||||
'PhabricatorEditorMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEditorSetting' => 'PhabricatorStringSetting',
|
||||
'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine',
|
||||
@@ -8267,6 +8315,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorEmailPreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorEmailRePrefixSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEmailSelfActionsSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEmailStampsSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEmailTagsSetting' => 'PhabricatorInternalSetting',
|
||||
'PhabricatorEmailVarySubjectsSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorEmailVerificationController' => 'PhabricatorAuthController',
|
||||
@@ -8285,9 +8334,14 @@ phutil_register_library_map(array(
|
||||
'PhabricatorEventListener' => 'PhutilEventListener',
|
||||
'PhabricatorEventType' => 'PhutilEventType',
|
||||
'PhabricatorExampleEventListener' => 'PhabricatorEventListener',
|
||||
'PhabricatorExcelExportFormat' => 'PhabricatorExportFormat',
|
||||
'PhabricatorExecFutureFileUploadSource' => 'PhabricatorFileUploadSource',
|
||||
'PhabricatorExportEngine' => 'Phobject',
|
||||
'PhabricatorExportEngineBulkJobType' => 'PhabricatorWorkerSingleBulkJobType',
|
||||
'PhabricatorExportEngineExtension' => 'Phobject',
|
||||
'PhabricatorExportField' => 'Phobject',
|
||||
'PhabricatorExportFormat' => 'Phobject',
|
||||
'PhabricatorExportFormatSetting' => 'PhabricatorInternalSetting',
|
||||
'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorExtensionsSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorExternalAccount' => array(
|
||||
@@ -8493,6 +8547,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorGDSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorGarbageCollector' => 'Phobject',
|
||||
'PhabricatorGarbageCollectorManagementCollectWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
||||
'PhabricatorGarbageCollectorManagementCompactEdgesWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
||||
'PhabricatorGarbageCollectorManagementSetPolicyWorkflow' => 'PhabricatorGarbageCollectorManagementWorkflow',
|
||||
'PhabricatorGarbageCollectorManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorGeneralCachePurger' => 'PhabricatorCachePurger',
|
||||
@@ -8604,9 +8659,11 @@ phutil_register_library_map(array(
|
||||
'PhabricatorLipsumManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorLipsumMondrianArtist' => 'PhabricatorLipsumArtist',
|
||||
'PhabricatorLiskDAO' => 'LiskDAO',
|
||||
'PhabricatorLiskExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||
'PhabricatorLiskFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||
'PhabricatorLiskSearchEngineExtension' => 'PhabricatorSearchEngineExtension',
|
||||
'PhabricatorLiskSerializer' => 'Phobject',
|
||||
'PhabricatorListExportField' => 'PhabricatorExportField',
|
||||
'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||
'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorLocaleScopeGuard' => 'Phobject',
|
||||
@@ -8642,14 +8699,17 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
|
||||
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
|
||||
'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase',
|
||||
'PhabricatorMailEmailHeraldField' => 'HeraldField',
|
||||
'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup',
|
||||
'PhabricatorMailEmailSubjectHeraldField' => 'PhabricatorMailEmailHeraldField',
|
||||
'PhabricatorMailEngineExtension' => 'Phobject',
|
||||
'PhabricatorMailImplementationAdapter' => 'Phobject',
|
||||
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
|
||||
'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMailImplementationPostmarkAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||
@@ -8662,6 +8722,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||
'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||
'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorMailMustEncryptHeraldAction' => 'HeraldAction',
|
||||
'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter',
|
||||
'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction',
|
||||
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
||||
@@ -8672,6 +8733,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMailReplyHandler' => 'Phobject',
|
||||
'PhabricatorMailRoutingRule' => 'Phobject',
|
||||
'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorMailStamp' => 'Phobject',
|
||||
'PhabricatorMailTarget' => 'Phobject',
|
||||
'PhabricatorMailgunConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
||||
@@ -8725,6 +8787,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMetaMTAMail' => array(
|
||||
'PhabricatorMetaMTADAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
),
|
||||
'PhabricatorMetaMTAMailBody' => 'Phobject',
|
||||
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
|
||||
@@ -8741,6 +8804,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController',
|
||||
'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery',
|
||||
'PhabricatorMetaMTAPermanentFailureException' => 'Exception',
|
||||
'PhabricatorMetaMTAPostmarkReceiveController' => 'PhabricatorMetaMTAController',
|
||||
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
|
||||
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
|
||||
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',
|
||||
@@ -8758,6 +8822,8 @@ phutil_register_library_map(array(
|
||||
'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorMultimeterApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController',
|
||||
'PhabricatorMutedByEdgeType' => 'PhabricatorEdgeType',
|
||||
'PhabricatorMutedEdgeType' => 'PhabricatorEdgeType',
|
||||
'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||
'PhabricatorMySQLSearchHost' => 'PhabricatorSearchHost',
|
||||
@@ -8944,6 +9010,8 @@ phutil_register_library_map(array(
|
||||
'PhabricatorPHIDExportField' => 'PhabricatorExportField',
|
||||
'PhabricatorPHIDListEditField' => 'PhabricatorEditField',
|
||||
'PhabricatorPHIDListEditType' => 'PhabricatorEditType',
|
||||
'PhabricatorPHIDListExportField' => 'PhabricatorListExportField',
|
||||
'PhabricatorPHIDMailStamp' => 'PhabricatorMailStamp',
|
||||
'PhabricatorPHIDResolver' => 'Phobject',
|
||||
'PhabricatorPHIDType' => 'Phobject',
|
||||
'PhabricatorPHIDTypeTestCase' => 'PhutilTestCase',
|
||||
@@ -9444,7 +9512,9 @@ phutil_register_library_map(array(
|
||||
'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension',
|
||||
'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||
'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField',
|
||||
'PhabricatorProjectsExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||
'PhabricatorProjectsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||
'PhabricatorProjectsMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||
'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension',
|
||||
'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule',
|
||||
@@ -9812,8 +9882,10 @@ phutil_register_library_map(array(
|
||||
'PhabricatorSpacesController' => 'PhabricatorController',
|
||||
'PhabricatorSpacesDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorSpacesEditController' => 'PhabricatorSpacesController',
|
||||
'PhabricatorSpacesExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||
'PhabricatorSpacesInterface' => 'PhabricatorPHIDInterface',
|
||||
'PhabricatorSpacesListController' => 'PhabricatorSpacesController',
|
||||
'PhabricatorSpacesMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'PhabricatorSpacesNamespace' => array(
|
||||
'PhabricatorSpacesDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
@@ -9885,6 +9957,8 @@ phutil_register_library_map(array(
|
||||
'PhabricatorStringExportField' => 'PhabricatorExportField',
|
||||
'PhabricatorStringListConfigType' => 'PhabricatorTextListConfigType',
|
||||
'PhabricatorStringListEditField' => 'PhabricatorEditField',
|
||||
'PhabricatorStringListExportField' => 'PhabricatorListExportField',
|
||||
'PhabricatorStringMailStamp' => 'PhabricatorMailStamp',
|
||||
'PhabricatorStringSetting' => 'PhabricatorSetting',
|
||||
'PhabricatorSubmitEditField' => 'PhabricatorEditField',
|
||||
'PhabricatorSubscribedToObjectEdgeType' => 'PhabricatorEdgeType',
|
||||
@@ -9898,9 +9972,12 @@ phutil_register_library_map(array(
|
||||
'PhabricatorSubscriptionsEditController' => 'PhabricatorController',
|
||||
'PhabricatorSubscriptionsEditEngineExtension' => 'PhabricatorEditEngineExtension',
|
||||
'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor',
|
||||
'PhabricatorSubscriptionsExportEngineExtension' => 'PhabricatorExportEngineExtension',
|
||||
'PhabricatorSubscriptionsFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||
'PhabricatorSubscriptionsHeraldAction' => 'HeraldAction',
|
||||
'PhabricatorSubscriptionsListController' => 'PhabricatorController',
|
||||
'PhabricatorSubscriptionsMailEngineExtension' => 'PhabricatorMailEngineExtension',
|
||||
'PhabricatorSubscriptionsMuteController' => 'PhabricatorController',
|
||||
'PhabricatorSubscriptionsRemoveSelfHeraldAction' => 'PhabricatorSubscriptionsHeraldAction',
|
||||
'PhabricatorSubscriptionsRemoveSubscribersHeraldAction' => 'PhabricatorSubscriptionsHeraldAction',
|
||||
'PhabricatorSubscriptionsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
|
||||
@@ -10021,6 +10098,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorUIExample' => 'Phobject',
|
||||
'PhabricatorUIExampleRenderController' => 'PhabricatorController',
|
||||
'PhabricatorUIExamplesApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorURIExportField' => 'PhabricatorExportField',
|
||||
'PhabricatorUSEnglishTranslation' => 'PhutilTranslation',
|
||||
'PhabricatorUnifiedDiffsSetting' => 'PhabricatorSelectSetting',
|
||||
'PhabricatorUnitTestContentSource' => 'PhabricatorContentSource',
|
||||
@@ -10144,6 +10222,7 @@ phutil_register_library_map(array(
|
||||
'PhabricatorWorkerManagementWorkflow' => 'PhabricatorManagementWorkflow',
|
||||
'PhabricatorWorkerPermanentFailureException' => 'Exception',
|
||||
'PhabricatorWorkerSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'PhabricatorWorkerSingleBulkJobType' => 'PhabricatorWorkerBulkJobType',
|
||||
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
|
||||
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
|
||||
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
|
||||
|
||||
@@ -358,9 +358,17 @@ final class PhabricatorAuditEditor
|
||||
array $changes,
|
||||
PhutilMarkupEngine $engine) {
|
||||
|
||||
// we are only really trying to find unmentionable phids here...
|
||||
// don't bother with this outside initial commit (i.e. create)
|
||||
// transaction
|
||||
$actor = $this->getActor();
|
||||
$result = array();
|
||||
|
||||
// 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;
|
||||
foreach ($xactions as $xaction) {
|
||||
switch ($xaction->getTransactionType()) {
|
||||
@@ -370,8 +378,6 @@ final class PhabricatorAuditEditor
|
||||
}
|
||||
}
|
||||
|
||||
// "result" is always an array....
|
||||
$result = array();
|
||||
if (!$is_commit) {
|
||||
return $result;
|
||||
}
|
||||
@@ -403,6 +409,46 @@ final class PhabricatorAuditEditor
|
||||
->withNames($monograms)
|
||||
->execute();
|
||||
$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);
|
||||
$this->setUnmentionablePHIDMap($phid_map);
|
||||
|
||||
@@ -427,17 +473,14 @@ final class PhabricatorAuditEditor
|
||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||
$identifier = $object->getCommitIdentifier();
|
||||
$repository = $object->getRepository();
|
||||
$monogram = $repository->getMonogram();
|
||||
|
||||
$summary = $object->getSummary();
|
||||
$name = $repository->formatCommitName($identifier);
|
||||
|
||||
$subject = "{$name}: {$summary}";
|
||||
$thread_topic = "Commit {$monogram}{$identifier}";
|
||||
|
||||
$template = id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->addHeader('Thread-Topic', $thread_topic);
|
||||
->setSubject($subject);
|
||||
|
||||
$this->attachPatch(
|
||||
$template,
|
||||
@@ -453,7 +496,6 @@ final class PhabricatorAuditEditor
|
||||
$phids[] = $object->getAuthorPHID();
|
||||
}
|
||||
|
||||
$status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
|
||||
foreach ($object->getAudits() as $audit) {
|
||||
if (!$audit->isInteresting()) {
|
||||
// Don't send mail to uninteresting auditors, like packages which
|
||||
@@ -461,7 +503,7 @@ final class PhabricatorAuditEditor
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($audit->getAuditStatus() != $status_resigned) {
|
||||
if (!$audit->isResigned()) {
|
||||
$phids[] = $audit->getAuditorPHID();
|
||||
}
|
||||
}
|
||||
@@ -471,6 +513,18 @@ final class PhabricatorAuditEditor
|
||||
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(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
|
||||
@@ -255,11 +255,9 @@ final class PhabricatorAuthSSHKeyEditor
|
||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||
$id = $object->getID();
|
||||
$name = $object->getName();
|
||||
$phid = $object->getPHID();
|
||||
|
||||
$mail = id(new PhabricatorMetaMTAMail())
|
||||
->setSubject(pht('SSH Key %d: %s', $id, $name))
|
||||
->addHeader('Thread-Topic', $phid);
|
||||
->setSubject(pht('SSH Key %d: %s', $id, $name));
|
||||
|
||||
// The primary value of this mail is alerting users to account compromises,
|
||||
// so force delivery. In particular, this mail should still be delivered
|
||||
|
||||
@@ -87,12 +87,10 @@ final class PhabricatorBadgesEditor
|
||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||
$name = $object->getName();
|
||||
$id = $object->getID();
|
||||
$topic = pht('Badge %d', $id);
|
||||
$subject = pht('Badge %d: %s', $id, $name);
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->addHeader('Thread-Topic', $topic);
|
||||
->setSubject($subject);
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
|
||||
@@ -309,13 +309,11 @@ final class PhabricatorCalendarEventEditor
|
||||
}
|
||||
|
||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||
$id = $object->getID();
|
||||
$name = $object->getName();
|
||||
$monogram = $object->getMonogram();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("{$monogram}: {$name}")
|
||||
->addHeader('Thread-Topic', $monogram);
|
||||
->setSubject("{$monogram}: {$name}");
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
$value = parent::getParameterValue($request, $key, $strict);
|
||||
|
||||
if ($this->getIsNullable()) {
|
||||
if ($value === null) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_string($value)) {
|
||||
$this->raiseValidationException(
|
||||
$request,
|
||||
@@ -17,7 +34,11 @@ final class ConduitPHIDParameterType
|
||||
}
|
||||
|
||||
protected function getParameterTypeName() {
|
||||
return 'phid';
|
||||
if ($this->getIsNullable()) {
|
||||
return 'phid|null';
|
||||
} else {
|
||||
return 'phid';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getParameterFormatDescriptions() {
|
||||
@@ -27,9 +48,15 @@ final class ConduitPHIDParameterType
|
||||
}
|
||||
|
||||
protected function getParameterExamples() {
|
||||
return array(
|
||||
$examples = array(
|
||||
'"PHID-WXYZ-1111222233334444"',
|
||||
);
|
||||
|
||||
if ($this->getIsNullable()) {
|
||||
$examples[] = 'null';
|
||||
}
|
||||
|
||||
return $examples;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ final class PhabricatorMailSetupCheck extends PhabricatorSetupCheck {
|
||||
}
|
||||
|
||||
protected function executeChecks() {
|
||||
if (PhabricatorEnv::getEnvConfig('cluster.mailers')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$adapter = PhabricatorEnv::getEnvConfig('metamta.mail-adapter');
|
||||
|
||||
switch ($adapter) {
|
||||
|
||||
@@ -6,7 +6,9 @@ final class PhabricatorConfigManagementSetWorkflow
|
||||
protected function didConstruct() {
|
||||
$this
|
||||
->setName('set')
|
||||
->setExamples('**set** __key__ __value__')
|
||||
->setExamples(
|
||||
"**set** __key__ __value__\n".
|
||||
"**set** __key__ --stdin < value.json")
|
||||
->setSynopsis(pht('Set a local configuration value.'))
|
||||
->setArguments(
|
||||
array(
|
||||
@@ -16,6 +18,10 @@ final class PhabricatorConfigManagementSetWorkflow
|
||||
'Update configuration in the database instead of '.
|
||||
'in local configuration.'),
|
||||
),
|
||||
array(
|
||||
'name' => 'stdin',
|
||||
'help' => pht('Read option value from stdin.'),
|
||||
),
|
||||
array(
|
||||
'name' => 'args',
|
||||
'wildcard' => true,
|
||||
@@ -31,22 +37,36 @@ final class PhabricatorConfigManagementSetWorkflow
|
||||
pht('Specify a configuration key and a value to set it to.'));
|
||||
}
|
||||
|
||||
$is_stdin = $args->getArg('stdin');
|
||||
|
||||
$key = $argv[0];
|
||||
|
||||
if (count($argv) == 1) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
"Specify a value to set the key '%s' to.",
|
||||
$key));
|
||||
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) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
"Specify a value to set the key '%s' to.",
|
||||
$key));
|
||||
}
|
||||
|
||||
if (count($argv) > 2) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Too many arguments: expected one key and one value.'));
|
||||
}
|
||||
|
||||
$value = $argv[1];
|
||||
}
|
||||
|
||||
$value = $argv[1];
|
||||
|
||||
if (count($argv) > 2) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Too many arguments: expected one key and one value.'));
|
||||
}
|
||||
|
||||
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
||||
if (empty($options[$key])) {
|
||||
|
||||
@@ -66,7 +66,9 @@ of each approach are:
|
||||
received a similar message, but can not prevent all stray email arising
|
||||
from "Reply All".
|
||||
- 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:
|
||||
- Policy controls work correctly and are enforced per-user.
|
||||
- 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
|
||||
thread.
|
||||
- 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
|
||||
));
|
||||
@@ -138,24 +140,19 @@ EODOC
|
||||
,
|
||||
'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 class to use to transmit mail to the MTA. The default uses
|
||||
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
|
||||
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
|
||||
,
|
||||
$adapter_doc_href,
|
||||
$adapter_doc_name));
|
||||
));
|
||||
|
||||
$placeholder_description = $this->deformat(pht(<<<EODOC
|
||||
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
|
||||
no value is set, messages with no To will have their CCs upgraded to To.
|
||||
When sending a message that has no To recipient (i.e. all recipients are CC'd),
|
||||
set the To field to the following value. If no value is set, messages with no
|
||||
To will have their CCs upgraded to To.
|
||||
EODOC
|
||||
));
|
||||
|
||||
@@ -197,7 +194,18 @@ The default is `full`.
|
||||
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(
|
||||
$this->newOption('cluster.mailers', 'cluster.mailers', null)
|
||||
->setHidden(true)
|
||||
->setDescription($mailers_description),
|
||||
$this->newOption(
|
||||
'metamta.default-address',
|
||||
'string',
|
||||
|
||||
@@ -227,11 +227,9 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
|
||||
'%s sent you a message.',
|
||||
$this->getActor()->getUserName());
|
||||
}
|
||||
$phid = $object->getPHID();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("Z{$id}: {$title}")
|
||||
->addHeader('Thread-Topic', "Z{$id}: {$phid}");
|
||||
->setSubject("Z{$id}: {$title}");
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
|
||||
@@ -45,8 +45,7 @@ final class PhabricatorCountdownEditor
|
||||
$name = $object->getTitle();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("{$monogram}: {$name}")
|
||||
->addHeader('Thread-Topic', $monogram);
|
||||
->setSubject("{$monogram}: {$name}");
|
||||
}
|
||||
|
||||
protected function buildMailBody(
|
||||
|
||||
@@ -71,18 +71,10 @@ final class PhabricatorDaemonBulkJobViewController
|
||||
$viewer = $this->getViewer();
|
||||
$curtain = $this->newCurtainView($job);
|
||||
|
||||
if ($job->isConfirming()) {
|
||||
$continue_uri = $job->getMonitorURI();
|
||||
} else {
|
||||
$continue_uri = $job->getDoneURI();
|
||||
foreach ($job->getCurtainActions($viewer) as $action) {
|
||||
$curtain->addAction($action);
|
||||
}
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setHref($continue_uri)
|
||||
->setIcon('fa-arrow-circle-o-right')
|
||||
->setName(pht('Continue')));
|
||||
|
||||
return $curtain;
|
||||
}
|
||||
|
||||
|
||||
@@ -632,6 +632,8 @@ final class DifferentialTransactionEditor
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
$this->requireReviewers($object);
|
||||
|
||||
$phids = array();
|
||||
$phids[] = $object->getAuthorPHID();
|
||||
foreach ($object->getReviewers() as $reviewer) {
|
||||
@@ -644,6 +646,20 @@ final class DifferentialTransactionEditor
|
||||
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(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
@@ -689,15 +705,10 @@ final class DifferentialTransactionEditor
|
||||
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
|
||||
$id = $object->getID();
|
||||
$title = $object->getTitle();
|
||||
|
||||
$original_title = $object->getOriginalTitle();
|
||||
|
||||
$subject = "D{$id}: {$title}";
|
||||
$thread_topic = "D{$id}: {$original_title}";
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->addHeader('Thread-Topic', $thread_topic);
|
||||
->setSubject($subject);
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
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 )----------------------------------------- */
|
||||
|
||||
|
||||
@@ -69,6 +69,11 @@ final class DifferentialReviewer
|
||||
return ($this->getReviewerStatus() == $status_resigned);
|
||||
}
|
||||
|
||||
public function isBlocking() {
|
||||
$status_blocking = DifferentialReviewerStatus::STATUS_BLOCKING;
|
||||
return ($this->getReviewerStatus() == $status_blocking);
|
||||
}
|
||||
|
||||
public function isRejected($diff_phid) {
|
||||
$status_rejected = DifferentialReviewerStatus::STATUS_REJECTED;
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ final class DifferentialRevision extends DifferentialDAO
|
||||
PhabricatorDraftInterface {
|
||||
|
||||
protected $title = '';
|
||||
protected $originalTitle;
|
||||
protected $status;
|
||||
|
||||
protected $summary = '';
|
||||
@@ -98,7 +97,6 @@ final class DifferentialRevision extends DifferentialDAO
|
||||
),
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'title' => 'text255',
|
||||
'originalTitle' => 'text255',
|
||||
'status' => 'text32',
|
||||
'summary' => 'text',
|
||||
'testPlan' => 'text',
|
||||
@@ -155,14 +153,6 @@ final class DifferentialRevision extends DifferentialDAO
|
||||
return '/'.$this->getMonogram();
|
||||
}
|
||||
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
if (!$this->getID()) {
|
||||
$this->originalTitle = $title;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function loadIDsByCommitPHIDs($phids) {
|
||||
if (!$phids) {
|
||||
return array();
|
||||
@@ -593,6 +583,10 @@ final class DifferentialRevision extends DifferentialDAO
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasAttachedReviewers() {
|
||||
return ($this->reviewerStatus !== self::ATTACHABLE);
|
||||
}
|
||||
|
||||
public function getReviewerPHIDs() {
|
||||
$reviewers = $this->getReviewers();
|
||||
return mpull($reviewers, 'getReviewerPHID');
|
||||
@@ -830,9 +824,15 @@ final class DifferentialRevision extends DifferentialDAO
|
||||
}
|
||||
|
||||
foreach ($reviewers as $reviewer) {
|
||||
if ($reviewer->getReviewerPHID() == $phid) {
|
||||
return true;
|
||||
if ($reviewer->getReviewerPHID() !== $phid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reviewer->isResigned()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -87,19 +87,6 @@ final class DifferentialTransaction
|
||||
}
|
||||
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:
|
||||
// Don't hide the initial "X requested review: ..." transaction from
|
||||
// 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),
|
||||
'path' => $display_filename,
|
||||
'icon' => $display_icon,
|
||||
'treeNodeID' => 'tree-node-'.$changeset->getAnchorName(),
|
||||
),
|
||||
'class' => $class,
|
||||
'id' => $id,
|
||||
|
||||
@@ -83,6 +83,9 @@ final class DifferentialChangesetFileTreeSideNavBuilder extends Phobject {
|
||||
while (($path = $path->getNextNode())) {
|
||||
$data = $path->getData();
|
||||
|
||||
$classes = array();
|
||||
$classes[] = 'phabricator-filetree-item';
|
||||
|
||||
$name = $path->getName();
|
||||
$style = 'padding-left: '.(2 + (3 * $path->getDepth())).'px';
|
||||
|
||||
@@ -90,13 +93,23 @@ final class DifferentialChangesetFileTreeSideNavBuilder extends Phobject {
|
||||
if ($data) {
|
||||
$href = '#'.$data->getAnchorName();
|
||||
$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 {
|
||||
$name .= '/';
|
||||
$title = $path->getFullPath().'/';
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon('fa-folder-open blue');
|
||||
|
||||
$count = null;
|
||||
}
|
||||
|
||||
$name_element = phutil_tag(
|
||||
@@ -106,15 +119,16 @@ final class DifferentialChangesetFileTreeSideNavBuilder extends Phobject {
|
||||
),
|
||||
$name);
|
||||
|
||||
|
||||
$filetree[] = javelin_tag(
|
||||
$href ? 'a' : 'span',
|
||||
array(
|
||||
'href' => $href,
|
||||
'style' => $style,
|
||||
'title' => $title,
|
||||
'class' => 'phabricator-filetree-item',
|
||||
'class' => implode(' ', $classes),
|
||||
),
|
||||
array($icon, $name_element));
|
||||
array($count, $icon, $name_element));
|
||||
}
|
||||
$tree->destroy();
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
||||
$this->getEditRoutePattern('edit/') =>
|
||||
'DiffusionRepositoryEditController',
|
||||
'pushlog/' => array(
|
||||
'(?:query/(?P<queryKey>[^/]+)/)?' => 'DiffusionPushLogListController',
|
||||
$this->getQueryRoutePattern() => 'DiffusionPushLogListController',
|
||||
'view/(?P<id>\d+)/' => 'DiffusionPushEventViewController',
|
||||
),
|
||||
'pulllog/' => array(
|
||||
|
||||
@@ -37,7 +37,11 @@ final class DiffusionQueryPathsConduitAPIMethod
|
||||
$commit = $request->getValue('commit');
|
||||
$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(
|
||||
'ls-tree --name-only -r -z %s -- %s',
|
||||
|
||||
@@ -9,4 +9,9 @@ final class DiffusionPullLogListController
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
return parent::buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Pull Logs'), $this->getApplicationURI('pulllog/'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,4 +9,9 @@ final class DiffusionPushLogListController
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
return parent::buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Push Logs'), $this->getApplicationURI('pushlog/'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,14 +23,10 @@ final class DiffusionRepositoryURIViewController
|
||||
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
|
||||
// with a different view of builtin URIs than we'd see if we loaded them
|
||||
// directly from the database. See T12884.
|
||||
$repository_with_uris = id(new PhabricatorRepositoryQuery())
|
||||
->setViewer($viewer)
|
||||
->needURIs(true)
|
||||
->execute();
|
||||
|
||||
$repository_uris = $repository->getURIs();
|
||||
$repository_uris = mpull($repository_uris, null, 'getID');
|
||||
|
||||
@@ -19,7 +19,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
||||
$add_edges) {
|
||||
|
||||
return pht(
|
||||
'%s added %s reverting commit(s): %s.',
|
||||
'%s added %s reverting change(s): %s.',
|
||||
$actor,
|
||||
$add_count,
|
||||
$add_edges);
|
||||
@@ -31,7 +31,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
||||
$rem_edges) {
|
||||
|
||||
return pht(
|
||||
'%s removed %s reverting commit(s): %s.',
|
||||
'%s removed %s reverting change(s): %s.',
|
||||
$actor,
|
||||
$rem_count,
|
||||
$rem_edges);
|
||||
@@ -46,7 +46,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
||||
$rem_edges) {
|
||||
|
||||
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,
|
||||
$add_count,
|
||||
$add_edges,
|
||||
@@ -61,7 +61,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
||||
$add_edges) {
|
||||
|
||||
return pht(
|
||||
'%s added %s reverting commit(s) for %s: %s.',
|
||||
'%s added %s reverting change(s) for %s: %s.',
|
||||
$actor,
|
||||
$add_count,
|
||||
$object,
|
||||
@@ -75,7 +75,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
||||
$rem_edges) {
|
||||
|
||||
return pht(
|
||||
'%s removed %s reverting commit(s) for %s: %s.',
|
||||
'%s removed %s reverting change(s) for %s: %s.',
|
||||
$actor,
|
||||
$rem_count,
|
||||
$object,
|
||||
@@ -92,7 +92,7 @@ final class DiffusionCommitRevertedByCommitEdgeType
|
||||
$rem_edges) {
|
||||
|
||||
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,
|
||||
$object,
|
||||
$add_count,
|
||||
|
||||
@@ -22,7 +22,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
||||
$add_edges) {
|
||||
|
||||
return pht(
|
||||
'%s added %s reverted commit(s): %s.',
|
||||
'%s added %s reverted change(s): %s.',
|
||||
$actor,
|
||||
$add_count,
|
||||
$add_edges);
|
||||
@@ -34,7 +34,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
||||
$rem_edges) {
|
||||
|
||||
return pht(
|
||||
'%s removed %s reverted commit(s): %s.',
|
||||
'%s removed %s reverted change(s): %s.',
|
||||
$actor,
|
||||
$rem_count,
|
||||
$rem_edges);
|
||||
@@ -49,7 +49,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
||||
$rem_edges) {
|
||||
|
||||
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,
|
||||
$add_count,
|
||||
$add_edges,
|
||||
@@ -64,7 +64,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
||||
$add_edges) {
|
||||
|
||||
return pht(
|
||||
'%s added %s reverted commit(s) for %s: %s.',
|
||||
'%s added %s reverted change(s) for %s: %s.',
|
||||
$actor,
|
||||
$add_count,
|
||||
$object,
|
||||
@@ -78,7 +78,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
||||
$rem_edges) {
|
||||
|
||||
return pht(
|
||||
'%s removed %s reverted commit(s) for %s: %s.',
|
||||
'%s removed %s reverted change(s) for %s: %s.',
|
||||
$actor,
|
||||
$rem_count,
|
||||
$object,
|
||||
@@ -95,7 +95,7 @@ final class DiffusionCommitRevertsCommitEdgeType extends PhabricatorEdgeType {
|
||||
$rem_edges) {
|
||||
|
||||
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,
|
||||
$object,
|
||||
$add_count,
|
||||
|
||||
@@ -297,7 +297,11 @@ final class DiffusionCommitHookEngine extends Phobject {
|
||||
return;
|
||||
}
|
||||
|
||||
$adapter_template->setHookEngine($this);
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$adapter_template
|
||||
->setHookEngine($this)
|
||||
->setActingAsPHID($viewer->getPHID());
|
||||
|
||||
$engine = new HeraldEngine();
|
||||
$rules = null;
|
||||
|
||||
@@ -84,7 +84,7 @@ final class DiffusionGitLFSAuthenticateWorkflow
|
||||
// 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.
|
||||
|
||||
$user = $this->getUser();
|
||||
$user = $this->getSSHUser();
|
||||
|
||||
$authorization = DiffusionGitLFSTemporaryTokenType::newHTTPAuthorization(
|
||||
$repository,
|
||||
|
||||
@@ -135,13 +135,16 @@ final class HeraldCommitAdapter
|
||||
}
|
||||
|
||||
public function loadAffectedPaths() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if ($this->affectedPaths === null) {
|
||||
$result = PhabricatorOwnerPathQuery::loadAffectedPaths(
|
||||
$this->getRepository(),
|
||||
$this->commit,
|
||||
PhabricatorUser::getOmnipotentUser());
|
||||
$viewer);
|
||||
$this->affectedPaths = $result;
|
||||
}
|
||||
|
||||
return $this->affectedPaths;
|
||||
}
|
||||
|
||||
@@ -172,6 +175,8 @@ final class HeraldCommitAdapter
|
||||
}
|
||||
|
||||
public function loadDifferentialRevision() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if ($this->affectedRevision === null) {
|
||||
$this->affectedRevision = false;
|
||||
|
||||
@@ -189,7 +194,7 @@ final class HeraldCommitAdapter
|
||||
|
||||
$revision = id(new DifferentialRevisionQuery())
|
||||
->withIDs(array($revision_id))
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->setViewer($viewer)
|
||||
->needReviewers(true)
|
||||
->executeOne();
|
||||
if ($revision) {
|
||||
@@ -197,6 +202,7 @@ final class HeraldCommitAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->affectedRevision;
|
||||
}
|
||||
|
||||
@@ -323,7 +329,7 @@ final class HeraldCommitAdapter
|
||||
}
|
||||
|
||||
private function callConduit($method, array $params) {
|
||||
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$drequest = DiffusionRequest::newFromDictionary(
|
||||
array(
|
||||
|
||||
@@ -26,6 +26,12 @@ final class DiffusionPullLogSearchEngine
|
||||
$query->withPullerPHIDs($map['pullerPHIDs']);
|
||||
}
|
||||
|
||||
if ($map['createdStart'] || $map['createdEnd']) {
|
||||
$query->withEpochBetween(
|
||||
$map['createdStart'],
|
||||
$map['createdEnd']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
@@ -44,17 +50,19 @@ final class DiffusionPullLogSearchEngine
|
||||
->setLabel(pht('Pullers'))
|
||||
->setDescription(
|
||||
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() {
|
||||
return array(
|
||||
id(new PhabricatorIDExportField())
|
||||
->setKey('id')
|
||||
->setLabel(pht('ID')),
|
||||
id(new PhabricatorPHIDExportField())
|
||||
->setKey('phid')
|
||||
->setLabel(pht('PHID')),
|
||||
$viewer = $this->requireViewer();
|
||||
|
||||
$fields = array(
|
||||
id(new PhabricatorPHIDExportField())
|
||||
->setKey('repositoryPHID')
|
||||
->setLabel(pht('Repository PHID')),
|
||||
@@ -80,9 +88,17 @@ final class DiffusionPullLogSearchEngine
|
||||
->setKey('date')
|
||||
->setLabel(pht('Date')),
|
||||
);
|
||||
|
||||
if ($viewer->getIsAdmin()) {
|
||||
$fields[] = id(new PhabricatorStringExportField())
|
||||
->setKey('remoteAddress')
|
||||
->setLabel(pht('Remote Address'));
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function newExport(array $events) {
|
||||
protected function newExportData(array $events) {
|
||||
$viewer = $this->requireViewer();
|
||||
|
||||
$phids = array();
|
||||
@@ -111,9 +127,7 @@ final class DiffusionPullLogSearchEngine
|
||||
$puller_name = null;
|
||||
}
|
||||
|
||||
$export[] = array(
|
||||
'id' => $event->getID(),
|
||||
'phid' => $event->getPHID(),
|
||||
$map = array(
|
||||
'repositoryPHID' => $repository_phid,
|
||||
'repository' => $repository_name,
|
||||
'pullerPHID' => $puller_phid,
|
||||
@@ -123,6 +137,12 @@ final class DiffusionPullLogSearchEngine
|
||||
'code' => $event->getResultCode(),
|
||||
'date' => $event->getEpoch(),
|
||||
);
|
||||
|
||||
if ($viewer->getIsAdmin()) {
|
||||
$map['remoteAddress'] = $event->getRemoteAddress();
|
||||
}
|
||||
|
||||
$export[] = $map;
|
||||
}
|
||||
|
||||
return $export;
|
||||
|
||||
@@ -22,24 +22,10 @@ final class DiffusionPullLogListView extends AphrontView {
|
||||
}
|
||||
$handles = $viewer->loadHandles($handle_phids);
|
||||
|
||||
// Figure out which repositories are editable. We only let you see remote
|
||||
// IPs if you have edit capability on a repository.
|
||||
$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');
|
||||
}
|
||||
// Only administrators can view remote addresses.
|
||||
$remotes_visible = $viewer->getIsAdmin();
|
||||
|
||||
$rows = array();
|
||||
$any_host = false;
|
||||
foreach ($events as $event) {
|
||||
if ($event->getRepositoryPHID()) {
|
||||
$repository = $event->getRepository();
|
||||
@@ -47,13 +33,10 @@ final class DiffusionPullLogListView extends AphrontView {
|
||||
$repository = null;
|
||||
}
|
||||
|
||||
// Reveal this if it's valid and the user can edit the repository. For
|
||||
// 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();
|
||||
}
|
||||
if ($remotes_visible) {
|
||||
$remote_address = $event->getRemoteAddress();
|
||||
} else {
|
||||
$remote_address = null;
|
||||
}
|
||||
|
||||
$event_id = $event->getID();
|
||||
@@ -107,6 +90,13 @@ final class DiffusionPullLogListView extends AphrontView {
|
||||
'',
|
||||
'n',
|
||||
'right',
|
||||
))
|
||||
->setColumnVisibility(
|
||||
array(
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
$remotes_visible,
|
||||
));
|
||||
|
||||
return $table;
|
||||
|
||||
@@ -25,31 +25,21 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||
|
||||
$handles = $viewer->loadHandles($handle_phids);
|
||||
|
||||
// Figure out which repositories are editable. We only let you see remote
|
||||
// IPs if you have edit capability on a repository.
|
||||
$editable_repos = array();
|
||||
if ($logs) {
|
||||
$editable_repos = id(new PhabricatorRepositoryQuery())
|
||||
->setViewer($viewer)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->withPHIDs(mpull($logs, 'getRepositoryPHID'))
|
||||
->execute();
|
||||
$editable_repos = mpull($editable_repos, null, 'getPHID');
|
||||
}
|
||||
// Only administrators can view remote addresses.
|
||||
$remotes_visible = $viewer->getIsAdmin();
|
||||
|
||||
$flag_map = PhabricatorRepositoryPushLog::getFlagDisplayNames();
|
||||
$reject_map = PhabricatorRepositoryPushLog::getRejectCodeDisplayNames();
|
||||
|
||||
$rows = array();
|
||||
$any_host = false;
|
||||
foreach ($logs as $log) {
|
||||
$repository = $log->getRepository();
|
||||
|
||||
// Reveal this if it's valid and the user can edit the repository.
|
||||
$remote_address = '-';
|
||||
if (isset($editable_repos[$log->getRepositoryPHID()])) {
|
||||
if ($remotes_visible) {
|
||||
$remote_address = $log->getPushEvent()->getRemoteAddress();
|
||||
} else {
|
||||
$remote_address = null;
|
||||
}
|
||||
|
||||
$event_id = $log->getPushEvent()->getID();
|
||||
@@ -72,6 +62,23 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||
$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(
|
||||
phutil_tag(
|
||||
'a',
|
||||
@@ -98,10 +105,8 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||
'href' => $repository->getCommitURI($log->getRefNew()),
|
||||
),
|
||||
$log->getRefNewShort()),
|
||||
|
||||
// TODO: Make these human-readable.
|
||||
$log->getChangeFlags(),
|
||||
$log->getPushEvent()->getRejectCode(),
|
||||
$flag_names,
|
||||
$reject_label,
|
||||
$viewer->formatShortDateTime($log->getEpoch()),
|
||||
);
|
||||
}
|
||||
@@ -120,7 +125,7 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||
pht('Old'),
|
||||
pht('New'),
|
||||
pht('Flags'),
|
||||
pht('Code'),
|
||||
pht('Result'),
|
||||
pht('Date'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
@@ -135,6 +140,8 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||
'wide',
|
||||
'n',
|
||||
'n',
|
||||
'',
|
||||
'',
|
||||
'right',
|
||||
))
|
||||
->setColumnVisibility(
|
||||
@@ -142,7 +149,7 @@ final class DiffusionPushLogListView extends AphrontView {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
$remotes_visible,
|
||||
true,
|
||||
$any_host,
|
||||
));
|
||||
|
||||
@@ -47,8 +47,7 @@ final class PhabricatorFileEditor
|
||||
$name = $object->getName();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("F{$id}: {$name}")
|
||||
->addHeader('Thread-Topic', "F{$id}");
|
||||
->setSubject("F{$id}: {$name}");
|
||||
}
|
||||
|
||||
protected function buildMailBody(
|
||||
|
||||
@@ -272,8 +272,12 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||
$file->setByteSize($length);
|
||||
|
||||
// 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.
|
||||
$file->setMimeType('application/octet-stream');
|
||||
// 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');
|
||||
}
|
||||
|
||||
$chunked_hash = idx($params, 'chunkedHash');
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ abstract class PhabricatorFileUploadSource
|
||||
private $name;
|
||||
private $relativeTTL;
|
||||
private $viewPolicy;
|
||||
private $mimeType;
|
||||
private $authorPHID;
|
||||
|
||||
private $rope;
|
||||
private $data;
|
||||
@@ -51,6 +53,24 @@ abstract class PhabricatorFileUploadSource
|
||||
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() {
|
||||
if (!$this->shouldChunkFile()) {
|
||||
return $this->writeSingleFile();
|
||||
@@ -245,6 +265,16 @@ abstract class PhabricatorFileUploadSource
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,7 @@ final class FundInitiativeEditor
|
||||
$name = $object->getName();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("{$monogram}: {$name}")
|
||||
->addHeader('Thread-Topic', $monogram);
|
||||
->setSubject("{$monogram}: {$name}");
|
||||
}
|
||||
|
||||
protected function buildMailBody(
|
||||
|
||||
@@ -39,6 +39,8 @@ abstract class HeraldAdapter extends Phobject {
|
||||
private $edgeCache = array();
|
||||
private $forbiddenActions = array();
|
||||
private $viewer;
|
||||
private $mustEncryptReasons = array();
|
||||
private $actingAsPHID;
|
||||
|
||||
public function getEmailPHIDs() {
|
||||
return array_values($this->emailPHIDs);
|
||||
@@ -48,6 +50,15 @@ abstract class HeraldAdapter extends Phobject {
|
||||
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) {
|
||||
$this->emailPHIDs[$phid] = $phid;
|
||||
if ($force) {
|
||||
@@ -1182,4 +1193,17 @@ abstract class HeraldAdapter extends Phobject {
|
||||
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');
|
||||
$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;
|
||||
$errors = array();
|
||||
@@ -348,7 +356,7 @@ final class HeraldRuleController extends HeraldController {
|
||||
$match_all,
|
||||
$conditions,
|
||||
$actions,
|
||||
$repetition_policy_param);
|
||||
$repetition_policy);
|
||||
|
||||
$xactions = array();
|
||||
$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
|
||||
$rule->setMustMatchAll((int)$match_all);
|
||||
$rule->setName($new_name);
|
||||
$rule->setRepetitionPolicyStringConstant($repetition_policy_param);
|
||||
$rule->setRepetitionPolicyStringConstant($repetition_policy);
|
||||
$rule->attachConditions($conditions);
|
||||
$rule->attachActions($actions);
|
||||
|
||||
@@ -594,13 +602,9 @@ final class HeraldRuleController extends HeraldController {
|
||||
*/
|
||||
private function renderRepetitionSelector($rule, HeraldAdapter $adapter) {
|
||||
$repetition_policy = $rule->getRepetitionPolicyStringConstant();
|
||||
|
||||
$repetition_options = $adapter->getRepetitionOptions();
|
||||
$repetition_names = HeraldRule::getRepetitionPolicySelectOptionMap();
|
||||
$repetition_map = array_select_keys($repetition_names, $repetition_options);
|
||||
|
||||
$repetition_map = $this->getRepetitionOptionMap($adapter);
|
||||
if (count($repetition_map) < 2) {
|
||||
return head($repetition_names);
|
||||
return head($repetition_map);
|
||||
} else {
|
||||
return AphrontFormSelectControl::renderSelectTag(
|
||||
$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() {
|
||||
$template = new AphrontTokenizerTemplateView();
|
||||
|
||||
@@ -41,6 +41,7 @@ final class HeraldTestConsoleController extends HeraldController {
|
||||
|
||||
$adapter
|
||||
->setIsNewObject(false)
|
||||
->setActingAsPHID($viewer->getPHID())
|
||||
->setViewer($viewer);
|
||||
|
||||
$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) {
|
||||
$id = $object->getID();
|
||||
$phid = $object->getPHID();
|
||||
$title = $object->getDocumentBody()->getTitle();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("L{$id}: {$title}")
|
||||
->addHeader('Thread-Topic', "L{$id}: {$phid}");
|
||||
->setSubject("L{$id}: {$title}");
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
|
||||
@@ -176,7 +176,7 @@ final class LegalpadDocumentSearchEngine
|
||||
$create_button = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setText(pht('Create a Document'))
|
||||
->setHref('/legalpad/create/')
|
||||
->setHref('/legalpad/edit/')
|
||||
->setColor(PHUIButtonView::GREEN);
|
||||
|
||||
$icon = $this->getApplication()->getIcon();
|
||||
|
||||
@@ -35,8 +35,7 @@ final class PhabricatorMacroEditor
|
||||
$name = 'Image Macro "'.$name.'"';
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($name)
|
||||
->addHeader('Thread-Topic', $name);
|
||||
->setSubject($name);
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
|
||||
@@ -51,13 +51,13 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
|
||||
'/T(?P<id>[1-9]\d*)' => 'ManiphestTaskDetailController',
|
||||
'/maniphest/' => array(
|
||||
'(?:project/(?P<projectKey>[^/]+)/)?(?:type/(?P<taskTypeKey>[^/]+)/)?(?:query/(?P<queryKey>[^/]+)/)?' => 'ManiphestTaskListController',
|
||||
$this->getQueryRoutePattern() => 'ManiphestTaskListController',
|
||||
'report/(?:(?P<view>\w+)/)?' => 'ManiphestReportController',
|
||||
$this->getBulkRoutePattern('bulk/') => 'ManiphestBulkEditController',
|
||||
'task/' => array(
|
||||
$this->getEditRoutePattern('edit/')
|
||||
=> 'ManiphestTaskEditController',
|
||||
),
|
||||
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
|
||||
'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.'))
|
||||
->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE)
|
||||
->setIsCopyable(true)
|
||||
->setIsNullable(true)
|
||||
->setSingleValue($object->getOwnerPHID())
|
||||
->setCommentActionLabel(pht('Assign / Claim'))
|
||||
->setCommentActionValue($owner_value)
|
||||
|
||||
@@ -206,8 +206,7 @@ final class ManiphestTransactionEditor
|
||||
$title = $object->getTitle();
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("T{$id}: {$title}")
|
||||
->addHeader('Thread-Topic', "T{$id}: ".$object->getOriginalTitle());
|
||||
->setSubject("T{$id}: {$title}");
|
||||
}
|
||||
|
||||
protected function buildMailBody(
|
||||
@@ -534,7 +533,6 @@ final class ManiphestTransactionEditor
|
||||
'status' => '""',
|
||||
'priority' => 0,
|
||||
'title' => '""',
|
||||
'originalTitle' => '""',
|
||||
'description' => '""',
|
||||
'dateCreated' => 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 $subtaskIDs;
|
||||
private $subtypes;
|
||||
private $closedEpochMin;
|
||||
private $closedEpochMax;
|
||||
private $closerPHIDs;
|
||||
|
||||
private $status = 'status-any';
|
||||
const STATUS_ANY = 'status-any';
|
||||
@@ -179,6 +182,17 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
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) {
|
||||
$this->needSubscriberPHIDs = $bool;
|
||||
return $this;
|
||||
@@ -411,6 +425,27 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
$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) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
@@ -754,7 +789,11 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
'outdated' => array(
|
||||
'vector' => array('-updated', '-id'),
|
||||
'name' => pht('Date Updated (Oldest First)'),
|
||||
),
|
||||
),
|
||||
'closed' => array(
|
||||
'vector' => array('closed', 'id'),
|
||||
'name' => pht('Date Closed (Latest First)'),
|
||||
),
|
||||
'title' => array(
|
||||
'vector' => array('title', 'id'),
|
||||
'name' => pht('Title'),
|
||||
@@ -773,6 +812,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
'outdated',
|
||||
'newest',
|
||||
'oldest',
|
||||
'closed',
|
||||
'title',
|
||||
)) + $orders;
|
||||
|
||||
@@ -822,6 +862,12 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
'column' => 'dateModified',
|
||||
'type' => 'int',
|
||||
),
|
||||
'closed' => array(
|
||||
'table' => 'task',
|
||||
'column' => 'closedEpoch',
|
||||
'type' => 'int',
|
||||
'null' => 'tail',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -840,6 +886,7 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
'status' => $task->getStatus(),
|
||||
'title' => $task->getTitle(),
|
||||
'updated' => $task->getDateModified(),
|
||||
'closed' => $task->getClosedEpoch(),
|
||||
);
|
||||
|
||||
foreach ($keys as $key) {
|
||||
|
||||
@@ -128,6 +128,17 @@ final class ManiphestTaskSearchEngine
|
||||
id(new PhabricatorSearchDateField())
|
||||
->setLabel(pht('Updated Before'))
|
||||
->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())
|
||||
->setLabel(pht('Page Size'))
|
||||
->setKey('limit'),
|
||||
@@ -155,6 +166,9 @@ final class ManiphestTaskSearchEngine
|
||||
'createdEnd',
|
||||
'modifiedStart',
|
||||
'modifiedEnd',
|
||||
'closedStart',
|
||||
'closedEnd',
|
||||
'closerPHIDs',
|
||||
'limit',
|
||||
);
|
||||
}
|
||||
@@ -210,6 +224,14 @@ final class ManiphestTaskSearchEngine
|
||||
$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) {
|
||||
$query->withOpenParents($map['hasParents']);
|
||||
}
|
||||
@@ -485,4 +507,131 @@ final class ManiphestTaskSearchEngine
|
||||
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 $title = '';
|
||||
protected $originalTitle = '';
|
||||
protected $description = '';
|
||||
protected $originalEmailSource;
|
||||
protected $mailKey;
|
||||
@@ -45,6 +44,9 @@ final class ManiphestTask extends ManiphestDAO
|
||||
protected $points;
|
||||
protected $subtype;
|
||||
|
||||
protected $closedEpoch;
|
||||
protected $closerPHID;
|
||||
|
||||
private $subscriberPHIDs = self::ATTACHABLE;
|
||||
private $groupByProjectPHID = self::ATTACHABLE;
|
||||
private $customFields = self::ATTACHABLE;
|
||||
@@ -83,7 +85,6 @@ final class ManiphestTask extends ManiphestDAO
|
||||
'status' => 'text64',
|
||||
'priority' => 'uint32',
|
||||
'title' => 'sort',
|
||||
'originalTitle' => 'text',
|
||||
'description' => 'text',
|
||||
'mailKey' => 'bytes20',
|
||||
'ownerOrdering' => 'text64?',
|
||||
@@ -92,6 +93,8 @@ final class ManiphestTask extends ManiphestDAO
|
||||
'points' => 'double?',
|
||||
'bridgedObjectPHID' => 'phid?',
|
||||
'subtype' => 'text64',
|
||||
'closedEpoch' => 'epoch?',
|
||||
'closerPHID' => 'phid?',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_phid' => null,
|
||||
@@ -133,6 +136,12 @@ final class ManiphestTask extends ManiphestDAO
|
||||
'key_subtype' => array(
|
||||
'columns' => array('subtype'),
|
||||
),
|
||||
'key_closed' => array(
|
||||
'columns' => array('closedEpoch'),
|
||||
),
|
||||
'key_closer' => array(
|
||||
'columns' => array('closerPHID', 'closedEpoch'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
@@ -176,14 +185,6 @@ final class ManiphestTask extends ManiphestDAO
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTitle($title) {
|
||||
$this->title = $title;
|
||||
if (!$this->getID()) {
|
||||
$this->originalTitle = $title;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMonogram() {
|
||||
return 'T'.$this->getID();
|
||||
}
|
||||
@@ -512,6 +513,16 @@ final class ManiphestTask extends ManiphestDAO
|
||||
->setKey('subtype')
|
||||
->setType('string')
|
||||
->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),
|
||||
);
|
||||
|
||||
$closed_epoch = $this->getClosedEpoch();
|
||||
if ($closed_epoch !== null) {
|
||||
$closed_epoch = (int)$closed_epoch;
|
||||
}
|
||||
|
||||
return array(
|
||||
'name' => $this->getTitle(),
|
||||
'description' => array(
|
||||
@@ -542,6 +558,8 @@ final class ManiphestTask extends ManiphestDAO
|
||||
'priority' => $priority_info,
|
||||
'points' => $this->getPoints(),
|
||||
'subtype' => $this->getSubtype(),
|
||||
'closerPHID' => $this->getCloserPHID(),
|
||||
'dateClosed' => $closed_epoch,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,11 @@ final class ManiphestTaskListView extends ManiphestView {
|
||||
->setHeader($task->getTitle())
|
||||
->setHref('/T'.$task->getID());
|
||||
|
||||
if ($task->getAuthorPHID()) {
|
||||
$author = $handles[$task->getAuthorPHID()];
|
||||
$item->addByline(pht('By: %s', $author->renderLink()));
|
||||
}
|
||||
|
||||
if ($task->getOwnerPHID()) {
|
||||
$owner = $handles[$task->getOwnerPHID()];
|
||||
$item->addByline(pht('Assigned: %s', $owner->renderLink()));
|
||||
@@ -87,19 +92,24 @@ final class ManiphestTaskListView extends ManiphestView {
|
||||
|
||||
$item->setStatusIcon($icon.' '.$color, $tooltip);
|
||||
|
||||
$date = phabricator_datetime($task->getDateModified(), $this->getUser());
|
||||
if ($task->isClosed()) {
|
||||
$closed_epoch = $task->getClosedEpoch();
|
||||
|
||||
if ($task->getAuthorPHID()) {
|
||||
$author = idx($handles, $task->getAuthorPHID());
|
||||
// TODO: This should be guaranteed, see T3817.
|
||||
if ($author) {
|
||||
$date = array($date, " by ", $author->renderLink());
|
||||
// We don't expect a task to be closed without a closed epoch, but
|
||||
// recover if we find one. This can happen with older objects or with
|
||||
// lipsum test data.
|
||||
if (!$closed_epoch) {
|
||||
$closed_epoch = $task->getDateModified();
|
||||
}
|
||||
}
|
||||
|
||||
$item->addIcon(
|
||||
'none',
|
||||
$date);
|
||||
$item->addIcon(
|
||||
'fa-check-square-o grey',
|
||||
phabricator_datetime($closed_epoch, $this->getUser()));
|
||||
} else {
|
||||
$item->addIcon(
|
||||
'none',
|
||||
phabricator_datetime($task->getDateModified(), $this->getUser()));
|
||||
}
|
||||
|
||||
if ($this->showSubpriorityControls) {
|
||||
$item->setGrippable(true);
|
||||
|
||||
@@ -175,8 +175,7 @@ final class ManiphestTaskResultListView extends ManiphestView {
|
||||
}
|
||||
|
||||
if (!$user->isLoggedIn()) {
|
||||
// Don't show the batch editor or excel export for logged-out users.
|
||||
// Technically we //could// let them export, but ehh.
|
||||
// Don't show the batch editor for logged-out users.
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -220,14 +219,6 @@ final class ManiphestTaskResultListView extends ManiphestView {
|
||||
),
|
||||
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(
|
||||
'div',
|
||||
array(
|
||||
@@ -239,14 +230,12 @@ final class ManiphestTaskResultListView extends ManiphestView {
|
||||
'<table class="maniphest-batch-editor-layout">'.
|
||||
'<tr>'.
|
||||
'<td>%s%s</td>'.
|
||||
'<td>%s</td>'.
|
||||
'<td id="batch-select-status-cell">%s</td>'.
|
||||
'<td class="batch-select-submit-cell">%s%s</td>'.
|
||||
'</tr>'.
|
||||
'</table>',
|
||||
$select_all,
|
||||
$select_none,
|
||||
$export,
|
||||
'',
|
||||
$submit,
|
||||
$hidden);
|
||||
|
||||
@@ -10,7 +10,7 @@ final class ManiphestTaskMergedIntoTransaction
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setStatus(ManiphestTaskStatus::getDuplicateStatus());
|
||||
$this->updateStatus($object, ManiphestTaskStatus::getDuplicateStatus());
|
||||
}
|
||||
|
||||
public function getActionName() {
|
||||
|
||||
@@ -10,7 +10,7 @@ final class ManiphestTaskStatusTransaction
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setStatus($value);
|
||||
$this->updateStatus($object, $value);
|
||||
}
|
||||
|
||||
public function shouldHide() {
|
||||
|
||||
@@ -3,4 +3,27 @@
|
||||
abstract class ManiphestTaskTransactionType
|
||||
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 {
|
||||
|
||||
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 addReplyTo($email, $name = '');
|
||||
abstract public function addTos(array $emails);
|
||||
@@ -12,6 +28,7 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||
abstract public function setHTMLBody($html_body);
|
||||
abstract public function setSubject($subject);
|
||||
|
||||
|
||||
/**
|
||||
* Some mailers, notably Amazon SES, do not support us setting a specific
|
||||
* Message-ID header.
|
||||
@@ -32,4 +49,59 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||
*/
|
||||
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
|
||||
extends PhabricatorMailImplementationPHPMailerLiteAdapter {
|
||||
|
||||
const ADAPTERTYPE = 'ses';
|
||||
|
||||
private $message;
|
||||
private $isHTML;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
public function prepareForSend() {
|
||||
parent::prepareForSend();
|
||||
$this->mailer->Mailer = 'amazon-ses';
|
||||
$this->mailer->customMailer = $this;
|
||||
}
|
||||
@@ -17,13 +19,39 @@ final class PhabricatorMailImplementationAmazonSESAdapter
|
||||
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
|
||||
*/
|
||||
public function executeSend($body) {
|
||||
$key = PhabricatorEnv::getEnvConfig('amazon-ses.access-key');
|
||||
$secret = PhabricatorEnv::getEnvConfig('amazon-ses.secret-key');
|
||||
$endpoint = PhabricatorEnv::getEnvConfig('amazon-ses.endpoint');
|
||||
$key = $this->getOption('access-key');
|
||||
$secret = $this->getOption('secret-key');
|
||||
$endpoint = $this->getOption('endpoint');
|
||||
|
||||
$root = phutil_get_library_root('phabricator');
|
||||
$root = dirname($root);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
final class PhabricatorMailImplementationMailgunAdapter
|
||||
extends PhabricatorMailImplementationAdapter {
|
||||
|
||||
const ADAPTERTYPE = 'mailgun';
|
||||
|
||||
private $params = array();
|
||||
private $attachments = array();
|
||||
|
||||
@@ -19,7 +21,7 @@ final class PhabricatorMailImplementationMailgunAdapter
|
||||
if (empty($this->params['reply-to'])) {
|
||||
$this->params['reply-to'] = array();
|
||||
}
|
||||
$this->params['reply-to'][] = "{$name} <{$email}>";
|
||||
$this->params['reply-to'][] = $this->renderAddress($email, $name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -71,9 +73,32 @@ final class PhabricatorMailImplementationMailgunAdapter
|
||||
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() {
|
||||
$key = PhabricatorEnv::getEnvConfig('mailgun.api-key');
|
||||
$domain = PhabricatorEnv::getEnvConfig('mailgun.domain');
|
||||
$key = $this->getOption('api-key');
|
||||
$domain = $this->getOption('domain');
|
||||
$params = array();
|
||||
|
||||
$params['to'] = implode(', ', idx($this->params, 'tos', array()));
|
||||
@@ -85,11 +110,8 @@ final class PhabricatorMailImplementationMailgunAdapter
|
||||
}
|
||||
|
||||
$from = idx($this->params, 'from');
|
||||
if (idx($this->params, 'from-name')) {
|
||||
$params['from'] = "\"{$this->params['from-name']}\" <{$from}>";
|
||||
} else {
|
||||
$params['from'] = $from;
|
||||
}
|
||||
$from_name = idx($this->params, 'from-name');
|
||||
$params['from'] = $this->renderAddress($from, $from_name);
|
||||
|
||||
if (idx($this->params, 'reply-to')) {
|
||||
$replyto = $this->params['reply-to'];
|
||||
|
||||
@@ -3,40 +3,79 @@
|
||||
final class PhabricatorMailImplementationPHPMailerAdapter
|
||||
extends PhabricatorMailImplementationAdapter {
|
||||
|
||||
const ADAPTERTYPE = 'smtp';
|
||||
|
||||
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
|
||||
*/
|
||||
public function __construct() {
|
||||
public function prepareForSend() {
|
||||
$root = phutil_get_library_root('phabricator');
|
||||
$root = dirname($root);
|
||||
require_once $root.'/externals/phpmailer/class.phpmailer.php';
|
||||
$this->mailer = new PHPMailer($use_exceptions = true);
|
||||
$this->mailer->CharSet = 'utf-8';
|
||||
|
||||
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding');
|
||||
$encoding = $this->getOption('encoding');
|
||||
$this->mailer->Encoding = $encoding;
|
||||
|
||||
// By default, PHPMailer sends one mail per recipient. We handle
|
||||
// multiplexing higher in the stack, so tell it to send mail exactly
|
||||
// like we ask.
|
||||
// combining or separating To and Cc higher in the stack, so tell it to
|
||||
// send mail exactly like we ask.
|
||||
$this->mailer->SingleTo = false;
|
||||
|
||||
$mailer = PhabricatorEnv::getEnvConfig('phpmailer.mailer');
|
||||
$mailer = $this->getOption('mailer');
|
||||
if ($mailer == 'smtp') {
|
||||
$this->mailer->IsSMTP();
|
||||
$this->mailer->Host = PhabricatorEnv::getEnvConfig('phpmailer.smtp-host');
|
||||
$this->mailer->Port = PhabricatorEnv::getEnvConfig('phpmailer.smtp-port');
|
||||
$user = PhabricatorEnv::getEnvConfig('phpmailer.smtp-user');
|
||||
$this->mailer->Host = $this->getOption('host');
|
||||
$this->mailer->Port = $this->getOption('port');
|
||||
$user = $this->getOption('user');
|
||||
if ($user) {
|
||||
$this->mailer->SMTPAuth = true;
|
||||
$this->mailer->Username = $user;
|
||||
$this->mailer->Password =
|
||||
PhabricatorEnv::getEnvConfig('phpmailer.smtp-password');
|
||||
$this->mailer->Password = $this->getOption('password');
|
||||
}
|
||||
|
||||
$protocol = PhabricatorEnv::getEnvConfig('phpmailer.smtp-protocol');
|
||||
$protocol = $this->getOption('protocol');
|
||||
if ($protocol) {
|
||||
$protocol = phutil_utf8_strtolower($protocol);
|
||||
$this->mailer->SMTPSecure = $protocol;
|
||||
|
||||
@@ -6,24 +6,46 @@
|
||||
class PhabricatorMailImplementationPHPMailerLiteAdapter
|
||||
extends PhabricatorMailImplementationAdapter {
|
||||
|
||||
const ADAPTERTYPE = 'sendmail';
|
||||
|
||||
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
|
||||
*/
|
||||
public function __construct() {
|
||||
public function prepareForSend() {
|
||||
$root = phutil_get_library_root('phabricator');
|
||||
$root = dirname($root);
|
||||
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
|
||||
$this->mailer = new PHPMailerLite($use_exceptions = true);
|
||||
$this->mailer->CharSet = 'utf-8';
|
||||
|
||||
$encoding = PhabricatorEnv::getEnvConfig('phpmailer.smtp-encoding');
|
||||
$encoding = $this->getOption('encoding');
|
||||
$this->mailer->Encoding = $encoding;
|
||||
|
||||
// By default, PHPMailerLite sends one mail per recipient. We handle
|
||||
// multiplexing higher in the stack, so tell it to send mail exactly
|
||||
// like we ask.
|
||||
// combining or separating To and Cc higher in the stack, so tell it to
|
||||
// send mail exactly like we ask.
|
||||
$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
|
||||
extends PhabricatorMailImplementationAdapter {
|
||||
|
||||
const ADAPTERTYPE = 'sendgrid';
|
||||
|
||||
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 = '') {
|
||||
$this->params['from'] = $email;
|
||||
$this->params['from-name'] = $name;
|
||||
@@ -73,8 +98,8 @@ final class PhabricatorMailImplementationSendGridAdapter
|
||||
|
||||
public function send() {
|
||||
|
||||
$user = PhabricatorEnv::getEnvConfig('sendgrid.api-user');
|
||||
$key = PhabricatorEnv::getEnvConfig('sendgrid.api-key');
|
||||
$user = $this->getOption('api-user');
|
||||
$key = $this->getOption('api-key');
|
||||
|
||||
if (!$user || !$key) {
|
||||
throw new Exception(
|
||||
|
||||
@@ -7,10 +7,26 @@
|
||||
final class PhabricatorMailImplementationTestAdapter
|
||||
extends PhabricatorMailImplementationAdapter {
|
||||
|
||||
private $guts = array();
|
||||
private $config;
|
||||
const ADAPTERTYPE = 'test';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ final class PhabricatorMetaMTAApplication extends PhabricatorApplication {
|
||||
'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController',
|
||||
'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController',
|
||||
'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController',
|
||||
'postmark/' => 'PhabricatorMetaMTAPostmarkReceiveController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,23 @@ final class PhabricatorMetaMTAMailViewController
|
||||
$color = PhabricatorMailOutboundStatus::getStatusColor($status);
|
||||
$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()
|
||||
->addTextCrumb(pht('Mail %d', $mail->getID()))
|
||||
->setBorder(true);
|
||||
@@ -58,8 +75,26 @@ final class PhabricatorMetaMTAMailViewController
|
||||
->setKey('metadata')
|
||||
->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())
|
||||
->setHeaderText(pht('Mail'))
|
||||
->setHeader($header_view)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->addTabGroup($tab_group);
|
||||
|
||||
@@ -134,6 +169,12 @@ final class PhabricatorMetaMTAMailViewController
|
||||
|
||||
$properties->addTextContent($body);
|
||||
|
||||
$file_phids = $mail->getAttachmentFilePHIDs();
|
||||
if ($file_phids) {
|
||||
$properties->addProperty(
|
||||
pht('Attached Files'),
|
||||
$viewer->loadHandles($file_phids)->renderList());
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
@@ -158,6 +199,15 @@ final class PhabricatorMetaMTAMailViewController
|
||||
$properties->addProperty($key, $value);
|
||||
}
|
||||
|
||||
$encrypt_phids = $mail->getMustEncryptReasons();
|
||||
if ($encrypt_phids) {
|
||||
$properties->addProperty(
|
||||
pht('Must Encrypt'),
|
||||
$viewer->loadHandles($encrypt_phids)
|
||||
->renderList());
|
||||
}
|
||||
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,28 @@ final class PhabricatorMetaMTAMailgunReceiveController
|
||||
}
|
||||
|
||||
private function verifyMessage() {
|
||||
$api_key = PhabricatorEnv::getEnvConfig('mailgun.api-key');
|
||||
$request = $this->getRequest();
|
||||
$timestamp = $request->getStr('timestamp');
|
||||
$token = $request->getStr('token');
|
||||
$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) {
|
||||
|
||||
@@ -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) {
|
||||
// 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.
|
||||
$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',
|
||||
$this->getGarbageEpoch());
|
||||
|
||||
$engine = new PhabricatorDestructionEngine();
|
||||
foreach ($mails as $mail) {
|
||||
$mail->delete();
|
||||
$engine->destroyObject($mail);
|
||||
}
|
||||
|
||||
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) {
|
||||
return self::isMailGeneratingObject($object);
|
||||
}
|
||||
|
||||
public static function isMailGeneratingObject($object) {
|
||||
// NOTE: This implementation lacks generality, but there's no great way to
|
||||
// figure out if something generates email right now.
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ final class PhabricatorMailManagementListOutboundWorkflow
|
||||
$table = id(new PhutilConsoleTable())
|
||||
->setShowHeader(false)
|
||||
->addColumn('id', array('title' => pht('ID')))
|
||||
->addColumn('encrypt', array('title' => pht('#')))
|
||||
->addColumn('status', array('title' => pht('Status')))
|
||||
->addColumn('subject', array('title' => pht('Subject')));
|
||||
|
||||
@@ -45,6 +46,7 @@ final class PhabricatorMailManagementListOutboundWorkflow
|
||||
|
||||
$table->addRow(array(
|
||||
'id' => $mail->getID(),
|
||||
'encrypt' => ($mail->getMustEncrypt() ? '#' : ' '),
|
||||
'status' => PhabricatorMailOutboundStatus::getStatusName($status),
|
||||
'subject' => $mail->getSubject(),
|
||||
));
|
||||
|
||||
@@ -47,6 +47,11 @@ final class PhabricatorMailManagementSendTestWorkflow
|
||||
'help' => pht('Attach a file.'),
|
||||
'repeat' => true,
|
||||
),
|
||||
array(
|
||||
'name' => 'mailer',
|
||||
'param' => 'key',
|
||||
'help' => pht('Send with a specific configured mailer.'),
|
||||
),
|
||||
array(
|
||||
'name' => 'html',
|
||||
'help' => pht('Send as HTML mail.'),
|
||||
@@ -161,6 +166,21 @@ final class PhabricatorMailManagementSendTestWorkflow
|
||||
$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) {
|
||||
$data = Filesystem::readFile($attachment);
|
||||
$name = basename($attachment);
|
||||
|
||||
@@ -79,7 +79,7 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
||||
|
||||
$info = array();
|
||||
|
||||
$info[] = pht('PROPERTIES');
|
||||
$info[] = $this->newSectionHeader(pht('PROPERTIES'));
|
||||
$info[] = pht('ID: %d', $message->getID());
|
||||
$info[] = pht('Status: %s', $message->getStatus());
|
||||
$info[] = pht('Related PHID: %s', $message->getRelatedPHID());
|
||||
@@ -87,15 +87,17 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
||||
|
||||
$ignore = array(
|
||||
'body' => true,
|
||||
'body.sent' => true,
|
||||
'html-body' => true,
|
||||
'headers' => true,
|
||||
'attachments' => true,
|
||||
'headers.sent' => true,
|
||||
'headers.unfiltered' => true,
|
||||
'authors.sent' => true,
|
||||
);
|
||||
|
||||
$info[] = null;
|
||||
$info[] = pht('PARAMETERS');
|
||||
$info[] = $this->newSectionHeader(pht('PARAMETERS'));
|
||||
$parameters = $message->getParameters();
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (isset($ignore[$key])) {
|
||||
@@ -110,22 +112,40 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
||||
}
|
||||
|
||||
$info[] = null;
|
||||
$info[] = pht('HEADERS');
|
||||
$info[] = $this->newSectionHeader(pht('HEADERS'));
|
||||
|
||||
$headers = $message->getDeliveredHeaders();
|
||||
if (!$headers) {
|
||||
$unfiltered = $message->getUnfilteredHeaders();
|
||||
if (!$unfiltered) {
|
||||
$headers = $message->generateHeaders();
|
||||
$unfiltered = $headers;
|
||||
}
|
||||
|
||||
$header_map = array();
|
||||
foreach ($headers as $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');
|
||||
if ($attachments) {
|
||||
$info[] = null;
|
||||
$info[] = pht('ATTACHMENTS');
|
||||
|
||||
$info[] = $this->newSectionHeader(pht('ATTACHMENTS'));
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
$info[] = idx($attachment, 'filename', pht('Unnamed File'));
|
||||
}
|
||||
@@ -136,7 +156,9 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
||||
$actors = $message->getDeliveredActors();
|
||||
if ($actors) {
|
||||
$info[] = null;
|
||||
$info[] = pht('RECIPIENTS');
|
||||
|
||||
$info[] = $this->newSectionHeader(pht('RECIPIENTS'));
|
||||
|
||||
foreach ($actors as $actor_phid => $actor_info) {
|
||||
$actor = idx($all_actors, $actor_phid);
|
||||
if ($actor) {
|
||||
@@ -162,15 +184,22 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
||||
}
|
||||
|
||||
$info[] = null;
|
||||
$info[] = pht('TEXT BODY');
|
||||
$info[] = $this->newSectionHeader(pht('TEXT BODY'));
|
||||
if (strlen($message->getBody())) {
|
||||
$info[] = $message->getBody();
|
||||
$info[] = tsprintf('%B', $message->getBody());
|
||||
} else {
|
||||
$info[] = pht('(This message has no text body.)');
|
||||
}
|
||||
|
||||
$delivered_body = $message->getDeliveredBody();
|
||||
if ($delivered_body !== null) {
|
||||
$info[] = null;
|
||||
$info[] = $this->newSectionHeader(pht('BODY AS DELIVERED'), true);
|
||||
$info[] = tsprintf('%B', $delivered_body);
|
||||
}
|
||||
|
||||
$info[] = null;
|
||||
$info[] = pht('HTML BODY');
|
||||
$info[] = $this->newSectionHeader(pht('HTML BODY'));
|
||||
if (strlen($message->getHTMLBody())) {
|
||||
$info[] = $message->getHTMLBody();
|
||||
$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_MAIL = 'route-as-mail';
|
||||
const REASON_UNVERIFIED = 'unverified';
|
||||
const REASON_MUTED = 'muted';
|
||||
|
||||
private $phid;
|
||||
private $emailAddress;
|
||||
@@ -116,6 +117,7 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
||||
self::REASON_ROUTE_AS_NOTIFICATION => pht('Route as Notification'),
|
||||
self::REASON_ROUTE_AS_MAIL => pht('Route as Mail'),
|
||||
self::REASON_UNVERIFIED => pht('Address Not Verified'),
|
||||
self::REASON_MUTED => pht('Muted'),
|
||||
);
|
||||
|
||||
return idx($names, $reason, pht('Unknown ("%s")', $reason));
|
||||
@@ -172,6 +174,8 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
||||
'in Herald.'),
|
||||
self::REASON_UNVERIFIED => pht(
|
||||
'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));
|
||||
|
||||
@@ -6,6 +6,7 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
||||
private $applicationEmail;
|
||||
private $actor;
|
||||
private $excludePHIDs = array();
|
||||
private $unexpandablePHIDs = array();
|
||||
|
||||
final public function setMailReceiver($mail_receiver) {
|
||||
$this->validateMailReceiver($mail_receiver);
|
||||
@@ -45,6 +46,15 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
||||
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 getPrivateReplyHandlerEmailAddress(
|
||||
PhabricatorUser $user);
|
||||
@@ -297,6 +307,16 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
||||
$to_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);
|
||||
if ($all_phids) {
|
||||
$map = id(new PhabricatorMetaMTAMemberQuery())
|
||||
@@ -305,11 +325,21 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
|
||||
->execute();
|
||||
foreach ($to as $phid) {
|
||||
foreach ($map[$phid] as $expanded) {
|
||||
if ($expanded !== $phid) {
|
||||
if (isset($unexpandable[$expanded])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$to_result[$expanded] = $expanded;
|
||||
}
|
||||
}
|
||||
foreach ($cc as $phid) {
|
||||
foreach ($map[$phid] as $expanded) {
|
||||
if ($expanded !== $phid) {
|
||||
if (isset($unexpandable[$expanded])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$cc_result[$expanded] = $expanded;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,23 +58,55 @@ final class PhabricatorMailTarget extends Phobject {
|
||||
public function willSendMail(PhabricatorMetaMTAMail $mail) {
|
||||
$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-Cc', $this->rawCCPHIDs);
|
||||
|
||||
$to_handles = $viewer->loadHandles($this->rawToPHIDs);
|
||||
$cc_handles = $viewer->loadHandles($this->rawCCPHIDs);
|
||||
|
||||
$body = $mail->getBody();
|
||||
$body .= "\n";
|
||||
$body .= $this->getRecipientsSummary($to_handles, $cc_handles);
|
||||
$mail->setBody($body);
|
||||
|
||||
$html_body = $mail->getHTMLBody();
|
||||
if (strlen($html_body)) {
|
||||
if ($has_html) {
|
||||
$html_body .= hsprintf(
|
||||
'%s',
|
||||
$this->getRecipientsSummaryHTML($to_handles, $cc_handles));
|
||||
}
|
||||
|
||||
$mail->setBody($body);
|
||||
$mail->setHTMLBody($html_body);
|
||||
|
||||
$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
|
||||
|
||||
final class PhabricatorMetaMTAAttachment extends Phobject {
|
||||
protected $data;
|
||||
protected $filename;
|
||||
protected $mimetype;
|
||||
|
||||
private $data;
|
||||
private $filename;
|
||||
private $mimetype;
|
||||
private $file;
|
||||
private $filePHID;
|
||||
|
||||
public function __construct($data, $filename, $mimetype) {
|
||||
$this->setData($data);
|
||||
@@ -39,18 +42,49 @@ final class PhabricatorMetaMTAAttachment extends Phobject {
|
||||
}
|
||||
|
||||
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(
|
||||
'filename' => $this->getFilename(),
|
||||
'mimetype' => $this->getMimeType(),
|
||||
'data' => $this->getData(),
|
||||
'filePHID' => $this->file->getPHID(),
|
||||
);
|
||||
}
|
||||
|
||||
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, 'filename'),
|
||||
idx($dict, 'mimetype'));
|
||||
|
||||
if ($file) {
|
||||
$attachment->file = $file;
|
||||
}
|
||||
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user