Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2889884
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
221 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
index 2b3d84efae..1f8dd90d58 100644
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -1,2192 +1,2192 @@
<?php
/**
* This file is automatically generated. Use 'bin/celerity map' to rebuild it.
* @generated
*/
return array(
'names' =>
array(
'core.pkg.css' => '92a99fb2',
'core.pkg.js' => '8f7aa2c3',
'darkconsole.pkg.js' => 'ca8671ce',
'differential.pkg.css' => '6aef439e',
'differential.pkg.js' => '322ea941',
'diffusion.pkg.css' => '3783278d',
'diffusion.pkg.js' => '7b51e80a',
'javelin.pkg.js' => '70ecd3ac',
'maniphest.pkg.css' => 'f1887d71',
'maniphest.pkg.js' => '1e8f11af',
'rsrc/css/aphront/aphront-bars.css' => '231ac33c',
'rsrc/css/aphront/aphront-notes.css' => '6acadd3f',
'rsrc/css/aphront/context-bar.css' => '1c3b0529',
'rsrc/css/aphront/dark-console.css' => '6378ef3d',
'rsrc/css/aphront/dialog-view.css' => 'dd9db96c',
'rsrc/css/aphront/error-view.css' => '16cd9949',
'rsrc/css/aphront/lightbox-attachment.css' => '686f8885',
'rsrc/css/aphront/list-filter-view.css' => 'ef989c67',
'rsrc/css/aphront/multi-column.css' => '12f65921',
'rsrc/css/aphront/notification.css' => '6901121e',
'rsrc/css/aphront/pager-view.css' => '2e3539af',
'rsrc/css/aphront/panel-view.css' => '5846dfa2',
'rsrc/css/aphront/phabricator-nav-view.css' => 'd0d4a509',
'rsrc/css/aphront/request-failure-view.css' => 'da14df31',
'rsrc/css/aphront/table-view.css' => '92a719ca',
'rsrc/css/aphront/tokenizer.css' => '75a7316a',
'rsrc/css/aphront/tooltip.css' => '9c90229d',
'rsrc/css/aphront/transaction.css' => 'ce491938',
'rsrc/css/aphront/two-column.css' => '16ab3ad2',
'rsrc/css/aphront/typeahead.css' => '271456a1',
'rsrc/css/application/auth/auth.css' => '1e655982',
'rsrc/css/application/base/main-menu-view.css' => 'd36e0c11',
'rsrc/css/application/base/notification-menu.css' => 'fc9a363c',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '55ba7571',
'rsrc/css/application/base/standard-page-view.css' => '517cdfb1',
'rsrc/css/application/chatlog/chatlog.css' => '852140ff',
'rsrc/css/application/config/config-options.css' => '7fedf08b',
'rsrc/css/application/config/config-template.css' => '25d446d6',
'rsrc/css/application/config/setup-issue.css' => '69e640e7',
'rsrc/css/application/conpherence/menu.css' => '561348ac',
'rsrc/css/application/conpherence/message-pane.css' => '2aedca89',
'rsrc/css/application/conpherence/notification.css' => 'f9ba9914',
'rsrc/css/application/conpherence/update.css' => '1099a660',
'rsrc/css/application/conpherence/widget-pane.css' => '87b12e0c',
'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4',
'rsrc/css/application/countdown/timer.css' => '86b7b0a0',
'rsrc/css/application/diff/inline-comment-summary.css' => '14a91639',
'rsrc/css/application/differential/add-comment.css' => 'c478bcaa',
'rsrc/css/application/differential/changeset-view.css' => '82431767',
'rsrc/css/application/differential/core.css' => '8135cb0c',
'rsrc/css/application/differential/local-commits-view.css' => '19649019',
'rsrc/css/application/differential/results-table.css' => '239924f9',
'rsrc/css/application/differential/revision-comment.css' => '48186045',
'rsrc/css/application/differential/revision-history.css' => 'f37aee8f',
'rsrc/css/application/differential/revision-list.css' => 'f3c47d33',
'rsrc/css/application/differential/table-of-contents.css' => '19566f76',
'rsrc/css/application/diffusion/commit-view.css' => '92d1e8f9',
'rsrc/css/application/diffusion/diffusion-icons.css' => '384a0f7d',
'rsrc/css/application/diffusion/diffusion-source.css' => '66fdf661',
'rsrc/css/application/directory/phabricator-jump-nav.css' => 'f0c5e726',
'rsrc/css/application/feed/feed.css' => '0d17c209',
'rsrc/css/application/files/global-drag-and-drop.css' => '697324ad',
'rsrc/css/application/flag/flag.css' => '5337623f',
'rsrc/css/application/herald/herald-test.css' => '2b7d0f54',
'rsrc/css/application/herald/herald.css' => '59d48f01',
'rsrc/css/application/legalpad/legalpad-document.css' => 'cd275275',
'rsrc/css/application/maniphest/batch-editor.css' => '78444bc1',
'rsrc/css/application/maniphest/report.css' => '6fc16517',
'rsrc/css/application/maniphest/task-edit.css' => '8e23031b',
'rsrc/css/application/maniphest/task-summary.css' => '6df1a768',
'rsrc/css/application/objectselector/object-selector.css' => '029a133d',
'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b',
'rsrc/css/application/paste/paste.css' => 'aa1767d1',
'rsrc/css/application/people/people-profile.css' => 'd0bababe',
'rsrc/css/application/phame/phame.css' => '450826e1',
'rsrc/css/application/pholio/pholio-edit.css' => 'b9e59b6d',
'rsrc/css/application/pholio/pholio-inline-comments.css' => '52be33f0',
'rsrc/css/application/pholio/pholio.css' => 'd23ace50',
'rsrc/css/application/phortune/phortune-credit-card-form.css' => 'b25b4beb',
'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad',
'rsrc/css/application/phriction/phriction-document-css.css' => 'b0309d8e',
'rsrc/css/application/policy/policy-edit.css' => '05cca26a',
'rsrc/css/application/policy/policy.css' => '957ea14c',
'rsrc/css/application/ponder/comments.css' => '6cdccea7',
'rsrc/css/application/ponder/feed.css' => 'e62615b6',
'rsrc/css/application/ponder/post.css' => 'ebab8a70',
'rsrc/css/application/ponder/vote.css' => '8ed6ed8b',
'rsrc/css/application/profile/profile-view.css' => '3a7e04ca',
'rsrc/css/application/projects/phabricator-object-list-view.css' => '1a1ea560',
'rsrc/css/application/projects/project-tag.css' => '095c9404',
'rsrc/css/application/releeph/releeph-branch.css' => 'b8821d2d',
'rsrc/css/application/releeph/releeph-colors.css' => '2d2d6aa8',
'rsrc/css/application/releeph/releeph-core.css' => '140b959d',
'rsrc/css/application/releeph/releeph-intents.css' => '7364ac97',
'rsrc/css/application/releeph/releeph-preview-branch.css' => '0e383ca3',
'rsrc/css/application/releeph/releeph-project.css' => 'ee1f9f57',
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae',
'rsrc/css/application/releeph/releeph-status.css' => 'a20631d9',
'rsrc/css/application/search/search-results.css' => 'f240504c',
'rsrc/css/application/settings/settings.css' => 'ea8f5915',
'rsrc/css/application/slowvote/slowvote.css' => '266df6a1',
'rsrc/css/application/tokens/tokens.css' => 'fb286311',
'rsrc/css/application/uiexample/example.css' => '4741b891',
'rsrc/css/core/core.css' => 'da26ddb2',
'rsrc/css/core/remarkup.css' => 'ca7f2265',
'rsrc/css/core/syntax.css' => '3c18c1cb',
'rsrc/css/core/z-index.css' => '0fd29d49',
'rsrc/css/diviner/diviner-shared.css' => 'be90f718',
'rsrc/css/layout/phabricator-action-header-view.css' => 'cc654b91',
'rsrc/css/layout/phabricator-action-list-view.css' => '81383e25',
'rsrc/css/layout/phabricator-crumbs-view.css' => '2d9db584',
'rsrc/css/layout/phabricator-filetree-view.css' => 'a8c86ace',
'rsrc/css/layout/phabricator-hovercard-view.css' => '67c12b16',
'rsrc/css/layout/phabricator-side-menu-view.css' => '503699d0',
'rsrc/css/layout/phabricator-source-code-view.css' => '62a99814',
'rsrc/css/phui/phui-box.css' => '1a82a4ae',
'rsrc/css/phui/phui-button.css' => '8784a966',
'rsrc/css/phui/phui-calendar-month.css' => '3474d15a',
'rsrc/css/phui/phui-document.css' => '143b2ac8',
'rsrc/css/phui/phui-feed-story.css' => '3a59c2cf',
'rsrc/css/phui/phui-form-view.css' => '0efd3326',
'rsrc/css/phui/phui-form.css' => 'b78ec020',
'rsrc/css/phui/phui-header-view.css' => '472a6003',
'rsrc/css/phui/phui-icon.css' => 'fcb145a7',
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
'rsrc/css/phui/phui-list.css' => '2edb76cf',
'rsrc/css/phui/phui-object-box.css' => '95767d08',
'rsrc/css/phui/phui-object-item-list-view.css' => 'eb579d6c',
'rsrc/css/phui/phui-pinboard-view.css' => '4b346c2a',
'rsrc/css/phui/phui-property-list-view.css' => 'dbf53b12',
'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b',
'rsrc/css/phui/phui-spacing.css' => '042804d6',
'rsrc/css/phui/phui-status.css' => '2f562399',
'rsrc/css/phui/phui-tag-view.css' => '295d81c4',
'rsrc/css/phui/phui-text.css' => '23e9b4b7',
'rsrc/css/phui/phui-timeline-view.css' => 'd3ccba00',
'rsrc/css/phui/phui-workboard-view.css' => 'bf70dd2e',
'rsrc/css/phui/phui-workpanel-view.css' => '97b69459',
'rsrc/css/sprite-actions.css' => '969ad0e5',
'rsrc/css/sprite-apps-large.css' => '5abf49e9',
'rsrc/css/sprite-apps-xlarge.css' => 'db66c878',
'rsrc/css/sprite-apps.css' => '6973a52b',
'rsrc/css/sprite-buttonbar.css' => 'ba1c5738',
'rsrc/css/sprite-conpherence.css' => '3b4a0487',
'rsrc/css/sprite-docs.css' => '5f65d0da',
'rsrc/css/sprite-gradient.css' => 'a10def53',
'rsrc/css/sprite-icons.css' => 'f19a828c',
'rsrc/css/sprite-login.css' => '9fbaec81',
'rsrc/css/sprite-main-header.css' => '92720ee2',
'rsrc/css/sprite-menu.css' => '8da53882',
'rsrc/css/sprite-minicons.css' => 'df4f76fe',
'rsrc/css/sprite-payments.css' => 'cc085d44',
'rsrc/css/sprite-projects.css' => '7578fa56',
'rsrc/css/sprite-status.css' => '8bce1c97',
'rsrc/css/sprite-tokens.css' => '1706b943',
'rsrc/externals/javelin/core/Event.js' => '79473b62',
'rsrc/externals/javelin/core/Stratcom.js' => 'c293f7b9',
'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => 'e27df27b',
'rsrc/externals/javelin/core/__tests__/install.js' => '1dd4d6db',
'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'da194d4b',
'rsrc/externals/javelin/core/__tests__/util.js' => 'd3b157a9',
'rsrc/externals/javelin/core/init.js' => 'b88ab49e',
'rsrc/externals/javelin/core/init_node.js' => 'd7dde471',
'rsrc/externals/javelin/core/install.js' => '52a92793',
'rsrc/externals/javelin/core/util.js' => '7501647b',
'rsrc/externals/javelin/docs/Base.js' => '3b9ca7eb',
'rsrc/externals/javelin/docs/onload.js' => '69948972',
'rsrc/externals/javelin/ext/fx/Color.js' => '7e41274a',
'rsrc/externals/javelin/ext/fx/FX.js' => '54b612ba',
'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => '63f9ad59',
'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => 'ba86e2fd',
'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '96474586',
'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '4c33dff1',
'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => 'bd3c1838',
'rsrc/externals/javelin/ext/view/HTMLView.js' => '957caa12',
'rsrc/externals/javelin/ext/view/View.js' => '4641579a',
'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => '0c33c1a0',
'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => '2fa810fc',
'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '77461fd6',
'rsrc/externals/javelin/ext/view/ViewVisitor.js' => 'ca704f2b',
'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => 'f92d7bcb',
'rsrc/externals/javelin/ext/view/__tests__/View.js' => 'bda69c40',
'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => '7a94d6a5',
'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '5426001c',
'rsrc/externals/javelin/lib/Cookie.js' => '6b3dcf44',
'rsrc/externals/javelin/lib/DOM.js' => '03be94fb',
'rsrc/externals/javelin/lib/History.js' => 'c60f4327',
'rsrc/externals/javelin/lib/JSON.js' => '08e56a4e',
'rsrc/externals/javelin/lib/Mask.js' => 'b9f26029',
'rsrc/externals/javelin/lib/Request.js' => '23f9bb8d',
'rsrc/externals/javelin/lib/Resource.js' => '356de121',
'rsrc/externals/javelin/lib/URI.js' => 'd9a9b862',
'rsrc/externals/javelin/lib/Vector.js' => '403a3dce',
'rsrc/externals/javelin/lib/Workflow.js' => 'd16edeae',
'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8',
'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b',
'rsrc/externals/javelin/lib/__tests__/JSON.js' => '2295d074',
'rsrc/externals/javelin/lib/__tests__/URI.js' => 'ece3ddb3',
'rsrc/externals/javelin/lib/__tests__/behavior.js' => 'c1d75ee6',
'rsrc/externals/javelin/lib/behavior.js' => '8a3ed18b',
'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => 'e7c21fb3',
'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => 'c54eeefb',
'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => '5f850b5c',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '0136cec1',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '89889fe7',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => 'e9b95df3',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '62e18640',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => 'c2b8bf64',
'rsrc/externals/raphael/g.raphael.js' => '40dde778',
'rsrc/externals/raphael/g.raphael.line.js' => '40da039e',
'rsrc/externals/raphael/raphael.js' => '51ee6b43',
'rsrc/image/BFCFDA.png' => 'd5ec91f4',
'rsrc/image/actions/edit.png' => '2fc41442',
'rsrc/image/apple-touch-icon.png' => '8458dda7',
'rsrc/image/avatar.png' => '62c5f933',
'rsrc/image/checker_dark.png' => 'd8e65881',
'rsrc/image/checker_light.png' => 'a0155918',
'rsrc/image/credit_cards.png' => '72b8ede8',
'rsrc/image/darkload.gif' => '1ffd3ec6',
'rsrc/image/divot.png' => '94dded62',
'rsrc/image/grippy_texture.png' => 'aca81e2f',
'rsrc/image/icon/fatcow/arrow_branch.png' => '2537c01c',
'rsrc/image/icon/fatcow/arrow_merge.png' => '21b660e0',
'rsrc/image/icon/fatcow/bullet_black.png' => 'ff190031',
'rsrc/image/icon/fatcow/bullet_orange.png' => 'e273e5bb',
'rsrc/image/icon/fatcow/bullet_red.png' => 'c0b75434',
'rsrc/image/icon/fatcow/calendar_edit.png' => '24632275',
'rsrc/image/icon/fatcow/document_black.png' => '45fe1c60',
'rsrc/image/icon/fatcow/flag_blue.png' => 'a01abb1d',
'rsrc/image/icon/fatcow/flag_finish.png' => '67825cee',
'rsrc/image/icon/fatcow/flag_ghost.png' => '20ca8783',
'rsrc/image/icon/fatcow/flag_green.png' => '7e0eaa7a',
'rsrc/image/icon/fatcow/flag_orange.png' => '9e73df66',
'rsrc/image/icon/fatcow/flag_pink.png' => '7e92f3b2',
'rsrc/image/icon/fatcow/flag_purple.png' => 'cc517522',
'rsrc/image/icon/fatcow/flag_red.png' => '04ec726f',
'rsrc/image/icon/fatcow/flag_yellow.png' => '73946fd4',
'rsrc/image/icon/fatcow/folder.png' => '95a435af',
'rsrc/image/icon/fatcow/folder_go.png' => '001cbc94',
'rsrc/image/icon/fatcow/key_question.png' => '52a0c26a',
'rsrc/image/icon/fatcow/link.png' => '7afd4d5e',
'rsrc/image/icon/fatcow/page_white_edit.png' => '39a2eed8',
'rsrc/image/icon/fatcow/page_white_link.png' => 'a90023c7',
'rsrc/image/icon/fatcow/page_white_put.png' => '08c95a0c',
'rsrc/image/icon/fatcow/page_white_text.png' => '1e1f79c3',
'rsrc/image/icon/fatcow/source/conduit.png' => '4ea01d2f',
'rsrc/image/icon/fatcow/source/email.png' => '9bab3239',
'rsrc/image/icon/fatcow/source/fax.png' => '04195e68',
'rsrc/image/icon/fatcow/source/mobile.png' => 'f1321264',
'rsrc/image/icon/fatcow/source/tablet.png' => '49396799',
'rsrc/image/icon/fatcow/source/web.png' => '136ccb5d',
'rsrc/image/icon/fatcow/thumbnails/default160x120.png' => 'f2e8a2eb',
'rsrc/image/icon/fatcow/thumbnails/default60x45.png' => '0118abed',
'rsrc/image/icon/fatcow/thumbnails/image160x120.png' => '79bb556a',
'rsrc/image/icon/fatcow/thumbnails/image60x45.png' => 'c5e1685e',
'rsrc/image/icon/fatcow/thumbnails/pdf160x120.png' => 'ac9edbf5',
'rsrc/image/icon/fatcow/thumbnails/pdf60x45.png' => 'c0db4143',
'rsrc/image/icon/fatcow/thumbnails/zip160x120.png' => '75f9cd0f',
'rsrc/image/icon/fatcow/thumbnails/zip60x45.png' => 'af11bf3e',
'rsrc/image/icon/lightbox/close-2.png' => 'cc40e7c8',
'rsrc/image/icon/lightbox/close-hover-2.png' => 'fb5d6d9e',
'rsrc/image/icon/lightbox/left-arrow-2.png' => '8426133b',
'rsrc/image/icon/lightbox/left-arrow-hover-2.png' => '701e5ee3',
'rsrc/image/icon/lightbox/right-arrow-2.png' => '6d5519a0',
'rsrc/image/icon/lightbox/right-arrow-hover-2.png' => '3a04aa21',
'rsrc/image/icon/subscribe.png' => 'd03ed5a5',
'rsrc/image/icon/tango/attachment.png' => 'ecc8022e',
'rsrc/image/icon/tango/edit.png' => '929a1363',
'rsrc/image/icon/tango/go-down.png' => '96d95e43',
'rsrc/image/icon/tango/log.png' => 'b08cc63a',
'rsrc/image/icon/tango/upload.png' => '7bbb7984',
'rsrc/image/icon/unsubscribe.png' => '25725013',
'rsrc/image/lightblue-header.png' => '5c168b6d',
'rsrc/image/loading.gif' => '75d384cc',
'rsrc/image/loading/boating_24.gif' => '5c90f086',
'rsrc/image/loading/compass_24.gif' => 'b36b4f46',
'rsrc/image/loading/loading_24.gif' => '26bc9adc',
'rsrc/image/loading/loading_48.gif' => '6a4994c7',
'rsrc/image/loading/loading_d48.gif' => 'cdcbe900',
'rsrc/image/loading/loading_w24.gif' => '7662fa2b',
'rsrc/image/main_texture.png' => '29a2c5ad',
'rsrc/image/menu_texture.png' => '5a17580d',
'rsrc/image/people/harding.png' => '45aa614e',
'rsrc/image/people/jefferson.png' => 'afca0e53',
'rsrc/image/people/lincoln.png' => '9369126d',
'rsrc/image/people/mckinley.png' => 'fb8f16ce',
'rsrc/image/people/taft.png' => 'd7bc402c',
'rsrc/image/people/washington.png' => '40dd301c',
'rsrc/image/phrequent_active.png' => 'a466a8ed',
'rsrc/image/phrequent_inactive.png' => 'bfc15a69',
'rsrc/image/search-white.png' => '64cc0d45',
'rsrc/image/search.png' => '82625a7e',
'rsrc/image/sprite-actions-X2.png' => '7dfd5652',
'rsrc/image/sprite-actions.png' => '2ddd18c3',
'rsrc/image/sprite-apps-X2.png' => 'c091b2d3',
'rsrc/image/sprite-apps-large-X2.png' => 'e1396a83',
'rsrc/image/sprite-apps-large.png' => '48cef7bd',
'rsrc/image/sprite-apps-xlarge.png' => 'a751a580',
'rsrc/image/sprite-apps.png' => '4f788e21',
'rsrc/image/sprite-buttonbar-X2.png' => '2c09a184',
'rsrc/image/sprite-buttonbar.png' => 'e98e96af',
'rsrc/image/sprite-conpherence-X2.png' => 'cd2d08d7',
'rsrc/image/sprite-conpherence.png' => 'a5ab2eb7',
'rsrc/image/sprite-docs-X2.png' => '6dc1adad',
'rsrc/image/sprite-docs.png' => '4636297f',
'rsrc/image/sprite-gradient.png' => '4ece0b62',
'rsrc/image/sprite-icons-X2.png' => '0d5867c0',
'rsrc/image/sprite-icons.png' => '3f754bda',
'rsrc/image/sprite-login-X2.png' => '81c1344f',
'rsrc/image/sprite-login.png' => '7c729508',
'rsrc/image/sprite-main-header.png' => '83521873',
'rsrc/image/sprite-menu-X2.png' => '949974c6',
'rsrc/image/sprite-menu.png' => '307d5da0',
'rsrc/image/sprite-minicons-X2.png' => '55377e4e',
'rsrc/image/sprite-minicons.png' => '272644ea',
'rsrc/image/sprite-payments.png' => 'd8576309',
'rsrc/image/sprite-projects-X2.png' => '218fdc8b',
'rsrc/image/sprite-projects.png' => '631ff9a7',
'rsrc/image/sprite-status-X2.png' => '82445ee0',
'rsrc/image/sprite-status.png' => '926a896a',
'rsrc/image/sprite-tokens-X2.png' => 'b4776580',
'rsrc/image/sprite-tokens.png' => '25b75533',
'rsrc/image/texture/card-gradient.png' => '815f26e8',
'rsrc/image/texture/dark-menu-hover.png' => '5fa7ece8',
'rsrc/image/texture/dark-menu.png' => '7e22296e',
'rsrc/image/texture/grip.png' => '719404f3',
'rsrc/image/texture/panel-header-gradient.png' => 'e3b8dcfe',
'rsrc/image/texture/phlnx-bg.png' => '8d819209',
'rsrc/image/texture/pholio-background.gif' => 'ba29239c',
'rsrc/image/texture/table_header.png' => '5c433037',
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
'rsrc/js/application/aphlict/Aphlict.js' => '493665ee',
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '2a2dba85',
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => '845731b8',
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
'rsrc/js/application/config/behavior-reorder-fields.js' => '69bb5094',
'rsrc/js/application/conpherence/behavior-menu.js' => '7ff0b011',
'rsrc/js/application/conpherence/behavior-pontificate.js' => '53f6f2dd',
'rsrc/js/application/conpherence/behavior-widget-pane.js' => 'd8ef8659',
'rsrc/js/application/countdown/timer.js' => '8454ce4f',
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => 'f2441746',
'rsrc/js/application/differential/behavior-accept-with-errors.js' => 'e12c760a',
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => '4ba4c13d',
'rsrc/js/application/differential/behavior-comment-jump.js' => '71755c79',
'rsrc/js/application/differential/behavior-comment-preview.js' => '127f2018',
'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1',
'rsrc/js/application/differential/behavior-dropdown-menus.js' => '5f004630',
'rsrc/js/application/differential/behavior-edit-inline-comments.js' => '93f43142',
'rsrc/js/application/differential/behavior-keyboard-nav.js' => 'da3e88f9',
'rsrc/js/application/differential/behavior-populate.js' => 'ce0c217a',
'rsrc/js/application/differential/behavior-show-all-comments.js' => '7c273581',
'rsrc/js/application/differential/behavior-show-field-details.js' => '441f2137',
'rsrc/js/application/differential/behavior-show-more.js' => 'dd7e8ef5',
'rsrc/js/application/differential/behavior-toggle-files.js' => 'ca3f91eb',
'rsrc/js/application/differential/behavior-user-select.js' => 'a8d8459d',
'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'be81801d',
'rsrc/js/application/diffusion/behavior-commit-branches.js' => 'eae2f65d',
'rsrc/js/application/diffusion/behavior-commit-graph.js' => '85ba3cf4',
'rsrc/js/application/diffusion/behavior-jump-to.js' => '9db3d160',
'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667',
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => '3c5310da',
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'fd27d99a',
'rsrc/js/application/files/behavior-icon-composer.js' => 'ea38f732',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '6ec125a0',
'rsrc/js/application/harbormaster/behavior-reorder-steps.js' => 'b21125a5',
'rsrc/js/application/herald/HeraldRuleEditor.js' => '4f31d692',
'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec',
'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3',
'rsrc/js/application/maniphest/behavior-batch-editor.js' => '391457d7',
'rsrc/js/application/maniphest/behavior-batch-selector.js' => 'ead554ec',
'rsrc/js/application/maniphest/behavior-line-chart.js' => 'cdcbe8a4',
'rsrc/js/application/maniphest/behavior-list-edit.js' => 'cf76cfd5',
'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '84845b5b',
'rsrc/js/application/maniphest/behavior-transaction-controls.js' => '75e50c72',
'rsrc/js/application/maniphest/behavior-transaction-expand.js' => '2f2e18aa',
'rsrc/js/application/maniphest/behavior-transaction-preview.js' => 'f8248bc5',
'rsrc/js/application/owners/OwnersPathEditor.js' => '46efd18e',
'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3',
'rsrc/js/application/passphrase/phame-credential-control.js' => '1e1c8a59',
'rsrc/js/application/phame/phame-post-preview.js' => '61d927ec',
'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '1e1e8bb0',
'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => '28497740',
'rsrc/js/application/phortune/behavior-balanced-payment-form.js' => '3b3e1664',
'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '1693a296',
'rsrc/js/application/phortune/behavior-test-payment-form.js' => 'b3e5ee60',
'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef',
'rsrc/js/application/policy/behavior-policy-control.js' => 'c01153ea',
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '263aeb8c',
'rsrc/js/application/ponder/behavior-votebox.js' => '327dbe61',
'rsrc/js/application/projects/behavior-project-boards.js' => '1b9facd8',
'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
'rsrc/js/application/releeph/releeph-preview-branch.js' => '9eb2cedb',
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'fe7fc914',
'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'cd9e7094',
'rsrc/js/application/repository/repository-crossreference.js' => '8ab282be',
'rsrc/js/application/search/behavior-reorder-queries.js' => '34397f68',
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => 'a51fdb2e',
'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => '9084a36f',
- 'rsrc/js/application/transactions/behavior-transaction-list.js' => 'bfb45968',
+ 'rsrc/js/application/transactions/behavior-transaction-list.js' => '3c918aa8',
'rsrc/js/application/uiexample/JavelinViewExample.js' => 'd4a14807',
'rsrc/js/application/uiexample/ReactorButtonExample.js' => '44524435',
'rsrc/js/application/uiexample/ReactorCheckboxExample.js' => '7ba325ee',
'rsrc/js/application/uiexample/ReactorFocusExample.js' => '82f568cd',
'rsrc/js/application/uiexample/ReactorInputExample.js' => 'd6ca6b1c',
'rsrc/js/application/uiexample/ReactorMouseoverExample.js' => '4e37e4de',
'rsrc/js/application/uiexample/ReactorRadioExample.js' => '858f9728',
'rsrc/js/application/uiexample/ReactorSelectExample.js' => '189e4fe3',
'rsrc/js/application/uiexample/ReactorSendClassExample.js' => 'bf97561d',
'rsrc/js/application/uiexample/ReactorSendPropertiesExample.js' => '551add57',
'rsrc/js/application/uiexample/busy-example.js' => 'fbbce3bf',
'rsrc/js/application/uiexample/gesture-example.js' => 'f42bb8c6',
'rsrc/js/application/uiexample/notification-example.js' => 'c51a6616',
'rsrc/js/core/Busy.js' => '6453c869',
'rsrc/js/core/DragAndDropFileUpload.js' => 'ae6abfba',
'rsrc/js/core/DraggableList.js' => '1681c4d4',
'rsrc/js/core/DropdownMenu.js' => 'fb342e18',
'rsrc/js/core/DropdownMenuItem.js' => '0f386ef4',
'rsrc/js/core/FileUpload.js' => '96713558',
'rsrc/js/core/Hovercard.js' => '4f344388',
'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2',
'rsrc/js/core/KeyboardShortcutManager.js' => 'ad7a69ca',
'rsrc/js/core/MultirowRowManager.js' => 'e7076916',
'rsrc/js/core/Notification.js' => '95944043',
'rsrc/js/core/Prefab.js' => '0326e5d0',
'rsrc/js/core/ShapedRequest.js' => 'dfa181a4',
'rsrc/js/core/TextAreaUtils.js' => 'b3ec3cfc',
'rsrc/js/core/ToolTip.js' => '0a81ea29',
'rsrc/js/core/behavior-active-nav.js' => 'c81bc98f',
'rsrc/js/core/behavior-audio-source.js' => '59b251eb',
'rsrc/js/core/behavior-autofocus.js' => '7319e029',
'rsrc/js/core/behavior-crop.js' => 'b98fc918',
'rsrc/js/core/behavior-dark-console.js' => 'e9fdb5e5',
'rsrc/js/core/behavior-device.js' => '03d6ed07',
'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '94d146cb',
'rsrc/js/core/behavior-error-log.js' => 'a5d7cf86',
'rsrc/js/core/behavior-fancy-datepicker.js' => '5d584426',
'rsrc/js/core/behavior-file-tree.js' => 'c8728c70',
'rsrc/js/core/behavior-form.js' => '27d4da3f',
'rsrc/js/core/behavior-gesture.js' => 'fe2e0ba4',
'rsrc/js/core/behavior-global-drag-and-drop.js' => '828a2eed',
'rsrc/js/core/behavior-history-install.js' => '7ee2b591',
'rsrc/js/core/behavior-hovercard.js' => '9c808199',
'rsrc/js/core/behavior-keyboard-pager.js' => 'b657bdf8',
'rsrc/js/core/behavior-keyboard-shortcuts.js' => 'd75709e6',
'rsrc/js/core/behavior-konami.js' => '5bc2cb21',
'rsrc/js/core/behavior-lightbox-attachments.js' => '3aa45ad9',
'rsrc/js/core/behavior-line-linker.js' => 'bc778103',
'rsrc/js/core/behavior-more.js' => '9b9197be',
'rsrc/js/core/behavior-object-selector.js' => 'b4eef37b',
'rsrc/js/core/behavior-oncopy.js' => 'dab9253e',
'rsrc/js/core/behavior-phabricator-nav.js' => 'b5842a5e',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c021950a',
'rsrc/js/core/behavior-refresh-csrf.js' => 'c4b31646',
'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45',
'rsrc/js/core/behavior-reveal-content.js' => '8f24abfc',
'rsrc/js/core/behavior-search-typeahead.js' => 'f6b56f7a',
'rsrc/js/core/behavior-select-on-click.js' => '0e34ca02',
'rsrc/js/core/behavior-toggle-class.js' => 'a82a7769',
'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884',
'rsrc/js/core/behavior-tooltip.js' => 'e5dd1c6d',
'rsrc/js/core/behavior-watch-anchor.js' => '06e05112',
'rsrc/js/core/behavior-workflow.js' => '82947dda',
'rsrc/js/core/phtize.js' => 'd254d646',
'rsrc/js/phui/behavior-phui-object-box-tabs.js' => 'a3e2244e',
'rsrc/swf/aphlict.swf' => 'abac967d',
),
'symbols' =>
array(
'aphront-bars' => '231ac33c',
'aphront-contextbar-view-css' => '1c3b0529',
'aphront-dark-console-css' => '6378ef3d',
'aphront-dialog-view-css' => 'dd9db96c',
'aphront-error-view-css' => '16cd9949',
'aphront-list-filter-view-css' => 'ef989c67',
'aphront-multi-column-view-css' => '12f65921',
'aphront-notes' => '6acadd3f',
'aphront-pager-view-css' => '2e3539af',
'aphront-panel-view-css' => '5846dfa2',
'aphront-request-failure-view-css' => 'da14df31',
'aphront-table-view-css' => '92a719ca',
'aphront-tokenizer-control-css' => '75a7316a',
'aphront-tooltip-css' => '9c90229d',
'aphront-two-column-view-css' => '16ab3ad2',
'aphront-typeahead-control-css' => '271456a1',
'auth-css' => '1e655982',
'config-options-css' => '7fedf08b',
'conpherence-menu-css' => '561348ac',
'conpherence-message-pane-css' => '2aedca89',
'conpherence-notification-css' => 'f9ba9914',
'conpherence-update-css' => '1099a660',
'conpherence-widget-pane-css' => '87b12e0c',
'differential-changeset-view-css' => '82431767',
'differential-core-view-css' => '8135cb0c',
'differential-inline-comment-editor' => 'f2441746',
'differential-local-commits-view-css' => '19649019',
'differential-results-table-css' => '239924f9',
'differential-revision-add-comment-css' => 'c478bcaa',
'differential-revision-comment-css' => '48186045',
'differential-revision-history-css' => 'f37aee8f',
'differential-revision-list-css' => 'f3c47d33',
'differential-table-of-contents-css' => '19566f76',
'diffusion-commit-view-css' => '92d1e8f9',
'diffusion-icons-css' => '384a0f7d',
'diffusion-source-css' => '66fdf661',
'diviner-shared-css' => 'be90f718',
'global-drag-and-drop-css' => '697324ad',
'herald-css' => '59d48f01',
'herald-rule-editor' => '4f31d692',
'herald-test-css' => '2b7d0f54',
'inline-comment-summary-css' => '14a91639',
'javelin-aphlict' => '493665ee',
'javelin-behavior' => '8a3ed18b',
'javelin-behavior-aphlict-dropdown' => '2a2dba85',
'javelin-behavior-aphlict-listen' => '845731b8',
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
'javelin-behavior-aphront-crop' => 'b98fc918',
'javelin-behavior-aphront-drag-and-drop-textarea' => '94d146cb',
'javelin-behavior-aphront-form-disable-on-submit' => '27d4da3f',
'javelin-behavior-aphront-more' => '9b9197be',
'javelin-behavior-audio-source' => '59b251eb',
'javelin-behavior-audit-preview' => 'be81801d',
'javelin-behavior-balanced-payment-form' => '3b3e1664',
'javelin-behavior-config-reorder-fields' => '69bb5094',
'javelin-behavior-conpherence-menu' => '7ff0b011',
'javelin-behavior-conpherence-pontificate' => '53f6f2dd',
'javelin-behavior-conpherence-widget-pane' => 'd8ef8659',
'javelin-behavior-countdown-timer' => '8454ce4f',
'javelin-behavior-dark-console' => 'e9fdb5e5',
'javelin-behavior-device' => '03d6ed07',
'javelin-behavior-differential-accept-with-errors' => 'e12c760a',
'javelin-behavior-differential-add-reviewers-and-ccs' => '4ba4c13d',
'javelin-behavior-differential-comment-jump' => '71755c79',
'javelin-behavior-differential-diff-radios' => 'e1ff79b1',
'javelin-behavior-differential-dropdown-menus' => '5f004630',
'javelin-behavior-differential-edit-inline-comments' => '93f43142',
'javelin-behavior-differential-feedback-preview' => '127f2018',
'javelin-behavior-differential-keyboard-navigation' => 'da3e88f9',
'javelin-behavior-differential-populate' => 'ce0c217a',
'javelin-behavior-differential-show-field-details' => '441f2137',
'javelin-behavior-differential-show-more' => 'dd7e8ef5',
'javelin-behavior-differential-toggle-files' => 'ca3f91eb',
'javelin-behavior-differential-user-select' => 'a8d8459d',
'javelin-behavior-diffusion-commit-branches' => 'eae2f65d',
'javelin-behavior-diffusion-commit-graph' => '85ba3cf4',
'javelin-behavior-diffusion-jump-to' => '9db3d160',
'javelin-behavior-diffusion-pull-lastmodified' => '3c5310da',
'javelin-behavior-doorkeeper-tag' => 'fd27d99a',
'javelin-behavior-error-log' => 'a5d7cf86',
'javelin-behavior-fancy-datepicker' => '5d584426',
'javelin-behavior-global-drag-and-drop' => '828a2eed',
'javelin-behavior-harbormaster-reorder-steps' => 'b21125a5',
'javelin-behavior-herald-rule-editor' => '7ebaeed3',
'javelin-behavior-history-install' => '7ee2b591',
'javelin-behavior-icon-composer' => 'ea38f732',
'javelin-behavior-konami' => '5bc2cb21',
'javelin-behavior-launch-icon-composer' => '6ec125a0',
'javelin-behavior-lightbox-attachments' => '3aa45ad9',
'javelin-behavior-line-chart' => 'cdcbe8a4',
'javelin-behavior-load-blame' => '42126667',
'javelin-behavior-maniphest-batch-editor' => '391457d7',
'javelin-behavior-maniphest-batch-selector' => 'ead554ec',
'javelin-behavior-maniphest-list-editor' => 'cf76cfd5',
'javelin-behavior-maniphest-subpriority-editor' => '84845b5b',
'javelin-behavior-maniphest-transaction-controls' => '75e50c72',
'javelin-behavior-maniphest-transaction-expand' => '2f2e18aa',
'javelin-behavior-maniphest-transaction-preview' => 'f8248bc5',
'javelin-behavior-owners-path-editor' => '7a68dda3',
'javelin-behavior-passphrase-credential-control' => '1e1c8a59',
'javelin-behavior-persona-login' => '9414ff18',
'javelin-behavior-phabricator-active-nav' => 'c81bc98f',
'javelin-behavior-phabricator-autofocus' => '7319e029',
'javelin-behavior-phabricator-busy-example' => 'fbbce3bf',
'javelin-behavior-phabricator-file-tree' => 'c8728c70',
'javelin-behavior-phabricator-gesture' => 'fe2e0ba4',
'javelin-behavior-phabricator-gesture-example' => 'f42bb8c6',
'javelin-behavior-phabricator-hovercards' => '9c808199',
'javelin-behavior-phabricator-keyboard-pager' => 'b657bdf8',
'javelin-behavior-phabricator-keyboard-shortcuts' => 'd75709e6',
'javelin-behavior-phabricator-line-linker' => 'bc778103',
'javelin-behavior-phabricator-nav' => 'b5842a5e',
'javelin-behavior-phabricator-notification-example' => 'c51a6616',
'javelin-behavior-phabricator-object-selector' => 'b4eef37b',
'javelin-behavior-phabricator-oncopy' => 'dab9253e',
'javelin-behavior-phabricator-remarkup-assist' => 'c021950a',
'javelin-behavior-phabricator-reveal-content' => '8f24abfc',
'javelin-behavior-phabricator-search-typeahead' => 'f6b56f7a',
'javelin-behavior-phabricator-show-all-transactions' => '7c273581',
'javelin-behavior-phabricator-tooltips' => 'e5dd1c6d',
'javelin-behavior-phabricator-transaction-comment-form' => '9084a36f',
- 'javelin-behavior-phabricator-transaction-list' => 'bfb45968',
+ 'javelin-behavior-phabricator-transaction-list' => '3c918aa8',
'javelin-behavior-phabricator-watch-anchor' => '06e05112',
'javelin-behavior-phame-post-preview' => '61d927ec',
'javelin-behavior-pholio-mock-edit' => '1e1e8bb0',
'javelin-behavior-pholio-mock-view' => '28497740',
'javelin-behavior-phui-object-box-tabs' => 'a3e2244e',
'javelin-behavior-policy-control' => 'c01153ea',
'javelin-behavior-policy-rule-editor' => '263aeb8c',
'javelin-behavior-ponder-votebox' => '327dbe61',
'javelin-behavior-project-boards' => '1b9facd8',
'javelin-behavior-project-create' => '065227cc',
'javelin-behavior-refresh-csrf' => 'c4b31646',
'javelin-behavior-releeph-preview-branch' => '9eb2cedb',
'javelin-behavior-releeph-request-state-change' => 'fe7fc914',
'javelin-behavior-releeph-request-typeahead' => 'cd9e7094',
'javelin-behavior-remarkup-preview' => 'f7379f45',
'javelin-behavior-repository-crossreference' => '8ab282be',
'javelin-behavior-search-reorder-queries' => '34397f68',
'javelin-behavior-select-on-click' => '0e34ca02',
'javelin-behavior-slowvote-embed' => 'a51fdb2e',
'javelin-behavior-stripe-payment-form' => '1693a296',
'javelin-behavior-test-payment-form' => 'b3e5ee60',
'javelin-behavior-toggle-class' => 'a82a7769',
'javelin-behavior-view-placeholder' => '2fa810fc',
'javelin-behavior-workflow' => '82947dda',
'javelin-color' => '7e41274a',
'javelin-cookie' => '6b3dcf44',
'javelin-dom' => '03be94fb',
'javelin-dynval' => '63f9ad59',
'javelin-event' => '79473b62',
'javelin-fx' => '54b612ba',
'javelin-history' => 'c60f4327',
'javelin-install' => '52a92793',
'javelin-json' => '08e56a4e',
'javelin-magical-init' => 'b88ab49e',
'javelin-mask' => 'b9f26029',
'javelin-reactor' => 'ba86e2fd',
'javelin-reactor-dom' => 'bd3c1838',
'javelin-reactor-node-calmer' => '4c33dff1',
'javelin-reactornode' => '96474586',
'javelin-request' => '23f9bb8d',
'javelin-resource' => '356de121',
'javelin-stratcom' => 'c293f7b9',
'javelin-tokenizer' => 'e7c21fb3',
'javelin-typeahead' => 'c54eeefb',
'javelin-typeahead-composite-source' => '0136cec1',
'javelin-typeahead-normalizer' => '5f850b5c',
'javelin-typeahead-ondemand-source' => '89889fe7',
'javelin-typeahead-preloaded-source' => 'e9b95df3',
'javelin-typeahead-source' => '62e18640',
'javelin-typeahead-static-source' => 'c2b8bf64',
'javelin-uri' => 'd9a9b862',
'javelin-util' => '7501647b',
'javelin-vector' => '403a3dce',
'javelin-view' => '4641579a',
'javelin-view-html' => '957caa12',
'javelin-view-interpreter' => '0c33c1a0',
'javelin-view-renderer' => '77461fd6',
'javelin-view-visitor' => 'ca704f2b',
'javelin-workflow' => 'd16edeae',
'legalpad-document-css' => 'cd275275',
'lightbox-attachment-css' => '686f8885',
'maniphest-batch-editor' => '78444bc1',
'maniphest-report-css' => '6fc16517',
'maniphest-task-edit-css' => '8e23031b',
'maniphest-task-summary-css' => '6df1a768',
'multirow-row-manager' => 'e7076916',
'owners-path-editor' => '46efd18e',
'owners-path-editor-css' => '2f00933b',
'paste-css' => 'aa1767d1',
'path-typeahead' => 'f7fc67ec',
'people-profile-css' => 'd0bababe',
'phabricator-action-header-view-css' => 'cc654b91',
'phabricator-action-list-view-css' => '81383e25',
'phabricator-application-launch-view-css' => '55ba7571',
'phabricator-busy' => '6453c869',
'phabricator-chatlog-css' => '852140ff',
'phabricator-content-source-view-css' => '4b8b05d4',
'phabricator-core-css' => 'da26ddb2',
'phabricator-countdown-css' => '86b7b0a0',
'phabricator-crumbs-view-css' => '2d9db584',
'phabricator-drag-and-drop-file-upload' => 'ae6abfba',
'phabricator-draggable-list' => '1681c4d4',
'phabricator-dropdown-menu' => 'fb342e18',
'phabricator-fatal-config-template-css' => '25d446d6',
'phabricator-feed-css' => '0d17c209',
'phabricator-file-upload' => '96713558',
'phabricator-filetree-view-css' => 'a8c86ace',
'phabricator-flag-css' => '5337623f',
'phabricator-hovercard' => '4f344388',
'phabricator-hovercard-view-css' => '67c12b16',
'phabricator-jump-nav' => 'f0c5e726',
'phabricator-keyboard-shortcut' => '1ae869f2',
'phabricator-keyboard-shortcut-manager' => 'ad7a69ca',
'phabricator-main-menu-view' => 'd36e0c11',
'phabricator-menu-item' => '0f386ef4',
'phabricator-nav-view-css' => 'd0d4a509',
'phabricator-notification' => '95944043',
'phabricator-notification-css' => '6901121e',
'phabricator-notification-menu-css' => 'fc9a363c',
'phabricator-object-list-view-css' => '1a1ea560',
'phabricator-object-selector-css' => '029a133d',
'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => '0326e5d0',
'phabricator-profile-css' => '3a7e04ca',
'phabricator-project-tag-css' => '095c9404',
'phabricator-remarkup-css' => 'ca7f2265',
'phabricator-search-results-css' => 'f240504c',
'phabricator-settings-css' => 'ea8f5915',
'phabricator-shaped-request' => 'dfa181a4',
'phabricator-side-menu-view-css' => '503699d0',
'phabricator-slowvote-css' => '266df6a1',
'phabricator-source-code-view-css' => '62a99814',
'phabricator-standard-page-view' => '517cdfb1',
'phabricator-textareautils' => 'b3ec3cfc',
'phabricator-tooltip' => '0a81ea29',
'phabricator-transaction-view-css' => 'ce491938',
'phabricator-ui-example-css' => '4741b891',
'phabricator-uiexample-javelin-view' => 'd4a14807',
'phabricator-uiexample-reactor-button' => '44524435',
'phabricator-uiexample-reactor-checkbox' => '7ba325ee',
'phabricator-uiexample-reactor-focus' => '82f568cd',
'phabricator-uiexample-reactor-input' => 'd6ca6b1c',
'phabricator-uiexample-reactor-mouseover' => '4e37e4de',
'phabricator-uiexample-reactor-radio' => '858f9728',
'phabricator-uiexample-reactor-select' => '189e4fe3',
'phabricator-uiexample-reactor-sendclass' => 'bf97561d',
'phabricator-uiexample-reactor-sendproperties' => '551add57',
'phabricator-zindex-css' => '0fd29d49',
'phame-css' => '450826e1',
'pholio-css' => 'd23ace50',
'pholio-edit-css' => 'b9e59b6d',
'pholio-inline-comments-css' => '52be33f0',
'phortune-credit-card-form' => '2290aeef',
'phortune-credit-card-form-css' => 'b25b4beb',
'phrequent-css' => 'ffc185ad',
'phriction-document-css' => 'b0309d8e',
'phui-box-css' => '1a82a4ae',
'phui-button-css' => '8784a966',
'phui-calendar-month-css' => '3474d15a',
'phui-document-view-css' => '143b2ac8',
'phui-feed-story-css' => '3a59c2cf',
'phui-form-css' => 'b78ec020',
'phui-form-view-css' => '0efd3326',
'phui-header-view-css' => '472a6003',
'phui-icon-view-css' => 'fcb145a7',
'phui-info-panel-css' => '27ea50a1',
'phui-list-view-css' => '2edb76cf',
'phui-object-box-css' => '95767d08',
'phui-object-item-list-view-css' => 'eb579d6c',
'phui-pinboard-view-css' => '4b346c2a',
'phui-property-list-view-css' => 'dbf53b12',
'phui-remarkup-preview-css' => '19ad512b',
'phui-spacing-css' => '042804d6',
'phui-status-list-view-css' => '2f562399',
'phui-tag-view-css' => '295d81c4',
'phui-text-css' => '23e9b4b7',
'phui-timeline-view-css' => 'd3ccba00',
'phui-workboard-view-css' => 'bf70dd2e',
'phui-workpanel-view-css' => '97b69459',
'policy-css' => '957ea14c',
'policy-edit-css' => '05cca26a',
'ponder-comment-table-css' => '6cdccea7',
'ponder-feed-view-css' => 'e62615b6',
'ponder-post-css' => 'ebab8a70',
'ponder-vote-css' => '8ed6ed8b',
'raphael-core' => '51ee6b43',
'raphael-g' => '40dde778',
'raphael-g-line' => '40da039e',
'releeph-branch' => 'b8821d2d',
'releeph-colors' => '2d2d6aa8',
'releeph-core' => '140b959d',
'releeph-intents' => '7364ac97',
'releeph-preview-branch' => '0e383ca3',
'releeph-project' => 'ee1f9f57',
'releeph-request-differential-create-dialog' => '8d8b92cd',
'releeph-request-typeahead-css' => '667a48ae',
'releeph-status' => 'a20631d9',
'setup-issue-css' => '69e640e7',
'sprite-actions-css' => '969ad0e5',
'sprite-apps-css' => '6973a52b',
'sprite-apps-large-css' => '5abf49e9',
'sprite-apps-xlarge-css' => 'db66c878',
'sprite-buttonbar-css' => 'ba1c5738',
'sprite-conpherence-css' => '3b4a0487',
'sprite-docs-css' => '5f65d0da',
'sprite-gradient-css' => 'a10def53',
'sprite-icons-css' => 'f19a828c',
'sprite-login-css' => '9fbaec81',
'sprite-main-header-css' => '92720ee2',
'sprite-menu-css' => '8da53882',
'sprite-minicons-css' => 'df4f76fe',
'sprite-payments-css' => 'cc085d44',
'sprite-projects-css' => '7578fa56',
'sprite-status-css' => '8bce1c97',
'sprite-tokens-css' => '1706b943',
'syntax-highlighting-css' => '3c18c1cb',
'tokens-css' => 'fb286311',
),
'requires' =>
array(
'0136cec1' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead-source',
2 => 'javelin-util',
),
'029a133d' =>
array(
0 => 'aphront-dialog-view-css',
),
'0326e5d0' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead',
4 => 'javelin-tokenizer',
5 => 'javelin-typeahead-preloaded-source',
6 => 'javelin-typeahead-ondemand-source',
7 => 'javelin-dom',
8 => 'javelin-stratcom',
9 => 'javelin-util',
),
'03be94fb' =>
array(
0 => 'javelin-magical-init',
1 => 'javelin-install',
2 => 'javelin-util',
3 => 'javelin-vector',
4 => 'javelin-stratcom',
),
'03d6ed07' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-install',
),
'065227cc' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
),
'06e05112' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-vector',
),
'08e56a4e' =>
array(
0 => 'javelin-install',
),
'0a81ea29' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-vector',
),
'0c33c1a0' =>
array(
0 => 'javelin-view',
1 => 'javelin-install',
2 => 'javelin-dom',
),
'0e34ca02' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'0f386ef4' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
),
'127f2018' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-util',
5 => 'phabricator-shaped-request',
),
'1681c4d4' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-util',
4 => 'javelin-vector',
5 => 'javelin-magical-init',
),
'1693a296' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phortune-credit-card-form',
),
'189e4fe3' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
'1ae869f2' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'phabricator-keyboard-shortcut-manager',
),
'1b9facd8' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'javelin-workflow',
5 => 'phabricator-draggable-list',
),
'1e1c8a59' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
4 => 'javelin-util',
5 => 'javelin-uri',
),
'1e1e8bb0' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-workflow',
4 => 'phabricator-phtize',
5 => 'phabricator-drag-and-drop-file-upload',
6 => 'phabricator-draggable-list',
),
'2290aeef' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-json',
3 => 'javelin-workflow',
4 => 'javelin-util',
),
'23f9bb8d' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-behavior',
4 => 'javelin-json',
5 => 'javelin-dom',
6 => 'javelin-resource',
),
'263aeb8c' =>
array(
0 => 'javelin-behavior',
1 => 'multirow-row-manager',
2 => 'javelin-dom',
3 => 'javelin-util',
4 => 'phabricator-prefab',
5 => 'javelin-tokenizer',
6 => 'javelin-typeahead',
7 => 'javelin-typeahead-preloaded-source',
8 => 'javelin-json',
),
'27d4da3f' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'2a2dba85' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-request',
2 => 'javelin-stratcom',
3 => 'javelin-vector',
4 => 'javelin-dom',
5 => 'javelin-uri',
6 => 'javelin-behavior-device',
),
'2f2e18aa' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
3 => 'javelin-stratcom',
),
'2fa810fc' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-view-renderer',
3 => 'javelin-install',
),
'327dbe61' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'javelin-request',
),
'34397f68' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
3 => 'javelin-dom',
4 => 'phabricator-draggable-list',
),
'356de121' =>
array(
0 => 'javelin-util',
1 => 'javelin-uri',
2 => 'javelin-install',
),
'391457d7' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-prefab',
4 => 'multirow-row-manager',
5 => 'javelin-json',
),
'3aa45ad9' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-mask',
4 => 'javelin-util',
5 => 'phabricator-busy',
),
'3b3e1664' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phortune-credit-card-form',
),
'3c5310da' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-request',
),
+ '3c918aa8' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-stratcom',
+ 2 => 'javelin-workflow',
+ 3 => 'javelin-dom',
+ 4 => 'javelin-fx',
+ ),
'403a3dce' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
),
'441f2137' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'4641579a' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'46efd18e' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-install',
2 => 'path-typeahead',
3 => 'javelin-dom',
4 => 'javelin-util',
5 => 'phabricator-prefab',
),
'493665ee' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'4ba4c13d' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-prefab',
),
'4c33dff1' =>
array(
0 => 'javelin-install',
1 => 'javelin-reactor',
2 => 'javelin-util',
),
'4e37e4de' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
'4f31d692' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-install',
2 => 'javelin-typeahead',
3 => 'javelin-util',
4 => 'javelin-dom',
5 => 'javelin-tokenizer',
6 => 'javelin-typeahead-preloaded-source',
7 => 'javelin-stratcom',
8 => 'javelin-json',
9 => 'phabricator-prefab',
),
'4f344388' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-vector',
3 => 'javelin-request',
4 => 'javelin-uri',
),
'52a92793' =>
array(
0 => 'javelin-util',
1 => 'javelin-magical-init',
),
'53f6f2dd' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-workflow',
4 => 'javelin-stratcom',
),
'54b612ba' =>
array(
0 => 'javelin-color',
1 => 'javelin-install',
2 => 'javelin-util',
),
'551add57' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
'59b251eb' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-vector',
3 => 'javelin-dom',
),
'5bc2cb21' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
),
'5d584426' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-stratcom',
4 => 'javelin-vector',
),
'5f004630' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'phabricator-dropdown-menu',
5 => 'phabricator-menu-item',
6 => 'phabricator-phtize',
),
'5f850b5c' =>
array(
0 => 'javelin-install',
),
'61d927ec' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'62e18640' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead-normalizer',
),
'63f9ad59' =>
array(
0 => 'javelin-install',
1 => 'javelin-reactornode',
2 => 'javelin-util',
3 => 'javelin-reactor',
),
'6453c869' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-fx',
),
'69bb5094' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-json',
4 => 'phabricator-draggable-list',
),
'6b3dcf44' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'6ec125a0' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
),
'71755c79' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'7319e029' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'75a7316a' =>
array(
0 => 'aphront-typeahead-control-css',
),
'75e50c72' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-prefab',
),
'77461fd6' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'79473b62' =>
array(
0 => 'javelin-install',
),
'7a68dda3' =>
array(
0 => 'owners-path-editor',
1 => 'javelin-behavior',
),
'7ba325ee' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
'7c273581' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'7e41274a' =>
array(
0 => 'javelin-install',
),
'7ebaeed3' =>
array(
0 => 'herald-rule-editor',
1 => 'javelin-behavior',
),
'7ee2b591' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-history',
),
'7ff0b011' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'javelin-workflow',
5 => 'javelin-behavior-device',
6 => 'javelin-history',
7 => 'javelin-vector',
8 => 'phabricator-shaped-request',
),
'828a2eed' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-uri',
3 => 'javelin-mask',
4 => 'phabricator-drag-and-drop-file-upload',
),
'82947dda' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
3 => 'javelin-dom',
),
'82f568cd' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
'8454ce4f' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'845731b8' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-aphlict',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-uri',
5 => 'javelin-dom',
6 => 'javelin-json',
7 => 'phabricator-notification',
),
'84845b5b' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
4 => 'phabricator-draggable-list',
),
'858f9728' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
'85ba3cf4' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'89889fe7' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
3 => 'javelin-typeahead-source',
),
'8a3ed18b' =>
array(
0 => 'javelin-magical-init',
1 => 'javelin-util',
),
'8ab282be' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-uri',
),
'8f24abfc' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'9084a36f' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-fx',
4 => 'javelin-request',
5 => 'phabricator-shaped-request',
),
'93f43142' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-util',
4 => 'javelin-vector',
5 => 'differential-inline-comment-editor',
),
'9414ff18' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-resource',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
4 => 'javelin-util',
),
'94d146cb' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-drag-and-drop-file-upload',
3 => 'phabricator-textareautils',
),
'957caa12' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-view-visitor',
3 => 'javelin-util',
),
'9b9197be' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'9c808199' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-behavior-device',
2 => 'javelin-stratcom',
3 => 'javelin-vector',
4 => 'phabricator-hovercard',
),
'9db3d160' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-vector',
2 => 'javelin-dom',
),
'9eb2cedb' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-uri',
3 => 'javelin-request',
),
'a3e2244e' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'a51fdb2e' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-request',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
),
'a5d7cf86' =>
array(
0 => 'javelin-dom',
),
'a82a7769' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'a8d8459d' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'ad7a69ca' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
4 => 'javelin-vector',
),
'ae6abfba' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
3 => 'javelin-dom',
4 => 'javelin-uri',
5 => 'phabricator-file-upload',
),
'b21125a5' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
3 => 'javelin-dom',
4 => 'phabricator-draggable-list',
),
'b3a4b884' =>
array(
0 => 'javelin-behavior',
1 => 'phabricator-prefab',
),
'b3e5ee60' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phortune-credit-card-form',
),
'b3ec3cfc' =>
array(
0 => 'javelin-install',
),
'b4eef37b' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
3 => 'javelin-util',
),
'b5842a5e' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-behavior-device',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
4 => 'javelin-magical-init',
5 => 'javelin-vector',
6 => 'javelin-request',
7 => 'javelin-util',
),
'b657bdf8' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-uri',
2 => 'phabricator-keyboard-shortcut',
),
'b98fc918' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-vector',
3 => 'javelin-magical-init',
),
'b9f26029' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
),
'ba86e2fd' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'bc778103' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-history',
),
'bd3c1838' =>
array(
0 => 'javelin-dom',
1 => 'javelin-dynval',
2 => 'javelin-reactor',
3 => 'javelin-reactornode',
4 => 'javelin-install',
5 => 'javelin-util',
),
'be81801d' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'bf97561d' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-reactor-dom',
),
- 'bfb45968' =>
- array(
- 0 => 'javelin-behavior',
- 1 => 'javelin-stratcom',
- 2 => 'javelin-workflow',
- 3 => 'javelin-dom',
- 4 => 'javelin-fx',
- ),
'c01153ea' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-dropdown-menu',
4 => 'phabricator-menu-item',
5 => 'javelin-workflow',
),
'c021950a' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'phabricator-phtize',
4 => 'phabricator-textareautils',
5 => 'javelin-workflow',
6 => 'javelin-vector',
),
'c293f7b9' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
2 => 'javelin-util',
3 => 'javelin-magical-init',
),
'c2b8bf64' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead-source',
),
'c4b31646' =>
array(
0 => 'javelin-request',
1 => 'javelin-behavior',
2 => 'javelin-dom',
3 => 'phabricator-busy',
),
'c51a6616' =>
array(
0 => 'phabricator-notification',
1 => 'javelin-stratcom',
2 => 'javelin-behavior',
),
'c54eeefb' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-vector',
3 => 'javelin-util',
),
'c60f4327' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-install',
2 => 'javelin-uri',
3 => 'javelin-util',
),
'c81bc98f' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-vector',
3 => 'javelin-dom',
4 => 'javelin-uri',
),
'c8728c70' =>
array(
0 => 'javelin-behavior',
1 => 'phabricator-keyboard-shortcut',
2 => 'javelin-stratcom',
),
'ca3f91eb' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'phabricator-phtize',
),
'ca704f2b' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'cd9e7094' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-typeahead',
3 => 'javelin-typeahead-ondemand-source',
4 => 'javelin-dom',
),
'cdcbe8a4' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-vector',
),
'ce0c217a' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-workflow',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-stratcom',
5 => 'javelin-behavior-device',
6 => 'javelin-vector',
7 => 'phabricator-tooltip',
),
'cf76cfd5' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
4 => 'javelin-fx',
5 => 'javelin-util',
),
'd16edeae' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-request',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-install',
5 => 'javelin-util',
6 => 'javelin-mask',
7 => 'javelin-uri',
),
'd254d646' =>
array(
0 => 'javelin-util',
),
'd4a14807' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-view',
),
'd6ca6b1c' =>
array(
0 => 'javelin-install',
1 => 'javelin-reactor-dom',
2 => 'javelin-view-html',
3 => 'javelin-view-interpreter',
4 => 'javelin-view-renderer',
),
'd75709e6' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-workflow',
2 => 'javelin-json',
3 => 'javelin-dom',
4 => 'phabricator-keyboard-shortcut',
),
'd8ef8659' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
4 => 'javelin-util',
5 => 'phabricator-notification',
6 => 'javelin-behavior-device',
7 => 'phabricator-dropdown-menu',
8 => 'phabricator-menu-item',
),
'd9a9b862' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
),
'da3e88f9' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'phabricator-keyboard-shortcut',
),
'dab9253e' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'dd7e8ef5' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
3 => 'javelin-util',
4 => 'javelin-stratcom',
),
'dfa181a4' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
),
'e12c760a' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'e1ff79b1' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'e5dd1c6d' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-behavior-device',
2 => 'javelin-stratcom',
3 => 'phabricator-tooltip',
),
'e7076916' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-util',
),
'e7c21fb3' =>
array(
0 => 'javelin-dom',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-install',
),
'e9b95df3' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
3 => 'javelin-typeahead-source',
),
'e9fdb5e5' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-request',
5 => 'phabricator-keyboard-shortcut',
),
'ea38f732' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'ead554ec' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-util',
),
'eae2f65d' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-request',
),
'f2441746' =>
array(
0 => 'javelin-dom',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-install',
4 => 'javelin-request',
5 => 'javelin-workflow',
),
'f42bb8c6' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-behavior',
2 => 'javelin-vector',
3 => 'javelin-dom',
),
'f6b56f7a' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-typeahead-ondemand-source',
2 => 'javelin-typeahead',
3 => 'javelin-dom',
4 => 'javelin-uri',
5 => 'javelin-util',
6 => 'javelin-stratcom',
),
'f7379f45' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'f7fc67ec' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-typeahead-ondemand-source',
5 => 'javelin-util',
),
'f8248bc5' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-json',
4 => 'javelin-stratcom',
5 => 'phabricator-shaped-request',
),
'fb342e18' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-stratcom',
5 => 'phabricator-menu-item',
),
'fbbce3bf' =>
array(
0 => 'phabricator-busy',
1 => 'javelin-behavior',
),
'fd27d99a' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-json',
3 => 'javelin-workflow',
4 => 'javelin-magical-init',
),
'fe2e0ba4' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-behavior-device',
2 => 'javelin-stratcom',
3 => 'javelin-vector',
4 => 'javelin-dom',
5 => 'javelin-magical-init',
),
'fe7fc914' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'phabricator-keyboard-shortcut',
5 => 'phabricator-notification',
),
28497740 =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
4 => 'javelin-vector',
5 => 'javelin-magical-init',
6 => 'javelin-request',
7 => 'javelin-history',
8 => 'javelin-workflow',
9 => 'javelin-mask',
10 => 'javelin-behavior-device',
11 => 'phabricator-keyboard-shortcut',
),
42126667 =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
),
44524435 =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-dynval',
4 => 'javelin-reactor-dom',
),
95944043 =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-util',
4 => 'phabricator-notification-css',
),
96474586 =>
array(
0 => 'javelin-install',
1 => 'javelin-reactor',
2 => 'javelin-util',
3 => 'javelin-reactor-node-calmer',
),
96713558 =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'phabricator-notification',
),
),
'packages' =>
array(
'core.pkg.css' =>
array(
0 => 'phabricator-core-css',
1 => 'phabricator-zindex-css',
2 => 'phui-button-css',
3 => 'phabricator-standard-page-view',
4 => 'aphront-dialog-view-css',
5 => 'phui-form-view-css',
6 => 'aphront-panel-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-tokenizer-control-css',
9 => 'aphront-typeahead-control-css',
10 => 'aphront-list-filter-view-css',
11 => 'phabricator-jump-nav',
12 => 'phabricator-remarkup-css',
13 => 'syntax-highlighting-css',
14 => 'aphront-pager-view-css',
15 => 'phabricator-transaction-view-css',
16 => 'aphront-tooltip-css',
17 => 'phabricator-flag-css',
18 => 'aphront-error-view-css',
19 => 'sprite-icons-css',
20 => 'sprite-gradient-css',
21 => 'sprite-menu-css',
22 => 'sprite-apps-large-css',
23 => 'sprite-status-css',
24 => 'phabricator-main-menu-view',
25 => 'phabricator-notification-css',
26 => 'phabricator-notification-menu-css',
27 => 'lightbox-attachment-css',
28 => 'phui-header-view-css',
29 => 'phabricator-filetree-view-css',
30 => 'phabricator-nav-view-css',
31 => 'phabricator-side-menu-view-css',
32 => 'phabricator-crumbs-view-css',
33 => 'phui-object-item-list-view-css',
34 => 'global-drag-and-drop-css',
35 => 'phui-spacing-css',
36 => 'phui-form-css',
37 => 'phui-icon-view-css',
38 => 'phabricator-application-launch-view-css',
39 => 'phabricator-action-list-view-css',
40 => 'phui-property-list-view-css',
41 => 'phui-tag-view-css',
42 => 'phui-list-view-css',
),
'core.pkg.js' =>
array(
0 => 'javelin-behavior-aphront-basic-tokenizer',
1 => 'javelin-behavior-workflow',
2 => 'javelin-behavior-aphront-form-disable-on-submit',
3 => 'phabricator-keyboard-shortcut-manager',
4 => 'phabricator-keyboard-shortcut',
5 => 'javelin-behavior-phabricator-keyboard-shortcuts',
6 => 'javelin-behavior-refresh-csrf',
7 => 'javelin-behavior-phabricator-watch-anchor',
8 => 'javelin-behavior-phabricator-autofocus',
9 => 'phabricator-menu-item',
10 => 'phabricator-dropdown-menu',
11 => 'phabricator-phtize',
12 => 'javelin-behavior-phabricator-oncopy',
13 => 'phabricator-tooltip',
14 => 'javelin-behavior-phabricator-tooltips',
15 => 'phabricator-prefab',
16 => 'javelin-behavior-device',
17 => 'javelin-behavior-toggle-class',
18 => 'javelin-behavior-lightbox-attachments',
19 => 'phabricator-busy',
20 => 'javelin-aphlict',
21 => 'phabricator-notification',
22 => 'javelin-behavior-aphlict-listen',
23 => 'javelin-behavior-phabricator-search-typeahead',
24 => 'javelin-behavior-konami',
25 => 'javelin-behavior-aphlict-dropdown',
26 => 'javelin-behavior-history-install',
27 => 'javelin-behavior-phabricator-gesture',
28 => 'javelin-behavior-phabricator-active-nav',
29 => 'javelin-behavior-phabricator-nav',
30 => 'javelin-behavior-phabricator-remarkup-assist',
31 => 'phabricator-textareautils',
32 => 'phabricator-file-upload',
33 => 'javelin-behavior-global-drag-and-drop',
34 => 'javelin-behavior-phabricator-reveal-content',
35 => 'phabricator-hovercard',
36 => 'javelin-behavior-phabricator-hovercards',
37 => 'javelin-color',
38 => 'javelin-fx',
),
'darkconsole.pkg.js' =>
array(
0 => 'javelin-behavior-dark-console',
1 => 'javelin-behavior-error-log',
),
'differential.pkg.css' =>
array(
0 => 'differential-core-view-css',
1 => 'differential-changeset-view-css',
2 => 'differential-results-table-css',
3 => 'differential-revision-history-css',
4 => 'differential-revision-list-css',
5 => 'differential-table-of-contents-css',
6 => 'differential-revision-comment-css',
7 => 'differential-revision-add-comment-css',
8 => 'phabricator-object-selector-css',
9 => 'phabricator-content-source-view-css',
10 => 'differential-local-commits-view-css',
11 => 'inline-comment-summary-css',
),
'differential.pkg.js' =>
array(
0 => 'phabricator-drag-and-drop-file-upload',
1 => 'phabricator-shaped-request',
2 => 'javelin-behavior-differential-feedback-preview',
3 => 'javelin-behavior-differential-edit-inline-comments',
4 => 'javelin-behavior-differential-populate',
5 => 'javelin-behavior-differential-show-more',
6 => 'javelin-behavior-differential-diff-radios',
7 => 'javelin-behavior-differential-accept-with-errors',
8 => 'javelin-behavior-differential-comment-jump',
9 => 'javelin-behavior-differential-add-reviewers-and-ccs',
10 => 'javelin-behavior-differential-keyboard-navigation',
11 => 'javelin-behavior-aphront-drag-and-drop-textarea',
12 => 'javelin-behavior-phabricator-object-selector',
13 => 'javelin-behavior-repository-crossreference',
14 => 'javelin-behavior-load-blame',
15 => 'differential-inline-comment-editor',
16 => 'javelin-behavior-differential-dropdown-menus',
17 => 'javelin-behavior-differential-toggle-files',
18 => 'javelin-behavior-differential-user-select',
),
'diffusion.pkg.css' =>
array(
0 => 'diffusion-commit-view-css',
1 => 'diffusion-icons-css',
),
'diffusion.pkg.js' =>
array(
0 => 'javelin-behavior-diffusion-pull-lastmodified',
1 => 'javelin-behavior-diffusion-commit-graph',
2 => 'javelin-behavior-audit-preview',
),
'javelin.pkg.js' =>
array(
0 => 'javelin-util',
1 => 'javelin-install',
2 => 'javelin-event',
3 => 'javelin-stratcom',
4 => 'javelin-behavior',
5 => 'javelin-resource',
6 => 'javelin-request',
7 => 'javelin-vector',
8 => 'javelin-dom',
9 => 'javelin-json',
10 => 'javelin-uri',
11 => 'javelin-workflow',
12 => 'javelin-mask',
13 => 'javelin-typeahead',
14 => 'javelin-typeahead-normalizer',
15 => 'javelin-typeahead-source',
16 => 'javelin-typeahead-preloaded-source',
17 => 'javelin-typeahead-ondemand-source',
18 => 'javelin-tokenizer',
19 => 'javelin-history',
),
'maniphest.pkg.css' =>
array(
0 => 'maniphest-task-summary-css',
1 => 'phabricator-project-tag-css',
),
'maniphest.pkg.js' =>
array(
0 => 'javelin-behavior-maniphest-batch-selector',
1 => 'javelin-behavior-maniphest-transaction-controls',
2 => 'javelin-behavior-maniphest-transaction-preview',
3 => 'javelin-behavior-maniphest-transaction-expand',
4 => 'javelin-behavior-maniphest-subpriority-editor',
),
),
);
diff --git a/src/applications/config/storage/PhabricatorConfigTransaction.php b/src/applications/config/storage/PhabricatorConfigTransaction.php
index ebfd944252..75c2cc34a3 100644
--- a/src/applications/config/storage/PhabricatorConfigTransaction.php
+++ b/src/applications/config/storage/PhabricatorConfigTransaction.php
@@ -1,121 +1,119 @@
<?php
final class PhabricatorConfigTransaction
extends PhabricatorApplicationTransaction {
const TYPE_EDIT = 'config:edit';
public function getApplicationName() {
return 'config';
}
public function getApplicationTransactionType() {
return PhabricatorConfigPHIDTypeConfig::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_EDIT:
// TODO: After T2213 show the actual values too; for now, we don't
// have the tools to do it without making a bit of a mess of it.
$old_del = idx($old, 'deleted');
$new_del = idx($new, 'deleted');
if ($old_del && !$new_del) {
return pht(
'%s created this configuration entry.',
$this->renderHandleLink($author_phid));
} else if (!$old_del && $new_del) {
return pht(
'%s deleted this configuration entry.',
$this->renderHandleLink($author_phid));
} else if ($old_del && $new_del) {
// This is a bug.
return pht(
'%s deleted this configuration entry (again?).',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s edited this configuration entry.',
$this->renderHandleLink($author_phid));
}
break;
}
return parent::getTitle();
}
public function getIcon() {
switch ($this->getTransactionType()) {
case self::TYPE_EDIT:
return 'edit';
}
return parent::getIcon();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_EDIT:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($old['deleted']) {
$old_text = '';
} else {
$old_text = PhabricatorConfigJSON::prettyPrintJSON($old['value']);
}
if ($new['deleted']) {
$new_text = '';
} else {
$new_text = PhabricatorConfigJSON::prettyPrintJSON($new['value']);
}
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old_text)
- ->setNewText($new_text);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $old_text,
+ $new_text);
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_EDIT:
$old_del = idx($old, 'deleted');
$new_del = idx($new, 'deleted');
if ($old_del && !$new_del) {
return PhabricatorTransactions::COLOR_GREEN;
} else if (!$old_del && $new_del) {
return PhabricatorTransactions::COLOR_RED;
} else {
return PhabricatorTransactions::COLOR_BLUE;
}
break;
}
}
}
diff --git a/src/applications/differential/customfield/DifferentialSummaryField.php b/src/applications/differential/customfield/DifferentialSummaryField.php
index 88f6cb779d..60aa173841 100644
--- a/src/applications/differential/customfield/DifferentialSummaryField.php
+++ b/src/applications/differential/customfield/DifferentialSummaryField.php
@@ -1,69 +1,81 @@
<?php
final class DifferentialSummaryField
extends DifferentialCoreCustomField {
public function getFieldKey() {
return 'differential:summary';
}
public function getFieldName() {
return pht('Summary');
}
public function getFieldDescription() {
return pht('Stores a summary of the revision.');
}
protected function readValueFromRevision(
DifferentialRevision $revision) {
return $revision->getSummary();
}
protected function writeValueToRevision(
DifferentialRevision $revision,
$value) {
$revision->setSummary($value);
}
public function readValueFromRequest(AphrontRequest $request) {
$this->setValue($request->getStr($this->getFieldKey()));
}
public function renderEditControl() {
return id(new PhabricatorRemarkupControl())
->setName($this->getFieldKey())
->setValue($this->getValue())
->setError($this->getFieldError())
->setLabel($this->getFieldName());
}
public function getApplicationTransactionTitle(
PhabricatorApplicationTransaction $xaction) {
$author_phid = $xaction->getAuthorPHID();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
return pht(
'%s updated the summary for this revision.',
$xaction->renderHandleLink($author_phid));
}
public function getApplicationTransactionTitleForFeed(
PhabricatorApplicationTransaction $xaction,
PhabricatorFeedStory $story) {
$object_phid = $xaction->getObjectPHID();
$author_phid = $xaction->getAuthorPHID();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
return pht(
'%s updated the summary for %s.',
$xaction->renderHandleLink($author_phid),
$xaction->renderHandleLink($object_phid));
}
- // TODO: Support hasChangeDetails() in CustomFields.
+ public function getApplicationTransactionHasChangeDetails(
+ PhabricatorApplicationTransaction $xaction) {
+ return true;
+ }
+
+ public function getApplicationTransactionChangeDetails(
+ PhabricatorApplicationTransaction $xaction,
+ PhabricatorUser $viewer) {
+ return $xaction->renderTextCorpusChangeDetails(
+ $viewer,
+ $xaction->getOldValue(),
+ $xaction->getNewValue());
+ }
}
diff --git a/src/applications/legalpad/storage/LegalpadTransaction.php b/src/applications/legalpad/storage/LegalpadTransaction.php
index 9abf15db2d..26cb8b1572 100644
--- a/src/applications/legalpad/storage/LegalpadTransaction.php
+++ b/src/applications/legalpad/storage/LegalpadTransaction.php
@@ -1,82 +1,77 @@
<?php
/**
* @group legalpad
*/
final class LegalpadTransaction extends PhabricatorApplicationTransaction {
public function getApplicationName() {
return 'legalpad';
}
public function getApplicationTransactionType() {
return PhabricatorLegalpadPHIDTypeDocument::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new LegalpadTransactionComment();
}
public function getApplicationTransactionViewObject() {
return new LegalpadTransactionView();
}
public function shouldHide() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case LegalpadTransactionType::TYPE_TITLE:
case LegalpadTransactionType::TYPE_TEXT:
return ($old === null);
}
return parent::shouldHide();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
$type = $this->getTransactionType();
switch ($type) {
case LegalpadTransactionType::TYPE_TITLE:
return pht(
'%s renamed this document from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
break;
case LegalpadTransactionType::TYPE_TEXT:
return pht(
"%s updated the document's text.",
$this->renderHandleLink($author_phid));
break;
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case LegalpadTransactionType::TYPE_TITLE:
case LegalpadTransactionType::TYPE_TEXT:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $this->getOldValue(),
+ $this->getNewValue());
}
}
diff --git a/src/applications/maniphest/storage/ManiphestTransaction.php b/src/applications/maniphest/storage/ManiphestTransaction.php
index 72b76714ba..09a3f936e5 100644
--- a/src/applications/maniphest/storage/ManiphestTransaction.php
+++ b/src/applications/maniphest/storage/ManiphestTransaction.php
@@ -1,677 +1,670 @@
<?php
final class ManiphestTransaction
extends PhabricatorApplicationTransaction {
const TYPE_TITLE = 'title';
const TYPE_STATUS = 'status';
const TYPE_DESCRIPTION = 'description';
const TYPE_OWNER = 'reassign';
const TYPE_CCS = 'ccs';
const TYPE_PROJECTS = 'projects';
const TYPE_PRIORITY = 'priority';
const TYPE_EDGE = 'edge';
const TYPE_ATTACH = 'attach';
public function getApplicationName() {
return 'maniphest';
}
public function getApplicationTransactionType() {
return ManiphestPHIDTypeTask::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new ManiphestTransactionComment();
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$new = $this->getNewValue();
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case self::TYPE_OWNER:
if ($new) {
$phids[] = $new;
}
if ($old) {
$phids[] = $old;
}
break;
case self::TYPE_CCS:
case self::TYPE_PROJECTS:
$phids = array_mergev(
array(
$phids,
nonempty($old, array()),
nonempty($new, array()),
));
break;
case self::TYPE_EDGE:
$phids = array_mergev(
array(
$phids,
array_keys(nonempty($old, array())),
array_keys(nonempty($new, array())),
));
break;
case self::TYPE_ATTACH:
$old = nonempty($old, array());
$new = nonempty($new, array());
$phids = array_mergev(
array(
$phids,
array_keys(idx($new, 'FILE', array())),
array_keys(idx($old, 'FILE', array())),
));
break;
}
return $phids;
}
public function shouldHide() {
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
case self::TYPE_DESCRIPTION:
case self::TYPE_PRIORITY:
if ($this->getOldValue() === null) {
return true;
} else {
return false;
}
break;
}
return false;
}
public function getActionStrength() {
switch ($this->getTransactionType()) {
case self::TYPE_STATUS:
return 1.3;
case self::TYPE_OWNER:
return 1.2;
case self::TYPE_PRIORITY:
return 1.1;
}
return parent::getActionStrength();
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_OWNER:
if ($this->getAuthorPHID() == $new) {
return 'green';
} else if (!$new) {
return 'black';
} else if (!$old) {
return 'green';
} else {
return 'green';
}
case self::TYPE_STATUS:
if ($new == ManiphestTaskStatus::STATUS_OPEN) {
return 'green';
} else {
return 'black';
}
case self::TYPE_PRIORITY:
if ($old == ManiphestTaskPriority::getDefaultPriority()) {
return 'green';
} else if ($old > $new) {
return 'grey';
} else {
return 'yellow';
}
}
return parent::getColor();
}
public function getActionName() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
return pht('Retitled');
case self::TYPE_STATUS:
switch ($new) {
case ManiphestTaskStatus::STATUS_OPEN:
if ($old === null) {
return pht('Created');
} else {
return pht('Reopened');
}
case ManiphestTaskStatus::STATUS_CLOSED_SPITE:
return pht('Spited');
case ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE:
return pht('Merged');
default:
return pht('Closed');
}
case self::TYPE_DESCRIPTION:
return pht('Edited');
case self::TYPE_OWNER:
if ($this->getAuthorPHID() == $new) {
return pht('Claimed');
} else if (!$new) {
return pht('Up For Grabs');
} else if (!$old) {
return pht('Assigned');
} else {
return pht('Reassigned');
}
case self::TYPE_CCS:
return pht('Changed CC');
case self::TYPE_PROJECTS:
return pht('Changed Projects');
case self::TYPE_PRIORITY:
if ($old == ManiphestTaskPriority::getDefaultPriority()) {
return pht('Triaged');
} else if ($old > $new) {
return pht('Lowered Priority');
} else {
return pht('Raised Priority');
}
case self::TYPE_EDGE:
case self::TYPE_ATTACH:
return pht('Attached');
}
return parent::getActionName();
}
public function getIcon() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_OWNER:
return 'user';
case self::TYPE_CCS:
return 'meta-mta';
case self::TYPE_TITLE:
return 'edit';
case self::TYPE_STATUS:
switch ($new) {
case ManiphestTaskStatus::STATUS_OPEN:
return 'create';
case ManiphestTaskStatus::STATUS_CLOSED_SPITE:
return 'dislike';
case ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE:
return 'delete';
default:
return 'check';
}
case self::TYPE_DESCRIPTION:
return 'edit';
case self::TYPE_PROJECTS:
return 'project';
case self::TYPE_PRIORITY:
if ($old == ManiphestTaskPriority::getDefaultPriority()) {
return 'normal-priority';
return pht('Triaged');
} else if ($old > $new) {
return 'lower-priority';
} else {
return 'raise-priority';
}
case self::TYPE_EDGE:
case self::TYPE_ATTACH:
return 'attach';
}
return parent::getIcon();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
return pht(
'%s changed the title from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
case self::TYPE_DESCRIPTION:
return pht(
'%s edited the task description.',
$this->renderHandleLink($author_phid));
case self::TYPE_STATUS:
switch ($new) {
case ManiphestTaskStatus::STATUS_OPEN:
if ($old === null) {
return pht(
'%s created this task.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s reopened this task.',
$this->renderHandleLink($author_phid));
}
case ManiphestTaskStatus::STATUS_CLOSED_SPITE:
return pht(
'%s closed this task out of spite.',
$this->renderHandleLink($author_phid));
case ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE:
return pht(
'%s closed this task as a duplicate.',
$this->renderHandleLink($author_phid));
default:
$status_name = idx(
ManiphestTaskStatus::getTaskStatusMap(),
$new,
'???');
return pht(
'%s closed this task as "%s".',
$this->renderHandleLink($author_phid),
$status_name);
}
case self::TYPE_OWNER:
if ($author_phid == $new) {
return pht(
'%s claimed this task.',
$this->renderHandleLink($author_phid));
} else if (!$new) {
return pht(
'%s placed this task up for grabs.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s assigned this task to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($new));
} else {
return pht(
'%s reassigned this task from %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
case self::TYPE_PROJECTS:
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
if ($added && !$removed) {
return pht(
'%s added %d project(s): %s',
$this->renderHandleLink($author_phid),
count($added),
$this->renderHandleList($added));
} else if ($removed && !$added) {
return pht(
'%s removed %d project(s): %s',
$this->renderHandleLink($author_phid),
count($removed),
$this->renderHandleList($removed));
} else if ($removed && $added) {
return pht(
'%s changed project(s), added %d: %s; removed %d: %s',
$this->renderHandleLink($author_phid),
count($added),
$this->renderHandleList($added),
count($removed),
$this->renderHandleList($removed));
} else {
// This is hit when rendering previews.
return pht(
'%s changed projects...',
$this->renderHandleLink($author_phid));
}
case self::TYPE_PRIORITY:
$old_name = ManiphestTaskPriority::getTaskPriorityName($old);
$new_name = ManiphestTaskPriority::getTaskPriorityName($new);
if ($old == ManiphestTaskPriority::getDefaultPriority()) {
return pht(
'%s triaged this task as "%s" priority.',
$this->renderHandleLink($author_phid),
$new_name);
} else if ($old > $new) {
return pht(
'%s lowered the priority of this task from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old_name,
$new_name);
} else {
return pht(
'%s raised the priority of this task from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old_name,
$new_name);
}
case self::TYPE_CCS:
// TODO: Remove this when we switch to subscribers. Just reuse the
// code in the parent.
$clone = clone $this;
$clone->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS);
return $clone->getTitle();
case self::TYPE_EDGE:
// TODO: Remove this when we switch to real edges. Just reuse the
// code in the parent;
$clone = clone $this;
$clone->setTransactionType(PhabricatorTransactions::TYPE_EDGE);
return $clone->getTitle();
case self::TYPE_ATTACH:
$old = nonempty($old, array());
$new = nonempty($new, array());
$new = array_keys(idx($new, 'FILE', array()));
$old = array_keys(idx($old, 'FILE', array()));
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
if ($added && !$removed) {
return pht(
'%s attached %d file(s): %s',
$this->renderHandleLink($author_phid),
count($added),
$this->renderHandleList($added));
} else if ($removed && !$added) {
return pht(
'%s detached %d file(s): %s',
$this->renderHandleLink($author_phid),
count($removed),
$this->renderHandleList($removed));
} else {
return pht(
'%s changed file(s), attached %d: %s; detached %d: %s',
$this->renderHandleLink($author_phid),
count($added),
$this->renderHandleList($added),
count($removed),
$this->renderHandleList($removed));
}
}
return parent::getTitle();
}
public function getTitleForFeed(PhabricatorFeedStory $story) {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
return pht(
'%s renamed %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$old,
$new);
case self::TYPE_DESCRIPTION:
return pht(
'%s edited the description of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case self::TYPE_STATUS:
switch ($new) {
case ManiphestTaskStatus::STATUS_OPEN:
if ($old === null) {
return pht(
'%s created %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s reopened %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
case ManiphestTaskStatus::STATUS_CLOSED_SPITE:
return pht(
'%s closed %s out of spite.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE:
return pht(
'%s closed %s as a duplicate.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
default:
$status_name = idx(
ManiphestTaskStatus::getTaskStatusMap(),
$new,
'???');
return pht(
'%s closed %s as "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$status_name);
}
case self::TYPE_OWNER:
if ($author_phid == $new) {
return pht(
'%s claimed %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else if (!$new) {
return pht(
'%s placed %s up for grabs.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else if (!$old) {
return pht(
'%s assigned %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$this->renderHandleLink($new));
} else {
return pht(
'%s reassigned %s from %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
case self::TYPE_PROJECTS:
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
if ($added && !$removed) {
return pht(
'%s added %d project(s) to %s: %s',
$this->renderHandleLink($author_phid),
count($added),
$this->renderHandleLink($object_phid),
$this->renderHandleList($added));
} else if ($removed && !$added) {
return pht(
'%s removed %d project(s) from %s: %s',
$this->renderHandleLink($author_phid),
count($removed),
$this->renderHandleLink($object_phid),
$this->renderHandleList($removed));
} else if ($removed && $added) {
return pht(
'%s changed project(s) of %s, added %d: %s; removed %d: %s',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
count($added),
$this->renderHandleList($added),
count($removed),
$this->renderHandleList($removed));
}
case self::TYPE_PRIORITY:
$old_name = ManiphestTaskPriority::getTaskPriorityName($old);
$new_name = ManiphestTaskPriority::getTaskPriorityName($new);
if ($old == ManiphestTaskPriority::getDefaultPriority()) {
return pht(
'%s triaged %s as "%s" priority.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$new_name);
} else if ($old > $new) {
return pht(
'%s lowered the priority of %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$old_name,
$new_name);
} else {
return pht(
'%s raised the priority of %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$old_name,
$new_name);
}
case self::TYPE_CCS:
// TODO: Remove this when we switch to subscribers. Just reuse the
// code in the parent.
$clone = clone $this;
$clone->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS);
return $clone->getTitleForFeed($story);
case self::TYPE_EDGE:
// TODO: Remove this when we switch to real edges. Just reuse the
// code in the parent;
$clone = clone $this;
$clone->setTransactionType(PhabricatorTransactions::TYPE_EDGE);
return $clone->getTitleForFeed($story);
case self::TYPE_ATTACH:
$old = nonempty($old, array());
$new = nonempty($new, array());
$new = array_keys(idx($new, 'FILE', array()));
$old = array_keys(idx($old, 'FILE', array()));
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
if ($added && !$removed) {
return pht(
'%s attached %d file(s) of %s: %s',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
count($added),
$this->renderHandleList($added));
} else if ($removed && !$added) {
return pht(
'%s detached %d file(s) of %s: %s',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
count($removed),
$this->renderHandleList($removed));
} else {
return pht(
'%s changed file(s) for %s, attached %d: %s; detached %d: %s',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
count($added),
$this->renderHandleList($added),
count($removed),
$this->renderHandleList($removed));
}
}
return parent::getTitleForFeed($story);
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- require_celerity_resource('differential-changeset-view-css');
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $this->getOldValue(),
+ $this->getNewValue());
}
public function getMailTags() {
$tags = array();
switch ($this->getTransactionType()) {
case self::TYPE_STATUS:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_STATUS;
break;
case self::TYPE_OWNER:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_OWNER;
break;
case self::TYPE_CCS:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_CC;
break;
case self::TYPE_PROJECTS:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_PROJECTS;
break;
case self::TYPE_PRIORITY:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_PRIORITY;
break;
case PhabricatorTransactions::TYPE_COMMENT:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_COMMENT;
break;
default:
$tags[] = MetaMTANotificationType::TYPE_MANIPHEST_OTHER;
break;
}
return $tags;
}
}
diff --git a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php
index 52739a4808..2303ea39ac 100644
--- a/src/applications/passphrase/storage/PassphraseCredentialTransaction.php
+++ b/src/applications/passphrase/storage/PassphraseCredentialTransaction.php
@@ -1,106 +1,101 @@
<?php
final class PassphraseCredentialTransaction
extends PhabricatorApplicationTransaction {
const TYPE_NAME = 'passphrase:name';
const TYPE_DESCRIPTION = 'passphrase:description';
const TYPE_USERNAME = 'passphrase:username';
const TYPE_SECRET_ID = 'passphrase:secretID';
const TYPE_DESTROY = 'passphrase:destroy';
public function getApplicationName() {
return 'passphrase';
}
public function getApplicationTransactionType() {
return PassphrasePHIDTypeCredential::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function shouldHide() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return ($old === null);
case self::TYPE_USERNAME:
return !strlen($old);
}
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:
return pht(
'%s updated the secret for this credential.',
$this->renderHandleLink($author_phid));
case self::TYPE_DESTROY:
return pht(
'%s destroyed this credential.',
$this->renderHandleLink($author_phid));
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText(json_encode($old))
- ->setNewText(json_encode($new));
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ json_encode($this->getOldValue()),
+ json_encode($this->getNewValue()));
}
}
diff --git a/src/applications/phlux/storage/PhluxTransaction.php b/src/applications/phlux/storage/PhluxTransaction.php
index 1835796620..9cac59fbec 100644
--- a/src/applications/phlux/storage/PhluxTransaction.php
+++ b/src/applications/phlux/storage/PhluxTransaction.php
@@ -1,58 +1,53 @@
<?php
final class PhluxTransaction extends PhabricatorApplicationTransaction {
const TYPE_EDIT_KEY = 'phlux:key';
const TYPE_EDIT_VALUE = 'phlux:value';
public function getApplicationName() {
return 'phlux';
}
public function getApplicationTransactionType() {
return PhluxPHIDTypeVariable::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
switch ($this->getTransactionType()) {
case self::TYPE_EDIT_KEY:
return pht(
'%s created this variable.',
$this->renderHandleLink($author_phid));
case self::TYPE_EDIT_VALUE:
return pht(
'%s updated this variable.',
$this->renderHandleLink($author_phid));
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_EDIT_VALUE:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText(json_encode($old))
- ->setNewText(json_encode($new));
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ json_encode($this->getOldValue()),
+ json_encode($this->getNewValue()));
}
}
diff --git a/src/applications/pholio/storage/PholioTransaction.php b/src/applications/pholio/storage/PholioTransaction.php
index c20865b914..d65414f098 100644
--- a/src/applications/pholio/storage/PholioTransaction.php
+++ b/src/applications/pholio/storage/PholioTransaction.php
@@ -1,337 +1,335 @@
<?php
final class PholioTransaction extends PhabricatorApplicationTransaction {
public function getApplicationName() {
return 'pholio';
}
public function getApplicationTransactionType() {
return PholioPHIDTypeMock::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new PholioTransactionComment();
}
public function getApplicationTransactionViewObject() {
return new PholioTransactionView();
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$phids[] = $this->getObjectPHID();
$new = $this->getNewValue();
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_IMAGE_FILE:
$phids = array_merge($phids, $new, $old);
break;
case PholioTransactionType::TYPE_IMAGE_REPLACE:
$phids[] = $new;
$phids[] = $old;
break;
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
case PholioTransactionType::TYPE_IMAGE_NAME:
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
$phids[] = key($new);
break;
}
return $phids;
}
public function shouldHide() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_DESCRIPTION:
return ($old === null);
case PholioTransactionType::TYPE_IMAGE_NAME:
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
return ($old === array(null => null));
// this is boring / silly to surface; changing sequence is NBD
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
return true;
}
return parent::shouldHide();
}
public function getIcon() {
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_INLINE:
return 'comment';
case PholioTransactionType::TYPE_NAME:
case PholioTransactionType::TYPE_DESCRIPTION:
case PholioTransactionType::TYPE_IMAGE_NAME:
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
return 'edit';
case PholioTransactionType::TYPE_IMAGE_FILE:
case PholioTransactionType::TYPE_IMAGE_REPLACE:
return 'attach';
}
return parent::getIcon();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
$type = $this->getTransactionType();
switch ($type) {
case PholioTransactionType::TYPE_NAME:
if ($old === null) {
return pht(
'%s created "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s renamed this mock from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case PholioTransactionType::TYPE_DESCRIPTION:
return pht(
"%s updated the mock's description.",
$this->renderHandleLink($author_phid));
break;
case PholioTransactionType::TYPE_INLINE:
$count = 1;
foreach ($this->getTransactionGroup() as $xaction) {
if ($xaction->getTransactionType() == $type) {
$count++;
}
}
return pht(
'%s added %d inline comment(s).',
$this->renderHandleLink($author_phid),
$count);
break;
case PholioTransactionType::TYPE_IMAGE_REPLACE:
return pht(
'%s replaced %s with %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
break;
case PholioTransactionType::TYPE_IMAGE_FILE:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
return pht(
'%s edited image(s), added %d: %s; removed %d: %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add),
count($rem),
$this->renderHandleList($rem));
} else if ($add) {
return pht(
'%s added %d image(s): %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add));
} else {
return pht(
'%s removed %d image(s): %s.',
$this->renderHandleLink($author_phid),
count($rem),
$this->renderHandleList($rem));
}
break;
case PholioTransactionType::TYPE_IMAGE_NAME:
return pht(
'%s renamed an image (%s) from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(key($new)),
reset($old),
reset($new));
break;
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
return pht(
'%s updated an image\'s (%s) description.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(key($new)));
break;
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
return pht(
'%s updated an image\'s (%s) sequence.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink(key($new)));
break;
}
return parent::getTitle();
}
public function getTitleForFeed(PhabricatorFeedStory $story) {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
$type = $this->getTransactionType();
switch ($type) {
case PholioTransactionType::TYPE_NAME:
if ($old === null) {
return pht(
'%s created %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
} else {
return pht(
'%s renamed %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid),
$old,
$new);
}
break;
case PholioTransactionType::TYPE_DESCRIPTION:
return pht(
'%s updated the description for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case PholioTransactionType::TYPE_INLINE:
return pht(
'%s added an inline comment to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case PholioTransactionType::TYPE_IMAGE_REPLACE:
case PholioTransactionType::TYPE_IMAGE_FILE:
return pht(
'%s updated images of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case PholioTransactionType::TYPE_IMAGE_NAME:
return pht(
'%s updated the image names of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
return pht(
'%s updated image descriptions of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
return pht(
'%s updated image sequence of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
break;
}
return parent::getTitleForFeed($story);
}
public function getBodyForFeed(PhabricatorFeedStory $story) {
$text = null;
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_NAME:
if ($this->getOldValue() === null) {
$mock = $story->getPrimaryObject();
$text = $mock->getDescription();
}
break;
case PholioTransactionType::TYPE_INLINE:
$text = $this->getComment()->getContent();
break;
}
if ($text) {
return phutil_escape_html_newlines(
phutil_utf8_shorten($text, 128));
}
return parent::getBodyForFeed($story);
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_DESCRIPTION:
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
$old = $this->getOldValue();
$new = $this->getNewValue();
if ($this->getTransactionType() ==
PholioTransactionType::TYPE_IMAGE_DESCRIPTION) {
$old = reset($old);
$new = reset($new);
}
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $old,
+ $new);
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_NAME:
if ($old === null) {
return PhabricatorTransactions::COLOR_GREEN;
}
case PholioTransactionType::TYPE_DESCRIPTION:
case PholioTransactionType::TYPE_IMAGE_NAME:
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
return PhabricatorTransactions::COLOR_BLUE;
case PholioTransactionType::TYPE_IMAGE_REPLACE:
return PhabricatorTransactions::COLOR_YELLOW;
case PholioTransactionType::TYPE_IMAGE_FILE:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
return PhabricatorTransactions::COLOR_YELLOW;
} else if ($add) {
return PhabricatorTransactions::COLOR_GREEN;
} else {
return PhabricatorTransactions::COLOR_RED;
}
}
return parent::getColor();
}
public function getNoEffectDescription() {
switch ($this->getTransactionType()) {
case PholioTransactionType::TYPE_IMAGE_NAME:
return pht('The image title was not updated.');
case PholioTransactionType::TYPE_IMAGE_DESCRIPTION:
return pht('The image description was not updated.');
case PholioTransactionType::TYPE_IMAGE_SEQUENCE:
return pht('The image sequence was not updated.');
}
return parent::getNoEffectDescription();
}
}
diff --git a/src/applications/ponder/storage/PonderAnswerTransaction.php b/src/applications/ponder/storage/PonderAnswerTransaction.php
index aaffe9102f..f12303b3a7 100644
--- a/src/applications/ponder/storage/PonderAnswerTransaction.php
+++ b/src/applications/ponder/storage/PonderAnswerTransaction.php
@@ -1,110 +1,105 @@
<?php
final class PonderAnswerTransaction
extends PhabricatorApplicationTransaction {
const TYPE_CONTENT = 'ponder.answer:content';
public function getApplicationName() {
return 'ponder';
}
public function getTableName() {
return 'ponder_answertransaction';
}
public function getApplicationTransactionType() {
return PonderPHIDTypeAnswer::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new PonderAnswerTransactionComment();
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
$phids[] = $this->getObjectPHID();
break;
}
return $phids;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
return pht(
'%s edited %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
return parent::getTitle();
}
public function getTitleForFeed(PhabricatorFeedStory $story) {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
$answer = $story->getObject($object_phid);
$question = $answer->getQuestion();
$answer_handle = $this->getHandle($object_phid);
$link = $answer_handle->renderLink(
$question->getFullTitle());
return pht(
'%s updated their answer to %s',
$this->renderHandleLink($author_phid),
$link);
}
return parent::getTitleForFeed($story);
}
public function getBodyForFeed(PhabricatorFeedStory $story) {
$new = $this->getNewValue();
$body = null;
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
return phutil_escape_html_newlines(
phutil_utf8_shorten($new, 128));
break;
}
return parent::getBodyForFeed($story);
}
public function hasChangeDetails() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
return $old !== null;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $this->getOldValue(),
+ $this->getNewValue());
}
}
diff --git a/src/applications/ponder/storage/PonderQuestionTransaction.php b/src/applications/ponder/storage/PonderQuestionTransaction.php
index 3218a01f8a..a1ed5d47cc 100644
--- a/src/applications/ponder/storage/PonderQuestionTransaction.php
+++ b/src/applications/ponder/storage/PonderQuestionTransaction.php
@@ -1,311 +1,306 @@
<?php
final class PonderQuestionTransaction
extends PhabricatorApplicationTransaction {
const TYPE_TITLE = 'ponder.question:question';
const TYPE_CONTENT = 'ponder.question:content';
const TYPE_ANSWERS = 'ponder.question:answer';
const TYPE_STATUS = 'ponder.question:status';
public function getApplicationName() {
return 'ponder';
}
public function getTableName() {
return 'ponder_questiontransaction';
}
public function getApplicationTransactionType() {
return PonderPHIDTypeQuestion::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new PonderQuestionTransactionComment();
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
switch ($this->getTransactionType()) {
case self::TYPE_ANSWERS:
$phids[] = $this->getNewAnswerPHID();
$phids[] = $this->getObjectPHID();
break;
}
return $phids;
}
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_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 this question.',
$this->renderHandleLink($author_phid));
case PonderQuestionStatus::STATUS_CLOSED:
return pht(
'%s closed this question.',
$this->renderHandleLink($author_phid));
}
}
return parent::getTitle();
}
public function getIcon() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
case self::TYPE_CONTENT:
return 'edit';
case self::TYPE_STATUS:
switch ($new) {
case PonderQuestionStatus::STATUS_OPEN:
return 'enable';
case PonderQuestionStatus::STATUS_CLOSED:
return 'disable';
}
case self::TYPE_ANSWERS:
return 'new';
}
return parent::getIcon();
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
case self::TYPE_CONTENT:
return PhabricatorTransactions::COLOR_BLUE;
case self::TYPE_ANSWERS:
return PhabricatorTransactions::COLOR_GREEN;
case self::TYPE_STATUS:
switch ($new) {
case PonderQuestionStatus::STATUS_OPEN:
return PhabricatorTransactions::COLOR_GREEN;
case PonderQuestionStatus::STATUS_CLOSED:
return PhabricatorTransactions::COLOR_BLACK;
}
}
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ 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 shouldHide() {
switch ($this->getTransactionType()) {
case self::TYPE_CONTENT:
if ($this->getOldValue() === null) {
return true;
} else {
return false;
}
break;
}
return parent::shouldHide();
}
public function getTitleForFeed(PhabricatorFeedStory $story) {
$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_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:
return pht(
'%s closed %s',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
}
return parent::getTitleForFeed($story);
}
public function getBodyForFeed(PhabricatorFeedStory $story) {
$new = $this->getNewValue();
$old = $this->getOldValue();
$body = null;
switch ($this->getTransactionType()) {
case self::TYPE_TITLE:
if ($old === null) {
$question = $story->getObject($this->getObjectPHID());
return phutil_escape_html_newlines(
phutil_utf8_shorten($question->getContent(), 128));
}
break;
case self::TYPE_ANSWERS:
$answer = $this->getNewAnswerObject($story);
if ($answer) {
return phutil_escape_html_newlines(
phutil_utf8_shorten($answer->getContent(), 128));
}
break;
}
return parent::getBodyForFeed($story);
}
/**
* 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(
'There should be only one answer added at a time.');
}
return reset($add);
}
/**
* Generally, the answer object is only available if the transaction
* type is self::TYPE_ANSWERS.
*
* Some stories - notably ones made before D7027 - will be of the more
* generic @{class:PhabricatorApplicationTransactionFeedStory}. These
* poor stories won't have the PonderAnswer loaded, and thus will have
* less cool information.
*/
private function getNewAnswerObject(PhabricatorFeedStory $story) {
if ($story instanceof PonderTransactionFeedStory) {
$answer_phid = $this->getNewAnswerPHID();
if ($answer_phid) {
return $story->getObject($answer_phid);
}
}
return null;
}
}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryTransaction.php b/src/applications/repository/storage/PhabricatorRepositoryTransaction.php
index c29aafde9b..446dcb19e6 100644
--- a/src/applications/repository/storage/PhabricatorRepositoryTransaction.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryTransaction.php
@@ -1,396 +1,391 @@
<?php
final class PhabricatorRepositoryTransaction
extends PhabricatorApplicationTransaction {
const TYPE_VCS = 'repo:vcs';
const TYPE_ACTIVATE = 'repo:activate';
const TYPE_NAME = 'repo:name';
const TYPE_DESCRIPTION = 'repo:description';
const TYPE_ENCODING = 'repo:encoding';
const TYPE_DEFAULT_BRANCH = 'repo:default-branch';
const TYPE_TRACK_ONLY = 'repo:track-only';
const TYPE_AUTOCLOSE_ONLY = 'repo:autoclose-only';
const TYPE_SVN_SUBPATH = 'repo:svn-subpath';
const TYPE_UUID = 'repo:uuid';
const TYPE_NOTIFY = 'repo:notify';
const TYPE_AUTOCLOSE = 'repo:autoclose';
const TYPE_REMOTE_URI = 'repo:remote-uri';
const TYPE_LOCAL_PATH = 'repo:local-path';
const TYPE_HOSTING = 'repo:hosting';
const TYPE_PROTOCOL_HTTP = 'repo:serve-http';
const TYPE_PROTOCOL_SSH = 'repo:serve-ssh';
const TYPE_PUSH_POLICY = 'repo:push-policy';
const TYPE_CREDENTIAL = 'repo:credential';
const TYPE_DANGEROUS = 'repo:dangerous';
const TYPE_CLONE_NAME = 'repo:clone-name';
// TODO: Clean up these legacy transaction types.
const TYPE_SSH_LOGIN = 'repo:ssh-login';
const TYPE_SSH_KEY = 'repo:ssh-key';
const TYPE_SSH_KEYFILE = 'repo:ssh-keyfile';
const TYPE_HTTP_LOGIN = 'repo:http-login';
const TYPE_HTTP_PASS = 'repo:http-pass';
public function getApplicationName() {
return 'repository';
}
public function getApplicationTransactionType() {
return PhabricatorRepositoryPHIDTypeRepository::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_PUSH_POLICY:
$phids[] = $old;
$phids[] = $new;
break;
}
return $phids;
}
public function shouldHide() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_REMOTE_URI:
case self::TYPE_SSH_LOGIN:
case self::TYPE_SSH_KEY:
case self::TYPE_SSH_KEYFILE:
case self::TYPE_HTTP_LOGIN:
case self::TYPE_HTTP_PASS:
// Hide null vs empty string changes.
return (!strlen($old) && !strlen($new));
case self::TYPE_LOCAL_PATH:
case self::TYPE_NAME:
// Hide these on create, they aren't interesting and we have an
// explicit "create" transaction.
if (!strlen($old)) {
return true;
}
break;
}
return parent::shouldHide();
}
public function getIcon() {
switch ($this->getTransactionType()) {
case self::TYPE_VCS:
return 'create';
}
return parent::getIcon();
}
public function getColor() {
switch ($this->getTransactionType()) {
case self::TYPE_VCS:
return 'green';
}
return parent::getIcon();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_VCS:
return pht(
'%s created this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_ACTIVATE:
if ($new) {
return pht(
'%s activated this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s deactivated this repository.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_NAME:
return pht(
'%s renamed this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the description of this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_ENCODING:
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the "%s" encoding configured for this repository.',
$this->renderHandleLink($author_phid),
$old);
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the encoding for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the repository encoding from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
case self::TYPE_DEFAULT_BRANCH:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the default branch.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the default branch to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the default branch from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_TRACK_ONLY:
if (!$new) {
return pht(
'%s set this repository to track all branches.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s set this repository to track branches: %s.',
$this->renderHandleLink($author_phid),
implode(', ', $new));
} else {
return pht(
'%s changed track branches from "%s" to "%s".',
$this->renderHandleLink($author_phid),
implode(', ', $old),
implode(', ', $new));
}
break;
case self::TYPE_AUTOCLOSE_ONLY:
if (!$new) {
return pht(
'%s set this repository to autoclose on all branches.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s set this repository to autoclose on branches: %s.',
$this->renderHandleLink($author_phid),
implode(', ', $new));
} else {
return pht(
'%s changed autoclose branches from "%s" to "%s".',
$this->renderHandleLink($author_phid),
implode(', ', $old),
implode(', ', $new));
}
break;
case self::TYPE_UUID:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the repository UUID.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the repository UUID to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the repository UUID from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_SVN_SUBPATH:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the Import Only path.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the repository to import only "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the import path from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_NOTIFY:
if ($new) {
return pht(
'%s enabled notifications and publishing for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled notifications and publishing for this repository.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_AUTOCLOSE:
if ($new) {
return pht(
'%s enabled autoclose for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled autoclose for this repository.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_REMOTE_URI:
if (!strlen($old)) {
return pht(
'%s set the remote URI for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else if (!strlen($new)) {
return pht(
'%s removed the remote URI for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s changed the remote URI for this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_SSH_LOGIN:
return pht(
'%s updated the SSH login for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_SSH_KEY:
return pht(
'%s updated the SSH key for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_SSH_KEYFILE:
return pht(
'%s updated the SSH keyfile for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_HTTP_LOGIN:
return pht(
'%s updated the HTTP login for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_HTTP_PASS:
return pht(
'%s updated the HTTP password for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_LOCAL_PATH:
return pht(
'%s changed the local path from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
case self::TYPE_HOSTING:
if ($new) {
return pht(
'%s changed this repository to be hosted on Phabricator.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s changed this repository to track a remote elsewhere.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_PROTOCOL_HTTP:
return pht(
'%s changed the availability of this repository over HTTP from '.
'"%s" to "%s".',
$this->renderHandleLink($author_phid),
PhabricatorRepository::getProtocolAvailabilityName($old),
PhabricatorRepository::getProtocolAvailabilityName($new));
case self::TYPE_PROTOCOL_SSH:
return pht(
'%s changed the availability of this repository over SSH from '.
'"%s" to "%s".',
$this->renderHandleLink($author_phid),
PhabricatorRepository::getProtocolAvailabilityName($old),
PhabricatorRepository::getProtocolAvailabilityName($new));
case self::TYPE_PUSH_POLICY:
return pht(
'%s changed the push policy of this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->renderPolicyName($old),
$this->renderPolicyName($new));
case self::TYPE_DANGEROUS:
if ($new) {
return pht(
'%s disabled protection against dangerous changes.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s enabled protection against dangerous changes.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_CLONE_NAME:
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the clone name of this repository.',
$this->renderHandleLink($author_phid));
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the clone name of this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the clone name of this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails(
+ $viewer,
+ $this->getOldValue(),
+ $this->getNewValue());
}
}
diff --git a/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php b/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php
index bdd04c8540..9370ea361a 100644
--- a/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php
+++ b/src/applications/slowvote/storage/PhabricatorSlowvoteTransaction.php
@@ -1,135 +1,127 @@
<?php
final class PhabricatorSlowvoteTransaction
extends PhabricatorApplicationTransaction {
const TYPE_QUESTION = 'vote:question';
const TYPE_DESCRIPTION = 'vote:description';
const TYPE_RESPONSES = 'vote:responses';
const TYPE_SHUFFLE = 'vote:shuffle';
public function getApplicationName() {
return 'slowvote';
}
public function getApplicationTransactionType() {
return PhabricatorSlowvotePHIDTypePoll::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return new PhabricatorSlowvoteTransactionComment();
}
public function shouldHide() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
return ($old === null);
}
return parent::shouldHide();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorSlowvoteTransaction::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 PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
return pht(
'%s updated the description for this poll.',
$this->renderHandleLink($author_phid));
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
// TODO: This could be more detailed
return pht(
'%s changed who can see the responses.',
$this->renderHandleLink($author_phid));
case PhabricatorSlowvoteTransaction::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;
}
return parent::getTitle();
}
public function getIcon() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorSlowvoteTransaction::TYPE_QUESTION:
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
return 'edit';
}
return parent::getIcon();
}
public function getColor() {
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorSlowvoteTransaction::TYPE_QUESTION:
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
case PhabricatorSlowvoteTransaction::TYPE_RESPONSES:
case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE:
return PhabricatorTransactions::COLOR_BLUE;
}
return parent::getColor();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case PhabricatorSlowvoteTransaction::TYPE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- $old = $this->getOldValue();
- $new = $this->getNewValue();
-
- $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
- ->setUser($viewer)
- ->setOldText($old)
- ->setNewText($new);
-
- return $view->render();
+ return $this->renderTextCorpusChangeDetails($viewer);
}
}
diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
index e378860aa5..2b4b282d76 100644
--- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
+++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
@@ -1,625 +1,670 @@
<?php
abstract class PhabricatorApplicationTransaction
extends PhabricatorLiskDAO
implements PhabricatorPolicyInterface {
const TARGET_TEXT = 'text';
const TARGET_HTML = 'html';
protected $phid;
protected $objectPHID;
protected $authorPHID;
protected $viewPolicy;
protected $editPolicy;
protected $commentPHID;
protected $commentVersion = 0;
protected $transactionType;
protected $oldValue;
protected $newValue;
protected $metadata = array();
protected $contentSource;
private $comment;
private $commentNotLoaded;
private $handles;
private $renderingTarget = self::TARGET_HTML;
private $transactionGroup = array();
private $viewer = self::ATTACHABLE;
private $object = self::ATTACHABLE;
abstract public function getApplicationTransactionType();
private function getApplicationObjectTypeName() {
$types = PhabricatorPHIDType::getAllTypes();
$type = idx($types, $this->getApplicationTransactionType());
if ($type) {
return $type->getTypeName();
}
return pht('Object');
}
public function getApplicationTransactionCommentObject() {
throw new Exception("Not implemented!");
}
public function getApplicationTransactionViewObject() {
return new PhabricatorApplicationTransactionView();
}
public function getMetadataValue($key, $default = null) {
return idx($this->metadata, $key, $default);
}
public function setMetadataValue($key, $value) {
$this->metadata[$key] = $value;
return $this;
}
public function generatePHID() {
$type = PhabricatorApplicationTransactionPHIDTypeTransaction::TYPECONST;
$subtype = $this->getApplicationTransactionType();
return PhabricatorPHID::generateNewPHID($type, $subtype);
}
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'oldValue' => self::SERIALIZATION_JSON,
'newValue' => self::SERIALIZATION_JSON,
'metadata' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function setContentSource(PhabricatorContentSource $content_source) {
$this->contentSource = $content_source->serialize();
return $this;
}
public function getContentSource() {
return PhabricatorContentSource::newFromSerialized($this->contentSource);
}
public function hasComment() {
return $this->getComment() && strlen($this->getComment()->getContent());
}
public function getComment() {
if ($this->commentNotLoaded) {
throw new Exception("Comment for this transaction was not loaded.");
}
return $this->comment;
}
public function attachComment(
PhabricatorApplicationTransactionComment $comment) {
$this->comment = $comment;
$this->commentNotLoaded = false;
return $this;
}
public function setCommentNotLoaded($not_loaded) {
$this->commentNotLoaded = $not_loaded;
return $this;
}
public function attachObject($object) {
$this->object = $object;
return $this;
}
public function getObject() {
return $this->assertAttached($this->object);
}
/* -( Rendering )---------------------------------------------------------- */
public function setRenderingTarget($rendering_target) {
$this->renderingTarget = $rendering_target;
return $this;
}
public function getRenderingTarget() {
return $this->renderingTarget;
}
public function attachViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
return $this->assertAttached($this->viewer);
}
public function getRequiredHandlePHIDs() {
$phids = array();
$old = $this->getOldValue();
$new = $this->getNewValue();
$phids[] = array($this->getAuthorPHID());
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$phids[] = $old;
$phids[] = $new;
break;
case PhabricatorTransactions::TYPE_EDGE:
$phids[] = ipull($old, 'dst');
$phids[] = ipull($new, 'dst');
break;
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
if (!PhabricatorPolicyQuery::isGlobalPolicy($old)) {
$phids[] = array($old);
}
if (!PhabricatorPolicyQuery::isGlobalPolicy($new)) {
$phids[] = array($new);
}
break;
}
return array_mergev($phids);
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function getHandle($phid) {
if (empty($this->handles[$phid])) {
throw new Exception(
"Transaction requires a handle ('{$phid}') it did not load.");
}
return $this->handles[$phid];
}
public function getHandleIfExists($phid) {
return idx($this->handles, $phid);
}
public function getHandles() {
if ($this->handles === null) {
throw new Exception(
'Transaction requires handles and it did not load them.'
);
}
return $this->handles;
}
public function renderHandleLink($phid) {
if ($this->renderingTarget == self::TARGET_HTML) {
return $this->getHandle($phid)->renderLink();
} else {
return $this->getHandle($phid)->getLinkName();
}
}
public function renderHandleList(array $phids) {
$links = array();
foreach ($phids as $phid) {
$links[] = $this->renderHandleLink($phid);
}
if ($this->renderingTarget == self::TARGET_HTML) {
return phutil_implode_html(', ', $links);
} else {
return implode(', ', $links);
}
}
public function renderPolicyName($phid) {
$policy = PhabricatorPolicy::newFromPolicyAndHandle(
$phid,
$this->getHandleIfExists($phid));
if ($this->renderingTarget == self::TARGET_HTML) {
$output = $policy->renderDescription();
} else {
$output = hsprintf('%s', $policy->getFullName());
}
return $output;
}
public function getIcon() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
return 'comment';
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
return 'message';
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
return 'lock';
case PhabricatorTransactions::TYPE_EDGE:
return 'link';
}
return 'edit';
}
public function getColor() {
return null;
}
+ protected function getTransactionCustomField() {
+ switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_CUSTOMFIELD:
+ $key = $this->getMetadataValue('customfield:key');
+ if (!$key) {
+ return null;
+ }
+
+ $field = PhabricatorCustomField::getObjectField(
+ $this->getObject(),
+ PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS,
+ $key);
+ if (!$field) {
+ return null;
+ }
+
+ $field->setViewer($this->getViewer());
+ return $field;
+ }
+
+ return null;
+ }
+
public function shouldHide() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
if ($this->getOldValue() === null) {
return true;
} else {
return false;
}
break;
}
return false;
}
public function shouldHideForMail() {
return $this->shouldHide();
}
public function getNoEffectDescription() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
return pht('You can not post an empty comment.');
case PhabricatorTransactions::TYPE_VIEW_POLICY:
return pht(
'This %s already has that view policy.',
$this->getApplicationObjectTypeName());
case PhabricatorTransactions::TYPE_EDIT_POLICY:
return pht(
'This %s already has that edit policy.',
$this->getApplicationObjectTypeName());
case PhabricatorTransactions::TYPE_JOIN_POLICY:
return pht(
'This %s already has that join policy.',
$this->getApplicationObjectTypeName());
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
return pht(
'All users are already subscribed to this %s.',
$this->getApplicationObjectTypeName());
case PhabricatorTransactions::TYPE_EDGE:
return pht('Edges already exist; transaction has no effect.');
}
return pht('Transaction has no effect.');
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
return pht(
'%s added a comment.',
$this->renderHandleLink($author_phid));
case PhabricatorTransactions::TYPE_VIEW_POLICY:
return pht(
'%s changed the visibility of this %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->getApplicationObjectTypeName(),
$this->renderPolicyName($old),
$this->renderPolicyName($new));
case PhabricatorTransactions::TYPE_EDIT_POLICY:
return pht(
'%s changed the edit policy of this %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->getApplicationObjectTypeName(),
$this->renderPolicyName($old),
$this->renderPolicyName($new));
case PhabricatorTransactions::TYPE_JOIN_POLICY:
return pht(
'%s changed the join policy of this %s from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$this->getApplicationObjectTypeName(),
$this->renderPolicyName($old),
$this->renderPolicyName($new));
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
return pht(
'%s edited subscriber(s), added %d: %s; removed %d: %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add),
count($rem),
$this->renderHandleList($rem));
} else if ($add) {
return pht(
'%s added %d subscriber(s): %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add));
} else if ($rem) {
return pht(
'%s removed %d subscriber(s): %s.',
$this->renderHandleLink($author_phid),
count($rem),
$this->renderHandleList($rem));
} else {
// This is used when rendering previews, before the user actually
// selects any CCs.
return pht(
'%s updated subscribers...',
$this->renderHandleLink($author_phid));
}
break;
case PhabricatorTransactions::TYPE_EDGE:
$new = ipull($new, 'dst');
$old = ipull($old, 'dst');
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
$type = $this->getMetadata('edge:type');
$type = head($type);
if ($add && $rem) {
$string = PhabricatorEdgeConfig::getEditStringForEdgeType($type);
return pht(
$string,
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add),
count($rem),
$this->renderHandleList($rem));
} else if ($add) {
$string = PhabricatorEdgeConfig::getAddStringForEdgeType($type);
return pht(
$string,
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add));
} else {
$string = PhabricatorEdgeConfig::getRemoveStringForEdgeType($type);
return pht(
$string,
$this->renderHandleLink($author_phid),
count($rem),
$this->renderHandleList($rem));
}
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
- $key = $this->getMetadataValue('customfield:key');
- $field = PhabricatorCustomField::getObjectField(
- $this->getObject(),
- PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS,
- $key);
+ $field = $this->getTransactionCustomField();
if ($field) {
- $field->setViewer($this->getViewer());
return $field->getApplicationTransactionTitle($this);
} else {
return pht(
'%s edited a custom field.',
$this->renderHandleLink($author_phid));
}
default:
return pht(
'%s edited this %s.',
$this->renderHandleLink($author_phid),
$this->getApplicationObjectTypeName());
}
}
public function getTitleForFeed(PhabricatorFeedStory $story) {
$author_phid = $this->getAuthorPHID();
$object_phid = $this->getObjectPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
return pht(
'%s added a comment to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_VIEW_POLICY:
return pht(
'%s changed the visibility for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_EDIT_POLICY:
return pht(
'%s changed the edit policy for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_JOIN_POLICY:
return pht(
'%s changed the join policy for %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
return pht(
'%s updated subscribers of %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_EDGE:
$type = $this->getMetadata('edge:type');
$type = head($type);
$string = PhabricatorEdgeConfig::getFeedStringForEdgeType($type);
return pht(
$string,
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
case PhabricatorTransactions::TYPE_CUSTOMFIELD:
- $key = $this->getMetadataValue('customfield:key');
- $field = PhabricatorCustomField::getObjectField(
- $this->getObject(),
- PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS,
- $key);
+ $field = $this->getTransactionCustomField();
if ($field) {
- $field->setViewer($this->getViewer());
return $field->getApplicationTransactionTitleForFeed($this, $story);
} else {
return pht(
'%s edited a custom field on %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($object_phid));
}
}
return $this->getTitle();
}
public function getBodyForFeed(PhabricatorFeedStory $story) {
$old = $this->getOldValue();
$new = $this->getNewValue();
$body = null;
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
$text = $this->getComment()->getContent();
$body = phutil_escape_html_newlines(
phutil_utf8_shorten($text, 128));
break;
}
return $body;
}
public function getActionStrength() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
return 0.5;
}
return 1.0;
}
public function getActionName() {
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_COMMENT:
return pht('Commented On');
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
case PhabricatorTransactions::TYPE_JOIN_POLICY:
return pht('Changed Policy');
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
return pht('Changed Subscribers');
default:
return pht('Updated');
}
}
public function getMailTags() {
return array();
}
public function hasChangeDetails() {
+ switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_CUSTOMFIELD:
+ $field = $this->getTransactionCustomField();
+ if ($field) {
+ return $field->getApplicationTransactionHasChangeDetails($this);
+ }
+ break;
+ }
return false;
}
public function renderChangeDetails(PhabricatorUser $viewer) {
- return null;
+ switch ($this->getTransactionType()) {
+ case PhabricatorTransactions::TYPE_CUSTOMFIELD:
+ $field = $this->getTransactionCustomField();
+ if ($field) {
+ return $field->getApplicationTransactionChangeDetails($this, $viewer);
+ }
+ break;
+ }
+
+ return $this->renderTextCorpusChangeDetails();
+ }
+
+ public function renderTextCorpusChangeDetails(
+ PhabricatorUser $viewer,
+ $old,
+ $new) {
+
+ require_celerity_resource('differential-changeset-view-css');
+
+ $view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
+ ->setUser($viewer)
+ ->setOldText($old)
+ ->setNewText($new);
+
+ return $view->render();
}
public function attachTransactionGroup(array $group) {
assert_instances_of($group, 'PhabricatorApplicationTransaction');
$this->transactionGroup = $group;
return $this;
}
public function getTransactionGroup() {
return $this->transactionGroup;
}
/**
* Should this transaction be visually grouped with an existing transaction
* group?
*
* @param list<PhabricatorApplicationTransaction> List of transactions.
* @return bool True to display in a group with the other transactions.
*/
public function shouldDisplayGroupWith(array $group) {
$type_comment = PhabricatorTransactions::TYPE_COMMENT;
$this_source = null;
if ($this->getContentSource()) {
$this_source = $this->getContentSource()->getSource();
}
foreach ($group as $xaction) {
// Don't group transactions by different authors.
if ($xaction->getAuthorPHID() != $this->getAuthorPHID()) {
return false;
}
// Don't group transactions for different objects.
if ($xaction->getObjectPHID() != $this->getObjectPHID()) {
return false;
}
// Don't group anything into a group which already has a comment.
if ($xaction->getTransactionType() == $type_comment) {
return false;
}
// Don't group transactions from different content sources.
$other_source = null;
if ($xaction->getContentSource()) {
$other_source = $xaction->getContentSource()->getSource();
}
if ($other_source != $this_source) {
return false;
}
// Don't group transactions which happened more than 2 minutes apart.
$apart = abs($xaction->getDateCreated() - $this->getDateCreated());
if ($apart > (60 * 2)) {
return false;
}
}
return true;
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return ($viewer->getPHID() == $this->getAuthorPHID());
}
public function describeAutomaticCapability($capability) {
// TODO: (T603) Exact policies are unclear here.
return null;
}
}
diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php
index 2d2a47afdb..38592a2978 100644
--- a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php
+++ b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php
@@ -1,356 +1,352 @@
<?php
/**
* @concrete-extensible
*/
class PhabricatorApplicationTransactionView extends AphrontView {
private $transactions;
private $engine;
private $anchorOffset = 1;
private $showEditActions = true;
private $isPreview;
private $objectPHID;
public function setObjectPHID($object_phid) {
$this->objectPHID = $object_phid;
return $this;
}
public function getObjectPHID() {
return $this->objectPHID;
}
public function setIsPreview($is_preview) {
$this->isPreview = $is_preview;
return $this;
}
public function setShowEditActions($show_edit_actions) {
$this->showEditActions = $show_edit_actions;
return $this;
}
public function getShowEditActions() {
return $this->showEditActions;
}
public function setAnchorOffset($anchor_offset) {
$this->anchorOffset = $anchor_offset;
return $this;
}
public function setMarkupEngine(PhabricatorMarkupEngine $engine) {
$this->engine = $engine;
return $this;
}
public function setTransactions(array $transactions) {
assert_instances_of($transactions, 'PhabricatorApplicationTransaction');
$this->transactions = $transactions;
return $this;
}
public function buildEvents($with_hiding = false) {
$user = $this->getUser();
$anchor = $this->anchorOffset;
$xactions = $this->transactions;
$xactions = $this->filterHiddenTransactions($xactions);
$xactions = $this->groupRelatedTransactions($xactions);
$groups = $this->groupDisplayTransactions($xactions);
// If the viewer has interacted with this object, we hide things from
// before their most recent interaction by default. This tends to make
// very long threads much more manageable, because you don't have to
// scroll through a lot of history and can focus on just new stuff.
$show_group = null;
if ($with_hiding) {
// Find the most recent comment by the viewer.
$group_keys = array_keys($groups);
$group_keys = array_reverse($group_keys);
// If we would only hide a small number of transactions, don't hide
// anything. Just don't examine the last few keys. Also, we always
// want to show the most recent pieces of activity, so don't examine
// the first few keys either.
$group_keys = array_slice($group_keys, 2, -2);
$type_comment = PhabricatorTransactions::TYPE_COMMENT;
foreach ($group_keys as $group_key) {
$group = $groups[$group_key];
foreach ($group as $xaction) {
if ($xaction->getAuthorPHID() == $user->getPHID() &&
$xaction->getTransactionType() == $type_comment) {
// This is the most recent group where the user commented.
$show_group = $group_key;
break 2;
}
}
}
}
$events = array();
$hide_by_default = ($show_group !== null);
foreach ($groups as $group_key => $group) {
if ($hide_by_default && ($show_group === $group_key)) {
$hide_by_default = false;
}
$group_event = null;
foreach ($group as $xaction) {
$event = $this->renderEvent($xaction, $group, $anchor);
$event->setHideByDefault($hide_by_default);
$anchor++;
if (!$group_event) {
$group_event = $event;
} else {
$group_event->addEventToGroup($event);
}
}
$events[] = $group_event;
}
return $events;
}
public function render() {
if (!$this->getObjectPHID()) {
throw new Exception("Call setObjectPHID() before render()!");
}
$view = new PHUITimelineView();
$events = $this->buildEvents($with_hiding = true);
foreach ($events as $event) {
$view->addEvent($event);
}
if ($this->getShowEditActions()) {
$list_id = celerity_generate_unique_node_id();
$view->setID($list_id);
Javelin::initBehavior(
'phabricator-transaction-list',
array(
'listID' => $list_id,
'objectPHID' => $this->getObjectPHID(),
'nextAnchor' => $this->anchorOffset + count($events),
));
}
return $view->render();
}
protected function getOrBuildEngine() {
if ($this->engine) {
return $this->engine;
}
$field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT;
$engine = id(new PhabricatorMarkupEngine())
->setViewer($this->getUser());
foreach ($this->transactions as $xaction) {
if (!$xaction->hasComment()) {
continue;
}
$engine->addObject($xaction->getComment(), $field);
}
$engine->process();
return $engine;
}
private function buildChangeDetailsLink(
PhabricatorApplicationTransaction $xaction) {
return javelin_tag(
'a',
array(
'href' => '/transactions/detail/'.$xaction->getPHID().'/',
- 'sigil' => 'transaction-detail',
- 'mustcapture' => true,
- 'meta' => array(
- 'anchor' => $this->anchorOffset,
- ),
+ 'sigil' => 'workflow',
),
pht('(Show Details)'));
}
protected function shouldGroupTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
return false;
}
protected function renderTransactionContent(
PhabricatorApplicationTransaction $xaction) {
$field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT;
$engine = $this->getOrBuildEngine();
$comment = $xaction->getComment();
if ($xaction->hasComment()) {
if ($comment->getIsDeleted()) {
return phutil_tag(
'em',
array(),
pht('This comment has been deleted.'));
} else {
return $engine->getOutput($comment, $field);
}
}
return null;
}
private function filterHiddenTransactions(array $xactions) {
foreach ($xactions as $key => $xaction) {
if ($xaction->shouldHide()) {
unset($xactions[$key]);
}
}
return $xactions;
}
private function groupRelatedTransactions(array $xactions) {
$last = null;
$last_key = null;
$groups = array();
foreach ($xactions as $key => $xaction) {
if ($last && $this->shouldGroupTransactions($last, $xaction)) {
$groups[$last_key][] = $xaction;
unset($xactions[$key]);
} else {
$last = $xaction;
$last_key = $key;
}
}
foreach ($xactions as $key => $xaction) {
$xaction->attachTransactionGroup(idx($groups, $key, array()));
}
return $xactions;
}
private function groupDisplayTransactions(array $xactions) {
$groups = array();
$group = array();
foreach ($xactions as $xaction) {
if ($xaction->shouldDisplayGroupWith($group)) {
$group[] = $xaction;
} else {
if ($group) {
$groups[] = $group;
}
$group = array($xaction);
}
}
if ($group) {
$groups[] = $group;
}
foreach ($groups as $key => $group) {
$group = msort($group, 'getActionStrength');
$group = array_reverse($group);
$groups[$key] = $group;
}
return $groups;
}
private function renderEvent(
PhabricatorApplicationTransaction $xaction,
array $group,
$anchor) {
$viewer = $this->getUser();
$event = id(new PHUITimelineEventView())
->setUser($viewer)
->setTransactionPHID($xaction->getPHID())
->setUserHandle($xaction->getHandle($xaction->getAuthorPHID()))
->setIcon($xaction->getIcon())
->setColor($xaction->getColor());
if (!$this->shouldSuppressTitle($xaction, $group)) {
$title = $xaction->getTitle();
if ($xaction->hasChangeDetails()) {
if (!$this->isPreview) {
$details = $this->buildChangeDetailsLink($xaction);
$title = array(
$title,
' ',
$details,
);
}
}
$event->setTitle($title);
}
if ($this->isPreview) {
$event->setIsPreview(true);
} else {
$event
->setDateCreated($xaction->getDateCreated())
->setContentSource($xaction->getContentSource())
->setAnchor($anchor);
}
$has_deleted_comment = $xaction->getComment() &&
$xaction->getComment()->getIsDeleted();
if ($this->getShowEditActions() && !$this->isPreview) {
if ($xaction->getCommentVersion() > 1) {
$event->setIsEdited(true);
}
$can_edit = PhabricatorPolicyCapability::CAN_EDIT;
if ($xaction->hasComment() || $has_deleted_comment) {
$has_edit_capability = PhabricatorPolicyFilter::hasCapability(
$viewer,
$xaction,
$can_edit);
if ($has_edit_capability) {
$event->setIsEditable(true);
}
}
}
$content = $this->renderTransactionContent($xaction);
if ($content) {
$event->appendChild($content);
}
return $event;
}
private function shouldSuppressTitle(
PhabricatorApplicationTransaction $xaction,
array $group) {
// This is a little hard-coded, but we don't have any other reasonable
// cases for now. Suppress "commented on" if there are other actions in
// the display group.
if (count($group) > 1) {
$type_comment = PhabricatorTransactions::TYPE_COMMENT;
if ($xaction->getTransactionType() == $type_comment) {
return true;
}
}
return false;
}
}
diff --git a/src/infrastructure/customfield/field/PhabricatorCustomField.php b/src/infrastructure/customfield/field/PhabricatorCustomField.php
index f4b6ac2b10..f8e9e69454 100644
--- a/src/infrastructure/customfield/field/PhabricatorCustomField.php
+++ b/src/infrastructure/customfield/field/PhabricatorCustomField.php
@@ -1,1015 +1,1036 @@
<?php
/**
* @task apps Building Applications with Custom Fields
* @task core Core Properties and Field Identity
* @task proxy Field Proxies
* @task context Contextual Data
* @task storage Field Storage
* @task appsearch Integration with ApplicationSearch
* @task appxaction Integration with ApplicationTransactions
* @task edit Integration with edit views
* @task view Integration with property views
* @task list Integration with list views
*/
abstract class PhabricatorCustomField {
private $viewer;
private $object;
private $proxy;
const ROLE_APPLICATIONTRANSACTIONS = 'ApplicationTransactions';
const ROLE_APPLICATIONSEARCH = 'ApplicationSearch';
const ROLE_STORAGE = 'storage';
const ROLE_DEFAULT = 'default';
const ROLE_EDIT = 'edit';
const ROLE_VIEW = 'view';
const ROLE_LIST = 'list';
/* -( Building Applications with Custom Fields )--------------------------- */
/**
* @task apps
*/
public static function getObjectFields(
PhabricatorCustomFieldInterface $object,
$role) {
try {
$attachment = $object->getCustomFields();
} catch (PhabricatorDataNotAttachedException $ex) {
$attachment = new PhabricatorCustomFieldAttachment();
$object->attachCustomFields($attachment);
}
try {
$field_list = $attachment->getCustomFieldList($role);
} catch (PhabricatorCustomFieldNotAttachedException $ex) {
$base_class = $object->getCustomFieldBaseClass();
$spec = $object->getCustomFieldSpecificationForRole($role);
if (!is_array($spec)) {
$obj_class = get_class($object);
throw new Exception(
"Expected an array from getCustomFieldSpecificationForRole() for ".
"object of class '{$obj_class}'.");
}
$fields = PhabricatorCustomField::buildFieldList($base_class, $spec);
foreach ($fields as $key => $field) {
if (!$field->shouldEnableForRole($role)) {
unset($fields[$key]);
}
}
foreach ($fields as $field) {
$field->setObject($object);
}
$field_list = new PhabricatorCustomFieldList($fields);
$attachment->addCustomFieldList($role, $field_list);
}
return $field_list;
}
/**
* @task apps
*/
public static function getObjectField(
PhabricatorCustomFieldInterface $object,
$role,
$field_key) {
$fields = self::getObjectFields($object, $role)->getFields();
return idx($fields, $field_key);
}
/**
* @task apps
*/
public static function buildFieldList($base_class, array $spec) {
$field_objects = id(new PhutilSymbolLoader())
->setAncestorClass($base_class)
->loadObjects();
$fields = array();
$from_map = array();
foreach ($field_objects as $field_object) {
$current_class = get_class($field_object);
foreach ($field_object->createFields() as $field) {
$key = $field->getFieldKey();
if (isset($fields[$key])) {
$original_class = $from_map[$key];
throw new Exception(
"Both '{$original_class}' and '{$current_class}' define a custom ".
"field with field key '{$key}'. Field keys must be unique.");
}
$from_map[$key] = $current_class;
$fields[$key] = $field;
}
}
foreach ($fields as $key => $field) {
if (!$field->isFieldEnabled()) {
unset($fields[$key]);
}
}
$fields = array_select_keys($fields, array_keys($spec)) + $fields;
foreach ($spec as $key => $config) {
if (empty($fields[$key])) {
continue;
}
if (!empty($config['disabled'])) {
if ($fields[$key]->canDisableField()) {
unset($fields[$key]);
}
}
}
return $fields;
}
/* -( Core Properties and Field Identity )--------------------------------- */
/**
* Return a key which uniquely identifies this field, like
* "mycompany:dinosaur:count". Normally you should provide some level of
* namespacing to prevent collisions.
*
* @return string String which uniquely identifies this field.
* @task core
*/
public function getFieldKey() {
if ($this->proxy) {
return $this->proxy->getFieldKey();
}
throw new PhabricatorCustomFieldImplementationIncompleteException(
$this,
$field_key_is_incomplete = true);
}
/**
* Return a human-readable field name.
*
* @return string Human readable field name.
* @task core
*/
public function getFieldName() {
if ($this->proxy) {
return $this->proxy->getFieldName();
}
return $this->getFieldKey();
}
/**
* Return a short, human-readable description of the field's behavior. This
* provides more context to administrators when they are customizing fields.
*
* @return string|null Optional human-readable description.
* @task core
*/
public function getFieldDescription() {
if ($this->proxy) {
return $this->proxy->getFieldDescription();
}
return null;
}
/**
* Most field implementations are unique, in that one class corresponds to
* one field. However, some field implementations are general and a single
* implementation may drive several fields.
*
* For general implementations, the general field implementation can return
* multiple field instances here.
*
* @return list<PhabricatorCustomField> List of fields.
* @task core
*/
public function createFields() {
return array($this);
}
/**
* You can return `false` here if the field should not be enabled for any
* role. For example, it might depend on something (like an application or
* library) which isn't installed, or might have some global configuration
* which allows it to be disabled.
*
* @return bool False to completely disable this field for all roles.
* @task core
*/
public function isFieldEnabled() {
if ($this->proxy) {
return $this->proxy->isFieldEnabled();
}
return true;
}
/**
* Low level selector for field availability. Fields can appear in different
* roles (like an edit view, a list view, etc.), but not every field needs
* to appear everywhere. Fields that are disabled in a role won't appear in
* that context within applications.
*
* Normally, you do not need to override this method. Instead, override the
* methods specific to roles you want to enable. For example, implement
* @{method:shouldUseStorage()} to activate the `'storage'` role.
*
* @return bool True to enable the field for the given role.
* @task core
*/
public function shouldEnableForRole($role) {
if ($this->proxy) {
return $this->proxy->shouldEnableForRole($role);
}
switch ($role) {
case self::ROLE_APPLICATIONTRANSACTIONS:
return $this->shouldAppearInApplicationTransactions();
case self::ROLE_APPLICATIONSEARCH:
return $this->shouldAppearInApplicationSearch();
case self::ROLE_STORAGE:
return $this->shouldUseStorage();
case self::ROLE_EDIT:
return $this->shouldAppearInEditView();
case self::ROLE_VIEW:
return $this->shouldAppearInPropertyView();
case self::ROLE_LIST:
return $this->shouldAppearInListView();
case self::ROLE_DEFAULT:
return true;
default:
throw new Exception("Unknown field role '{$role}'!");
}
}
/**
* Allow administrators to disable this field. Most fields should allow this,
* but some are fundamental to the behavior of the application and can be
* locked down to avoid chaos, disorder, and the decline of civilization.
*
* @return bool False to prevent this field from being disabled through
* configuration.
* @task core
*/
public function canDisableField() {
return true;
}
/**
* Return an index string which uniquely identifies this field.
*
* @return string Index string which uniquely identifies this field.
* @task core
*/
final public function getFieldIndex() {
return PhabricatorHash::digestForIndex($this->getFieldKey());
}
/* -( Field Proxies )------------------------------------------------------ */
/**
* Proxies allow a field to use some other field's implementation for most
* of their behavior while still subclassing an application field. When a
* proxy is set for a field with @{method:setProxy}, all of its methods will
* call through to the proxy by default.
*
* This is most commonly used to implement configuration-driven custom fields
* using @{class:PhabricatorStandardCustomField}.
*
* This method must be overridden to return `true` before a field can accept
* proxies.
*
* @return bool True if you can @{method:setProxy} this field.
* @task proxy
*/
public function canSetProxy() {
if ($this instanceof PhabricatorStandardCustomFieldInterface) {
return true;
}
return false;
}
/**
* Set the proxy implementation for this field. See @{method:canSetProxy} for
* discussion of field proxies.
*
* @param PhabricatorCustomField Field implementation.
* @return this
*/
final public function setProxy(PhabricatorCustomField $proxy) {
if (!$this->canSetProxy()) {
throw new PhabricatorCustomFieldNotProxyException($this);
}
$this->proxy = $proxy;
return $this;
}
/**
* Get the field's proxy implementation, if any. For discussion, see
* @{method:canSetProxy}.
*
* @return PhabricatorCustomField|null Proxy field, if one is set.
*/
final public function getProxy() {
return $this->proxy;
}
/* -( Contextual Data )---------------------------------------------------- */
/**
* Sets the object this field belongs to.
*
* @param PhabricatorCustomFieldInterface The object this field belongs to.
* @task context
*/
final public function setObject(PhabricatorCustomFieldInterface $object) {
if ($this->proxy) {
$this->proxy->setObject($object);
return $this;
}
$this->object = $object;
$this->didSetObject($object);
return $this;
}
/**
* Get the object this field belongs to.
*
* @return PhabricatorCustomFieldInterface The object this field belongs to.
* @task context
*/
final public function getObject() {
if ($this->proxy) {
return $this->proxy->getObject();
}
return $this->object;
}
/**
* This is a hook, primarily for subclasses to load object data.
*
* @return PhabricatorCustomFieldInterface The object this field belongs to.
* @return void
*/
protected function didSetObject(PhabricatorCustomFieldInterface $object) {
return;
}
/**
* @task context
*/
final public function setViewer(PhabricatorUser $viewer) {
if ($this->proxy) {
$this->proxy->setViewer($viewer);
return $this;
}
$this->viewer = $viewer;
return $this;
}
/**
* @task context
*/
final public function getViewer() {
if ($this->proxy) {
return $this->proxy->getViewer();
}
return $this->viewer;
}
/**
* @task context
*/
final protected function requireViewer() {
if ($this->proxy) {
return $this->proxy->requireViewer();
}
if (!$this->viewer) {
throw new PhabricatorCustomFieldDataNotAvailableException($this);
}
return $this->viewer;
}
/* -( Storage )------------------------------------------------------------ */
/**
* Return true to use field storage.
*
* Fields which can be edited by the user will most commonly use storage,
* while some other types of fields (for instance, those which just display
* information in some stylized way) may not. Many builtin fields do not use
* storage because their data is available on the object itself.
*
* If you implement this, you must also implement @{method:getValueForStorage}
* and @{method:setValueFromStorage}.
*
* @return bool True to use storage.
* @task storage
*/
public function shouldUseStorage() {
if ($this->proxy) {
return $this->proxy->shouldUseStorage();
}
return false;
}
/**
* Return a new, empty storage object. This should be a subclass of
* @{class:PhabricatorCustomFieldStorage} which is bound to the application's
* database.
*
* @return PhabricatorCustomFieldStorage New empty storage object.
* @task storage
*/
public function newStorageObject() {
if ($this->proxy) {
return $this->proxy->newStorageObject();
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Return a serialized representation of the field value, appropriate for
* storing in auxiliary field storage. You must implement this method if
* you implement @{method:shouldUseStorage}.
*
* If the field value is a scalar, it can be returned unmodiifed. If not,
* it should be serialized (for example, using JSON).
*
* @return string Serialized field value.
* @task storage
*/
public function getValueForStorage() {
if ($this->proxy) {
return $this->proxy->getValueForStorage();
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Set the field's value given a serialized storage value. This is called
* when the field is loaded; if no data is available, the value will be
* null. You must implement this method if you implement
* @{method:shouldUseStorage}.
*
* Usually, the value can be loaded directly. If it isn't a scalar, you'll
* need to undo whatever serialization you applied in
* @{method:getValueForStorage}.
*
* @param string|null Serialized field representation (from
* @{method:getValueForStorage}) or null if no value has
* ever been stored.
* @return this
* @task storage
*/
public function setValueFromStorage($value) {
if ($this->proxy) {
return $this->proxy->setValueFromStorage($value);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/* -( ApplicationSearch )-------------------------------------------------- */
/**
* Appearing in ApplicationSearch allows a field to be indexed and searched
* for.
*
* @return bool True to appear in ApplicationSearch.
* @task appsearch
*/
public function shouldAppearInApplicationSearch() {
if ($this->proxy) {
return $this->proxy->shouldAppearInApplicationSearch();
}
return false;
}
/**
* Return one or more indexes which this field can meaningfully query against
* to implement ApplicationSearch.
*
* Normally, you should build these using @{method:newStringIndex} and
* @{method:newNumericIndex}. For example, if a field holds a numeric value
* it might return a single numeric index:
*
* return array($this->newNumericIndex($this->getValue()));
*
* If a field holds a more complex value (like a list of users), it might
* return several string indexes:
*
* $indexes = array();
* foreach ($this->getValue() as $phid) {
* $indexes[] = $this->newStringIndex($phid);
* }
* return $indexes;
*
* @return list<PhabricatorCustomFieldIndexStorage> List of indexes.
* @task appsearch
*/
public function buildFieldIndexes() {
if ($this->proxy) {
return $this->proxy->buildFieldIndexes();
}
return array();
}
/**
* Build a new empty storage object for storing string indexes. Normally,
* this should be a concrete subclass of
* @{class:PhabricatorCustomFieldStringIndexStorage}.
*
* @return PhabricatorCustomFieldStringIndexStorage Storage object.
* @task appsearch
*/
protected function newStringIndexStorage() {
// NOTE: This intentionally isn't proxied, to avoid call cycles.
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Build a new empty storage object for storing string indexes. Normally,
* this should be a concrete subclass of
* @{class:PhabricatorCustomFieldStringIndexStorage}.
*
* @return PhabricatorCustomFieldStringIndexStorage Storage object.
* @task appsearch
*/
protected function newNumericIndexStorage() {
// NOTE: This intentionally isn't proxied, to avoid call cycles.
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Build and populate storage for a string index.
*
* @param string String to index.
* @return PhabricatorCustomFieldStringIndexStorage Populated storage.
* @task appsearch
*/
protected function newStringIndex($value) {
if ($this->proxy) {
return $this->proxy->newStringIndex();
}
$key = $this->getFieldIndex();
return $this->newStringIndexStorage()
->setIndexKey($key)
->setIndexValue($value);
}
/**
* Build and populate storage for a numeric index.
*
* @param string Numeric value to index.
* @return PhabricatorCustomFieldNumericIndexStorage Populated storage.
* @task appsearch
*/
protected function newNumericIndex($value) {
if ($this->proxy) {
return $this->proxy->newNumericIndex();
}
$key = $this->getFieldIndex();
return $this->newNumericIndexStorage()
->setIndexKey($key)
->setIndexValue($value);
}
/**
* Read a query value from a request, for storage in a saved query. Normally,
* this method should, e.g., read a string out of the request.
*
* @param PhabricatorApplicationSearchEngine Engine building the query.
* @param AphrontRequest Request to read from.
* @return wild
* @task appsearch
*/
public function readApplicationSearchValueFromRequest(
PhabricatorApplicationSearchEngine $engine,
AphrontRequest $request) {
if ($this->proxy) {
return $this->proxy->readApplicationSearchValueFromRequest(
$engine,
$request);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Constrain a query, given a field value. Generally, this method should
* use `with...()` methods to apply filters or other constraints to the
* query.
*
* @param PhabricatorApplicationSearchEngine Engine executing the query.
* @param PhabricatorCursorPagedPolicyAwareQuery Query to constrain.
* @param wild Constraint provided by the user.
* @return void
* @task appsearch
*/
public function applyApplicationSearchConstraintToQuery(
PhabricatorApplicationSearchEngine $engine,
PhabricatorCursorPagedPolicyAwareQuery $query,
$value) {
if ($this->proxy) {
return $this->proxy->applyApplicationSearchConstraintToQuery(
$engine,
$query,
$value);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Append search controls to the interface. If you need handles, use
* @{method:getRequiredHandlePHIDsForApplicationSearch} to get them.
*
* @param PhabricatorApplicationSearchEngine Engine constructing the form.
* @param AphrontFormView The form to update.
* @param wild Value from the saved query.
* @param list<PhabricatorObjectHandle> List of handles.
* @return void
* @task appsearch
*/
public function appendToApplicationSearchForm(
PhabricatorApplicationSearchEngine $engine,
AphrontFormView $form,
$value,
array $handles) {
if ($this->proxy) {
return $this->proxy->appendToApplicationSearchForm(
$engine,
$form,
$value,
$handles);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* Return a list of PHIDs which @{method:appendToApplicationSearchForm} needs
* handles for. This is primarily useful if the field stores PHIDs and you
* need to (for example) render a tokenizer control.
*
* @param wild Value from the saved query.
* @return list<phid> List of PHIDs.
* @task appsearch
*/
public function getRequiredHandlePHIDsForApplicationSearch($value) {
if ($this->proxy) {
return $this->proxy->getRequiredHandlePHIDsForApplicationSearch($value);
}
return array();
}
/* -( ApplicationTransactions )-------------------------------------------- */
/**
* Appearing in ApplicationTrasactions allows a field to be edited using
* standard workflows.
*
* @return bool True to appear in ApplicationTransactions.
* @task appxaction
*/
public function shouldAppearInApplicationTransactions() {
if ($this->proxy) {
return $this->proxy->shouldAppearInApplicationTransactions();
}
return false;
}
/**
* @task appxaction
*/
public function getOldValueForApplicationTransactions() {
if ($this->proxy) {
return $this->proxy->getOldValueForApplicationTransactions();
}
return $this->getValueForStorage();
}
/**
* @task appxaction
*/
public function getNewValueForApplicationTransactions() {
if ($this->proxy) {
return $this->proxy->getNewValueForApplicationTransactions();
}
return $this->getValueForStorage();
}
/**
* @task appxaction
*/
public function setValueFromApplicationTransactions($value) {
if ($this->proxy) {
return $this->proxy->setValueFromApplicationTransactions($value);
}
return $this->setValueFromStorage($value);
}
/**
* @task appxaction
*/
public function getNewValueFromApplicationTransactions(
PhabricatorApplicationTransaction $xaction) {
if ($this->proxy) {
return $this->proxy->getNewValueFromApplicationTransactions($xaction);
}
return $xaction->getNewValue();
}
/**
* @task appxaction
*/
public function getApplicationTransactionHasEffect(
PhabricatorApplicationTransaction $xaction) {
if ($this->proxy) {
return $this->proxy->getApplicationTransactionHasEffect($xaction);
}
return ($xaction->getOldValue() !== $xaction->getNewValue());
}
/**
* @task appxaction
*/
public function applyApplicationTransactionInternalEffects(
PhabricatorApplicationTransaction $xaction) {
if ($this->proxy) {
return $this->proxy->applyApplicationTransactionInternalEffects($xaction);
}
return;
}
/**
* @task appxaction
*/
public function applyApplicationTransactionExternalEffects(
PhabricatorApplicationTransaction $xaction) {
if ($this->proxy) {
return $this->proxy->applyApplicationTransactionExternalEffects($xaction);
}
if (!$this->shouldEnableForRole(self::ROLE_STORAGE)) {
return;
}
$this->setValueFromApplicationTransactions($xaction->getNewValue());
$value = $this->getValueForStorage();
$table = $this->newStorageObject();
$conn_w = $table->establishConnection('w');
if ($value === null) {
queryfx(
$conn_w,
'DELETE FROM %T WHERE objectPHID = %s AND fieldIndex = %s',
$table->getTableName(),
$this->getObject()->getPHID(),
$this->getFieldIndex());
} else {
queryfx(
$conn_w,
'INSERT INTO %T (objectPHID, fieldIndex, fieldValue)
VALUES (%s, %s, %s)
ON DUPLICATE KEY UPDATE fieldValue = VALUES(fieldValue)',
$table->getTableName(),
$this->getObject()->getPHID(),
$this->getFieldIndex(),
$value);
}
return;
}
/**
* Validate transactions for an object. This allows you to raise an error
* when a transaction would set a field to an invalid value, or when a field
* is required but no transactions provide value.
*
* @param PhabricatorLiskDAO Editor applying the transactions.
* @param string Transaction type. This type is always
* `PhabricatorTransactions::TYPE_CUSTOMFIELD`, it is provided for
* convenience when constructing exceptions.
* @param list<PhabricatorApplicationTransaction> Transactions being applied,
* which may be empty if this field is not being edited.
* @return list<PhabricatorApplicationTransactionValidationError> Validation
* errors.
*
* @task appxaction
*/
public function validateApplicationTransactions(
PhabricatorApplicationTransactionEditor $editor,
$type,
array $xactions) {
if ($this->proxy) {
return $this->proxy->validateApplicationTransactions(
$editor,
$type,
$xactions);
}
return array();
}
public function getApplicationTransactionTitle(
PhabricatorApplicationTransaction $xaction) {
if ($this->proxy) {
return $this->proxy->getApplicationTransactionTitle(
$xaction);
}
$author_phid = $xaction->getAuthorPHID();
return pht(
'%s updated this object.',
$xaction->renderHandleLink($author_phid));
}
public function getApplicationTransactionTitleForFeed(
PhabricatorApplicationTransaction $xaction,
PhabricatorFeedStory $story) {
if ($this->proxy) {
return $this->proxy->getApplicationTransactionTitleForFeed(
$xaction,
$story);
}
$author_phid = $xaction->getAuthorPHID();
$object_phid = $xaction->getObjectPHID();
return pht(
'%s updated %s.',
$xaction->renderHandleLink($author_phid),
$xaction->renderHandleLink($object_phid));
}
+ public function getApplicationTransactionHasChangeDetails(
+ PhabricatorApplicationTransaction $xaction) {
+ if ($this->proxy) {
+ return $this->proxy->getApplicationTransactionHasChangeDetails(
+ $xaction);
+ }
+ return false;
+ }
+
+ public function getApplicationTransactionChangeDetails(
+ PhabricatorApplicationTransaction $xaction,
+ PhabricatorUser $viewer) {
+ if ($this->proxy) {
+ return $this->proxy->getApplicationTransactionChangeDetails(
+ $xaction,
+ $viewer);
+ }
+ return null;
+ }
+
+
/* -( Edit View )---------------------------------------------------------- */
/**
* @task edit
*/
public function shouldAppearInEditView() {
if ($this->proxy) {
return $this->proxy->shouldAppearInEditView();
}
return false;
}
/**
* @task edit
*/
public function readValueFromRequest(AphrontRequest $request) {
if ($this->proxy) {
return $this->proxy->readValueFromRequest($request);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* @task edit
*/
public function renderEditControl() {
if ($this->proxy) {
return $this->proxy->renderEditControl();
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/* -( Property View )------------------------------------------------------ */
/**
* @task view
*/
public function shouldAppearInPropertyView() {
if ($this->proxy) {
return $this->proxy->shouldAppearInPropertyView();
}
return false;
}
/**
* @task view
*/
public function renderPropertyViewLabel() {
if ($this->proxy) {
return $this->proxy->renderPropertyViewLabel();
}
return $this->getFieldName();
}
/**
* @task view
*/
public function renderPropertyViewValue() {
if ($this->proxy) {
return $this->proxy->renderPropertyViewValue();
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* @task view
*/
public function getStyleForPropertyView() {
if ($this->proxy) {
return $this->proxy->getStyleForPropertyView();
}
return 'property';
}
/* -( List View )---------------------------------------------------------- */
/**
* @task list
*/
public function shouldAppearInListView() {
if ($this->proxy) {
return $this->proxy->shouldAppearInListView();
}
return false;
}
/**
* @task list
*/
public function renderOnListItem(PHUIObjectItemView $view) {
if ($this->proxy) {
return $this->proxy->renderOnListItem($view);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
}
diff --git a/webroot/rsrc/js/application/transactions/behavior-transaction-list.js b/webroot/rsrc/js/application/transactions/behavior-transaction-list.js
index 6793d6c342..8b93f04f7b 100644
--- a/webroot/rsrc/js/application/transactions/behavior-transaction-list.js
+++ b/webroot/rsrc/js/application/transactions/behavior-transaction-list.js
@@ -1,148 +1,135 @@
/**
* @provides javelin-behavior-phabricator-transaction-list
* @requires javelin-behavior
* javelin-stratcom
* javelin-workflow
* javelin-dom
* javelin-fx
*/
JX.behavior('phabricator-transaction-list', function(config) {
var list = JX.$(config.listID);
var xaction_nodes = null;
var next_anchor = config.nextAnchor;
function get_xaction_nodes() {
if (xaction_nodes === null) {
xaction_nodes = {};
var xactions = JX.DOM.scry(list, 'div', 'transaction');
for (var ii = 0; ii < xactions.length; ii++) {
xaction_nodes[JX.Stratcom.getData(xactions[ii]).phid] = xactions[ii];
}
}
return xaction_nodes;
}
function ontransactions(response) {
var fade_in = [];
var first_new = null;
var nodes = get_xaction_nodes();
for (var phid in response.xactions) {
var new_node = JX.$H(response.xactions[phid]).getFragment().firstChild;
fade_in.push(new_node);
if (nodes[phid]) {
JX.DOM.replace(nodes[phid], new_node);
} else {
if (first_new === null) {
first_new = new_node;
}
list.appendChild(new_node);
// Add a spacer after new transactions.
var spacer = JX.$H(response.spacer).getFragment().firstChild;
list.appendChild(spacer);
fade_in.push(spacer);
next_anchor++;
}
nodes[phid] = new_node;
}
// Scroll to the first new transaction, if transactions were added.
if (first_new) {
JX.DOM.scrollTo(first_new);
}
// Make any new or updated transactions fade in.
for (var ii = 0; ii < fade_in.length; ii++) {
new JX.FX(fade_in[ii]).setDuration(500).start({opacity: [0, 1]});
}
}
JX.DOM.listen(list, 'click', 'transaction-edit', function(e) {
if (!e.isNormalClick()) {
return;
}
JX.Workflow.newFromLink(e.getTarget())
.setData({anchor: e.getNodeData('transaction').anchor})
.setHandler(ontransactions)
.start();
e.kill();
});
- JX.DOM.listen(list, 'click', 'transaction-detail', function(e) {
- if (!e.isNormalClick()) {
- return;
- }
-
- JX.Workflow.newFromLink(e.getTarget())
- .setData({anchor: e.getData('anchor')})
- .setHandler(ontransactions)
- .start();
-
- e.kill();
- });
-
JX.Stratcom.listen(
['submit', 'didSyntheticSubmit'],
'transaction-append',
function(e) {
var form = e.getTarget();
if (JX.Stratcom.getData(form).objectPHID != config.objectPHID) {
// This indicates there are several forms on the page, and the user
// submitted a different one than the one we're in control of.
return;
}
e.kill();
JX.DOM.invoke(form, 'willSubmit');
JX.Workflow.newFromForm(form, { anchor : next_anchor })
.setHandler(function(response) {
ontransactions(response);
var e = JX.DOM.invoke(form, 'willClear');
if (!e.getPrevented()) {
var ii;
var textareas = JX.DOM.scry(form, 'textarea');
for (ii = 0; ii < textareas.length; ii++) {
textareas[ii].value = '';
}
var inputs = JX.DOM.scry(form, 'input');
for (ii = 0; ii < inputs.length; ii++) {
switch (inputs[ii].type) {
case 'password':
case 'text':
inputs[ii].value = '';
break;
case 'checkbox':
case 'radio':
inputs[ii].checked = false;
break;
}
}
var selects = JX.DOM.scry(form, 'select');
var jj;
for (ii = 0; ii < selects.length; ii++) {
if (selects[ii].type == 'select-one') {
selects[ii].selectedIndex = 0;
} else {
for (jj = 0; jj < selects[ii].options.length; jj++) {
selects[ii].options[jj].selected = false;
}
}
}
}
})
.start();
});
});
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 12:47 (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1124729
Default Alt Text
(221 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment