mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-10 23:01:04 +01:00
(stable) Promote 2018 Week 15
This commit is contained in:
commit
1f68a3b6eb
144 changed files with 4373 additions and 3131 deletions
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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};
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
final class AlamancServiceEditConduitAPIMethod
|
||||
final class AlmanacServiceEditConduitAPIMethod
|
||||
extends PhabricatorEditEngineAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
|
@ -40,7 +40,7 @@ final class AlmanacBindingDisableController
|
|||
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$type_disable = AlmanacBindingTransaction::TYPE_DISABLE;
|
||||
$type_disable = AlmanacBindingDisableTransaction::TRANSACTIONTYPE;
|
||||
|
||||
$xactions = array();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
172
src/applications/almanac/editor/AlmanacBindingEditEngine.php
Normal file
172
src/applications/almanac/editor/AlmanacBindingEditEngine.php
Normal 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')),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
public function getCreateObjectTitleForFeed($author, $object) {
|
||||
return pht('%s created %s.', $author, $object);
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||
protected function supportsSearch() {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
183
src/applications/almanac/editor/AlmanacInterfaceEditEngine.php
Normal file
183
src/applications/almanac/editor/AlmanacInterfaceEditEngine.php
Normal 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()),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
18
src/applications/almanac/editor/AlmanacInterfaceEditor.php
Normal file
18
src/applications/almanac/editor/AlmanacInterfaceEditor.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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()),
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()),
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,5 +9,7 @@ interface AlmanacPropertyInterface {
|
|||
public function getAlmanacPropertyValue($key, $default = null);
|
||||
public function getAlmanacPropertyFieldSpecifications();
|
||||
public function newAlmanacPropertyEditEngine();
|
||||
public function getAlmanacPropertySetTransactionType();
|
||||
public function getAlmanacPropertyDeleteTransactionType();
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,10 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
return array();
|
||||
}
|
||||
|
||||
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available service type implementations.
|
||||
*
|
||||
|
|
|
@ -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'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,6 +143,14 @@ final class AlmanacDevice
|
|||
return new AlmanacDevicePropertyEditEngine();
|
||||
}
|
||||
|
||||
public function getAlmanacPropertySetTransactionType() {
|
||||
return AlmanacDeviceSetPropertyTransaction::TRANSACTIONTYPE;
|
||||
}
|
||||
|
||||
public function getAlmanacPropertyDeleteTransactionType() {
|
||||
return AlmanacDeviceDeletePropertyTransaction::TRANSACTIONTYPE;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacInterfaceTransaction
|
||||
extends AlmanacModularTransaction {
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return AlmanacInterfacePHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getBaseTransactionClass() {
|
||||
return 'AlmanacInterfaceTransactionType';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacModularTransaction
|
||||
extends PhabricatorModularTransaction {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'almanac';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionCommentObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacBindingTransactionType
|
||||
extends AlmanacTransactionType {}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacDeviceTransactionType
|
||||
extends AlmanacTransactionType {}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacInterfaceTransactionType
|
||||
extends AlmanacTransactionType {}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacNamespaceTransactionType
|
||||
extends AlmanacTransactionType {}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacNetworkTransactionType
|
||||
extends AlmanacTransactionType {}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class AlmanacServiceTransactionType
|
||||
extends AlmanacTransactionType {}
|
|
@ -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;
|
||||
}
|
||||
}
|
97
src/applications/almanac/xaction/AlmanacTransactionType.php
Normal file
97
src/applications/almanac/xaction/AlmanacTransactionType.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -431,10 +431,13 @@ final class DiffusionServeController extends DiffusionController {
|
|||
|
||||
$uri = $repository->getAlmanacServiceURI(
|
||||
$viewer,
|
||||
$is_cluster_request,
|
||||
array(
|
||||
'neverProxy' => $is_cluster_request,
|
||||
'protocols' => array(
|
||||
'http',
|
||||
'https',
|
||||
),
|
||||
'writable' => !$this->isReadOnlyRequest($repository),
|
||||
));
|
||||
if ($uri) {
|
||||
$future = $this->getRequest()->newClusterProxyFuture($uri);
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue