@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Modularize mail tags

Summary:
Ref T5861. Currently, mail tags are hard-coded; move them into applications. Each Editor defines its own tags.

This has zero impact on the UI or behavior.

Test Plan:
- Checked/unchecked some options, saved form.
- Swapped back to `master` and saw exactly the same values.

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5861

Differential Revision: https://secure.phabricator.com/D10238

+435 -109
+8
src/applications/audit/editor/PhabricatorAuditEditor.php
··· 3 3 final class PhabricatorAuditEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorAuditApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Audits'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/auth/editor/PhabricatorAuthProviderConfigEditor.php
··· 3 3 final class PhabricatorAuthProviderConfigEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorAuthApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Auth Providers'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/config/editor/PhabricatorConfigEditor.php
··· 3 3 final class PhabricatorConfigEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorConfigApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Phabricator Configuration'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/conpherence/editor/ConpherenceEditor.php
··· 5 5 const ERROR_EMPTY_PARTICIPANTS = 'error-empty-participants'; 6 6 const ERROR_EMPTY_MESSAGE = 'error-empty-message'; 7 7 8 + public function getEditorApplicationClass() { 9 + return 'PhabricatorConpherenceApplication'; 10 + } 11 + 12 + public function getEditorObjectsDescription() { 13 + return pht('Conpherence Threads'); 14 + } 15 + 8 16 public static function createConpherence( 9 17 PhabricatorUser $creator, 10 18 array $participant_phids,
+8
src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
··· 3 3 final class PhabricatorDashboardPanelTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorDashboardApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Dashboard Panels'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
··· 3 3 final class PhabricatorDashboardTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorDashboardApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Dashboards'); 12 + } 13 + 6 14 public static function addPanelToDashboard( 7 15 PhabricatorUser $actor, 8 16 PhabricatorContentSource $content_source,
+27
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 7 7 private $changedPriorToCommitURI; 8 8 private $isCloseByCommit; 9 9 10 + public function getEditorApplicationClass() { 11 + return 'PhabricatorDifferentialApplication'; 12 + } 13 + 14 + public function getEditorObjectsDescription() { 15 + return pht('Differential Revisions'); 16 + } 17 + 10 18 public function getDiffUpdateTransaction(array $xactions) { 11 19 $type_update = DifferentialTransaction::TYPE_UPDATE; 12 20 ··· 1190 1198 } 1191 1199 1192 1200 return $body; 1201 + } 1202 + 1203 + public function getMailTagsMap() { 1204 + return array( 1205 + MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEW_REQUEST => 1206 + pht('A revision is created.'), 1207 + MetaMTANotificationType::TYPE_DIFFERENTIAL_UPDATED => 1208 + pht('A revision is updated.'), 1209 + MetaMTANotificationType::TYPE_DIFFERENTIAL_COMMENT => 1210 + pht('Someone comments on a revision.'), 1211 + MetaMTANotificationType::TYPE_DIFFERENTIAL_CLOSED => 1212 + pht('A revision is closed.'), 1213 + MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEWERS => 1214 + pht("A revision's reviewers change."), 1215 + MetaMTANotificationType::TYPE_DIFFERENTIAL_CC => 1216 + pht("A revision's CCs change."), 1217 + MetaMTANotificationType::TYPE_DIFFERENTIAL_OTHER => 1218 + pht('Other revision activity not listed above occurs.'), 1219 + ); 1193 1220 } 1194 1221 1195 1222 protected function supportsSearch() {
+8
src/applications/drydock/editor/DrydockBlueprintEditor.php
··· 3 3 final class DrydockBlueprintEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorDrydockApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Drydock Blueprints'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/files/editor/PhabricatorFileEditor.php
··· 3 3 final class PhabricatorFileEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorFilesApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Files'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/harbormaster/editor/HarbormasterBuildPlanEditor.php
··· 3 3 final class HarbormasterBuildPlanEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorHarbormasterApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Harbormaster Build Plans'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16 $types[] = HarbormasterBuildPlanTransaction::TYPE_NAME;
+8
src/applications/harbormaster/editor/HarbormasterBuildStepEditor.php
··· 3 3 final class HarbormasterBuildStepEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorHarbormasterApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Harbormaster Build Steps'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/harbormaster/editor/HarbormasterBuildTransactionEditor.php
··· 3 3 final class HarbormasterBuildTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorHarbormasterApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Harbormaster Builds'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/harbormaster/editor/HarbormasterBuildableTransactionEditor.php
··· 3 3 final class HarbormasterBuildableTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorHarbormasterApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Harbormaster Buildables'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/herald/editor/HeraldRuleEditor.php
··· 3 3 final class HeraldRuleEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorHeraldApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Herald Rules'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/legalpad/editor/LegalpadDocumentEditor.php
··· 5 5 6 6 private $isContribution = false; 7 7 8 + public function getEditorApplicationClass() { 9 + return 'PhabricatorLegalpadApplication'; 10 + } 11 + 12 + public function getEditorObjectsDescription() { 13 + return pht('Legalpad Documents'); 14 + } 15 + 8 16 private function setIsContribution($is_contribution) { 9 17 $this->isContribution = $is_contribution; 10 18 }
+8
src/applications/macro/editor/PhabricatorMacroEditor.php
··· 3 3 final class PhabricatorMacroEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorMacroApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Macros'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+27
src/applications/maniphest/editor/ManiphestTransactionEditor.php
··· 5 5 6 6 private $heraldEmailPHIDs = array(); 7 7 8 + public function getEditorApplicationClass() { 9 + return 'PhabricatorManiphestApplication'; 10 + } 11 + 12 + public function getEditorObjectsDescription() { 13 + return pht('Maniphest Tasks'); 14 + } 15 + 8 16 public function getTransactionTypes() { 9 17 $types = parent::getTransactionTypes(); 10 18 ··· 426 434 } 427 435 428 436 return $phids; 437 + } 438 + 439 + public function getMailTagsMap() { 440 + return array( 441 + MetaMTANotificationType::TYPE_MANIPHEST_STATUS => 442 + pht("A task's status changes."), 443 + MetaMTANotificationType::TYPE_MANIPHEST_OWNER => 444 + pht("A task's owner changes."), 445 + MetaMTANotificationType::TYPE_MANIPHEST_PRIORITY => 446 + pht("A task's priority changes."), 447 + MetaMTANotificationType::TYPE_MANIPHEST_CC => 448 + pht("A task's CCs change."), 449 + MetaMTANotificationType::TYPE_MANIPHEST_PROJECTS => 450 + pht("A task's associated projects change."), 451 + MetaMTANotificationType::TYPE_MANIPHEST_COMMENT => 452 + pht('Someone comments on a task.'), 453 + MetaMTANotificationType::TYPE_MANIPHEST_OTHER => 454 + pht('Other task activity not listed above occurs.'), 455 + ); 429 456 } 430 457 431 458 protected function buildReplyHandler(PhabricatorLiskDAO $object) {
+8
src/applications/nuance/editor/NuanceItemEditor.php
··· 3 3 final class NuanceItemEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorNuanceApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Nuance Items'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/nuance/editor/NuanceQueueEditor.php
··· 3 3 final class NuanceQueueEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorNuanceApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Nuance Queues'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/nuance/editor/NuanceRequestorEditor.php
··· 3 3 final class NuanceRequestorEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorNuanceApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Nuance Requestors'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/nuance/editor/NuanceSourceEditor.php
··· 3 3 final class NuanceSourceEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorNuanceApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Nuance Sources'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php
··· 3 3 final class PassphraseCredentialTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorPassphraseApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Passphrase Credentials'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/paste/editor/PhabricatorPasteEditor.php
··· 5 5 6 6 private $pasteFile; 7 7 8 + public function getEditorApplicationClass() { 9 + return 'PhabricatorPasteApplication'; 10 + } 11 + 12 + public function getEditorObjectsDescription() { 13 + return pht('Pastes'); 14 + } 15 + 8 16 public static function initializeFileForPaste( 9 17 PhabricatorUser $actor, 10 18 $name,
+8
src/applications/people/editor/PhabricatorUserProfileEditor.php
··· 3 3 final class PhabricatorUserProfileEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorPeopleApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('User Profiles'); 12 + } 13 + 6 14 7 15 }
+8
src/applications/phlux/editor/PhluxVariableEditor.php
··· 3 3 final class PhluxVariableEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorPhluxApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Phlux Variables'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16 $types[] = PhluxTransaction::TYPE_EDIT_KEY;
+22
src/applications/pholio/editor/PholioMockEditor.php
··· 3 3 final class PholioMockEditor extends PhabricatorApplicationTransactionEditor { 4 4 5 5 private $newImages = array(); 6 + 7 + public function getEditorApplicationClass() { 8 + return 'PhabricatorPholioApplication'; 9 + } 10 + 11 + public function getEditorObjectsDescription() { 12 + return pht('Pholio Mocks'); 13 + } 14 + 6 15 private function setNewImages(array $new_images) { 7 16 assert_instances_of($new_images, 'PholioImage'); 8 17 $this->newImages = $new_images; ··· 409 418 410 419 protected function getMailSubjectPrefix() { 411 420 return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix'); 421 + } 422 + 423 + public function getMailTagsMap() { 424 + return array( 425 + MetaMTANotificationType::TYPE_PHOLIO_STATUS => 426 + pht("A mock's status changes."), 427 + MetaMTANotificationType::TYPE_PHOLIO_COMMENT => 428 + pht('Someone comments on a mock.'), 429 + MetaMTANotificationType::TYPE_PHOLIO_UPDATED => 430 + pht('Mock images or descriptions change.'), 431 + MetaMTANotificationType::TYPE_PHOLIO_OTHER => 432 + pht('Other mock activity not listed above occurs.'), 433 + ); 412 434 } 413 435 414 436 protected function shouldPublishFeedStory(
+8
src/applications/phortune/editor/PhortuneAccountEditor.php
··· 4 4 final class PhortuneAccountEditor 5 5 extends PhabricatorApplicationTransactionEditor { 6 6 7 + public function getEditorApplicationClass() { 8 + return 'PhabricatorPhortuneApplication'; 9 + } 10 + 11 + public function getEditorObjectsDescription() { 12 + return pht('Phortune Accounts'); 13 + } 14 + 7 15 public function getTransactionTypes() { 8 16 $types = parent::getTransactionTypes(); 9 17
+8
src/applications/phortune/editor/PhortuneProductEditor.php
··· 4 4 final class PhortuneProductEditor 5 5 extends PhabricatorApplicationTransactionEditor { 6 6 7 + public function getEditorApplicationClass() { 8 + return 'PhabricatorPhortuneApplication'; 9 + } 10 + 11 + public function getEditorObjectsDescription() { 12 + return pht('Phortune Products'); 13 + } 14 + 7 15 public function getTransactionTypes() { 8 16 $types = parent::getTransactionTypes(); 9 17
+4
src/applications/ponder/editor/PonderAnswerEditor.php
··· 2 2 3 3 final class PonderAnswerEditor extends PonderEditor { 4 4 5 + public function getEditorObjectsDescription() { 6 + return pht('Ponder Answers'); 7 + } 8 + 5 9 public function getTransactionTypes() { 6 10 $types = parent::getTransactionTypes(); 7 11
+4
src/applications/ponder/editor/PonderEditor.php
··· 3 3 abstract class PonderEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorPonderApplication'; 8 + } 9 + 6 10 protected function shouldPublishFeedStory( 7 11 PhabricatorLiskDAO $object, 8 12 array $xactions) {
+4
src/applications/ponder/editor/PonderQuestionEditor.php
··· 5 5 6 6 private $answer; 7 7 8 + public function getEditorObjectsDescription() { 9 + return pht('Ponder Questions'); 10 + } 11 + 8 12 /** 9 13 * This is used internally on @{method:applyInitialEffects} if a transaction 10 14 * of type PonderQuestionTransaction::TYPE_ANSWERS is in the mix. The value
+8
src/applications/project/editor/PhabricatorProjectColumnTransactionEditor.php
··· 3 3 final class PhabricatorProjectColumnTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorProjectApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Workboard Columns'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/project/editor/PhabricatorProjectTransactionEditor.php
··· 3 3 final class PhabricatorProjectTransactionEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorProjectApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Projects'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/releeph/editor/ReleephProductEditor.php
··· 3 3 final class ReleephProductEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorReleephApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Releeph Products'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/releeph/editor/ReleephRequestTransactionalEditor.php
··· 3 3 final class ReleephRequestTransactionalEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorReleephApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Releeph Requests'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+8
src/applications/repository/editor/PhabricatorRepositoryEditor.php
··· 3 3 final class PhabricatorRepositoryEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorDiffusionApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Repositories'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+69 -109
src/applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php
··· 35 35 36 36 $new_tags = $request->getArr('mailtags'); 37 37 $mailtags = $preferences->getPreference('mailtags', array()); 38 - $all_tags = $this->getMailTags(); 39 - 40 - $maniphest = 'PhabricatorManiphestApplication'; 41 - if (!PhabricatorApplication::isClassInstalled($maniphest)) { 42 - $all_tags = array_diff_key($all_tags, $this->getManiphestMailTags()); 43 - } 44 - 45 - $pholio = 'PhabricatorPholioApplication'; 46 - if (!PhabricatorApplication::isClassInstalled($pholio)) { 47 - $all_tags = array_diff_key($all_tags, $this->getPholioMailTags()); 48 - } 38 + $all_tags = $this->getAllTags($user); 49 39 50 40 foreach ($all_tags as $key => $label) { 51 41 $mailtags[$key] = (bool)idx($new_tags, $key, false); ··· 125 115 'CC\'d on). To receive email alerts when other objects are created, '. 126 116 'configure [[ /herald/ | Herald Rules ]].'. 127 117 "\n\n". 128 - '**Phabricator will send an email to your primary account when:**')); 118 + 'Phabricator will send an email to your primary account when:')); 119 + 120 + $editors = $this->getAllEditorsWithTags($user); 121 + 122 + // Find all the tags shared by more than one application, and put them 123 + // in a "common" group. 124 + $all_tags = array(); 125 + foreach ($editors as $editor) { 126 + foreach ($editor->getMailTagsMap() as $tag => $name) { 127 + if (empty($all_tags[$tag])) { 128 + $all_tags[$tag] = array( 129 + 'count' => 0, 130 + 'name' => $name, 131 + ); 132 + } 133 + $all_tags[$tag]['count']; 134 + } 135 + } 136 + 137 + $common_tags = array(); 138 + foreach ($all_tags as $tag => $info) { 139 + if ($info['count'] > 1) { 140 + $common_tags[$tag] = $info['name']; 141 + } 142 + } 129 143 130 - if (PhabricatorApplication::isClassInstalledForViewer( 131 - 'PhabricatorDifferentialApplication', $user)) { 132 - $form 133 - ->appendChild( 134 - $this->buildMailTagCheckboxes( 135 - $this->getDifferentialMailTags(), 136 - $mailtags) 137 - ->setLabel(pht('Differential'))); 144 + // Build up the groups of application-specific options. 145 + $tag_groups = array(); 146 + foreach ($editors as $editor) { 147 + $tag_groups[] = array( 148 + $editor->getEditorObjectsDescription(), 149 + array_diff_key($editor->getMailTagsMap(), $common_tags)); 138 150 } 139 151 140 - if (PhabricatorApplication::isClassInstalledForViewer( 141 - 'PhabricatorManiphestApplication', $user)) { 142 - $form->appendChild( 143 - $this->buildMailTagCheckboxes( 144 - $this->getManiphestMailTags(), 145 - $mailtags) 146 - ->setLabel(pht('Maniphest'))); 152 + // Sort them, then put "Common" at the top. 153 + $tag_groups = isort($tag_groups, 0); 154 + if ($common_tags) { 155 + array_unshift($tag_groups, array(pht('Common'), $common_tags)); 147 156 } 148 157 149 - if (PhabricatorApplication::isClassInstalledForViewer( 150 - 'PhabricatorPholioApplication', $user)) { 151 - $form->appendChild( 152 - $this->buildMailTagCheckboxes( 153 - $this->getPholioMailTags(), 154 - $mailtags) 155 - ->setLabel(pht('Pholio'))); 158 + // Finally, build the controls. 159 + foreach ($tag_groups as $spec) { 160 + list($label, $map) = $spec; 161 + $control = $this->buildMailTagControl($label, $map, $mailtags); 162 + $form->appendChild($control); 156 163 } 157 164 158 165 $form ··· 173 180 )); 174 181 } 175 182 176 - private function getMailTags() { 177 - return array( 178 - MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEW_REQUEST => 179 - pht('A revision is created.'), 180 - MetaMTANotificationType::TYPE_DIFFERENTIAL_UPDATED => 181 - pht('A revision is updated.'), 182 - MetaMTANotificationType::TYPE_DIFFERENTIAL_COMMENT => 183 - pht('Someone comments on a revision.'), 184 - MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEWERS => 185 - pht("A revision's reviewers change."), 186 - MetaMTANotificationType::TYPE_DIFFERENTIAL_CLOSED => 187 - pht('A revision is closed.'), 188 - MetaMTANotificationType::TYPE_DIFFERENTIAL_CC => 189 - pht("A revision's CCs change."), 190 - MetaMTANotificationType::TYPE_DIFFERENTIAL_OTHER => 191 - pht('Other revision activity not listed above occurs.'), 192 - MetaMTANotificationType::TYPE_MANIPHEST_STATUS => 193 - pht("A task's status changes."), 194 - MetaMTANotificationType::TYPE_MANIPHEST_OWNER => 195 - pht("A task's owner changes."), 196 - MetaMTANotificationType::TYPE_MANIPHEST_COMMENT => 197 - pht('Someone comments on a task.'), 198 - MetaMTANotificationType::TYPE_MANIPHEST_PRIORITY => 199 - pht("A task's priority changes."), 200 - MetaMTANotificationType::TYPE_MANIPHEST_CC => 201 - pht("A task's CCs change."), 202 - MetaMTANotificationType::TYPE_MANIPHEST_PROJECTS => 203 - pht("A task's associated projects change."), 204 - MetaMTANotificationType::TYPE_MANIPHEST_OTHER => 205 - pht('Other task activity not listed above occurs.'), 206 - MetaMTANotificationType::TYPE_PHOLIO_STATUS => 207 - pht("A mock's status changes."), 208 - MetaMTANotificationType::TYPE_PHOLIO_COMMENT => 209 - pht('Someone comments on a mock.'), 210 - MetaMTANotificationType::TYPE_PHOLIO_UPDATED => 211 - pht('Mock images or descriptions change.'), 212 - MetaMTANotificationType::TYPE_PHOLIO_OTHER => 213 - pht('Other mock activity not listed above occurs.'), 214 - ); 215 - } 183 + private function getAllEditorsWithTags(PhabricatorUser $user) { 184 + $editors = id(new PhutilSymbolLoader()) 185 + ->setAncestorClass('PhabricatorApplicationTransactionEditor') 186 + ->loadObjects(); 187 + 188 + foreach ($editors as $key => $editor) { 189 + // Remove editors which do not support mail tags. 190 + if (!$editor->getMailTagsMap()) { 191 + unset($editors[$key]); 192 + } 216 193 217 - private function getManiphestMailTags() { 218 - return array_select_keys( 219 - $this->getMailTags(), 220 - array( 221 - MetaMTANotificationType::TYPE_MANIPHEST_STATUS, 222 - MetaMTANotificationType::TYPE_MANIPHEST_OWNER, 223 - MetaMTANotificationType::TYPE_MANIPHEST_PRIORITY, 224 - MetaMTANotificationType::TYPE_MANIPHEST_CC, 225 - MetaMTANotificationType::TYPE_MANIPHEST_PROJECTS, 226 - MetaMTANotificationType::TYPE_MANIPHEST_COMMENT, 227 - MetaMTANotificationType::TYPE_MANIPHEST_OTHER, 228 - )); 229 - } 194 + // Remove editors for applications which are not installed. 195 + $app = $editor->getEditorApplicationClass(); 196 + if ($app !== null) { 197 + if (!PhabricatorApplication::isClassInstalledForViewer($app, $user)) { 198 + unset($editors[$key]); 199 + } 200 + } 201 + } 230 202 231 - private function getDifferentialMailTags() { 232 - return array_select_keys( 233 - $this->getMailTags(), 234 - array( 235 - MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEW_REQUEST, 236 - MetaMTANotificationType::TYPE_DIFFERENTIAL_UPDATED, 237 - MetaMTANotificationType::TYPE_DIFFERENTIAL_COMMENT, 238 - MetaMTANotificationType::TYPE_DIFFERENTIAL_CLOSED, 239 - MetaMTANotificationType::TYPE_DIFFERENTIAL_REVIEWERS, 240 - MetaMTANotificationType::TYPE_DIFFERENTIAL_CC, 241 - MetaMTANotificationType::TYPE_DIFFERENTIAL_OTHER, 242 - )); 203 + return $editors; 243 204 } 244 205 245 - private function getPholioMailTags() { 246 - return array_select_keys( 247 - $this->getMailTags(), 248 - array( 249 - MetaMTANotificationType::TYPE_PHOLIO_STATUS, 250 - MetaMTANotificationType::TYPE_PHOLIO_COMMENT, 251 - MetaMTANotificationType::TYPE_PHOLIO_UPDATED, 252 - MetaMTANotificationType::TYPE_PHOLIO_OTHER, 253 - )); 206 + private function getAllTags(PhabricatorUser $user) { 207 + $tags = array(); 208 + foreach ($this->getAllEditorsWithTags($user) as $editor) { 209 + $tags += $editor->getMailTagsMap(); 210 + } 211 + return $tags; 254 212 } 255 213 256 - private function buildMailTagCheckboxes( 214 + private function buildMailTagControl( 215 + $control_label, 257 216 array $tags, 258 217 array $prefs) { 259 218 260 219 $control = new AphrontFormCheckboxControl(); 220 + $control->setLabel($control_label); 261 221 foreach ($tags as $key => $label) { 262 222 $control->addCheckbox( 263 223 'mailtags['.$key.']',
+8
src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php
··· 3 3 final class PhabricatorSlowvoteEditor 4 4 extends PhabricatorApplicationTransactionEditor { 5 5 6 + public function getEditorApplicationClass() { 7 + return 'PhabricatorSlowvoteApplication'; 8 + } 9 + 10 + public function getEditorObjectsDescription() { 11 + return pht('Slowvotes'); 12 + } 13 + 6 14 public function getTransactionTypes() { 7 15 $types = parent::getTransactionTypes(); 8 16
+30
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 28 28 private $actingAsPHID; 29 29 private $disableEmail; 30 30 31 + 32 + /** 33 + * Get the class name for the application this editor is a part of. 34 + * 35 + * Uninstalling the application will disable the editor. 36 + * 37 + * @return string Editor's application class name. 38 + */ 39 + abstract public function getEditorApplicationClass(); 40 + 41 + 42 + /** 43 + * Get a description of the objects this editor edits, like "Differential 44 + * Revisions". 45 + * 46 + * @return string Human readable description of edited objects. 47 + */ 48 + abstract public function getEditorObjectsDescription(); 49 + 50 + 31 51 public function setActingAsPHID($acting_as_phid) { 32 52 $this->actingAsPHID = $acting_as_phid; 33 53 return $this; ··· 39 59 } 40 60 return $this->getActor()->getPHID(); 41 61 } 62 + 42 63 43 64 /** 44 65 * When the editor tries to apply transactions that have no effect, should ··· 1929 1950 1930 1951 return array_mergev($tags); 1931 1952 } 1953 + 1954 + /** 1955 + * @task mail 1956 + */ 1957 + public function getMailTagsMap() { 1958 + // TODO: We should move shared mail tags, like "comment", here. 1959 + return array(); 1960 + } 1961 + 1932 1962 1933 1963 /** 1934 1964 * @task mail