1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-10 14:51:06 +01:00

(stable) Promote 2018 Week 15

This commit is contained in:
epriestley 2018-04-13 16:21:56 -07:00
commit 1f68a3b6eb
144 changed files with 4373 additions and 3131 deletions

View file

@ -9,10 +9,10 @@ return array(
'names' => array(
'conpherence.pkg.css' => 'e68cf1fa',
'conpherence.pkg.js' => '15191c65',
'core.pkg.css' => '49b87886',
'core.pkg.js' => '1ea38af8',
'differential.pkg.css' => '113e692c',
'differential.pkg.js' => 'f6d809c0',
'core.pkg.css' => '39061f68',
'core.pkg.js' => 'e1f0f7bd',
'differential.pkg.css' => '06dc617c',
'differential.pkg.js' => 'c2ca903a',
'diffusion.pkg.css' => 'a2d17c7d',
'diffusion.pkg.js' => '6134c5a1',
'maniphest.pkg.css' => '4845691a',
@ -29,7 +29,7 @@ return array(
'rsrc/css/aphront/multi-column.css' => '84cc6640',
'rsrc/css/aphront/notification.css' => '457861ec',
'rsrc/css/aphront/panel-view.css' => '8427b78d',
'rsrc/css/aphront/phabricator-nav-view.css' => 'a9e3e6d5',
'rsrc/css/aphront/phabricator-nav-view.css' => '694d7723',
'rsrc/css/aphront/table-view.css' => '8c9bbafe',
'rsrc/css/aphront/tokenizer.css' => '15d5ff71',
'rsrc/css/aphront/tooltip.css' => '173b9431',
@ -61,7 +61,7 @@ return array(
'rsrc/css/application/dashboard/dashboard.css' => 'fe5b1869',
'rsrc/css/application/diff/inline-comment-summary.css' => 'f23d4e8f',
'rsrc/css/application/differential/add-comment.css' => 'c47f8c40',
'rsrc/css/application/differential/changeset-view.css' => 'bf84345b',
'rsrc/css/application/differential/changeset-view.css' => 'db34a142',
'rsrc/css/application/differential/core.css' => '5b7b8ff4',
'rsrc/css/application/differential/phui-inline-comment.css' => '65ae3bc2',
'rsrc/css/application/differential/revision-comment.css' => '14b8565a',
@ -71,7 +71,6 @@ return array(
'rsrc/css/application/diffusion/diffusion-icons.css' => '0c15255e',
'rsrc/css/application/diffusion/diffusion-readme.css' => '419dd5b6',
'rsrc/css/application/diffusion/diffusion-repository.css' => 'ee6f20ec',
'rsrc/css/application/diffusion/diffusion-source.css' => '5f35a3bd',
'rsrc/css/application/diffusion/diffusion.css' => '45727264',
'rsrc/css/application/feed/feed.css' => 'ecd4ec57',
'rsrc/css/application/files/global-drag-and-drop.css' => 'b556a948',
@ -112,15 +111,15 @@ return array(
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
'rsrc/css/application/uiexample/example.css' => '528b19de',
'rsrc/css/core/core.css' => '62fa3ace',
'rsrc/css/core/remarkup.css' => '1828e2ad',
'rsrc/css/core/syntax.css' => 'cae95e89',
'rsrc/css/core/remarkup.css' => 'bff43c81',
'rsrc/css/core/syntax.css' => 'e9c95dd4',
'rsrc/css/core/z-index.css' => '9d8f7c4b',
'rsrc/css/diviner/diviner-shared.css' => '896f1d43',
'rsrc/css/font/font-awesome.css' => 'e838e088',
'rsrc/css/font/font-lato.css' => 'c7ccd872',
'rsrc/css/font/phui-font-icon-base.css' => '870a7360',
'rsrc/css/layout/phabricator-filetree-view.css' => 'b912ad97',
'rsrc/css/layout/phabricator-source-code-view.css' => '31ee3c83',
'rsrc/css/layout/phabricator-source-code-view.css' => '09368218',
'rsrc/css/phui/button/phui-button-bar.css' => 'f1ff5494',
'rsrc/css/phui/button/phui-button-simple.css' => '8e1baf68',
'rsrc/css/phui/button/phui-button.css' => '1863cc6e',
@ -386,13 +385,11 @@ return array(
'rsrc/js/application/diffusion/behavior-commit-branches.js' => 'bdaf4d04',
'rsrc/js/application/diffusion/behavior-commit-graph.js' => '75b83cbb',
'rsrc/js/application/diffusion/behavior-diffusion-browse-file.js' => '054a0f0b',
'rsrc/js/application/diffusion/behavior-jump-to.js' => '73d09eef',
'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667',
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '1db13e70',
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
'rsrc/js/application/files/behavior-document-engine.js' => '9108ee1a',
'rsrc/js/application/files/behavior-document-engine.js' => '0333c0b6',
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909',
@ -423,7 +420,7 @@ return array(
'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8',
'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f',
'rsrc/js/application/repository/repository-crossreference.js' => '2ab10a76',
'rsrc/js/application/repository/repository-crossreference.js' => '9a860428',
'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072',
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
@ -473,11 +470,11 @@ return array(
'rsrc/js/core/behavior-keyboard-pager.js' => 'a8da01f0',
'rsrc/js/core/behavior-keyboard-shortcuts.js' => '01fca1f0',
'rsrc/js/core/behavior-lightbox-attachments.js' => '6b31879a',
'rsrc/js/core/behavior-line-linker.js' => '13e39479',
'rsrc/js/core/behavior-line-linker.js' => '66a62306',
'rsrc/js/core/behavior-more.js' => 'a80d0378',
'rsrc/js/core/behavior-object-selector.js' => '77c1f0b0',
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
'rsrc/js/core/behavior-phabricator-nav.js' => '836f966d',
'rsrc/js/core/behavior-phabricator-nav.js' => '94b7c320',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'acd29eee',
'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207',
'rsrc/js/core/behavior-redirect.js' => '0213259f',
@ -543,7 +540,7 @@ return array(
'conpherence-thread-manager' => '4d863052',
'conpherence-transaction-css' => '85129c68',
'd3' => 'a11a5ff2',
'differential-changeset-view-css' => 'bf84345b',
'differential-changeset-view-css' => 'db34a142',
'differential-core-view-css' => '5b7b8ff4',
'differential-revision-add-comment-css' => 'c47f8c40',
'differential-revision-comment-css' => '14b8565a',
@ -554,7 +551,6 @@ return array(
'diffusion-icons-css' => '0c15255e',
'diffusion-readme-css' => '419dd5b6',
'diffusion-repository-css' => 'ee6f20ec',
'diffusion-source-css' => '5f35a3bd',
'diviner-shared-css' => '896f1d43',
'font-fontawesome' => 'e838e088',
'font-lato' => 'c7ccd872',
@ -604,10 +600,9 @@ return array(
'javelin-behavior-diffusion-browse-file' => '054a0f0b',
'javelin-behavior-diffusion-commit-branches' => 'bdaf4d04',
'javelin-behavior-diffusion-commit-graph' => '75b83cbb',
'javelin-behavior-diffusion-jump-to' => '73d09eef',
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
'javelin-behavior-document-engine' => '9108ee1a',
'javelin-behavior-document-engine' => '0333c0b6',
'javelin-behavior-doorkeeper-tag' => '1db13e70',
'javelin-behavior-drydock-live-operation-status' => '901935ef',
'javelin-behavior-durable-column' => '2ae077e1',
@ -624,7 +619,6 @@ return array(
'javelin-behavior-launch-icon-composer' => '48086888',
'javelin-behavior-lightbox-attachments' => '6b31879a',
'javelin-behavior-line-chart' => 'e4232876',
'javelin-behavior-load-blame' => '42126667',
'javelin-behavior-maniphest-batch-selector' => 'ad54037e',
'javelin-behavior-maniphest-list-editor' => 'a9f88de2',
'javelin-behavior-maniphest-subpriority-editor' => '71237763',
@ -638,8 +632,8 @@ return array(
'javelin-behavior-phabricator-gesture-example' => '558829c2',
'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0',
'javelin-behavior-phabricator-keyboard-shortcuts' => '01fca1f0',
'javelin-behavior-phabricator-line-linker' => '13e39479',
'javelin-behavior-phabricator-nav' => '836f966d',
'javelin-behavior-phabricator-line-linker' => '66a62306',
'javelin-behavior-phabricator-nav' => '94b7c320',
'javelin-behavior-phabricator-notification-example' => '8ce821c5',
'javelin-behavior-phabricator-object-selector' => '77c1f0b0',
'javelin-behavior-phabricator-oncopy' => '2926fff2',
@ -676,7 +670,7 @@ return array(
'javelin-behavior-reorder-applications' => '76b9fc3e',
'javelin-behavior-reorder-columns' => 'e1d25dfb',
'javelin-behavior-reorder-profile-menu-items' => 'e2e0a072',
'javelin-behavior-repository-crossreference' => '2ab10a76',
'javelin-behavior-repository-crossreference' => '9a860428',
'javelin-behavior-scrollbar' => '834a1173',
'javelin-behavior-search-reorder-queries' => 'e9581f08',
'javelin-behavior-select-content' => 'bf5374ef',
@ -773,18 +767,18 @@ return array(
'phabricator-keyboard-shortcut' => '1ae869f2',
'phabricator-keyboard-shortcut-manager' => 'c19dd9b9',
'phabricator-main-menu-view' => '1802a242',
'phabricator-nav-view-css' => 'a9e3e6d5',
'phabricator-nav-view-css' => '694d7723',
'phabricator-notification' => '4f774dac',
'phabricator-notification-css' => '457861ec',
'phabricator-notification-menu-css' => '10685bd4',
'phabricator-object-selector-css' => '85ee8ce6',
'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => '77b0ae28',
'phabricator-remarkup-css' => '1828e2ad',
'phabricator-remarkup-css' => 'bff43c81',
'phabricator-search-results-css' => '505dd8cf',
'phabricator-shaped-request' => '7cbe244b',
'phabricator-slowvote-css' => 'a94b7230',
'phabricator-source-code-view-css' => '31ee3c83',
'phabricator-source-code-view-css' => '09368218',
'phabricator-standard-page-view' => '34ee718b',
'phabricator-textareautils' => '320810c8',
'phabricator-title' => '485aaa6c',
@ -884,7 +878,7 @@ return array(
'sprite-login-css' => '396f3c3a',
'sprite-tokens-css' => '9cdfd599',
'syntax-default-css' => '9923583c',
'syntax-highlighting-css' => 'cae95e89',
'syntax-highlighting-css' => 'e9c95dd4',
'tokens-css' => '3d0f239e',
'typeahead-browse-css' => 'f2818435',
'unhandled-exception-css' => '4c96257a',
@ -913,6 +907,11 @@ return array(
'javelin-behavior',
'javelin-uri',
),
'0333c0b6' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
),
'040fce04' => array(
'javelin-behavior',
'javelin-request',
@ -964,12 +963,6 @@ return array(
'javelin-install',
'javelin-util',
),
'13e39479' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-history',
),
'15d5ff71' => array(
'aphront-typeahead-control-css',
'phui-tag-view-css',
@ -1056,12 +1049,6 @@ return array(
'javelin-install',
'javelin-util',
),
'2ab10a76' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-uri',
),
'2ae077e1' => array(
'javelin-behavior',
'javelin-dom',
@ -1165,11 +1152,6 @@ return array(
'phabricator-diff-changeset-list',
'phabricator-diff-changeset',
),
42126667 => array(
'javelin-behavior',
'javelin-dom',
'javelin-request',
),
'4250a34e' => array(
'javelin-behavior',
'javelin-dom',
@ -1405,6 +1387,12 @@ return array(
'phabricator-darklog',
'phabricator-darkmessage',
),
'66a62306' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-history',
),
'66a6def1' => array(
'javelin-behavior',
'javelin-dom',
@ -1481,11 +1469,6 @@ return array(
'javelin-behavior',
'javelin-dom',
),
'73d09eef' => array(
'javelin-behavior',
'javelin-vector',
'javelin-dom',
),
'758b4758' => array(
'javelin-install',
'javelin-workboard-card',
@ -1557,16 +1540,6 @@ return array(
'javelin-behavior',
'javelin-scrollbar',
),
'836f966d' => array(
'javelin-behavior',
'javelin-behavior-device',
'javelin-stratcom',
'javelin-dom',
'javelin-magical-init',
'javelin-vector',
'javelin-request',
'javelin-util',
),
'8499b6ab' => array(
'javelin-behavior',
'javelin-dom',
@ -1644,11 +1617,6 @@ return array(
'javelin-stratcom',
'javelin-vector',
),
'9108ee1a' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
),
'92b9ec77' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1673,6 +1641,16 @@ return array(
'javelin-resource',
'javelin-routable',
),
'94b7c320' => array(
'javelin-behavior',
'javelin-behavior-device',
'javelin-stratcom',
'javelin-dom',
'javelin-magical-init',
'javelin-vector',
'javelin-request',
'javelin-util',
),
'960f6a39' => array(
'javelin-behavior',
'javelin-dom',
@ -1689,6 +1667,12 @@ return array(
'phuix-icon-view',
'javelin-behavior-phabricator-gesture',
),
'9a860428' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-uri',
),
'9bbf3762' => array(
'javelin-behavior',
'javelin-dom',
@ -1908,9 +1892,6 @@ return array(
'javelin-stratcom',
'javelin-dom',
),
'bf84345b' => array(
'phui-inline-comment-view-css',
),
'bff6884b' => array(
'javelin-install',
'javelin-dom',
@ -1978,9 +1959,6 @@ return array(
'phabricator-title',
'phabricator-favicon',
),
'cae95e89' => array(
'syntax-default-css',
),
'cd2b9b77' => array(
'phui-oi-list-view-css',
),
@ -2030,6 +2008,9 @@ return array(
'javelin-util',
'phabricator-shaped-request',
),
'db34a142' => array(
'phui-inline-comment-view-css',
),
'dca75c0e' => array(
'multirow-row-manager',
'javelin-install',
@ -2109,6 +2090,9 @@ return array(
'javelin-dom',
'phabricator-draggable-list',
),
'e9c95dd4' => array(
'syntax-default-css',
),
'ec1f3669' => array(
'javelin-behavior',
'javelin-util',
@ -2367,7 +2351,6 @@ return array(
'javelin-behavior-aphront-drag-and-drop-textarea',
'javelin-behavior-phabricator-object-selector',
'javelin-behavior-repository-crossreference',
'javelin-behavior-load-blame',
'javelin-behavior-differential-user-select',
'javelin-behavior-aphront-more',
'phabricator-diff-inline',

View file

@ -199,7 +199,6 @@ return array(
'javelin-behavior-aphront-drag-and-drop-textarea',
'javelin-behavior-phabricator-object-selector',
'javelin-behavior-repository-crossreference',
'javelin-behavior-load-blame',
'javelin-behavior-differential-user-select',
'javelin-behavior-aphront-more',

View file

@ -0,0 +1,19 @@
CREATE TABLE {$NAMESPACE}_almanac.almanac_interfacetransaction (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
authorPHID VARBINARY(64) NOT NULL,
objectPHID VARBINARY(64) NOT NULL,
viewPolicy VARBINARY(64) NOT NULL,
editPolicy VARBINARY(64) NOT NULL,
commentPHID VARBINARY(64) DEFAULT NULL,
commentVersion INT UNSIGNED NOT NULL,
transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (`phid`),
KEY `key_object` (`objectPHID`)
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -9,18 +9,27 @@
phutil_register_library_map(array(
'__library_version__' => 2,
'class' => array(
'AlamancServiceEditConduitAPIMethod' => 'applications/almanac/conduit/AlamancServiceEditConduitAPIMethod.php',
'AlmanacAddress' => 'applications/almanac/util/AlmanacAddress.php',
'AlmanacBinding' => 'applications/almanac/storage/AlmanacBinding.php',
'AlmanacBindingDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacBindingDeletePropertyTransaction.php',
'AlmanacBindingDisableController' => 'applications/almanac/controller/AlmanacBindingDisableController.php',
'AlmanacBindingDisableTransaction' => 'applications/almanac/xaction/AlmanacBindingDisableTransaction.php',
'AlmanacBindingEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacBindingEditConduitAPIMethod.php',
'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php',
'AlmanacBindingEditEngine' => 'applications/almanac/editor/AlmanacBindingEditEngine.php',
'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php',
'AlmanacBindingInterfaceTransaction' => 'applications/almanac/xaction/AlmanacBindingInterfaceTransaction.php',
'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php',
'AlmanacBindingPropertyEditEngine' => 'applications/almanac/editor/AlmanacBindingPropertyEditEngine.php',
'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php',
'AlmanacBindingSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacBindingSearchConduitAPIMethod.php',
'AlmanacBindingSearchEngine' => 'applications/almanac/query/AlmanacBindingSearchEngine.php',
'AlmanacBindingServiceTransaction' => 'applications/almanac/xaction/AlmanacBindingServiceTransaction.php',
'AlmanacBindingSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacBindingSetPropertyTransaction.php',
'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php',
'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php',
'AlmanacBindingTransactionQuery' => 'applications/almanac/query/AlmanacBindingTransactionQuery.php',
'AlmanacBindingTransactionType' => 'applications/almanac/xaction/AlmanacBindingTransactionType.php',
'AlmanacBindingViewController' => 'applications/almanac/controller/AlmanacBindingViewController.php',
'AlmanacBindingsSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php',
'AlmanacCacheEngineExtension' => 'applications/almanac/engineextension/AlmanacCacheEngineExtension.php',
@ -35,66 +44,94 @@ phutil_register_library_map(array(
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
'AlmanacCustomServiceType' => 'applications/almanac/servicetype/AlmanacCustomServiceType.php',
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
'AlmanacDeletePropertyEditField' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditField.php',
'AlmanacDeletePropertyEditType' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditType.php',
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php',
'AlmanacDeviceDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceDeletePropertyTransaction.php',
'AlmanacDeviceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceEditConduitAPIMethod.php',
'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php',
'AlmanacDeviceEditEngine' => 'applications/almanac/editor/AlmanacDeviceEditEngine.php',
'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php',
'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php',
'AlmanacDeviceNameTransaction' => 'applications/almanac/xaction/AlmanacDeviceNameTransaction.php',
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
'AlmanacDevicePropertyEditEngine' => 'applications/almanac/editor/AlmanacDevicePropertyEditEngine.php',
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
'AlmanacDeviceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php',
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
'AlmanacDeviceSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceSetPropertyTransaction.php',
'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php',
'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php',
'AlmanacDeviceTransactionType' => 'applications/almanac/xaction/AlmanacDeviceTransactionType.php',
'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php',
'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php',
'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php',
'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php',
'AlmanacInterfaceAddressTransaction' => 'applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php',
'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php',
'AlmanacInterfaceDeleteController' => 'applications/almanac/controller/AlmanacInterfaceDeleteController.php',
'AlmanacInterfaceDestroyTransaction' => 'applications/almanac/xaction/AlmanacInterfaceDestroyTransaction.php',
'AlmanacInterfaceDeviceTransaction' => 'applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php',
'AlmanacInterfaceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacInterfaceEditConduitAPIMethod.php',
'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php',
'AlmanacInterfaceEditEngine' => 'applications/almanac/editor/AlmanacInterfaceEditEngine.php',
'AlmanacInterfaceEditor' => 'applications/almanac/editor/AlmanacInterfaceEditor.php',
'AlmanacInterfaceNetworkTransaction' => 'applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php',
'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php',
'AlmanacInterfacePortTransaction' => 'applications/almanac/xaction/AlmanacInterfacePortTransaction.php',
'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php',
'AlmanacInterfaceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacInterfaceSearchConduitAPIMethod.php',
'AlmanacInterfaceSearchEngine' => 'applications/almanac/query/AlmanacInterfaceSearchEngine.php',
'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php',
'AlmanacInterfaceTransaction' => 'applications/almanac/storage/AlmanacInterfaceTransaction.php',
'AlmanacInterfaceTransactionType' => 'applications/almanac/xaction/AlmanacInterfaceTransactionType.php',
'AlmanacKeys' => 'applications/almanac/util/AlmanacKeys.php',
'AlmanacManageClusterServicesCapability' => 'applications/almanac/capability/AlmanacManageClusterServicesCapability.php',
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
'AlmanacManagementTrustKeyWorkflow' => 'applications/almanac/management/AlmanacManagementTrustKeyWorkflow.php',
'AlmanacManagementUntrustKeyWorkflow' => 'applications/almanac/management/AlmanacManagementUntrustKeyWorkflow.php',
'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php',
'AlmanacModularTransaction' => 'applications/almanac/storage/AlmanacModularTransaction.php',
'AlmanacNames' => 'applications/almanac/util/AlmanacNames.php',
'AlmanacNamesTestCase' => 'applications/almanac/util/__tests__/AlmanacNamesTestCase.php',
'AlmanacNamespace' => 'applications/almanac/storage/AlmanacNamespace.php',
'AlmanacNamespaceController' => 'applications/almanac/controller/AlmanacNamespaceController.php',
'AlmanacNamespaceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNamespaceEditConduitAPIMethod.php',
'AlmanacNamespaceEditController' => 'applications/almanac/controller/AlmanacNamespaceEditController.php',
'AlmanacNamespaceEditEngine' => 'applications/almanac/editor/AlmanacNamespaceEditEngine.php',
'AlmanacNamespaceEditor' => 'applications/almanac/editor/AlmanacNamespaceEditor.php',
'AlmanacNamespaceListController' => 'applications/almanac/controller/AlmanacNamespaceListController.php',
'AlmanacNamespaceNameNgrams' => 'applications/almanac/storage/AlmanacNamespaceNameNgrams.php',
'AlmanacNamespaceNameTransaction' => 'applications/almanac/xaction/AlmanacNamespaceNameTransaction.php',
'AlmanacNamespacePHIDType' => 'applications/almanac/phid/AlmanacNamespacePHIDType.php',
'AlmanacNamespaceQuery' => 'applications/almanac/query/AlmanacNamespaceQuery.php',
'AlmanacNamespaceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNamespaceSearchConduitAPIMethod.php',
'AlmanacNamespaceSearchEngine' => 'applications/almanac/query/AlmanacNamespaceSearchEngine.php',
'AlmanacNamespaceTransaction' => 'applications/almanac/storage/AlmanacNamespaceTransaction.php',
'AlmanacNamespaceTransactionQuery' => 'applications/almanac/query/AlmanacNamespaceTransactionQuery.php',
'AlmanacNamespaceTransactionType' => 'applications/almanac/xaction/AlmanacNamespaceTransactionType.php',
'AlmanacNamespaceViewController' => 'applications/almanac/controller/AlmanacNamespaceViewController.php',
'AlmanacNetwork' => 'applications/almanac/storage/AlmanacNetwork.php',
'AlmanacNetworkController' => 'applications/almanac/controller/AlmanacNetworkController.php',
'AlmanacNetworkEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNetworkEditConduitAPIMethod.php',
'AlmanacNetworkEditController' => 'applications/almanac/controller/AlmanacNetworkEditController.php',
'AlmanacNetworkEditEngine' => 'applications/almanac/editor/AlmanacNetworkEditEngine.php',
'AlmanacNetworkEditor' => 'applications/almanac/editor/AlmanacNetworkEditor.php',
'AlmanacNetworkListController' => 'applications/almanac/controller/AlmanacNetworkListController.php',
'AlmanacNetworkNameNgrams' => 'applications/almanac/storage/AlmanacNetworkNameNgrams.php',
'AlmanacNetworkNameTransaction' => 'applications/almanac/xaction/AlmanacNetworkNameTransaction.php',
'AlmanacNetworkPHIDType' => 'applications/almanac/phid/AlmanacNetworkPHIDType.php',
'AlmanacNetworkQuery' => 'applications/almanac/query/AlmanacNetworkQuery.php',
'AlmanacNetworkSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacNetworkSearchConduitAPIMethod.php',
'AlmanacNetworkSearchEngine' => 'applications/almanac/query/AlmanacNetworkSearchEngine.php',
'AlmanacNetworkTransaction' => 'applications/almanac/storage/AlmanacNetworkTransaction.php',
'AlmanacNetworkTransactionQuery' => 'applications/almanac/query/AlmanacNetworkTransactionQuery.php',
'AlmanacNetworkTransactionType' => 'applications/almanac/xaction/AlmanacNetworkTransactionType.php',
'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php',
'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php',
'AlmanacPropertiesEditEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesEditEngineExtension.php',
'AlmanacPropertiesSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php',
'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php',
'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php',
@ -109,23 +146,31 @@ phutil_register_library_map(array(
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php',
'AlmanacServiceDatasource' => 'applications/almanac/typeahead/AlmanacServiceDatasource.php',
'AlmanacServiceDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacServiceDeletePropertyTransaction.php',
'AlmanacServiceEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacServiceEditConduitAPIMethod.php',
'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php',
'AlmanacServiceEditEngine' => 'applications/almanac/editor/AlmanacServiceEditEngine.php',
'AlmanacServiceEditor' => 'applications/almanac/editor/AlmanacServiceEditor.php',
'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php',
'AlmanacServiceNameNgrams' => 'applications/almanac/storage/AlmanacServiceNameNgrams.php',
'AlmanacServiceNameTransaction' => 'applications/almanac/xaction/AlmanacServiceNameTransaction.php',
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
'AlmanacServicePropertyEditEngine' => 'applications/almanac/editor/AlmanacServicePropertyEditEngine.php',
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
'AlmanacServiceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacServiceSearchConduitAPIMethod.php',
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
'AlmanacServiceSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacServiceSetPropertyTransaction.php',
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
'AlmanacServiceTransactionType' => 'applications/almanac/xaction/AlmanacServiceTransactionType.php',
'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php',
'AlmanacServiceTypeDatasource' => 'applications/almanac/typeahead/AlmanacServiceTypeDatasource.php',
'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php',
'AlmanacServiceTypeTransaction' => 'applications/almanac/xaction/AlmanacServiceTypeTransaction.php',
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php',
'AlmanacSetPropertyEditField' => 'applications/almanac/engineextension/AlmanacSetPropertyEditField.php',
'AlmanacSetPropertyEditType' => 'applications/almanac/engineextension/AlmanacSetPropertyEditType.php',
'AlmanacTransactionType' => 'applications/almanac/xaction/AlmanacTransactionType.php',
'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php',
'Aphront304Response' => 'aphront/response/Aphront304Response.php',
'Aphront400Response' => 'aphront/response/Aphront400Response.php',
@ -632,6 +677,7 @@ phutil_register_library_map(array(
'DiffusionAuditorsAddSelfHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddSelfHeraldAction.php',
'DiffusionAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsHeraldAction.php',
'DiffusionBlameConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionBlameConduitAPIMethod.php',
'DiffusionBlameController' => 'applications/diffusion/controller/DiffusionBlameController.php',
'DiffusionBlameQuery' => 'applications/diffusion/query/blame/DiffusionBlameQuery.php',
'DiffusionBlockHeraldAction' => 'applications/diffusion/herald/DiffusionBlockHeraldAction.php',
'DiffusionBranchListView' => 'applications/diffusion/view/DiffusionBranchListView.php',
@ -732,6 +778,8 @@ phutil_register_library_map(array(
'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php',
'DiffusionDiffInlineCommentQuery' => 'applications/diffusion/query/DiffusionDiffInlineCommentQuery.php',
'DiffusionDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionDiffQueryConduitAPIMethod.php',
'DiffusionDocumentController' => 'applications/diffusion/controller/DiffusionDocumentController.php',
'DiffusionDocumentRenderingEngine' => 'applications/diffusion/document/DiffusionDocumentRenderingEngine.php',
'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php',
'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php',
'DiffusionExistsQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionExistsQueryConduitAPIMethod.php',
@ -2066,6 +2114,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationTransactionWarningException' => 'applications/transactions/exception/PhabricatorApplicationTransactionWarningException.php',
'PhabricatorApplicationTransactionWarningResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionWarningResponse.php',
'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php',
'PhabricatorApplicationUninstallTransaction' => 'applications/meta/xactions/PhabricatorApplicationUninstallTransaction.php',
'PhabricatorApplicationsApplication' => 'applications/meta/application/PhabricatorApplicationsApplication.php',
'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php',
'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php',
@ -2819,6 +2868,7 @@ phutil_register_library_map(array(
'PhabricatorDivinerApplication' => 'applications/diviner/application/PhabricatorDivinerApplication.php',
'PhabricatorDocumentEngine' => 'applications/files/document/PhabricatorDocumentEngine.php',
'PhabricatorDocumentRef' => 'applications/files/document/PhabricatorDocumentRef.php',
'PhabricatorDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorDocumentRenderingEngine.php',
'PhabricatorDoorkeeperApplication' => 'applications/doorkeeper/application/PhabricatorDoorkeeperApplication.php',
'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php',
'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php',
@ -3010,6 +3060,7 @@ phutil_register_library_map(array(
'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php',
'PhabricatorFileDeleteTransaction' => 'applications/files/xaction/PhabricatorFileDeleteTransaction.php',
'PhabricatorFileDocumentController' => 'applications/files/controller/PhabricatorFileDocumentController.php',
'PhabricatorFileDocumentRenderingEngine' => 'applications/files/document/render/PhabricatorFileDocumentRenderingEngine.php',
'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php',
'PhabricatorFileEditController' => 'applications/files/controller/PhabricatorFileEditController.php',
'PhabricatorFileEditEngine' => 'applications/files/editor/PhabricatorFileEditEngine.php',
@ -3185,6 +3236,7 @@ phutil_register_library_map(array(
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php',
'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php',
'PhabricatorIntEditField' => 'applications/transactions/editfield/PhabricatorIntEditField.php',
'PhabricatorIntExportField' => 'infrastructure/export/field/PhabricatorIntExportField.php',
'PhabricatorInternalSetting' => 'applications/settings/setting/PhabricatorInternalSetting.php',
'PhabricatorInternationalizationManagementExtractWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php',
@ -5156,7 +5208,6 @@ phutil_register_library_map(array(
'require_celerity_resource' => 'applications/celerity/api.php',
),
'xmap' => array(
'AlamancServiceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacAddress' => 'Phobject',
'AlmanacBinding' => array(
'AlmanacDAO',
@ -5165,16 +5216,27 @@ phutil_register_library_map(array(
'AlmanacPropertyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorExtendedPolicyInterface',
'PhabricatorConduitResultInterface',
),
'AlmanacBindingDeletePropertyTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingDisableController' => 'AlmanacServiceController',
'AlmanacBindingDisableTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacBindingEditController' => 'AlmanacServiceController',
'AlmanacBindingEditEngine' => 'PhabricatorEditEngine',
'AlmanacBindingEditor' => 'AlmanacEditor',
'AlmanacBindingInterfaceTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingPHIDType' => 'PhabricatorPHIDType',
'AlmanacBindingPropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacBindingQuery' => 'AlmanacQuery',
'AlmanacBindingSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacBindingSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacBindingServiceTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingSetPropertyTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingTableView' => 'AphrontView',
'AlmanacBindingTransaction' => 'AlmanacTransaction',
'AlmanacBindingTransaction' => 'AlmanacModularTransaction',
'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacBindingTransactionType' => 'AlmanacTransactionType',
'AlmanacBindingViewController' => 'AlmanacServiceController',
'AlmanacBindingsSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
'AlmanacCacheEngineExtension' => 'PhabricatorCacheEngineExtension',
@ -5189,6 +5251,8 @@ phutil_register_library_map(array(
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacCustomServiceType' => 'AlmanacServiceType',
'AlmanacDAO' => 'PhabricatorLiskDAO',
'AlmanacDeletePropertyEditField' => 'PhabricatorEditField',
'AlmanacDeletePropertyEditType' => 'PhabricatorEditType',
'AlmanacDevice' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
@ -5202,19 +5266,23 @@ phutil_register_library_map(array(
'PhabricatorExtendedPolicyInterface',
),
'AlmanacDeviceController' => 'AlmanacController',
'AlmanacDeviceDeletePropertyTransaction' => 'AlmanacDeviceTransactionType',
'AlmanacDeviceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
'AlmanacDeviceEditEngine' => 'PhabricatorEditEngine',
'AlmanacDeviceEditor' => 'AlmanacEditor',
'AlmanacDeviceListController' => 'AlmanacDeviceController',
'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacDeviceNameTransaction' => 'AlmanacDeviceTransactionType',
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacDeviceQuery' => 'AlmanacQuery',
'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacDeviceTransaction' => 'AlmanacTransaction',
'AlmanacDeviceSetPropertyTransaction' => 'AlmanacDeviceTransactionType',
'AlmanacDeviceTransaction' => 'AlmanacModularTransaction',
'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacDeviceTransactionType' => 'AlmanacTransactionType',
'AlmanacDeviceViewController' => 'AlmanacDeviceController',
'AlmanacDrydockPoolServiceType' => 'AlmanacServiceType',
'AlmanacEditor' => 'PhabricatorApplicationTransactionEditor',
@ -5223,19 +5291,34 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorExtendedPolicyInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorConduitResultInterface',
),
'AlmanacInterfaceAddressTransaction' => 'AlmanacInterfaceTransactionType',
'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacInterfaceDeleteController' => 'AlmanacDeviceController',
'AlmanacInterfaceDestroyTransaction' => 'AlmanacInterfaceTransactionType',
'AlmanacInterfaceDeviceTransaction' => 'AlmanacInterfaceTransactionType',
'AlmanacInterfaceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacInterfaceEditController' => 'AlmanacDeviceController',
'AlmanacInterfaceEditEngine' => 'PhabricatorEditEngine',
'AlmanacInterfaceEditor' => 'AlmanacEditor',
'AlmanacInterfaceNetworkTransaction' => 'AlmanacInterfaceTransactionType',
'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType',
'AlmanacInterfacePortTransaction' => 'AlmanacInterfaceTransactionType',
'AlmanacInterfaceQuery' => 'AlmanacQuery',
'AlmanacInterfaceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacInterfaceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacInterfaceTableView' => 'AphrontView',
'AlmanacInterfaceTransaction' => 'AlmanacModularTransaction',
'AlmanacInterfaceTransactionType' => 'AlmanacTransactionType',
'AlmanacKeys' => 'Phobject',
'AlmanacManageClusterServicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
'AlmanacManagementTrustKeyWorkflow' => 'AlmanacManagementWorkflow',
'AlmanacManagementUntrustKeyWorkflow' => 'AlmanacManagementWorkflow',
'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow',
'AlmanacModularTransaction' => 'PhabricatorModularTransaction',
'AlmanacNames' => 'Phobject',
'AlmanacNamesTestCase' => 'PhabricatorTestCase',
'AlmanacNamespace' => array(
@ -5246,18 +5329,23 @@ phutil_register_library_map(array(
'AlmanacPropertyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorNgramsInterface',
'PhabricatorConduitResultInterface',
),
'AlmanacNamespaceController' => 'AlmanacController',
'AlmanacNamespaceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacNamespaceEditController' => 'AlmanacNamespaceController',
'AlmanacNamespaceEditEngine' => 'PhabricatorEditEngine',
'AlmanacNamespaceEditor' => 'PhabricatorApplicationTransactionEditor',
'AlmanacNamespaceEditor' => 'AlmanacEditor',
'AlmanacNamespaceListController' => 'AlmanacNamespaceController',
'AlmanacNamespaceNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacNamespaceNameTransaction' => 'AlmanacNamespaceTransactionType',
'AlmanacNamespacePHIDType' => 'PhabricatorPHIDType',
'AlmanacNamespaceQuery' => 'AlmanacQuery',
'AlmanacNamespaceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacNamespaceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacNamespaceTransaction' => 'PhabricatorApplicationTransaction',
'AlmanacNamespaceTransaction' => 'AlmanacModularTransaction',
'AlmanacNamespaceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacNamespaceTransactionType' => 'AlmanacTransactionType',
'AlmanacNamespaceViewController' => 'AlmanacNamespaceController',
'AlmanacNetwork' => array(
'AlmanacDAO',
@ -5265,20 +5353,26 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorNgramsInterface',
'PhabricatorConduitResultInterface',
),
'AlmanacNetworkController' => 'AlmanacController',
'AlmanacNetworkEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacNetworkEditController' => 'AlmanacNetworkController',
'AlmanacNetworkEditEngine' => 'PhabricatorEditEngine',
'AlmanacNetworkEditor' => 'PhabricatorApplicationTransactionEditor',
'AlmanacNetworkEditor' => 'AlmanacEditor',
'AlmanacNetworkListController' => 'AlmanacNetworkController',
'AlmanacNetworkNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacNetworkNameTransaction' => 'AlmanacNetworkTransactionType',
'AlmanacNetworkPHIDType' => 'PhabricatorPHIDType',
'AlmanacNetworkQuery' => 'AlmanacQuery',
'AlmanacNetworkSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacNetworkSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacNetworkTransaction' => 'PhabricatorApplicationTransaction',
'AlmanacNetworkTransaction' => 'AlmanacModularTransaction',
'AlmanacNetworkTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacNetworkTransactionType' => 'AlmanacTransactionType',
'AlmanacNetworkViewController' => 'AlmanacNetworkController',
'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'AlmanacPropertiesEditEngineExtension' => 'PhabricatorEditEngineExtension',
'AlmanacPropertiesSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
'AlmanacProperty' => array(
'AlmanacDAO',
@ -5305,23 +5399,31 @@ phutil_register_library_map(array(
),
'AlmanacServiceController' => 'AlmanacController',
'AlmanacServiceDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacServiceDeletePropertyTransaction' => 'AlmanacServiceTransactionType',
'AlmanacServiceEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacServiceEditController' => 'AlmanacServiceController',
'AlmanacServiceEditEngine' => 'PhabricatorEditEngine',
'AlmanacServiceEditor' => 'AlmanacEditor',
'AlmanacServiceListController' => 'AlmanacServiceController',
'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacServiceNameTransaction' => 'AlmanacServiceTransactionType',
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacServiceQuery' => 'AlmanacQuery',
'AlmanacServiceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacServiceTransaction' => 'AlmanacTransaction',
'AlmanacServiceSetPropertyTransaction' => 'AlmanacServiceTransactionType',
'AlmanacServiceTransaction' => 'AlmanacModularTransaction',
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacServiceTransactionType' => 'AlmanacTransactionType',
'AlmanacServiceType' => 'Phobject',
'AlmanacServiceTypeDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase',
'AlmanacServiceTypeTransaction' => 'AlmanacServiceTransactionType',
'AlmanacServiceViewController' => 'AlmanacServiceController',
'AlmanacTransaction' => 'PhabricatorApplicationTransaction',
'AlmanacSetPropertyEditField' => 'PhabricatorEditField',
'AlmanacSetPropertyEditType' => 'PhabricatorEditType',
'AlmanacTransactionType' => 'PhabricatorModularTransactionType',
'AphlictDropdownDataQuery' => 'Phobject',
'Aphront304Response' => 'AphrontResponse',
'Aphront400Response' => 'AphrontResponse',
@ -5885,6 +5987,7 @@ phutil_register_library_map(array(
'DiffusionAuditorsAddSelfHeraldAction' => 'DiffusionAuditorsHeraldAction',
'DiffusionAuditorsHeraldAction' => 'HeraldAction',
'DiffusionBlameConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
'DiffusionBlameController' => 'DiffusionController',
'DiffusionBlameQuery' => 'DiffusionQuery',
'DiffusionBlockHeraldAction' => 'HeraldAction',
'DiffusionBranchListView' => 'DiffusionView',
@ -5985,6 +6088,8 @@ phutil_register_library_map(array(
'DiffusionDiffController' => 'DiffusionController',
'DiffusionDiffInlineCommentQuery' => 'PhabricatorDiffInlineCommentQuery',
'DiffusionDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
'DiffusionDocumentController' => 'DiffusionController',
'DiffusionDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine',
'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher',
'DiffusionEmptyResultView' => 'DiffusionView',
'DiffusionExistsQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod',
@ -7525,6 +7630,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationTransactionWarningException' => 'Exception',
'PhabricatorApplicationTransactionWarningResponse' => 'AphrontProxyResponse',
'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationUninstallTransaction' => 'PhabricatorApplicationTransactionType',
'PhabricatorApplicationsApplication' => 'PhabricatorApplication',
'PhabricatorApplicationsController' => 'PhabricatorController',
'PhabricatorApplicationsListController' => 'PhabricatorApplicationsController',
@ -8401,6 +8507,7 @@ phutil_register_library_map(array(
'PhabricatorDivinerApplication' => 'PhabricatorApplication',
'PhabricatorDocumentEngine' => 'Phobject',
'PhabricatorDocumentRef' => 'Phobject',
'PhabricatorDocumentRenderingEngine' => 'Phobject',
'PhabricatorDoorkeeperApplication' => 'PhabricatorApplication',
'PhabricatorDraft' => 'PhabricatorDraftDAO',
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
@ -8624,6 +8731,7 @@ phutil_register_library_map(array(
'PhabricatorFileDeleteController' => 'PhabricatorFileController',
'PhabricatorFileDeleteTransaction' => 'PhabricatorFileTransactionType',
'PhabricatorFileDocumentController' => 'PhabricatorFileController',
'PhabricatorFileDocumentRenderingEngine' => 'PhabricatorDocumentRenderingEngine',
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
'PhabricatorFileEditController' => 'PhabricatorFileController',
'PhabricatorFileEditEngine' => 'PhabricatorEditEngine',
@ -8816,6 +8924,7 @@ phutil_register_library_map(array(
'PhabricatorInlineSummaryView' => 'AphrontView',
'PhabricatorInstructionsEditField' => 'PhabricatorEditField',
'PhabricatorIntConfigType' => 'PhabricatorTextConfigType',
'PhabricatorIntEditField' => 'PhabricatorEditField',
'PhabricatorIntExportField' => 'PhabricatorExportField',
'PhabricatorInternalSetting' => 'PhabricatorSetting',
'PhabricatorInternationalizationManagementExtractWorkflow' => 'PhabricatorInternationalizationManagementWorkflow',

View file

@ -61,6 +61,10 @@ final class AphrontRequest extends Phobject {
*/
public function getURILineRange($key, $limit) {
$range = $this->getURIData($key);
return self::parseURILineRange($range, $limit);
}
public static function parseURILineRange($range, $limit) {
if (!strlen($range)) {
return null;
}

View file

@ -0,0 +1,19 @@
<?php
final class AlmanacBindingEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.binding.edit';
}
public function newEditEngine() {
return new AlmanacBindingEditEngine();
}
public function getMethodSummary() {
return pht(
'Apply transactions to create a new binding or edit an existing one.');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacBindingSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.binding.search';
}
public function newSearchEngine() {
return new AlmanacBindingSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Almanac bindings.');
}
}

View file

@ -0,0 +1,19 @@
<?php
final class AlmanacInterfaceEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.interface.edit';
}
public function newEditEngine() {
return new AlmanacInterfaceEditEngine();
}
public function getMethodSummary() {
return pht(
'Apply transactions to create a new interface or edit an existing one.');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacInterfaceSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.interface.search';
}
public function newSearchEngine() {
return new AlmanacInterfaceSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Almanac interfaces.');
}
}

View file

@ -0,0 +1,19 @@
<?php
final class AlmanacNamespaceEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.namespace.edit';
}
public function newEditEngine() {
return new AlmanacNamespaceEditEngine();
}
public function getMethodSummary() {
return pht(
'Apply transactions to create a new namespace or edit an existing one.');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacNamespaceSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.namespace.search';
}
public function newSearchEngine() {
return new AlmanacNamespaceSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Almanac namespaces.');
}
}

View file

@ -0,0 +1,19 @@
<?php
final class AlmanacNetworkEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.network.edit';
}
public function newEditEngine() {
return new AlmanacNetworkEditEngine();
}
public function getMethodSummary() {
return pht(
'Apply transactions to create a new network or edit an existing one.');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacNetworkSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.network.search';
}
public function newSearchEngine() {
return new AlmanacNetworkSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Almanac networks.');
}
}

View file

@ -1,6 +1,6 @@
<?php
final class AlamancServiceEditConduitAPIMethod
final class AlmanacServiceEditConduitAPIMethod
extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {

View file

@ -40,7 +40,7 @@ final class AlmanacBindingDisableController
if ($request->isFormPost()) {
$type_disable = AlmanacBindingTransaction::TYPE_DISABLE;
$type_disable = AlmanacBindingDisableTransaction::TRANSACTIONTYPE;
$xactions = array();

View file

@ -58,7 +58,7 @@ final class AlmanacBindingEditController
if ($request->isFormPost()) {
$v_interface = $request->getArr('interfacePHIDs');
$type_interface = AlmanacBindingTransaction::TYPE_INTERFACE;
$type_interface = AlmanacBindingInterfaceTransaction::TRANSACTIONTYPE;
$xactions = array();

View file

@ -38,7 +38,7 @@ abstract class AlmanacController
));
$builtins = $object->getAlmanacPropertyFieldSpecifications();
$defaults = mpull($builtins, null, 'getValueForTransaction');
$defaults = mpull($builtins, 'getValueForTransaction');
// Sort fields so builtin fields appear first, then fields are ordered
// alphabetically.
@ -65,6 +65,7 @@ abstract class AlmanacController
$value = $property->getFieldValue();
$is_builtin = isset($builtins[$key]);
$is_persistent = (bool)$property->getID();
$delete_uri = id(new PhutilURI($delete_base))
->setQueryParams(
@ -83,7 +84,7 @@ abstract class AlmanacController
$delete = javelin_tag(
'a',
array(
'class' => ($can_edit
'class' => (($can_edit && $is_persistent)
? 'button button-grey small'
: 'button button-grey small disabled'),
'sigil' => 'workflow',

View file

@ -34,26 +34,21 @@ final class AlmanacInterfaceDeleteController
}
if ($request->isFormPost()) {
$type_interface = AlmanacDeviceTransaction::TYPE_INTERFACE;
$type_destroy = AlmanacInterfaceDestroyTransaction::TRANSACTIONTYPE;
$xactions = array();
$v_old = array(
'id' => $interface->getID(),
) + $interface->toAddress()->toDictionary();
$xactions[] = $interface->getApplicationTransactionTemplate()
->setTransactionType($type_destroy)
->setNewValue(true);
$xactions[] = id(new AlmanacDeviceTransaction())
->setTransactionType($type_interface)
->setOldValue($v_old)
->setNewValue(null);
$editor = id(new AlmanacDeviceEditor())
$editor = id(new AlmanacInterfaceEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
$editor->applyTransactions($device, $xactions);
$editor->applyTransactions($interface, $xactions);
return id(new AphrontRedirectResponse())->setURI($device_uri);
}

View file

@ -4,32 +4,16 @@ final class AlmanacInterfaceEditController
extends AlmanacDeviceController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$viewer = $this->getViewer();
$engine = id(new AlmanacInterfaceEditEngine())
->setController($this);
$id = $request->getURIData('id');
if ($id) {
$interface = id(new AlmanacInterfaceQuery())
->setViewer($viewer)
->withIDs(array($id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$interface) {
return new Aphront404Response();
}
$device = $interface->getDevice();
$is_new = false;
$title = pht('Edit Interface');
$save_button = pht('Save Changes');
} else {
if (!$id) {
$device = id(new AlmanacDeviceQuery())
->setViewer($viewer)
->withIDs(array($request->getStr('deviceID')))
->withIDs(array($request->getInt('deviceID')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
@ -40,127 +24,12 @@ final class AlmanacInterfaceEditController
return new Aphront404Response();
}
$interface = AlmanacInterface::initializeNewInterface();
$is_new = true;
$title = pht('Create Interface');
$save_button = pht('Create Interface');
$engine
->addContextParameter('deviceID', $device->getID())
->setDevice($device);
}
$device_uri = $device->getURI();
$cancel_uri = $device_uri;
$v_network = $interface->getNetworkPHID();
$v_address = $interface->getAddress();
$e_address = true;
$v_port = $interface->getPort();
$validation_exception = null;
if ($request->isFormPost()) {
$v_network = $request->getStr('networkPHID');
$v_address = $request->getStr('address');
$v_port = $request->getStr('port');
$type_interface = AlmanacDeviceTransaction::TYPE_INTERFACE;
$address = AlmanacAddress::newFromParts($v_network, $v_address, $v_port);
$xaction = id(new AlmanacDeviceTransaction())
->setTransactionType($type_interface)
->setNewValue($address->toDictionary());
if ($interface->getID()) {
$xaction->setOldValue(array(
'id' => $interface->getID(),
) + $interface->toAddress()->toDictionary());
} else {
$xaction->setOldValue(array());
}
$xactions = array();
$xactions[] = $xaction;
$editor = id(new AlmanacDeviceEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true);
try {
$editor->applyTransactions($device, $xactions);
$device_uri = $device->getURI();
return id(new AphrontRedirectResponse())->setURI($device_uri);
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$e_address = $ex->getShortMessage($type_interface);
}
}
$networks = id(new AlmanacNetworkQuery())
->setViewer($viewer)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Network'))
->setName('networkPHID')
->setValue($v_network)
->setOptions(mpull($networks, 'getName', 'getPHID')))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Address'))
->setName('address')
->setValue($v_address)
->setError($e_address))
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Port'))
->setName('port')
->setValue($v_port)
->setError($e_address))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($cancel_uri)
->setValue($save_button));
$box = id(new PHUIObjectBoxView())
->setValidationException($validation_exception)
->setHeaderText(pht('Interface'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setForm($form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb($device->getName(), $device_uri);
if ($is_new) {
$crumbs->addTextCrumb(pht('Create Interface'));
$header = id(new PHUIHeaderView())
->setHeader(pht('Create Interface'))
->setHeaderIcon('fa-plus-square');
} else {
$crumbs->addTextCrumb(pht('Edit Interface'));
$header = id(new PHUIHeaderView())
->setHeader(pht('Edit Interface'))
->setHeaderIcon('fa-pencil');
}
$crumbs->setBorder(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$box,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
return $engine->buildResponse();
}
}

View file

@ -39,8 +39,10 @@ final class AlmanacPropertyDeleteController
$validation_exception = null;
if ($request->isFormPost()) {
$xaction_type = $object->getAlmanacPropertyDeleteTransactionType();
$xaction = $object->getApplicationTransactionTemplate()
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
->setTransactionType($xaction_type)
->setMetadataValue('almanac.property', $key);
$editor = $object->getApplicationTransactionEditor()

View file

@ -0,0 +1,172 @@
<?php
final class AlmanacBindingEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.binding';
private $service;
public function setService(AlmanacService $service) {
$this->service = $service;
return $this;
}
public function getService() {
if (!$this->service) {
throw new PhutilInvalidStateException('setService');
}
return $this->service;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Bindings');
}
public function getSummaryHeader() {
return pht('Edit Almanac Binding Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac bindings.');
}
public function getEngineApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
protected function newEditableObject() {
$service = $this->getService();
return AlmanacBinding::initializeNewBinding($service);
}
protected function newEditableObjectForDocumentation() {
$service_type = AlmanacCustomServiceType::SERVICETYPE;
$service = AlmanacService::initializeNewService($service_type);
$this->setService($service);
return $this->newEditableObject();
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$service_phid = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'service') {
continue;
}
$service_phid = $raw_xaction['value'];
}
if ($service_phid === null) {
throw new Exception(
pht(
'When creating a new Almanac binding via the Conduit API, you '.
'must provide a "service" transaction to select a service to bind.'));
}
$service = id(new AlmanacServiceQuery())
->setViewer($this->getViewer())
->withPHIDs(array($service_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$service) {
throw new Exception(
pht(
'Service "%s" is unrecognized, restricted, or you do not have '.
'permission to edit it.',
$service_phid));
}
$this->setService($service);
return $this->newEditableObject();
}
protected function newObjectQuery() {
return id(new AlmanacBindingQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {
return pht('Create Binding');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Binding');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Binding');
}
protected function getObjectEditShortText($object) {
return pht('Edit Binding');
}
protected function getObjectCreateShortText() {
return pht('Create Binding');
}
protected function getObjectName() {
return pht('Binding');
}
protected function getEditorURI() {
return '/almanac/binding/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/binding/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorTextEditField())
->setKey('service')
->setLabel(pht('Service'))
->setIsConduitOnly(true)
->setTransactionType(
AlmanacBindingServiceTransaction::TRANSACTIONTYPE)
->setDescription(pht('Service to create a binding for.'))
->setConduitDescription(pht('Select the service to bind.'))
->setConduitTypeDescription(pht('Service PHID.'))
->setValue($object->getServicePHID()),
id(new PhabricatorTextEditField())
->setKey('interface')
->setLabel(pht('Interface'))
->setIsConduitOnly(true)
->setTransactionType(
AlmanacBindingInterfaceTransaction::TRANSACTIONTYPE)
->setDescription(pht('Interface to bind the service to.'))
->setConduitDescription(pht('Set the interface to bind.'))
->setConduitTypeDescription(pht('Interface PHID.'))
->setValue($object->getInterfacePHID()),
id(new PhabricatorBoolEditField())
->setKey('disabled')
->setLabel(pht('Disabled'))
->setIsConduitOnly(true)
->setTransactionType(
AlmanacBindingDisableTransaction::TRANSACTIONTYPE)
->setDescription(pht('Disable or enable the binding.'))
->setConduitDescription(pht('Disable or enable the binding.'))
->setConduitTypeDescription(pht('True to disable the binding.'))
->setValue($object->getIsDisabled())
->setOptions(
pht('Enable Binding'),
pht('Disable Binding')),
);
}
}

View file

@ -3,173 +3,20 @@
final class AlmanacBindingEditor
extends AlmanacEditor {
private $devicePHID;
public function getEditorObjectsDescription() {
return pht('Almanac Binding');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = AlmanacBindingTransaction::TYPE_INTERFACE;
$types[] = AlmanacBindingTransaction::TYPE_DISABLE;
return $types;
public function getCreateObjectTitle($author, $object) {
return pht('%s created this binding.', $author);
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacBindingTransaction::TYPE_INTERFACE:
return $object->getInterfacePHID();
case AlmanacBindingTransaction::TYPE_DISABLE:
return $object->getIsDisabled();
}
return parent::getCustomTransactionOldValue($object, $xaction);
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacBindingTransaction::TYPE_INTERFACE:
return $xaction->getNewValue();
case AlmanacBindingTransaction::TYPE_DISABLE:
return (int)$xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
protected function supportsSearch() {
return true;
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacBindingTransaction::TYPE_INTERFACE:
$interface = id(new AlmanacInterfaceQuery())
->setViewer($this->requireActor())
->withPHIDs(array($xaction->getNewValue()))
->executeOne();
$object->setDevicePHID($interface->getDevicePHID());
$object->setInterfacePHID($interface->getPHID());
return;
case AlmanacBindingTransaction::TYPE_DISABLE:
$object->setIsDisabled($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacBindingTransaction::TYPE_DISABLE:
return;
case AlmanacBindingTransaction::TYPE_INTERFACE:
$interface_phids = array();
$interface_phids[] = $xaction->getOldValue();
$interface_phids[] = $xaction->getNewValue();
$interface_phids = array_filter($interface_phids);
$interface_phids = array_unique($interface_phids);
$interfaces = id(new AlmanacInterfaceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($interface_phids)
->execute();
$device_phids = array();
foreach ($interfaces as $interface) {
$device_phids[] = $interface->getDevicePHID();
}
$device_phids = array_unique($device_phids);
$devices = id(new AlmanacDeviceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($device_phids)
->execute();
foreach ($devices as $device) {
$device->rebuildClusterBindingStatus();
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case AlmanacBindingTransaction::TYPE_INTERFACE:
$missing = $this->validateIsEmptyTextField(
$object->getInterfacePHID(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Bindings must specify an interface.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
} else if ($xactions) {
foreach ($xactions as $xaction) {
$interfaces = id(new AlmanacInterfaceQuery())
->setViewer($this->requireActor())
->withPHIDs(array($xaction->getNewValue()))
->execute();
if (!$interfaces) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'You can not bind a service to an invalid or restricted '.
'interface.'),
$xaction);
$errors[] = $error;
}
}
$final_value = last($xactions)->getNewValue();
$binding = id(new AlmanacBindingQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withServicePHIDs(array($object->getServicePHID()))
->withInterfacePHIDs(array($final_value))
->executeOne();
if ($binding && ($binding->getID() != $object->getID())) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Already Bound'),
pht(
'You can not bind a service to the same interface multiple '.
'times.'),
last($xactions));
$errors[] = $error;
}
}
break;
}
return $errors;
}
}

View file

@ -30,7 +30,8 @@ final class AlmanacDeviceEditEngine
}
protected function newObjectQuery() {
return new AlmanacDeviceQuery();
return id(new AlmanacDeviceQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {
@ -80,7 +81,7 @@ final class AlmanacDeviceEditEngine
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the device.'))
->setTransactionType(AlmanacDeviceTransaction::TYPE_NAME)
->setTransactionType(AlmanacDeviceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);

View file

@ -7,329 +7,25 @@ final class AlmanacDeviceEditor
return pht('Almanac Device');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this device.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = AlmanacDeviceTransaction::TYPE_NAME;
$types[] = AlmanacDeviceTransaction::TYPE_INTERFACE;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacDeviceTransaction::TYPE_NAME:
return $object->getName();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacDeviceTransaction::TYPE_NAME:
case AlmanacDeviceTransaction::TYPE_INTERFACE:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacDeviceTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
case AlmanacDeviceTransaction::TYPE_INTERFACE:
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacDeviceTransaction::TYPE_NAME:
return;
case AlmanacDeviceTransaction::TYPE_INTERFACE:
$old = $xaction->getOldValue();
if ($old) {
$interface = id(new AlmanacInterfaceQuery())
->setViewer($this->requireActor())
->withIDs(array($old['id']))
->executeOne();
if (!$interface) {
throw new Exception(pht('Unable to load interface!'));
}
} else {
$interface = AlmanacInterface::initializeNewInterface()
->setDevicePHID($object->getPHID());
}
$new = $xaction->getNewValue();
if ($new) {
$interface
->setNetworkPHID($new['networkPHID'])
->setAddress($new['address'])
->setPort((int)$new['port']);
if (idx($new, 'phid')) {
$interface->setPHID($new['phid']);
}
$interface->save();
} else {
$interface->delete();
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case AlmanacDeviceTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Device name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
} else {
foreach ($xactions as $xaction) {
$message = null;
$name = $xaction->getNewValue();
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
$errors[] = $error;
continue;
}
$other = id(new AlmanacDeviceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($name))
->executeOne();
if ($other && ($other->getID() != $object->getID())) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Unique'),
pht('Almanac devices must have unique names.'),
$xaction);
$errors[] = $error;
continue;
}
if ($name === $object->getName()) {
continue;
}
$namespace = AlmanacNamespace::loadRestrictedNamespace(
$this->getActor(),
$name);
if ($namespace) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Restricted'),
pht(
'You do not have permission to create Almanac devices '.
'within the "%s" namespace.',
$namespace->getName()),
$xaction);
$errors[] = $error;
continue;
}
}
}
break;
case AlmanacDeviceTransaction::TYPE_INTERFACE:
// We want to make sure that all the affected networks are visible to
// the actor, any edited interfaces exist, and that the actual address
// components are valid.
$network_phids = array();
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
if ($old) {
$network_phids[] = $old['networkPHID'];
}
if ($new) {
$network_phids[] = $new['networkPHID'];
$address = $new['address'];
if (!strlen($address)) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('Interfaces must have an address.'),
$xaction);
$errors[] = $error;
} else {
// TODO: Validate addresses, but IPv6 addresses are not trivial
// to validate.
}
$port = $new['port'];
if (!strlen($port)) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('Interfaces must have a port.'),
$xaction);
$errors[] = $error;
} else if ((int)$port < 1 || (int)$port > 65535) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Port numbers must be between 1 and 65535, inclusive.'),
$xaction);
$errors[] = $error;
}
$phid = idx($new, 'phid');
if ($phid) {
$interface_phid_type = AlmanacInterfacePHIDType::TYPECONST;
if (phid_get_type($phid) !== $interface_phid_type) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'Precomputed interface PHIDs must be of type '.
'AlmanacInterfacePHIDType.'),
$xaction);
$errors[] = $error;
}
}
}
}
if ($network_phids) {
$networks = id(new AlmanacNetworkQuery())
->setViewer($this->requireActor())
->withPHIDs($network_phids)
->execute();
$networks = mpull($networks, null, 'getPHID');
} else {
$networks = array();
}
$addresses = array();
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
if ($old) {
$network = idx($networks, $old['networkPHID']);
if (!$network) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'You can not edit an interface which belongs to a '.
'nonexistent or restricted network.'),
$xaction);
$errors[] = $error;
}
$addresses[] = $old['id'];
}
$new = $xaction->getNewValue();
if ($new) {
$network = idx($networks, $new['networkPHID']);
if (!$network) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'You can not add an interface on a nonexistent or '.
'restricted network.'),
$xaction);
$errors[] = $error;
}
}
}
if ($addresses) {
$interfaces = id(new AlmanacInterfaceQuery())
->setViewer($this->requireActor())
->withDevicePHIDs(array($object->getPHID()))
->withIDs($addresses)
->execute();
$interfaces = mpull($interfaces, null, 'getID');
} else {
$interfaces = array();
}
foreach ($xactions as $xaction) {
$old = $xaction->getOldValue();
if ($old) {
$interface = idx($interfaces, $old['id']);
if (!$interface) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht('You can not edit an invalid or restricted interface.'),
$xaction);
$errors[] = $error;
continue;
}
$new = $xaction->getNewValue();
if (!$new) {
if ($interface->loadIsInUse()) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('In Use'),
pht('You can not delete an interface which is still in use.'),
$xaction);
$errors[] = $error;
}
}
}
}
break;
}
return $errors;
}
}

View file

@ -7,150 +7,4 @@ abstract class AlmanacEditor
return 'PhabricatorAlmanacApplication';
}
protected function supportsSearch() {
return true;
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = AlmanacTransaction::TYPE_PROPERTY_UPDATE;
$types[] = AlmanacTransaction::TYPE_PROPERTY_REMOVE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
$property_key = $xaction->getMetadataValue('almanac.property');
$exists = $object->hasAlmanacProperty($property_key);
$value = $object->getAlmanacPropertyValue($property_key);
return array(
'existed' => $exists,
'value' => $value,
);
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
$property_key = $xaction->getMetadataValue('almanac.property');
if ($object->hasAlmanacProperty($property_key)) {
$property = $object->getAlmanacProperty($property_key);
} else {
$property = id(new AlmanacProperty())
->setObjectPHID($object->getPHID())
->setFieldName($property_key);
}
$property
->setFieldValue($xaction->getNewValue())
->save();
return;
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
$property_key = $xaction->getMetadataValue('almanac.property');
if ($object->hasAlmanacProperty($property_key)) {
$property = $object->getAlmanacProperty($property_key);
$property->delete();
}
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
foreach ($xactions as $xaction) {
$property_key = $xaction->getMetadataValue('almanac.property');
$message = null;
try {
AlmanacNames::validateName($property_key);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
$errors[] = $error;
continue;
}
$new_value = $xaction->getNewValue();
try {
phutil_json_encode($new_value);
} catch (Exception $ex) {
$message = pht(
'Almanac property values must be representable in JSON. %s',
$ex->getMessage());
}
if ($message !== null) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
$errors[] = $error;
continue;
}
}
break;
case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
// NOTE: No name validation on removals since it's OK to delete
// an invalid property that somehow came into existence.
break;
}
return $errors;
}
}

View file

@ -0,0 +1,183 @@
<?php
final class AlmanacInterfaceEditEngine
extends PhabricatorEditEngine {
const ENGINECONST = 'almanac.interface';
private $device;
public function setDevice(AlmanacDevice $device) {
$this->device = $device;
return $this;
}
public function getDevice() {
if (!$this->device) {
throw new PhutilInvalidStateException('setDevice');
}
return $this->device;
}
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Almanac Interfaces');
}
public function getSummaryHeader() {
return pht('Edit Almanac Interface Configurations');
}
public function getSummaryText() {
return pht('This engine is used to edit Almanac interfaces.');
}
public function getEngineApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
protected function newEditableObject() {
$interface = AlmanacInterface::initializeNewInterface();
$device = $this->getDevice();
$interface
->setDevicePHID($device->getPHID())
->attachDevice($device);
return $interface;
}
protected function newEditableObjectForDocumentation() {
$this->setDevice(new AlmanacDevice());
return $this->newEditableObject();
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$device_phid = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'device') {
continue;
}
$device_phid = $raw_xaction['value'];
}
if ($device_phid === null) {
throw new Exception(
pht(
'When creating a new Almanac interface via the Conduit API, you '.
'must provide a "device" transaction to select a device.'));
}
$device = id(new AlmanacDeviceQuery())
->setViewer($this->getViewer())
->withPHIDs(array($device_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$device) {
throw new Exception(
pht(
'Device "%s" is unrecognized, restricted, or you do not have '.
'permission to edit it.',
$device_phid));
}
$this->setDevice($device);
return $this->newEditableObject();
}
protected function newObjectQuery() {
return new AlmanacInterfaceQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Interface');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Interface');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Interface');
}
protected function getObjectEditShortText($object) {
return pht('Edit Interface');
}
protected function getObjectCreateShortText() {
return pht('Create Interface');
}
protected function getObjectName() {
return pht('Interface');
}
protected function getEditorURI() {
return '/almanac/interface/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/almanac/interface/';
}
protected function getObjectViewURI($object) {
return $object->getDevice()->getURI();
}
protected function buildCustomEditFields($object) {
$viewer = $this->getViewer();
// TODO: Some day, this should be a datasource.
$networks = id(new AlmanacNetworkQuery())
->setViewer($viewer)
->execute();
$network_map = mpull($networks, 'getName', 'getPHID');
return array(
id(new PhabricatorTextEditField())
->setKey('device')
->setLabel(pht('Device'))
->setIsConduitOnly(true)
->setTransactionType(
AlmanacInterfaceDeviceTransaction::TRANSACTIONTYPE)
->setDescription(pht('When creating an interface, set the device.'))
->setConduitDescription(pht('Set the device.'))
->setConduitTypeDescription(pht('Device PHID.'))
->setValue($object->getDevicePHID()),
id(new PhabricatorSelectEditField())
->setKey('network')
->setLabel(pht('Network'))
->setDescription(pht('Network for the interface.'))
->setTransactionType(
AlmanacInterfaceNetworkTransaction::TRANSACTIONTYPE)
->setValue($object->getNetworkPHID())
->setOptions($network_map),
id(new PhabricatorTextEditField())
->setKey('address')
->setLabel(pht('Address'))
->setDescription(pht('Address of the service.'))
->setTransactionType(
AlmanacInterfaceAddressTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getAddress()),
id(new PhabricatorIntEditField())
->setKey('port')
->setLabel(pht('Port'))
->setDescription(pht('Port of the service.'))
->setTransactionType(AlmanacInterfacePortTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getPort()),
);
}
}

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacInterfaceEditor
extends AlmanacEditor {
public function getEditorObjectsDescription() {
return pht('Almanac Interface');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this interface.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}

View file

@ -81,7 +81,7 @@ final class AlmanacNamespaceEditEngine
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the namespace.'))
->setTransactionType(AlmanacNamespaceTransaction::TYPE_NAME)
->setTransactionType(AlmanacNamespaceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);

View file

@ -1,16 +1,20 @@
<?php
final class AlmanacNamespaceEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
extends AlmanacEditor {
public function getEditorObjectsDescription() {
return pht('Almanac Namespace');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this namespace.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
@ -18,149 +22,12 @@ final class AlmanacNamespaceEditor
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = AlmanacNamespaceTransaction::TYPE_NAME;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNamespaceTransaction::TYPE_NAME:
return $object->getName();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNamespaceTransaction::TYPE_NAME:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNamespaceTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNamespaceTransaction::TYPE_NAME:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case AlmanacNamespaceTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Namespace name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
} else {
foreach ($xactions as $xaction) {
$name = $xaction->getNewValue();
$message = null;
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
$errors[] = $error;
continue;
}
$other = id(new AlmanacNamespaceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($name))
->executeOne();
if ($other && ($other->getID() != $object->getID())) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Unique'),
pht(
'The namespace name "%s" is already in use by another '.
'namespace. Each namespace must have a unique name.',
$name),
$xaction);
$errors[] = $error;
continue;
}
if ($name === $object->getName()) {
continue;
}
$namespace = AlmanacNamespace::loadRestrictedNamespace(
$this->getActor(),
$name);
if ($namespace) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Restricted'),
pht(
'You do not have permission to create Almanac namespaces '.
'within the "%s" namespace.',
$namespace->getName()),
$xaction);
$errors[] = $error;
continue;
}
}
}
break;
}
return $errors;
}
protected function didCatchDuplicateKeyException(
PhabricatorLiskDAO $object,
array $xactions,

View file

@ -81,7 +81,7 @@ final class AlmanacNetworkEditEngine
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the network.'))
->setTransactionType(AlmanacNetworkTransaction::TYPE_NAME)
->setTransactionType(AlmanacNetworkNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
);

View file

@ -1,16 +1,20 @@
<?php
final class AlmanacNetworkEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
extends AlmanacEditor {
public function getEditorObjectsDescription() {
return pht('Almanac Network');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this network.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
protected function supportsSearch() {
return true;
}
@ -18,90 +22,10 @@ final class AlmanacNetworkEditor
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = AlmanacNetworkTransaction::TYPE_NAME;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNetworkTransaction::TYPE_NAME:
return $object->getName();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNetworkTransaction::TYPE_NAME:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNetworkTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacNetworkTransaction::TYPE_NAME:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case AlmanacNetworkTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Network name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
}
break;
}
return $errors;
}
}

View file

@ -64,10 +64,17 @@ abstract class AlmanacPropertyEditEngine
protected function buildCustomEditFields($object) {
$property_key = $this->getPropertyKey();
$xaction_type = AlmanacTransaction::TYPE_PROPERTY_UPDATE;
$xaction_type = $object->getAlmanacPropertySetTransactionType();
$specs = $object->getAlmanacPropertyFieldSpecifications();
if (isset($specs[$property_key])) {
$field_template = clone $specs[$property_key];
} else {
$field_template = new PhabricatorTextEditField();
}
return array(
id(new PhabricatorTextEditField())
$field_template
->setKey('value')
->setMetadataValue('almanac.property', $property_key)
->setLabel($property_key)

View file

@ -41,8 +41,46 @@ final class AlmanacServiceEditEngine
return AlmanacService::initializeNewService($service_type);
}
protected function newEditableObjectFromConduit(array $raw_xactions) {
$type = null;
foreach ($raw_xactions as $raw_xaction) {
if ($raw_xaction['type'] !== 'type') {
continue;
}
$type = $raw_xaction['value'];
}
if ($type === null) {
throw new Exception(
pht(
'When creating a new Almanac service via the Conduit API, you '.
'must provide a "type" transaction to select a type.'));
}
$map = AlmanacServiceType::getAllServiceTypes();
if (!isset($map[$type])) {
throw new Exception(
pht(
'Service type "%s" is unrecognized. Valid types are: %s.',
$type,
implode(', ', array_keys($map))));
}
$this->setServiceType($type);
return $this->newEditableObject();
}
protected function newEditableObjectForDocumentation() {
$service_type = new AlmanacCustomServiceType();
$this->setServiceType($service_type->getServiceTypeConstant());
return $this->newEditableObject();
}
protected function newObjectQuery() {
return new AlmanacServiceQuery();
return id(new AlmanacServiceQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {
@ -92,9 +130,19 @@ final class AlmanacServiceEditEngine
->setKey('name')
->setLabel(pht('Name'))
->setDescription(pht('Name of the service.'))
->setTransactionType(AlmanacServiceTransaction::TYPE_NAME)
->setTransactionType(AlmanacServiceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
id(new PhabricatorTextEditField())
->setKey('type')
->setLabel(pht('Type'))
->setIsConduitOnly(true)
->setTransactionType(
AlmanacServiceTypeTransaction::TRANSACTIONTYPE)
->setDescription(pht('When creating a service, set the type.'))
->setConduitDescription(pht('Set the service type.'))
->setConduitTypeDescription(pht('Service type.'))
->setValue($object->getServiceType()),
);
}

View file

@ -7,152 +7,23 @@ final class AlmanacServiceEditor
return pht('Almanac Service');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this service.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = AlmanacServiceTransaction::TYPE_NAME;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacServiceTransaction::TYPE_NAME:
return $object->getName();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacServiceTransaction::TYPE_NAME:
return $xaction->getNewValue();
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacServiceTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case AlmanacServiceTransaction::TYPE_NAME:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
case AlmanacServiceTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
if ($missing) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
pht('Service name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
$errors[] = $error;
} else {
foreach ($xactions as $xaction) {
$message = null;
$name = $xaction->getNewValue();
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$message,
$xaction);
$errors[] = $error;
continue;
}
$other = id(new AlmanacServiceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($name))
->executeOne();
if ($other && ($other->getID() != $object->getID())) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Unique'),
pht('Almanac services must have unique names.'),
last($xactions));
$errors[] = $error;
continue;
}
if ($name === $object->getName()) {
continue;
}
$namespace = AlmanacNamespace::loadRestrictedNamespace(
$this->getActor(),
$name);
if ($namespace) {
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Restricted'),
pht(
'You do not have permission to create Almanac services '.
'within the "%s" namespace.',
$namespace->getName()),
$xaction);
$errors[] = $error;
continue;
}
}
}
break;
}
return $errors;
}
protected function validateAllTransactions(
PhabricatorLiskDAO $object,
array $xactions) {

View file

@ -0,0 +1,22 @@
<?php
final class AlmanacDeletePropertyEditField
extends PhabricatorEditField {
protected function newControl() {
return null;
}
protected function newHTTPParameterType() {
return null;
}
protected function newConduitParameterType() {
return new ConduitStringListParameterType();
}
protected function newEditType() {
return new AlmanacDeletePropertyEditType();
}
}

View file

@ -0,0 +1,36 @@
<?php
final class AlmanacDeletePropertyEditType
extends PhabricatorEditType {
public function generateTransactions(
PhabricatorApplicationTransaction $template,
array $spec) {
$value = idx($spec, 'value');
if (!is_array($value)) {
throw new Exception(
pht(
'Transaction value when deleting Almanac properties must be a list '.
'of property names.'));
}
$xactions = array();
foreach ($value as $idx => $property_key) {
if (!is_string($property_key)) {
throw new Exception(
pht(
'When deleting Almanac properties, each property name must '.
'be a string. The value at index "%s" is not a string.',
$idx));
}
$xactions[] = $this->newTransaction($template)
->setMetadataValue('almanac.property', $property_key)
->setNewValue(true);
}
return $xactions;
}
}

View file

@ -0,0 +1,44 @@
<?php
final class AlmanacPropertiesEditEngineExtension
extends PhabricatorEditEngineExtension {
const EXTENSIONKEY = 'almanac.properties';
public function isExtensionEnabled() {
return true;
}
public function getExtensionName() {
return pht('Almanac Properties');
}
public function supportsObject(
PhabricatorEditEngine $engine,
PhabricatorApplicationTransactionInterface $object) {
return ($object instanceof AlmanacPropertyInterface);
}
public function buildCustomEditFields(
PhabricatorEditEngine $engine,
PhabricatorApplicationTransactionInterface $object) {
return array(
id(new AlmanacSetPropertyEditField())
->setKey('property.set')
->setTransactionType($object->getAlmanacPropertySetTransactionType())
->setConduitDescription(
pht('Pass a map of values to set one or more properties.'))
->setConduitTypeDescription(pht('Map of property names to values.'))
->setIsConduitOnly(true),
id(new AlmanacDeletePropertyEditField())
->setKey('property.delete')
->setTransactionType($object->getAlmanacPropertyDeleteTransactionType())
->setConduitDescription(
pht('Pass a list of property names to delete properties.'))
->setConduitTypeDescription(pht('List of property names.'))
->setIsConduitOnly(true),
);
}
}

View file

@ -0,0 +1,22 @@
<?php
final class AlmanacSetPropertyEditField
extends PhabricatorEditField {
protected function newControl() {
return null;
}
protected function newHTTPParameterType() {
return null;
}
protected function newConduitParameterType() {
return new ConduitWildParameterType();
}
protected function newEditType() {
return new AlmanacSetPropertyEditType();
}
}

View file

@ -0,0 +1,28 @@
<?php
final class AlmanacSetPropertyEditType
extends PhabricatorEditType {
public function generateTransactions(
PhabricatorApplicationTransaction $template,
array $spec) {
$value = idx($spec, 'value');
if (!is_array($value)) {
throw new Exception(
pht(
'Transaction value when setting Almanac properties must be a map '.
'with property names as keys.'));
}
$xactions = array();
foreach ($value as $property_key => $property_value) {
$xactions[] = $this->newTransaction($template)
->setMetadataValue('almanac.property', $property_key)
->setNewValue($property_value);
}
return $xactions;
}
}

View file

@ -26,20 +26,4 @@ abstract class AlmanacManagementWorkflow
return $services;
}
protected function updateServiceLock(AlmanacService $service, $lock) {
$almanac_phid = id(new PhabricatorAlmanacApplication())->getPHID();
$xaction = id(new AlmanacServiceTransaction())
->setTransactionType(AlmanacServiceTransaction::TYPE_LOCK)
->setNewValue((int)$lock);
$editor = id(new AlmanacServiceEditor())
->setActor($this->getViewer())
->setActingAsPHID($almanac_phid)
->setContentSource($this->newContentSource())
->setContinueOnMissingFields(true);
$editor->applyTransactions($service, array($xaction));
}
}

View file

@ -9,5 +9,7 @@ interface AlmanacPropertyInterface {
public function getAlmanacPropertyValue($key, $default = null);
public function getAlmanacPropertyFieldSpecifications();
public function newAlmanacPropertyEditEngine();
public function getAlmanacPropertySetTransactionType();
public function getAlmanacPropertyDeleteTransactionType();
}

View file

@ -0,0 +1,80 @@
<?php
final class AlmanacBindingSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Bindings');
}
public function getApplicationClassName() {
return 'PhabricatorAlmanacApplication';
}
public function newQuery() {
return new AlmanacBindingQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Services'))
->setKey('servicePHIDs')
->setAliases(array('service', 'servicePHID', 'services'))
->setDescription(pht('Search for bindings on particular services.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices'))
->setKey('devicePHIDs')
->setAliases(array('device', 'devicePHID', 'devices'))
->setDescription(pht('Search for bindings on particular devices.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['servicePHIDs']) {
$query->withServicePHIDs($map['servicePHIDs']);
}
if ($map['devicePHIDs']) {
$query->withDevicePHIDs($map['devicePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/binding/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Bindings'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $devices,
PhabricatorSavedQuery $query,
array $handles) {
// For now, this SearchEngine just supports API access via Conduit.
throw new PhutilMethodNotImplementedException();
}
}

View file

@ -0,0 +1,71 @@
<?php
final class AlmanacInterfaceSearchEngine
extends PhabricatorApplicationSearchEngine {
public function getResultTypeDescription() {
return pht('Almanac Interfaces');
}
public function getApplicationClassName() {
return 'PhabricatorAlmanacApplication';
}
public function newQuery() {
return new AlmanacInterfaceQuery();
}
protected function buildCustomSearchFields() {
return array(
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices'))
->setKey('devicePHIDs')
->setAliases(array('device', 'devicePHID', 'devices'))
->setDescription(pht('Search for interfaces on particular devices.')),
);
}
protected function buildQueryFromParameters(array $map) {
$query = $this->newQuery();
if ($map['devicePHIDs']) {
$query->withDevicePHIDs($map['devicePHIDs']);
}
return $query;
}
protected function getURI($path) {
return '/almanac/interface/'.$path;
}
protected function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Interfaces'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function renderResultList(
array $devices,
PhabricatorSavedQuery $query,
array $handles) {
// For now, this SearchEngine just supports API access via Conduit.
throw new PhutilMethodNotImplementedException();
}
}

View file

@ -34,10 +34,12 @@ abstract class AlmanacQuery
$specs = $object->getAlmanacPropertyFieldSpecifications();
foreach ($specs as $key => $spec) {
if (empty($object_properties[$key])) {
$default_value = $spec->getValueForTransaction();
$object_properties[$key] = id(new AlmanacProperty())
->setObjectPHID($object->getPHID())
->setFieldName($key)
->setFieldValue($spec->getValueForTransaction());
->setFieldValue($default_value);
}
}

View file

@ -20,7 +20,48 @@ final class AlmanacClusterRepositoryServiceType
public function getFieldSpecifications() {
return array(
'closed' => id(new PhabricatorTextEditField()),
'closed' => id(new PhabricatorBoolEditField())
->setOptions(
pht('Allow New Repositories'),
pht('Prevent New Repositories'))
->setValue(false),
);
}
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
$protocols = array(
array(
'value' => 'http',
'port' => 80,
),
array(
'value' => 'https',
'port' => 443,
),
array(
'value' => 'ssh',
'port' => 22,
),
);
$default_value = 'http';
if ($binding->hasInterface()) {
$interface = $binding->getInterface();
$port = $interface->getPort();
$default_ports = ipull($protocols, 'value', 'port');
$default_value = idx($default_ports, $port, $default_value);
}
return array(
'protocol' => id(new PhabricatorSelectEditField())
->setOptions(ipull($protocols, 'value', 'value'))
->setValue($default_value),
'writable' => id(new PhabricatorBoolEditField())
->setOptions(
pht('Prevent Writes'),
pht('Allow Writes'))
->setValue(true),
);
}

View file

@ -60,6 +60,10 @@ abstract class AlmanacServiceType extends Phobject {
return array();
}
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
return array();
}
/**
* List all available service type implementations.
*

View file

@ -7,7 +7,8 @@ final class AlmanacBinding
PhabricatorApplicationTransactionInterface,
AlmanacPropertyInterface,
PhabricatorDestructibleInterface,
PhabricatorExtendedPolicyInterface {
PhabricatorExtendedPolicyInterface,
PhabricatorConduitResultInterface {
protected $servicePHID;
protected $devicePHID;
@ -23,6 +24,7 @@ final class AlmanacBinding
public static function initializeNewBinding(AlmanacService $service) {
return id(new AlmanacBinding())
->setServicePHID($service->getPHID())
->attachService($service)
->attachAlmanacProperties(array())
->setIsDisabled(0);
}
@ -86,6 +88,10 @@ final class AlmanacBinding
return $this;
}
public function hasInterface() {
return ($this->interface !== self::ATTACHABLE);
}
public function getInterface() {
return $this->assertAttached($this->interface);
}
@ -127,13 +133,21 @@ final class AlmanacBinding
}
public function getAlmanacPropertyFieldSpecifications() {
return array();
return $this->getService()->getBindingFieldSpecifications($this);
}
public function newAlmanacPropertyEditEngine() {
return new AlmanacBindingPropertyEditEngine();
}
public function getAlmanacPropertySetTransactionType() {
return AlmanacBindingSetPropertyTransaction::TRANSACTIONTYPE;
}
public function getAlmanacPropertyDeleteTransactionType() {
return AlmanacBindingDeletePropertyTransaction::TRANSACTIONTYPE;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@ -217,4 +231,44 @@ final class AlmanacBinding
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('servicePHID')
->setType('phid')
->setDescription(pht('The bound service.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('devicePHID')
->setType('phid')
->setDescription(pht('The device the service is bound to.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('interfacePHID')
->setType('phid')
->setDescription(pht('The interface the service is bound to.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('disabled')
->setType('bool')
->setDescription(pht('Interface status.')),
);
}
public function getFieldValuesForConduit() {
return array(
'servicePHID' => $this->getServicePHID(),
'devicePHID' => $this->getDevicePHID(),
'interfacePHID' => $this->getInterfacePHID(),
'disabled' => (bool)$this->getIsDisabled(),
);
}
public function getConduitSearchAttachments() {
return array(
id(new AlmanacPropertiesSearchEngineAttachment())
->setAttachmentKey('properties'),
);
}
}

View file

@ -1,77 +1,14 @@
<?php
final class AlmanacBindingTransaction
extends AlmanacTransaction {
const TYPE_INTERFACE = 'almanac:binding:interface';
const TYPE_DISABLE = 'almanac:binding:disable';
public function getApplicationName() {
return 'almanac';
}
extends AlmanacModularTransaction {
public function getApplicationTransactionType() {
return AlmanacBindingPHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_INTERFACE:
if ($old) {
$phids[] = $old;
}
if ($new) {
$phids[] = $new;
}
break;
}
return $phids;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_INTERFACE:
if ($old === null) {
return pht(
'%s created this binding.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s changed this binding from %s to %s.',
$this->renderHandleLink($author_phid),
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
break;
case self::TYPE_DISABLE:
if ($new) {
return pht(
'%s disabled this binding.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s enabled this binding.',
$this->renderHandleLink($author_phid));
}
break;
}
return parent::getTitle();
public function getBaseTransactionClass() {
return 'AlmanacBindingTransactionType';
}
}

View file

@ -143,6 +143,14 @@ final class AlmanacDevice
return new AlmanacDevicePropertyEditEngine();
}
public function getAlmanacPropertySetTransactionType() {
return AlmanacDeviceSetPropertyTransaction::TRANSACTIONTYPE;
}
public function getAlmanacPropertyDeleteTransactionType() {
return AlmanacDeviceDeletePropertyTransaction::TRANSACTIONTYPE;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -1,100 +1,14 @@
<?php
final class AlmanacDeviceTransaction
extends AlmanacTransaction {
const TYPE_NAME = 'almanac:device:name';
const TYPE_INTERFACE = 'almanac:device:interface';
public function getApplicationName() {
return 'almanac';
}
extends AlmanacModularTransaction {
public function getApplicationTransactionType() {
return AlmanacDevicePHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_INTERFACE:
if ($old) {
$phids[] = $old['networkPHID'];
}
if ($new) {
$phids[] = $new['networkPHID'];
}
break;
}
return $phids;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_NAME:
if ($old === null) {
return pht(
'%s created this device.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s renamed this device from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_INTERFACE:
if ($old && $new) {
return pht(
'%s changed interface %s on this device to %s.',
$this->renderHandleLink($author_phid),
$this->describeInterface($old),
$this->describeInterface($new));
} else if ($old) {
return pht(
'%s removed the interface %s from this device.',
$this->renderHandleLink($author_phid),
$this->describeInterface($old));
} else if ($new) {
return pht(
'%s added the interface %s to this device.',
$this->renderHandleLink($author_phid),
$this->describeInterface($new));
}
}
return parent::getTitle();
}
public function shouldGenerateOldValue() {
switch ($this->getTransactionType()) {
case self::TYPE_INTERFACE:
return false;
}
return parent::shouldGenerateOldValue();
}
private function describeInterface(array $info) {
return pht(
'%s:%s (%s)',
$info['address'],
$info['port'],
$this->renderHandleLink($info['networkPHID']));
public function getBaseTransactionClass() {
return 'AlmanacDeviceTransactionType';
}
}

View file

@ -5,7 +5,9 @@ final class AlmanacInterface
implements
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface,
PhabricatorExtendedPolicyInterface {
PhabricatorExtendedPolicyInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorConduitResultInterface {
protected $devicePHID;
protected $networkPHID;
@ -154,4 +156,64 @@ final class AlmanacInterface
$this->delete();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new AlmanacInterfaceEditor();
}
public function getApplicationTransactionObject() {
return $this;
}
public function getApplicationTransactionTemplate() {
return new AlmanacInterfaceTransaction();
}
public function willRenderTimeline(
PhabricatorApplicationTransactionView $timeline,
AphrontRequest $request) {
return $timeline;
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('devicePHID')
->setType('phid')
->setDescription(pht('The device the interface is on.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('networkPHID')
->setType('phid')
->setDescription(pht('The network the interface is part of.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('address')
->setType('string')
->setDescription(pht('The address of the interface.')),
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('port')
->setType('int')
->setDescription(pht('The port number of the interface.')),
);
}
public function getFieldValuesForConduit() {
return array(
'devicePHID' => $this->getDevicePHID(),
'networkPHID' => $this->getNetworkPHID(),
'address' => (string)$this->getAddress(),
'port' => (int)$this->getPort(),
);
}
public function getConduitSearchAttachments() {
return array();
}
}

View file

@ -0,0 +1,14 @@
<?php
final class AlmanacInterfaceTransaction
extends AlmanacModularTransaction {
public function getApplicationTransactionType() {
return AlmanacInterfacePHIDType::TYPECONST;
}
public function getBaseTransactionClass() {
return 'AlmanacInterfaceTransactionType';
}
}

View file

@ -0,0 +1,14 @@
<?php
abstract class AlmanacModularTransaction
extends PhabricatorModularTransaction {
public function getApplicationName() {
return 'almanac';
}
public function getApplicationTransactionCommentObject() {
return null;
}
}

View file

@ -8,7 +8,8 @@ final class AlmanacNamespace
PhabricatorProjectInterface,
AlmanacPropertyInterface,
PhabricatorDestructibleInterface,
PhabricatorNgramsInterface {
PhabricatorNgramsInterface,
PhabricatorConduitResultInterface {
protected $name;
protected $nameIndex;
@ -150,6 +151,14 @@ final class AlmanacNamespace
throw new PhutilMethodNotImplementedException();
}
public function getAlmanacPropertySetTransactionType() {
throw new PhutilMethodNotImplementedException();
}
public function getAlmanacPropertyDeleteTransactionType() {
throw new PhutilMethodNotImplementedException();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@ -216,4 +225,28 @@ final class AlmanacNamespace
);
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of the namespace.')),
);
}
public function getFieldValuesForConduit() {
return array(
'name' => $this->getName(),
);
}
public function getConduitSearchAttachments() {
return array();
}
}

View file

@ -1,43 +1,14 @@
<?php
final class AlmanacNamespaceTransaction
extends PhabricatorApplicationTransaction {
const TYPE_NAME = 'almanac:namespace:name';
public function getApplicationName() {
return 'almanac';
}
extends AlmanacModularTransaction {
public function getApplicationTransactionType() {
return AlmanacNamespacePHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this namespace.',
$this->renderHandleLink($author_phid));
break;
case self::TYPE_NAME:
return pht(
'%s renamed this namespace from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
return parent::getTitle();
public function getBaseTransactionClass() {
return 'AlmanacNamespaceTransactionType';
}
}

View file

@ -6,7 +6,8 @@ final class AlmanacNetwork
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface,
PhabricatorNgramsInterface {
PhabricatorNgramsInterface,
PhabricatorConduitResultInterface {
protected $name;
protected $mailKey;
@ -122,4 +123,27 @@ final class AlmanacNetwork
);
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of the network.')),
);
}
public function getFieldValuesForConduit() {
return array(
'name' => $this->getName(),
);
}
public function getConduitSearchAttachments() {
return array();
}
}

View file

@ -1,42 +1,14 @@
<?php
final class AlmanacNetworkTransaction
extends PhabricatorApplicationTransaction {
const TYPE_NAME = 'almanac:network:name';
public function getApplicationName() {
return 'almanac';
}
extends AlmanacModularTransaction {
public function getApplicationTransactionType() {
return AlmanacNetworkPHIDType::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case PhabricatorTransactions::TYPE_CREATE:
return pht(
'%s created this network.',
$this->renderHandleLink($author_phid));
case self::TYPE_NAME:
return pht(
'%s renamed this network from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
return parent::getTitle();
public function getBaseTransactionClass() {
return 'AlmanacNetworkTransactionType';
}
}

View file

@ -54,7 +54,7 @@ final class AlmanacProperty
}
$xactions[] = id(clone $template)
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_UPDATE)
->setTransactionType($object->getAlmanacPropertySetTransactionType())
->setMetadataValue('almanac.property', $name)
->setNewValue($property);
}
@ -71,7 +71,7 @@ final class AlmanacProperty
$xactions = array();
foreach ($properties as $property) {
$xactions[] = id(clone $template)
->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
->setTransactionType($object->getAlmanacPropertyDeleteTransactionType())
->setMetadataValue('almanac.property', $property)
->setNewValue(null);
}

View file

@ -156,10 +156,23 @@ final class AlmanacService
return $this->getServiceImplementation()->getFieldSpecifications();
}
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
$impl = $this->getServiceImplementation();
return $impl->getBindingFieldSpecifications($binding);
}
public function newAlmanacPropertyEditEngine() {
return new AlmanacServicePropertyEditEngine();
}
public function getAlmanacPropertySetTransactionType() {
return AlmanacServiceSetPropertyTransaction::TRANSACTIONTYPE;
}
public function getAlmanacPropertyDeleteTransactionType() {
return AlmanacServiceDeletePropertyTransaction::TRANSACTIONTYPE;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -1,49 +1,14 @@
<?php
final class AlmanacServiceTransaction
extends AlmanacTransaction {
const TYPE_NAME = 'almanac:service:name';
const TYPE_LOCK = 'almanac:service:lock';
extends AlmanacModularTransaction {
public function getApplicationTransactionType() {
return AlmanacServicePHIDType::TYPECONST;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case self::TYPE_NAME:
if ($old === null) {
return pht(
'%s created this service.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s renamed this service from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_LOCK:
if ($new) {
return pht(
'%s locked this service.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s unlocked this service.',
$this->renderHandleLink($author_phid));
}
break;
}
return parent::getTitle();
public function getBaseTransactionClass() {
return 'AlmanacServiceTransactionType';
}
}

View file

@ -1,38 +0,0 @@
<?php
abstract class AlmanacTransaction
extends PhabricatorApplicationTransaction {
const TYPE_PROPERTY_UPDATE = 'almanac:property:update';
const TYPE_PROPERTY_REMOVE = 'almanac:property:remove';
public function getApplicationName() {
return 'almanac';
}
public function getApplicationTransactionCommentObject() {
return null;
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
switch ($this->getTransactionType()) {
case self::TYPE_PROPERTY_UPDATE:
$property_key = $this->getMetadataValue('almanac.property');
return pht(
'%s updated the property "%s".',
$this->renderHandleLink($author_phid),
$property_key);
case self::TYPE_PROPERTY_REMOVE:
$property_key = $this->getMetadataValue('almanac.property');
return pht(
'%s deleted the property "%s".',
$this->renderHandleLink($author_phid),
$property_key);
}
return parent::getTitle();
}
}

View file

@ -0,0 +1,20 @@
<?php
final class AlmanacBindingDeletePropertyTransaction
extends AlmanacBindingTransactionType {
const TRANSACTIONTYPE = 'almanac:property:remove';
public function generateOldValue($object) {
return $this->getAlmanacPropertyOldValue($object);
}
public function applyInternalEffects($object, $value) {
return $this->deleteAlmanacProperty($object);
}
public function getTitle() {
return $this->getAlmanacDeletePropertyTitle();
}
}

View file

@ -0,0 +1,28 @@
<?php
final class AlmanacBindingDisableTransaction
extends AlmanacBindingTransactionType {
const TRANSACTIONTYPE = 'almanac:binding:disable';
public function generateOldValue($object) {
return (bool)$object->getIsDisabled();
}
public function applyInternalEffects($object, $value) {
$object->setIsDisabled((int)$value);
}
public function getTitle() {
if ($this->getNewValue()) {
return pht(
'%s disabled this binding.',
$this->renderAuthor());
} else {
return pht(
'%s enabled this binding.',
$this->renderAuthor());
}
}
}

View file

@ -0,0 +1,111 @@
<?php
final class AlmanacBindingInterfaceTransaction
extends AlmanacBindingTransactionType {
const TRANSACTIONTYPE = 'almanac:binding:interface';
public function generateOldValue($object) {
return $object->getInterfacePHID();
}
public function applyInternalEffects($object, $value) {
$interface = $this->loadInterface($value);
$object
->setDevicePHID($interface->getDevicePHID())
->setInterfacePHID($interface->getPHID());
}
public function applyExternalEffects($object, $value) {
// When we change which services a device is bound to, we need to
// recalculate whether it is a cluster device or not so we can tell if
// the "Can Manage Cluster Services" permission applies to it.
$viewer = PhabricatorUser::getOmnipotentUser();
$interface_phids = array();
$interface_phids[] = $this->getOldValue();
$interface_phids[] = $this->getNewValue();
$interface_phids = array_filter($interface_phids);
$interface_phids = array_unique($interface_phids);
$interfaces = id(new AlmanacInterfaceQuery())
->setViewer($viewer)
->withPHIDs($interface_phids)
->execute();
$device_phids = array();
foreach ($interfaces as $interface) {
$device_phids[] = $interface->getDevicePHID();
}
$device_phids = array_unique($device_phids);
$devices = id(new AlmanacDeviceQuery())
->setViewer($viewer)
->withPHIDs($device_phids)
->execute();
foreach ($devices as $device) {
$device->rebuildClusterBindingStatus();
}
}
public function getTitle() {
return pht(
'%s changed the interface for this binding from %s to %s.',
$this->renderAuthor(),
$this->renderOldHandle(),
$this->renderNewHandle());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$interface_phid = $object->getInterfacePHID();
if ($this->isEmptyTextTransaction($interface_phid, $xactions)) {
$errors[] = $this->newRequiredError(
pht('Bindings must specify an interface.'));
}
foreach ($xactions as $xaction) {
$interface_phid = $xaction->getNewValue();
$interface = $this->loadInterface($interface_phid);
if (!$interface) {
$errors[] = $this->newInvalidError(
pht(
'You can not bind a service to an invalid or restricted '.
'interface.'),
$xaction);
continue;
}
$binding = id(new AlmanacBindingQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withServicePHIDs(array($object->getServicePHID()))
->withInterfacePHIDs(array($interface_phid))
->executeOne();
if ($binding && ($binding->getID() != $object->getID())) {
$errors[] = $this->newInvalidError(
pht(
'You can not bind a service to the same interface multiple '.
'times.'),
$xaction);
continue;
}
}
return $errors;
}
private function loadInterface($phid) {
return id(new AlmanacInterfaceQuery())
->setViewer($this->getActor())
->withPHIDs(array($phid))
->executeOne();
}
}

View file

@ -0,0 +1,64 @@
<?php
final class AlmanacBindingServiceTransaction
extends AlmanacBindingTransactionType {
const TRANSACTIONTYPE = 'almanac:binding:service';
public function generateOldValue($object) {
return $object->getServicePHID();
}
public function applyInternalEffects($object, $value) {
$object->setServicePHID($value);
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$service_phid = $object->getServicePHID();
if ($this->isEmptyTextTransaction($service_phid, $xactions)) {
$errors[] = $this->newRequiredError(
pht('Bindings must have a service.'));
}
foreach ($xactions as $xaction) {
if (!$this->isNewObject()) {
$errors[] = $this->newInvalidError(
pht(
'The service for a binding can not be changed once it has '.
'been created.'),
$xaction);
continue;
}
$service_phid = $xaction->getNewValue();
$services = id(new AlmanacServiceQuery())
->setViewer($this->getActor())
->withPHIDs(array($service_phid))
->execute();
if (!$services) {
$errors[] = $this->newInvalidError(
pht('You can not bind a nonexistent or restricted service.'),
$xaction);
continue;
}
$service = head($services);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$this->getActor(),
$service,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
$errors[] = $this->newInvalidError(
pht(
'You can not bind a service which you do not have permission '.
'to edit.'));
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,24 @@
<?php
final class AlmanacBindingSetPropertyTransaction
extends AlmanacBindingTransactionType {
const TRANSACTIONTYPE = 'almanac:property:update';
public function generateOldValue($object) {
return $this->getAlmanacPropertyOldValue($object);
}
public function applyExternalEffects($object, $value) {
return $this->setAlmanacProperty($object, $value);
}
public function getTitle() {
return $this->getAlmanacSetPropertyTitle();
}
public function validateTransactions($object, array $xactions) {
return $this->validateAlmanacSetPropertyTransactions($object, $xactions);
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class AlmanacBindingTransactionType
extends AlmanacTransactionType {}

View file

@ -0,0 +1,20 @@
<?php
final class AlmanacDeviceDeletePropertyTransaction
extends AlmanacDeviceTransactionType {
const TRANSACTIONTYPE = 'almanac:property:remove';
public function generateOldValue($object) {
return $this->getAlmanacPropertyOldValue($object);
}
public function applyInternalEffects($object, $value) {
return $this->deleteAlmanacProperty($object);
}
public function getTitle() {
return $this->getAlmanacDeletePropertyTitle();
}
}

View file

@ -0,0 +1,79 @@
<?php
final class AlmanacDeviceNameTransaction
extends AlmanacDeviceTransactionType {
const TRANSACTIONTYPE = 'almanac:device:name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this device from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Device name is required.'));
}
foreach ($xactions as $xaction) {
$name = $xaction->getNewValue();
$message = null;
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$errors[] = $this->newInvalidError($message, $xaction);
continue;
}
if ($name === $object->getName()) {
continue;
}
$other = id(new AlmanacDeviceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($name))
->executeOne();
if ($other && ($other->getID() != $object->getID())) {
$errors[] = $this->newInvalidError(
pht('Almanac devices must have unique names.'),
$xaction);
continue;
}
$namespace = AlmanacNamespace::loadRestrictedNamespace(
$this->getActor(),
$name);
if ($namespace) {
$errors[] = $this->newInvalidError(
pht(
'You do not have permission to create Almanac devices '.
'within the "%s" namespace.',
$namespace->getName()),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,24 @@
<?php
final class AlmanacDeviceSetPropertyTransaction
extends AlmanacDeviceTransactionType {
const TRANSACTIONTYPE = 'almanac:property:update';
public function generateOldValue($object) {
return $this->getAlmanacPropertyOldValue($object);
}
public function applyExternalEffects($object, $value) {
return $this->setAlmanacProperty($object, $value);
}
public function getTitle() {
return $this->getAlmanacSetPropertyTitle();
}
public function validateTransactions($object, array $xactions) {
return $this->validateAlmanacSetPropertyTransactions($object, $xactions);
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class AlmanacDeviceTransactionType
extends AlmanacTransactionType {}

View file

@ -0,0 +1,44 @@
<?php
final class AlmanacInterfaceAddressTransaction
extends AlmanacInterfaceTransactionType {
const TRANSACTIONTYPE = 'almanac:interface:address';
public function generateOldValue($object) {
return $object->getAddress();
}
public function applyInternalEffects($object, $value) {
$object->setAddress($value);
}
public function getTitle() {
return pht(
'%s changed the address for this interface from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getAddress(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Interfaces must have an address.'));
}
foreach ($xactions as $xaction) {
// NOTE: For now, we don't validate addresses. We generally expect users
// to provide IPv4 addresses, but it's reasonable for them to provide
// IPv6 addresses, and some installs currently use DNS names. This is
// off-label but works today.
}
return $errors;
}
}

View file

@ -0,0 +1,32 @@
<?php
final class AlmanacInterfaceDestroyTransaction
extends AlmanacInterfaceTransactionType {
const TRANSACTIONTYPE = 'almanac:interface:destroy';
public function generateOldValue($object) {
return false;
}
public function applyExternalEffects($object, $value) {
id(new PhabricatorDestructionEngine())
->destroyObject($object);
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($xactions) {
if ($object->loadIsInUse()) {
$errors[] = $this->newInvalidError(
pht(
'You can not delete this interface because it is currently in '.
'use. One or more services are bound to it.'));
}
}
return $errors;
}
}

View file

@ -0,0 +1,74 @@
<?php
final class AlmanacInterfaceDeviceTransaction
extends AlmanacInterfaceTransactionType {
const TRANSACTIONTYPE = 'almanac:interface:device';
public function generateOldValue($object) {
return $object->getDevicePHID();
}
public function applyInternalEffects($object, $value) {
$object->setDevicePHID($value);
}
public function getTitle() {
return pht(
'%s changed the device for this interface from %s to %s.',
$this->renderAuthor(),
$this->renderOldHandle(),
$this->renderNewHandle());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$device_phid = $object->getDevicePHID();
if ($this->isEmptyTextTransaction($device_phid, $xactions)) {
$errors[] = $this->newRequiredError(
pht('Interfaces must have a device.'));
}
foreach ($xactions as $xaction) {
if (!$this->isNewObject()) {
$errors[] = $this->newInvalidError(
pht(
'The device for an interface can not be changed once it has '.
'been created.'),
$xaction);
continue;
}
$device_phid = $xaction->getNewValue();
$devices = id(new AlmanacDeviceQuery())
->setViewer($this->getActor())
->withPHIDs(array($device_phid))
->execute();
if (!$devices) {
$errors[] = $this->newInvalidError(
pht(
'You can not attach an interface to a nonexistent or restricted '.
'device.'),
$xaction);
continue;
}
$device = head($devices);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$this->getActor(),
$device,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
$errors[] = $this->newInvalidError(
pht(
'You can not attach an interface to a device which you do not '.
'have permission to edit.'));
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,53 @@
<?php
final class AlmanacInterfaceNetworkTransaction
extends AlmanacInterfaceTransactionType {
const TRANSACTIONTYPE = 'almanac:interface:network';
public function generateOldValue($object) {
return $object->getNetworkPHID();
}
public function applyInternalEffects($object, $value) {
$object->setNetworkPHID($value);
}
public function getTitle() {
return pht(
'%s changed the network for this interface from %s to %s.',
$this->renderAuthor(),
$this->renderOldHandle(),
$this->renderNewHandle());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$network_phid = $object->getNetworkPHID();
if ($this->isEmptyTextTransaction($network_phid, $xactions)) {
$errors[] = $this->newRequiredError(
pht('Interfaces must have a network.'));
}
foreach ($xactions as $xaction) {
$network_phid = $xaction->getNewValue();
$networks = id(new AlmanacNetworkQuery())
->setViewer($this->getActor())
->withPHIDs(array($network_phid))
->execute();
if (!$networks) {
$errors[] = $this->newInvalidError(
pht(
'You can not put an interface on a nonexistent or restricted '.
'network.'),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,53 @@
<?php
final class AlmanacInterfacePortTransaction
extends AlmanacInterfaceTransactionType {
const TRANSACTIONTYPE = 'almanac:interface:port';
public function generateOldValue($object) {
$port = $object->getPort();
if ($port !== null) {
$port = (int)$port;
}
return $port;
}
public function applyInternalEffects($object, $value) {
$object->setPort((int)$value);
}
public function getTitle() {
return pht(
'%s changed the port for this interface from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getPort(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Interfaces must have a port number.'));
}
foreach ($xactions as $xaction) {
$port = $xaction->getNewValue();
$port = (int)$port;
if ($port < 1 || $port > 65535) {
$errors[] = $this->newInvalidError(
pht('Port numbers must be between 1 and 65535, inclusive.'),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class AlmanacInterfaceTransactionType
extends AlmanacTransactionType {}

View file

@ -0,0 +1,91 @@
<?php
final class AlmanacNamespaceNameTransaction
extends AlmanacNamespaceTransactionType {
const TRANSACTIONTYPE = 'almanac:namespace:name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this namespace from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function getTitleForFeed() {
return pht(
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Namespace name is required.'));
}
foreach ($xactions as $xaction) {
$name = $xaction->getNewValue();
$message = null;
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$errors[] = $this->newInvalidError($message, $xaction);
continue;
}
if ($name === $object->getName()) {
continue;
}
$other = id(new AlmanacNamespaceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($name))
->executeOne();
if ($other && ($other->getID() != $object->getID())) {
$errors[] = $this->newInvalidError(
pht(
'The namespace name "%s" is already in use by another '.
'namespace. Each namespace must have a unique name.',
$name),
$xaction);
continue;
}
$namespace = AlmanacNamespace::loadRestrictedNamespace(
$this->getActor(),
$name);
if ($namespace) {
$errors[] = $this->newInvalidError(
pht(
'You do not have permission to create Almanac namespaces '.
'within the "%s" namespace.',
$namespace->getName()),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class AlmanacNamespaceTransactionType
extends AlmanacTransactionType {}

View file

@ -0,0 +1,44 @@
<?php
final class AlmanacNetworkNameTransaction
extends AlmanacNetworkTransactionType {
const TRANSACTIONTYPE = 'almanac:network:name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this network from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function getTitleForFeed() {
return pht(
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Network name is required.'));
}
return $errors;
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class AlmanacNetworkTransactionType
extends AlmanacTransactionType {}

View file

@ -0,0 +1,20 @@
<?php
final class AlmanacServiceDeletePropertyTransaction
extends AlmanacServiceTransactionType {
const TRANSACTIONTYPE = 'almanac:property:remove';
public function generateOldValue($object) {
return $this->getAlmanacPropertyOldValue($object);
}
public function applyInternalEffects($object, $value) {
return $this->deleteAlmanacProperty($object);
}
public function getTitle() {
return $this->getAlmanacDeletePropertyTitle();
}
}

View file

@ -0,0 +1,87 @@
<?php
final class AlmanacServiceNameTransaction
extends AlmanacServiceTransactionType {
const TRANSACTIONTYPE = 'almanac:service:name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
return pht(
'%s renamed this service from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function getTitleForFeed() {
return pht(
'%s renamed %s from %s to %s.',
$this->renderAuthor(),
$this->renderObject(),
$this->renderOldValue(),
$this->renderNewValue());
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('Almanac services must have a name.'));
}
foreach ($xactions as $xaction) {
$name = $xaction->getNewValue();
$message = null;
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$errors[] = $this->newInvalidError($message, $xaction);
continue;
}
if ($name === $object->getName()) {
continue;
}
$other = id(new AlmanacServiceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array($name))
->executeOne();
if ($other && ($other->getID() != $object->getID())) {
$errors[] = $this->newInvalidError(
pht('Almanac services must have unique names.'),
$xaction);
continue;
}
$namespace = AlmanacNamespace::loadRestrictedNamespace(
$this->getActor(),
$name);
if ($namespace) {
$errors[] = $this->newInvalidError(
pht(
'You do not have permission to create Almanac services '.
'within the "%s" namespace.',
$namespace->getName()),
$xaction);
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,24 @@
<?php
final class AlmanacServiceSetPropertyTransaction
extends AlmanacServiceTransactionType {
const TRANSACTIONTYPE = 'almanac:property:update';
public function generateOldValue($object) {
return $this->getAlmanacPropertyOldValue($object);
}
public function applyExternalEffects($object, $value) {
return $this->setAlmanacProperty($object, $value);
}
public function getTitle() {
return $this->getAlmanacSetPropertyTitle();
}
public function validateTransactions($object, array $xactions) {
return $this->validateAlmanacSetPropertyTransactions($object, $xactions);
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class AlmanacServiceTransactionType
extends AlmanacTransactionType {}

View file

@ -0,0 +1,55 @@
<?php
final class AlmanacServiceTypeTransaction
extends AlmanacServiceTransactionType {
const TRANSACTIONTYPE = 'almanac:service:type';
public function generateOldValue($object) {
return $object->getServiceType();
}
public function applyInternalEffects($object, $value) {
$object->setServiceType($value);
}
public function getTitle() {
// This transaction can only be applied during object creation via
// Conduit and never generates a timeline event.
return null;
}
public function validateTransactions($object, array $xactions) {
$errors = array();
if ($this->isEmptyTextTransaction($object->getServiceType(), $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must select a service type when creating a service.'));
}
$map = AlmanacServiceType::getAllServiceTypes();
foreach ($xactions as $xaction) {
if (!$this->isNewObject()) {
$errors[] = $this->newInvalidError(
pht(
'The type of a service can not be changed once it has '.
'been created.'),
$xaction);
continue;
}
$new = $xaction->getNewValue();
if (!isset($map[$new])) {
$errors[] = $this->newInvalidError(
pht(
'Service type "%s" is not valid. Valid types are: %s.',
$new,
implode(', ', array_keys($map))));
continue;
}
}
return $errors;
}
}

View file

@ -0,0 +1,97 @@
<?php
abstract class AlmanacTransactionType
extends PhabricatorModularTransactionType {
protected function getAlmanacPropertyOldValue($object) {
$property_key = $this->getMetadataValue('almanac.property');
$exists = $object->hasAlmanacProperty($property_key);
$value = $object->getAlmanacPropertyValue($property_key);
return array(
'existed' => $exists,
'value' => $value,
);
}
protected function setAlmanacProperty($object, $value) {
$property_key = $this->getMetadataValue('almanac.property');
if ($object->hasAlmanacProperty($property_key)) {
$property = $object->getAlmanacProperty($property_key);
} else {
$property = id(new AlmanacProperty())
->setObjectPHID($object->getPHID())
->setFieldName($property_key);
}
$property
->setFieldValue($value)
->save();
}
protected function deleteAlmanacProperty($object) {
$property_key = $this->getMetadataValue('almanac.property');
if ($object->hasAlmanacProperty($property_key)) {
$property = $object->getAlmanacProperty($property_key);
$property->delete();
}
}
protected function getAlmanacSetPropertyTitle() {
$property_key = $this->getMetadataValue('almanac.property');
return pht(
'%s updated the property %s.',
$this->renderAuthor(),
$this->renderValue($property_key));
}
protected function getAlmanacDeletePropertyTitle() {
$property_key = $this->getMetadataValue('almanac.property');
return pht(
'%s removed the property %s.',
$this->renderAuthor(),
$this->renderValue($property_key));
}
protected function validateAlmanacSetPropertyTransactions(
$object,
array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
$property_key = $xaction->getMetadataValue('almanac.property');
$message = null;
try {
AlmanacNames::validateName($property_key);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
if ($message !== null) {
$errors[] = $this->newInvalidError($message, $xaction);
continue;
}
$new_value = $xaction->getNewValue();
try {
phutil_json_encode($new_value);
} catch (Exception $ex) {
$message = pht(
'Almanac property values must be representable in JSON. %s',
$ex->getMessage());
}
if ($message !== null) {
$errors[] = $this->newInvalidError($message, $xaction);
continue;
}
}
return $errors;
}
}

View file

@ -57,10 +57,6 @@ abstract class PhabricatorApplication
abstract public function getName();
public function getMenuName() {
return $this->getName();
}
public function getShortDescription() {
return pht('%s Application', $this->getName());
}

View file

@ -268,24 +268,24 @@ EOREMARKUP
if ($protocol !== 'http' && $protocol !== 'https') {
throw new PhabricatorConfigValidationException(
pht(
"Config option '%s' is invalid. The URI must start with ".
"%s' or '%s'.",
'Config option "%s" is invalid. The URI must start with '.
'"%s" or "%s".',
$key,
'http://',
'https://',
$key));
'https://'));
}
$domain = $uri->getDomain();
if (strpos($domain, '.') === false) {
throw new PhabricatorConfigValidationException(
pht(
"Config option '%s' is invalid. The URI must contain a dot ".
"('%s'), like '%s', not just a bare name like '%s'. Some web ".
"browsers will not set cookies on domains with no TLD.",
'Config option "%s" is invalid. The URI must contain a dot '.
'("%s"), like "%s", not just a bare name like "%s". Some web '.
'browsers will not set cookies on domains with no TLD.',
$key,
'.',
'http://example.com/',
'http://example/',
$key));
'http://example/'));
}
$path = $uri->getPath();

View file

@ -10,10 +10,6 @@ final class PhabricatorDifferentialApplication extends PhabricatorApplication {
return pht('Differential');
}
public function getMenuName() {
return pht('Code Review');
}
public function getShortDescription() {
return pht('Pre-Commit Review');
}

View file

@ -850,11 +850,13 @@ final class DifferentialTransactionEditor
$revert_phids = array();
}
$this->setUnmentionablePHIDMap(
array_merge(
$task_phids,
$rev_phids,
$revert_phids));
// See PHI574. Respect any unmentionable PHIDs which were set on the
// Editor by the caller.
$unmentionable_map = $this->getUnmentionablePHIDMap();
$unmentionable_map += $task_phids;
$unmentionable_map += $rev_phids;
$unmentionable_map += $revert_phids;
$this->setUnmentionablePHIDMap($unmentionable_map);
$result = array();
foreach ($edges as $type => $specs) {

View file

@ -6,10 +6,6 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
return pht('Diffusion');
}
public function getMenuName() {
return pht('Repositories');
}
public function getShortDescription() {
return pht('Host and Browse Repositories');
}
@ -57,6 +53,10 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
'graph/(?P<dblob>.*)' => 'DiffusionGraphController',
'browse/(?P<dblob>.*)' => 'DiffusionBrowseController',
'document/(?P<dblob>.*)'
=> 'DiffusionDocumentController',
'blame/(?P<dblob>.*)'
=> 'DiffusionBlameController',
'lastmodified/(?P<dblob>.*)' => 'DiffusionLastModifiedController',
'diff/' => 'DiffusionDiffController',
'tags/(?P<dblob>.*)' => 'DiffusionTagListController',

View file

@ -0,0 +1,266 @@
<?php
final class DiffusionBlameController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$response = $this->loadDiffusionContext();
if ($response) {
return $response;
}
$viewer = $this->getViewer();
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
$blame = $this->loadBlame();
$identifiers = array_fuse($blame);
if ($identifiers) {
$commits = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withRepository($repository)
->withIdentifiers($identifiers)
->execute();
$commits = mpull($commits, null, 'getCommitIdentifier');
} else {
$commits = array();
}
$commit_map = mpull($commits, 'getCommitIdentifier', 'getPHID');
$revisions = array();
$revision_map = array();
if ($commits) {
$revision_ids = id(new DifferentialRevision())
->loadIDsByCommitPHIDs(array_keys($commit_map));
if ($revision_ids) {
$revisions = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->withIDs($revision_ids)
->execute();
$revisions = mpull($revisions, null, 'getID');
}
foreach ($revision_ids as $commit_phid => $revision_id) {
// If the viewer can't actually see this revision, skip it.
if (!isset($revisions[$revision_id])) {
continue;
}
$revision_map[$commit_map[$commit_phid]] = $revision_id;
}
}
$base_href = (string)$drequest->generateURI(
array(
'action' => 'browse',
'stable' => true,
));
$skip_text = pht('Skip Past This Commit');
$skip_icon = id(new PHUIIconView())
->setIcon('fa-backward');
Javelin::initBehavior('phabricator-tooltips');
$handle_phids = array();
foreach ($commits as $commit) {
$author_phid = $commit->getAuthorPHID();
if ($author_phid) {
$handle_phids[] = $author_phid;
}
}
foreach ($revisions as $revision) {
$handle_phids[] = $revision->getAuthorPHID();
}
$handles = $viewer->loadHandles($handle_phids);
$map = array();
$epochs = array();
foreach ($identifiers as $identifier) {
$revision_id = idx($revision_map, $identifier);
if ($revision_id) {
$revision = idx($revisions, $revision_id);
} else {
$revision = null;
}
$skip_href = $base_href.'?before='.$identifier;
$skip_link = javelin_tag(
'a',
array(
'href' => $skip_href,
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $skip_text,
'align' => 'E',
'size' => 300,
),
),
$skip_icon);
$commit = $commits[$identifier];
$author_phid = $commit->getAuthorPHID();
if (!$author_phid && $revision) {
$author_phid = $revision->getAuthorPHID();
}
if (!$author_phid) {
// This means we couldn't identify an author for the commit or the
// revision. We just render a blank for alignment.
$author_style = null;
$author_href = null;
$author_sigil = null;
$author_meta = null;
} else {
$author_src = $handles[$author_phid]->getImageURI();
$author_style = 'background-image: url('.$author_src.');';
$author_href = $handles[$author_phid]->getURI();
$author_sigil = 'has-tooltip';
$author_meta = array(
'tip' => $handles[$author_phid]->getName(),
'align' => 'E',
);
}
$author_link = javelin_tag(
$author_href ? 'a' : 'span',
array(
'class' => 'phabricator-source-blame-author',
'style' => $author_style,
'href' => $author_href,
'sigil' => $author_sigil,
'meta' => $author_meta,
));
$commit_link = javelin_tag(
'a',
array(
'href' => $commit->getURI(),
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $this->renderCommitTooltip($commit, $handles),
'align' => 'E',
'size' => 600,
),
),
$commit->getLocalName());
$info = array(
$author_link,
$commit_link,
);
if ($revision) {
$revision_link = javelin_tag(
'a',
array(
'href' => $revision->getURI(),
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $this->renderRevisionTooltip($revision, $handles),
'align' => 'E',
'size' => 600,
),
),
$revision->getMonogram());
$info = array(
$info,
" \xC2\xB7 ",
$revision_link,
);
}
$epoch = $commit->getEpoch();
$epochs[] = $epoch;
$data = array(
'skip' => $skip_link,
'info' => hsprintf('%s', $info),
'epoch' => $epoch,
);
$map[$identifier] = $data;
}
$epoch_min = min($epochs);
$epoch_max = max($epochs);
return id(new AphrontAjaxResponse())->setContent(
array(
'blame' => $blame,
'map' => $map,
'epoch' => array(
'min' => $epoch_min,
'max' => $epoch_max,
),
));
}
private function loadBlame() {
$drequest = $this->getDiffusionRequest();
$commit = $drequest->getCommit();
$path = $drequest->getPath();
$blame_timeout = 15;
$blame = $this->callConduitWithDiffusionRequest(
'diffusion.blame',
array(
'commit' => $commit,
'paths' => array($path),
'timeout' => $blame_timeout,
));
return idx($blame, $path, array());
}
private function renderRevisionTooltip(
DifferentialRevision $revision,
$handles) {
$viewer = $this->getViewer();
$date = phabricator_date($revision->getDateModified(), $viewer);
$monogram = $revision->getMonogram();
$title = $revision->getTitle();
$header = "{$monogram} {$title}";
$author = $handles[$revision->getAuthorPHID()]->getName();
return "{$header}\n{$date} \xC2\xB7 {$author}";
}
private function renderCommitTooltip(
PhabricatorRepositoryCommit $commit,
$handles) {
$viewer = $this->getViewer();
$date = phabricator_date($commit->getEpoch(), $viewer);
$summary = trim($commit->getSummary());
$author_phid = $commit->getAuthorPHID();
if ($author_phid && isset($handles[$author_phid])) {
$author_name = $handles[$author_phid]->getName();
} else {
$author_name = null;
}
if ($author_name) {
return "{$summary}\n{$date} \xC2\xB7 {$author_name}";
} else {
return "{$summary}\n{$date}";
}
}
}

View file

@ -0,0 +1,45 @@
<?php
final class DiffusionDocumentController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$response = $this->loadDiffusionContext();
if ($response) {
return $response;
}
$drequest = $this->getDiffusionRequest();
$engine = id(new DiffusionDocumentRenderingEngine())
->setRequest($request)
->setDiffusionRequest($drequest)
->setController($this);
$viewer = $this->getViewer();
$request = $this->getRequest();
$repository = $drequest->getRepository();
$file_phid = $request->getStr('filePHID');
$file = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($file_phid))
->executeOne();
if (!$file) {
return $engine->newErrorResponse(
pht(
'This file ("%s") does not exist or could not be loaded.',
$file_phid));
}
$ref = id(new PhabricatorDocumentRef())
->setFile($file);
return $engine->newRenderResponse($ref);
}
}

View file

@ -431,10 +431,13 @@ final class DiffusionServeController extends DiffusionController {
$uri = $repository->getAlmanacServiceURI(
$viewer,
$is_cluster_request,
array(
'http',
'https',
'neverProxy' => $is_cluster_request,
'protocols' => array(
'http',
'https',
),
'writable' => !$this->isReadOnlyRequest($repository),
));
if ($uri) {
$future = $this->getRequest()->newClusterProxyFuture($uri);

View file

@ -0,0 +1,102 @@
<?php
final class DiffusionDocumentRenderingEngine
extends PhabricatorDocumentRenderingEngine {
private $diffusionRequest;
public function setDiffusionRequest(DiffusionRequest $drequest) {
$this->diffusionRequest = $drequest;
return $this;
}
public function getDiffusionRequest() {
return $this->diffusionRequest;
}
protected function newRefViewURI(
PhabricatorDocumentRef $ref,
PhabricatorDocumentEngine $engine) {
$file = $ref->getFile();
$engine_key = $engine->getDocumentEngineKey();
$drequest = $this->getDiffusionRequest();
return (string)$drequest->generateURI(
array(
'action' => 'browse',
'stable' => true,
'params' => array(
'as' => $engine_key,
),
));
}
protected function newRefRenderURI(
PhabricatorDocumentRef $ref,
PhabricatorDocumentEngine $engine) {
$engine_key = $engine->getDocumentEngineKey();
$file = $ref->getFile();
$file_phid = $file->getPHID();
$drequest = $this->getDiffusionRequest();
return (string)$drequest->generateURI(
array(
'action' => 'document',
'stable' => true,
'params' => array(
'as' => $engine_key,
'filePHID' => $file_phid,
),
));
}
protected function getSelectedDocumentEngineKey() {
return $this->getRequest()->getStr('as');
}
protected function getSelectedLineRange() {
$range = $this->getDiffusionRequest()->getLine();
return AphrontRequest::parseURILineRange($range, 1000);
}
protected function addApplicationCrumbs(
PHUICrumbsView $crumbs,
PhabricatorDocumentRef $ref = null) {
return;
}
protected function willRenderRef(PhabricatorDocumentRef $ref) {
$drequest = $this->getDiffusionRequest();
$blame_uri = (string)$drequest->generateURI(
array(
'action' => 'blame',
'stable' => true,
));
$ref
->setSymbolMetadata($this->getSymbolMetadata())
->setBlameURI($blame_uri);
}
private function getSymbolMetadata() {
$drequest = $this->getDiffusionRequest();
$repo = $drequest->getRepository();
$symbol_repos = nonempty($repo->getSymbolSources(), array());
$symbol_repos[] = $repo->getPHID();
$lang = last(explode('.', $drequest->getPath()));
return array(
'repositories' => $symbol_repos,
'lang' => $lang,
'path' => $drequest->getPath(),
);
}
}

View file

@ -29,7 +29,7 @@ final class DiffusionGitReceivePackSSHWorkflow extends DiffusionGitSSHWorkflow {
->setLog($this);
if ($this->shouldProxy()) {
$command = $this->getProxyCommand();
$command = $this->getProxyCommand(true);
$did_synchronize = false;
if ($device) {

View file

@ -22,7 +22,7 @@ final class DiffusionGitUploadPackSSHWorkflow extends DiffusionGitSSHWorkflow {
$is_proxy = $this->shouldProxy();
if ($is_proxy) {
$command = $this->getProxyCommand();
$command = $this->getProxyCommand(false);
if ($device) {
$this->writeClusterEngineLogMessage(

View file

@ -45,7 +45,10 @@ final class DiffusionMercurialServeSSHWorkflow
}
if ($this->shouldProxy()) {
$command = $this->getProxyCommand();
// NOTE: For now, we're always requesting a writable node. The request
// may not actually need one, but we can't currently determine whether
// it is read-only or not at this phase of evaluation.
$command = $this->getProxyCommand(true);
} else {
$command = csprintf(
'hg -R %s serve --stdio',

Some files were not shown because too many files have changed in this diff Show more