diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 8c426f8b7f..930beaa0eb 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,8 +9,8 @@ return array( 'names' => array( 'conpherence.pkg.css' => 'ff161f2d', 'conpherence.pkg.js' => 'b5b51108', - 'core.pkg.css' => '84ce260a', - 'core.pkg.js' => 'fffe0122', + 'core.pkg.css' => '24ffbe93', + 'core.pkg.js' => '2ff7879f', 'darkconsole.pkg.js' => '1f9a31bc', 'differential.pkg.css' => '90b30783', 'differential.pkg.js' => 'ddfeb49b', @@ -114,7 +114,7 @@ return array( 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/core/core.css' => '9f4cb463', - 'rsrc/css/core/remarkup.css' => '17c0fb37', + 'rsrc/css/core/remarkup.css' => 'd1a5e11e', 'rsrc/css/core/syntax.css' => 'cae95e89', 'rsrc/css/core/z-index.css' => '0233d039', 'rsrc/css/diviner/diviner-shared.css' => '896f1d43', @@ -378,7 +378,7 @@ return array( 'rsrc/js/application/config/behavior-reorder-fields.js' => 'b6993408', 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '4d863052', 'rsrc/js/application/conpherence/behavior-conpherence-search.js' => '9bbf3762', - 'rsrc/js/application/conpherence/behavior-durable-column.js' => 'aa3bd034', + 'rsrc/js/application/conpherence/behavior-durable-column.js' => '2ae077e1', 'rsrc/js/application/conpherence/behavior-menu.js' => 'c9b99b77', 'rsrc/js/application/conpherence/behavior-participant-pane.js' => '8604caa8', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '55616e04', @@ -639,7 +639,7 @@ return array( 'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc', 'javelin-behavior-doorkeeper-tag' => 'e5822781', 'javelin-behavior-drydock-live-operation-status' => '901935ef', - 'javelin-behavior-durable-column' => 'aa3bd034', + 'javelin-behavior-durable-column' => '2ae077e1', 'javelin-behavior-editengine-reorder-configs' => 'd7a74243', 'javelin-behavior-editengine-reorder-fields' => 'b59e1e96', 'javelin-behavior-error-log' => '6882e80a', @@ -804,7 +804,7 @@ return array( 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', 'phabricator-prefab' => 'c5af80a2', - 'phabricator-remarkup-css' => '17c0fb37', + 'phabricator-remarkup-css' => 'd1a5e11e', 'phabricator-search-results-css' => 'f87d23ad', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-slowvote-css' => 'a94b7230', @@ -1095,6 +1095,16 @@ return array( 'javelin-install', 'javelin-util', ), + '2ae077e1' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-behavior-device', + 'javelin-scrollbar', + 'javelin-quicksand', + 'phabricator-keyboard-shortcut', + 'conpherence-thread-manager', + ), '2b8de964' => array( 'javelin-install', 'javelin-util', @@ -1793,16 +1803,6 @@ return array( 'javelin-util', 'phabricator-prefab', ), - 'aa3bd034' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-behavior-device', - 'javelin-scrollbar', - 'javelin-quicksand', - 'phabricator-keyboard-shortcut', - 'conpherence-thread-manager', - ), 'ab2f381b' => array( 'javelin-request', 'javelin-behavior', diff --git a/resources/sql/autopatches/20170504.1.slowvote.shuffle.sql b/resources/sql/autopatches/20170504.1.slowvote.shuffle.sql new file mode 100644 index 0000000000..5797f3fd5c --- /dev/null +++ b/resources/sql/autopatches/20170504.1.slowvote.shuffle.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_slowvote.slowvote_poll + MODIFY shuffle BOOL NOT NULL DEFAULT 0; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4d6ef65368..8389ee567e 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -292,13 +292,14 @@ phutil_register_library_map(array( 'ConpherenceCreateThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php', 'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php', 'ConpherenceDurableColumnView' => 'applications/conpherence/view/ConpherenceDurableColumnView.php', + 'ConpherenceEditConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceEditConduitAPIMethod.php', + 'ConpherenceEditEngine' => 'applications/conpherence/editor/ConpherenceEditEngine.php', 'ConpherenceEditor' => 'applications/conpherence/editor/ConpherenceEditor.php', 'ConpherenceFulltextQuery' => 'applications/conpherence/query/ConpherenceFulltextQuery.php', 'ConpherenceIndex' => 'applications/conpherence/storage/ConpherenceIndex.php', 'ConpherenceLayoutView' => 'applications/conpherence/view/ConpherenceLayoutView.php', 'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php', 'ConpherenceMenuItemView' => 'applications/conpherence/view/ConpherenceMenuItemView.php', - 'ConpherenceNewRoomController' => 'applications/conpherence/controller/ConpherenceNewRoomController.php', 'ConpherenceNotificationPanelController' => 'applications/conpherence/controller/ConpherenceNotificationPanelController.php', 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', 'ConpherenceParticipantController' => 'applications/conpherence/controller/ConpherenceParticipantController.php', @@ -308,6 +309,7 @@ phutil_register_library_map(array( 'ConpherenceQueryThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryThreadConduitAPIMethod.php', 'ConpherenceQueryTransactionConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceQueryTransactionConduitAPIMethod.php', 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', + 'ConpherenceRoomEditController' => 'applications/conpherence/controller/ConpherenceRoomEditController.php', 'ConpherenceRoomListController' => 'applications/conpherence/controller/ConpherenceRoomListController.php', 'ConpherenceRoomPictureController' => 'applications/conpherence/controller/ConpherenceRoomPictureController.php', 'ConpherenceRoomPreferencesController' => 'applications/conpherence/controller/ConpherenceRoomPreferencesController.php', @@ -1122,29 +1124,40 @@ phutil_register_library_map(array( 'FundBackerPHIDType' => 'applications/fund/phid/FundBackerPHIDType.php', 'FundBackerProduct' => 'applications/fund/phortune/FundBackerProduct.php', 'FundBackerQuery' => 'applications/fund/query/FundBackerQuery.php', + 'FundBackerRefundTransaction' => 'applications/fund/xaction/FundBackerRefundTransaction.php', 'FundBackerSearchEngine' => 'applications/fund/query/FundBackerSearchEngine.php', + 'FundBackerStatusTransaction' => 'applications/fund/xaction/FundBackerStatusTransaction.php', 'FundBackerTransaction' => 'applications/fund/storage/FundBackerTransaction.php', 'FundBackerTransactionQuery' => 'applications/fund/query/FundBackerTransactionQuery.php', + 'FundBackerTransactionType' => 'applications/fund/xaction/FundBackerTransactionType.php', 'FundController' => 'applications/fund/controller/FundController.php', 'FundCreateInitiativesCapability' => 'applications/fund/capability/FundCreateInitiativesCapability.php', 'FundDAO' => 'applications/fund/storage/FundDAO.php', 'FundDefaultViewCapability' => 'applications/fund/capability/FundDefaultViewCapability.php', 'FundInitiative' => 'applications/fund/storage/FundInitiative.php', 'FundInitiativeBackController' => 'applications/fund/controller/FundInitiativeBackController.php', + 'FundInitiativeBackerTransaction' => 'applications/fund/xaction/FundInitiativeBackerTransaction.php', 'FundInitiativeCloseController' => 'applications/fund/controller/FundInitiativeCloseController.php', 'FundInitiativeCommentController' => 'applications/fund/controller/FundInitiativeCommentController.php', + 'FundInitiativeDescriptionTransaction' => 'applications/fund/xaction/FundInitiativeDescriptionTransaction.php', 'FundInitiativeEditController' => 'applications/fund/controller/FundInitiativeEditController.php', 'FundInitiativeEditor' => 'applications/fund/editor/FundInitiativeEditor.php', 'FundInitiativeFulltextEngine' => 'applications/fund/search/FundInitiativeFulltextEngine.php', 'FundInitiativeListController' => 'applications/fund/controller/FundInitiativeListController.php', + 'FundInitiativeMerchantTransaction' => 'applications/fund/xaction/FundInitiativeMerchantTransaction.php', + 'FundInitiativeNameTransaction' => 'applications/fund/xaction/FundInitiativeNameTransaction.php', 'FundInitiativePHIDType' => 'applications/fund/phid/FundInitiativePHIDType.php', 'FundInitiativeQuery' => 'applications/fund/query/FundInitiativeQuery.php', + 'FundInitiativeRefundTransaction' => 'applications/fund/xaction/FundInitiativeRefundTransaction.php', 'FundInitiativeRemarkupRule' => 'applications/fund/remarkup/FundInitiativeRemarkupRule.php', 'FundInitiativeReplyHandler' => 'applications/fund/mail/FundInitiativeReplyHandler.php', + 'FundInitiativeRisksTransaction' => 'applications/fund/xaction/FundInitiativeRisksTransaction.php', 'FundInitiativeSearchEngine' => 'applications/fund/query/FundInitiativeSearchEngine.php', + 'FundInitiativeStatusTransaction' => 'applications/fund/xaction/FundInitiativeStatusTransaction.php', 'FundInitiativeTransaction' => 'applications/fund/storage/FundInitiativeTransaction.php', 'FundInitiativeTransactionComment' => 'applications/fund/storage/FundInitiativeTransactionComment.php', 'FundInitiativeTransactionQuery' => 'applications/fund/query/FundInitiativeTransactionQuery.php', + 'FundInitiativeTransactionType' => 'applications/fund/xaction/FundInitiativeTransactionType.php', 'FundInitiativeViewController' => 'applications/fund/controller/FundInitiativeViewController.php', 'FundSchemaSpec' => 'applications/fund/storage/FundSchemaSpec.php', 'HarbormasterArcLintBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterArcLintBuildStepImplementation.php', @@ -1398,8 +1411,10 @@ phutil_register_library_map(array( 'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php', 'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php', 'LegalpadDocumentManageController' => 'applications/legalpad/controller/LegalpadDocumentManageController.php', + 'LegalpadDocumentPreambleTransaction' => 'applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php', 'LegalpadDocumentQuery' => 'applications/legalpad/query/LegalpadDocumentQuery.php', 'LegalpadDocumentRemarkupRule' => 'applications/legalpad/remarkup/LegalpadDocumentRemarkupRule.php', + 'LegalpadDocumentRequireSignatureTransaction' => 'applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php', 'LegalpadDocumentSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSearchEngine.php', 'LegalpadDocumentSignController' => 'applications/legalpad/controller/LegalpadDocumentSignController.php', 'LegalpadDocumentSignature' => 'applications/legalpad/storage/LegalpadDocumentSignature.php', @@ -1407,8 +1422,12 @@ phutil_register_library_map(array( 'LegalpadDocumentSignatureListController' => 'applications/legalpad/controller/LegalpadDocumentSignatureListController.php', 'LegalpadDocumentSignatureQuery' => 'applications/legalpad/query/LegalpadDocumentSignatureQuery.php', 'LegalpadDocumentSignatureSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSignatureSearchEngine.php', + 'LegalpadDocumentSignatureTypeTransaction' => 'applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php', 'LegalpadDocumentSignatureVerificationController' => 'applications/legalpad/controller/LegalpadDocumentSignatureVerificationController.php', 'LegalpadDocumentSignatureViewController' => 'applications/legalpad/controller/LegalpadDocumentSignatureViewController.php', + 'LegalpadDocumentTextTransaction' => 'applications/legalpad/xaction/LegalpadDocumentTextTransaction.php', + 'LegalpadDocumentTitleTransaction' => 'applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php', + 'LegalpadDocumentTransactionType' => 'applications/legalpad/xaction/LegalpadDocumentTransactionType.php', 'LegalpadMailReceiver' => 'applications/legalpad/mail/LegalpadMailReceiver.php', 'LegalpadObjectNeedsSignatureEdgeType' => 'applications/legalpad/edge/LegalpadObjectNeedsSignatureEdgeType.php', 'LegalpadReplyHandler' => 'applications/legalpad/mail/LegalpadReplyHandler.php', @@ -1760,23 +1779,32 @@ phutil_register_library_map(array( 'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php', 'PassphraseCredentialAuthorPolicyRule' => 'applications/passphrase/policyrule/PassphraseCredentialAuthorPolicyRule.php', 'PassphraseCredentialConduitController' => 'applications/passphrase/controller/PassphraseCredentialConduitController.php', + 'PassphraseCredentialConduitTransaction' => 'applications/passphrase/xaction/PassphraseCredentialConduitTransaction.php', 'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php', 'PassphraseCredentialCreateController' => 'applications/passphrase/controller/PassphraseCredentialCreateController.php', + 'PassphraseCredentialDescriptionTransaction' => 'applications/passphrase/xaction/PassphraseCredentialDescriptionTransaction.php', 'PassphraseCredentialDestroyController' => 'applications/passphrase/controller/PassphraseCredentialDestroyController.php', + 'PassphraseCredentialDestroyTransaction' => 'applications/passphrase/xaction/PassphraseCredentialDestroyTransaction.php', 'PassphraseCredentialEditController' => 'applications/passphrase/controller/PassphraseCredentialEditController.php', 'PassphraseCredentialFulltextEngine' => 'applications/passphrase/search/PassphraseCredentialFulltextEngine.php', 'PassphraseCredentialListController' => 'applications/passphrase/controller/PassphraseCredentialListController.php', 'PassphraseCredentialLockController' => 'applications/passphrase/controller/PassphraseCredentialLockController.php', + 'PassphraseCredentialLockTransaction' => 'applications/passphrase/xaction/PassphraseCredentialLockTransaction.php', + 'PassphraseCredentialLookedAtTransaction' => 'applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php', + 'PassphraseCredentialNameTransaction' => 'applications/passphrase/xaction/PassphraseCredentialNameTransaction.php', 'PassphraseCredentialPHIDType' => 'applications/passphrase/phid/PassphraseCredentialPHIDType.php', 'PassphraseCredentialPublicController' => 'applications/passphrase/controller/PassphraseCredentialPublicController.php', 'PassphraseCredentialQuery' => 'applications/passphrase/query/PassphraseCredentialQuery.php', 'PassphraseCredentialRevealController' => 'applications/passphrase/controller/PassphraseCredentialRevealController.php', 'PassphraseCredentialSearchEngine' => 'applications/passphrase/query/PassphraseCredentialSearchEngine.php', + 'PassphraseCredentialSecretIDTransaction' => 'applications/passphrase/xaction/PassphraseCredentialSecretIDTransaction.php', 'PassphraseCredentialTransaction' => 'applications/passphrase/storage/PassphraseCredentialTransaction.php', 'PassphraseCredentialTransactionEditor' => 'applications/passphrase/editor/PassphraseCredentialTransactionEditor.php', 'PassphraseCredentialTransactionQuery' => 'applications/passphrase/query/PassphraseCredentialTransactionQuery.php', + 'PassphraseCredentialTransactionType' => 'applications/passphrase/xaction/PassphraseCredentialTransactionType.php', 'PassphraseCredentialType' => 'applications/passphrase/credentialtype/PassphraseCredentialType.php', 'PassphraseCredentialTypeTestCase' => 'applications/passphrase/credentialtype/__tests__/PassphraseCredentialTypeTestCase.php', + 'PassphraseCredentialUsernameTransaction' => 'applications/passphrase/xaction/PassphraseCredentialUsernameTransaction.php', 'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php', 'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php', 'PassphraseDefaultEditCapability' => 'applications/passphrase/capability/PassphraseDefaultEditCapability.php', @@ -1847,9 +1875,12 @@ phutil_register_library_map(array( 'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php', 'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php', 'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php', + 'PhabricatorApplicationEditEngine' => 'applications/meta/editor/PhabricatorApplicationEditEngine.php', 'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php', + 'PhabricatorApplicationEditor' => 'applications/meta/editor/PhabricatorApplicationEditor.php', 'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php', 'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php', + 'PhabricatorApplicationPolicyChangeTransaction' => 'applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php', 'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php', 'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php', 'PhabricatorApplicationSchemaSpec' => 'applications/meta/storage/PhabricatorApplicationSchemaSpec.php', @@ -2389,6 +2420,8 @@ phutil_register_library_map(array( 'PhabricatorConpherenceNotificationsSetting' => 'applications/settings/setting/PhabricatorConpherenceNotificationsSetting.php', 'PhabricatorConpherencePreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorConpherencePreferencesSettingsPanel.php', 'PhabricatorConpherenceProfileMenuItem' => 'applications/search/menuitem/PhabricatorConpherenceProfileMenuItem.php', + 'PhabricatorConpherenceRoomContextFreeGrammar' => 'applications/conpherence/lipsum/PhabricatorConpherenceRoomContextFreeGrammar.php', + 'PhabricatorConpherenceRoomTestDataGenerator' => 'applications/conpherence/lipsum/PhabricatorConpherenceRoomTestDataGenerator.php', 'PhabricatorConpherenceSoundSetting' => 'applications/settings/setting/PhabricatorConpherenceSoundSetting.php', 'PhabricatorConpherenceThreadPHIDType' => 'applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php', 'PhabricatorConpherenceWidgetVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceWidgetVisibleSetting.php', @@ -2968,26 +3001,32 @@ phutil_register_library_map(array( 'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php', 'PhabricatorLunarPhasePolicyRule' => 'applications/policy/rule/PhabricatorLunarPhasePolicyRule.php', 'PhabricatorMacroApplication' => 'applications/macro/application/PhabricatorMacroApplication.php', + 'PhabricatorMacroAudioBehaviorTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php', 'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php', - 'PhabricatorMacroCommentController' => 'applications/macro/controller/PhabricatorMacroCommentController.php', + 'PhabricatorMacroAudioTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioTransaction.php', 'PhabricatorMacroConfigOptions' => 'applications/macro/config/PhabricatorMacroConfigOptions.php', 'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php', 'PhabricatorMacroDatasource' => 'applications/macro/typeahead/PhabricatorMacroDatasource.php', 'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php', + 'PhabricatorMacroDisabledTransaction' => 'applications/macro/xaction/PhabricatorMacroDisabledTransaction.php', 'PhabricatorMacroEditController' => 'applications/macro/controller/PhabricatorMacroEditController.php', + 'PhabricatorMacroEditEngine' => 'applications/macro/editor/PhabricatorMacroEditEngine.php', 'PhabricatorMacroEditor' => 'applications/macro/editor/PhabricatorMacroEditor.php', + 'PhabricatorMacroFileTransaction' => 'applications/macro/xaction/PhabricatorMacroFileTransaction.php', 'PhabricatorMacroListController' => 'applications/macro/controller/PhabricatorMacroListController.php', 'PhabricatorMacroMacroPHIDType' => 'applications/macro/phid/PhabricatorMacroMacroPHIDType.php', 'PhabricatorMacroMailReceiver' => 'applications/macro/mail/PhabricatorMacroMailReceiver.php', 'PhabricatorMacroManageCapability' => 'applications/macro/capability/PhabricatorMacroManageCapability.php', 'PhabricatorMacroMemeController' => 'applications/macro/controller/PhabricatorMacroMemeController.php', 'PhabricatorMacroMemeDialogController' => 'applications/macro/controller/PhabricatorMacroMemeDialogController.php', + 'PhabricatorMacroNameTransaction' => 'applications/macro/xaction/PhabricatorMacroNameTransaction.php', 'PhabricatorMacroQuery' => 'applications/macro/query/PhabricatorMacroQuery.php', 'PhabricatorMacroReplyHandler' => 'applications/macro/mail/PhabricatorMacroReplyHandler.php', 'PhabricatorMacroSearchEngine' => 'applications/macro/query/PhabricatorMacroSearchEngine.php', 'PhabricatorMacroTransaction' => 'applications/macro/storage/PhabricatorMacroTransaction.php', 'PhabricatorMacroTransactionComment' => 'applications/macro/storage/PhabricatorMacroTransactionComment.php', 'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php', + 'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php', 'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php', 'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php', 'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php', @@ -3873,10 +3912,12 @@ phutil_register_library_map(array( 'PhabricatorSlowvoteApplication' => 'applications/slowvote/application/PhabricatorSlowvoteApplication.php', 'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php', 'PhabricatorSlowvoteCloseController' => 'applications/slowvote/controller/PhabricatorSlowvoteCloseController.php', + 'PhabricatorSlowvoteCloseTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteCloseTransaction.php', 'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php', 'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php', 'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/PhabricatorSlowvoteDAO.php', 'PhabricatorSlowvoteDefaultViewCapability' => 'applications/slowvote/capability/PhabricatorSlowvoteDefaultViewCapability.php', + 'PhabricatorSlowvoteDescriptionTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteDescriptionTransaction.php', 'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php', 'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php', 'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php', @@ -3886,12 +3927,16 @@ phutil_register_library_map(array( 'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php', 'PhabricatorSlowvotePollPHIDType' => 'applications/slowvote/phid/PhabricatorSlowvotePollPHIDType.php', 'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php', + 'PhabricatorSlowvoteQuestionTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteQuestionTransaction.php', 'PhabricatorSlowvoteReplyHandler' => 'applications/slowvote/mail/PhabricatorSlowvoteReplyHandler.php', + 'PhabricatorSlowvoteResponsesTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteResponsesTransaction.php', 'PhabricatorSlowvoteSchemaSpec' => 'applications/slowvote/storage/PhabricatorSlowvoteSchemaSpec.php', 'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php', + 'PhabricatorSlowvoteShuffleTransaction' => 'applications/slowvote/xactions/PhabricatorSlowvoteShuffleTransaction.php', 'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php', 'PhabricatorSlowvoteTransactionComment' => 'applications/slowvote/storage/PhabricatorSlowvoteTransactionComment.php', 'PhabricatorSlowvoteTransactionQuery' => 'applications/slowvote/query/PhabricatorSlowvoteTransactionQuery.php', + 'PhabricatorSlowvoteTransactionType' => 'applications/slowvote/xactions/PhabricatorSlowvoteTransactionType.php', 'PhabricatorSlowvoteVoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteVoteController.php', 'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php', 'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php', @@ -3909,13 +3954,18 @@ phutil_register_library_map(array( 'PhabricatorSpacesInterface' => 'applications/spaces/interface/PhabricatorSpacesInterface.php', 'PhabricatorSpacesListController' => 'applications/spaces/controller/PhabricatorSpacesListController.php', 'PhabricatorSpacesNamespace' => 'applications/spaces/storage/PhabricatorSpacesNamespace.php', + 'PhabricatorSpacesNamespaceArchiveTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php', 'PhabricatorSpacesNamespaceDatasource' => 'applications/spaces/typeahead/PhabricatorSpacesNamespaceDatasource.php', + 'PhabricatorSpacesNamespaceDefaultTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceDefaultTransaction.php', + 'PhabricatorSpacesNamespaceDescriptionTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceDescriptionTransaction.php', 'PhabricatorSpacesNamespaceEditor' => 'applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php', + 'PhabricatorSpacesNamespaceNameTransaction' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceNameTransaction.php', 'PhabricatorSpacesNamespacePHIDType' => 'applications/spaces/phid/PhabricatorSpacesNamespacePHIDType.php', 'PhabricatorSpacesNamespaceQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceQuery.php', 'PhabricatorSpacesNamespaceSearchEngine' => 'applications/spaces/query/PhabricatorSpacesNamespaceSearchEngine.php', 'PhabricatorSpacesNamespaceTransaction' => 'applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php', 'PhabricatorSpacesNamespaceTransactionQuery' => 'applications/spaces/query/PhabricatorSpacesNamespaceTransactionQuery.php', + 'PhabricatorSpacesNamespaceTransactionType' => 'applications/spaces/xaction/PhabricatorSpacesNamespaceTransactionType.php', 'PhabricatorSpacesNoAccessController' => 'applications/spaces/controller/PhabricatorSpacesNoAccessController.php', 'PhabricatorSpacesRemarkupRule' => 'applications/spaces/remarkup/PhabricatorSpacesRemarkupRule.php', 'PhabricatorSpacesSchemaSpec' => 'applications/spaces/storage/PhabricatorSpacesSchemaSpec.php', @@ -4222,24 +4272,34 @@ phutil_register_library_map(array( 'PhameBlogController' => 'applications/phame/controller/blog/PhameBlogController.php', 'PhameBlogCreateCapability' => 'applications/phame/capability/PhameBlogCreateCapability.php', 'PhameBlogDatasource' => 'applications/phame/typeahead/PhameBlogDatasource.php', + 'PhameBlogDescriptionTransaction' => 'applications/phame/xaction/PhameBlogDescriptionTransaction.php', 'PhameBlogEditConduitAPIMethod' => 'applications/phame/conduit/PhameBlogEditConduitAPIMethod.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogEditEngine' => 'applications/phame/editor/PhameBlogEditEngine.php', 'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php', 'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php', + 'PhameBlogFullDomainTransaction' => 'applications/phame/xaction/PhameBlogFullDomainTransaction.php', 'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php', + 'PhameBlogHeaderImageTransaction' => 'applications/phame/xaction/PhameBlogHeaderImageTransaction.php', 'PhameBlogHeaderPictureController' => 'applications/phame/controller/blog/PhameBlogHeaderPictureController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', 'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php', 'PhameBlogManageController' => 'applications/phame/controller/blog/PhameBlogManageController.php', + 'PhameBlogNameTransaction' => 'applications/phame/xaction/PhameBlogNameTransaction.php', + 'PhameBlogParentDomainTransaction' => 'applications/phame/xaction/PhameBlogParentDomainTransaction.php', + 'PhameBlogParentSiteTransaction' => 'applications/phame/xaction/PhameBlogParentSiteTransaction.php', + 'PhameBlogProfileImageTransaction' => 'applications/phame/xaction/PhameBlogProfileImageTransaction.php', 'PhameBlogProfilePictureController' => 'applications/phame/controller/blog/PhameBlogProfilePictureController.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogReplyHandler' => 'applications/phame/mail/PhameBlogReplyHandler.php', 'PhameBlogSearchConduitAPIMethod' => 'applications/phame/conduit/PhameBlogSearchConduitAPIMethod.php', 'PhameBlogSearchEngine' => 'applications/phame/query/PhameBlogSearchEngine.php', 'PhameBlogSite' => 'applications/phame/site/PhameBlogSite.php', + 'PhameBlogStatusTransaction' => 'applications/phame/xaction/PhameBlogStatusTransaction.php', + 'PhameBlogSubtitleTransaction' => 'applications/phame/xaction/PhameBlogSubtitleTransaction.php', 'PhameBlogTransaction' => 'applications/phame/storage/PhameBlogTransaction.php', 'PhameBlogTransactionQuery' => 'applications/phame/query/PhameBlogTransactionQuery.php', + 'PhameBlogTransactionType' => 'applications/phame/xaction/PhameBlogTransactionType.php', 'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php', 'PhameConstants' => 'applications/phame/constants/PhameConstants.php', 'PhameController' => 'applications/phame/controller/PhameController.php', @@ -4251,12 +4311,15 @@ phutil_register_library_map(array( 'PhameNextPostView' => 'applications/phame/view/PhameNextPostView.php', 'PhamePost' => 'applications/phame/storage/PhamePost.php', 'PhamePostArchiveController' => 'applications/phame/controller/post/PhamePostArchiveController.php', + 'PhamePostBlogTransaction' => 'applications/phame/xaction/PhamePostBlogTransaction.php', + 'PhamePostBodyTransaction' => 'applications/phame/xaction/PhamePostBodyTransaction.php', 'PhamePostController' => 'applications/phame/controller/post/PhamePostController.php', 'PhamePostEditConduitAPIMethod' => 'applications/phame/conduit/PhamePostEditConduitAPIMethod.php', 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 'PhamePostEditEngine' => 'applications/phame/editor/PhamePostEditEngine.php', 'PhamePostEditor' => 'applications/phame/editor/PhamePostEditor.php', 'PhamePostFulltextEngine' => 'applications/phame/search/PhamePostFulltextEngine.php', + 'PhamePostHeaderImageTransaction' => 'applications/phame/xaction/PhamePostHeaderImageTransaction.php', 'PhamePostHeaderPictureController' => 'applications/phame/controller/post/PhamePostHeaderPictureController.php', 'PhamePostHistoryController' => 'applications/phame/controller/post/PhamePostHistoryController.php', 'PhamePostListController' => 'applications/phame/controller/post/PhamePostListController.php', @@ -4269,10 +4332,14 @@ phutil_register_library_map(array( 'PhamePostReplyHandler' => 'applications/phame/mail/PhamePostReplyHandler.php', 'PhamePostSearchConduitAPIMethod' => 'applications/phame/conduit/PhamePostSearchConduitAPIMethod.php', 'PhamePostSearchEngine' => 'applications/phame/query/PhamePostSearchEngine.php', + 'PhamePostSubtitleTransaction' => 'applications/phame/xaction/PhamePostSubtitleTransaction.php', + 'PhamePostTitleTransaction' => 'applications/phame/xaction/PhamePostTitleTransaction.php', 'PhamePostTransaction' => 'applications/phame/storage/PhamePostTransaction.php', 'PhamePostTransactionComment' => 'applications/phame/storage/PhamePostTransactionComment.php', 'PhamePostTransactionQuery' => 'applications/phame/query/PhamePostTransactionQuery.php', + 'PhamePostTransactionType' => 'applications/phame/xaction/PhamePostTransactionType.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', + 'PhamePostVisibilityTransaction' => 'applications/phame/xaction/PhamePostVisibilityTransaction.php', 'PhameSchemaSpec' => 'applications/phame/storage/PhameSchemaSpec.php', 'PhameSite' => 'applications/phame/site/PhameSite.php', 'PhluxController' => 'applications/phlux/controller/PhluxController.php', @@ -4547,18 +4614,22 @@ phutil_register_library_map(array( 'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', 'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', 'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php', + 'PonderAnswerContentTransaction' => 'applications/ponder/xaction/PonderAnswerContentTransaction.php', 'PonderAnswerEditController' => 'applications/ponder/controller/PonderAnswerEditController.php', 'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php', 'PonderAnswerHistoryController' => 'applications/ponder/controller/PonderAnswerHistoryController.php', 'PonderAnswerMailReceiver' => 'applications/ponder/mail/PonderAnswerMailReceiver.php', 'PonderAnswerPHIDType' => 'applications/ponder/phid/PonderAnswerPHIDType.php', 'PonderAnswerQuery' => 'applications/ponder/query/PonderAnswerQuery.php', + 'PonderAnswerQuestionIDTransaction' => 'applications/ponder/xaction/PonderAnswerQuestionIDTransaction.php', 'PonderAnswerReplyHandler' => 'applications/ponder/mail/PonderAnswerReplyHandler.php', 'PonderAnswerSaveController' => 'applications/ponder/controller/PonderAnswerSaveController.php', 'PonderAnswerStatus' => 'applications/ponder/constants/PonderAnswerStatus.php', + 'PonderAnswerStatusTransaction' => 'applications/ponder/xaction/PonderAnswerStatusTransaction.php', 'PonderAnswerTransaction' => 'applications/ponder/storage/PonderAnswerTransaction.php', 'PonderAnswerTransactionComment' => 'applications/ponder/storage/PonderAnswerTransactionComment.php', 'PonderAnswerTransactionQuery' => 'applications/ponder/query/PonderAnswerTransactionQuery.php', + 'PonderAnswerTransactionType' => 'applications/ponder/xaction/PonderAnswerTransactionType.php', 'PonderAnswerView' => 'applications/ponder/view/PonderAnswerView.php', 'PonderConstants' => 'applications/ponder/constants/PonderConstants.php', 'PonderController' => 'applications/ponder/controller/PonderController.php', @@ -4568,9 +4639,13 @@ phutil_register_library_map(array( 'PonderFooterView' => 'applications/ponder/view/PonderFooterView.php', 'PonderModerateCapability' => 'applications/ponder/capability/PonderModerateCapability.php', 'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php', + 'PonderQuestionAnswerTransaction' => 'applications/ponder/xaction/PonderQuestionAnswerTransaction.php', + 'PonderQuestionAnswerWikiTransaction' => 'applications/ponder/xaction/PonderQuestionAnswerWikiTransaction.php', 'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php', + 'PonderQuestionContentTransaction' => 'applications/ponder/xaction/PonderQuestionContentTransaction.php', 'PonderQuestionCreateMailReceiver' => 'applications/ponder/mail/PonderQuestionCreateMailReceiver.php', 'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php', + 'PonderQuestionEditEngine' => 'applications/ponder/editor/PonderQuestionEditEngine.php', 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 'PonderQuestionFulltextEngine' => 'applications/ponder/search/PonderQuestionFulltextEngine.php', 'PonderQuestionHistoryController' => 'applications/ponder/controller/PonderQuestionHistoryController.php', @@ -4582,9 +4657,12 @@ phutil_register_library_map(array( 'PonderQuestionSearchEngine' => 'applications/ponder/query/PonderQuestionSearchEngine.php', 'PonderQuestionStatus' => 'applications/ponder/constants/PonderQuestionStatus.php', 'PonderQuestionStatusController' => 'applications/ponder/controller/PonderQuestionStatusController.php', + 'PonderQuestionStatusTransaction' => 'applications/ponder/xaction/PonderQuestionStatusTransaction.php', + 'PonderQuestionTitleTransaction' => 'applications/ponder/xaction/PonderQuestionTitleTransaction.php', 'PonderQuestionTransaction' => 'applications/ponder/storage/PonderQuestionTransaction.php', 'PonderQuestionTransactionComment' => 'applications/ponder/storage/PonderQuestionTransactionComment.php', 'PonderQuestionTransactionQuery' => 'applications/ponder/query/PonderQuestionTransactionQuery.php', + 'PonderQuestionTransactionType' => 'applications/ponder/xaction/PonderQuestionTransactionType.php', 'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php', 'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php', 'PonderSchemaSpec' => 'applications/ponder/storage/PonderSchemaSpec.php', @@ -5074,13 +5152,14 @@ phutil_register_library_map(array( 'ConpherenceCreateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceDAO' => 'PhabricatorLiskDAO', 'ConpherenceDurableColumnView' => 'AphrontTagView', + 'ConpherenceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', + 'ConpherenceEditEngine' => 'PhabricatorEditEngine', 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 'ConpherenceFulltextQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceIndex' => 'ConpherenceDAO', 'ConpherenceLayoutView' => 'AphrontTagView', 'ConpherenceListController' => 'ConpherenceController', 'ConpherenceMenuItemView' => 'AphrontTagView', - 'ConpherenceNewRoomController' => 'ConpherenceController', 'ConpherenceNotificationPanelController' => 'ConpherenceController', 'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipantController' => 'ConpherenceController', @@ -5090,6 +5169,7 @@ phutil_register_library_map(array( 'ConpherenceQueryThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceQueryTransactionConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler', + 'ConpherenceRoomEditController' => 'ConpherenceController', 'ConpherenceRoomListController' => 'ConpherenceController', 'ConpherenceRoomPictureController' => 'ConpherenceController', 'ConpherenceRoomPreferencesController' => 'ConpherenceController', @@ -5997,9 +6077,12 @@ phutil_register_library_map(array( 'FundBackerPHIDType' => 'PhabricatorPHIDType', 'FundBackerProduct' => 'PhortuneProductImplementation', 'FundBackerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'FundBackerRefundTransaction' => 'FundBackerTransactionType', 'FundBackerSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'FundBackerTransaction' => 'PhabricatorApplicationTransaction', + 'FundBackerStatusTransaction' => 'FundBackerTransactionType', + 'FundBackerTransaction' => 'PhabricatorModularTransaction', 'FundBackerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'FundBackerTransactionType' => 'PhabricatorModularTransactionType', 'FundController' => 'PhabricatorController', 'FundCreateInitiativesCapability' => 'PhabricatorPolicyCapability', 'FundDAO' => 'PhabricatorLiskDAO', @@ -6017,20 +6100,28 @@ phutil_register_library_map(array( 'PhabricatorFulltextInterface', ), 'FundInitiativeBackController' => 'FundController', + 'FundInitiativeBackerTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeCloseController' => 'FundController', 'FundInitiativeCommentController' => 'FundController', + 'FundInitiativeDescriptionTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeEditController' => 'FundController', 'FundInitiativeEditor' => 'PhabricatorApplicationTransactionEditor', 'FundInitiativeFulltextEngine' => 'PhabricatorFulltextEngine', 'FundInitiativeListController' => 'FundController', + 'FundInitiativeMerchantTransaction' => 'FundInitiativeTransactionType', + 'FundInitiativeNameTransaction' => 'FundInitiativeTransactionType', 'FundInitiativePHIDType' => 'PhabricatorPHIDType', 'FundInitiativeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'FundInitiativeRefundTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'FundInitiativeReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', + 'FundInitiativeRisksTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'FundInitiativeTransaction' => 'PhabricatorApplicationTransaction', + 'FundInitiativeStatusTransaction' => 'FundInitiativeTransactionType', + 'FundInitiativeTransaction' => 'PhabricatorModularTransaction', 'FundInitiativeTransactionComment' => 'PhabricatorApplicationTransactionComment', 'FundInitiativeTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'FundInitiativeTransactionType' => 'PhabricatorModularTransactionType', 'FundInitiativeViewController' => 'FundController', 'FundSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'HarbormasterArcLintBuildStepImplementation' => 'HarbormasterBuildStepImplementation', @@ -6343,8 +6434,10 @@ phutil_register_library_map(array( 'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor', 'LegalpadDocumentListController' => 'LegalpadController', 'LegalpadDocumentManageController' => 'LegalpadController', + 'LegalpadDocumentPreambleTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentRemarkupRule' => 'PhabricatorObjectRemarkupRule', + 'LegalpadDocumentRequireSignatureTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine', 'LegalpadDocumentSignController' => 'LegalpadController', 'LegalpadDocumentSignature' => array( @@ -6355,15 +6448,19 @@ phutil_register_library_map(array( 'LegalpadDocumentSignatureListController' => 'LegalpadController', 'LegalpadDocumentSignatureQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'LegalpadDocumentSignatureSearchEngine' => 'PhabricatorApplicationSearchEngine', + 'LegalpadDocumentSignatureTypeTransaction' => 'LegalpadDocumentTransactionType', 'LegalpadDocumentSignatureVerificationController' => 'LegalpadController', 'LegalpadDocumentSignatureViewController' => 'LegalpadController', + 'LegalpadDocumentTextTransaction' => 'LegalpadDocumentTransactionType', + 'LegalpadDocumentTitleTransaction' => 'LegalpadDocumentTransactionType', + 'LegalpadDocumentTransactionType' => 'PhabricatorModularTransactionType', 'LegalpadMailReceiver' => 'PhabricatorObjectMailReceiver', 'LegalpadObjectNeedsSignatureEdgeType' => 'PhabricatorEdgeType', 'LegalpadReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'LegalpadRequireSignatureHeraldAction' => 'HeraldAction', 'LegalpadSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'LegalpadSignatureNeededByObjectEdgeType' => 'PhabricatorEdgeType', - 'LegalpadTransaction' => 'PhabricatorApplicationTransaction', + 'LegalpadTransaction' => 'PhabricatorModularTransaction', 'LegalpadTransactionComment' => 'PhabricatorApplicationTransactionComment', 'LegalpadTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'LegalpadTransactionView' => 'PhabricatorApplicationTransactionView', @@ -6758,23 +6855,32 @@ phutil_register_library_map(array( ), 'PassphraseCredentialAuthorPolicyRule' => 'PhabricatorPolicyRule', 'PassphraseCredentialConduitController' => 'PassphraseController', + 'PassphraseCredentialConduitTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialControl' => 'AphrontFormControl', 'PassphraseCredentialCreateController' => 'PassphraseController', + 'PassphraseCredentialDescriptionTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialDestroyController' => 'PassphraseController', + 'PassphraseCredentialDestroyTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialEditController' => 'PassphraseController', 'PassphraseCredentialFulltextEngine' => 'PhabricatorFulltextEngine', 'PassphraseCredentialListController' => 'PassphraseController', 'PassphraseCredentialLockController' => 'PassphraseController', + 'PassphraseCredentialLockTransaction' => 'PassphraseCredentialTransactionType', + 'PassphraseCredentialLookedAtTransaction' => 'PassphraseCredentialTransactionType', + 'PassphraseCredentialNameTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialPHIDType' => 'PhabricatorPHIDType', 'PassphraseCredentialPublicController' => 'PassphraseController', 'PassphraseCredentialQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PassphraseCredentialRevealController' => 'PassphraseController', 'PassphraseCredentialSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'PassphraseCredentialTransaction' => 'PhabricatorApplicationTransaction', + 'PassphraseCredentialSecretIDTransaction' => 'PassphraseCredentialTransactionType', + 'PassphraseCredentialTransaction' => 'PhabricatorModularTransaction', 'PassphraseCredentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 'PassphraseCredentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PassphraseCredentialTransactionType' => 'PhabricatorModularTransactionType', 'PassphraseCredentialType' => 'Phobject', 'PassphraseCredentialTypeTestCase' => 'PhabricatorTestCase', + 'PassphraseCredentialUsernameTransaction' => 'PassphraseCredentialTransactionType', 'PassphraseCredentialViewController' => 'PassphraseController', 'PassphraseDAO' => 'PhabricatorLiskDAO', 'PassphraseDefaultEditCapability' => 'PhabricatorPolicyCapability', @@ -6849,9 +6955,12 @@ phutil_register_library_map(array( 'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController', + 'PhabricatorApplicationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView', + 'PhabricatorApplicationEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController', + 'PhabricatorApplicationPolicyChangeTransaction' => 'PhabricatorApplicationTransactionType', 'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationSchemaSpec' => 'PhabricatorConfigSchemaSpec', @@ -7487,6 +7596,8 @@ phutil_register_library_map(array( 'PhabricatorConpherenceNotificationsSetting' => 'PhabricatorSelectSetting', 'PhabricatorConpherencePreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 'PhabricatorConpherenceProfileMenuItem' => 'PhabricatorProfileMenuItem', + 'PhabricatorConpherenceRoomContextFreeGrammar' => 'PhutilContextFreeGrammar', + 'PhabricatorConpherenceRoomTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorConpherenceSoundSetting' => 'PhabricatorSelectSetting', 'PhabricatorConpherenceThreadPHIDType' => 'PhabricatorPHIDType', 'PhabricatorConpherenceWidgetVisibleSetting' => 'PhabricatorInternalSetting', @@ -8144,26 +8255,32 @@ phutil_register_library_map(array( 'PhabricatorLogoutController' => 'PhabricatorAuthController', 'PhabricatorLunarPhasePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorMacroApplication' => 'PhabricatorApplication', + 'PhabricatorMacroAudioBehaviorTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroAudioController' => 'PhabricatorMacroController', - 'PhabricatorMacroCommentController' => 'PhabricatorMacroController', + 'PhabricatorMacroAudioTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMacroController' => 'PhabricatorController', 'PhabricatorMacroDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorMacroDisableController' => 'PhabricatorMacroController', - 'PhabricatorMacroEditController' => 'PhabricatorMacroController', + 'PhabricatorMacroDisabledTransaction' => 'PhabricatorMacroTransactionType', + 'PhabricatorMacroEditController' => 'PhameBlogController', + 'PhabricatorMacroEditEngine' => 'PhabricatorEditEngine', 'PhabricatorMacroEditor' => 'PhabricatorApplicationTransactionEditor', + 'PhabricatorMacroFileTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroListController' => 'PhabricatorMacroController', 'PhabricatorMacroMacroPHIDType' => 'PhabricatorPHIDType', 'PhabricatorMacroMailReceiver' => 'PhabricatorObjectMailReceiver', 'PhabricatorMacroManageCapability' => 'PhabricatorPolicyCapability', 'PhabricatorMacroMemeController' => 'PhabricatorMacroController', 'PhabricatorMacroMemeDialogController' => 'PhabricatorMacroController', + 'PhabricatorMacroNameTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorMacroReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhabricatorMacroSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'PhabricatorMacroTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorMacroTransaction' => 'PhabricatorModularTransaction', 'PhabricatorMacroTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorMacroViewController' => 'PhabricatorMacroController', 'PhabricatorMailEmailHeraldField' => 'HeraldField', 'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup', @@ -9238,10 +9355,12 @@ phutil_register_library_map(array( 'PhabricatorSlowvoteApplication' => 'PhabricatorApplication', 'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteCloseController' => 'PhabricatorSlowvoteController', + 'PhabricatorSlowvoteCloseTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteController' => 'PhabricatorController', 'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO', 'PhabricatorSlowvoteDefaultViewCapability' => 'PhabricatorPolicyCapability', + 'PhabricatorSlowvoteDescriptionTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteEditController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController', @@ -9261,12 +9380,16 @@ phutil_register_library_map(array( 'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvotePollPHIDType' => 'PhabricatorPHIDType', 'PhabricatorSlowvoteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorSlowvoteQuestionTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', + 'PhabricatorSlowvoteResponsesTransaction' => 'PhabricatorSlowvoteTransactionType', 'PhabricatorSlowvoteSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'PhabricatorSlowvoteTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorSlowvoteShuffleTransaction' => 'PhabricatorSlowvoteTransactionType', + 'PhabricatorSlowvoteTransaction' => 'PhabricatorModularTransaction', 'PhabricatorSlowvoteTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorSlowvoteTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhabricatorSlowvoteTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorSlowvoteVoteController' => 'PhabricatorSlowvoteController', 'PhabricatorSlug' => 'Phobject', 'PhabricatorSlugTestCase' => 'PhabricatorTestCase', @@ -9289,13 +9412,18 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionInterface', 'PhabricatorDestructibleInterface', ), + 'PhabricatorSpacesNamespaceArchiveTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespaceDatasource' => 'PhabricatorTypeaheadDatasource', + 'PhabricatorSpacesNamespaceDefaultTransaction' => 'PhabricatorSpacesNamespaceTransactionType', + 'PhabricatorSpacesNamespaceDescriptionTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespaceEditor' => 'PhabricatorApplicationTransactionEditor', + 'PhabricatorSpacesNamespaceNameTransaction' => 'PhabricatorSpacesNamespaceTransactionType', 'PhabricatorSpacesNamespacePHIDType' => 'PhabricatorPHIDType', 'PhabricatorSpacesNamespaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorSpacesNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorSpacesNamespaceTransaction' => 'PhabricatorModularTransaction', 'PhabricatorSpacesNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhabricatorSpacesNamespaceTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorSpacesNoAccessController' => 'PhabricatorSpacesController', 'PhabricatorSpacesRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PhabricatorSpacesSchemaSpec' => 'PhabricatorConfigSchemaSpec', @@ -9660,24 +9788,34 @@ phutil_register_library_map(array( 'PhameBlogController' => 'PhameController', 'PhameBlogCreateCapability' => 'PhabricatorPolicyCapability', 'PhameBlogDatasource' => 'PhabricatorTypeaheadDatasource', + 'PhameBlogDescriptionTransaction' => 'PhameBlogTransactionType', 'PhameBlogEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhameBlogEditController' => 'PhameBlogController', 'PhameBlogEditEngine' => 'PhabricatorEditEngine', 'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor', 'PhameBlogFeedController' => 'PhameBlogController', + 'PhameBlogFullDomainTransaction' => 'PhameBlogTransactionType', 'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine', + 'PhameBlogHeaderImageTransaction' => 'PhameBlogTransactionType', 'PhameBlogHeaderPictureController' => 'PhameBlogController', 'PhameBlogListController' => 'PhameBlogController', 'PhameBlogListView' => 'AphrontTagView', 'PhameBlogManageController' => 'PhameBlogController', + 'PhameBlogNameTransaction' => 'PhameBlogTransactionType', + 'PhameBlogParentDomainTransaction' => 'PhameBlogTransactionType', + 'PhameBlogParentSiteTransaction' => 'PhameBlogTransactionType', + 'PhameBlogProfileImageTransaction' => 'PhameBlogTransactionType', 'PhameBlogProfilePictureController' => 'PhameBlogController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhameBlogSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhameBlogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhameBlogSite' => 'PhameSite', - 'PhameBlogTransaction' => 'PhabricatorApplicationTransaction', + 'PhameBlogStatusTransaction' => 'PhameBlogTransactionType', + 'PhameBlogSubtitleTransaction' => 'PhameBlogTransactionType', + 'PhameBlogTransaction' => 'PhabricatorModularTransaction', 'PhameBlogTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhameBlogTransactionType' => 'PhabricatorModularTransactionType', 'PhameBlogViewController' => 'PhameLiveController', 'PhameConstants' => 'Phobject', 'PhameController' => 'PhabricatorController', @@ -9701,12 +9839,15 @@ phutil_register_library_map(array( 'PhabricatorFulltextInterface', ), 'PhamePostArchiveController' => 'PhamePostController', + 'PhamePostBlogTransaction' => 'PhamePostTransactionType', + 'PhamePostBodyTransaction' => 'PhamePostTransactionType', 'PhamePostController' => 'PhameController', 'PhamePostEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 'PhamePostEditController' => 'PhamePostController', 'PhamePostEditEngine' => 'PhabricatorEditEngine', 'PhamePostEditor' => 'PhabricatorApplicationTransactionEditor', 'PhamePostFulltextEngine' => 'PhabricatorFulltextEngine', + 'PhamePostHeaderImageTransaction' => 'PhamePostTransactionType', 'PhamePostHeaderPictureController' => 'PhamePostController', 'PhamePostHistoryController' => 'PhamePostController', 'PhamePostListController' => 'PhamePostController', @@ -9719,10 +9860,14 @@ phutil_register_library_map(array( 'PhamePostReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PhamePostSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'PhamePostSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'PhamePostTransaction' => 'PhabricatorApplicationTransaction', + 'PhamePostSubtitleTransaction' => 'PhamePostTransactionType', + 'PhamePostTitleTransaction' => 'PhamePostTransactionType', + 'PhamePostTransaction' => 'PhabricatorModularTransaction', 'PhamePostTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhamePostTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhamePostTransactionType' => 'PhabricatorModularTransactionType', 'PhamePostViewController' => 'PhameLiveController', + 'PhamePostVisibilityTransaction' => 'PhamePostTransactionType', 'PhameSchemaSpec' => 'PhabricatorConfigSchemaSpec', 'PhameSite' => 'PhabricatorSite', 'PhluxController' => 'PhabricatorController', @@ -10085,18 +10230,22 @@ phutil_register_library_map(array( 'PhabricatorDestructibleInterface', ), 'PonderAnswerCommentController' => 'PonderController', + 'PonderAnswerContentTransaction' => 'PonderAnswerTransactionType', 'PonderAnswerEditController' => 'PonderController', 'PonderAnswerEditor' => 'PonderEditor', 'PonderAnswerHistoryController' => 'PonderController', 'PonderAnswerMailReceiver' => 'PhabricatorObjectMailReceiver', 'PonderAnswerPHIDType' => 'PhabricatorPHIDType', 'PonderAnswerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PonderAnswerQuestionIDTransaction' => 'PonderAnswerTransactionType', 'PonderAnswerReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PonderAnswerSaveController' => 'PonderController', 'PonderAnswerStatus' => 'PonderConstants', - 'PonderAnswerTransaction' => 'PhabricatorApplicationTransaction', + 'PonderAnswerStatusTransaction' => 'PonderAnswerTransactionType', + 'PonderAnswerTransaction' => 'PhabricatorModularTransaction', 'PonderAnswerTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderAnswerTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PonderAnswerTransactionType' => 'PhabricatorModularTransactionType', 'PonderAnswerView' => 'AphrontTagView', 'PonderConstants' => 'Phobject', 'PonderController' => 'PhabricatorController', @@ -10118,9 +10267,13 @@ phutil_register_library_map(array( 'PhabricatorSpacesInterface', 'PhabricatorFulltextInterface', ), + 'PonderQuestionAnswerTransaction' => 'PonderQuestionTransactionType', + 'PonderQuestionAnswerWikiTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionCommentController' => 'PonderController', + 'PonderQuestionContentTransaction' => 'PonderQuestionTransactionType', 'PonderQuestionCreateMailReceiver' => 'PhabricatorMailReceiver', 'PonderQuestionEditController' => 'PonderController', + 'PonderQuestionEditEngine' => 'PhabricatorEditEngine', 'PonderQuestionEditor' => 'PonderEditor', 'PonderQuestionFulltextEngine' => 'PhabricatorFulltextEngine', 'PonderQuestionHistoryController' => 'PonderController', @@ -10132,9 +10285,12 @@ phutil_register_library_map(array( 'PonderQuestionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PonderQuestionStatus' => 'PonderConstants', 'PonderQuestionStatusController' => 'PonderController', - 'PonderQuestionTransaction' => 'PhabricatorApplicationTransaction', + 'PonderQuestionStatusTransaction' => 'PonderQuestionTransactionType', + 'PonderQuestionTitleTransaction' => 'PonderQuestionTransactionType', + 'PonderQuestionTransaction' => 'PhabricatorModularTransaction', 'PonderQuestionTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PonderQuestionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PonderQuestionTransactionType' => 'PhabricatorModularTransactionType', 'PonderQuestionViewController' => 'PonderController', 'PonderRemarkupRule' => 'PhabricatorObjectRemarkupRule', 'PonderSchemaSpec' => 'PhabricatorConfigSchemaSpec', diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 29f5ed35be..af683e0592 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -284,7 +284,6 @@ abstract class PhabricatorApplication throw new PhutilMethodNotImplementedException(); } - /* -( Fact Integration )--------------------------------------------------- */ diff --git a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php index eee6b46751..4ab13fd360 100644 --- a/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php +++ b/src/applications/calendar/editor/PhabricatorCalendarEventEditor.php @@ -127,6 +127,9 @@ final class PhabricatorCalendarEventEditor // Clear the availability caches for users whose availability is affected // by this edit. + $phids = mpull($object->getInvitees(), 'getInviteePHID'); + $phids = array_fuse($phids); + $invalidate_all = false; $invalidate_phids = array(); foreach ($xactions as $xaction) { @@ -146,16 +149,21 @@ final class PhabricatorCalendarEventEditor $invalidate_phids[$acting_phid] = $acting_phid; break; case PhabricatorCalendarEventInviteTransaction::TRANSACTIONTYPE: - foreach ($xaction->getNewValue() as $phid => $ignored) { + foreach ($xaction->getOldValue() as $phid) { + // Add the possibly un-invited user to the list of potentially + // affected users if they are't already present. + $phids[$phid] = $phid; + + $invalidate_phids[$phid] = $phid; + } + + foreach ($xaction->getNewValue() as $phid) { $invalidate_phids[$phid] = $phid; } break; } } - $phids = mpull($object->getInvitees(), 'getInviteePHID'); - $phids = array_fuse($phids); - if (!$invalidate_all) { $phids = array_select_keys($phids, $invalidate_phids); } @@ -168,10 +176,9 @@ final class PhabricatorCalendarEventEditor queryfx( $conn_w, 'UPDATE %T SET availabilityCacheTTL = NULL - WHERE phid IN (%Ls) AND availabilityCacheTTL >= %d', + WHERE phid IN (%Ls)', $user->getTableName(), - $phids, - $object->getStartDateTimeEpochForCache()); + $phids); } return $xactions; diff --git a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php index e969b48447..a0c21bd33a 100644 --- a/src/applications/conpherence/application/PhabricatorConpherenceApplication.php +++ b/src/applications/conpherence/application/PhabricatorConpherenceApplication.php @@ -45,8 +45,10 @@ final class PhabricatorConpherenceApplication extends PhabricatorApplication { => 'ConpherenceViewController', 'columnview/' => 'ConpherenceColumnViewController', - 'new/' - => 'ConpherenceNewRoomController', + $this->getEditRoutePattern('new/') + => 'ConpherenceRoomEditController', + $this->getEditRoutePattern('edit/') + => 'ConpherenceRoomEditController', 'picture/(?P[1-9]\d*)/' => 'ConpherenceRoomPictureController', 'search/(?:query/(?P[^/]+)/)?' diff --git a/src/applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php b/src/applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php index 9cae87e10a..e751318c16 100644 --- a/src/applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php +++ b/src/applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php @@ -11,6 +11,16 @@ final class ConpherenceCreateThreadConduitAPIMethod return pht('Create a new conpherence thread.'); } + public function getMethodStatus() { + return self::METHOD_STATUS_FROZEN; + } + + public function getMethodStatusDescription() { + return pht( + 'This method is frozen and will eventually be deprecated. New code '. + 'should use "conpherence.edit" instead.'); + } + protected function defineParamTypes() { return array( 'title' => 'required string', diff --git a/src/applications/conpherence/conduit/ConpherenceEditConduitAPIMethod.php b/src/applications/conpherence/conduit/ConpherenceEditConduitAPIMethod.php new file mode 100644 index 0000000000..9fc799c194 --- /dev/null +++ b/src/applications/conpherence/conduit/ConpherenceEditConduitAPIMethod.php @@ -0,0 +1,19 @@ + 'optional int', diff --git a/src/applications/conpherence/constants/ConpherenceUpdateActions.php b/src/applications/conpherence/constants/ConpherenceUpdateActions.php index a2b97f9c6a..afec800de3 100644 --- a/src/applications/conpherence/constants/ConpherenceUpdateActions.php +++ b/src/applications/conpherence/constants/ConpherenceUpdateActions.php @@ -2,7 +2,6 @@ final class ConpherenceUpdateActions extends ConpherenceConstants { - const METADATA = 'metadata'; const MESSAGE = 'message'; const DRAFT = 'draft'; const JOIN_ROOM = 'join_room'; diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php index f7fd7ef1b4..90328cca04 100644 --- a/src/applications/conpherence/controller/ConpherenceController.php +++ b/src/applications/conpherence/controller/ConpherenceController.php @@ -91,7 +91,8 @@ abstract class ConpherenceController extends PhabricatorController { $header->addActionItem( id(new PHUIIconCircleView()) - ->setHref($this->getApplicationURI("update/{$id}/")) + ->setHref( + $this->getApplicationURI('edit/'.$conpherence->getID()).'/') ->setIcon('fa-pencil') ->addClass('hide-on-device') ->setColor('violet') diff --git a/src/applications/conpherence/controller/ConpherenceNewRoomController.php b/src/applications/conpherence/controller/ConpherenceNewRoomController.php deleted file mode 100644 index 6cbe86aaa2..0000000000 --- a/src/applications/conpherence/controller/ConpherenceNewRoomController.php +++ /dev/null @@ -1,117 +0,0 @@ -getUser(); - - $title = pht('New Room'); - $e_title = true; - $validation_exception = null; - - $conpherence = ConpherenceThread::initializeNewRoom($user); - $participants = array(); - if ($request->isFormPost()) { - $editor = new ConpherenceEditor(); - $xactions = array(); - - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(ConpherenceThreadTitleTransaction::TRANSACTIONTYPE) - ->setNewValue($request->getStr('title')); - - $participants = $request->getArr('participants'); - $participants[] = $user->getPHID(); - $participants = array_unique($participants); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType( - ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE) - ->setNewValue(array('+' => $participants)); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(ConpherenceThreadTopicTransaction::TRANSACTIONTYPE) - ->setNewValue($request->getStr('topic')); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) - ->setNewValue($request->getStr('viewPolicy')); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) - ->setNewValue($request->getStr('editPolicy')); - - try { - $editor - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true) - ->setActor($user) - ->applyTransactions($conpherence, $xactions); - - return id(new AphrontRedirectResponse()) - ->setURI('/'.$conpherence->getMonogram()); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - - $e_title = $ex->getShortMessage( - ConpherenceThreadTitleTransaction::TRANSACTIONTYPE); - - $conpherence->setViewPolicy($request->getStr('viewPolicy')); - $conpherence->setEditPolicy($request->getStr('editPolicy')); - } - } else { - if ($request->getStr('participant')) { - $participants[] = $request->getStr('participant'); - } - } - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) - ->setObject($conpherence) - ->execute(); - - $submit_uri = $this->getApplicationURI('new/'); - $cancel_uri = $this->getApplicationURI('search/'); - - $dialog = $this->newDialog() - ->setWidth(AphrontDialogView::WIDTH_FORM) - ->setValidationException($validation_exception) - ->setUser($user) - ->setTitle($title) - ->addCancelButton($cancel_uri) - ->addSubmitButton(pht('Create Room')); - - $form = id(new PHUIFormLayoutView()) - ->setUser($user) - ->appendChild( - id(new AphrontFormTextControl()) - ->setError($e_title) - ->setLabel(pht('Name')) - ->setName('title') - ->setValue($request->getStr('title'))) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Topic')) - ->setName('topic') - ->setValue($request->getStr('topic'))) - ->appendChild( - id(new AphrontFormTokenizerControl()) - ->setName('participants') - ->setUser($user) - ->setDatasource(new PhabricatorPeopleDatasource()) - ->setValue($participants) - ->setLabel(pht('Other Participants'))) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('viewPolicy') - ->setPolicyObject($conpherence) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicies($policies)) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('editPolicy') - ->setPolicyObject($conpherence) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicies($policies)); - - $dialog->appendChild($form); - - return id(new AphrontDialogResponse())->setDialog($dialog); - } - -} diff --git a/src/applications/conpherence/controller/ConpherenceRoomEditController.php b/src/applications/conpherence/controller/ConpherenceRoomEditController.php new file mode 100644 index 0000000000..56f808056c --- /dev/null +++ b/src/applications/conpherence/controller/ConpherenceRoomEditController.php @@ -0,0 +1,11 @@ +setController($this) + ->buildResponse(); + } +} diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php index 728d917589..a814c64452 100644 --- a/src/applications/conpherence/controller/ConpherenceUpdateController.php +++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php @@ -12,7 +12,7 @@ final class ConpherenceUpdateController $need_participants = false; $needed_capabilities = array(PhabricatorPolicyCapability::CAN_VIEW); - $action = $request->getStr('action', ConpherenceUpdateActions::METADATA); + $action = $request->getStr('action'); switch ($action) { case ConpherenceUpdateActions::REMOVE_PERSON: $person_phid = $request->getStr('remove_person'); @@ -21,7 +21,6 @@ final class ConpherenceUpdateController } break; case ConpherenceUpdateActions::ADD_PERSON: - case ConpherenceUpdateActions::METADATA: $needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT; break; case ConpherenceUpdateActions::LOAD: @@ -110,35 +109,6 @@ final class ConpherenceUpdateController $response_mode = 'go-home'; } break; - case ConpherenceUpdateActions::METADATA: - $title = $request->getStr('title'); - $topic = $request->getStr('topic'); - - // all other metadata updates are continue requests - if (!$request->isContinueRequest()) { - break; - } - - $title = $request->getStr('title'); - $topic = $request->getStr('topic'); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType( - ConpherenceThreadTitleTransaction::TRANSACTIONTYPE) - ->setNewValue($title); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType( - ConpherenceThreadTopicTransaction::TRANSACTIONTYPE) - ->setNewValue($topic); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) - ->setNewValue($request->getStr('viewPolicy')); - $xactions[] = id(new ConpherenceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) - ->setNewValue($request->getStr('editPolicy')); - if (!$request->getExists('force_ajax')) { - $response_mode = 'redirect'; - } - break; case ConpherenceUpdateActions::LOAD: $updated = false; $response_mode = 'ajax'; @@ -208,10 +178,6 @@ final class ConpherenceUpdateController case ConpherenceUpdateActions::REMOVE_PERSON: $dialog = $this->renderRemovePersonDialog($conpherence); break; - case ConpherenceUpdateActions::METADATA: - default: - $dialog = $this->renderMetadataDialog($conpherence, $error_view); - break; } return @@ -332,62 +298,6 @@ final class ConpherenceUpdateController return $dialog; } - private function renderMetadataDialog( - ConpherenceThread $conpherence, - $error_view) { - - $request = $this->getRequest(); - $user = $request->getUser(); - - $title = pht('Update Room'); - $form = id(new PHUIFormLayoutView()) - ->appendChild($error_view) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Title')) - ->setName('title') - ->setValue($conpherence->getTitle())) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Topic')) - ->setName('topic') - ->setValue($conpherence->getTopic())); - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($user) - ->setObject($conpherence) - ->execute(); - - $form - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('viewPolicy') - ->setPolicyObject($conpherence) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicies($policies)) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('editPolicy') - ->setPolicyObject($conpherence) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicies($policies)); - - $view = id(new AphrontDialogView()) - ->setTitle($title) - ->addHiddenInput('action', 'metadata') - ->addHiddenInput( - 'latest_transaction_id', - $request->getInt('latest_transaction_id')) - ->addHiddenInput('__continue__', true) - ->appendChild($form); - - if ($request->getExists('force_ajax')) { - $view->addHiddenInput('force_ajax', true); - } - - return $view; - } - private function loadAndRenderUpdates( $action, $conpherence_id, @@ -395,7 +305,6 @@ final class ConpherenceUpdateController $need_transactions = false; switch ($action) { - case ConpherenceUpdateActions::METADATA: case ConpherenceUpdateActions::LOAD: $need_transactions = true; break; @@ -444,15 +353,6 @@ final class ConpherenceUpdateController $header = null; $people_widget = null; switch ($action) { - case ConpherenceUpdateActions::METADATA: - $header = $this->buildHeaderPaneContent($conpherence); - $header = hsprintf('%s', $header); - $nav_item = id(new ConpherenceThreadListView()) - ->setUser($user) - ->setBaseURI($this->getApplicationURI()) - ->renderThreadItem($conpherence); - $nav_item = hsprintf('%s', $nav_item); - break; case ConpherenceUpdateActions::ADD_PERSON: $people_widget = id(new ConpherenceParticipantView()) ->setUser($user) diff --git a/src/applications/conpherence/editor/ConpherenceEditEngine.php b/src/applications/conpherence/editor/ConpherenceEditEngine.php new file mode 100644 index 0000000000..91cd8fd081 --- /dev/null +++ b/src/applications/conpherence/editor/ConpherenceEditEngine.php @@ -0,0 +1,118 @@ +getViewer()); + } + + protected function newObjectQuery() { + return new ConpherenceThreadQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Room'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit Room: %s', $object->getTitle()); + } + + protected function getObjectEditShortText($object) { + return $object->getTitle(); + } + + protected function getObjectCreateShortText() { + return pht('Create Room'); + } + + protected function getObjectName() { + return pht('Room'); + } + + protected function getObjectCreateCancelURI($object) { + return $this->getApplication()->getApplicationURI('/'); + } + + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('edit/'); + } + + protected function getObjectViewURI($object) { + return $object->getURI(); + } + + public function isEngineConfigurable() { + return false; + } + + protected function buildCustomEditFields($object) { + $viewer = $this->getViewer(); + + if ($this->getIsCreate()) { + $participant_phids = array($viewer->getPHID()); + $initial_phids = array(); + } else { + $participant_phids = $object->getParticipantPHIDs(); + $initial_phids = $participant_phids; + } + + // Only show participants on create or conduit, not edit + $conduit_only = !$this->getIsCreate(); + + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setDescription(pht('Room name.')) + ->setConduitTypeDescription(pht('New Room name.')) + ->setIsRequired(true) + ->setTransactionType( + ConpherenceThreadTitleTransaction::TRANSACTIONTYPE) + ->setValue($object->getTitle()), + + id(new PhabricatorTextEditField()) + ->setKey('topic') + ->setLabel(pht('Topic')) + ->setDescription(pht('Room topic.')) + ->setConduitTypeDescription(pht('New Room topic.')) + ->setTransactionType( + ConpherenceThreadTopicTransaction::TRANSACTIONTYPE) + ->setValue($object->getTopic()), + + id(new PhabricatorUsersEditField()) + ->setKey('participants') + ->setValue($participant_phids) + ->setInitialValue($initial_phids) + ->setIsConduitOnly($conduit_only) + ->setAliases(array('users', 'members', 'participants', 'userPHID')) + ->setDescription(pht('Room participants.')) + ->setUseEdgeTransactions(true) + ->setConduitTypeDescription(pht('New Room participants.')) + ->setTransactionType( + ConpherenceThreadParticipantsTransaction::TRANSACTIONTYPE) + ->setLabel(pht('Initial Participants')), + + ); + } + +} diff --git a/src/applications/conpherence/lipsum/PhabricatorConpherenceRoomContextFreeGrammar.php b/src/applications/conpherence/lipsum/PhabricatorConpherenceRoomContextFreeGrammar.php new file mode 100644 index 0000000000..5ff68b096f --- /dev/null +++ b/src/applications/conpherence/lipsum/PhabricatorConpherenceRoomContextFreeGrammar.php @@ -0,0 +1,97 @@ + array( + '[dept]', + '[dept]', + '[dept]', + '[dept]', + '[dept]', + '[dept]', + '[dept]', + '[dept] ([city])', + '[dept] ([city])', + '[dept] - [city]', + '[dept] - [room]', + '[dept] / [room]', + '[dept] [room]', + '[city] ([dept]) - [room]', + '[dept] ([city]) - [room]', + '[dept] ([city]) [room]', + ), + 'dept' => array( + 'Eng', + 'Engineering', + 'User Interface', + 'Design', + 'Data Science', + 'Database', + 'Marketing', + 'Content', + 'Ads', + 'Operations', + 'Network Ops', + 'Ops', + 'Server Ops', + 'IT', + 'Information Technology', + 'i18n', + 'Internationalization', + 'Human Resources', + 'HR', + 'Research & Development', + 'R&D', + 'Management', + 'Directors', + 'Managers', + 'Support', + 'Customer Support', + 'Finance', + 'Sales', + 'Purchasing', + 'Education', + 'Hardware Engineering', + 'Software', + 'Supply Management', + 'Logistics', + 'Growth', + 'Content Strategy', + 'Developer Relations', + 'Accounting', + 'Production', + ), + 'city' => array( + 'Palo Alto', + 'Mtn View', + 'Cupertino', + 'Los Altos', + 'Menlo Park', + 'Santa Cruz', + 'S.F.', + 'San Francisco', + 'Seattle', + 'London', + 'New York', + 'Dublin', + 'Tokyo', + ), + 'room' => array( + 'General', + 'Announcements', + 'Staff', + 'Interns', + 'Managers', + 'Book Club', + 'Parking', + 'Sports', + 'Social', + 'Commuting', + 'For Sale', + 'Parents@', + ), + ); + } +} diff --git a/src/applications/conpherence/lipsum/PhabricatorConpherenceRoomTestDataGenerator.php b/src/applications/conpherence/lipsum/PhabricatorConpherenceRoomTestDataGenerator.php new file mode 100644 index 0000000000..8346df3313 --- /dev/null +++ b/src/applications/conpherence/lipsum/PhabricatorConpherenceRoomTestDataGenerator.php @@ -0,0 +1,76 @@ +loadRandomUser(); + + $name = $this->newRoomName(); + + $participants = array(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + $participants[] = $this->loadRandomUser(); + + $rando_phids = array(); + $rando_phids[] = $author->getPHID(); + foreach ($participants as $actor) { + $rando_phids[] = $actor->getPHID(); + } + + $xactions = array(); + + $xactions[] = array( + 'type' => 'name', + 'value' => $name, + ); + + $xactions[] = array( + 'type' => 'participants.set', + 'value' => $rando_phids, + ); + + $xactions[] = array( + 'type' => 'view', + 'value' => 'users', + ); + + $xactions[] = array( + 'type' => 'edit', + 'value' => 'users', + ); + + $params = array( + 'transactions' => $xactions, + ); + + $result = id(new ConduitCall('conpherence.edit', $params)) + ->setUser($author) + ->execute(); + + return $result['object']['phid']; + } + + protected function newRoomName() { + $generator = new PhabricatorConpherenceRoomContextFreeGrammar(); + $name = $generator->generate(); + return $name; + } + + + +} diff --git a/src/applications/conpherence/view/ConpherenceDurableColumnView.php b/src/applications/conpherence/view/ConpherenceDurableColumnView.php index e3240bc2e4..5d6a5eaaec 100644 --- a/src/applications/conpherence/view/ConpherenceDurableColumnView.php +++ b/src/applications/conpherence/view/ConpherenceDurableColumnView.php @@ -363,9 +363,9 @@ final class ConpherenceDurableColumnView extends AphrontTagView { $actions[] = array( 'name' => pht('Edit Room'), 'disabled' => !$can_edit, - 'href' => '/conpherence/update/'.$conpherence->getID().'/?nopic', + 'href' => '/conpherence/edit/'.$conpherence->getID().'/', 'icon' => 'fa-pencil', - 'key' => ConpherenceUpdateActions::METADATA, + 'key' => 'go_edit', ); $actions[] = array( 'name' => pht('View in Conpherence'), diff --git a/src/applications/conpherence/view/ConpherenceThreadListView.php b/src/applications/conpherence/view/ConpherenceThreadListView.php index af15f82a6e..42f1b605c1 100644 --- a/src/applications/conpherence/view/ConpherenceThreadListView.php +++ b/src/applications/conpherence/view/ConpherenceThreadListView.php @@ -117,7 +117,7 @@ final class ConpherenceThreadListView extends AphrontView { $new_icon = id(new PHUIIconView()) ->setIcon('fa-plus-square') ->addSigil('has-tooltip') - ->setHref('/conpherence/new/') + ->setHref('/conpherence/edit/') ->setWorkflow(true) ->setMetaData(array( 'tip' => pht('New Room'), diff --git a/src/applications/differential/editor/DifferentialTransactionEditor.php b/src/applications/differential/editor/DifferentialTransactionEditor.php index 0086c101e2..9204a1aadb 100644 --- a/src/applications/differential/editor/DifferentialTransactionEditor.php +++ b/src/applications/differential/editor/DifferentialTransactionEditor.php @@ -1191,12 +1191,23 @@ final class DifferentialTransactionEditor array $changes, PhutilMarkupEngine $engine) { - $flat_blocks = mpull($changes, 'getNewValue'); - $huge_block = implode("\n\n", $flat_blocks); - + // For "Fixes ..." and "Depends on ...", we're only going to look at + // content blocks which are part of the revision itself (like "Summary" + // and "Test Plan"), not comments. + $content_parts = array(); + foreach ($changes as $change) { + if ($change->getTransaction()->isCommentTransaction()) { + continue; + } + $content_parts[] = $change->getNewValue(); + } + if (!$content_parts) { + return array(); + } + $content_block = implode("\n\n", $content_parts); $task_map = array(); $task_refs = id(new ManiphestCustomFieldStatusParser()) - ->parseCorpus($huge_block); + ->parseCorpus($content_block); foreach ($task_refs as $match) { foreach ($match['monograms'] as $monogram) { $task_id = (int)trim($monogram, 'tT'); @@ -1206,7 +1217,7 @@ final class DifferentialTransactionEditor $rev_map = array(); $rev_refs = id(new DifferentialCustomFieldDependsOnParser()) - ->parseCorpus($huge_block); + ->parseCorpus($content_block); foreach ($rev_refs as $match) { foreach ($match['monograms'] as $monogram) { $rev_id = (int)trim($monogram, 'dD'); diff --git a/src/applications/fund/controller/FundInitiativeBackController.php b/src/applications/fund/controller/FundInitiativeBackController.php index 414a5ebd64..17ead82ebf 100644 --- a/src/applications/fund/controller/FundInitiativeBackController.php +++ b/src/applications/fund/controller/FundInitiativeBackController.php @@ -96,7 +96,7 @@ final class FundInitiativeBackController $xactions = array(); $xactions[] = id(new FundBackerTransaction()) - ->setTransactionType(FundBackerTransaction::TYPE_STATUS) + ->setTransactionType(FundBackerStatusTransaction::TRANSACTIONTYPE) ->setNewValue(FundBacker::STATUS_IN_CART); $editor = id(new FundBackerEditor()) diff --git a/src/applications/fund/controller/FundInitiativeCloseController.php b/src/applications/fund/controller/FundInitiativeCloseController.php index 6adddb0d80..97c6de3d97 100644 --- a/src/applications/fund/controller/FundInitiativeCloseController.php +++ b/src/applications/fund/controller/FundInitiativeCloseController.php @@ -25,7 +25,7 @@ final class FundInitiativeCloseController $is_close = !$initiative->isClosed(); if ($request->isFormPost()) { - $type_status = FundInitiativeTransaction::TYPE_STATUS; + $type_status = FundInitiativeStatusTransaction::TRANSACTIONTYPE; if ($is_close) { $new_status = FundInitiative::STATUS_CLOSED; diff --git a/src/applications/fund/controller/FundInitiativeEditController.php b/src/applications/fund/controller/FundInitiativeEditController.php index 6e092d1e05..0576e47330 100644 --- a/src/applications/fund/controller/FundInitiativeEditController.php +++ b/src/applications/fund/controller/FundInitiativeEditController.php @@ -68,10 +68,10 @@ final class FundInitiativeEditController $v_merchant = $request->getStr('merchantPHID'); $v_projects = $request->getArr('projects'); - $type_name = FundInitiativeTransaction::TYPE_NAME; - $type_desc = FundInitiativeTransaction::TYPE_DESCRIPTION; - $type_risk = FundInitiativeTransaction::TYPE_RISKS; - $type_merchant = FundInitiativeTransaction::TYPE_MERCHANT; + $type_name = FundInitiativeNameTransaction::TRANSACTIONTYPE; + $type_desc = FundInitiativeDescriptionTransaction::TRANSACTIONTYPE; + $type_risk = FundInitiativeRisksTransaction::TRANSACTIONTYPE; + $type_merchant = FundInitiativeMerchantTransaction::TRANSACTIONTYPE; $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; diff --git a/src/applications/fund/controller/FundInitiativeViewController.php b/src/applications/fund/controller/FundInitiativeViewController.php index 4960e7aa35..eee79e4df0 100644 --- a/src/applications/fund/controller/FundInitiativeViewController.php +++ b/src/applications/fund/controller/FundInitiativeViewController.php @@ -29,8 +29,8 @@ final class FundInitiativeViewController $initiative->getName()); if ($initiative->isClosed()) { - $status_icon = 'fa-times'; - $status_color = 'bluegrey'; + $status_icon = 'fa-ban'; + $status_color = 'indigo'; } else { $status_icon = 'fa-check'; $status_color = 'bluegrey'; diff --git a/src/applications/fund/editor/FundBackerEditor.php b/src/applications/fund/editor/FundBackerEditor.php index aabd1d8e60..403853863b 100644 --- a/src/applications/fund/editor/FundBackerEditor.php +++ b/src/applications/fund/editor/FundBackerEditor.php @@ -11,67 +11,4 @@ final class FundBackerEditor return pht('Fund Backing'); } - public function getTransactionTypes() { - $types = parent::getTransactionTypes(); - - $types[] = FundBackerTransaction::TYPE_STATUS; - $types[] = FundBackerTransaction::TYPE_REFUND; - - return $types; - } - - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case FundBackerTransaction::TYPE_STATUS: - return $object->getStatus(); - case FundBackerTransaction::TYPE_REFUND: - return null; - } - - return parent::getCustomTransactionOldValue($object, $xaction); - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case FundBackerTransaction::TYPE_STATUS: - case FundBackerTransaction::TYPE_REFUND: - return $xaction->getNewValue(); - } - - return parent::getCustomTransactionNewValue($object, $xaction); - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case FundBackerTransaction::TYPE_STATUS: - $object->setStatus($xaction->getNewValue()); - return; - case FundBackerTransaction::TYPE_REFUND: - return; - } - - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case FundBackerTransaction::TYPE_STATUS: - case FundBackerTransaction::TYPE_REFUND: - return; - } - - return parent::applyCustomExternalTransaction($object, $xaction); - } - } diff --git a/src/applications/fund/editor/FundInitiativeEditor.php b/src/applications/fund/editor/FundInitiativeEditor.php index 40fc6f0174..e5c372fd12 100644 --- a/src/applications/fund/editor/FundInitiativeEditor.php +++ b/src/applications/fund/editor/FundInitiativeEditor.php @@ -11,16 +11,16 @@ final class FundInitiativeEditor return pht('Fund Initiatives'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s created this initiative.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); + } + public function getTransactionTypes() { $types = parent::getTransactionTypes(); - - $types[] = FundInitiativeTransaction::TYPE_NAME; - $types[] = FundInitiativeTransaction::TYPE_DESCRIPTION; - $types[] = FundInitiativeTransaction::TYPE_RISKS; - $types[] = FundInitiativeTransaction::TYPE_STATUS; - $types[] = FundInitiativeTransaction::TYPE_BACKER; - $types[] = FundInitiativeTransaction::TYPE_REFUND; - $types[] = FundInitiativeTransaction::TYPE_MERCHANT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = PhabricatorTransactions::TYPE_COMMENT; @@ -28,204 +28,6 @@ final class FundInitiativeEditor return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case FundInitiativeTransaction::TYPE_NAME: - return $object->getName(); - case FundInitiativeTransaction::TYPE_DESCRIPTION: - return $object->getDescription(); - case FundInitiativeTransaction::TYPE_RISKS: - return $object->getRisks(); - case FundInitiativeTransaction::TYPE_STATUS: - return $object->getStatus(); - case FundInitiativeTransaction::TYPE_BACKER: - case FundInitiativeTransaction::TYPE_REFUND: - return null; - case FundInitiativeTransaction::TYPE_MERCHANT: - return $object->getMerchantPHID(); - } - - return parent::getCustomTransactionOldValue($object, $xaction); - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case FundInitiativeTransaction::TYPE_NAME: - case FundInitiativeTransaction::TYPE_DESCRIPTION: - case FundInitiativeTransaction::TYPE_RISKS: - case FundInitiativeTransaction::TYPE_STATUS: - case FundInitiativeTransaction::TYPE_BACKER: - case FundInitiativeTransaction::TYPE_REFUND: - case FundInitiativeTransaction::TYPE_MERCHANT: - return $xaction->getNewValue(); - } - - return parent::getCustomTransactionNewValue($object, $xaction); - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - $type = $xaction->getTransactionType(); - switch ($type) { - case FundInitiativeTransaction::TYPE_NAME: - $object->setName($xaction->getNewValue()); - return; - case FundInitiativeTransaction::TYPE_DESCRIPTION: - $object->setDescription($xaction->getNewValue()); - return; - case FundInitiativeTransaction::TYPE_RISKS: - $object->setRisks($xaction->getNewValue()); - return; - case FundInitiativeTransaction::TYPE_MERCHANT: - $object->setMerchantPHID($xaction->getNewValue()); - return; - case FundInitiativeTransaction::TYPE_STATUS: - $object->setStatus($xaction->getNewValue()); - return; - case FundInitiativeTransaction::TYPE_BACKER: - case FundInitiativeTransaction::TYPE_REFUND: - $amount = $xaction->getMetadataValue( - FundInitiativeTransaction::PROPERTY_AMOUNT); - $amount = PhortuneCurrency::newFromString($amount); - - if ($type == FundInitiativeTransaction::TYPE_REFUND) { - $total = $object->getTotalAsCurrency()->subtract($amount); - } else { - $total = $object->getTotalAsCurrency()->add($amount); - } - - $object->setTotalAsCurrency($total); - return; - } - - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - $type = $xaction->getTransactionType(); - switch ($type) { - case FundInitiativeTransaction::TYPE_NAME: - case FundInitiativeTransaction::TYPE_DESCRIPTION: - case FundInitiativeTransaction::TYPE_RISKS: - case FundInitiativeTransaction::TYPE_STATUS: - case FundInitiativeTransaction::TYPE_MERCHANT: - return; - case FundInitiativeTransaction::TYPE_BACKER: - case FundInitiativeTransaction::TYPE_REFUND: - $backer = id(new FundBackerQuery()) - ->setViewer($this->requireActor()) - ->withPHIDs(array($xaction->getNewValue())) - ->executeOne(); - if (!$backer) { - throw new Exception(pht('Unable to load %s!', 'FundBacker')); - } - - $subx = array(); - - if ($type == FundInitiativeTransaction::TYPE_BACKER) { - $subx[] = id(new FundBackerTransaction()) - ->setTransactionType(FundBackerTransaction::TYPE_STATUS) - ->setNewValue(FundBacker::STATUS_PURCHASED); - } else { - $amount = $xaction->getMetadataValue( - FundInitiativeTransaction::PROPERTY_AMOUNT); - $subx[] = id(new FundBackerTransaction()) - ->setTransactionType(FundBackerTransaction::TYPE_STATUS) - ->setNewValue($amount); - } - - $editor = id(new FundBackerEditor()) - ->setActor($this->requireActor()) - ->setContentSource($this->getContentSource()) - ->setContinueOnMissingFields(true) - ->setContinueOnNoEffect(true); - - $editor->applyTransactions($backer, $subx); - return; - } - - return parent::applyCustomExternalTransaction($object, $xaction); - } - - protected function validateTransaction( - PhabricatorLiskDAO $object, - $type, - array $xactions) { - - $errors = parent::validateTransaction($object, $type, $xactions); - - switch ($type) { - case FundInitiativeTransaction::TYPE_NAME: - $missing = $this->validateIsEmptyTextField( - $object->getName(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Initiative name is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - break; - case FundInitiativeTransaction::TYPE_MERCHANT: - $missing = $this->validateIsEmptyTextField( - $object->getName(), - $xactions); - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Payable merchant is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } else if ($xactions) { - $merchant_phid = last($xactions)->getNewValue(); - - // Make sure the actor has permission to edit the merchant they're - // selecting. You aren't allowed to send payments to an account you - // do not control. - $merchants = id(new PhortuneMerchantQuery()) - ->setViewer($this->requireActor()) - ->withPHIDs(array($merchant_phid)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->execute(); - if (!$merchants) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid'), - pht( - 'You must specify a merchant account you control as the '. - 'recipient of funds from this initiative.'), - last($xactions)); - $errors[] = $error; - } - } - break; - } - - return $errors; - } - protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { diff --git a/src/applications/fund/phortune/FundBackerProduct.php b/src/applications/fund/phortune/FundBackerProduct.php index 679a1a41d2..be0dbd9171 100644 --- a/src/applications/fund/phortune/FundBackerProduct.php +++ b/src/applications/fund/phortune/FundBackerProduct.php @@ -105,7 +105,7 @@ final class FundBackerProduct extends PhortuneProductImplementation { $xactions = array(); $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType(FundInitiativeTransaction::TYPE_BACKER) + ->setTransactionType(FundInitiativeBackerTransaction::TRANSACTIONTYPE) ->setMetadataValue( FundInitiativeTransaction::PROPERTY_AMOUNT, $backer->getAmountAsCurrency()->serializeForStorage()) @@ -134,7 +134,7 @@ final class FundBackerProduct extends PhortuneProductImplementation { $xactions = array(); $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType(FundInitiativeTransaction::TYPE_REFUND) + ->setTransactionType(FundInitiativeRefundTransaction::TRANSACTIONTYPE) ->setMetadataValue( FundInitiativeTransaction::PROPERTY_AMOUNT, $amount->serializeForStorage()) diff --git a/src/applications/fund/storage/FundBackerTransaction.php b/src/applications/fund/storage/FundBackerTransaction.php index 555c7d2966..c24e769eb6 100644 --- a/src/applications/fund/storage/FundBackerTransaction.php +++ b/src/applications/fund/storage/FundBackerTransaction.php @@ -1,10 +1,7 @@ getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_MERCHANT: - if ($old) { - $phids[] = $old; - } - if ($new) { - $phids[] = $new; - } - break; - case self::TYPE_REFUND: - $phids[] = $this->getMetadataValue(self::PROPERTY_BACKER); - break; - } - - return $phids; + public function getBaseTransactionClass() { + return 'FundInitiativeTransactionType'; } - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created this initiative.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s renamed this initiative from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } - break; - case self::TYPE_RISKS: - return pht( - '%s edited the risks for this initiative.', - $this->renderHandleLink($author_phid)); - case self::TYPE_DESCRIPTION: - return pht( - '%s edited the description of this initiative.', - $this->renderHandleLink($author_phid)); - case self::TYPE_STATUS: - switch ($new) { - case FundInitiative::STATUS_OPEN: - return pht( - '%s reopened this initiative.', - $this->renderHandleLink($author_phid)); - case FundInitiative::STATUS_CLOSED: - return pht( - '%s closed this initiative.', - $this->renderHandleLink($author_phid)); - } - break; - case self::TYPE_BACKER: - $amount = $this->getMetadataValue(self::PROPERTY_AMOUNT); - $amount = PhortuneCurrency::newFromString($amount); - return pht( - '%s backed this initiative with %s.', - $this->renderHandleLink($author_phid), - $amount->formatForDisplay()); - case self::TYPE_REFUND: - $amount = $this->getMetadataValue(self::PROPERTY_AMOUNT); - $amount = PhortuneCurrency::newFromString($amount); - - $backer_phid = $this->getMetadataValue(self::PROPERTY_BACKER); - - return pht( - '%s refunded %s to %s.', - $this->renderHandleLink($author_phid), - $amount->formatForDisplay(), - $this->renderHandleLink($backer_phid)); - case self::TYPE_MERCHANT: - if ($old === null) { - return pht( - '%s set this initiative to pay to %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($new)); - } else { - return pht( - '%s changed the merchant receiving funds from this '. - 'initiative from %s to %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - } - } - - return parent::getTitle(); - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - - } else { - return pht( - '%s renamed %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_DESCRIPTION: - return pht( - '%s updated the description for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case self::TYPE_STATUS: - switch ($new) { - case FundInitiative::STATUS_OPEN: - return pht( - '%s reopened %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case FundInitiative::STATUS_CLOSED: - return pht( - '%s closed %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_BACKER: - $amount = $this->getMetadataValue(self::PROPERTY_AMOUNT); - $amount = PhortuneCurrency::newFromString($amount); - return pht( - '%s backed %s with %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid), - $amount->formatForDisplay()); - case self::TYPE_REFUND: - $amount = $this->getMetadataValue(self::PROPERTY_AMOUNT); - $amount = PhortuneCurrency::newFromString($amount); - - $backer_phid = $this->getMetadataValue(self::PROPERTY_BACKER); - - return pht( - '%s refunded %s to %s for %s.', - $this->renderHandleLink($author_phid), - $amount->formatForDisplay(), - $this->renderHandleLink($backer_phid), - $this->renderHandleLink($object_phid)); - } - - return parent::getTitleForFeed(); + protected function shouldPublishFeedStory( + PhabricatorLiskDAO $object, + array $xactions) { + return true; } public function getMailTags() { $tags = parent::getMailTags(); switch ($this->getTransactionType()) { - case self::TYPE_STATUS: + case FundInitiativeStatusTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_STATUS; break; - case self::TYPE_BACKER: - case self::TYPE_REFUND: + case FundInitiativeBackerTransaction::TRANSACTIONTYPE: + case FundInitiativeRefundTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_BACKER; break; default: @@ -219,31 +51,4 @@ final class FundInitiativeTransaction return $tags; } - - public function shouldHide() { - $old = $this->getOldValue(); - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - case self::TYPE_RISKS: - return ($old === null); - } - return parent::shouldHide(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - case self::TYPE_RISKS: - return ($this->getOldValue() !== null); - } - - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - $this->getOldValue(), - $this->getNewValue()); - } } diff --git a/src/applications/fund/xaction/FundBackerRefundTransaction.php b/src/applications/fund/xaction/FundBackerRefundTransaction.php new file mode 100644 index 0000000000..0aad952482 --- /dev/null +++ b/src/applications/fund/xaction/FundBackerRefundTransaction.php @@ -0,0 +1,13 @@ +getStatus(); + } + + public function applyInternalEffects($object, $value) { + $object->setStatus($value); + } + + +} diff --git a/src/applications/fund/xaction/FundBackerTransactionType.php b/src/applications/fund/xaction/FundBackerTransactionType.php new file mode 100644 index 0000000000..86ca6703d7 --- /dev/null +++ b/src/applications/fund/xaction/FundBackerTransactionType.php @@ -0,0 +1,4 @@ +getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $amount = PhortuneCurrency::newFromString($amount); + $total = $object->getTotalAsCurrency()->add($amount); + $object->setTotalAsCurrency($total); + } + + public function applyExternalEffects($object, $value) { + $backer = id(new FundBackerQuery()) + ->setViewer($this->getActor()) + ->withPHIDs(array($value)) + ->executeOne(); + if (!$backer) { + throw new Exception(pht('Unable to load %s!', 'FundBacker')); + } + + $subx = array(); + $subx[] = id(new FundBackerTransaction()) + ->setTransactionType(FundBackerStatusTransaction::TRANSACTIONTYPE) + ->setNewValue(FundBacker::STATUS_PURCHASED); + + $content_source = $this->getEditor()->getContentSource(); + + $editor = id(new FundBackerEditor()) + ->setActor($this->getActor()) + ->setContentSource($content_source) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($backer, $subx); + } + + public function getTitle() { + $amount = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $amount = PhortuneCurrency::newFromString($amount); + return pht( + '%s backed this initiative with %s.', + $this->renderAuthor(), + $amount->formatForDisplay()); + } + + public function getTitleForFeed() { + $amount = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $amount = PhortuneCurrency::newFromString($amount); + return pht( + '%s backed %s with %s.', + $this->renderAuthor(), + $this->renderObject(), + $amount->formatForDisplay()); + } + + public function getIcon() { + return 'fa-heart'; + } + + public function getColor() { + return 'red'; + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeDescriptionTransaction.php b/src/applications/fund/xaction/FundInitiativeDescriptionTransaction.php new file mode 100644 index 0000000000..f32b8499cf --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeDescriptionTransaction.php @@ -0,0 +1,75 @@ +getDescription(); + } + + public function applyInternalEffects($object, $value) { + $object->setDescription($value); + } + + public function shouldHide() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + if (!strlen($old) && !strlen($new)) { + return true; + } + return false; + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + if ($old === null) { + return pht( + '%s set the initiative description.', + $this->renderAuthor()); + } else { + return pht( + '%s updated the initiative description.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + return pht( + '%s updated the initiative description for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO INITIATIVE DESCRIPTION'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeMerchantTransaction.php b/src/applications/fund/xaction/FundInitiativeMerchantTransaction.php new file mode 100644 index 0000000000..e2a2597c50 --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeMerchantTransaction.php @@ -0,0 +1,93 @@ +getMerchantPHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setMerchantPHID($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + $new_merchant = $this->renderHandleList(array($new)); + + $old = $this->getOldValue(); + $old_merchant = $this->renderHandleList(array($old)); + + if ($old) { + return pht( + '%s changed the merchant receiving funds from this '. + 'initiative from %s to %s.', + $this->renderAuthor(), + $old_merchant, + $new_merchant); + } else { + return pht( + '%s set the merchant receiving funds from this '. + 'initiative to %s.', + $this->renderAuthor(), + $new_merchant); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + $new_merchant = $this->renderHandleList(array($new)); + + $old = $this->getOldValue(); + $old_merchant = $this->renderHandleList(array($old)); + + return pht( + '%s changed the merchant receiving funds from %s '. + 'initiative from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $old_merchant, + $new_merchant); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getMerchantPHID(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Initiatives must have a payable merchant.')); + } + + foreach ($xactions as $xaction) { + $merchant_phid = $xaction->getNewValue(); + + // Make sure the actor has permission to edit the merchant they're + // selecting. You aren't allowed to send payments to an account you + // do not control. + $merchants = id(new PhortuneMerchantQuery()) + ->setViewer($this->getActor()) + ->withPHIDs(array($merchant_phid)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->execute(); + if (!$merchants) { + $errors[] = $this->newInvalidError( + pht('You must specify a merchant account you control as the '. + 'recipient of funds from this initiative.')); + } + } + + return $errors; + } + + public function getIcon() { + return 'fa-bank'; + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeNameTransaction.php b/src/applications/fund/xaction/FundInitiativeNameTransaction.php new file mode 100644 index 0000000000..5883c32ce2 --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeNameTransaction.php @@ -0,0 +1,71 @@ +getName(); + } + + public function applyInternalEffects($object, $value) { + $object->setName($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s created this initiative.', + $this->renderAuthor()); + } else { + return pht( + '%s renamed this initiative from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s created initiative %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s renamed %s initiative from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Initiatives must have a name.')); + } + + $max_length = $object->getColumnMaximumByteLength('name'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The name can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeRefundTransaction.php b/src/applications/fund/xaction/FundInitiativeRefundTransaction.php new file mode 100644 index 0000000000..60bb610a80 --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeRefundTransaction.php @@ -0,0 +1,77 @@ +getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $amount = PhortuneCurrency::newFromString($amount); + $total = $object->getTotalAsCurrency()->subtract($amount); + $object->setTotalAsCurrency($total); + } + + public function applyExternalEffects($object, $value) { + $backer = id(new FundBackerQuery()) + ->setViewer($this->getActor()) + ->withPHIDs(array($value)) + ->executeOne(); + if (!$backer) { + throw new Exception(pht('Unable to load %s!', 'FundBacker')); + } + + $subx = array(); + $amount = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $subx[] = id(new FundBackerTransaction()) + ->setTransactionType(FundBackerStatusTransaction::TRANSACTIONTYPE) + ->setNewValue($amount); + + $content_source = $this->getEditor()->getContentSource(); + + $editor = id(new FundBackerEditor()) + ->setActor($this->getActor()) + ->setContentSource($content_source) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($backer, $subx); + } + + public function getTitle() { + $amount = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $amount = PhortuneCurrency::newFromString($amount); + $backer_phid = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_BACKER); + + return pht( + '%s refunded %s to %s.', + $this->renderAuthor(), + $amount->formatForDisplay(), + $this->renderHandleLink($backer_phid)); + } + + public function getTitleForFeed() { + $amount = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_AMOUNT); + $amount = PhortuneCurrency::newFromString($amount); + $backer_phid = $this->getMetadataValue( + FundInitiativeTransaction::PROPERTY_BACKER); + + return pht( + '%s refunded %s to %s for %s.', + $this->renderAuthor(), + $amount->formatForDisplay(), + $this->renderHandleLink($backer_phid), + $this->renderObject()); + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeRisksTransaction.php b/src/applications/fund/xaction/FundInitiativeRisksTransaction.php new file mode 100644 index 0000000000..183f9caa67 --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeRisksTransaction.php @@ -0,0 +1,80 @@ +getRisks(); + } + + public function applyInternalEffects($object, $value) { + $object->setRisks($value); + } + + public function shouldHide() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + if (!strlen($old) && !strlen($new)) { + return true; + } + return false; + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + if ($old === null) { + return pht( + '%s set the initiative risks/challenges.', + $this->renderAuthor()); + } else { + return pht( + '%s updated the initiative risks/challenges.', + $this->renderAuthor()); + } + + } + + public function getTitleForFeed() { + return pht( + '%s updated the initiative risks/challenges for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO INITIATIVE RISKS/CHALLENGES'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + public function getIcon() { + return 'fa-ambulance'; + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeStatusTransaction.php b/src/applications/fund/xaction/FundInitiativeStatusTransaction.php new file mode 100644 index 0000000000..688c8b52c4 --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeStatusTransaction.php @@ -0,0 +1,51 @@ +getStatus(); + } + + public function applyInternalEffects($object, $value) { + $object->setStatus($value); + } + + public function getTitle() { + if ($this->getNewValue() == FundInitiative::STATUS_CLOSED) { + return pht( + '%s closed this initiative.', + $this->renderAuthor()); + } else { + return pht( + '%s reopened this initiative.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + if ($this->getNewValue() == FundInitiative::STATUS_CLOSED) { + return pht( + '%s closed the initiative %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s reopened the initiative %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + if ($this->getNewValue() == FundInitiative::STATUS_CLOSED) { + return 'fa-ban'; + } else { + return 'fa-check'; + } + } + + +} diff --git a/src/applications/fund/xaction/FundInitiativeTransactionType.php b/src/applications/fund/xaction/FundInitiativeTransactionType.php new file mode 100644 index 0000000000..6bcd17f1c7 --- /dev/null +++ b/src/applications/fund/xaction/FundInitiativeTransactionType.php @@ -0,0 +1,4 @@ +setTransactionType(LegalpadTransaction::TYPE_TITLE) + ->setTransactionType( + LegalpadDocumentTitleTransaction::TRANSACTIONTYPE) ->setNewValue($title); } @@ -67,7 +68,8 @@ final class LegalpadDocumentEditController extends LegalpadController { $errors[] = pht('The document may not be blank.'); } else { $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_TEXT) + ->setTransactionType( + LegalpadDocumentTextTransaction::TRANSACTIONTYPE) ->setNewValue($text); } @@ -83,13 +85,15 @@ final class LegalpadDocumentEditController extends LegalpadController { if ($is_create) { $v_signature_type = $request->getStr('signatureType'); $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_SIGNATURE_TYPE) + ->setTransactionType( + LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE) ->setNewValue($v_signature_type); } $v_preamble = $request->getStr('preamble'); $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_PREAMBLE) + ->setTransactionType( + LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE) ->setNewValue($v_preamble); $v_require_signature = $request->getBool('requireSignature', 0); @@ -106,7 +110,8 @@ final class LegalpadDocumentEditController extends LegalpadController { } if ($viewer->getIsAdmin()) { $xactions[] = id(new LegalpadTransaction()) - ->setTransactionType(LegalpadTransaction::TYPE_REQUIRE_SIGNATURE) + ->setTransactionType( + LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE) ->setNewValue($v_require_signature); } diff --git a/src/applications/legalpad/editor/LegalpadDocumentEditor.php b/src/applications/legalpad/editor/LegalpadDocumentEditor.php index 5e319b5905..14430b2c33 100644 --- a/src/applications/legalpad/editor/LegalpadDocumentEditor.php +++ b/src/applications/legalpad/editor/LegalpadDocumentEditor.php @@ -3,8 +3,6 @@ final class LegalpadDocumentEditor extends PhabricatorApplicationTransactionEditor { - private $isContribution = false; - public function getEditorApplicationClass() { return 'PhabricatorLegalpadApplication'; } @@ -13,15 +11,6 @@ final class LegalpadDocumentEditor return pht('Legalpad Documents'); } - private function setIsContribution($is_contribution) { - $this->isContribution = $is_contribution; - return $this; - } - - private function isContribution() { - return $this->isContribution; - } - public function getTransactionTypes() { $types = parent::getTransactionTypes(); @@ -29,99 +18,25 @@ final class LegalpadDocumentEditor $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; - $types[] = LegalpadTransaction::TYPE_TITLE; - $types[] = LegalpadTransaction::TYPE_TEXT; - $types[] = LegalpadTransaction::TYPE_SIGNATURE_TYPE; - $types[] = LegalpadTransaction::TYPE_PREAMBLE; - $types[] = LegalpadTransaction::TYPE_REQUIRE_SIGNATURE; - return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TITLE: - return $object->getDocumentBody()->getTitle(); - case LegalpadTransaction::TYPE_TEXT: - return $object->getDocumentBody()->getText(); - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - return $object->getSignatureType(); - case LegalpadTransaction::TYPE_PREAMBLE: - return $object->getPreamble(); - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - return (bool)$object->getRequireSignature(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TITLE: - case LegalpadTransaction::TYPE_TEXT: - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - case LegalpadTransaction::TYPE_PREAMBLE: - return $xaction->getNewValue(); - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - return (bool)$xaction->getNewValue(); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TITLE: - $object->setTitle($xaction->getNewValue()); - $body = $object->getDocumentBody(); - $body->setTitle($xaction->getNewValue()); - $this->setIsContribution(true); - break; - case LegalpadTransaction::TYPE_TEXT: - $body = $object->getDocumentBody(); - $body->setText($xaction->getNewValue()); - $this->setIsContribution(true); - break; - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - $object->setSignatureType($xaction->getNewValue()); - break; - case LegalpadTransaction::TYPE_PREAMBLE: - $object->setPreamble($xaction->getNewValue()); - break; - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - $object->setRequireSignature((int)$xaction->getNewValue()); - break; - } - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - if ($xaction->getNewValue()) { - $session = new PhabricatorAuthSession(); - queryfx( - $session->establishConnection('w'), - 'UPDATE %T SET signedLegalpadDocuments = 0', - $session->getTableName()); - } - break; - } - return; - } - protected function applyFinalEffects( PhabricatorLiskDAO $object, array $xactions) { - if ($this->isContribution()) { + $is_contribution = false; + + foreach ($xactions as $xaction) { + switch ($xaction->getTransactionType()) { + case LegalpadDocumentTitleTransaction::TRANSACTIONTYPE: + case LegalpadDocumentTextTransaction::TRANSACTIONTYPE: + $is_contribution = true; + break; + } + } + + if ($is_contribution) { $object->setVersions($object->getVersions() + 1); $body = $object->getDocumentBody(); $body->setVersion($object->getVersions()); @@ -149,22 +64,6 @@ final class LegalpadDocumentEditor return $xactions; } - protected function mergeTransactions( - PhabricatorApplicationTransaction $u, - PhabricatorApplicationTransaction $v) { - - $type = $u->getTransactionType(); - switch ($type) { - case LegalpadTransaction::TYPE_TITLE: - case LegalpadTransaction::TYPE_TEXT: - case LegalpadTransaction::TYPE_SIGNATURE_TYPE: - case LegalpadTransaction::TYPE_PREAMBLE: - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: - return $v; - } - - return parent::mergeTransactions($u, $v); - } /* -( Sending Mail )------------------------------------------------------- */ @@ -201,10 +100,10 @@ final class LegalpadDocumentEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case LegalpadTransaction::TYPE_TEXT: - case LegalpadTransaction::TYPE_TITLE: - case LegalpadTransaction::TYPE_PREAMBLE: - case LegalpadTransaction::TYPE_REQUIRE_SIGNATURE: + case LegalpadDocumentTextTransaction::TRANSACTIONTYPE: + case LegalpadDocumentTitleTransaction::TRANSACTIONTYPE: + case LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE: + case LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE: return true; } diff --git a/src/applications/legalpad/storage/LegalpadTransaction.php b/src/applications/legalpad/storage/LegalpadTransaction.php index f85c569279..c43c86c5fc 100644 --- a/src/applications/legalpad/storage/LegalpadTransaction.php +++ b/src/applications/legalpad/storage/LegalpadTransaction.php @@ -1,12 +1,6 @@ getOldValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - case self::TYPE_TEXT: - return ($old === null); - case self::TYPE_SIGNATURE_TYPE: - return true; - } - - return parent::shouldHide(); - } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_TITLE: - return pht( - '%s renamed this document from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - case self::TYPE_TEXT: - return pht( - "%s updated the document's text.", - $this->renderHandleLink($author_phid)); - case self::TYPE_PREAMBLE: - return pht( - '%s updated the preamble.', - $this->renderHandleLink($author_phid)); - case self::TYPE_REQUIRE_SIGNATURE: - if ($new) { - $text = pht( - '%s set the document to require signatures.', - $this->renderHandleLink($author_phid)); - } else { - $text = pht( - '%s set the document to not require signatures.', - $this->renderHandleLink($author_phid)); - } - return $text; - } - - return parent::getTitle(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - case self::TYPE_TEXT: - case self::TYPE_PREAMBLE: - return true; - } - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - $this->getOldValue(), - $this->getNewValue()); + public function getBaseTransactionClass() { + return 'LegalpadDocumentTransactionType'; } } diff --git a/src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php new file mode 100644 index 0000000000..a2b5e1f5cd --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentPreambleTransaction.php @@ -0,0 +1,57 @@ +getPreamble(); + } + + public function applyInternalEffects($object, $value) { + $object->setPreamble($value); + } + + public function getTitle() { + return pht( + '%s updated the document preamble.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the document preamble for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO DOCUMENT PREAMBLE'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php new file mode 100644 index 0000000000..ffef42f0ce --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php @@ -0,0 +1,58 @@ +getRequireSignature(); + } + + public function applyInternalEffects($object, $value) { + $object->setRequireSignature($value); + } + + public function applyExternalEffects($object, $value) { + if (strlen($value)) { + $session = new PhabricatorAuthSession(); + queryfx( + $session->establishConnection('w'), + 'UPDATE %T SET signedLegalpadDocuments = 0', + $session->getTableName()); + } + } + + public function getTitle() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s set the document to require signatures.', + $this->renderAuthor()); + } else { + return pht( + '%s set the document to not require signatures.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s set the document %s to require signatures.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s set the document %s to not require signatures.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + return 'fa-pencil-square'; + } + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php new file mode 100644 index 0000000000..df9cf60457 --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentSignatureTypeTransaction.php @@ -0,0 +1,29 @@ +getSignatureType(); + } + + public function applyInternalEffects($object, $value) { + $object->setSignatureType($value); + } + + public function getTitle() { + return pht( + '%s set the document signature type.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s set the document signature type for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php new file mode 100644 index 0000000000..c17ebc890d --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentTextTransaction.php @@ -0,0 +1,60 @@ +getDocumentBody(); + return $body->getText(); + } + + public function applyInternalEffects($object, $value) { + $body = $object->getDocumentBody(); + $body->setText($value); + $object->attachDocumentBody($body); + } + + public function getTitle() { + return pht( + '%s updated the document text.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the document text for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO DOCUMENT TEXT'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php b/src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php new file mode 100644 index 0000000000..c6a4b5b509 --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentTitleTransaction.php @@ -0,0 +1,58 @@ +getTitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setTitle($value); + $body = $object->getDocumentBody(); + $body->setTitle($value); + $object->attachDocumentBody($body); + } + + public function getTitle() { + return pht( + '%s renamed this document from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s renamed document %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Documents must have a title.')); + } + + $max_length = $object->getColumnMaximumByteLength('title'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The title can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php b/src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php new file mode 100644 index 0000000000..58763914ee --- /dev/null +++ b/src/applications/legalpad/xaction/LegalpadDocumentTransactionType.php @@ -0,0 +1,4 @@ +[^/]+)/)?' => 'PhabricatorMacroListController', 'create/' => 'PhabricatorMacroEditController', 'view/(?P[1-9]\d*)/' => 'PhabricatorMacroViewController', - 'comment/(?P[1-9]\d*)/' => 'PhabricatorMacroCommentController', - 'edit/(?P[1-9]\d*)/' => 'PhabricatorMacroEditController', + $this->getEditRoutePattern('edit/') + => 'PhabricatorMacroEditController', 'audio/(?P[1-9]\d*)/' => 'PhabricatorMacroAudioController', 'disable/(?P[1-9]\d*)/' => 'PhabricatorMacroDisableController', 'meme/' => 'PhabricatorMacroMemeController', diff --git a/src/applications/macro/controller/PhabricatorMacroAudioController.php b/src/applications/macro/controller/PhabricatorMacroAudioController.php index 7e2b924637..382c82ae3a 100644 --- a/src/applications/macro/controller/PhabricatorMacroAudioController.php +++ b/src/applications/macro/controller/PhabricatorMacroAudioController.php @@ -34,7 +34,7 @@ final class PhabricatorMacroAudioController extends PhabricatorMacroController { if ($request->getBool('behaviorForm')) { $xactions[] = id(new PhabricatorMacroTransaction()) ->setTransactionType( - PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR) + PhabricatorMacroAudioBehaviorTransaction::TRANSACTIONTYPE) ->setNewValue($request->getStr('audioBehavior')); } else { $file = null; @@ -54,7 +54,8 @@ final class PhabricatorMacroAudioController extends PhabricatorMacroController { $e_file = pht('Invalid'); } else { $xactions[] = id(new PhabricatorMacroTransaction()) - ->setTransactionType(PhabricatorMacroTransaction::TYPE_AUDIO) + ->setTransactionType( + PhabricatorMacroAudioTransaction::TRANSACTIONTYPE) ->setNewValue($file->getPHID()); } } else { diff --git a/src/applications/macro/controller/PhabricatorMacroCommentController.php b/src/applications/macro/controller/PhabricatorMacroCommentController.php deleted file mode 100644 index f038140be1..0000000000 --- a/src/applications/macro/controller/PhabricatorMacroCommentController.php +++ /dev/null @@ -1,63 +0,0 @@ -getViewer(); - $id = $request->getURIData('id'); - - if (!$request->isFormPost()) { - return new Aphront400Response(); - } - - $macro = id(new PhabricatorMacroQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->executeOne(); - if (!$macro) { - return new Aphront404Response(); - } - - $is_preview = $request->isPreviewRequest(); - $draft = PhabricatorDraft::buildFromRequest($request); - - $view_uri = $this->getApplicationURI('/view/'.$macro->getID().'/'); - - $xactions = array(); - $xactions[] = id(new PhabricatorMacroTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) - ->attachComment( - id(new PhabricatorMacroTransactionComment()) - ->setContent($request->getStr('comment'))); - - $editor = id(new PhabricatorMacroEditor()) - ->setActor($viewer) - ->setContinueOnNoEffect($request->isContinueRequest()) - ->setContentSourceFromRequest($request) - ->setIsPreview($is_preview); - - try { - $xactions = $editor->applyTransactions($macro, $xactions); - } catch (PhabricatorApplicationTransactionNoEffectException $ex) { - return id(new PhabricatorApplicationTransactionNoEffectResponse()) - ->setCancelURI($view_uri) - ->setException($ex); - } - - if ($draft) { - $draft->replaceOrDelete(); - } - - if ($request->isAjax() && $is_preview) { - return id(new PhabricatorApplicationTransactionResponse()) - ->setViewer($viewer) - ->setTransactions($xactions) - ->setIsPreview($is_preview); - } else { - return id(new AphrontRedirectResponse()) - ->setURI($view_uri); - } - } - -} diff --git a/src/applications/macro/controller/PhabricatorMacroDisableController.php b/src/applications/macro/controller/PhabricatorMacroDisableController.php index a9868647f0..6c74e44442 100644 --- a/src/applications/macro/controller/PhabricatorMacroDisableController.php +++ b/src/applications/macro/controller/PhabricatorMacroDisableController.php @@ -22,7 +22,8 @@ final class PhabricatorMacroDisableController if ($request->isDialogFormPost() || $macro->getIsDisabled()) { $xaction = id(new PhabricatorMacroTransaction()) - ->setTransactionType(PhabricatorMacroTransaction::TYPE_DISABLED) + ->setTransactionType( + PhabricatorMacroDisabledTransaction::TRANSACTIONTYPE) ->setNewValue($macro->getIsDisabled() ? 0 : 1); $editor = id(new PhabricatorMacroEditor()) diff --git a/src/applications/macro/controller/PhabricatorMacroEditController.php b/src/applications/macro/controller/PhabricatorMacroEditController.php index 110296c172..d4b7d5aeec 100644 --- a/src/applications/macro/controller/PhabricatorMacroEditController.php +++ b/src/applications/macro/controller/PhabricatorMacroEditController.php @@ -1,302 +1,10 @@ getViewer(); - $id = $request->getURIData('id'); - - $this->requireApplicationCapability( - PhabricatorMacroManageCapability::CAPABILITY); - - if ($id) { - $macro = id(new PhabricatorMacroQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->needFiles(true) - ->executeOne(); - if (!$macro) { - return new Aphront404Response(); - } - } else { - $macro = new PhabricatorFileImageMacro(); - $macro->setAuthorPHID($viewer->getPHID()); - } - - $errors = array(); - $e_name = true; - $e_file = null; - $file = null; - - if ($request->isFormPost()) { - $original = clone $macro; - - $new_name = null; - if ($request->getBool('name_form') || !$macro->getID()) { - $new_name = $request->getStr('name'); - - $macro->setName($new_name); - - if (!strlen($macro->getName())) { - $errors[] = pht('Macro name is required.'); - $e_name = pht('Required'); - } else if (!preg_match('/^[a-z0-9:_-]{3,}\z/', $macro->getName())) { - $errors[] = pht( - 'Macro must be at least three characters long and contain only '. - 'lowercase letters, digits, hyphens, colons and underscores.'); - $e_name = pht('Invalid'); - } else { - $e_name = null; - } - } - - $uri = $request->getStr('url'); - - $engine = new PhabricatorDestructionEngine(); - - $file = null; - if ($request->getFileExists('file')) { - $file = PhabricatorFile::newFromPHPUpload( - $_FILES['file'], - array( - 'name' => $request->getStr('name'), - 'authorPHID' => $viewer->getPHID(), - 'isExplicitUpload' => true, - 'canCDN' => true, - )); - } else if ($uri) { - try { - // Rate limit outbound fetches to make this mechanism less useful for - // scanning networks and ports. - PhabricatorSystemActionEngine::willTakeAction( - array($viewer->getPHID()), - new PhabricatorFilesOutboundRequestAction(), - 1); - - $file = PhabricatorFile::newFromFileDownload( - $uri, - array( - 'name' => $request->getStr('name'), - 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, - 'isExplicitUpload' => true, - 'canCDN' => true, - )); - - if (!$file->isViewableInBrowser()) { - $mime_type = $file->getMimeType(); - $engine->destroyObject($file); - $file = null; - throw new Exception( - pht( - 'The URI "%s" does not correspond to a valid image file, got '. - 'a file with MIME type "%s". You must specify the URI of a '. - 'valid image file.', - $uri, - $mime_type)); - } else { - $file - ->setAuthorPHID($viewer->getPHID()) - ->save(); - } - } catch (HTTPFutureHTTPResponseStatus $status) { - $errors[] = pht( - 'The URI "%s" could not be loaded, got %s error.', - $uri, - $status->getStatusCode()); - } catch (Exception $ex) { - $errors[] = $ex->getMessage(); - } - } else if ($request->getStr('phid')) { - $file = id(new PhabricatorFileQuery()) - ->setViewer($viewer) - ->withPHIDs(array($request->getStr('phid'))) - ->executeOne(); - } - - if ($file) { - if (!$file->isViewableInBrowser()) { - $errors[] = pht('You must upload an image.'); - $e_file = pht('Invalid'); - } else { - $macro->setFilePHID($file->getPHID()); - $macro->attachFile($file); - $e_file = null; - } - } - - if (!$macro->getID() && !$file) { - $errors[] = pht('You must upload an image to create a macro.'); - $e_file = pht('Required'); - } - - if (!$errors) { - try { - $xactions = array(); - - if ($new_name !== null) { - $xactions[] = id(new PhabricatorMacroTransaction()) - ->setTransactionType(PhabricatorMacroTransaction::TYPE_NAME) - ->setNewValue($new_name); - } - - if ($file) { - $xactions[] = id(new PhabricatorMacroTransaction()) - ->setTransactionType(PhabricatorMacroTransaction::TYPE_FILE) - ->setNewValue($file->getPHID()); - } - - $editor = id(new PhabricatorMacroEditor()) - ->setActor($viewer) - ->setContinueOnNoEffect(true) - ->setContentSourceFromRequest($request); - - $xactions = $editor->applyTransactions($original, $xactions); - - $view_uri = $this->getApplicationURI('/view/'.$original->getID().'/'); - return id(new AphrontRedirectResponse())->setURI($view_uri); - } catch (AphrontDuplicateKeyQueryException $ex) { - throw $ex; - $errors[] = pht('Macro name is not unique!'); - $e_name = pht('Duplicate'); - } - } - } - - $current_file = null; - if ($macro->getFilePHID()) { - $current_file = $macro->getFile(); - } - - $form = new AphrontFormView(); - $form->addHiddenInput('name_form', 1); - $form->setUser($request->getUser()); - - $form - ->setEncType('multipart/form-data') - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Name')) - ->setName('name') - ->setValue($macro->getName()) - ->setCaption( - pht('This word or phrase will be replaced with the image.')) - ->setError($e_name)); - - if (!$macro->getID()) { - if ($current_file) { - $current_file_view = id(new PhabricatorFileLinkView()) - ->setViewer($viewer) - ->setFilePHID($current_file->getPHID()) - ->setFileName($current_file->getName()) - ->setFileViewable(true) - ->setFileViewURI($current_file->getBestURI()) - ->render(); - $form->addHiddenInput('phid', $current_file->getPHID()); - $form->appendChild( - id(new AphrontFormMarkupControl()) - ->setLabel(pht('Selected File')) - ->setValue($current_file_view)); - - $other_label = pht('Change File'); - } else { - $other_label = pht('File'); - } - - $form->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('URL')) - ->setName('url') - ->setValue($request->getStr('url')) - ->setError($request->getFileExists('file') ? false : $e_file)); - - $form->appendChild( - id(new AphrontFormFileControl()) - ->setLabel($other_label) - ->setName('file') - ->setError($request->getStr('url') ? false : $e_file)); - } - - - $view_uri = $this->getApplicationURI('/view/'.$macro->getID().'/'); - - if ($macro->getID()) { - $cancel_uri = $view_uri; - } else { - $cancel_uri = $this->getApplicationURI(); - } - - $form - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Save Image Macro')) - ->addCancelButton($cancel_uri)); - - $crumbs = $this->buildApplicationCrumbs(); - - if ($macro->getID()) { - $title = pht('Edit Macro: %s', $macro->getName()); - $crumb = pht('Edit Macro'); - $header_icon = 'fa-pencil'; - - $crumbs->addTextCrumb(pht('Macro: %s', $macro->getName()), $view_uri); - } else { - $title = pht('Create Image Macro'); - $crumb = pht('Create Macro'); - $header_icon = 'fa-plus-square'; - } - - $crumbs->addTextCrumb($crumb, $request->getRequestURI()); - $crumbs->setBorder(true); - - $upload = null; - if ($macro->getID()) { - $upload_form = id(new AphrontFormView()) - ->setEncType('multipart/form-data') - ->setUser($request->getUser()); - - $upload_form->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('URL')) - ->setName('url') - ->setValue($request->getStr('url'))); - - $upload_form - ->appendChild( - id(new AphrontFormFileControl()) - ->setLabel(pht('File')) - ->setName('file')) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Upload File'))); - - $upload = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Upload New File')) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($upload_form); - } - - $form_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Macro')) - ->setFormErrors($errors) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($form); - - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon($header_icon); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter(array( - $form_box, - $upload, - )); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); - + return id(new PhabricatorMacroEditEngine()) + ->setController($this) + ->buildResponse(); } - } diff --git a/src/applications/macro/controller/PhabricatorMacroViewController.php b/src/applications/macro/controller/PhabricatorMacroViewController.php index 386029c7ce..1bcf34240a 100644 --- a/src/applications/macro/controller/PhabricatorMacroViewController.php +++ b/src/applications/macro/controller/PhabricatorMacroViewController.php @@ -36,6 +36,8 @@ final class PhabricatorMacroViewController $macro, new PhabricatorMacroTransactionQuery()); + $comment_form = $this->buildCommentForm($macro, $timeline); + $header = id(new PHUIHeaderView()) ->setUser($viewer) ->setPolicyObject($macro) @@ -45,32 +47,16 @@ final class PhabricatorMacroViewController if (!$macro->getIsDisabled()) { $header->setStatus('fa-check', 'bluegrey', pht('Active')); } else { - $header->setStatus('fa-ban', 'red', pht('Archived')); + $header->setStatus('fa-ban', 'indigo', pht('Archived')); } - $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); - - $comment_header = $is_serious - ? pht('Add Comment') - : pht('Grovel in Awe'); - - $draft = PhabricatorDraft::newFromUserAndKey($viewer, $macro->getPHID()); - - $add_comment_form = id(new PhabricatorApplicationTransactionCommentView()) - ->setUser($viewer) - ->setObjectPHID($macro->getPHID()) - ->setDraft($draft) - ->setHeaderText($comment_header) - ->setAction($this->getApplicationURI('/comment/'.$macro->getID().'/')) - ->setSubmitButtonName(pht('Add Comment')); - $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setSubheader($subheader) ->setCurtain($curtain) ->setMainColumn(array( $timeline, - $add_comment_form, + $comment_form, )) ->addPropertySection(pht('Macro'), $file) ->addPropertySection(pht('Details'), $details); @@ -82,6 +68,16 @@ final class PhabricatorMacroViewController ->appendChild($view); } + private function buildCommentForm( + PhabricatorFileImageMacro $macro, $timeline) { + $viewer = $this->getViewer(); + + return id(new PhabricatorMacroEditEngine()) + ->setViewer($viewer) + ->buildEditEngineCommentView($macro) + ->setTransactionTimeline($timeline); + } + private function buildCurtain( PhabricatorFileImageMacro $macro) { $can_manage = $this->hasApplicationCapability( diff --git a/src/applications/macro/editor/PhabricatorMacroEditEngine.php b/src/applications/macro/editor/PhabricatorMacroEditEngine.php new file mode 100644 index 0000000000..3f472ff0ce --- /dev/null +++ b/src/applications/macro/editor/PhabricatorMacroEditEngine.php @@ -0,0 +1,88 @@ +getViewer(); + return PhabricatorFileImageMacro::initializeNewFileImageMacro($viewer); + } + + protected function newObjectQuery() { + return new PhabricatorMacroQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Macro'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit %s', $object->getName()); + } + + protected function getObjectEditShortText($object) { + return $object->getName(); + } + + protected function getObjectCreateShortText() { + return pht('Create Macro'); + } + + protected function getObjectName() { + return pht('Macro'); + } + + protected function getObjectViewURI($object) { + return $object->getViewURI(); + } + + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('edit/'); + } + + protected function getCreateNewObjectPolicy() { + return $this->getApplication()->getPolicy( + PhabricatorMacroManageCapability::CAPABILITY); + } + + protected function buildCustomEditFields($object) { + + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setDescription(pht('Macro name.')) + ->setConduitDescription(pht('Rename the macro.')) + ->setConduitTypeDescription(pht('New macro name.')) + ->setTransactionType(PhabricatorMacroNameTransaction::TRANSACTIONTYPE) + ->setValue($object->getName()), + id(new PhabricatorFileEditField()) + ->setKey('filePHID') + ->setLabel(pht('Image File')) + ->setDescription(pht('Image file to import.')) + ->setTransactionType(PhabricatorMacroFileTransaction::TRANSACTIONTYPE) + ->setConduitDescription(pht('File PHID to import.')) + ->setConduitTypeDescription(pht('File PHID.')), + ); + + } + +} diff --git a/src/applications/macro/editor/PhabricatorMacroEditor.php b/src/applications/macro/editor/PhabricatorMacroEditor.php index 1bb139a4de..d9067c5367 100644 --- a/src/applications/macro/editor/PhabricatorMacroEditor.php +++ b/src/applications/macro/editor/PhabricatorMacroEditor.php @@ -11,72 +11,12 @@ final class PhabricatorMacroEditor return pht('Macros'); } - public function getTransactionTypes() { - $types = parent::getTransactionTypes(); - - $types[] = PhabricatorTransactions::TYPE_COMMENT; - $types[] = PhabricatorMacroTransaction::TYPE_NAME; - $types[] = PhabricatorMacroTransaction::TYPE_DISABLED; - $types[] = PhabricatorMacroTransaction::TYPE_FILE; - $types[] = PhabricatorMacroTransaction::TYPE_AUDIO; - $types[] = PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR; - - return $types; + public function getCreateObjectTitle($author, $object) { + return pht('%s created this macro.', $author); } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorMacroTransaction::TYPE_NAME: - return $object->getName(); - case PhabricatorMacroTransaction::TYPE_DISABLED: - return $object->getIsDisabled(); - case PhabricatorMacroTransaction::TYPE_FILE: - return $object->getFilePHID(); - case PhabricatorMacroTransaction::TYPE_AUDIO: - return $object->getAudioPHID(); - case PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR: - return $object->getAudioBehavior(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorMacroTransaction::TYPE_NAME: - case PhabricatorMacroTransaction::TYPE_DISABLED: - case PhabricatorMacroTransaction::TYPE_FILE: - case PhabricatorMacroTransaction::TYPE_AUDIO: - case PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR: - return $xaction->getNewValue(); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorMacroTransaction::TYPE_NAME: - $object->setName($xaction->getNewValue()); - break; - case PhabricatorMacroTransaction::TYPE_DISABLED: - $object->setIsDisabled($xaction->getNewValue()); - break; - case PhabricatorMacroTransaction::TYPE_FILE: - $object->setFilePHID($xaction->getNewValue()); - break; - case PhabricatorMacroTransaction::TYPE_AUDIO: - $object->setAudioPHID($xaction->getNewValue()); - break; - case PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR: - $object->setAudioBehavior($xaction->getNewValue()); - break; - } + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); } protected function applyCustomExternalTransaction( @@ -84,8 +24,8 @@ final class PhabricatorMacroEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PhabricatorMacroTransaction::TYPE_FILE: - case PhabricatorMacroTransaction::TYPE_AUDIO: + case PhabricatorMacroFileTransaction::TRANSACTIONTYPE: + case PhabricatorMacroAudioTransaction::TRANSACTIONTYPE: // When changing a macro's image or audio, attach the underlying files // to the macro (and detach the old files). $old = $xaction->getOldValue(); @@ -117,34 +57,9 @@ final class PhabricatorMacroEditor } } - protected function mergeTransactions( - PhabricatorApplicationTransaction $u, - PhabricatorApplicationTransaction $v) { - - $type = $u->getTransactionType(); - switch ($type) { - case PhabricatorMacroTransaction::TYPE_NAME: - case PhabricatorMacroTransaction::TYPE_DISABLED: - case PhabricatorMacroTransaction::TYPE_FILE: - case PhabricatorMacroTransaction::TYPE_AUDIO: - case PhabricatorMacroTransaction::TYPE_AUDIO_BEHAVIOR: - return $v; - } - - return parent::mergeTransactions($u, $v); - } - protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { - foreach ($xactions as $xaction) { - switch ($xaction->getTransactionType()) { - case PhabricatorMacroTransaction::TYPE_NAME; - return ($xaction->getOldValue() !== null); - default: - break; - } - } return true; } diff --git a/src/applications/macro/storage/PhabricatorFileImageMacro.php b/src/applications/macro/storage/PhabricatorFileImageMacro.php index bc23e639d7..0cd6726f5f 100644 --- a/src/applications/macro/storage/PhabricatorFileImageMacro.php +++ b/src/applications/macro/storage/PhabricatorFileImageMacro.php @@ -41,6 +41,12 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO return $this->assertAttached($this->audio); } + public static function initializeNewFileImageMacro(PhabricatorUser $actor) { + $macro = id(new self()) + ->setAuthorPHID($actor->getPHID()); + return $macro; + } + protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, @@ -80,6 +86,10 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO return parent::save(); } + public function getViewURI() { + return '/macro/view/'.$this->getID().'/'; + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ @@ -128,11 +138,19 @@ final class PhabricatorFileImageMacro extends PhabricatorFileDAO public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { - return PhabricatorPolicies::getMostOpenPolicy(); + switch ($capability) { + case PhabricatorPolicyCapability::CAN_VIEW: + return PhabricatorPolicies::getMostOpenPolicy(); + case PhabricatorPolicyCapability::CAN_EDIT: + $app = PhabricatorApplication::getByClass( + 'PhabricatorMacroApplication'); + return $app->getPolicy(PhabricatorMacroManageCapability::CAPABILITY); + } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { diff --git a/src/applications/macro/storage/PhabricatorMacroTransaction.php b/src/applications/macro/storage/PhabricatorMacroTransaction.php index 46eb932476..3a15b4c15d 100644 --- a/src/applications/macro/storage/PhabricatorMacroTransaction.php +++ b/src/applications/macro/storage/PhabricatorMacroTransaction.php @@ -1,14 +1,7 @@ getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_FILE: - case self::TYPE_AUDIO: - if ($old !== null) { - $phids[] = $old; - } - $phids[] = $new; - break; - } - - return $phids; - } - - public function shouldHide() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - return ($old === null); - } - - return parent::shouldHide(); - } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - return pht( - '%s renamed this macro from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - break; - case self::TYPE_DISABLED: - if ($new) { - return pht( - '%s disabled this macro.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s restored this macro.', - $this->renderHandleLink($author_phid)); - } - break; - - case self::TYPE_AUDIO: - if (!$old) { - return pht( - '%s attached audio: %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($new)); - } else { - return pht( - '%s changed the audio for this macro from %s to %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - } - - case self::TYPE_AUDIO_BEHAVIOR: - switch ($new) { - case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE: - return pht( - '%s set the audio to play once.', - $this->renderHandleLink($author_phid)); - case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP: - return pht( - '%s set the audio to loop.', - $this->renderHandleLink($author_phid)); - default: - return pht( - '%s disabled the audio for this macro.', - $this->renderHandleLink($author_phid)); - } - - case self::TYPE_FILE: - if ($old === null) { - return pht( - '%s created this macro.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s changed the image for this macro from %s to %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - } - break; - } - - return parent::getTitle(); - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - return pht( - '%s renamed %s from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid), - $old, - $new); - case self::TYPE_DISABLED: - if ($new) { - return pht( - '%s disabled %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s restored %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - case self::TYPE_FILE: - if ($old === null) { - return pht( - '%s created %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s updated the image for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - - case self::TYPE_AUDIO: - if (!$old) { - return pht( - '%s attached audio to %s: %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid), - $this->renderHandleLink($new)); - } else { - return pht( - '%s changed the audio for %s from %s to %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - } - - case self::TYPE_AUDIO_BEHAVIOR: - switch ($new) { - case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE: - return pht( - '%s set the audio for %s to play once.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP: - return pht( - '%s set the audio for %s to loop.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - default: - return pht( - '%s disabled the audio for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - - } - - return parent::getTitleForFeed(); - } - - public function getActionName() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - if ($old === null) { - return pht('Created'); - } else { - return pht('Renamed'); - } - case self::TYPE_DISABLED: - if ($new) { - return pht('Disabled'); - } else { - return pht('Restored'); - } - case self::TYPE_FILE: - if ($old === null) { - return pht('Created'); - } else { - return pht('Edited Image'); - } - - case self::TYPE_AUDIO: - return pht('Audio'); - - case self::TYPE_AUDIO_BEHAVIOR: - return pht('Audio Behavior'); - - } - - return parent::getActionName(); - } - - public function getActionStrength() { - switch ($this->getTransactionType()) { - case self::TYPE_DISABLED: - return 2.0; - case self::TYPE_FILE: - return 1.5; - } - return parent::getActionStrength(); - } - - public function getIcon() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - return 'fa-pencil'; - case self::TYPE_FILE: - if ($old === null) { - return 'fa-plus'; - } else { - return 'fa-pencil'; - } - case self::TYPE_DISABLED: - if ($new) { - return 'fa-times'; - } else { - return 'fa-undo'; - } - case self::TYPE_AUDIO: - return 'fa-headphones'; - } - - return parent::getIcon(); - } - - public function getColor() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - return PhabricatorTransactions::COLOR_BLUE; - case self::TYPE_FILE: - if ($old === null) { - return PhabricatorTransactions::COLOR_GREEN; - } else { - return PhabricatorTransactions::COLOR_BLUE; - } - case self::TYPE_DISABLED: - if ($new) { - return PhabricatorTransactions::COLOR_RED; - } else { - return PhabricatorTransactions::COLOR_SKY; - } - } - - return parent::getColor(); + public function getBaseTransactionClass() { + return 'PhabricatorMacroTransactionType'; } diff --git a/src/applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php b/src/applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php new file mode 100644 index 0000000000..e27e9081ed --- /dev/null +++ b/src/applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php @@ -0,0 +1,69 @@ +getAudioBehavior(); + } + + public function applyInternalEffects($object, $value) { + $object->setAudioBehavior($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + $old = $this->getOldValue(); + switch ($new) { + case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE: + return pht( + '%s set the audio to play once.', + $this->renderAuthor()); + case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP: + return pht( + '%s set the audio to loop.', + $this->renderAuthor()); + default: + return pht( + '%s disabled the audio for this macro.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + $old = $this->getOldValue(); + switch ($new) { + case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE: + return pht( + '%s set the audio for %s to play once.', + $this->renderAuthor(), + $this->renderObject()); + case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP: + return pht( + '%s set the audio for %s to loop.', + $this->renderAuthor(), + $this->renderObject()); + default: + return pht( + '%s disabled the audio for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + switch ($new) { + case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_ONCE: + return 'fa-play-circle'; + case PhabricatorFileImageMacro::AUDIO_BEHAVIOR_LOOP: + return 'fa-repeat'; + default: + return 'fa-pause-circle'; + } + } + +} diff --git a/src/applications/macro/xaction/PhabricatorMacroAudioTransaction.php b/src/applications/macro/xaction/PhabricatorMacroAudioTransaction.php new file mode 100644 index 0000000000..aacf9f4016 --- /dev/null +++ b/src/applications/macro/xaction/PhabricatorMacroAudioTransaction.php @@ -0,0 +1,56 @@ +getAudioPHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setAudioPHID($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + $old = $this->getOldValue(); + if (!$old) { + return pht( + '%s attached audio: %s.', + $this->renderAuthor(), + $this->renderHandle($new)); + } else { + return pht( + '%s changed the audio for this macro from %s to %s.', + $this->renderAuthor(), + $this->renderHandle($old), + $this->renderHandle($new)); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + $old = $this->getOldValue(); + if (!$old) { + return pht( + '%s attached audio to %s: %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderHandle($new)); + } else { + return pht( + '%s changed the audio for %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderHandle($old), + $this->renderHandle($new)); + } + } + + public function getIcon() { + return 'fa-music'; + } + +} diff --git a/src/applications/macro/xaction/PhabricatorMacroDisabledTransaction.php b/src/applications/macro/xaction/PhabricatorMacroDisabledTransaction.php new file mode 100644 index 0000000000..334dc9ef6f --- /dev/null +++ b/src/applications/macro/xaction/PhabricatorMacroDisabledTransaction.php @@ -0,0 +1,50 @@ +getIsDisabled(); + } + + public function applyInternalEffects($object, $value) { + $object->setIsDisabled($value); + } + + public function getTitle() { + if ($this->getNewValue()) { + return pht( + '%s disabled this macro.', + $this->renderAuthor()); + } else { + return pht( + '%s restored this macro.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + if ($this->getNewValue()) { + return pht( + '%s disabled %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s restored %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + if ($this->getNewValue()) { + return 'fa-ban'; + } else { + return 'fa-check'; + } + } + +} diff --git a/src/applications/macro/xaction/PhabricatorMacroFileTransaction.php b/src/applications/macro/xaction/PhabricatorMacroFileTransaction.php new file mode 100644 index 0000000000..77c9f24dd9 --- /dev/null +++ b/src/applications/macro/xaction/PhabricatorMacroFileTransaction.php @@ -0,0 +1,68 @@ +getFilePHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setFilePHID($value); + } + + public function getTitle() { + return pht( + '%s changed the image for this macro.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s changed the image for macro %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + $viewer = $this->getActor(); + + foreach ($xactions as $xaction) { + $file_phid = $xaction->getNewValue(); + + if ($this->isEmptyTextTransaction($file_phid, $xactions)) { + $errors[] = $this->newRequiredError( + pht('Image macros must have a file.')); + } + + $file = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withPHIDs(array($file_phid)) + ->executeOne(); + + if (!$file) { + $errors[] = $this->newInvalidError( + pht('"%s" is not a valid file PHID.', + $file_phid)); + } else { + if (!$file->isViewableInBrowser()) { + $mime_type = $file->getMimeType(); + $errors[] = $this->newInvalidError( + pht('File mime type of "%s" is not a valid viewable image.', + $mime_type)); + } + } + + } + + return $errors; + } + + public function getIcon() { + return 'fa-file-image-o'; + } + +} diff --git a/src/applications/macro/xaction/PhabricatorMacroNameTransaction.php b/src/applications/macro/xaction/PhabricatorMacroNameTransaction.php new file mode 100644 index 0000000000..5b7b6f4417 --- /dev/null +++ b/src/applications/macro/xaction/PhabricatorMacroNameTransaction.php @@ -0,0 +1,80 @@ +getName(); + } + + public function applyInternalEffects($object, $value) { + $object->setName($value); + } + + public function getTitle() { + return pht( + '%s renamed this macro from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s renamed %s macro %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + $viewer = $this->getActor(); + + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Macros must have a name.')); + } + + $max_length = $object->getColumnMaximumByteLength('name'); + foreach ($xactions as $xaction) { + $old_value = $this->generateOldValue($object); + $new_value = $xaction->getNewValue(); + + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The name can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + + if (!preg_match('/^[a-z0-9:_-]{3,}\z/', $new_value)) { + $errors[] = $this->newInvalidError( + pht('Macro name "%s" be at least three characters long and contain '. + 'only lowercase letters, digits, hyphens, colons and '. + 'underscores.', + $new_value)); + } + + // Check name is unique when updating / creating + if ($old_value != $new_value) { + $macro = id(new PhabricatorMacroQuery()) + ->setViewer($viewer) + ->withNames(array($new_value)) + ->executeOne(); + + if ($macro) { + $errors[] = $this->newInvalidError( + pht('Macro "%s" already exists.', $new_value)); + } + } + + } + + return $errors; + } + +} diff --git a/src/applications/macro/xaction/PhabricatorMacroTransactionType.php b/src/applications/macro/xaction/PhabricatorMacroTransactionType.php new file mode 100644 index 0000000000..6a8e98c05b --- /dev/null +++ b/src/applications/macro/xaction/PhabricatorMacroTransactionType.php @@ -0,0 +1,4 @@ +setStatus('fa-ban', 'dark', pht('Uninstalled')); } + $timeline = $this->buildTransactionTimeline( + $selected, + new PhabricatorApplicationApplicationTransactionQuery()); + $timeline->setShouldTerminate(true); + $curtain = $this->buildCurtain($selected); $details = $this->buildPropertySectionView($selected); $policies = $this->buildPolicyView($selected); @@ -61,6 +66,7 @@ final class PhabricatorApplicationDetailViewController ->setMainColumn(array( $policies, $panels, + $timeline, )) ->addPropertySection(pht('Details'), $details); diff --git a/src/applications/meta/controller/PhabricatorApplicationEditController.php b/src/applications/meta/controller/PhabricatorApplicationEditController.php index ed51405db9..c9f6a2cafb 100644 --- a/src/applications/meta/controller/PhabricatorApplicationEditController.php +++ b/src/applications/meta/controller/PhabricatorApplicationEditController.php @@ -30,8 +30,15 @@ final class PhabricatorApplicationEditController ->execute(); if ($request->isFormPost()) { + $xactions = array(); + $result = array(); + $template = $application->getApplicationTransactionTemplate(); foreach ($application->getCapabilities() as $capability) { + if (!$application->isCapabilityEditable($capability)) { + continue; + } + $old = $application->getPolicy($capability); $new = $request->getStr('policy:'.$capability); @@ -40,67 +47,36 @@ final class PhabricatorApplicationEditController continue; } - if (empty($policies[$new])) { - // Not a standard policy, check for a custom policy. - $policy = id(new PhabricatorPolicyQuery()) - ->setViewer($user) - ->withPHIDs(array($new)) - ->executeOne(); - if (!$policy) { - // Not a custom policy either. Can't set the policy to something - // invalid, so skip this. - continue; - } - } - - if ($new == PhabricatorPolicies::POLICY_PUBLIC) { - $capobj = PhabricatorPolicyCapability::getCapabilityByKey( - $capability); - if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) { - // Can't set non-public policies to public. - continue; - } - } - $result[$capability] = $new; + + $xactions[] = id(clone $template) + ->setTransactionType( + PhabricatorApplicationPolicyChangeTransaction::TRANSACTIONTYPE) + ->setMetadataValue( + PhabricatorApplicationPolicyChangeTransaction::METADATA_ATTRIBUTE, + $capability) + ->setNewValue($new); } if ($result) { - $key = 'phabricator.application-settings'; - $config_entry = PhabricatorConfigEntry::loadConfigEntry($key); - $value = $config_entry->getValue(); + $editor = id(new PhabricatorApplicationEditor()) + ->setActor($user) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true); - $phid = $application->getPHID(); - if (empty($value[$phid])) { - $value[$application->getPHID()] = array(); - } - if (empty($value[$phid]['policy'])) { - $value[$phid]['policy'] = array(); + try { + $editor->applyTransactions($application, $xactions); + return id(new AphrontRedirectResponse())->setURI($view_uri); + } catch (PhabricatorApplicationTransactionValidationException $ex) { + $validation_exception = $ex; } - $value[$phid]['policy'] = $result + $value[$phid]['policy']; - - // Don't allow users to make policy edits which would lock them out of - // applications, since they would be unable to undo those actions. - PhabricatorEnv::overrideConfig($key, $value); - PhabricatorPolicyFilter::mustRetainCapability( - $user, - $application, - PhabricatorPolicyCapability::CAN_VIEW); - - PhabricatorPolicyFilter::mustRetainCapability( - $user, - $application, - PhabricatorPolicyCapability::CAN_EDIT); - - PhabricatorConfigEditor::storeNewValue( - $user, - $config_entry, - $value, - PhabricatorContentSource::newFromRequest($request)); + return $this->newDialog() + ->setTitle('Validation Failed') + ->setValidationException($validation_exception) + ->addCancelButton($view_uri); } - - return id(new AphrontRedirectResponse())->setURI($view_uri); } $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( diff --git a/src/applications/meta/editor/PhabricatorApplicationEditEngine.php b/src/applications/meta/editor/PhabricatorApplicationEditEngine.php new file mode 100644 index 0000000000..7cad5d9242 --- /dev/null +++ b/src/applications/meta/editor/PhabricatorApplicationEditEngine.php @@ -0,0 +1,64 @@ +getName()); + } + + protected function getObjectEditShortText($object) { + return $object->getName(); + } + + protected function getObjectCreateShortText() { + return pht('Create Application'); + } + + protected function getObjectName() { + return pht('Application'); + } + + protected function getObjectViewURI($object) { + return $object->getViewURI(); + } + + protected function buildCustomEditFields($object) { + return array(); + } + +} diff --git a/src/applications/meta/editor/PhabricatorApplicationEditor.php b/src/applications/meta/editor/PhabricatorApplicationEditor.php new file mode 100644 index 0000000000..83003b4c27 --- /dev/null +++ b/src/applications/meta/editor/PhabricatorApplicationEditor.php @@ -0,0 +1,46 @@ +getCapabilityName(); + return $application->getPolicy($capability); + } + + public function applyInternalEffects($object, $value) { + $application = $object; + $user = $this->getActor(); + + $key = 'phabricator.application-settings'; + $config_entry = PhabricatorConfigEntry::loadConfigEntry($key); + $current_value = $config_entry->getValue(); + + $phid = $application->getPHID(); + if (empty($current_value[$phid])) { + $current_value[$application->getPHID()] = array(); + } + if (empty($current_value[$phid]['policy'])) { + $current_value[$phid]['policy'] = array(); + } + + $new = array($this->getCapabilityName() => $value); + $current_value[$phid]['policy'] = $new + $current_value[$phid]['policy']; + + $editor = $this->getEditor(); + $content_source = $editor->getContentSource(); + PhabricatorConfigEditor::storeNewValue( + $user, + $config_entry, + $current_value, + $content_source); + } + + public function getTitle() { + $old = $this->renderPolicy($this->getOldValue()); + $new = $this->renderPolicy($this->getNewValue()); + + return pht( + '%s changed the "%s" policy from "%s" to "%s".', + $this->renderAuthor(), + $this->renderCapability(), + $old, + $new); + } + + public function getTitleForFeed() { + $old = $this->renderPolicy($this->getOldValue()); + $new = $this->renderPolicy($this->getNewValue()); + + return pht( + '%s changed the "%s" policy for application %s from "%s" to "%s".', + $this->renderAuthor(), + $this->renderCapability(), + $this->renderObject(), + $old, + $new); + } + + public function validateTransactions($object, array $xactions) { + $user = $this->getActor(); + $application = $object; + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($user) + ->setObject($application) + ->execute(); + + $errors = array(); + foreach ($xactions as $xaction) { + $new = $xaction->getNewValue(); + $capability = $xaction->getMetadataValue(self::METADATA_ATTRIBUTE); + + if (empty($policies[$new])) { + // Not a standard policy, check for a custom policy. + $policy = id(new PhabricatorPolicyQuery()) + ->setViewer($user) + ->withPHIDs(array($new)) + ->executeOne(); + if (!$policy) { + $errors[] = $this->newInvalidError( + pht('Policy does not exist.')); + continue; + } + } else { + $policy = idx($policies, $new); + } + + if (!$policy->isValidPolicyForEdit()) { + $errors[] = $this->newInvalidError( + pht('Can\'t set the policy to a policy you can\'t view!')); + continue; + } + + if ($new == PhabricatorPolicies::POLICY_PUBLIC) { + $capobj = PhabricatorPolicyCapability::getCapabilityByKey( + $capability); + if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) { + $errors[] = $this->newInvalidError( + pht('Can\'t set non-public policies to public.')); + continue; + } + } + + if (!$application->isCapabilityEditable($capability)) { + $errors[] = $this->newInvalidError( + pht('Capability "%s" is not editable for this application.', + $capability)); + continue; + } + } + + // If we're changing these policies, the viewer needs to still be able to + // view or edit the application under the new policy. + $validate_map = array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + ); + $validate_map = array_fill_keys($validate_map, array()); + + foreach ($xactions as $xaction) { + $capability = $xaction->getMetadataValue(self::METADATA_ATTRIBUTE); + if (!isset($validate_map[$capability])) { + continue; + } + + $validate_map[$capability][] = $xaction; + } + + foreach ($validate_map as $capability => $cap_xactions) { + if (!$cap_xactions) { + continue; + } + + $editor = $this->getEditor(); + $policy_errors = $editor->validatePolicyTransaction( + $object, + $cap_xactions, + self::TRANSACTIONTYPE, + $capability); + + foreach ($policy_errors as $error) { + $errors[] = $error; + } + } + + return $errors; + } + + private function renderPolicy($name) { + $policies = $this->getAllPolicies(); + if (empty($policies[$name])) { + // Not a standard policy, check for a custom policy. + $policy = id(new PhabricatorPolicyQuery()) + ->setViewer($this->getViewer()) + ->withPHIDs(array($name)) + ->executeOne(); + $policies[$name] = $policy; + } + + $policy = idx($policies, $name); + return $this->renderValue($policy->getFullName()); + } + + private function getAllPolicies() { + if (!$this->policies) { + $viewer = $this->getViewer(); + $application = $this->getObject(); + $this->policies = id(new PhabricatorPolicyQuery()) + ->setViewer($viewer) + ->setObject($application) + ->execute(); + } + + return $this->policies; + } + + private function renderCapability() { + $application = $this->getObject(); + $capability = $this->getCapabilityName(); + return $application->getCapabilityLabel($capability); + } + + private function getCapabilityName() { + return $this->getMetadataValue(self::METADATA_ATTRIBUTE); + } + +} diff --git a/src/applications/passphrase/controller/PassphraseCredentialConduitController.php b/src/applications/passphrase/controller/PassphraseCredentialConduitController.php index ce8f21f62d..3c95fd8459 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialConduitController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialConduitController.php @@ -50,7 +50,8 @@ final class PassphraseCredentialConduitController $xactions = array(); $xactions[] = id(new PassphraseCredentialTransaction()) - ->setTransactionType(PassphraseCredentialTransaction::TYPE_CONDUIT) + ->setTransactionType( + PassphraseCredentialConduitTransaction::TRANSACTIONTYPE) ->setNewValue(!$credential->getAllowConduit()); $editor = id(new PassphraseCredentialTransactionEditor()) diff --git a/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php b/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php index 8858d0ef6b..e1f0532f8a 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialDestroyController.php @@ -32,7 +32,8 @@ final class PassphraseCredentialDestroyController $xactions = array(); $xactions[] = id(new PassphraseCredentialTransaction()) - ->setTransactionType(PassphraseCredentialTransaction::TYPE_DESTROY) + ->setTransactionType( + PassphraseCredentialDestroyTransaction::TRANSACTIONTYPE) ->setNewValue(1); $editor = id(new PassphraseCredentialTransactionEditor()) diff --git a/src/applications/passphrase/controller/PassphraseCredentialEditController.php b/src/applications/passphrase/controller/PassphraseCredentialEditController.php index bdb1802880..9c86a7f5c9 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialEditController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialEditController.php @@ -117,12 +117,19 @@ final class PassphraseCredentialEditController extends PassphraseController { } if (!$errors) { - $type_name = PassphraseCredentialTransaction::TYPE_NAME; - $type_desc = PassphraseCredentialTransaction::TYPE_DESCRIPTION; - $type_username = PassphraseCredentialTransaction::TYPE_USERNAME; - $type_destroy = PassphraseCredentialTransaction::TYPE_DESTROY; - $type_secret_id = PassphraseCredentialTransaction::TYPE_SECRET_ID; - $type_is_locked = PassphraseCredentialTransaction::TYPE_LOCK; + $type_name = + PassphraseCredentialNameTransaction::TRANSACTIONTYPE; + $type_desc = + PassphraseCredentialDescriptionTransaction::TRANSACTIONTYPE; + $type_username = + PassphraseCredentialUsernameTransaction::TRANSACTIONTYPE; + $type_destroy = + PassphraseCredentialDestroyTransaction::TRANSACTIONTYPE; + $type_secret_id = + PassphraseCredentialSecretIDTransaction::TRANSACTIONTYPE; + $type_is_locked = + PassphraseCredentialLockTransaction::TRANSACTIONTYPE; + $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY; $type_space = PhabricatorTransactions::TYPE_SPACE; diff --git a/src/applications/passphrase/controller/PassphraseCredentialLockController.php b/src/applications/passphrase/controller/PassphraseCredentialLockController.php index 9832705427..b489851baa 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialLockController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialLockController.php @@ -40,11 +40,13 @@ final class PassphraseCredentialLockController $xactions = array(); $xactions[] = id(new PassphraseCredentialTransaction()) - ->setTransactionType(PassphraseCredentialTransaction::TYPE_CONDUIT) + ->setTransactionType( + PassphraseCredentialConduitTransaction::TRANSACTIONTYPE) ->setNewValue(0); $xactions[] = id(new PassphraseCredentialTransaction()) - ->setTransactionType(PassphraseCredentialTransaction::TYPE_LOCK) + ->setTransactionType( + PassphraseCredentialLockTransaction::TRANSACTIONTYPE) ->setNewValue(1); $editor = id(new PassphraseCredentialTransactionEditor()) diff --git a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php index 4fb299b85e..3a40d253c9 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php @@ -67,7 +67,7 @@ final class PassphraseCredentialRevealController ->setDisableWorkflowOnCancel(true) ->addCancelButton($view_uri, pht('Done')); - $type_secret = PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET; + $type_secret = PassphraseCredentialLookedAtTransaction::TRANSACTIONTYPE; $xactions = array( id(new PassphraseCredentialTransaction()) ->setTransactionType($type_secret) diff --git a/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php b/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php index fd743f4aac..1e23c874cf 100644 --- a/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php +++ b/src/applications/passphrase/editor/PassphraseCredentialTransactionEditor.php @@ -17,185 +17,15 @@ final class PassphraseCredentialTransactionEditor $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; - $types[] = PassphraseCredentialTransaction::TYPE_NAME; - $types[] = PassphraseCredentialTransaction::TYPE_DESCRIPTION; - $types[] = PassphraseCredentialTransaction::TYPE_USERNAME; - $types[] = PassphraseCredentialTransaction::TYPE_SECRET_ID; - $types[] = PassphraseCredentialTransaction::TYPE_DESTROY; - $types[] = PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET; - $types[] = PassphraseCredentialTransaction::TYPE_LOCK; - $types[] = PassphraseCredentialTransaction::TYPE_CONDUIT; - return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case PassphraseCredentialTransaction::TYPE_NAME: - if ($this->getIsNewObject()) { - return null; - } - return $object->getName(); - case PassphraseCredentialTransaction::TYPE_DESCRIPTION: - return $object->getDescription(); - case PassphraseCredentialTransaction::TYPE_USERNAME: - return $object->getUsername(); - case PassphraseCredentialTransaction::TYPE_SECRET_ID: - return $object->getSecretID(); - case PassphraseCredentialTransaction::TYPE_DESTROY: - return (int)$object->getIsDestroyed(); - case PassphraseCredentialTransaction::TYPE_LOCK: - return (int)$object->getIsLocked(); - case PassphraseCredentialTransaction::TYPE_CONDUIT: - return (int)$object->getAllowConduit(); - case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET: - return null; - } - - return parent::getCustomTransactionOldValue($object, $xaction); + public function getCreateObjectTitle($author, $object) { + return pht('%s created this credential.', $author); } - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case PassphraseCredentialTransaction::TYPE_NAME: - case PassphraseCredentialTransaction::TYPE_DESCRIPTION: - case PassphraseCredentialTransaction::TYPE_USERNAME: - case PassphraseCredentialTransaction::TYPE_SECRET_ID: - case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET: - return $xaction->getNewValue(); - case PassphraseCredentialTransaction::TYPE_DESTROY: - case PassphraseCredentialTransaction::TYPE_LOCK: - return (int)$xaction->getNewValue(); - case PassphraseCredentialTransaction::TYPE_CONDUIT: - return (int)$xaction->getNewValue(); - } - return parent::getCustomTransactionNewValue($object, $xaction); - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case PassphraseCredentialTransaction::TYPE_NAME: - $object->setName($xaction->getNewValue()); - return; - case PassphraseCredentialTransaction::TYPE_DESCRIPTION: - $object->setDescription($xaction->getNewValue()); - return; - case PassphraseCredentialTransaction::TYPE_USERNAME: - $object->setUsername($xaction->getNewValue()); - return; - case PassphraseCredentialTransaction::TYPE_SECRET_ID: - $old_id = $object->getSecretID(); - if ($old_id) { - $this->destroySecret($old_id); - } - $object->setSecretID($xaction->getNewValue()); - return; - case PassphraseCredentialTransaction::TYPE_DESTROY: - // When destroying a credential, wipe out its secret. - $is_destroyed = $xaction->getNewValue(); - $object->setIsDestroyed($is_destroyed); - if ($is_destroyed) { - $secret_id = $object->getSecretID(); - if ($secret_id) { - $this->destroySecret($secret_id); - $object->setSecretID(null); - } - } - return; - case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET: - return; - case PassphraseCredentialTransaction::TYPE_LOCK: - $object->setIsLocked((int)$xaction->getNewValue()); - return; - case PassphraseCredentialTransaction::TYPE_CONDUIT: - $object->setAllowConduit((int)$xaction->getNewValue()); - return; - } - - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PassphraseCredentialTransaction::TYPE_NAME: - case PassphraseCredentialTransaction::TYPE_DESCRIPTION: - case PassphraseCredentialTransaction::TYPE_USERNAME: - case PassphraseCredentialTransaction::TYPE_SECRET_ID: - case PassphraseCredentialTransaction::TYPE_DESTROY: - case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET: - case PassphraseCredentialTransaction::TYPE_LOCK: - case PassphraseCredentialTransaction::TYPE_CONDUIT: - return; - } - - return parent::applyCustomExternalTransaction($object, $xaction); - } - - private function destroySecret($secret_id) { - $table = new PassphraseSecret(); - queryfx( - $table->establishConnection('w'), - 'DELETE FROM %T WHERE id = %d', - $table->getTableName(), - $secret_id); - } - - protected function validateTransaction( - PhabricatorLiskDAO $object, - $type, - array $xactions) { - - $errors = parent::validateTransaction($object, $type, $xactions); - - switch ($type) { - case PassphraseCredentialTransaction::TYPE_NAME: - $missing = $this->validateIsEmptyTextField( - $object->getName(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Credential name is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - break; - case PassphraseCredentialTransaction::TYPE_USERNAME: - $credential_type = $object->getImplementation(); - if (!$credential_type->shouldRequireUsername()) { - break; - } - $missing = $this->validateIsEmptyTextField( - $object->getUsername(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Username is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - break; - } - - return $errors; + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); } protected function supportsSearch() { diff --git a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php index e0c90fcdb9..b7e4f904ef 100644 --- a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php +++ b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php @@ -1,16 +1,7 @@ getOldValue(); - $new = $this->getNewValue(); - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - return ($old === null); - case self::TYPE_LOCK: - return ($old === null); - case self::TYPE_USERNAME: - return !strlen($old); - case self::TYPE_LOOKEDATSECRET: - return false; - case self::TYPE_DESTROY: - // Don't show "undestroy" transactions because they're a bit confusing - // and redundant with restoring a secret. - if (!$new) { - return true; - } - } - return parent::shouldHide(); - } - - public function getTitle() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - $author_phid = $this->getAuthorPHID(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created this credential.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s renamed this credential from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } - break; - case self::TYPE_DESCRIPTION: - return pht( - '%s updated the description for this credential.', - $this->renderHandleLink($author_phid)); - case self::TYPE_USERNAME: - if (strlen($old)) { - return pht( - '%s changed the username for this credential from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } else { - return pht( - '%s set the username for this credential to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_SECRET_ID: - if ($old === null) { - return pht( - '%s attached a new secret to this credential.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s updated the secret for this credential.', - $this->renderHandleLink($author_phid)); - } - case self::TYPE_DESTROY: - return pht( - '%s destroyed the secret for this credential.', - $this->renderHandleLink($author_phid)); - case self::TYPE_LOOKEDATSECRET: - return pht( - '%s examined the secret plaintext for this credential.', - $this->renderHandleLink($author_phid)); - case self::TYPE_LOCK: - return pht( - '%s locked this credential.', - $this->renderHandleLink($author_phid)); - case self::TYPE_CONDUIT: - if ($old) { - return pht( - '%s disallowed Conduit API access to this credential.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s allowed Conduit API access to this credential.', - $this->renderHandleLink($author_phid)); - } - break; - } - - return parent::getTitle(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - return true; - } - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - json_encode($this->getOldValue()), - json_encode($this->getNewValue())); + public function getBaseTransactionClass() { + return 'PassphraseCredentialTransactionType'; } } diff --git a/src/applications/passphrase/xaction/PassphraseCredentialConduitTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialConduitTransaction.php new file mode 100644 index 0000000000..57d9828560 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialConduitTransaction.php @@ -0,0 +1,53 @@ +getAllowConduit(); + } + + public function applyInternalEffects($object, $value) { + $object->setAllowConduit((int)$value); + } + + public function getTitle() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s allowed Conduit API access to this credential.', + $this->renderAuthor()); + } else { + return pht( + '%s disallowed Conduit API access to this credential.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s allowed Conduit API access to credential %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s disallowed Conduit API access to credential %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + if ($new) { + return 'fa-tty'; + } else { + return 'fa-ban'; + } + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialDescriptionTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialDescriptionTransaction.php new file mode 100644 index 0000000000..ec989cf9c9 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialDescriptionTransaction.php @@ -0,0 +1,64 @@ +getDescription(); + } + + public function applyInternalEffects($object, $value) { + $object->setDescription($value); + } + + public function shouldHide() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return true; + } + return false; + } + + public function getTitle() { + return pht( + '%s updated the description for this credential.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the description for credential %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO CREDENTIAL DESCRIPTION'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialDestroyTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialDestroyTransaction.php new file mode 100644 index 0000000000..3983fd0bbc --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialDestroyTransaction.php @@ -0,0 +1,52 @@ +getIsDestroyed(); + } + + public function applyInternalEffects($object, $value) { + $is_destroyed = $value; + $object->setIsDestroyed($is_destroyed); + if ($is_destroyed) { + $secret_id = $object->getSecretID(); + if ($secret_id) { + $this->destroySecret($secret_id); + $object->setSecretID(null); + } + } + } + + public function shouldHide() { + $new = $this->getNewValue(); + if (!$new) { + return true; + } + } + + public function getTitle() { + return pht( + '%s destroyed the secret for this credential.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s destroyed the secret for credential %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-ban'; + } + + public function getColor() { + return 'red'; + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialLockTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialLockTransaction.php new file mode 100644 index 0000000000..64eba1da71 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialLockTransaction.php @@ -0,0 +1,41 @@ +getIsLocked(); + } + + public function applyInternalEffects($object, $value) { + $object->setIsLocked((int)$value); + } + + public function shouldHide() { + $new = $this->getNewValue(); + if ($new === null) { + return true; + } + return false; + } + + public function getTitle() { + return pht( + '%s locked this credential.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s locked credential %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-lock'; + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php new file mode 100644 index 0000000000..3d8cb36f31 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php @@ -0,0 +1,33 @@ +renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s examined the secret plaintext for credential %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-eye'; + } + + public function getColor() { + return 'blue'; + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialNameTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialNameTransaction.php new file mode 100644 index 0000000000..1afac71395 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialNameTransaction.php @@ -0,0 +1,71 @@ +getName(); + } + + public function applyInternalEffects($object, $value) { + $object->setName($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s created this credential.', + $this->renderAuthor()); + } else { + return pht( + '%s renamed this credential from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s created %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s renamed %s credential %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Credentials must have a name.')); + } + + $max_length = $object->getColumnMaximumByteLength('name'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The name can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialSecretIDTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialSecretIDTransaction.php new file mode 100644 index 0000000000..2c8e53553a --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialSecretIDTransaction.php @@ -0,0 +1,56 @@ +getSecretID(); + } + + public function applyInternalEffects($object, $value) { + $old_id = $object->getSecretID(); + if ($old_id) { + $this->destroySecret($old_id); + } + $object->setSecretID($value); + } + + public function shouldHide() { + if (!$this->getOldValue()) { + return true; + } + + return false; + } + + public function getTitle() { + $old = $this->getOldValue(); + if ($old === null) { + return pht( + '%s attached a new secret to this credential.', + $this->renderAuthor()); + } else { + return pht( + '%s updated the secret for this credential.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if ($old === null) { + return pht( + '%s attached a new secret to %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s updated the secret for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialTransactionType.php b/src/applications/passphrase/xaction/PassphraseCredentialTransactionType.php new file mode 100644 index 0000000000..4e6aadb697 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialTransactionType.php @@ -0,0 +1,15 @@ +establishConnection('w'), + 'DELETE FROM %T WHERE id = %d', + $table->getTableName(), + $secret_id); + } + +} diff --git a/src/applications/passphrase/xaction/PassphraseCredentialUsernameTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialUsernameTransaction.php new file mode 100644 index 0000000000..fe07bd2990 --- /dev/null +++ b/src/applications/passphrase/xaction/PassphraseCredentialUsernameTransaction.php @@ -0,0 +1,56 @@ +getUsername(); + } + + public function applyInternalEffects($object, $value) { + $object->setUsername($value); + } + + public function getTitle() { + return pht( + '%s set the username for this credential to %s.', + $this->renderAuthor(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s set the username for credential %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $credential_type = $object->getImplementation(); + if ($credential_type->shouldRequireUsername()) { + if ($this->isEmptyTextTransaction($object->getUsername(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('This credential must have a username.')); + } + } + + $max_length = $object->getColumnMaximumByteLength('username'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The username can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/people/markup/PhabricatorMentionRemarkupRule.php b/src/applications/people/markup/PhabricatorMentionRemarkupRule.php index 1f82d78423..aa5b7f908e 100644 --- a/src/applications/people/markup/PhabricatorMentionRemarkupRule.php +++ b/src/applications/people/markup/PhabricatorMentionRemarkupRule.php @@ -150,7 +150,9 @@ final class PhabricatorMentionRemarkupRule extends PhutilRemarkupRule { $tag->addClass('phabricator-remarkup-mention-nopermission'); } - if (!$user->isResponsive()) { + if ($user->getIsDisabled()) { + $tag->setDotColor(PHUITagView::COLOR_GREY); + } else if (!$user->isResponsive()) { $tag->setDotColor(PHUITagView::COLOR_VIOLET); } else { if ($user->getAwayUntil()) { diff --git a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php index b2a456cd51..f0512e91f1 100644 --- a/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php +++ b/src/applications/people/phid/PhabricatorPeopleUserPHIDType.php @@ -61,7 +61,9 @@ final class PhabricatorPeopleUserPHIDType extends PhabricatorPHIDType { } $availability = null; - if (!$user->isResponsive()) { + if ($user->getIsDisabled()) { + $availability = PhabricatorObjectHandle::AVAILABILITY_DISABLED; + } else if (!$user->isResponsive()) { $availability = PhabricatorObjectHandle::AVAILABILITY_NOEMAIL; } else { $until = $user->getAwayUntil(); diff --git a/src/applications/phame/controller/blog/PhameBlogArchiveController.php b/src/applications/phame/controller/blog/PhameBlogArchiveController.php index 4c8d4a4a63..8b63bad9ff 100644 --- a/src/applications/phame/controller/blog/PhameBlogArchiveController.php +++ b/src/applications/phame/controller/blog/PhameBlogArchiveController.php @@ -32,7 +32,7 @@ final class PhameBlogArchiveController $xactions = array(); $xactions[] = id(new PhameBlogTransaction()) - ->setTransactionType(PhameBlogTransaction::TYPE_STATUS) + ->setTransactionType(PhameBlogStatusTransaction::TRANSACTIONTYPE) ->setNewValue($new_status); id(new PhameBlogEditor()) diff --git a/src/applications/phame/controller/blog/PhameBlogHeaderPictureController.php b/src/applications/phame/controller/blog/PhameBlogHeaderPictureController.php index ab026fecbf..0106b9571d 100644 --- a/src/applications/phame/controller/blog/PhameBlogHeaderPictureController.php +++ b/src/applications/phame/controller/blog/PhameBlogHeaderPictureController.php @@ -61,7 +61,7 @@ final class PhameBlogHeaderPictureController $xactions = array(); $xactions[] = id(new PhameBlogTransaction()) - ->setTransactionType(PhameBlogTransaction::TYPE_HEADERIMAGE) + ->setTransactionType(PhameBlogHeaderImageTransaction::TRANSACTIONTYPE) ->setNewValue($new_value); $editor = id(new PhameBlogEditor()) diff --git a/src/applications/phame/controller/blog/PhameBlogProfilePictureController.php b/src/applications/phame/controller/blog/PhameBlogProfilePictureController.php index 3368046414..04b41dbb79 100644 --- a/src/applications/phame/controller/blog/PhameBlogProfilePictureController.php +++ b/src/applications/phame/controller/blog/PhameBlogProfilePictureController.php @@ -76,7 +76,8 @@ final class PhameBlogProfilePictureController $xactions = array(); $xactions[] = id(new PhameBlogTransaction()) - ->setTransactionType(PhameBlogTransaction::TYPE_PROFILEIMAGE) + ->setTransactionType( + PhameBlogProfileImageTransaction::TRANSACTIONTYPE) ->setNewValue($new_value); $editor = id(new PhameBlogEditor()) diff --git a/src/applications/phame/controller/post/PhamePostArchiveController.php b/src/applications/phame/controller/post/PhamePostArchiveController.php index 5a3b32944a..b8647121ef 100644 --- a/src/applications/phame/controller/post/PhamePostArchiveController.php +++ b/src/applications/phame/controller/post/PhamePostArchiveController.php @@ -26,7 +26,7 @@ final class PhamePostArchiveController extends PhamePostController { $new_value = PhameConstants::VISIBILITY_ARCHIVED; $xactions[] = id(new PhamePostTransaction()) - ->setTransactionType(PhamePostTransaction::TYPE_VISIBILITY) + ->setTransactionType(PhamePostVisibilityTransaction::TRANSACTIONTYPE) ->setNewValue($new_value); id(new PhamePostEditor()) diff --git a/src/applications/phame/controller/post/PhamePostHeaderPictureController.php b/src/applications/phame/controller/post/PhamePostHeaderPictureController.php index 2e60c9ba71..60075cc077 100644 --- a/src/applications/phame/controller/post/PhamePostHeaderPictureController.php +++ b/src/applications/phame/controller/post/PhamePostHeaderPictureController.php @@ -61,7 +61,7 @@ final class PhamePostHeaderPictureController $xactions = array(); $xactions[] = id(new PhamePostTransaction()) - ->setTransactionType(PhamePostTransaction::TYPE_HEADERIMAGE) + ->setTransactionType(PhamePostHeaderImageTransaction::TRANSACTIONTYPE) ->setNewValue($new_value); $editor = id(new PhamePostEditor()) diff --git a/src/applications/phame/controller/post/PhamePostMoveController.php b/src/applications/phame/controller/post/PhamePostMoveController.php index 3e09a9ba2d..d088b260b5 100644 --- a/src/applications/phame/controller/post/PhamePostMoveController.php +++ b/src/applications/phame/controller/post/PhamePostMoveController.php @@ -28,7 +28,7 @@ final class PhamePostMoveController extends PhamePostController { $xactions = array(); $xactions[] = id(new PhamePostTransaction()) - ->setTransactionType(PhamePostTransaction::TYPE_BLOG) + ->setTransactionType(PhamePostBlogTransaction::TRANSACTIONTYPE) ->setNewValue($v_blog); $editor = id(new PhamePostEditor()) diff --git a/src/applications/phame/controller/post/PhamePostPublishController.php b/src/applications/phame/controller/post/PhamePostPublishController.php index 567099f0d4..70989082bd 100644 --- a/src/applications/phame/controller/post/PhamePostPublishController.php +++ b/src/applications/phame/controller/post/PhamePostPublishController.php @@ -34,7 +34,7 @@ final class PhamePostPublishController extends PhamePostController { } $xactions[] = id(new PhamePostTransaction()) - ->setTransactionType(PhamePostTransaction::TYPE_VISIBILITY) + ->setTransactionType(PhamePostVisibilityTransaction::TRANSACTIONTYPE) ->setNewValue($new_value); id(new PhamePostEditor()) diff --git a/src/applications/phame/editor/PhameBlogEditEngine.php b/src/applications/phame/editor/PhameBlogEditEngine.php index 7d6511d55c..6d6c0a9f77 100644 --- a/src/applications/phame/editor/PhameBlogEditEngine.php +++ b/src/applications/phame/editor/PhameBlogEditEngine.php @@ -75,7 +75,7 @@ final class PhameBlogEditEngine ->setDescription(pht('Blog name.')) ->setConduitDescription(pht('Retitle the blog.')) ->setConduitTypeDescription(pht('New blog title.')) - ->setTransactionType(PhameBlogTransaction::TYPE_NAME) + ->setTransactionType(PhameBlogNameTransaction::TRANSACTIONTYPE) ->setValue($object->getName()), id(new PhabricatorTextEditField()) ->setKey('subtitle') @@ -83,7 +83,7 @@ final class PhameBlogEditEngine ->setDescription(pht('Blog subtitle.')) ->setConduitDescription(pht('Change the blog subtitle.')) ->setConduitTypeDescription(pht('New blog subtitle.')) - ->setTransactionType(PhameBlogTransaction::TYPE_SUBTITLE) + ->setTransactionType(PhameBlogSubtitleTransaction::TRANSACTIONTYPE) ->setValue($object->getSubtitle()), id(new PhabricatorRemarkupEditField()) ->setKey('description') @@ -91,7 +91,7 @@ final class PhameBlogEditEngine ->setDescription(pht('Blog description.')) ->setConduitDescription(pht('Change the blog description.')) ->setConduitTypeDescription(pht('New blog description.')) - ->setTransactionType(PhameBlogTransaction::TYPE_DESCRIPTION) + ->setTransactionType(PhameBlogDescriptionTransaction::TRANSACTIONTYPE) ->setValue($object->getDescription()), id(new PhabricatorTextEditField()) ->setKey('domainFullURI') @@ -104,7 +104,7 @@ final class PhameBlogEditEngine ->setConduitDescription(pht('Change the blog full domain URI.')) ->setConduitTypeDescription(pht('New blog full domain URI.')) ->setValue($object->getDomainFullURI()) - ->setTransactionType(PhameBlogTransaction::TYPE_FULLDOMAIN), + ->setTransactionType(PhameBlogFullDomainTransaction::TRANSACTIONTYPE), id(new PhabricatorTextEditField()) ->setKey('parentSite') ->setLabel(pht('Parent Site Name')) @@ -112,7 +112,7 @@ final class PhameBlogEditEngine ->setConduitDescription(pht('Change the blog parent site name.')) ->setConduitTypeDescription(pht('New blog parent site name.')) ->setValue($object->getParentSite()) - ->setTransactionType(PhameBlogTransaction::TYPE_PARENTSITE), + ->setTransactionType(PhameBlogParentSiteTransaction::TRANSACTIONTYPE), id(new PhabricatorTextEditField()) ->setKey('parentDomain') ->setLabel(pht('Parent Site URI')) @@ -120,11 +120,11 @@ final class PhameBlogEditEngine ->setConduitDescription(pht('Change the blog parent domain.')) ->setConduitTypeDescription(pht('New blog parent domain.')) ->setValue($object->getParentDomain()) - ->setTransactionType(PhameBlogTransaction::TYPE_PARENTDOMAIN), + ->setTransactionType(PhameBlogParentDomainTransaction::TRANSACTIONTYPE), id(new PhabricatorSelectEditField()) ->setKey('status') ->setLabel(pht('Status')) - ->setTransactionType(PhameBlogTransaction::TYPE_STATUS) + ->setTransactionType(PhameBlogStatusTransaction::TRANSACTIONTYPE) ->setIsConduitOnly(true) ->setOptions(PhameBlog::getStatusNameMap()) ->setDescription(pht('Active or archived status.')) diff --git a/src/applications/phame/editor/PhameBlogEditor.php b/src/applications/phame/editor/PhameBlogEditor.php index 14f63f51ac..f30a74065e 100644 --- a/src/applications/phame/editor/PhameBlogEditor.php +++ b/src/applications/phame/editor/PhameBlogEditor.php @@ -11,251 +11,22 @@ final class PhameBlogEditor return pht('Phame Blogs'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s created this blog.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); + } + public function getTransactionTypes() { $types = parent::getTransactionTypes(); - - $types[] = PhameBlogTransaction::TYPE_NAME; - $types[] = PhameBlogTransaction::TYPE_SUBTITLE; - $types[] = PhameBlogTransaction::TYPE_DESCRIPTION; - $types[] = PhameBlogTransaction::TYPE_FULLDOMAIN; - $types[] = PhameBlogTransaction::TYPE_PARENTSITE; - $types[] = PhameBlogTransaction::TYPE_PARENTDOMAIN; - $types[] = PhameBlogTransaction::TYPE_STATUS; - $types[] = PhameBlogTransaction::TYPE_HEADERIMAGE; - $types[] = PhameBlogTransaction::TYPE_PROFILEIMAGE; - $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhameBlogTransaction::TYPE_NAME: - return $object->getName(); - case PhameBlogTransaction::TYPE_SUBTITLE: - return $object->getSubtitle(); - case PhameBlogTransaction::TYPE_DESCRIPTION: - return $object->getDescription(); - case PhameBlogTransaction::TYPE_FULLDOMAIN: - return $object->getDomainFullURI(); - case PhameBlogTransaction::TYPE_PARENTSITE: - return $object->getParentSite(); - case PhameBlogTransaction::TYPE_PARENTDOMAIN: - return $object->getParentDomain(); - case PhameBlogTransaction::TYPE_PROFILEIMAGE: - return $object->getProfileImagePHID(); - case PhameBlogTransaction::TYPE_HEADERIMAGE: - return $object->getHeaderImagePHID(); - case PhameBlogTransaction::TYPE_STATUS: - return $object->getStatus(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhameBlogTransaction::TYPE_NAME: - case PhameBlogTransaction::TYPE_SUBTITLE: - case PhameBlogTransaction::TYPE_DESCRIPTION: - case PhameBlogTransaction::TYPE_STATUS: - case PhameBlogTransaction::TYPE_PARENTSITE: - case PhameBlogTransaction::TYPE_PARENTDOMAIN: - case PhameBlogTransaction::TYPE_PROFILEIMAGE: - case PhameBlogTransaction::TYPE_HEADERIMAGE: - return $xaction->getNewValue(); - case PhameBlogTransaction::TYPE_FULLDOMAIN: - $domain = $xaction->getNewValue(); - if (!strlen($xaction->getNewValue())) { - return null; - } - return $domain; - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhameBlogTransaction::TYPE_NAME: - return $object->setName($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_SUBTITLE: - return $object->setSubtitle($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_DESCRIPTION: - return $object->setDescription($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_FULLDOMAIN: - $new_value = $xaction->getNewValue(); - if (strlen($new_value)) { - $uri = new PhutilURI($new_value); - $domain = $uri->getDomain(); - $object->setDomain($domain); - } else { - $object->setDomain(null); - } - $object->setDomainFullURI($new_value); - return; - case PhameBlogTransaction::TYPE_PROFILEIMAGE: - return $object->setProfileImagePHID($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_HEADERIMAGE: - return $object->setHeaderImagePHID($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_STATUS: - return $object->setStatus($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_PARENTSITE: - return $object->setParentSite($xaction->getNewValue()); - case PhameBlogTransaction::TYPE_PARENTDOMAIN: - return $object->setParentDomain($xaction->getNewValue()); - } - - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhameBlogTransaction::TYPE_NAME: - case PhameBlogTransaction::TYPE_SUBTITLE: - case PhameBlogTransaction::TYPE_DESCRIPTION: - case PhameBlogTransaction::TYPE_FULLDOMAIN: - case PhameBlogTransaction::TYPE_PARENTSITE: - case PhameBlogTransaction::TYPE_PARENTDOMAIN: - case PhameBlogTransaction::TYPE_HEADERIMAGE: - case PhameBlogTransaction::TYPE_PROFILEIMAGE: - case PhameBlogTransaction::TYPE_STATUS: - return; - } - - return parent::applyCustomExternalTransaction($object, $xaction); - } - - protected function validateTransaction( - PhabricatorLiskDAO $object, - $type, - array $xactions) { - - $errors = parent::validateTransaction($object, $type, $xactions); - - - switch ($type) { - case PhameBlogTransaction::TYPE_NAME: - $missing = $this->validateIsEmptyTextField( - $object->getName(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Name is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - - foreach ($xactions as $xaction) { - $new = $xaction->getNewValue(); - if (phutil_utf8_strlen($new) > 64) { - $errors[] = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid'), - pht( - 'The selected blog title is too long. The maximum length '. - 'of a blog title is 64 characters.'), - $xaction); - } - } - break; - case PhameBlogTransaction::TYPE_SUBTITLE: - foreach ($xactions as $xaction) { - $new = $xaction->getNewValue(); - if (phutil_utf8_strlen($new) > 64) { - $errors[] = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid'), - pht( - 'The selected blog subtitle is too long. The maximum length '. - 'of a blog subtitle is 64 characters.'), - $xaction); - } - } - break; - case PhameBlogTransaction::TYPE_PARENTDOMAIN: - if (!$xactions) { - continue; - } - $parent_domain = last($xactions)->getNewValue(); - if (empty($parent_domain)) { - continue; - } - try { - PhabricatorEnv::requireValidRemoteURIForLink($parent_domain); - } catch (Exception $ex) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid URI'), - pht('Parent Domain must be set to a valid Remote URI.'), - nonempty(last($xactions), null)); - $errors[] = $error; - } - break; - case PhameBlogTransaction::TYPE_FULLDOMAIN: - if (!$xactions) { - continue; - } - $custom_domain = last($xactions)->getNewValue(); - if (empty($custom_domain)) { - continue; - } - list($error_label, $error_text) = - $object->validateCustomDomain($custom_domain); - if ($error_label) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - $error_label, - $error_text, - nonempty(last($xactions), null)); - $errors[] = $error; - } - if ($object->getViewPolicy() != PhabricatorPolicies::POLICY_PUBLIC) { - $error_text = pht( - 'For custom domains to work, the blog must have a view policy of '. - 'public.'); - $error = new PhabricatorApplicationTransactionValidationError( - PhabricatorTransactions::TYPE_VIEW_POLICY, - pht('Invalid Policy'), - $error_text, - nonempty(last($xactions), null)); - $errors[] = $error; - } - $domain = new PhutilURI($custom_domain); - $domain = $domain->getDomain(); - $duplicate_blog = id(new PhameBlogQuery()) - ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withDomain($domain) - ->executeOne(); - if ($duplicate_blog && $duplicate_blog->getID() != $object->getID()) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Not Unique'), - pht('Domain must be unique; another blog already has this domain.'), - nonempty(last($xactions), null)); - $errors[] = $error; - } - - break; - } - return $errors; - } - protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { diff --git a/src/applications/phame/editor/PhamePostEditEngine.php b/src/applications/phame/editor/PhamePostEditEngine.php index e80c1f6d0d..af1b1091d1 100644 --- a/src/applications/phame/editor/PhamePostEditEngine.php +++ b/src/applications/phame/editor/PhamePostEditEngine.php @@ -84,7 +84,7 @@ final class PhamePostEditEngine pht('Choose a blog to create a post on (or move a post to).')) ->setConduitTypeDescription(pht('PHID of the blog.')) ->setAliases(array('blogPHID')) - ->setTransactionType(PhamePostTransaction::TYPE_BLOG) + ->setTransactionType(PhamePostBlogTransaction::TRANSACTIONTYPE) ->setHandleParameterType(new AphrontPHIDListHTTPParameterType()) ->setSingleValue($blog_phid) ->setIsReorderable(false) @@ -97,7 +97,7 @@ final class PhamePostEditEngine ->setDescription(pht('Post title.')) ->setConduitDescription(pht('Retitle the post.')) ->setConduitTypeDescription(pht('New post title.')) - ->setTransactionType(PhamePostTransaction::TYPE_TITLE) + ->setTransactionType(PhamePostTitleTransaction::TRANSACTIONTYPE) ->setValue($object->getTitle()), id(new PhabricatorTextEditField()) ->setKey('subtitle') @@ -105,7 +105,7 @@ final class PhamePostEditEngine ->setDescription(pht('Post subtitle.')) ->setConduitDescription(pht('Change the post subtitle.')) ->setConduitTypeDescription(pht('New post subtitle.')) - ->setTransactionType(PhamePostTransaction::TYPE_SUBTITLE) + ->setTransactionType(PhamePostSubtitleTransaction::TRANSACTIONTYPE) ->setValue($object->getSubtitle()), id(new PhabricatorSelectEditField()) ->setKey('visibility') @@ -113,7 +113,7 @@ final class PhamePostEditEngine ->setDescription(pht('Post visibility.')) ->setConduitDescription(pht('Change post visibility.')) ->setConduitTypeDescription(pht('New post visibility constant.')) - ->setTransactionType(PhamePostTransaction::TYPE_VISIBILITY) + ->setTransactionType(PhamePostVisibilityTransaction::TRANSACTIONTYPE) ->setValue($object->getVisibility()) ->setOptions(PhameConstants::getPhamePostStatusMap()), id(new PhabricatorRemarkupEditField()) @@ -122,7 +122,7 @@ final class PhamePostEditEngine ->setDescription(pht('Post body.')) ->setConduitDescription(pht('Change post body.')) ->setConduitTypeDescription(pht('New post body.')) - ->setTransactionType(PhamePostTransaction::TYPE_BODY) + ->setTransactionType(PhamePostBodyTransaction::TRANSACTIONTYPE) ->setValue($object->getBody()) ->setPreviewPanel( id(new PHUIRemarkupPreviewPanel()) diff --git a/src/applications/phame/editor/PhamePostEditor.php b/src/applications/phame/editor/PhamePostEditor.php index 929613fe80..8f0e2b5099 100644 --- a/src/applications/phame/editor/PhamePostEditor.php +++ b/src/applications/phame/editor/PhamePostEditor.php @@ -11,177 +11,21 @@ final class PhamePostEditor return pht('Phame Posts'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s created this post.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); + } + public function getTransactionTypes() { $types = parent::getTransactionTypes(); - - $types[] = PhamePostTransaction::TYPE_BLOG; - $types[] = PhamePostTransaction::TYPE_TITLE; - $types[] = PhamePostTransaction::TYPE_SUBTITLE; - $types[] = PhamePostTransaction::TYPE_BODY; - $types[] = PhamePostTransaction::TYPE_VISIBILITY; - $types[] = PhamePostTransaction::TYPE_HEADERIMAGE; $types[] = PhabricatorTransactions::TYPE_COMMENT; return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhamePostTransaction::TYPE_BLOG: - return $object->getBlogPHID(); - case PhamePostTransaction::TYPE_TITLE: - return $object->getTitle(); - case PhamePostTransaction::TYPE_SUBTITLE: - return $object->getSubtitle(); - case PhamePostTransaction::TYPE_BODY: - return $object->getBody(); - case PhamePostTransaction::TYPE_VISIBILITY: - return $object->getVisibility(); - case PhamePostTransaction::TYPE_HEADERIMAGE: - return $object->getHeaderImagePHID(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhamePostTransaction::TYPE_TITLE: - case PhamePostTransaction::TYPE_SUBTITLE: - case PhamePostTransaction::TYPE_BODY: - case PhamePostTransaction::TYPE_VISIBILITY: - case PhamePostTransaction::TYPE_HEADERIMAGE: - case PhamePostTransaction::TYPE_BLOG: - return $xaction->getNewValue(); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhamePostTransaction::TYPE_TITLE: - return $object->setTitle($xaction->getNewValue()); - case PhamePostTransaction::TYPE_SUBTITLE: - return $object->setSubtitle($xaction->getNewValue()); - case PhamePostTransaction::TYPE_BODY: - return $object->setBody($xaction->getNewValue()); - case PhamePostTransaction::TYPE_BLOG: - return $object->setBlogPHID($xaction->getNewValue()); - case PhamePostTransaction::TYPE_HEADERIMAGE: - return $object->setHeaderImagePHID($xaction->getNewValue()); - case PhamePostTransaction::TYPE_VISIBILITY: - if ($xaction->getNewValue() == PhameConstants::VISIBILITY_DRAFT) { - $object->setDatePublished(0); - } else if ($xaction->getNewValue() == - PhameConstants::VISIBILITY_ARCHIVED) { - $object->setDatePublished(0); - } else { - $object->setDatePublished(PhabricatorTime::getNow()); - } - return $object->setVisibility($xaction->getNewValue()); - } - - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhamePostTransaction::TYPE_TITLE: - case PhamePostTransaction::TYPE_SUBTITLE: - case PhamePostTransaction::TYPE_BODY: - case PhamePostTransaction::TYPE_VISIBILITY: - case PhamePostTransaction::TYPE_HEADERIMAGE: - case PhamePostTransaction::TYPE_BLOG: - return; - } - - return parent::applyCustomExternalTransaction($object, $xaction); - } - - protected function validateTransaction( - PhabricatorLiskDAO $object, - $type, - array $xactions) { - - $errors = parent::validateTransaction($object, $type, $xactions); - - switch ($type) { - case PhamePostTransaction::TYPE_TITLE: - $missing = $this->validateIsEmptyTextField( - $object->getTitle(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Title is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - break; - case PhamePostTransaction::TYPE_BLOG: - if ($this->getIsNewObject()) { - if (!$xactions) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht( - 'When creating a post, you must specify which blog it '. - 'should belong to.'), - null); - - $error->setIsMissingFieldError(true); - - $errors[] = $error; - break; - } - } - - foreach ($xactions as $xaction) { - $new_phid = $xaction->getNewValue(); - - $blog = id(new PhameBlogQuery()) - ->setViewer($this->getActor()) - ->withPHIDs(array($new_phid)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->execute(); - - if ($blog) { - continue; - } - - $errors[] = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid'), - pht( - 'The specified blog PHID ("%s") is not valid. You can only '. - 'create a post on (or move a post into) a blog which you '. - 'have permission to see and edit.', - $new_phid), - $xaction); - } - - break; - } - return $errors; - } - protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php index bd4954d0ab..b72fc4bcfe 100644 --- a/src/applications/phame/storage/PhameBlog.php +++ b/src/applications/phame/storage/PhameBlog.php @@ -127,53 +127,41 @@ final class PhameBlog extends PhameDAO $supported_protocols = array('http', 'https'); if (!in_array($protocol, $supported_protocols)) { - return array( - $label, - pht( + return pht( 'The custom domain should include a valid protocol in the URI '. '(for example, "%s"). Valid protocols are "http" or "https".', - $example_domain), - ); + $example_domain); } if (strlen($path) && $path != '/') { - return array( - $label, - pht( + return pht( 'The custom domain should not specify a path (hosting a Phame '. 'blog at a path is currently not supported). Instead, just provide '. 'the bare domain name (for example, "%s").', - $example_domain), - ); + $example_domain); } if (strpos($domain, '.') === false) { - return array( - $label, - pht( + return pht( 'The custom domain should contain at least one dot (.) because '. 'some browsers fail to set cookies on domains without a dot. '. 'Instead, use a normal looking domain name like "%s".', - $example_domain), - ); + $example_domain); } if (!PhabricatorEnv::getEnvConfig('policy.allow-public')) { $href = PhabricatorEnv::getProductionURI( '/config/edit/policy.allow-public/'); - return array( - pht('Fix Configuration'), - pht( - 'For custom domains to work, this Phabricator instance must be '. - 'configured to allow the public access policy. Configure this '. - 'setting %s, or ask an administrator to configure this setting. '. - 'The domain can be specified later once this setting has been '. - 'changed.', - phutil_tag( - 'a', - array('href' => $href), - pht('here'))), - ); + return pht( + 'For custom domains to work, this Phabricator instance must be '. + 'configured to allow the public access policy. Configure this '. + 'setting %s, or ask an administrator to configure this setting. '. + 'The domain can be specified later once this setting has been '. + 'changed.', + phutil_tag( + 'a', + array('href' => $href), + pht('here'))); } return null; diff --git a/src/applications/phame/storage/PhameBlogTransaction.php b/src/applications/phame/storage/PhameBlogTransaction.php index f08c7be688..c5702a2b18 100644 --- a/src/applications/phame/storage/PhameBlogTransaction.php +++ b/src/applications/phame/storage/PhameBlogTransaction.php @@ -1,17 +1,7 @@ getOldValue(); - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - if ($old === null) { - return true; - } - } - return parent::shouldHide(); - } - - public function getRequiredHandlePHIDs() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $req_phids = array(); - switch ($this->getTransactionType()) { - case self::TYPE_PROFILEIMAGE: - case self::TYPE_HEADERIMAGE: - $req_phids[] = $old; - $req_phids[] = $new; - break; - } - - return array_merge($req_phids, parent::getRequiredHandlePHIDs()); - } - - public function getIcon() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - if ($old === null) { - return 'fa-plus'; - } else { - return 'fa-pencil'; - } - break; - case self::TYPE_DESCRIPTION: - case self::TYPE_FULLDOMAIN: - return 'fa-pencil'; - case self::TYPE_HEADERIMAGE: - return 'fa-image'; - case self::TYPE_PROFILEIMAGE: - return 'fa-star'; - case self::TYPE_STATUS: - if ($new == PhameBlog::STATUS_ARCHIVED) { - return 'fa-ban'; - } else { - return 'fa-check'; - } - break; - } - return parent::getIcon(); - } - - public function getColor() { - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_STATUS: - if ($new == PhameBlog::STATUS_ARCHIVED) { - return 'violet'; - } else { - return 'green'; - } - } - return parent::getColor(); + public function getBaseTransactionClass() { + return 'PhameBlogTransactionType'; } public function getMailTags() { @@ -121,247 +43,4 @@ final class PhameBlogTransaction return $tags; } - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case PhabricatorTransactions::TYPE_CREATE: - return pht( - '%s created this blog.', - $this->renderHandleLink($author_phid)); - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created this blog.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s updated the blog\'s name to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_SUBTITLE: - if ($old === null) { - return pht( - '%s set this blog\'s subtitle to "%s".', - $this->renderHandleLink($author_phid), - $new); - } else { - return pht( - '%s updated the blog\'s subtitle to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_DESCRIPTION: - return pht( - '%s updated the blog\'s description.', - $this->renderHandleLink($author_phid)); - break; - case self::TYPE_FULLDOMAIN: - return pht( - '%s updated the blog\'s full domain to "%s".', - $this->renderHandleLink($author_phid), - $new); - break; - case self::TYPE_PARENTSITE: - if ($old === null) { - return pht( - '%s set this blog\'s parent site to "%s".', - $this->renderHandleLink($author_phid), - $new); - } else { - return pht( - '%s updated the blog\'s parent site to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_PARENTDOMAIN: - if ($old === null) { - return pht( - '%s set this blog\'s parent domain to "%s".', - $this->renderHandleLink($author_phid), - $new); - } else { - return pht( - '%s updated the blog\'s parent domain to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_HEADERIMAGE: - if (!$old) { - return pht( - "%s set this blog's header image to %s.", - $this->renderHandleLink($author_phid), - $this->renderHandleLink($new)); - } else if (!$new) { - return pht( - "%s removed this blog's header image.", - $this->renderHandleLink($author_phid)); - } else { - return pht( - "%s updated this blog's header image from %s to %s.", - $this->renderHandleLink($author_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - } - break; - case self::TYPE_PROFILEIMAGE: - if (!$old) { - return pht( - "%s set this blog's profile image to %s.", - $this->renderHandleLink($author_phid), - $this->renderHandleLink($new)); - } else if (!$new) { - return pht( - "%s removed this blog's profile image.", - $this->renderHandleLink($author_phid)); - } else { - return pht( - "%s updated this blog's profile image from %s to %s.", - $this->renderHandleLink($author_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - } - break; - case self::TYPE_STATUS: - switch ($new) { - case PhameBlog::STATUS_ACTIVE: - return pht( - '%s published this blog.', - $this->renderHandleLink($author_phid)); - case PhameBlog::STATUS_ARCHIVED: - return pht( - '%s archived this blog.', - $this->renderHandleLink($author_phid)); - } - - } - - return parent::getTitle(); - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s updated the name for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_SUBTITLE: - if ($old === null) { - return pht( - '%s set the subtitle for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s updated the subtitle for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_DESCRIPTION: - return pht( - '%s updated the description for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_FULLDOMAIN: - return pht( - '%s updated the full domain for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_PARENTSITE: - return pht( - '%s updated the parent site for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_PARENTDOMAIN: - return pht( - '%s updated the parent domain for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_HEADERIMAGE: - return pht( - '%s updated the header image for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_PROFILEIMAGE: - return pht( - '%s updated the profile image for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_STATUS: - switch ($new) { - case PhameBlog::STATUS_ACTIVE: - return pht( - '%s published the blog %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case PhameBlog::STATUS_ARCHIVED: - return pht( - '%s archived the blog %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - - } - - return parent::getTitleForFeed(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - return ($this->getOldValue() !== null); - } - - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - return $this->renderTextCorpusChangeDetails( - $viewer, - $old, - $new); - } - - return parent::renderChangeDetails($viewer); - } - } diff --git a/src/applications/phame/storage/PhamePostTransaction.php b/src/applications/phame/storage/PhamePostTransaction.php index 6e54aeda6d..1c259911f3 100644 --- a/src/applications/phame/storage/PhamePostTransaction.php +++ b/src/applications/phame/storage/PhamePostTransaction.php @@ -1,14 +1,7 @@ getTransactionType()) { - case self::TYPE_BODY: - $blocks[] = $this->getNewValue(); - break; - } - - return $blocks; - } - - public function shouldHide() { - return parent::shouldHide(); - } - - public function getRequiredHandlePHIDs() { - $phids = parent::getRequiredHandlePHIDs(); - - switch ($this->getTransactionType()) { - case self::TYPE_BLOG: - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - if ($old) { - $phids[] = $old; - } - - if ($new) { - $phids[] = $new; - } - break; - } - - return $phids; - } - - - public function getIcon() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - switch ($this->getTransactionType()) { - case PhabricatorTransactions::TYPE_CREATE: - return 'fa-plus'; - break; - case self::TYPE_HEADERIMAGE: - return 'fa-camera-retro'; - break; - case self::TYPE_VISIBILITY: - if ($new == PhameConstants::VISIBILITY_PUBLISHED) { - return 'fa-globe'; - } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { - return 'fa-ban'; - } else { - return 'fa-eye-slash'; - } - break; - } - return parent::getIcon(); - } - public function getMailTags() { $tags = parent::getMailTags(); @@ -110,200 +46,4 @@ final class PhamePostTransaction return $tags; } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case PhabricatorTransactions::TYPE_CREATE: - return pht( - '%s authored this post.', - $this->renderHandleLink($author_phid)); - case self::TYPE_BLOG: - return pht( - '%s moved this post from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - case self::TYPE_TITLE: - if ($old === null) { - return pht( - '%s authored this post.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s updated the post\'s name to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_SUBTITLE: - if ($old === null) { - return pht( - '%s set the post\'s subtitle to "%s".', - $this->renderHandleLink($author_phid), - $new); - } else { - return pht( - '%s updated the post\'s subtitle to "%s".', - $this->renderHandleLink($author_phid), - $new); - } - break; - case self::TYPE_BODY: - return pht( - '%s updated the blog post.', - $this->renderHandleLink($author_phid)); - break; - case self::TYPE_HEADERIMAGE: - return pht( - '%s updated the header image.', - $this->renderHandleLink($author_phid)); - break; - case self::TYPE_VISIBILITY: - if ($new == PhameConstants::VISIBILITY_DRAFT) { - return pht( - '%s marked this post as a draft.', - $this->renderHandleLink($author_phid)); - } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { - return pht( - '%s archived this post.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s published this post.', - $this->renderHandleLink($author_phid)); - } - break; - } - - return parent::getTitle(); - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case PhabricatorTransactions::TYPE_CREATE: - return pht( - '%s authored %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case self::TYPE_BLOG: - return pht( - '%s moved post "%s" from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid), - $this->renderHandleLink($old), - $this->renderHandleLink($new)); - case self::TYPE_TITLE: - if ($old === null) { - return pht( - '%s authored %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s updated the name for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_SUBTITLE: - return pht( - '%s updated the subtitle for %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_BODY: - return pht( - '%s updated the blog post %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_HEADERIMAGE: - return pht( - '%s updated the header image for post %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - break; - case self::TYPE_VISIBILITY: - if ($new == PhameConstants::VISIBILITY_DRAFT) { - return pht( - '%s marked %s as a draft.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { - return pht( - '%s marked %s as archived.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s published %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - } - - return parent::getTitleForFeed(); - } - - public function getRemarkupBodyForFeed(PhabricatorFeedStory $story) { - $old = $this->getOldValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_BODY: - if ($old === null) { - return $this->getNewValue(); - } - break; - } - - return null; - } - - public function getColor() { - switch ($this->getTransactionType()) { - case PhabricatorTransactions::TYPE_CREATE: - return PhabricatorTransactions::COLOR_GREEN; - } - return parent::getColor(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_BODY: - return ($this->getOldValue() !== null); - } - - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - switch ($this->getTransactionType()) { - case self::TYPE_BODY: - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - return $this->renderTextCorpusChangeDetails( - $viewer, - $old, - $new); - } - - return parent::renderChangeDetails($viewer); - } - } diff --git a/src/applications/phame/xaction/PhameBlogDescriptionTransaction.php b/src/applications/phame/xaction/PhameBlogDescriptionTransaction.php new file mode 100644 index 0000000000..2bc12f3998 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogDescriptionTransaction.php @@ -0,0 +1,60 @@ +getDescription(); + } + + public function applyInternalEffects($object, $value) { + $object->setDescription($value); + } + + public function getTitle() { + return pht( + '%s updated the description.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the description for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO BLOG DESCRIPTION'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + public function getIcon() { + return 'fa-file-text-o'; + } + +} diff --git a/src/applications/phame/xaction/PhameBlogFullDomainTransaction.php b/src/applications/phame/xaction/PhameBlogFullDomainTransaction.php new file mode 100644 index 0000000000..5287f9cc06 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogFullDomainTransaction.php @@ -0,0 +1,95 @@ +getDomainFullURI(); + } + + public function applyInternalEffects($object, $value) { + if (strlen($value)) { + $uri = new PhutilURI($value); + $domain = $uri->getDomain(); + $object->setDomain($domain); + } else { + $object->setDomain(null); + } + $object->setDomainFullURI($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s set this blog\'s full domain to %s.', + $this->renderAuthor(), + $this->renderNewValue()); + } else { + return pht( + '%s updated the blog\'s full domain from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s set %s blog\'s full domain to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderNewValue()); + } else { + return pht( + '%s updated %s blog\'s full domain from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if (!$xactions) { + return $errors; + } + + $custom_domain = last($xactions)->getNewValue(); + if (empty($custom_domain)) { + return $errors; + } + + $error_text = $object->validateCustomDomain($custom_domain); + if ($error_text) { + $errors[] = $this->newInvalidError($error_text); + } + + if ($object->getViewPolicy() != PhabricatorPolicies::POLICY_PUBLIC) { + $errors[] = $this->newInvalidError( + pht('For custom domains to work, the blog must have a view policy of '. + 'public. This blog is currently set to "%s".', + $object->getViewPolicy())); + } + + $domain = new PhutilURI($custom_domain); + $domain = $domain->getDomain(); + $duplicate_blog = id(new PhameBlogQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withDomain($domain) + ->executeOne(); + if ($duplicate_blog && $duplicate_blog->getID() != $object->getID()) { + $errors[] = $this->newInvalidError( + pht('Domain must be unique; another blog already has this domain.')); + } + + return $errors; + } + +} diff --git a/src/applications/phame/xaction/PhameBlogHeaderImageTransaction.php b/src/applications/phame/xaction/PhameBlogHeaderImageTransaction.php new file mode 100644 index 0000000000..b328b9aca5 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogHeaderImageTransaction.php @@ -0,0 +1,34 @@ +getHeaderImagePHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setHeaderImagePHID($value); + } + + public function getTitle() { + return pht( + '%s changed the header image for this blog.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s changed the header image for blog %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-camera'; + } + +} diff --git a/src/applications/phame/xaction/PhameBlogNameTransaction.php b/src/applications/phame/xaction/PhameBlogNameTransaction.php new file mode 100644 index 0000000000..c219ba494b --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogNameTransaction.php @@ -0,0 +1,59 @@ +getName(); + } + + public function applyInternalEffects($object, $value) { + $object->setName($value); + } + + public function getTitle() { + return pht( + '%s renamed this blog from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s renamed %s blog from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Blogs must have a name.')); + } + + $max_length = $object->getColumnMaximumByteLength('name'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The name can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + + public function getIcon() { + return 'fa-rss'; + } + +} diff --git a/src/applications/phame/xaction/PhameBlogParentDomainTransaction.php b/src/applications/phame/xaction/PhameBlogParentDomainTransaction.php new file mode 100644 index 0000000000..227c8ce8c3 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogParentDomainTransaction.php @@ -0,0 +1,82 @@ +getParentDomain(); + } + + public function applyInternalEffects($object, $value) { + $object->setParentDomain($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s set this blog\'s parent domain to %s.', + $this->renderAuthor(), + $this->renderNewValue()); + } else { + return pht( + '%s updated the blog\'s parent domain from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s set %s blog\'s parent domain to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderNewValue()); + } else { + return pht( + '%s updated %s blog\'s parent domain from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if (!$xactions) { + return $errors; + } + + $parent_domain = last($xactions)->getNewValue(); + if (empty($parent_domain)) { + return $errors; + } + + try { + PhabricatorEnv::requireValidRemoteURIForLink($parent_domain); + } catch (Exception $ex) { + $errors[] = $this->newInvalidError( + pht('Parent Domain must be set to a valid Remote URI.')); + } + + $max_length = $object->getColumnMaximumByteLength('parentDomain'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The parent domain can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } +} diff --git a/src/applications/phame/xaction/PhameBlogParentSiteTransaction.php b/src/applications/phame/xaction/PhameBlogParentSiteTransaction.php new file mode 100644 index 0000000000..1b62b98488 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogParentSiteTransaction.php @@ -0,0 +1,66 @@ +getParentSite(); + } + + public function applyInternalEffects($object, $value) { + $object->setParentSite($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s set this blog\'s parent site to %s.', + $this->renderAuthor(), + $this->renderNewValue()); + } else { + return pht( + '%s updated the blog\'s parent site from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s set %s blog\'s parent site to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderNewValue()); + } else { + return pht( + '%s updated %s blog\'s parent site from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $max_length = $object->getColumnMaximumByteLength('parentSite'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The parent site can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } +} diff --git a/src/applications/phame/xaction/PhameBlogProfileImageTransaction.php b/src/applications/phame/xaction/PhameBlogProfileImageTransaction.php new file mode 100644 index 0000000000..77acf680fd --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogProfileImageTransaction.php @@ -0,0 +1,34 @@ +getProfileImagePHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setProfileImagePHID($value); + } + + public function getTitle() { + return pht( + '%s changed the profile image for this blog.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s changed the profile image for blog %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-file-image-o'; + } + +} diff --git a/src/applications/phame/xaction/PhameBlogStatusTransaction.php b/src/applications/phame/xaction/PhameBlogStatusTransaction.php new file mode 100644 index 0000000000..b3366bece7 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogStatusTransaction.php @@ -0,0 +1,55 @@ +getStatus(); + } + + public function applyInternalEffects($object, $value) { + $object->setStatus($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + switch ($new) { + case PhameBlog::STATUS_ACTIVE: + return pht( + '%s published this blog.', + $this->renderAuthor()); + case PhameBlog::STATUS_ARCHIVED: + return pht( + '%s archived this blog.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + switch ($new) { + case PhameBlog::STATUS_ACTIVE: + return pht( + '%s published the blog %s.', + $this->renderAuthor(), + $this->renderObject()); + case PhameBlog::STATUS_ARCHIVED: + return pht( + '%s archived the blog %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + if ($new == PhameBlog::STATUS_ARCHIVED) { + return 'fa-ban'; + } else { + return 'fa-check'; + } + } + +} diff --git a/src/applications/phame/xaction/PhameBlogSubtitleTransaction.php b/src/applications/phame/xaction/PhameBlogSubtitleTransaction.php new file mode 100644 index 0000000000..87788a31f7 --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogSubtitleTransaction.php @@ -0,0 +1,63 @@ +getSubtitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setSubtitle($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if ($old === null) { + return pht( + '%s set this blog\'s subtitle to "%s".', + $this->renderAuthor(), + $this->renderNewValue()); + } else { + return pht( + '%s updated the blog\'s subtitle to "%s".', + $this->renderAuthor(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if ($old === null) { + return pht( + '%s set the subtitle for %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s updated the subtitle for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $max_length = $object->getColumnMaximumByteLength('subtitle'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The subtitle can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/phame/xaction/PhameBlogTransactionType.php b/src/applications/phame/xaction/PhameBlogTransactionType.php new file mode 100644 index 0000000000..cf83633b9f --- /dev/null +++ b/src/applications/phame/xaction/PhameBlogTransactionType.php @@ -0,0 +1,4 @@ +getBlogPHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setBlogPHID($value); + } + + public function getTitle() { + return pht( + '%s changed the blog for this post.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s changed the blog for post %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getBlogPHID(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Posts must be attached to a blog.')); + } + + foreach ($xactions as $xaction) { + $new_phid = $xaction->getNewValue(); + + $blog = id(new PhameBlogQuery()) + ->setViewer($this->getActor()) + ->withPHIDs(array($new_phid)) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->execute(); + + if ($blog) { + continue; + } + + $errors[] = $this->newInvalidError( + pht('The specified blog PHID ("%s") is not valid. You can only '. + 'create a post on (or move a post into) a blog which you '. + 'have permission to see and edit.', + $new_phid)); + } + + return $errors; + } + +} diff --git a/src/applications/phame/xaction/PhamePostBodyTransaction.php b/src/applications/phame/xaction/PhamePostBodyTransaction.php new file mode 100644 index 0000000000..bf34cf73ff --- /dev/null +++ b/src/applications/phame/xaction/PhamePostBodyTransaction.php @@ -0,0 +1,60 @@ +getBody(); + } + + public function applyInternalEffects($object, $value) { + $object->setBody($value); + } + + public function getTitle() { + return pht( + '%s updated the post content.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the post content for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO POST CONTENT'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + public function getIcon() { + return 'fa-file-text-o'; + } + +} diff --git a/src/applications/phame/xaction/PhamePostHeaderImageTransaction.php b/src/applications/phame/xaction/PhamePostHeaderImageTransaction.php new file mode 100644 index 0000000000..2b9631cdc4 --- /dev/null +++ b/src/applications/phame/xaction/PhamePostHeaderImageTransaction.php @@ -0,0 +1,33 @@ +getHeaderImagePHID(); + } + + public function applyInternalEffects($object, $value) { + $object->setHeaderImagePHID($value); + } + + public function getTitle() { + return pht( + '%s changed the header image for this post.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s changed the header image for post %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-camera'; + } + +} diff --git a/src/applications/phame/xaction/PhamePostSubtitleTransaction.php b/src/applications/phame/xaction/PhamePostSubtitleTransaction.php new file mode 100644 index 0000000000..05b0f34790 --- /dev/null +++ b/src/applications/phame/xaction/PhamePostSubtitleTransaction.php @@ -0,0 +1,63 @@ +getSubtitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setSubtitle($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if ($old === null) { + return pht( + '%s set this post\'s subtitle to "%s".', + $this->renderAuthor(), + $this->renderNewValue()); + } else { + return pht( + '%s updated the post\'s subtitle to "%s".', + $this->renderAuthor(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + if ($old === null) { + return pht( + '%s set the subtitle for %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s updated the subtitle for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + $max_length = $object->getColumnMaximumByteLength('subtitle'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The subtitle can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/phame/xaction/PhamePostTitleTransaction.php b/src/applications/phame/xaction/PhamePostTitleTransaction.php new file mode 100644 index 0000000000..99c556cc3a --- /dev/null +++ b/src/applications/phame/xaction/PhamePostTitleTransaction.php @@ -0,0 +1,55 @@ +getTitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setTitle($value); + } + + public function getTitle() { + return pht( + '%s renamed this blog post from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s renamed %s blog post from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Posts must have a title.')); + } + + $max_length = $object->getColumnMaximumByteLength('title'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The title can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/phame/xaction/PhamePostTransactionType.php b/src/applications/phame/xaction/PhamePostTransactionType.php new file mode 100644 index 0000000000..b8ce182bc7 --- /dev/null +++ b/src/applications/phame/xaction/PhamePostTransactionType.php @@ -0,0 +1,4 @@ +getVisibility(); + } + + public function applyInternalEffects($object, $value) { + if ($value == PhameConstants::VISIBILITY_DRAFT) { + $object->setDatePublished(0); + } else if ($value == PhameConstants::VISIBILITY_ARCHIVED) { + $object->setDatePublished(0); + } else { + $object->setDatePublished(PhabricatorTime::getNow()); + } + $object->setVisibility($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + if ($new == PhameConstants::VISIBILITY_DRAFT) { + return pht( + '%s marked this post as a draft.', + $this->renderAuthor()); + } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { + return pht( + '%s archived this post.', + $this->renderAuthor()); + } else { + return pht( + '%s published this post.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + if ($new == PhameConstants::VISIBILITY_DRAFT) { + return pht( + '%s marked %s as a draft.', + $this->renderAuthor(), + $this->renderObject()); + } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { + return pht( + '%s marked %s as archived.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s published %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + if ($new == PhameConstants::VISIBILITY_PUBLISHED) { + return 'fa-rss'; + } else if ($new == PhameConstants::VISIBILITY_ARCHIVED) { + return 'fa-ban'; + } else { + return 'fa-eye-slash'; + } + } +} diff --git a/src/applications/policy/storage/PhabricatorPolicy.php b/src/applications/policy/storage/PhabricatorPolicy.php index 68462cbc19..4141ef9c36 100644 --- a/src/applications/policy/storage/PhabricatorPolicy.php +++ b/src/applications/policy/storage/PhabricatorPolicy.php @@ -264,9 +264,11 @@ final class PhabricatorPolicy public function getFullName() { switch ($this->getType()) { case PhabricatorPolicyType::TYPE_PROJECT: - return pht('Project: %s', $this->getName()); + return pht('Members of Project: %s', $this->getName()); case PhabricatorPolicyType::TYPE_MASKED: return pht('Other: %s', $this->getName()); + case PhabricatorPolicyType::TYPE_USER: + return pht('Only User: %s', $this->getName()); default: return $this->getName(); } @@ -422,6 +424,10 @@ final class PhabricatorPolicy return ($this_strength > $other_strength); } + public function isValidPolicyForEdit() { + return $this->getType() !== PhabricatorPolicyType::TYPE_MASKED; + } + public static function getSpecialRules( PhabricatorPolicyInterface $object, PhabricatorUser $viewer, diff --git a/src/applications/ponder/application/PhabricatorPonderApplication.php b/src/applications/ponder/application/PhabricatorPonderApplication.php index ced8606e99..ed37c7ef6e 100644 --- a/src/applications/ponder/application/PhabricatorPonderApplication.php +++ b/src/applications/ponder/application/PhabricatorPonderApplication.php @@ -60,22 +60,26 @@ final class PhabricatorPonderApplication extends PhabricatorApplication { '/ponder/' => array( '(?:query/(?P[^/]+)/)?' => 'PonderQuestionListController', - 'answer/add/' - => 'PonderAnswerSaveController', - 'answer/edit/(?P\d+)/' - => 'PonderAnswerEditController', - 'answer/comment/(?P\d+)/' - => 'PonderAnswerCommentController', - 'answer/history/(?P\d+)/' - => 'PonderAnswerHistoryController', - 'question/edit/(?:(?P\d+)/)?' - => 'PonderQuestionEditController', - 'question/create/' - => 'PonderQuestionEditController', - 'question/comment/(?P\d+)/' - => 'PonderQuestionCommentController', - 'question/history/(?P\d+)/' - => 'PonderQuestionHistoryController', + 'answer/' => array( + 'add/' + => 'PonderAnswerSaveController', + 'edit/(?P\d+)/' + => 'PonderAnswerEditController', + 'comment/(?P\d+)/' + => 'PonderAnswerCommentController', + 'history/(?P\d+)/' + => 'PonderAnswerHistoryController', + ), + 'question/' => array( + $this->getEditRoutePattern('edit/') + => 'PonderQuestionEditController', + 'create/' + => 'PonderQuestionEditController', + 'comment/(?P\d+)/' + => 'PonderQuestionCommentController', + 'history/(?P\d+)/' + => 'PonderQuestionHistoryController', + ), 'preview/' => 'PhabricatorMarkupPreviewController', 'question/status/(?P[1-9]\d*)/' diff --git a/src/applications/ponder/controller/PonderAnswerEditController.php b/src/applications/ponder/controller/PonderAnswerEditController.php index 3362e15834..9c48c7c669 100644 --- a/src/applications/ponder/controller/PonderAnswerEditController.php +++ b/src/applications/ponder/controller/PonderAnswerEditController.php @@ -42,11 +42,11 @@ final class PonderAnswerEditController extends PonderController { if (!$errors) { $xactions = array(); $xactions[] = id(new PonderAnswerTransaction()) - ->setTransactionType(PonderAnswerTransaction::TYPE_CONTENT) + ->setTransactionType(PonderAnswerContentTransaction::TRANSACTIONTYPE) ->setNewValue($v_content); $xactions[] = id(new PonderAnswerTransaction()) - ->setTransactionType(PonderAnswerTransaction::TYPE_STATUS) + ->setTransactionType(PonderAnswerStatusTransaction::TRANSACTIONTYPE) ->setNewValue($v_status); $editor = id(new PonderAnswerEditor()) diff --git a/src/applications/ponder/controller/PonderAnswerSaveController.php b/src/applications/ponder/controller/PonderAnswerSaveController.php index cac17acbed..53e0f06ea6 100644 --- a/src/applications/ponder/controller/PonderAnswerSaveController.php +++ b/src/applications/ponder/controller/PonderAnswerSaveController.php @@ -38,7 +38,7 @@ final class PonderAnswerSaveController extends PonderController { $xactions = array(); $xactions[] = id(new PonderQuestionTransaction()) - ->setTransactionType(PonderQuestionTransaction::TYPE_ANSWERS) + ->setTransactionType(PonderQuestionAnswerTransaction::TRANSACTIONTYPE) ->setNewValue( array( '+' => array( @@ -58,11 +58,11 @@ final class PonderAnswerSaveController extends PonderController { $xactions = array(); $xactions[] = id(clone $template) - ->setTransactionType(PonderAnswerTransaction::TYPE_QUESTION_ID) + ->setTransactionType(PonderAnswerQuestionIDTransaction::TRANSACTIONTYPE) ->setNewValue($question->getID()); $xactions[] = id(clone $template) - ->setTransactionType(PonderAnswerTransaction::TYPE_CONTENT) + ->setTransactionType(PonderAnswerContentTransaction::TRANSACTIONTYPE) ->setNewValue($content); $editor = id(new PonderAnswerEditor()) diff --git a/src/applications/ponder/controller/PonderController.php b/src/applications/ponder/controller/PonderController.php index a14d70c773..99edcc1af1 100644 --- a/src/applications/ponder/controller/PonderController.php +++ b/src/applications/ponder/controller/PonderController.php @@ -27,13 +27,9 @@ abstract class PonderController extends PhabricatorController { protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); - $href = $this->getApplicationURI('question/create/'); - $crumbs - ->addAction( - id(new PHUIListItemView()) - ->setName(pht('Ask Question')) - ->setHref($href) - ->setIcon('fa-plus-square')); + id(new PonderQuestionEditEngine()) + ->setViewer($this->getViewer()) + ->addActionToCrumbs($crumbs); return $crumbs; } diff --git a/src/applications/ponder/controller/PonderQuestionEditController.php b/src/applications/ponder/controller/PonderQuestionEditController.php index 49ca5fe846..c881d60f92 100644 --- a/src/applications/ponder/controller/PonderQuestionEditController.php +++ b/src/applications/ponder/controller/PonderQuestionEditController.php @@ -1,219 +1,11 @@ getViewer(); - $id = $request->getURIData('id'); - - if ($id) { - $question = id(new PonderQuestionQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$question) { - return new Aphront404Response(); - } - $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $question->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $v_projects = array_reverse($v_projects); - $is_new = false; - } else { - $is_new = true; - $question = PonderQuestion::initializeNewQuestion($viewer); - $v_projects = array(); - } - - $v_title = $question->getTitle(); - $v_content = $question->getContent(); - $v_wiki = $question->getAnswerWiki(); - $v_view = $question->getViewPolicy(); - $v_space = $question->getSpacePHID(); - $v_status = $question->getStatus(); - - - $errors = array(); - $e_title = true; - if ($request->isFormPost()) { - $v_title = $request->getStr('title'); - $v_content = $request->getStr('content'); - $v_wiki = $request->getStr('answerWiki'); - $v_projects = $request->getArr('projects'); - $v_view = $request->getStr('viewPolicy'); - $v_space = $request->getStr('spacePHID'); - $v_status = $request->getStr('status'); - - $len = phutil_utf8_strlen($v_title); - if ($len < 1) { - $errors[] = pht('Title must not be empty.'); - $e_title = pht('Required'); - } else if ($len > 255) { - $errors[] = pht('Title is too long.'); - $e_title = pht('Too Long'); - } - - if (!$errors) { - $template = id(new PonderQuestionTransaction()); - $xactions = array(); - - $xactions[] = id(clone $template) - ->setTransactionType(PonderQuestionTransaction::TYPE_TITLE) - ->setNewValue($v_title); - - $xactions[] = id(clone $template) - ->setTransactionType(PonderQuestionTransaction::TYPE_CONTENT) - ->setNewValue($v_content); - - $xactions[] = id(clone $template) - ->setTransactionType(PonderQuestionTransaction::TYPE_ANSWERWIKI) - ->setNewValue($v_wiki); - - if (!$is_new) { - $xactions[] = id(clone $template) - ->setTransactionType(PonderQuestionTransaction::TYPE_STATUS) - ->setNewValue($v_status); - } - - $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) - ->setNewValue($v_view); - - $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) - ->setNewValue($v_space); - - $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $xactions[] = id(new PonderQuestionTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $proj_edge_type) - ->setNewValue(array('=' => array_fuse($v_projects))); - - $editor = id(new PonderQuestionEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - $editor->applyTransactions($question, $xactions); - - return id(new AphrontRedirectResponse()) - ->setURI('/Q'.$question->getID()); - } - } - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($question) - ->execute(); - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Question')) - ->setName('title') - ->setValue($v_title) - ->setError($e_title)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($viewer) - ->setName('content') - ->setID('content') - ->setValue($v_content) - ->setLabel(pht('Question Details')) - ->setUser($viewer)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($viewer) - ->setName('answerWiki') - ->setID('answerWiki') - ->setValue($v_wiki) - ->setLabel(pht('Answer Summary')) - ->setUser($viewer)) - ->appendControl( - id(new AphrontFormPolicyControl()) - ->setName('viewPolicy') - ->setPolicyObject($question) - ->setSpacePHID($v_space) - ->setPolicies($policies) - ->setValue($v_view) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)); - - - if (!$is_new) { - $form->appendChild( - id(new AphrontFormSelectControl()) - ->setLabel(pht('Status')) - ->setName('status') - ->setValue($v_status) - ->setOptions(PonderQuestionStatus::getQuestionStatusMap())); - } - - $form->appendControl( - id(new AphrontFormTokenizerControl()) - ->setLabel(pht('Tags')) - ->setName('projects') - ->setValue($v_projects) - ->setDatasource(new PhabricatorProjectDatasource())); - - $form->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($this->getApplicationURI()) - ->setValue(pht('Submit'))); - - $preview = id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Question Preview')) - ->setControlID('content') - ->setPreviewURI($this->getApplicationURI('preview/')); - - $answer_preview = id(new PHUIRemarkupPreviewPanel()) - ->setHeader(pht('Answer Summary Preview')) - ->setControlID('answerWiki') - ->setPreviewURI($this->getApplicationURI('preview/')); - - $crumbs = $this->buildApplicationCrumbs(); - - $id = $question->getID(); - if ($id) { - $crumbs->addTextCrumb("Q{$id}", "/Q{$id}"); - $crumbs->addTextCrumb(pht('Edit')); - $title = pht('Edit Question'); - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon('fa-pencil'); - } else { - $crumbs->addTextCrumb(pht('Ask Question')); - $title = pht('Ask New Question'); - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon('fa-plus-square'); - } - $crumbs->setBorder(true); - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Question')) - ->setFormErrors($errors) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setForm($form); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter(array( - $box, - $preview, - $answer_preview, - )); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); - + return id(new PonderQuestionEditEngine()) + ->setController($this) + ->buildResponse(); } } diff --git a/src/applications/ponder/controller/PonderQuestionStatusController.php b/src/applications/ponder/controller/PonderQuestionStatusController.php index a4671d5915..ab791b740f 100644 --- a/src/applications/ponder/controller/PonderQuestionStatusController.php +++ b/src/applications/ponder/controller/PonderQuestionStatusController.php @@ -28,7 +28,7 @@ final class PonderQuestionStatusController $xactions = array(); $xactions[] = id(new PonderQuestionTransaction()) - ->setTransactionType(PonderQuestionTransaction::TYPE_STATUS) + ->setTransactionType(PonderQuestionStatusTransaction::TRANSACTIONTYPE) ->setNewValue($v_status); $editor = id(new PonderQuestionEditor()) diff --git a/src/applications/ponder/editor/PonderAnswerEditor.php b/src/applications/ponder/editor/PonderAnswerEditor.php index 10a90a1945..8d66fffc17 100644 --- a/src/applications/ponder/editor/PonderAnswerEditor.php +++ b/src/applications/ponder/editor/PonderAnswerEditor.php @@ -6,80 +6,21 @@ final class PonderAnswerEditor extends PonderEditor { return pht('Ponder Answers'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s added this answer.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s added %s.', $author, $object); + } + public function getTransactionTypes() { $types = parent::getTransactionTypes(); - $types[] = PhabricatorTransactions::TYPE_COMMENT; - $types[] = PhabricatorTransactions::TYPE_EDGE; - - $types[] = PonderAnswerTransaction::TYPE_CONTENT; - $types[] = PonderAnswerTransaction::TYPE_STATUS; - $types[] = PonderAnswerTransaction::TYPE_QUESTION_ID; return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PonderAnswerTransaction::TYPE_CONTENT: - case PonderAnswerTransaction::TYPE_STATUS: - return $object->getContent(); - case PonderAnswerTransaction::TYPE_QUESTION_ID: - return $object->getQuestionID(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PonderAnswerTransaction::TYPE_CONTENT: - case PonderAnswerTransaction::TYPE_STATUS: - case PonderAnswerTransaction::TYPE_QUESTION_ID: - return $xaction->getNewValue(); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PonderAnswerTransaction::TYPE_CONTENT: - $object->setContent($xaction->getNewValue()); - break; - case PonderAnswerTransaction::TYPE_STATUS: - $object->setStatus($xaction->getNewValue()); - break; - case PonderAnswerTransaction::TYPE_QUESTION_ID: - $object->setQuestionID($xaction->getNewValue()); - break; - } - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - return; - } - - protected function mergeTransactions( - PhabricatorApplicationTransaction $u, - PhabricatorApplicationTransaction $v) { - - $type = $u->getTransactionType(); - switch ($type) { - case PonderAnswerTransaction::TYPE_CONTENT: - return $v; - } - - return parent::mergeTransactions($u, $v); - } - protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { diff --git a/src/applications/ponder/editor/PonderQuestionEditEngine.php b/src/applications/ponder/editor/PonderQuestionEditEngine.php new file mode 100644 index 0000000000..640f657ad1 --- /dev/null +++ b/src/applications/ponder/editor/PonderQuestionEditEngine.php @@ -0,0 +1,109 @@ +getViewer()); + } + + protected function newObjectQuery() { + return new PonderQuestionQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Question'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit Question: %s', $object->getTitle()); + } + + protected function getObjectEditShortText($object) { + return $object->getTitle(); + } + + protected function getObjectCreateShortText() { + return pht('New Question'); + } + + protected function getObjectName() { + return pht('Question'); + } + + protected function getObjectCreateCancelURI($object) { + return $this->getApplication()->getApplicationURI('/'); + } + + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('question/edit/'); + } + + protected function getObjectViewURI($object) { + return $object->getViewURI(); + } + + protected function buildCustomEditFields($object) { + + return array( + id(new PhabricatorTextEditField()) + ->setKey('title') + ->setLabel(pht('Question')) + ->setDescription(pht('Question title.')) + ->setConduitTypeDescription(pht('New question title.')) + ->setTransactionType( + PonderQuestionTitleTransaction::TRANSACTIONTYPE) + ->setValue($object->getTitle()) + ->setIsRequired(true), + id(new PhabricatorRemarkupEditField()) + ->setKey('content') + ->setLabel(pht('Details')) + ->setDescription(pht('Long details of the question.')) + ->setConduitTypeDescription(pht('New question details.')) + ->setValue($object->getContent()) + ->setTransactionType( + PonderQuestionContentTransaction::TRANSACTIONTYPE), + id(new PhabricatorRemarkupEditField()) + ->setKey('answerWiki') + ->setLabel(pht('Answer Summary')) + ->setDescription(pht('Answer summary of the question.')) + ->setConduitTypeDescription(pht('New question answer summary.')) + ->setValue($object->getAnswerWiki()) + ->setTransactionType( + PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE), + id(new PhabricatorSelectEditField()) + ->setKey('status') + ->setLabel(pht('Status')) + ->setDescription(pht('Status of the question.')) + ->setConduitTypeDescription(pht('New question status.')) + ->setValue($object->getStatus()) + ->setTransactionType( + PonderQuestionStatusTransaction::TRANSACTIONTYPE) + ->setOptions(PonderQuestionStatus::getQuestionStatusMap()), + + ); + } + +} diff --git a/src/applications/ponder/editor/PonderQuestionEditor.php b/src/applications/ponder/editor/PonderQuestionEditor.php index 73d9ed0ce0..a17aebecf8 100644 --- a/src/applications/ponder/editor/PonderQuestionEditor.php +++ b/src/applications/ponder/editor/PonderQuestionEditor.php @@ -9,6 +9,14 @@ final class PonderQuestionEditor return pht('Ponder Questions'); } + public function getCreateObjectTitle($author, $object) { + return pht('%s created this question.', $author); + } + + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created %s.', $author, $object); + } + /** * This is used internally on @{method:applyInitialEffects} if a transaction * of type PonderQuestionTransaction::TYPE_ANSWERS is in the mix. The value @@ -32,7 +40,7 @@ final class PonderQuestionEditor foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_ANSWERS: + case PonderQuestionAnswerTransaction::TRANSACTIONTYPE: return true; } } @@ -46,7 +54,7 @@ final class PonderQuestionEditor foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_ANSWERS: + case PonderQuestionAnswerTransaction::TRANSACTIONTYPE: $new_value = $xaction->getNewValue(); $new = idx($new_value, '+', array()); foreach ($new as $new_answer) { @@ -64,123 +72,12 @@ final class PonderQuestionEditor public function getTransactionTypes() { $types = parent::getTransactionTypes(); - $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; - $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; - $types[] = PhabricatorTransactions::TYPE_SPACE; - - $types[] = PonderQuestionTransaction::TYPE_TITLE; - $types[] = PonderQuestionTransaction::TYPE_CONTENT; - $types[] = PonderQuestionTransaction::TYPE_ANSWERS; - $types[] = PonderQuestionTransaction::TYPE_STATUS; - $types[] = PonderQuestionTransaction::TYPE_ANSWERWIKI; return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_TITLE: - return $object->getTitle(); - case PonderQuestionTransaction::TYPE_CONTENT: - return $object->getContent(); - case PonderQuestionTransaction::TYPE_ANSWERS: - return mpull($object->getAnswers(), 'getPHID'); - case PonderQuestionTransaction::TYPE_STATUS: - return $object->getStatus(); - case PonderQuestionTransaction::TYPE_ANSWERWIKI: - return $object->getAnswerWiki(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_TITLE: - case PonderQuestionTransaction::TYPE_CONTENT: - case PonderQuestionTransaction::TYPE_STATUS: - case PonderQuestionTransaction::TYPE_ANSWERWIKI: - return $xaction->getNewValue(); - case PonderQuestionTransaction::TYPE_ANSWERS: - $raw_new_value = $xaction->getNewValue(); - $new_value = array(); - foreach ($raw_new_value as $key => $answers) { - $phids = array(); - foreach ($answers as $answer) { - $obj = idx($answer, 'answer'); - if (!$answer) { - continue; - } - $phids[] = $obj->getPHID(); - } - $new_value[$key] = $phids; - } - $xaction->setNewValue($new_value); - return $this->getPHIDTransactionNewValue($xaction); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_TITLE: - $object->setTitle($xaction->getNewValue()); - break; - case PonderQuestionTransaction::TYPE_CONTENT: - $object->setContent($xaction->getNewValue()); - break; - case PonderQuestionTransaction::TYPE_STATUS: - $object->setStatus($xaction->getNewValue()); - break; - case PonderQuestionTransaction::TYPE_ANSWERWIKI: - $object->setAnswerWiki($xaction->getNewValue()); - break; - case PonderQuestionTransaction::TYPE_ANSWERS: - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - $add = array_diff_key($new, $old); - $rem = array_diff_key($old, $new); - - $count = $object->getAnswerCount(); - $count += count($add); - $count -= count($rem); - - $object->setAnswerCount($count); - break; - } - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - return; - } - - protected function mergeTransactions( - PhabricatorApplicationTransaction $u, - PhabricatorApplicationTransaction $v) { - - $type = $u->getTransactionType(); - switch ($type) { - case PonderQuestionTransaction::TYPE_TITLE: - case PonderQuestionTransaction::TYPE_CONTENT: - case PonderQuestionTransaction::TYPE_STATUS: - case PonderQuestionTransaction::TYPE_ANSWERWIKI: - return $v; - } - - return parent::mergeTransactions($u, $v); - } - protected function supportsSearch() { return true; } @@ -190,7 +87,7 @@ final class PonderQuestionEditor PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_ANSWERS: + case PonderQuestionAnswerTransaction::TRANSACTIONTYPE: return false; } @@ -202,7 +99,7 @@ final class PonderQuestionEditor array $xactions) { foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_ANSWERS: + case PonderQuestionAnswerTransaction::TRANSACTIONTYPE: return false; } } @@ -221,7 +118,7 @@ final class PonderQuestionEditor array $xactions) { foreach ($xactions as $xaction) { switch ($xaction->getTransactionType()) { - case PonderQuestionTransaction::TYPE_ANSWERS: + case PonderQuestionAnswerTransaction::TRANSACTIONTYPE: return false; } } @@ -269,7 +166,7 @@ final class PonderQuestionEditor $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); // If the user just asked the question, add the question text. - if ($type == PonderQuestionTransaction::TYPE_CONTENT) { + if ($type == PonderQuestionContentTransaction::TRANSACTIONTYPE) { if ($old === null) { $body->addRawSection($new); } diff --git a/src/applications/ponder/storage/PonderAnswerTransaction.php b/src/applications/ponder/storage/PonderAnswerTransaction.php index 924817b34e..784b8a36e7 100644 --- a/src/applications/ponder/storage/PonderAnswerTransaction.php +++ b/src/applications/ponder/storage/PonderAnswerTransaction.php @@ -1,11 +1,7 @@ getTransactionType()) { - case self::TYPE_CONTENT: - case self::TYPE_STATUS: - $phids[] = $this->getObjectPHID(); - break; - } - - return $phids; - } - - public function getRemarkupBlocks() { - $blocks = parent::getRemarkupBlocks(); - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - $blocks[] = $this->getNewValue(); - break; - } - return $blocks; - } - - public function shouldHide() { - switch ($this->getTransactionType()) { - case self::TYPE_QUESTION_ID: - return true; - } - return parent::shouldHide(); - } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - if ($old === '') { - return pht( - '%s added %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s edited %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_STATUS: - if ($new == PonderAnswerStatus::ANSWER_STATUS_VISIBLE) { - return pht( - '%s marked %s as visible.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else if ($new == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) { - return pht( - '%s marked %s as hidden.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - } - - return parent::getTitle(); - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - if ($old === '') { - return pht( - '%s added %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s updated %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_STATUS: - if ($new == PonderAnswerStatus::ANSWER_STATUS_VISIBLE) { - return pht( - '%s marked %s as visible.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else if ($new == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) { - return pht( - '%s marked %s as hidden.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - } - - return parent::getTitleForFeed(); - } - - public function getRemarkupBodyForFeed(PhabricatorFeedStory $story) { - $text = null; - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - $text = $this->getNewValue(); - break; - } - return $text; - } - - - public function hasChangeDetails() { - $old = $this->getOldValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - return $old !== null; - } - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - $this->getOldValue(), - $this->getNewValue()); + public function getBaseTransactionClass() { + return 'PonderAnswerTransactionType'; } } diff --git a/src/applications/ponder/storage/PonderQuestion.php b/src/applications/ponder/storage/PonderQuestion.php index 6594219f5a..c505deeed9 100644 --- a/src/applications/ponder/storage/PonderQuestion.php +++ b/src/applications/ponder/storage/PonderQuestion.php @@ -105,6 +105,14 @@ final class PonderQuestion extends PonderDAO return $this->comments; } + public function getMonogram() { + return 'Q'.$this->getID(); + } + + public function getViewURI() { + return '/'.$this->getMonogram(); + } + public function attachAnswers(array $answers) { assert_instances_of($answers, 'PonderAnswer'); $this->answers = $answers; diff --git a/src/applications/ponder/storage/PonderQuestionTransaction.php b/src/applications/ponder/storage/PonderQuestionTransaction.php index 7abfd247f5..73a0899ca8 100644 --- a/src/applications/ponder/storage/PonderQuestionTransaction.php +++ b/src/applications/ponder/storage/PonderQuestionTransaction.php @@ -1,13 +1,7 @@ getTransactionType()) { - case self::TYPE_ANSWERS: - $phids[] = $this->getNewAnswerPHID(); - $phids[] = $this->getObjectPHID(); - break; - } - - return $phids; - } - - public function getRemarkupBlocks() { - $blocks = parent::getRemarkupBlocks(); - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - $blocks[] = $this->getNewValue(); - break; - } - return $blocks; - } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - if ($old === null) { - return pht( - '%s asked this question.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s edited the question title from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } - case self::TYPE_CONTENT: - return pht( - '%s edited the question description.', - $this->renderHandleLink($author_phid)); - case self::TYPE_ANSWERWIKI: - return pht( - '%s edited the question answer wiki.', - $this->renderHandleLink($author_phid)); - case self::TYPE_ANSWERS: - $answer_handle = $this->getHandle($this->getNewAnswerPHID()); - $question_handle = $this->getHandle($object_phid); - - return pht( - '%s answered %s', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case self::TYPE_STATUS: - switch ($new) { - case PonderQuestionStatus::STATUS_OPEN: - return pht( - '%s reopened this question.', - $this->renderHandleLink($author_phid)); - case PonderQuestionStatus::STATUS_CLOSED_RESOLVED: - return pht( - '%s closed this question as resolved.', - $this->renderHandleLink($author_phid)); - case PonderQuestionStatus::STATUS_CLOSED_OBSOLETE: - return pht( - '%s closed this question as obsolete.', - $this->renderHandleLink($author_phid)); - case PonderQuestionStatus::STATUS_CLOSED_INVALID: - return pht( - '%s closed this question as invalid.', - $this->renderHandleLink($author_phid)); - } - } - - return parent::getTitle(); + public function getBaseTransactionClass() { + return 'PonderQuestionTransactionType'; } public function getMailTags() { @@ -120,13 +35,13 @@ final class PonderQuestionTransaction case PhabricatorTransactions::TYPE_COMMENT: $tags[] = self::MAILTAG_COMMENT; break; - case self::TYPE_TITLE: - case self::TYPE_CONTENT: - case self::TYPE_STATUS: - case self::TYPE_ANSWERWIKI: + case PonderQuestionTitleTransaction::TRANSACTIONTYPE: + case PonderQuestionContentTransaction::TRANSACTIONTYPE: + case PonderQuestionStatusTransaction::TRANSACTIONTYPE: + case PonderQuestionAnswerWikiTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_DETAILS; break; - case self::TYPE_ANSWERS: + case PonderQuestionAnswerTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_ANSWERS; break; default: @@ -136,182 +51,4 @@ final class PonderQuestionTransaction return $tags; } - public function getIcon() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - case self::TYPE_CONTENT: - case self::TYPE_ANSWERWIKI: - return 'fa-pencil'; - case self::TYPE_STATUS: - return PonderQuestionStatus::getQuestionStatusIcon($new); - case self::TYPE_ANSWERS: - return 'fa-plus'; - } - - return parent::getIcon(); - } - - public function getColor() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - case self::TYPE_CONTENT: - case self::TYPE_ANSWERWIKI: - return PhabricatorTransactions::COLOR_BLUE; - case self::TYPE_ANSWERS: - return PhabricatorTransactions::COLOR_GREEN; - case self::TYPE_STATUS: - return PonderQuestionStatus::getQuestionStatusTagColor($new); - } - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - case self::TYPE_ANSWERWIKI: - return true; - } - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - $this->getOldValue(), - $this->getNewValue()); - } - - public function getActionStrength() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - if ($old === null) { - return 3; - } - break; - case self::TYPE_ANSWERS: - return 2; - } - - return parent::getActionStrength(); - } - - public function getActionName() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - if ($old === null) { - return pht('Asked'); - } - break; - case self::TYPE_ANSWERS: - return pht('Answered'); - } - - return parent::getActionName(); - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_TITLE: - if ($old === null) { - return pht( - '%s asked a question: %s', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } else { - return pht( - '%s edited the title of %s (was "%s")', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid), - $old); - } - case self::TYPE_CONTENT: - return pht( - '%s edited the description of %s', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case self::TYPE_ANSWERWIKI: - return pht( - '%s edited the answer wiki for %s', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case self::TYPE_ANSWERS: - $answer_handle = $this->getHandle($this->getNewAnswerPHID()); - $question_handle = $this->getHandle($object_phid); - return pht( - '%s answered %s', - $this->renderHandleLink($author_phid), - $answer_handle->renderLink($question_handle->getFullName())); - case self::TYPE_STATUS: - switch ($new) { - case PonderQuestionStatus::STATUS_OPEN: - return pht( - '%s reopened %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case PonderQuestionStatus::STATUS_CLOSED_RESOLVED: - return pht( - '%s closed %s as resolved.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case PonderQuestionStatus::STATUS_CLOSED_INVALID: - return pht( - '%s closed %s as invalid.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - case PonderQuestionStatus::STATUS_CLOSED_OBSOLETE: - return pht( - '%s closed %s as obsolete.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - } - - return parent::getTitleForFeed(); - } - - public function getRemarkupBodyForFeed(PhabricatorFeedStory $story) { - $text = null; - switch ($this->getTransactionType()) { - case self::TYPE_CONTENT: - $text = $this->getNewValue(); - break; - } - return $text; - } - - /** - * Currently the application only supports adding answers one at a time. - * This data is stored as a list of phids. Use this function to get the - * new phid. - */ - private function getNewAnswerPHID() { - $new = $this->getNewValue(); - $old = $this->getOldValue(); - $add = array_diff($new, $old); - - if (count($add) != 1) { - throw new Exception( - pht('There should be only one answer added at a time.')); - } - - return reset($add); - } - } diff --git a/src/applications/ponder/xaction/PonderAnswerContentTransaction.php b/src/applications/ponder/xaction/PonderAnswerContentTransaction.php new file mode 100644 index 0000000000..5d5c6ad157 --- /dev/null +++ b/src/applications/ponder/xaction/PonderAnswerContentTransaction.php @@ -0,0 +1,56 @@ +getContent(); + } + + public function applyInternalEffects($object, $value) { + $object->setContent($value); + } + + public function getTitle() { + return pht( + '%s updated the answer details.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the answer details for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO ANSWER DETAILS'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/ponder/xaction/PonderAnswerQuestionIDTransaction.php b/src/applications/ponder/xaction/PonderAnswerQuestionIDTransaction.php new file mode 100644 index 0000000000..a66608479c --- /dev/null +++ b/src/applications/ponder/xaction/PonderAnswerQuestionIDTransaction.php @@ -0,0 +1,16 @@ +getQuestionID(); + } + + public function applyInternalEffects($object, $value) { + $object->setQuestionID($value); + } + +} diff --git a/src/applications/ponder/xaction/PonderAnswerStatusTransaction.php b/src/applications/ponder/xaction/PonderAnswerStatusTransaction.php new file mode 100644 index 0000000000..46a359aa5e --- /dev/null +++ b/src/applications/ponder/xaction/PonderAnswerStatusTransaction.php @@ -0,0 +1,62 @@ +getStatus(); + } + + public function applyInternalEffects($object, $value) { + $object->setStatus($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + if ($new == PonderAnswerStatus::ANSWER_STATUS_VISIBLE) { + return pht( + '%s marked this answer as visible.', + $this->renderAuthor()); + } else if ($new == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) { + return pht( + '%s marked this answer as hidden.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + if ($new == PonderAnswerStatus::ANSWER_STATUS_VISIBLE) { + return pht( + '%s marked %s as visible.', + $this->renderAuthor(), + $this->renderObject()); + } else if ($new == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) { + return pht( + '%s marked %s as hidden.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + if ($new == PonderAnswerStatus::ANSWER_STATUS_VISIBLE) { + return 'fa-ban'; + } else if ($new == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) { + return 'fa-check'; + } + } + + public function getColor() { + $new = $this->getNewValue(); + if ($new == PonderAnswerStatus::ANSWER_STATUS_VISIBLE) { + return 'green'; + } else if ($new == PonderAnswerStatus::ANSWER_STATUS_HIDDEN) { + return 'indigo'; + } + } + +} diff --git a/src/applications/ponder/xaction/PonderAnswerTransactionType.php b/src/applications/ponder/xaction/PonderAnswerTransactionType.php new file mode 100644 index 0000000000..84268f33b2 --- /dev/null +++ b/src/applications/ponder/xaction/PonderAnswerTransactionType.php @@ -0,0 +1,4 @@ +getAnswers(); + } + + public function applyInternalEffects($object, $value) { + $count = $object->getAnswerCount(); + $count++; + $object->setAnswerCount($count); + } + + public function getTitle() { + return pht( + '%s added an answer.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s added an answer to %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function getIcon() { + return 'fa-plus'; + } + +} diff --git a/src/applications/ponder/xaction/PonderQuestionAnswerWikiTransaction.php b/src/applications/ponder/xaction/PonderQuestionAnswerWikiTransaction.php new file mode 100644 index 0000000000..b6b5b150fc --- /dev/null +++ b/src/applications/ponder/xaction/PonderQuestionAnswerWikiTransaction.php @@ -0,0 +1,56 @@ +getAnswerWiki(); + } + + public function applyInternalEffects($object, $value) { + $object->setAnswerWiki($value); + } + + public function getTitle() { + return pht( + '%s updated the answer wiki.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the answer wiki for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO ANSWER WIKI'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/ponder/xaction/PonderQuestionContentTransaction.php b/src/applications/ponder/xaction/PonderQuestionContentTransaction.php new file mode 100644 index 0000000000..d958170475 --- /dev/null +++ b/src/applications/ponder/xaction/PonderQuestionContentTransaction.php @@ -0,0 +1,56 @@ +getContent(); + } + + public function applyInternalEffects($object, $value) { + $object->setContent($value); + } + + public function getTitle() { + return pht( + '%s updated the question details.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the question details for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO QUESTION DETAILS'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/ponder/xaction/PonderQuestionStatusTransaction.php b/src/applications/ponder/xaction/PonderQuestionStatusTransaction.php new file mode 100644 index 0000000000..85080b12b7 --- /dev/null +++ b/src/applications/ponder/xaction/PonderQuestionStatusTransaction.php @@ -0,0 +1,74 @@ +getStatus(); + } + + public function applyInternalEffects($object, $value) { + $object->setStatus($value); + } + + public function getTitle() { + $new = $this->getNewValue(); + switch ($new) { + case PonderQuestionStatus::STATUS_OPEN: + return pht( + '%s reopened this question.', + $this->renderAuthor()); + case PonderQuestionStatus::STATUS_CLOSED_RESOLVED: + return pht( + '%s closed this question as resolved.', + $this->renderAuthor()); + case PonderQuestionStatus::STATUS_CLOSED_OBSOLETE: + return pht( + '%s closed this question as obsolete.', + $this->renderAuthor()); + case PonderQuestionStatus::STATUS_CLOSED_INVALID: + return pht( + '%s closed this question as invalid.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + switch ($new) { + case PonderQuestionStatus::STATUS_OPEN: + return pht( + '%s reopened %s.', + $this->renderAuthor(), + $this->renderObject()); + case PonderQuestionStatus::STATUS_CLOSED_RESOLVED: + return pht( + '%s closed %s as resolved.', + $this->renderAuthor(), + $this->renderObject()); + case PonderQuestionStatus::STATUS_CLOSED_INVALID: + return pht( + '%s closed %s as invalid.', + $this->renderAuthor(), + $this->renderObject()); + case PonderQuestionStatus::STATUS_CLOSED_OBSOLETE: + return pht( + '%s closed %s as obsolete.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + return PonderQuestionStatus::getQuestionStatusIcon($new); + } + + public function getColor() { + $new = $this->getNewValue(); + return PonderQuestionStatus::getQuestionStatusTagColor($new); + } + +} diff --git a/src/applications/ponder/xaction/PonderQuestionTitleTransaction.php b/src/applications/ponder/xaction/PonderQuestionTitleTransaction.php new file mode 100644 index 0000000000..e96af9d78f --- /dev/null +++ b/src/applications/ponder/xaction/PonderQuestionTitleTransaction.php @@ -0,0 +1,55 @@ +getTitle(); + } + + public function applyInternalEffects($object, $value) { + $object->setTitle($value); + } + + public function getTitle() { + return pht( + '%s updated the question from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function getTitleForFeed() { + return pht( + '%s updated %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getTitle(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Questions must have a title.')); + } + + $max_length = $object->getColumnMaximumByteLength('title'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The title can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/ponder/xaction/PonderQuestionTransactionType.php b/src/applications/ponder/xaction/PonderQuestionTransactionType.php new file mode 100644 index 0000000000..6b68122464 --- /dev/null +++ b/src/applications/ponder/xaction/PonderQuestionTransactionType.php @@ -0,0 +1,4 @@ +setObjectName('#'.$slug); $handle->setURI("/tag/{$slug}/"); } else { + // We set the name to the project's PHID to avoid a parse error when a + // project has no hashtag (as is the case with milestones by default). + // See T12659 for more details + $handle->setCommandLineObjectName($project->getPHID()); $handle->setURI("/project/view/{$id}/"); } diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php index 05c12aec27..a4da0f7f7d 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteCloseController.php @@ -32,7 +32,8 @@ final class PhabricatorSlowvoteCloseController $xactions = array(); $xactions[] = id(new PhabricatorSlowvoteTransaction()) - ->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_CLOSE) + ->setTransactionType( + PhabricatorSlowvoteCloseTransaction::TRANSACTIONTYPE) ->setNewValue($new_status); id(new PhabricatorSlowvoteEditor()) diff --git a/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php b/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php index e9f3d48de4..d490a77c50 100644 --- a/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php +++ b/src/applications/slowvote/controller/PhabricatorSlowvoteEditController.php @@ -77,23 +77,32 @@ final class PhabricatorSlowvoteEditController } } - $xactions = array(); $template = id(new PhabricatorSlowvoteTransaction()); + $xactions = array(); + + if ($is_new) { + $xactions[] = id(new PhabricatorSlowvoteTransaction()) + ->setTransactionType(PhabricatorTransactions::TYPE_CREATE); + } $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_QUESTION) + ->setTransactionType( + PhabricatorSlowvoteQuestionTransaction::TRANSACTIONTYPE) ->setNewValue($v_question); $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION) + ->setTransactionType( + PhabricatorSlowvoteDescriptionTransaction::TRANSACTIONTYPE) ->setNewValue($v_description); $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_RESPONSES) + ->setTransactionType( + PhabricatorSlowvoteResponsesTransaction::TRANSACTIONTYPE) ->setNewValue($v_responses); $xactions[] = id(clone $template) - ->setTransactionType(PhabricatorSlowvoteTransaction::TYPE_SHUFFLE) + ->setTransactionType( + PhabricatorSlowvoteShuffleTransaction::TRANSACTIONTYPE) ->setNewValue($v_shuffle); $xactions[] = id(clone $template) diff --git a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php index 94e31e8b92..3f6baefd8d 100644 --- a/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php +++ b/src/applications/slowvote/editor/PhabricatorSlowvoteEditor.php @@ -13,105 +13,12 @@ final class PhabricatorSlowvoteEditor public function getTransactionTypes() { $types = parent::getTransactionTypes(); - - $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; - $types[] = PhabricatorSlowvoteTransaction::TYPE_QUESTION; - $types[] = PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION; - $types[] = PhabricatorSlowvoteTransaction::TYPE_RESPONSES; - $types[] = PhabricatorSlowvoteTransaction::TYPE_SHUFFLE; - $types[] = PhabricatorSlowvoteTransaction::TYPE_CLOSE; - return $types; } - protected function transactionHasEffect( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - $old = $xaction->getOldValue(); - $new = $xaction->getNewValue(); - - switch ($xaction->getTransactionType()) { - case PhabricatorSlowvoteTransaction::TYPE_RESPONSES: - if ($old === null) { - return true; - } - return ((int)$old !== (int)$new); - case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE: - if ($old === null) { - return true; - } - return ((bool)$old !== (bool)$new); - } - - return parent::transactionHasEffect($object, $xaction); - } - - - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorSlowvoteTransaction::TYPE_QUESTION: - return $object->getQuestion(); - case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION: - return $object->getDescription(); - case PhabricatorSlowvoteTransaction::TYPE_RESPONSES: - return $object->getResponseVisibility(); - case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE: - return $object->getShuffle(); - case PhabricatorSlowvoteTransaction::TYPE_CLOSE: - return $object->getIsClosed(); - } - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorSlowvoteTransaction::TYPE_QUESTION: - case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION: - case PhabricatorSlowvoteTransaction::TYPE_RESPONSES: - case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE: - case PhabricatorSlowvoteTransaction::TYPE_CLOSE: - return $xaction->getNewValue(); - } - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorSlowvoteTransaction::TYPE_QUESTION: - $object->setQuestion($xaction->getNewValue()); - break; - case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION: - $object->setDescription($xaction->getNewValue()); - break; - case PhabricatorSlowvoteTransaction::TYPE_RESPONSES: - $object->setResponseVisibility($xaction->getNewValue()); - break; - case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE: - $object->setShuffle($xaction->getNewValue()); - break; - case PhabricatorSlowvoteTransaction::TYPE_CLOSE: - $object->setIsClosed((int)$xaction->getNewValue()); - break; - } - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - return; - } - - protected function shouldSendMail( + protected function shouldSendMail( PhabricatorLiskDAO $object, array $xactions) { return true; diff --git a/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php b/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php index 78c21f5d65..06c4f6f68f 100644 --- a/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php +++ b/src/applications/slowvote/storage/PhabricatorSlowvotePoll.php @@ -21,8 +21,8 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO protected $question; protected $description; protected $authorPHID; - protected $responseVisibility; - protected $shuffle; + protected $responseVisibility = 0; + protected $shuffle = 0; protected $method; protected $mailKey; protected $viewPolicy; @@ -54,7 +54,7 @@ final class PhabricatorSlowvotePoll extends PhabricatorSlowvoteDAO self::CONFIG_COLUMN_SCHEMA => array( 'question' => 'text255', 'responseVisibility' => 'uint32', - 'shuffle' => 'uint32', + 'shuffle' => 'bool', 'method' => 'uint32', 'description' => 'text', 'isClosed' => 'bool', diff --git a/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php b/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php index fb1b7fc2f3..1781733acf 100644 --- a/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php +++ b/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php @@ -1,13 +1,7 @@ getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - case self::TYPE_RESPONSES: - case self::TYPE_SHUFFLE: - case self::TYPE_CLOSE: - return ($old === null); - } - - return parent::shouldHide(); - } - - public function getTitle() { - $author_phid = $this->getAuthorPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_QUESTION: - if ($old === null) { - return pht( - '%s created this poll.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s changed the poll question from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } - break; - case self::TYPE_DESCRIPTION: - return pht( - '%s updated the description for this poll.', - $this->renderHandleLink($author_phid)); - case self::TYPE_RESPONSES: - // TODO: This could be more detailed - return pht( - '%s changed who can see the responses.', - $this->renderHandleLink($author_phid)); - case self::TYPE_SHUFFLE: - if ($new) { - return pht( - '%s made poll responses appear in a random order.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s made poll responses appear in a fixed order.', - $this->renderHandleLink($author_phid)); - } - break; - case self::TYPE_CLOSE: - if ($new) { - return pht( - '%s closed this poll.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s reopened this poll.', - $this->renderHandleLink($author_phid)); - } - - break; - } - - return parent::getTitle(); - } - - public function getRemarkupBlocks() { - $blocks = parent::getRemarkupBlocks(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_DESCRIPTION: - $blocks[] = $this->getNewValue(); - break; - } - - return $blocks; - } - - public function getTitleForFeed() { - $author_phid = $this->getAuthorPHID(); - $object_phid = $this->getObjectPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $type = $this->getTransactionType(); - switch ($type) { - case self::TYPE_QUESTION: - if ($old === null) { - return pht( - '%s created %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - - } else { - return pht( - '%s renamed %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_DESCRIPTION: - if ($old === null) { - return pht( - '%s set the description of %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - - } else { - return pht( - '%s edited the description of %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - case self::TYPE_RESPONSES: - // TODO: This could be more detailed - return pht( - '%s changed who can see the responses of %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - - case self::TYPE_SHUFFLE: - if ($new) { - return pht( - '%s made %s responses appear in a random order.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - - } else { - return pht( - '%s made %s responses appear in a fixed order.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - case self::TYPE_CLOSE: - if ($new) { - return pht( - '%s closed %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - - } else { - return pht( - '%s reopened %s.', - $this->renderHandleLink($author_phid), - $this->renderHandleLink($object_phid)); - } - break; - } - - return parent::getTitleForFeed(); - } - - public function getIcon() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_QUESTION: - if ($old === null) { - return 'fa-plus'; - } else { - return 'fa-pencil'; - } - case self::TYPE_DESCRIPTION: - case self::TYPE_RESPONSES: - return 'fa-pencil'; - case self::TYPE_SHUFFLE: - return 'fa-refresh'; - case self::TYPE_CLOSE: - if ($new) { - return 'fa-ban'; - } else { - return 'fa-pencil'; - } - } - - return parent::getIcon(); - } - - - public function getColor() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_QUESTION: - case self::TYPE_DESCRIPTION: - case self::TYPE_RESPONSES: - case self::TYPE_SHUFFLE: - case self::TYPE_CLOSE: - return PhabricatorTransactions::COLOR_BLUE; - } - - return parent::getColor(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - return true; - } - return parent::hasChangeDetails(); - } - - public function renderChangeDetails(PhabricatorUser $viewer) { - return $this->renderTextCorpusChangeDetails( - $viewer, - $this->getOldValue(), - $this->getNewValue()); + public function getBaseTransactionClass() { + return 'PhabricatorSlowvoteTransactionType'; } public function getMailTags() { $tags = parent::getMailTags(); switch ($this->getTransactionType()) { - case self::TYPE_QUESTION: - case self::TYPE_DESCRIPTION: - case self::TYPE_SHUFFLE: - case self::TYPE_CLOSE: + case PhabricatorSlowvoteQuestionTransaction::TRANSACTIONTYPE: + case PhabricatorSlowvoteDescriptionTransaction::TRANSACTIONTYPE: + case PhabricatorSlowvoteShuffleTransaction::TRANSACTIONTYPE: + case PhabricatorSlowvoteCloseTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_DETAILS; break; - case self::TYPE_RESPONSES: + case PhabricatorSlowvoteResponsesTransaction::TRANSACTIONTYPE: $tags[] = self::MAILTAG_RESPONSES; break; default: diff --git a/src/applications/slowvote/xactions/PhabricatorSlowvoteCloseTransaction.php b/src/applications/slowvote/xactions/PhabricatorSlowvoteCloseTransaction.php new file mode 100644 index 0000000000..ce3eaf5879 --- /dev/null +++ b/src/applications/slowvote/xactions/PhabricatorSlowvoteCloseTransaction.php @@ -0,0 +1,60 @@ +getIsClosed(); + } + + public function generateNewValue($object, $value) { + return (bool)$value; + } + + public function applyInternalEffects($object, $value) { + $object->setIsClosed((int)$value); + } + + public function getTitle() { + $new = $this->getNewValue(); + + if ($new) { + return pht( + '%s closed this poll.', + $this->renderAuthor()); + } else { + return pht( + '%s reopened this poll.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + + if ($new) { + return pht( + '%s closed %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s reopened %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + + if ($new) { + return 'fa-ban'; + } else { + return 'fa-pencil'; + } + } + +} diff --git a/src/applications/slowvote/xactions/PhabricatorSlowvoteDescriptionTransaction.php b/src/applications/slowvote/xactions/PhabricatorSlowvoteDescriptionTransaction.php new file mode 100644 index 0000000000..8a46f7dc5e --- /dev/null +++ b/src/applications/slowvote/xactions/PhabricatorSlowvoteDescriptionTransaction.php @@ -0,0 +1,60 @@ +getDescription(); + } + + public function applyInternalEffects($object, $value) { + $object->setDescription($value); + } + + public function getTitle() { + return pht( + '%s updated the description for this poll.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + + if ($old === null) { + return pht( + '%s set the description of %s.', + $this->renderAuthor(), + $this->renderObject()); + + } else { + return pht( + '%s edited the description of %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function hasChangeDetails() { + return true; + } + + public function newChangeDetailView() { + return $this->renderTextCorpusChangeDetails( + $this->getViewer(), + $this->getOldValue(), + $this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + +} diff --git a/src/applications/slowvote/xactions/PhabricatorSlowvoteQuestionTransaction.php b/src/applications/slowvote/xactions/PhabricatorSlowvoteQuestionTransaction.php new file mode 100644 index 0000000000..09c5f93e66 --- /dev/null +++ b/src/applications/slowvote/xactions/PhabricatorSlowvoteQuestionTransaction.php @@ -0,0 +1,70 @@ +getQuestion(); + } + + public function applyInternalEffects($object, $value) { + $object->setQuestion($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + if ($old === null) { + return pht( + '%s created this poll.', + $this->renderAuthor()); + } else { + return pht( + '%s changed the poll question from "%s" to "%s".', + $this->renderAuthor(), + $old, + $new); + } + } + + public function getTitleForFeed() { + $old = $this->getOldValue(); + + if ($old === null) { + return pht( + '%s created %s.', + $this->renderAuthor(), + $this->renderObject()); + + } else { + return pht( + '%s renamed %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $old = $this->getOldValue(); + + if ($old === null) { + return 'fa-plus'; + } else { + return 'fa-pencil'; + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getQuestion(), $xactions)) { + $errors[] = $this->newRequiredError(pht('Polls must have a question.')); + } + + return $errors; + } + +} diff --git a/src/applications/slowvote/xactions/PhabricatorSlowvoteResponsesTransaction.php b/src/applications/slowvote/xactions/PhabricatorSlowvoteResponsesTransaction.php new file mode 100644 index 0000000000..93035cbd6a --- /dev/null +++ b/src/applications/slowvote/xactions/PhabricatorSlowvoteResponsesTransaction.php @@ -0,0 +1,31 @@ +getResponseVisibility(); + } + + public function applyInternalEffects($object, $value) { + $object->setResponseVisibility($value); + } + + public function getTitle() { + // TODO: This could be more detailed + return pht( + '%s changed who can see the responses.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + // TODO: This could be more detailed + return pht( + '%s changed who can see the responses of %s.', + $this->renderAuthor(), + $this->renderObject()); + } + +} diff --git a/src/applications/slowvote/xactions/PhabricatorSlowvoteShuffleTransaction.php b/src/applications/slowvote/xactions/PhabricatorSlowvoteShuffleTransaction.php new file mode 100644 index 0000000000..645e86b393 --- /dev/null +++ b/src/applications/slowvote/xactions/PhabricatorSlowvoteShuffleTransaction.php @@ -0,0 +1,55 @@ +getShuffle(); + } + + public function generateNewValue($object, $value) { + return (bool)$value; + } + + public function applyInternalEffects($object, $value) { + $object->setShuffle((int)$value); + } + + public function getTitle() { + $new = $this->getNewValue(); + + if ($new) { + return pht( + '%s made poll responses appear in a random order.', + $this->renderAuthor()); + } else { + return pht( + '%s made poll responses appear in a fixed order.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + + if ($new) { + return pht( + '%s made %s responses appear in a random order.', + $this->renderAuthor(), + $this->renderObject()); + + } else { + return pht( + '%s made %s responses appear in a fixed order.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + return 'fa-refresh'; + } + +} diff --git a/src/applications/slowvote/xactions/PhabricatorSlowvoteTransactionType.php b/src/applications/slowvote/xactions/PhabricatorSlowvoteTransactionType.php new file mode 100644 index 0000000000..f380aa101c --- /dev/null +++ b/src/applications/slowvote/xactions/PhabricatorSlowvoteTransactionType.php @@ -0,0 +1,4 @@ +getMonogram(); if ($request->isFormPost()) { - $type_archive = PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE; + $type_archive = + PhabricatorSpacesNamespaceArchiveTransaction::TRANSACTIONTYPE; $xactions = array(); $xactions[] = id(new PhabricatorSpacesNamespaceTransaction()) diff --git a/src/applications/spaces/controller/PhabricatorSpacesEditController.php b/src/applications/spaces/controller/PhabricatorSpacesEditController.php index 3f7dae9e82..faca39d634 100644 --- a/src/applications/spaces/controller/PhabricatorSpacesEditController.php +++ b/src/applications/spaces/controller/PhabricatorSpacesEditController.php @@ -67,9 +67,12 @@ final class PhabricatorSpacesEditController $v_view = $request->getStr('viewPolicy'); $v_edit = $request->getStr('editPolicy'); - $type_name = PhabricatorSpacesNamespaceTransaction::TYPE_NAME; - $type_desc = PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION; - $type_default = PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT; + $type_name = + PhabricatorSpacesNamespaceNameTransaction::TRANSACTIONTYPE; + $type_desc = + PhabricatorSpacesNamespaceDescriptionTransaction::TRANSACTIONTYPE; + $type_default = + PhabricatorSpacesNamespaceDefaultTransaction::TRANSACTIONTYPE; $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; diff --git a/src/applications/spaces/controller/PhabricatorSpacesViewController.php b/src/applications/spaces/controller/PhabricatorSpacesViewController.php index 495a0c8dee..5fa1c01143 100644 --- a/src/applications/spaces/controller/PhabricatorSpacesViewController.php +++ b/src/applications/spaces/controller/PhabricatorSpacesViewController.php @@ -39,7 +39,7 @@ final class PhabricatorSpacesViewController ->setHeaderIcon('fa-th-large'); if ($space->getIsArchived()) { - $header->setStatus('fa-ban', 'red', pht('Archived')); + $header->setStatus('fa-ban', 'indigo', pht('Archived')); } else { $header->setStatus('fa-check', 'bluegrey', pht('Active')); } diff --git a/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php b/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php index caa45f28c2..e4dc9c5b69 100644 --- a/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php +++ b/src/applications/spaces/editor/PhabricatorSpacesNamespaceEditor.php @@ -14,153 +14,18 @@ final class PhabricatorSpacesNamespaceEditor public function getTransactionTypes() { $types = parent::getTransactionTypes(); - $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_NAME; - $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION; - $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT; - $types[] = PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE; - $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; return $types; } - protected function getCustomTransactionOldValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorSpacesNamespaceTransaction::TYPE_NAME: - $name = $object->getNamespaceName(); - if (!strlen($name)) { - return null; - } - return $name; - case PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION: - if ($this->getIsNewObject()) { - return null; - } - return $object->getDescription(); - case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: - return $object->getIsArchived(); - case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: - return $object->getIsDefaultNamespace() ? 1 : null; - case PhabricatorTransactions::TYPE_VIEW_POLICY: - return $object->getViewPolicy(); - case PhabricatorTransactions::TYPE_EDIT_POLICY: - return $object->getEditPolicy(); - } - - return parent::getCustomTransactionOldValue($object, $xaction); + public function getCreateObjectTitle($author, $object) { + return pht('%s created this space.', $author); } - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorSpacesNamespaceTransaction::TYPE_NAME: - case PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION: - case PhabricatorTransactions::TYPE_VIEW_POLICY: - case PhabricatorTransactions::TYPE_EDIT_POLICY: - return $xaction->getNewValue(); - case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: - return $xaction->getNewValue() ? 1 : 0; - case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: - return $xaction->getNewValue() ? 1 : null; - } - - return parent::getCustomTransactionNewValue($object, $xaction); - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - $new = $xaction->getNewValue(); - - switch ($xaction->getTransactionType()) { - case PhabricatorSpacesNamespaceTransaction::TYPE_NAME: - $object->setNamespaceName($new); - return; - case PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION: - $object->setDescription($new); - return; - case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: - $object->setIsDefaultNamespace($new ? 1 : null); - return; - case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: - $object->setIsArchived($new ? 1 : 0); - return; - case PhabricatorTransactions::TYPE_VIEW_POLICY: - $object->setViewPolicy($new); - return; - case PhabricatorTransactions::TYPE_EDIT_POLICY: - $object->setEditPolicy($new); - return; - } - - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - - switch ($xaction->getTransactionType()) { - case PhabricatorSpacesNamespaceTransaction::TYPE_NAME: - case PhabricatorSpacesNamespaceTransaction::TYPE_DESCRIPTION: - case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: - case PhabricatorSpacesNamespaceTransaction::TYPE_ARCHIVE: - case PhabricatorTransactions::TYPE_VIEW_POLICY: - case PhabricatorTransactions::TYPE_EDIT_POLICY: - return; - } - - return parent::applyCustomExternalTransaction($object, $xaction); - } - - protected function validateTransaction( - PhabricatorLiskDAO $object, - $type, - array $xactions) { - - $errors = parent::validateTransaction($object, $type, $xactions); - - switch ($type) { - case PhabricatorSpacesNamespaceTransaction::TYPE_NAME: - $missing = $this->validateIsEmptyTextField( - $object->getNamespaceName(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Spaces must have a name.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - break; - case PhabricatorSpacesNamespaceTransaction::TYPE_DEFAULT: - if (!$this->getIsNewObject()) { - foreach ($xactions as $xaction) { - $errors[] = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid'), - pht( - 'Only the first space created can be the default space, and '. - 'it must remain the default space evermore.'), - $xaction); - } - } - break; - - } - - return $errors; + public function getCreateObjectTitleForFeed($author, $object) { + return pht('%s created space %s.', $author, $object); } } diff --git a/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php b/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php index 4c438537f1..0f50a870f6 100644 --- a/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php +++ b/src/applications/spaces/storage/PhabricatorSpacesNamespaceTransaction.php @@ -1,12 +1,7 @@ getOldValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - return ($old === null); - } - - return parent::shouldHide(); - } - - public function hasChangeDetails() { - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - return true; - } - - return parent::hasChangeDetails(); - } - - public function getRemarkupBlocks() { - $blocks = parent::getRemarkupBlocks(); - - switch ($this->getTransactionType()) { - case self::TYPE_DESCRIPTION: - $blocks[] = $this->getNewValue(); - break; - } - - return $blocks; - } - - public function getTitle() { - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - $author_phid = $this->getAuthorPHID(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created this space.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s renamed this space from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } - case self::TYPE_DESCRIPTION: - return pht( - '%s updated the description for this space.', - $this->renderHandleLink($author_phid)); - case self::TYPE_DEFAULT: - return pht( - '%s made this the default space.', - $this->renderHandleLink($author_phid)); - case self::TYPE_ARCHIVE: - if ($new) { - return pht( - '%s archived this space.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s activated this space.', - $this->renderHandleLink($author_phid)); - } - } - - return parent::getTitle(); + public function getBaseTransactionClass() { + return 'PhabricatorSpacesNamespaceTransactionType'; } } diff --git a/src/applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php new file mode 100644 index 0000000000..a1dedbd85f --- /dev/null +++ b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceArchiveTransaction.php @@ -0,0 +1,60 @@ +getIsArchived(); + } + + public function applyInternalEffects($object, $value) { + $object->setIsArchived((int)$value); + } + + public function getTitle() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s archived this space.', + $this->renderAuthor()); + } else { + return pht( + '%s activated this space.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + $new = $this->getNewValue(); + if ($new) { + return pht( + '%s archived space %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s activated space %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + + public function getIcon() { + $new = $this->getNewValue(); + if ($new) { + return 'fa-ban'; + } else { + return 'fa-check'; + } + } + + public function getColor() { + $new = $this->getNewValue(); + if ($new) { + return 'indigo'; + } + } + +} diff --git a/src/applications/spaces/xaction/PhabricatorSpacesNamespaceDefaultTransaction.php b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceDefaultTransaction.php new file mode 100644 index 0000000000..bc09b06d91 --- /dev/null +++ b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceDefaultTransaction.php @@ -0,0 +1,44 @@ +getIsDefaultNamespace(); + } + + public function applyInternalEffects($object, $value) { + $object->setIsDefaultNamespace($value); + } + + public function getTitle() { + return pht( + '%s made this the default space.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s made space %s the default space.', + $this->renderAuthor(), + $this->renderObject()); + + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if (!$this->isNewObject()) { + foreach ($xactions as $xaction) { + $errors[] = $this->newInvalidError( + pht('Only the first space created can be the default space, and '. + 'it must remain the default space evermore.')); + } + } + + return $errors; + } + +} diff --git a/src/applications/spaces/xaction/PhabricatorSpacesNamespaceDescriptionTransaction.php b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceDescriptionTransaction.php new file mode 100644 index 0000000000..22b0faa5d1 --- /dev/null +++ b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceDescriptionTransaction.php @@ -0,0 +1,57 @@ +getDescription(); + } + + public function applyInternalEffects($object, $value) { + $object->setDescription($value); + } + + public function getTitle() { + return pht( + '%s updated the space description.', + $this->renderAuthor()); + } + + public function getTitleForFeed() { + return pht( + '%s updated the space description for %s.', + $this->renderAuthor(), + $this->renderObject()); + } + + public function hasChangeDetailView() { + return true; + } + + public function getMailDiffSectionHeader() { + return pht('CHANGES TO SPACE DESCRIPTION'); + } + + public function newChangeDetailView() { + $viewer = $this->getViewer(); + + return id(new PhabricatorApplicationTransactionTextDiffDetailView()) + ->setViewer($viewer) + ->setOldText($this->getOldValue()) + ->setNewText($this->getNewValue()); + } + + public function newRemarkupChanges() { + $changes = array(); + + $changes[] = $this->newRemarkupChange() + ->setOldValue($this->getOldValue()) + ->setNewValue($this->getNewValue()); + + return $changes; + } + + +} diff --git a/src/applications/spaces/xaction/PhabricatorSpacesNamespaceNameTransaction.php b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceNameTransaction.php new file mode 100644 index 0000000000..d7fcbc2c7a --- /dev/null +++ b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceNameTransaction.php @@ -0,0 +1,62 @@ +getNamespaceName(); + } + + public function applyInternalEffects($object, $value) { + $object->setNamespaceName($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + if (!strlen($old)) { + return pht( + '%s created this space.', + $this->renderAuthor()); + } else { + return pht( + '%s renamed this space from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } + } + + public function getTitleForFeed() { + return pht( + '%s renamed space %s from %s to %s.', + $this->renderAuthor(), + $this->renderObject(), + $this->renderOldValue(), + $this->renderNewValue()); + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getNamespaceName(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Spaces must have a name.')); + } + + $max_length = $object->getColumnMaximumByteLength('namespaceName'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newInvalidError( + pht('The name can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/spaces/xaction/PhabricatorSpacesNamespaceTransactionType.php b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceTransactionType.php new file mode 100644 index 0000000000..a6f206a16c --- /dev/null +++ b/src/applications/spaces/xaction/PhabricatorSpacesNamespaceTransactionType.php @@ -0,0 +1,4 @@ +getApplicationTransactionCommentObject(); + } catch (PhutilMethodNotImplementedException $ex) { + $comment = null; + } + + if ($comment) { + $types[] = PhabricatorTransactions::TYPE_COMMENT; + } + } + return $types; } @@ -322,6 +334,8 @@ abstract class PhabricatorApplicationTransactionEditor $xtype = $this->getModularTransactionType($type); if ($xtype) { + $xtype = clone $xtype; + $xtype->setStorage($xaction); return $xtype->generateOldValue($object); } @@ -402,6 +416,8 @@ abstract class PhabricatorApplicationTransactionEditor $xtype = $this->getModularTransactionType($type); if ($xtype) { + $xtype = clone $xtype; + $xtype->setStorage($xaction); return $xtype->generateNewValue($object, $xaction->getNewValue()); } @@ -541,6 +557,8 @@ abstract class PhabricatorApplicationTransactionEditor $xtype = $this->getModularTransactionType($type); if ($xtype) { + $xtype = clone $xtype; + $xtype->setStorage($xaction); return $xtype->applyInternalEffects($object, $xaction->getNewValue()); } @@ -2151,7 +2169,7 @@ abstract class PhabricatorApplicationTransactionEditor return array_mergev($errors); } - private function validatePolicyTransaction( + public function validatePolicyTransaction( PhabricatorLiskDAO $object, array $xactions, $transaction_type, @@ -2760,7 +2778,11 @@ abstract class PhabricatorApplicationTransactionEditor } if (!$has_support) { - throw new Exception(pht('Capability not supported.')); + throw new Exception( + pht('The object being edited does not implement any standard '. + 'interfaces (like PhabricatorSubscribableInterface) which allow '. + 'CCs to be generated automatically. Override the "getMailCC()" '. + 'method and generate CCs explicitly.')); } return array_mergev($phids); diff --git a/src/applications/transactions/storage/PhabricatorModularTransactionType.php b/src/applications/transactions/storage/PhabricatorModularTransactionType.php index 9d8510cdc9..8a56e8e8ce 100644 --- a/src/applications/transactions/storage/PhabricatorModularTransactionType.php +++ b/src/applications/transactions/storage/PhabricatorModularTransactionType.php @@ -315,4 +315,8 @@ abstract class PhabricatorModularTransactionType return $editor->getPHIDList($old, $new); } + public function getMetadataValue($key, $default = null) { + return $this->getStorage()->getMetadataValue($key, $default); + } + } diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css index a986409227..0c07c145a8 100644 --- a/webroot/rsrc/css/core/remarkup.css +++ b/webroot/rsrc/css/core/remarkup.css @@ -126,12 +126,13 @@ } .phabricator-remarkup .remarkup-list-with-checkmarks input { - margin-right: 2px; + margin-right: 4px; opacity: 1; } .phabricator-remarkup .remarkup-list-with-checkmarks .remarkup-checked-item { text-decoration: line-through; + color: {$lightgreytext}; } .phabricator-remarkup ul.remarkup-list ol.remarkup-list, diff --git a/webroot/rsrc/js/application/conpherence/behavior-durable-column.js b/webroot/rsrc/js/application/conpherence/behavior-durable-column.js index c6c82bc3be..a521046d8e 100644 --- a/webroot/rsrc/js/application/conpherence/behavior-durable-column.js +++ b/webroot/rsrc/js/application/conpherence/behavior-durable-column.js @@ -177,7 +177,7 @@ JX.behavior('durable-column', function(config, statics) { var params = null; switch (action) { - case 'metadata': + case 'go_edit': threadManager.runUpdateWorkflowFromLink( link, {