Merge branch 'master' into blender-tweaks
Conflicts: resources/celerity/map.php src/applications/maniphest/controller/ManiphestTaskListController.php
This commit is contained in:
		| @@ -7,14 +7,14 @@ | ||||
|  */ | ||||
| return array( | ||||
|   'names' => array( | ||||
|     'core.pkg.css' => 'a3c49f47', | ||||
|     'core.pkg.css' => '85697954', | ||||
|     'core.pkg.js' => 'cbdbd552', | ||||
|     'darkconsole.pkg.js' => 'df001cab', | ||||
|     'differential.pkg.css' => '0f9c3082', | ||||
|     'differential.pkg.css' => '8af45893', | ||||
|     'differential.pkg.js' => '73337d1d', | ||||
|     'diffusion.pkg.css' => '591664fa', | ||||
|     'diffusion.pkg.js' => 'bfc0737b', | ||||
|     'maniphest.pkg.css' => 'f5d89daf', | ||||
|     'maniphest.pkg.css' => 'e34dfbec', | ||||
|     'maniphest.pkg.js' => 'df4aa49f', | ||||
|     'rsrc/css/aphront/aphront-bars.css' => '231ac33c', | ||||
|     'rsrc/css/aphront/context-bar.css' => '1c3b0529', | ||||
| @@ -24,7 +24,7 @@ return array( | ||||
|     'rsrc/css/aphront/lightbox-attachment.css' => '7acac05d', | ||||
|     'rsrc/css/aphront/list-filter-view.css' => '2ae43867', | ||||
|     'rsrc/css/aphront/multi-column.css' => '1b95ab2e', | ||||
|     'rsrc/css/aphront/notification.css' => 'ef2c9b34', | ||||
|     'rsrc/css/aphront/notification.css' => '9c279160', | ||||
|     'rsrc/css/aphront/pager-view.css' => '2e3539af', | ||||
|     'rsrc/css/aphront/panel-view.css' => '5846dfa2', | ||||
|     'rsrc/css/aphront/phabricator-nav-view.css' => '9283c2df', | ||||
| @@ -60,7 +60,7 @@ return array( | ||||
|     'rsrc/css/application/differential/revision-comment.css' => '48186045', | ||||
|     'rsrc/css/application/differential/revision-history.css' => '0e8eb855', | ||||
|     'rsrc/css/application/differential/revision-list.css' => 'f3c47d33', | ||||
|     'rsrc/css/application/differential/table-of-contents.css' => '6bf8e1d2', | ||||
|     'rsrc/css/application/differential/table-of-contents.css' => '63f3ef4a', | ||||
|     'rsrc/css/application/diffusion/diffusion-icons.css' => '9c5828da', | ||||
|     'rsrc/css/application/diffusion/diffusion-source.css' => '66fdf661', | ||||
|     'rsrc/css/application/feed/feed.css' => '7bfc6f12', | ||||
| @@ -72,15 +72,15 @@ return array( | ||||
|     'rsrc/css/application/maniphest/batch-editor.css' => '8f380ebc', | ||||
|     'rsrc/css/application/maniphest/report.css' => '6fc16517', | ||||
|     'rsrc/css/application/maniphest/task-edit.css' => '8e23031b', | ||||
|     'rsrc/css/application/maniphest/task-summary.css' => '00c3be7a', | ||||
|     'rsrc/css/application/maniphest/task-summary.css' => '13ed8360', | ||||
|     'rsrc/css/application/objectselector/object-selector.css' => '029a133d', | ||||
|     'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', | ||||
|     'rsrc/css/application/paste/paste.css' => 'aa1767d1', | ||||
|     'rsrc/css/application/people/people-profile.css' => '5402f7a5', | ||||
|     'rsrc/css/application/people/people-profile.css' => '0d5f6498', | ||||
|     'rsrc/css/application/phame/phame.css' => '19ecc703', | ||||
|     'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', | ||||
|     'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', | ||||
|     'rsrc/css/application/pholio/pholio.css' => '47dffb9c', | ||||
|     'rsrc/css/application/pholio/pholio.css' => '95174bdd', | ||||
|     'rsrc/css/application/phortune/phortune-credit-card-form.css' => 'b25b4beb', | ||||
|     'rsrc/css/application/phortune/phortune.css' => '9149f103', | ||||
|     'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', | ||||
| @@ -104,12 +104,12 @@ return array( | ||||
|     'rsrc/css/application/uiexample/example.css' => '528b19de', | ||||
|     'rsrc/css/core/core.css' => '40151074', | ||||
|     'rsrc/css/core/remarkup.css' => '45313445', | ||||
|     'rsrc/css/core/syntax.css' => '863f3cd8', | ||||
|     'rsrc/css/core/syntax.css' => '56c1ba38', | ||||
|     'rsrc/css/core/z-index.css' => '44e1d311', | ||||
|     'rsrc/css/diviner/diviner-shared.css' => '38813222', | ||||
|     'rsrc/css/font/font-awesome.css' => '73d075c3', | ||||
|     'rsrc/css/font/font-source-sans-pro.css' => '91d53463', | ||||
|     'rsrc/css/font/phui-font-icon-base.css' => 'eb84f033', | ||||
|     'rsrc/css/font/phui-font-icon-base.css' => '3dad2ae3', | ||||
|     'rsrc/css/layout/phabricator-action-header-view.css' => '83e2cc86', | ||||
|     'rsrc/css/layout/phabricator-crumbs-view.css' => 'a49339de', | ||||
|     'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', | ||||
| @@ -119,13 +119,13 @@ return array( | ||||
|     'rsrc/css/phui/calendar/phui-calendar-day.css' => 'de035c8a', | ||||
|     'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1d0ca59', | ||||
|     'rsrc/css/phui/calendar/phui-calendar-month.css' => 'a92e47d2', | ||||
|     'rsrc/css/phui/calendar/phui-calendar.css' => '5e1ad989', | ||||
|     'rsrc/css/phui/calendar/phui-calendar.css' => '8675968e', | ||||
|     'rsrc/css/phui/phui-action-list.css' => '9ee9910a', | ||||
|     'rsrc/css/phui/phui-box.css' => '7b3a2eed', | ||||
|     'rsrc/css/phui/phui-button.css' => 'c7412aa1', | ||||
|     'rsrc/css/phui/phui-document.css' => 'a5615198', | ||||
|     'rsrc/css/phui/phui-feed-story.css' => '55dc7732', | ||||
|     'rsrc/css/phui/phui-fontkit.css' => 'fff25cfa', | ||||
|     'rsrc/css/phui/phui-fontkit.css' => '9c3d2dce', | ||||
|     'rsrc/css/phui/phui-form-view.css' => '1ff38f33', | ||||
|     'rsrc/css/phui/phui-form.css' => 'b78ec020', | ||||
|     'rsrc/css/phui/phui-header-view.css' => '39594ac0', | ||||
| @@ -134,15 +134,15 @@ return array( | ||||
|     'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', | ||||
|     'rsrc/css/phui/phui-list.css' => '43ed2d93', | ||||
|     'rsrc/css/phui/phui-object-box.css' => 'e9f7e938', | ||||
|     'rsrc/css/phui/phui-object-item-list-view.css' => 'e1e6425f', | ||||
|     'rsrc/css/phui/phui-object-item-list-view.css' => '5053dee8', | ||||
|     'rsrc/css/phui/phui-pinboard-view.css' => '3dd4a269', | ||||
|     'rsrc/css/phui/phui-property-list-view.css' => '86f9df88', | ||||
|     'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b', | ||||
|     'rsrc/css/phui/phui-spacing.css' => '042804d6', | ||||
|     'rsrc/css/phui/phui-status.css' => '2f562399', | ||||
|     'rsrc/css/phui/phui-tag-view.css' => 'c4158073', | ||||
|     'rsrc/css/phui/phui-text.css' => '23e9b4b7', | ||||
|     'rsrc/css/phui/phui-timeline-view.css' => 'bbd990d0', | ||||
|     'rsrc/css/phui/phui-status.css' => '888cedb8', | ||||
|     'rsrc/css/phui/phui-tag-view.css' => 'b0c282e0', | ||||
|     'rsrc/css/phui/phui-text.css' => 'cf019f54', | ||||
|     'rsrc/css/phui/phui-timeline-view.css' => '8c6fefe7', | ||||
|     'rsrc/css/phui/phui-workboard-view.css' => '2bf82d00', | ||||
|     'rsrc/css/phui/phui-workpanel-view.css' => '198c7e6c', | ||||
|     'rsrc/css/sprite-apps-large.css' => '20ec0cc0', | ||||
| @@ -150,7 +150,7 @@ return array( | ||||
|     'rsrc/css/sprite-conpherence.css' => '3b4a0487', | ||||
|     'rsrc/css/sprite-docs.css' => '5f65d0da', | ||||
|     'rsrc/css/sprite-gradient.css' => '4bdb98a7', | ||||
|     'rsrc/css/sprite-login.css' => 'cf08ac44', | ||||
|     'rsrc/css/sprite-login.css' => 'a355d921', | ||||
|     'rsrc/css/sprite-main-header.css' => '92720ee2', | ||||
|     'rsrc/css/sprite-menu.css' => '8fead76a', | ||||
|     'rsrc/css/sprite-payments.css' => 'cc085d44', | ||||
| @@ -323,8 +323,8 @@ return array( | ||||
|     'rsrc/image/sprite-docs-X2.png' => '6dc1adad', | ||||
|     'rsrc/image/sprite-docs.png' => '4636297f', | ||||
|     'rsrc/image/sprite-gradient.png' => 'ec15a417', | ||||
|     'rsrc/image/sprite-login-X2.png' => '46f95dcc', | ||||
|     'rsrc/image/sprite-login.png' => '4e0e66ee', | ||||
|     'rsrc/image/sprite-login-X2.png' => '5ae6de3a', | ||||
|     'rsrc/image/sprite-login.png' => '07f2c67c', | ||||
|     'rsrc/image/sprite-main-header.png' => '83521873', | ||||
|     'rsrc/image/sprite-menu-X2.png' => '39d78f97', | ||||
|     'rsrc/image/sprite-menu.png' => '259dab45', | ||||
| @@ -524,7 +524,7 @@ return array( | ||||
|     'differential-revision-comment-css' => '48186045', | ||||
|     'differential-revision-history-css' => '0e8eb855', | ||||
|     'differential-revision-list-css' => 'f3c47d33', | ||||
|     'differential-table-of-contents-css' => '6bf8e1d2', | ||||
|     'differential-table-of-contents-css' => '63f3ef4a', | ||||
|     'diffusion-icons-css' => '9c5828da', | ||||
|     'diffusion-source-css' => '66fdf661', | ||||
|     'diviner-shared-css' => '38813222', | ||||
| @@ -692,13 +692,13 @@ return array( | ||||
|     'maniphest-batch-editor' => '8f380ebc', | ||||
|     'maniphest-report-css' => '6fc16517', | ||||
|     'maniphest-task-edit-css' => '8e23031b', | ||||
|     'maniphest-task-summary-css' => '00c3be7a', | ||||
|     'maniphest-task-summary-css' => '13ed8360', | ||||
|     'multirow-row-manager' => '41e47dea', | ||||
|     'owners-path-editor' => 'aa1733d0', | ||||
|     'owners-path-editor-css' => '2f00933b', | ||||
|     'paste-css' => 'aa1767d1', | ||||
|     'path-typeahead' => 'f7fc67ec', | ||||
|     'people-profile-css' => '5402f7a5', | ||||
|     'people-profile-css' => '0d5f6498', | ||||
|     'phabricator-action-list-view-css' => '9ee9910a', | ||||
|     'phabricator-application-launch-view-css' => '5d71008f', | ||||
|     'phabricator-busy' => '6453c869', | ||||
| @@ -722,7 +722,7 @@ return array( | ||||
|     'phabricator-main-menu-view' => 'a1c976b2', | ||||
|     'phabricator-nav-view-css' => '9283c2df', | ||||
|     'phabricator-notification' => '0c6946e7', | ||||
|     'phabricator-notification-css' => 'ef2c9b34', | ||||
|     'phabricator-notification-css' => '9c279160', | ||||
|     'phabricator-notification-menu-css' => '6aa0a74b', | ||||
|     'phabricator-object-selector-css' => '029a133d', | ||||
|     'phabricator-phtize' => 'd254d646', | ||||
| @@ -753,7 +753,7 @@ return array( | ||||
|     'phabricator-welcome-page' => 'c370f13b', | ||||
|     'phabricator-zindex-css' => '44e1d311', | ||||
|     'phame-css' => '19ecc703', | ||||
|     'pholio-css' => '47dffb9c', | ||||
|     'pholio-css' => '95174bdd', | ||||
|     'pholio-edit-css' => '3ad9d1ee', | ||||
|     'pholio-inline-comments-css' => '8e545e49', | ||||
|     'phortune-credit-card-form' => '2290aeef', | ||||
| @@ -764,14 +764,14 @@ return array( | ||||
|     'phui-action-header-view-css' => '83e2cc86', | ||||
|     'phui-box-css' => '7b3a2eed', | ||||
|     'phui-button-css' => 'c7412aa1', | ||||
|     'phui-calendar-css' => '5e1ad989', | ||||
|     'phui-calendar-css' => '8675968e', | ||||
|     'phui-calendar-day-css' => 'de035c8a', | ||||
|     'phui-calendar-list-css' => 'c1d0ca59', | ||||
|     'phui-calendar-month-css' => 'a92e47d2', | ||||
|     'phui-document-view-css' => 'a5615198', | ||||
|     'phui-feed-story-css' => '55dc7732', | ||||
|     'phui-font-icon-base-css' => 'eb84f033', | ||||
|     'phui-fontkit-css' => 'fff25cfa', | ||||
|     'phui-font-icon-base-css' => '3dad2ae3', | ||||
|     'phui-fontkit-css' => '9c3d2dce', | ||||
|     'phui-form-css' => 'b78ec020', | ||||
|     'phui-form-view-css' => '1ff38f33', | ||||
|     'phui-header-view-css' => '39594ac0', | ||||
| @@ -780,15 +780,15 @@ return array( | ||||
|     'phui-info-panel-css' => '27ea50a1', | ||||
|     'phui-list-view-css' => '43ed2d93', | ||||
|     'phui-object-box-css' => 'e9f7e938', | ||||
|     'phui-object-item-list-view-css' => 'e1e6425f', | ||||
|     'phui-object-item-list-view-css' => '5053dee8', | ||||
|     'phui-pinboard-view-css' => '3dd4a269', | ||||
|     'phui-property-list-view-css' => '86f9df88', | ||||
|     'phui-remarkup-preview-css' => '19ad512b', | ||||
|     'phui-spacing-css' => '042804d6', | ||||
|     'phui-status-list-view-css' => '2f562399', | ||||
|     'phui-tag-view-css' => 'c4158073', | ||||
|     'phui-text-css' => '23e9b4b7', | ||||
|     'phui-timeline-view-css' => 'bbd990d0', | ||||
|     'phui-status-list-view-css' => '888cedb8', | ||||
|     'phui-tag-view-css' => 'b0c282e0', | ||||
|     'phui-text-css' => 'cf019f54', | ||||
|     'phui-timeline-view-css' => '8c6fefe7', | ||||
|     'phui-workboard-view-css' => '2bf82d00', | ||||
|     'phui-workpanel-view-css' => '198c7e6c', | ||||
|     'phuix-action-list-view' => 'b5c256b8', | ||||
| @@ -815,13 +815,13 @@ return array( | ||||
|     'sprite-conpherence-css' => '3b4a0487', | ||||
|     'sprite-docs-css' => '5f65d0da', | ||||
|     'sprite-gradient-css' => '4bdb98a7', | ||||
|     'sprite-login-css' => 'cf08ac44', | ||||
|     'sprite-login-css' => 'a355d921', | ||||
|     'sprite-main-header-css' => '92720ee2', | ||||
|     'sprite-menu-css' => '8fead76a', | ||||
|     'sprite-payments-css' => 'cc085d44', | ||||
|     'sprite-projects-css' => '7578fa56', | ||||
|     'sprite-tokens-css' => '1706b943', | ||||
|     'syntax-highlighting-css' => '863f3cd8', | ||||
|     'syntax-highlighting-css' => '56c1ba38', | ||||
|     'tokens-css' => '3d0f239e', | ||||
|   ), | ||||
|   'requires' => array( | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.9 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.4 KiB | 
| @@ -74,7 +74,7 @@ | ||||
|     "login-MediaWiki"    : { | ||||
|       "name" : "login-MediaWiki", | ||||
|       "rule" : ".login-MediaWiki", | ||||
|       "hash" : "6e9e75fdad545f415d78719bd2dee3ec" | ||||
|       "hash" : "51c7e71ab0e44126e72d8a130779b02c" | ||||
|     }, | ||||
|     "login-Openid"       : { | ||||
|       "name" : "login-Openid", | ||||
|   | ||||
							
								
								
									
										2
									
								
								resources/sql/autopatches/20141011.phortunemerchedit.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								resources/sql/autopatches/20141011.phortunemerchedit.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ALTER TABLE {$NAMESPACE}_phortune.phortune_merchant | ||||
|   DROP editPolicy; | ||||
							
								
								
									
										19
									
								
								resources/sql/autopatches/20141012.phortunecartxaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/sql/autopatches/20141012.phortunecartxaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| CREATE TABLE {$NAMESPACE}_phortune.phortune_carttransaction ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL, | ||||
|   oldValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   newValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   metadata LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   KEY `key_object` (`objectPHID`) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										2
									
								
								resources/sql/autopatches/20141013.phortunecartkey.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								resources/sql/autopatches/20141013.phortunecartkey.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ALTER TABLE {$NAMESPACE}_phortune.phortune_cart | ||||
|   ADD mailKey BINARY(20) NOT NULL; | ||||
							
								
								
									
										22
									
								
								resources/sql/autopatches/20141016.almanac.device.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								resources/sql/autopatches/20141016.almanac.device.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| TRUNCATE TABLE {$NAMESPACE}_almanac.almanac_device; | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   CHANGE name name VARCHAR(128) NOT NULL COLLATE utf8_bin; | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   ADD nameIndex BINARY(12) NOT NULL; | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   ADD mailKey BINARY(20) NOT NULL; | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   ADD UNIQUE KEY `key_name` (nameIndex); | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   ADD KEY `key_nametext` (name); | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   ADD viewPolicy VARBINARY(64) NOT NULL; | ||||
|  | ||||
| ALTER TABLE {$NAMESPACE}_almanac.almanac_device | ||||
|   ADD editPolicy VARBINARY(64) NOT NULL; | ||||
							
								
								
									
										19
									
								
								resources/sql/autopatches/20141016.almanac.dxaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/sql/autopatches/20141016.almanac.dxaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_devicetransaction ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL, | ||||
|   oldValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   newValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   metadata LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   KEY `key_object` (`objectPHID`) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										13
									
								
								resources/sql/autopatches/20141016.almanac.interface.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								resources/sql/autopatches/20141016.almanac.interface.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_interface ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARBINARY(64) NOT NULL, | ||||
|   devicePHID VARBINARY(64) NOT NULL, | ||||
|   networkPHID VARBINARY(64) NOT NULL, | ||||
|   address VARCHAR(128) NOT NULL COLLATE utf8_bin, | ||||
|   port INT UNSIGNED NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (phid), | ||||
|   KEY `key_location` (networkPHID, address, port), | ||||
|   KEY `key_device` (devicePHID) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										11
									
								
								resources/sql/autopatches/20141016.almanac.network.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								resources/sql/autopatches/20141016.almanac.network.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_network ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARBINARY(64) NOT NULL, | ||||
|   name VARCHAR(128) NOT NULL COLLATE utf8_bin, | ||||
|   mailKey BINARY(20) NOT NULL, | ||||
|   viewPolicy VARBINARY(64) NOT NULL, | ||||
|   editPolicy VARBINARY(64) NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (phid) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										19
									
								
								resources/sql/autopatches/20141016.almanac.nxaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/sql/autopatches/20141016.almanac.nxaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_networktransaction ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL, | ||||
|   oldValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   newValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   metadata LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   KEY `key_object` (`objectPHID`) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										14
									
								
								resources/sql/autopatches/20141016.almanac.service.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								resources/sql/autopatches/20141016.almanac.service.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_service ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARBINARY(64) NOT NULL, | ||||
|   name VARCHAR(128) NOT NULL COLLATE utf8_bin, | ||||
|   nameIndex BINARY(12) NOT NULL, | ||||
|   mailKey BINARY(20) NOT NULL, | ||||
|   viewPolicy VARBINARY(64) NOT NULL, | ||||
|   editPolicy VARBINARY(64) NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (phid), | ||||
|   UNIQUE KEY `key_name` (nameIndex), | ||||
|   KEY `key_nametext` (name) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										19
									
								
								resources/sql/autopatches/20141016.almanac.sxaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/sql/autopatches/20141016.almanac.sxaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_servicetransaction ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL, | ||||
|   oldValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   newValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   metadata LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   KEY `key_object` (`objectPHID`) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										14
									
								
								resources/sql/autopatches/20141017.almanac.binding.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								resources/sql/autopatches/20141017.almanac.binding.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_binding ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARBINARY(64) NOT NULL, | ||||
|   servicePHID VARBINARY(64) NOT NULL, | ||||
|   devicePHID VARBINARY(64) NOT NULL, | ||||
|   interfacePHID VARBINARY(64) NOT NULL, | ||||
|   mailKey BINARY(20) NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (phid), | ||||
|   UNIQUE KEY `key_service` (servicePHID, interfacePHID), | ||||
|   KEY `key_device` (devicePHID), | ||||
|   KEY `key_interface` (interfacePHID) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										19
									
								
								resources/sql/autopatches/20141017.almanac.bxaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/sql/autopatches/20141017.almanac.bxaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| CREATE TABLE {$NAMESPACE}_almanac.almanac_bindingtransaction ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL, | ||||
|   oldValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   newValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   metadata LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   KEY `key_object` (`objectPHID`) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										19
									
								
								resources/sql/autopatches/20141025.phriction.1.xaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								resources/sql/autopatches/20141025.phriction.1.xaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| CREATE TABLE {$NAMESPACE}_phriction.phriction_transaction ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL, | ||||
|   commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL, | ||||
|   oldValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   newValue LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   metadata LONGTEXT COLLATE utf8_bin NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   KEY `key_object` (`objectPHID`) | ||||
| ) ENGINE=InnoDB, COLLATE utf8_general_ci; | ||||
							
								
								
									
										16
									
								
								resources/sql/autopatches/20141025.phriction.2.xaction.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								resources/sql/autopatches/20141025.phriction.2.xaction.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| CREATE TABLE {$NAMESPACE}_phriction.phriction_transaction_comment ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   phid VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, | ||||
|   transactionPHID VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, | ||||
|   authorPHID VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, | ||||
|   viewPolicy VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, | ||||
|   editPolicy VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, | ||||
|   commentVersion INT UNSIGNED NOT NULL, | ||||
|   content LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, | ||||
|   contentSource LONGTEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, | ||||
|   isDeleted TINYINT(1) NOT NULL, | ||||
|   dateCreated INT UNSIGNED NOT NULL, | ||||
|   dateModified INT UNSIGNED NOT NULL, | ||||
|   UNIQUE KEY `key_phid` (`phid`), | ||||
|   UNIQUE KEY `key_version` (`transactionPHID`,`commentVersion`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | ||||
							
								
								
									
										2
									
								
								resources/sql/autopatches/20141025.phriction.mailkey.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								resources/sql/autopatches/20141025.phriction.mailkey.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ALTER TABLE {$NAMESPACE}_phriction.phriction_document | ||||
|   ADD mailKey VARCHAR(20) NOT NULL COLLATE utf8_bin; | ||||
| @@ -1,6 +1,6 @@ | ||||
| create table {$NAMESPACE}_project.project ( | ||||
|   id int unsigned not null auto_increment primary key, | ||||
|   name varchar(255) not null, | ||||
|   name varchar(255) COLLATE `binary` not null, | ||||
|   unique key (name), | ||||
|   phid varchar(64) binary not null, | ||||
|   authorPHID varchar(64) binary not null, | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| create table {$NAMESPACE}_user.user_oauthinfo ( | ||||
|   id int unsigned not null auto_increment primary key, | ||||
|   userID int unsigned not null, | ||||
|   oauthProvider varchar(255) not null, | ||||
|   oauthUID varchar(255) not null, | ||||
|   oauthProvider varchar(255) COLLATE `binary` not null, | ||||
|   oauthUID varchar(255) COLLATE `binary` not null, | ||||
|   unique key (userID, oauthProvider), | ||||
|   unique key (oauthProvider, oauthUID), | ||||
|   dateCreated int unsigned not null, | ||||
|   | ||||
| @@ -23,6 +23,6 @@ create table {$NAMESPACE}_timeline.timeline_eventdata ( | ||||
| ); | ||||
|  | ||||
| create table {$NAMESPACE}_timeline.timeline_cursor ( | ||||
|   name varchar(255) not null primary key, | ||||
|   name varchar(255) COLLATE `binary` not null primary key, | ||||
|   position int unsigned not null | ||||
| ); | ||||
|   | ||||
| @@ -7,7 +7,7 @@ CREATE TABLE {$NAMESPACE}_herald.herald_action ( | ||||
|  | ||||
| CREATE TABLE {$NAMESPACE}_herald.herald_rule ( | ||||
|   id int unsigned not null auto_increment primary key, | ||||
|   name varchar(255) not null, | ||||
|   name varchar(255) COLLATE `binary` not null, | ||||
|   authorPHID varchar(64) binary not null, | ||||
|   contentType varchar(255) not null, | ||||
|   mustMatchAll bool not null, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| CREATE TABLE {$NAMESPACE}_repository.repository_badcommit ( | ||||
|   fullCommitName varchar(255) binary not null primary key, | ||||
|   fullCommitName varchar(255) COLLATE `binary` not null primary key, | ||||
|   description longblob not null | ||||
| ); | ||||
|   | ||||
| @@ -2,7 +2,7 @@ CREATE TABLE {$NAMESPACE}_owners.owners_package ( | ||||
|   id int unsigned not null auto_increment primary key, | ||||
|   phid varchar(64) binary not null, | ||||
|   unique key(phid), | ||||
|   name varchar(255) not null, | ||||
|   name varchar(255) COLLATE `binary` not null, | ||||
|   unique key(name), | ||||
|   description text not null, | ||||
|   primaryOwnerPHID varchar(64) binary | ||||
|   | ||||
| @@ -2,7 +2,7 @@ CREATE TABLE {$NAMESPACE}_repository.repository_arcanistproject ( | ||||
|   id int unsigned not null auto_increment primary key, | ||||
|   phid varchar(64) binary not null, | ||||
|   unique key(phid), | ||||
|   name varchar(255) not null, | ||||
|   name varchar(255) COLLATE `binary` not null, | ||||
|   unique key (name), | ||||
|   repositoryID int unsigned | ||||
| ); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| CREATE TABLE {$NAMESPACE}_file.file_proxyimage ( | ||||
|   id int unsigned not null primary key auto_increment, | ||||
|   uri varchar(255) binary not null, | ||||
|   uri varchar(255) COLLATE `binary` not null, | ||||
|   unique key(uri), | ||||
|   filePHID varchar(64) binary not null | ||||
| ) ENGINE=InnoDB; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| CREATE TABLE {$NAMESPACE}_file.file_transformedfile ( | ||||
|   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||
|   originalPHID varchar(64) BINARY NOT NULL, | ||||
|   transform varchar(255) BINARY NOT NULL, | ||||
|   originalPHID varchar(64) COLLATE `binary` NOT NULL, | ||||
|   transform varchar(255) COLLATE `binary` NOT NULL, | ||||
|   unique key (originalPHID, transform), | ||||
|   transformedPHID varchar(64) BINARY NOT NULL, | ||||
|   key (transformedPHID), | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| create table {$NAMESPACE}_maniphest.maniphest_taskauxiliarystorage | ||||
|     (id int unsigned not null auto_increment primary key, | ||||
|     taskPHID varchar(64) binary not null, | ||||
|     name varchar(255) not null, | ||||
|     name varchar(255) COLLATE `binary` not null, | ||||
|     value varchar(255) not null, | ||||
|     unique key (taskPHID,name), | ||||
|     dateCreated int unsigned not null, | ||||
|   | ||||
| @@ -64,6 +64,13 @@ try { | ||||
|         'help'  => 'Do not actually change anything, just show what would be '. | ||||
|                    'changed.', | ||||
|       ), | ||||
|       array( | ||||
|         'name' => 'disable-utf8mb4', | ||||
|         'help' => pht( | ||||
|           'Disable utf8mb4, even if the database supports it. This is an '. | ||||
|           'advanced feature used for testing changes to Phabricator; you '. | ||||
|           'should not normally use this flag.'), | ||||
|       ) | ||||
|     )); | ||||
| } catch (PhutilArgumentUsageException $ex) { | ||||
|   $args->printUsageException($ex); | ||||
| @@ -126,6 +133,7 @@ $api->setHost($default_host); | ||||
| $api->setPort($default_port); | ||||
| $api->setPassword($password); | ||||
| $api->setNamespace($args->getArg('namespace')); | ||||
| $api->setDisableUTF8MB4($args->getArg('disable-utf8mb4')); | ||||
|  | ||||
| try { | ||||
|   queryfx( | ||||
|   | ||||
| @@ -9,14 +9,67 @@ | ||||
| phutil_register_library_map(array( | ||||
|   '__library_version__' => 2, | ||||
|   'class' => array( | ||||
|     'AlmanacAddress' => 'applications/almanac/util/AlmanacAddress.php', | ||||
|     'AlmanacBinding' => 'applications/almanac/storage/AlmanacBinding.php', | ||||
|     'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php', | ||||
|     'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php', | ||||
|     'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php', | ||||
|     'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php', | ||||
|     'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php', | ||||
|     'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php', | ||||
|     'AlmanacBindingTransactionQuery' => 'applications/almanac/query/AlmanacBindingTransactionQuery.php', | ||||
|     'AlmanacBindingViewController' => 'applications/almanac/controller/AlmanacBindingViewController.php', | ||||
|     'AlmanacConduitUtil' => 'applications/almanac/util/AlmanacConduitUtil.php', | ||||
|     'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php', | ||||
|     'AlmanacController' => 'applications/almanac/controller/AlmanacController.php', | ||||
|     'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php', | ||||
|     'AlmanacCreateNetworksCapability' => 'applications/almanac/capability/AlmanacCreateNetworksCapability.php', | ||||
|     'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php', | ||||
|     'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php', | ||||
|     'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php', | ||||
|     'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php', | ||||
|     'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php', | ||||
|     'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php', | ||||
|     'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php', | ||||
|     'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php', | ||||
|     'AlmanacDeviceProperty' => 'applications/almanac/storage/AlmanacDeviceProperty.php', | ||||
|     'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php', | ||||
|     'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php', | ||||
|     'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php', | ||||
|     'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php', | ||||
|     'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php', | ||||
|     'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php', | ||||
|     'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php', | ||||
|     'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php', | ||||
|     'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php', | ||||
|     'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php', | ||||
|     'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php', | ||||
|     'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php', | ||||
|     'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php', | ||||
|     'AlmanacNames' => 'applications/almanac/util/AlmanacNames.php', | ||||
|     'AlmanacNamesTestCase' => 'applications/almanac/util/__tests__/AlmanacNamesTestCase.php', | ||||
|     'AlmanacNetwork' => 'applications/almanac/storage/AlmanacNetwork.php', | ||||
|     'AlmanacNetworkController' => 'applications/almanac/controller/AlmanacNetworkController.php', | ||||
|     'AlmanacNetworkEditController' => 'applications/almanac/controller/AlmanacNetworkEditController.php', | ||||
|     'AlmanacNetworkEditor' => 'applications/almanac/editor/AlmanacNetworkEditor.php', | ||||
|     'AlmanacNetworkListController' => 'applications/almanac/controller/AlmanacNetworkListController.php', | ||||
|     'AlmanacNetworkPHIDType' => 'applications/almanac/phid/AlmanacNetworkPHIDType.php', | ||||
|     'AlmanacNetworkQuery' => 'applications/almanac/query/AlmanacNetworkQuery.php', | ||||
|     'AlmanacNetworkSearchEngine' => 'applications/almanac/query/AlmanacNetworkSearchEngine.php', | ||||
|     'AlmanacNetworkTransaction' => 'applications/almanac/storage/AlmanacNetworkTransaction.php', | ||||
|     'AlmanacNetworkTransactionQuery' => 'applications/almanac/query/AlmanacNetworkTransactionQuery.php', | ||||
|     'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php', | ||||
|     'AlmanacService' => 'applications/almanac/storage/AlmanacService.php', | ||||
|     'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php', | ||||
|     'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php', | ||||
|     'AlmanacServiceEditor' => 'applications/almanac/editor/AlmanacServiceEditor.php', | ||||
|     'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php', | ||||
|     'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php', | ||||
|     'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php', | ||||
|     'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php', | ||||
|     'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php', | ||||
|     'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php', | ||||
|     'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php', | ||||
|     'Aphront304Response' => 'aphront/response/Aphront304Response.php', | ||||
|     'Aphront400Response' => 'aphront/response/Aphront400Response.php', | ||||
|     'Aphront403Response' => 'aphront/response/Aphront403Response.php', | ||||
| @@ -109,22 +162,22 @@ phutil_register_library_map(array( | ||||
|     'CalendarConstants' => 'applications/calendar/constants/CalendarConstants.php', | ||||
|     'CalendarTimeUtil' => 'applications/calendar/util/CalendarTimeUtil.php', | ||||
|     'CalendarTimeUtilTestCase' => 'applications/calendar/__tests__/CalendarTimeUtilTestCase.php', | ||||
|     'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php', | ||||
|     'CelerityManagementMapWorkflow' => 'infrastructure/celerity/management/CelerityManagementMapWorkflow.php', | ||||
|     'CelerityManagementWorkflow' => 'infrastructure/celerity/management/CelerityManagementWorkflow.php', | ||||
|     'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php', | ||||
|     'CelerityPhabricatorResources' => 'infrastructure/celerity/resources/CelerityPhabricatorResources.php', | ||||
|     'CelerityPhysicalResources' => 'infrastructure/celerity/resources/CelerityPhysicalResources.php', | ||||
|     'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php', | ||||
|     'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php', | ||||
|     'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php', | ||||
|     'CelerityResourceMapGenerator' => 'infrastructure/celerity/CelerityResourceMapGenerator.php', | ||||
|     'CelerityResourceTransformer' => 'infrastructure/celerity/CelerityResourceTransformer.php', | ||||
|     'CelerityResourceTransformerTestCase' => 'infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php', | ||||
|     'CelerityResources' => 'infrastructure/celerity/resources/CelerityResources.php', | ||||
|     'CelerityResourcesOnDisk' => 'infrastructure/celerity/resources/CelerityResourcesOnDisk.php', | ||||
|     'CeleritySpriteGenerator' => 'infrastructure/celerity/CeleritySpriteGenerator.php', | ||||
|     'CelerityStaticResourceResponse' => 'infrastructure/celerity/CelerityStaticResourceResponse.php', | ||||
|     'CelerityAPI' => 'applications/celerity/CelerityAPI.php', | ||||
|     'CelerityManagementMapWorkflow' => 'applications/celerity/management/CelerityManagementMapWorkflow.php', | ||||
|     'CelerityManagementWorkflow' => 'applications/celerity/management/CelerityManagementWorkflow.php', | ||||
|     'CelerityPhabricatorResourceController' => 'applications/celerity/controller/CelerityPhabricatorResourceController.php', | ||||
|     'CelerityPhabricatorResources' => 'applications/celerity/resources/CelerityPhabricatorResources.php', | ||||
|     'CelerityPhysicalResources' => 'applications/celerity/resources/CelerityPhysicalResources.php', | ||||
|     'CelerityResourceController' => 'applications/celerity/controller/CelerityResourceController.php', | ||||
|     'CelerityResourceGraph' => 'applications/celerity/CelerityResourceGraph.php', | ||||
|     'CelerityResourceMap' => 'applications/celerity/CelerityResourceMap.php', | ||||
|     'CelerityResourceMapGenerator' => 'applications/celerity/CelerityResourceMapGenerator.php', | ||||
|     'CelerityResourceTransformer' => 'applications/celerity/CelerityResourceTransformer.php', | ||||
|     'CelerityResourceTransformerTestCase' => 'applications/celerity/__tests__/CelerityResourceTransformerTestCase.php', | ||||
|     'CelerityResources' => 'applications/celerity/resources/CelerityResources.php', | ||||
|     'CelerityResourcesOnDisk' => 'applications/celerity/resources/CelerityResourcesOnDisk.php', | ||||
|     'CeleritySpriteGenerator' => 'applications/celerity/CeleritySpriteGenerator.php', | ||||
|     'CelerityStaticResourceResponse' => 'applications/celerity/CelerityStaticResourceResponse.php', | ||||
|     'ChatLogConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogConduitAPIMethod.php', | ||||
|     'ChatLogQueryConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogQueryConduitAPIMethod.php', | ||||
|     'ChatLogRecordConduitAPIMethod' => 'applications/chatlog/conduit/ChatLogRecordConduitAPIMethod.php', | ||||
| @@ -185,18 +238,18 @@ phutil_register_library_map(array( | ||||
|     'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php', | ||||
|     'ConpherenceWidgetController' => 'applications/conpherence/controller/ConpherenceWidgetController.php', | ||||
|     'ConpherenceWidgetView' => 'applications/conpherence/view/ConpherenceWidgetView.php', | ||||
|     'DarkConsoleController' => 'aphront/console/DarkConsoleController.php', | ||||
|     'DarkConsoleCore' => 'aphront/console/DarkConsoleCore.php', | ||||
|     'DarkConsoleDataController' => 'aphront/console/DarkConsoleDataController.php', | ||||
|     'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/DarkConsoleErrorLogPlugin.php', | ||||
|     'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/DarkConsoleErrorLogPluginAPI.php', | ||||
|     'DarkConsoleEventPlugin' => 'aphront/console/plugin/DarkConsoleEventPlugin.php', | ||||
|     'DarkConsoleEventPluginAPI' => 'aphront/console/plugin/event/DarkConsoleEventPluginAPI.php', | ||||
|     'DarkConsolePlugin' => 'aphront/console/plugin/DarkConsolePlugin.php', | ||||
|     'DarkConsoleRequestPlugin' => 'aphront/console/plugin/DarkConsoleRequestPlugin.php', | ||||
|     'DarkConsoleServicesPlugin' => 'aphront/console/plugin/DarkConsoleServicesPlugin.php', | ||||
|     'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/DarkConsoleXHProfPlugin.php', | ||||
|     'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/DarkConsoleXHProfPluginAPI.php', | ||||
|     'DarkConsoleController' => 'applications/console/controller/DarkConsoleController.php', | ||||
|     'DarkConsoleCore' => 'applications/console/core/DarkConsoleCore.php', | ||||
|     'DarkConsoleDataController' => 'applications/console/controller/DarkConsoleDataController.php', | ||||
|     'DarkConsoleErrorLogPlugin' => 'applications/console/plugin/DarkConsoleErrorLogPlugin.php', | ||||
|     'DarkConsoleErrorLogPluginAPI' => 'applications/console/plugin/errorlog/DarkConsoleErrorLogPluginAPI.php', | ||||
|     'DarkConsoleEventPlugin' => 'applications/console/plugin/DarkConsoleEventPlugin.php', | ||||
|     'DarkConsoleEventPluginAPI' => 'applications/console/plugin/event/DarkConsoleEventPluginAPI.php', | ||||
|     'DarkConsolePlugin' => 'applications/console/plugin/DarkConsolePlugin.php', | ||||
|     'DarkConsoleRequestPlugin' => 'applications/console/plugin/DarkConsoleRequestPlugin.php', | ||||
|     'DarkConsoleServicesPlugin' => 'applications/console/plugin/DarkConsoleServicesPlugin.php', | ||||
|     'DarkConsoleXHProfPlugin' => 'applications/console/plugin/DarkConsoleXHProfPlugin.php', | ||||
|     'DarkConsoleXHProfPluginAPI' => 'applications/console/plugin/xhprof/DarkConsoleXHProfPluginAPI.php', | ||||
|     'DatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DatabaseConfigurationProvider.php', | ||||
|     'DefaultDatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php', | ||||
|     'DifferentialAction' => 'applications/differential/constants/DifferentialAction.php', | ||||
| @@ -330,6 +383,7 @@ phutil_register_library_map(array( | ||||
|     'DifferentialReviewersField' => 'applications/differential/customfield/DifferentialReviewersField.php', | ||||
|     'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php', | ||||
|     'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php', | ||||
|     'DifferentialRevisionCloseDetailsController' => 'applications/differential/controller/DifferentialRevisionCloseDetailsController.php', | ||||
|     'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php', | ||||
|     'DifferentialRevisionDetailView' => 'applications/differential/view/DifferentialRevisionDetailView.php', | ||||
|     'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', | ||||
| @@ -684,6 +738,7 @@ phutil_register_library_map(array( | ||||
|     'FundInitiativeCloseController' => 'applications/fund/controller/FundInitiativeCloseController.php', | ||||
|     'FundInitiativeEditController' => 'applications/fund/controller/FundInitiativeEditController.php', | ||||
|     'FundInitiativeEditor' => 'applications/fund/editor/FundInitiativeEditor.php', | ||||
|     'FundInitiativeIndexer' => 'applications/fund/search/FundInitiativeIndexer.php', | ||||
|     'FundInitiativeListController' => 'applications/fund/controller/FundInitiativeListController.php', | ||||
|     'FundInitiativePHIDType' => 'applications/fund/phid/FundInitiativePHIDType.php', | ||||
|     'FundInitiativeQuery' => 'applications/fund/query/FundInitiativeQuery.php', | ||||
| @@ -1320,6 +1375,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php', | ||||
|     'PhabricatorCalendarViewController' => 'applications/calendar/controller/PhabricatorCalendarViewController.php', | ||||
|     'PhabricatorCampfireProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php', | ||||
|     'PhabricatorCelerityApplication' => 'applications/celerity/application/PhabricatorCelerityApplication.php', | ||||
|     'PhabricatorCelerityTestCase' => '__tests__/PhabricatorCelerityTestCase.php', | ||||
|     'PhabricatorChangeParserTestCase' => 'applications/repository/worker/__tests__/PhabricatorChangeParserTestCase.php', | ||||
|     'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', | ||||
| @@ -1405,6 +1461,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorConfigWelcomeController' => 'applications/config/controller/PhabricatorConfigWelcomeController.php', | ||||
|     'PhabricatorConpherenceApplication' => 'applications/conpherence/application/PhabricatorConpherenceApplication.php', | ||||
|     'PhabricatorConpherenceThreadPHIDType' => 'applications/conpherence/phid/PhabricatorConpherenceThreadPHIDType.php', | ||||
|     'PhabricatorConsoleApplication' => 'applications/console/application/PhabricatorConsoleApplication.php', | ||||
|     'PhabricatorContentSource' => 'applications/metamta/contentsource/PhabricatorContentSource.php', | ||||
|     'PhabricatorContentSourceView' => 'applications/metamta/contentsource/PhabricatorContentSourceView.php', | ||||
|     'PhabricatorController' => 'applications/base/controller/PhabricatorController.php', | ||||
| @@ -2567,16 +2624,23 @@ phutil_register_library_map(array( | ||||
|     'PhortuneCartCancelController' => 'applications/phortune/controller/PhortuneCartCancelController.php', | ||||
|     'PhortuneCartCheckoutController' => 'applications/phortune/controller/PhortuneCartCheckoutController.php', | ||||
|     'PhortuneCartController' => 'applications/phortune/controller/PhortuneCartController.php', | ||||
|     'PhortuneCartEditor' => 'applications/phortune/editor/PhortuneCartEditor.php', | ||||
|     'PhortuneCartImplementation' => 'applications/phortune/cart/PhortuneCartImplementation.php', | ||||
|     'PhortuneCartListController' => 'applications/phortune/controller/PhortuneCartListController.php', | ||||
|     'PhortuneCartPHIDType' => 'applications/phortune/phid/PhortuneCartPHIDType.php', | ||||
|     'PhortuneCartQuery' => 'applications/phortune/query/PhortuneCartQuery.php', | ||||
|     'PhortuneCartReplyHandler' => 'applications/phortune/mail/PhortuneCartReplyHandler.php', | ||||
|     'PhortuneCartSearchEngine' => 'applications/phortune/query/PhortuneCartSearchEngine.php', | ||||
|     'PhortuneCartTransaction' => 'applications/phortune/storage/PhortuneCartTransaction.php', | ||||
|     'PhortuneCartTransactionQuery' => 'applications/phortune/query/PhortuneCartTransactionQuery.php', | ||||
|     'PhortuneCartUpdateController' => 'applications/phortune/controller/PhortuneCartUpdateController.php', | ||||
|     'PhortuneCartViewController' => 'applications/phortune/controller/PhortuneCartViewController.php', | ||||
|     'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php', | ||||
|     'PhortuneChargeListController' => 'applications/phortune/controller/PhortuneChargeListController.php', | ||||
|     'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php', | ||||
|     'PhortuneChargeQuery' => 'applications/phortune/query/PhortuneChargeQuery.php', | ||||
|     'PhortuneChargeSearchEngine' => 'applications/phortune/query/PhortuneChargeSearchEngine.php', | ||||
|     'PhortuneChargeTableView' => 'applications/phortune/view/PhortuneChargeTableView.php', | ||||
|     'PhortuneConstants' => 'applications/phortune/constants/PhortuneConstants.php', | ||||
|     'PhortuneController' => 'applications/phortune/controller/PhortuneController.php', | ||||
|     'PhortuneCreditCardForm' => 'applications/phortune/view/PhortuneCreditCardForm.php', | ||||
| @@ -2587,11 +2651,13 @@ phutil_register_library_map(array( | ||||
|     'PhortuneErrCode' => 'applications/phortune/constants/PhortuneErrCode.php', | ||||
|     'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php', | ||||
|     'PhortuneMemberHasAccountEdgeType' => 'applications/phortune/edge/PhortuneMemberHasAccountEdgeType.php', | ||||
|     'PhortuneMemberHasMerchantEdgeType' => 'applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php', | ||||
|     'PhortuneMerchant' => 'applications/phortune/storage/PhortuneMerchant.php', | ||||
|     'PhortuneMerchantCapability' => 'applications/phortune/capability/PhortuneMerchantCapability.php', | ||||
|     'PhortuneMerchantController' => 'applications/phortune/controller/PhortuneMerchantController.php', | ||||
|     'PhortuneMerchantEditController' => 'applications/phortune/controller/PhortuneMerchantEditController.php', | ||||
|     'PhortuneMerchantEditor' => 'applications/phortune/editor/PhortuneMerchantEditor.php', | ||||
|     'PhortuneMerchantHasMemberEdgeType' => 'applications/phortune/edge/PhortuneMerchantHasMemberEdgeType.php', | ||||
|     'PhortuneMerchantListController' => 'applications/phortune/controller/PhortuneMerchantListController.php', | ||||
|     'PhortuneMerchantPHIDType' => 'applications/phortune/phid/PhortuneMerchantPHIDType.php', | ||||
|     'PhortuneMerchantQuery' => 'applications/phortune/query/PhortuneMerchantQuery.php', | ||||
| @@ -2603,6 +2669,7 @@ phutil_register_library_map(array( | ||||
|     'PhortuneMultiplePaymentProvidersException' => 'applications/phortune/exception/PhortuneMultiplePaymentProvidersException.php', | ||||
|     'PhortuneNoPaymentProviderException' => 'applications/phortune/exception/PhortuneNoPaymentProviderException.php', | ||||
|     'PhortuneNotImplementedException' => 'applications/phortune/exception/PhortuneNotImplementedException.php', | ||||
|     'PhortuneOrderTableView' => 'applications/phortune/view/PhortuneOrderTableView.php', | ||||
|     'PhortunePayPalPaymentProvider' => 'applications/phortune/provider/PhortunePayPalPaymentProvider.php', | ||||
|     'PhortunePaymentMethod' => 'applications/phortune/storage/PhortunePaymentMethod.php', | ||||
|     'PhortunePaymentMethodCreateController' => 'applications/phortune/controller/PhortunePaymentMethodCreateController.php', | ||||
| @@ -2629,7 +2696,6 @@ phutil_register_library_map(array( | ||||
|     'PhortunePurchase' => 'applications/phortune/storage/PhortunePurchase.php', | ||||
|     'PhortunePurchasePHIDType' => 'applications/phortune/phid/PhortunePurchasePHIDType.php', | ||||
|     'PhortunePurchaseQuery' => 'applications/phortune/query/PhortunePurchaseQuery.php', | ||||
|     'PhortunePurchaseViewController' => 'applications/phortune/controller/PhortunePurchaseViewController.php', | ||||
|     'PhortuneSchemaSpec' => 'applications/phortune/storage/PhortuneSchemaSpec.php', | ||||
|     'PhortuneStripePaymentProvider' => 'applications/phortune/provider/PhortuneStripePaymentProvider.php', | ||||
|     'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php', | ||||
| @@ -2710,9 +2776,14 @@ phutil_register_library_map(array( | ||||
|     'PhrictionMoveController' => 'applications/phriction/controller/PhrictionMoveController.php', | ||||
|     'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php', | ||||
|     'PhrictionRemarkupRule' => 'applications/phriction/markup/PhrictionRemarkupRule.php', | ||||
|     'PhrictionReplyHandler' => 'applications/phriction/mail/PhrictionReplyHandler.php', | ||||
|     'PhrictionSchemaSpec' => 'applications/phriction/storage/PhrictionSchemaSpec.php', | ||||
|     'PhrictionSearchEngine' => 'applications/phriction/query/PhrictionSearchEngine.php', | ||||
|     'PhrictionSearchIndexer' => 'applications/phriction/search/PhrictionSearchIndexer.php', | ||||
|     'PhrictionTransaction' => 'applications/phriction/storage/PhrictionTransaction.php', | ||||
|     'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php', | ||||
|     'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php', | ||||
|     'PhrictionTransactionQuery' => 'applications/phriction/query/PhrictionTransactionQuery.php', | ||||
|     'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', | ||||
|     'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', | ||||
|     'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php', | ||||
| @@ -2762,6 +2833,7 @@ phutil_register_library_map(array( | ||||
|     'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php', | ||||
|     'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php', | ||||
|     'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php', | ||||
|     'ProjectRemarkupRuleTestCase' => 'applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php', | ||||
|     'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php', | ||||
|     'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php', | ||||
|     'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php', | ||||
| @@ -2878,8 +2950,8 @@ phutil_register_library_map(array( | ||||
|   ), | ||||
|   'function' => array( | ||||
|     '_phabricator_time_format' => 'view/viewutils.php', | ||||
|     'celerity_generate_unique_node_id' => 'infrastructure/celerity/api.php', | ||||
|     'celerity_get_resource_uri' => 'infrastructure/celerity/api.php', | ||||
|     'celerity_generate_unique_node_id' => 'applications/celerity/api.php', | ||||
|     'celerity_get_resource_uri' => 'applications/celerity/api.php', | ||||
|     'implode_selected_handle_links' => 'applications/phid/handle/view/render.php', | ||||
|     'javelin_tag' => 'infrastructure/javelin/markup.php', | ||||
|     'phabricator_date' => 'view/viewutils.php', | ||||
| @@ -2892,20 +2964,85 @@ phutil_register_library_map(array( | ||||
|     'phid_get_subtype' => 'applications/phid/utils.php', | ||||
|     'phid_get_type' => 'applications/phid/utils.php', | ||||
|     'phid_group_by_type' => 'applications/phid/utils.php', | ||||
|     'require_celerity_resource' => 'infrastructure/celerity/api.php', | ||||
|     'require_celerity_resource' => 'applications/celerity/api.php', | ||||
|   ), | ||||
|   'xmap' => array( | ||||
|     'AlmanacAddress' => 'Phobject', | ||||
|     'AlmanacBinding' => array( | ||||
|       'AlmanacDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
|     ), | ||||
|     'AlmanacBindingEditController' => 'AlmanacServiceController', | ||||
|     'AlmanacBindingEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'AlmanacBindingPHIDType' => 'PhabricatorPHIDType', | ||||
|     'AlmanacBindingQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'AlmanacBindingTableView' => 'AphrontView', | ||||
|     'AlmanacBindingTransaction' => 'PhabricatorApplicationTransaction', | ||||
|     'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'AlmanacBindingViewController' => 'AlmanacServiceController', | ||||
|     'AlmanacConduitUtil' => 'Phobject', | ||||
|     'AlmanacConsoleController' => 'AlmanacController', | ||||
|     'AlmanacController' => 'PhabricatorController', | ||||
|     'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability', | ||||
|     'AlmanacCreateNetworksCapability' => 'PhabricatorPolicyCapability', | ||||
|     'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability', | ||||
|     'AlmanacDAO' => 'PhabricatorLiskDAO', | ||||
|     'AlmanacDevice' => array( | ||||
|       'AlmanacDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
|     ), | ||||
|     'AlmanacDeviceController' => 'AlmanacController', | ||||
|     'AlmanacDeviceEditController' => 'AlmanacDeviceController', | ||||
|     'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'AlmanacDeviceListController' => 'AlmanacDeviceController', | ||||
|     'AlmanacDevicePHIDType' => 'PhabricatorPHIDType', | ||||
|     'AlmanacDeviceProperty' => 'AlmanacDAO', | ||||
|     'AlmanacDeviceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'AlmanacDeviceTransaction' => 'PhabricatorApplicationTransaction', | ||||
|     'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'AlmanacDeviceViewController' => 'AlmanacDeviceController', | ||||
|     'AlmanacInterface' => array( | ||||
|       'AlmanacDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
|     ), | ||||
|     'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource', | ||||
|     'AlmanacInterfaceEditController' => 'AlmanacDeviceController', | ||||
|     'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType', | ||||
|     'AlmanacInterfaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'AlmanacInterfaceTableView' => 'AphrontView', | ||||
|     'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow', | ||||
|     'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow', | ||||
|     'AlmanacNames' => 'Phobject', | ||||
|     'AlmanacNamesTestCase' => 'PhabricatorTestCase', | ||||
|     'AlmanacNetwork' => array( | ||||
|       'AlmanacDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
|     ), | ||||
|     'AlmanacNetworkController' => 'AlmanacController', | ||||
|     'AlmanacNetworkEditController' => 'AlmanacNetworkController', | ||||
|     'AlmanacNetworkEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'AlmanacNetworkListController' => 'AlmanacNetworkController', | ||||
|     'AlmanacNetworkPHIDType' => 'PhabricatorPHIDType', | ||||
|     'AlmanacNetworkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'AlmanacNetworkSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'AlmanacNetworkTransaction' => 'PhabricatorApplicationTransaction', | ||||
|     'AlmanacNetworkTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'AlmanacNetworkViewController' => 'AlmanacNetworkController', | ||||
|     'AlmanacService' => array( | ||||
|       'AlmanacDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
|     ), | ||||
|     'AlmanacServiceController' => 'AlmanacController', | ||||
|     'AlmanacServiceEditController' => 'AlmanacServiceController', | ||||
|     'AlmanacServiceEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'AlmanacServiceListController' => 'AlmanacServiceController', | ||||
|     'AlmanacServicePHIDType' => 'PhabricatorPHIDType', | ||||
|     'AlmanacServiceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'AlmanacServiceTransaction' => 'PhabricatorApplicationTransaction', | ||||
|     'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'AlmanacServiceViewController' => 'AlmanacServiceController', | ||||
|     'Aphront304Response' => 'AphrontResponse', | ||||
|     'Aphront400Response' => 'AphrontResponse', | ||||
|     'Aphront403Response' => 'AphrontHTMLResponse', | ||||
| @@ -3216,6 +3353,7 @@ phutil_register_library_map(array( | ||||
|       'PhabricatorDestructibleInterface', | ||||
|       'PhabricatorProjectInterface', | ||||
|     ), | ||||
|     'DifferentialRevisionCloseDetailsController' => 'DifferentialController', | ||||
|     'DifferentialRevisionDetailView' => 'AphrontView', | ||||
|     'DifferentialRevisionEditController' => 'DifferentialController', | ||||
|     'DifferentialRevisionHasTaskEdgeType' => 'PhabricatorEdgeType', | ||||
| @@ -3582,6 +3720,7 @@ phutil_register_library_map(array( | ||||
|     'FundInitiativeCloseController' => 'FundController', | ||||
|     'FundInitiativeEditController' => 'FundController', | ||||
|     'FundInitiativeEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'FundInitiativeIndexer' => 'PhabricatorSearchDocumentIndexer', | ||||
|     'FundInitiativeListController' => 'FundController', | ||||
|     'FundInitiativePHIDType' => 'PhabricatorPHIDType', | ||||
|     'FundInitiativeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
| @@ -4284,6 +4423,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase', | ||||
|     'PhabricatorCalendarViewController' => 'PhabricatorCalendarController', | ||||
|     'PhabricatorCampfireProtocolAdapter' => 'PhabricatorBotBaseStreamingProtocolAdapter', | ||||
|     'PhabricatorCelerityApplication' => 'PhabricatorApplication', | ||||
|     'PhabricatorCelerityTestCase' => 'PhabricatorTestCase', | ||||
|     'PhabricatorChangeParserTestCase' => 'PhabricatorWorkingCopyTestCase', | ||||
|     'PhabricatorChangesetResponse' => 'AphrontProxyResponse', | ||||
| @@ -4380,6 +4520,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorConfigWelcomeController' => 'PhabricatorConfigController', | ||||
|     'PhabricatorConpherenceApplication' => 'PhabricatorApplication', | ||||
|     'PhabricatorConpherenceThreadPHIDType' => 'PhabricatorPHIDType', | ||||
|     'PhabricatorConsoleApplication' => 'PhabricatorApplication', | ||||
|     'PhabricatorContentSourceView' => 'AphrontView', | ||||
|     'PhabricatorController' => 'AphrontController', | ||||
|     'PhabricatorCookies' => 'Phobject', | ||||
| @@ -5634,18 +5775,25 @@ phutil_register_library_map(array( | ||||
|     'PhortuneCartCancelController' => 'PhortuneCartController', | ||||
|     'PhortuneCartCheckoutController' => 'PhortuneCartController', | ||||
|     'PhortuneCartController' => 'PhortuneController', | ||||
|     'PhortuneCartEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'PhortuneCartListController' => 'PhortuneController', | ||||
|     'PhortuneCartPHIDType' => 'PhabricatorPHIDType', | ||||
|     'PhortuneCartQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'PhortuneCartReplyHandler' => 'PhabricatorMailReplyHandler', | ||||
|     'PhortuneCartSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'PhortuneCartTransaction' => 'PhabricatorApplicationTransaction', | ||||
|     'PhortuneCartTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'PhortuneCartUpdateController' => 'PhortuneCartController', | ||||
|     'PhortuneCartViewController' => 'PhortuneCartController', | ||||
|     'PhortuneCharge' => array( | ||||
|       'PhortuneDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
|     ), | ||||
|     'PhortuneChargeListController' => 'PhortuneController', | ||||
|     'PhortuneChargePHIDType' => 'PhabricatorPHIDType', | ||||
|     'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'PhortuneChargeSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'PhortuneChargeTableView' => 'AphrontView', | ||||
|     'PhortuneController' => 'PhabricatorController', | ||||
|     'PhortuneCurrency' => 'Phobject', | ||||
|     'PhortuneCurrencySerializer' => 'PhabricatorLiskSerializer', | ||||
| @@ -5654,6 +5802,7 @@ phutil_register_library_map(array( | ||||
|     'PhortuneErrCode' => 'PhortuneConstants', | ||||
|     'PhortuneLandingController' => 'PhortuneController', | ||||
|     'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType', | ||||
|     'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType', | ||||
|     'PhortuneMerchant' => array( | ||||
|       'PhortuneDAO', | ||||
|       'PhabricatorPolicyInterface', | ||||
| @@ -5662,6 +5811,7 @@ phutil_register_library_map(array( | ||||
|     'PhortuneMerchantController' => 'PhortuneController', | ||||
|     'PhortuneMerchantEditController' => 'PhortuneMerchantController', | ||||
|     'PhortuneMerchantEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'PhortuneMerchantHasMemberEdgeType' => 'PhabricatorEdgeType', | ||||
|     'PhortuneMerchantListController' => 'PhortuneMerchantController', | ||||
|     'PhortuneMerchantPHIDType' => 'PhabricatorPHIDType', | ||||
|     'PhortuneMerchantQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
| @@ -5673,6 +5823,7 @@ phutil_register_library_map(array( | ||||
|     'PhortuneMultiplePaymentProvidersException' => 'Exception', | ||||
|     'PhortuneNoPaymentProviderException' => 'Exception', | ||||
|     'PhortuneNotImplementedException' => 'Exception', | ||||
|     'PhortuneOrderTableView' => 'AphrontView', | ||||
|     'PhortunePayPalPaymentProvider' => 'PhortunePaymentProvider', | ||||
|     'PhortunePaymentMethod' => array( | ||||
|       'PhortuneDAO', | ||||
| @@ -5709,7 +5860,6 @@ phutil_register_library_map(array( | ||||
|     ), | ||||
|     'PhortunePurchasePHIDType' => 'PhabricatorPHIDType', | ||||
|     'PhortunePurchaseQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'PhortunePurchaseViewController' => 'PhortuneController', | ||||
|     'PhortuneSchemaSpec' => 'PhabricatorConfigSchemaSpec', | ||||
|     'PhortuneStripePaymentProvider' => 'PhortunePaymentProvider', | ||||
|     'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider', | ||||
| @@ -5813,9 +5963,14 @@ phutil_register_library_map(array( | ||||
|     'PhrictionMoveController' => 'PhrictionController', | ||||
|     'PhrictionNewController' => 'PhrictionController', | ||||
|     'PhrictionRemarkupRule' => 'PhutilRemarkupRule', | ||||
|     'PhrictionReplyHandler' => 'PhabricatorMailReplyHandler', | ||||
|     'PhrictionSchemaSpec' => 'PhabricatorConfigSchemaSpec', | ||||
|     'PhrictionSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||
|     'PhrictionSearchIndexer' => 'PhabricatorSearchDocumentIndexer', | ||||
|     'PhrictionTransaction' => 'PhabricatorApplicationTransaction', | ||||
|     'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment', | ||||
|     'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'PonderAddAnswerView' => 'AphrontView', | ||||
|     'PonderAnswer' => array( | ||||
|       'PonderDAO', | ||||
| @@ -5881,6 +6036,7 @@ phutil_register_library_map(array( | ||||
|     'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability', | ||||
|     'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod', | ||||
|     'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule', | ||||
|     'ProjectRemarkupRuleTestCase' => 'PhabricatorTestCase', | ||||
|     'QueryFormattingTestCase' => 'PhabricatorTestCase', | ||||
|     'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification', | ||||
|     'ReleephBranch' => array( | ||||
|   | ||||
| @@ -28,25 +28,45 @@ abstract class AphrontController extends Phobject { | ||||
|     return $response; | ||||
|   } | ||||
|  | ||||
|   abstract public function processRequest(); | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     if (method_exists($this, 'processRequest')) { | ||||
|       return $this->processRequest(); | ||||
|     } | ||||
|  | ||||
|   final public function __construct(AphrontRequest $request) { | ||||
|     throw new PhutilMethodNotImplementedException( | ||||
|       pht( | ||||
|         'Controllers must implement either handleRequest() (recommended) '. | ||||
|         'or processRequest() (deprecated).')); | ||||
|   } | ||||
|  | ||||
|   final public function setRequest(AphrontRequest $request) { | ||||
|     $this->request = $request; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   final public function getRequest() { | ||||
|     if (!$this->request) { | ||||
|       throw new Exception(pht('Call setRequest() before getRequest()!')); | ||||
|     } | ||||
|     return $this->request; | ||||
|   } | ||||
|  | ||||
|   final public function getViewer() { | ||||
|     return $this->getRequest()->getViewer(); | ||||
|   } | ||||
|  | ||||
|   final public function delegateToController(AphrontController $controller) { | ||||
|     $request = $this->getRequest(); | ||||
|  | ||||
|     $controller->setDelegatingController($this); | ||||
|     $controller->setRequest($request); | ||||
|  | ||||
|     $application = $this->getCurrentApplication(); | ||||
|     if ($application) { | ||||
|       $controller->setCurrentApplication($application); | ||||
|     } | ||||
|  | ||||
|     return $controller->processRequest(); | ||||
|     return $controller->handleRequest($request); | ||||
|   } | ||||
|  | ||||
|   final public function setCurrentApplication( | ||||
|   | ||||
| @@ -25,12 +25,26 @@ final class AphrontRequest { | ||||
|   private $requestData; | ||||
|   private $user; | ||||
|   private $applicationConfiguration; | ||||
|   private $uriData; | ||||
|  | ||||
|   final public function __construct($host, $path) { | ||||
|     $this->host = $host; | ||||
|     $this->path = $path; | ||||
|   } | ||||
|  | ||||
|   final public function setURIMap(array $uri_data) { | ||||
|     $this->uriData = $uri_data; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   final public function getURIMap() { | ||||
|     return $this->uriData; | ||||
|   } | ||||
|  | ||||
|   final public function getURIData($key, $default = null) { | ||||
|     return idx($this->uriData, $key, $default); | ||||
|   } | ||||
|  | ||||
|   final public function setApplicationConfiguration( | ||||
|     $application_configuration) { | ||||
|     $this->applicationConfiguration = $application_configuration; | ||||
| @@ -476,6 +490,10 @@ final class AphrontRequest { | ||||
|     return $this->user; | ||||
|   } | ||||
|  | ||||
|   final public function getViewer() { | ||||
|     return $this->user; | ||||
|   } | ||||
|  | ||||
|   final public function getRequestURI() { | ||||
|     $get = $_GET; | ||||
|     unset($get['__path__']); | ||||
|   | ||||
| @@ -11,7 +11,6 @@ abstract class AphrontApplicationConfiguration { | ||||
|   private $console; | ||||
|  | ||||
|   abstract public function getApplicationName(); | ||||
|   abstract public function getURIMap(); | ||||
|   abstract public function buildRequest(); | ||||
|   abstract public function build404Controller(); | ||||
|   abstract public function buildRedirectController($uri, $external); | ||||
| @@ -64,8 +63,8 @@ abstract class AphrontApplicationConfiguration { | ||||
|    * first test if the HTTP_HOST is configured as a valid Phabricator URI. If | ||||
|    * it isn't, we do a special check to see if it's a custom domain for a blog | ||||
|    * in the Phame application and if that fails we error. Otherwise, we test | ||||
|    * the URI against all builtin routes from @{method:getURIMap}, then against | ||||
|    * all application routes from installed @{class:PhabricatorApplication}s. | ||||
|    * against all application routes from installed | ||||
|    * @{class:PhabricatorApplication}s. | ||||
|    * | ||||
|    * If we match a route, we construct the controller it points at, build it, | ||||
|    * and return it. | ||||
| @@ -212,7 +211,6 @@ abstract class AphrontApplicationConfiguration { | ||||
|    */ | ||||
|   final public function buildControllerForPath($path) { | ||||
|     $maps = array(); | ||||
|     $maps[] = array(null, $this->getURIMap()); | ||||
|  | ||||
|     $applications = PhabricatorApplication::getAllInstalledApplications(); | ||||
|     foreach ($applications as $application) { | ||||
| @@ -241,7 +239,7 @@ abstract class AphrontApplicationConfiguration { | ||||
|  | ||||
|     $request = $this->getRequest(); | ||||
|  | ||||
|     $controller = newv($controller_class, array($request)); | ||||
|     $controller = newv($controller_class, array()); | ||||
|     if ($current_application) { | ||||
|       $controller->setCurrentApplication($current_application); | ||||
|     } | ||||
|   | ||||
| @@ -14,31 +14,6 @@ class AphrontDefaultApplicationConfiguration | ||||
|     return 'aphront-default'; | ||||
|   } | ||||
|  | ||||
|   public function getURIMap() { | ||||
|     return $this->getResourceURIMapRules() + array( | ||||
|       '/~/' => array( | ||||
|         '' => 'DarkConsoleController', | ||||
|         'data/(?P<key>[^/]+)/' => 'DarkConsoleDataController', | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   protected function getResourceURIMapRules() { | ||||
|     $extensions = CelerityResourceController::getSupportedResourceTypes(); | ||||
|     $extensions = array_keys($extensions); | ||||
|     $extensions = implode('|', $extensions); | ||||
|  | ||||
|     return array( | ||||
|       '/res/' => array( | ||||
|         '(?:(?P<mtime>[0-9]+)T/)?'. | ||||
|         '(?P<library>[^/]+)/'. | ||||
|         '(?P<hash>[a-f0-9]{8})/'. | ||||
|         '(?P<path>.+\.(?:'.$extensions.'))' | ||||
|           => 'CelerityPhabricatorResourceController', | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * @phutil-external-symbol class PhabricatorStartup | ||||
|    */ | ||||
| @@ -177,13 +152,14 @@ class AphrontDefaultApplicationConfiguration | ||||
|         // | ||||
|         // Possibly we should add a header here like "you need to login to see | ||||
|         // the thing you are trying to look at". | ||||
|         $login_controller = new PhabricatorAuthStartController($request); | ||||
|         $login_controller = new PhabricatorAuthStartController(); | ||||
|         $login_controller->setRequest($request); | ||||
|  | ||||
|         $auth_app_class = 'PhabricatorAuthApplication'; | ||||
|         $auth_app = PhabricatorApplication::getByClass($auth_app_class); | ||||
|         $login_controller->setCurrentApplication($auth_app); | ||||
|  | ||||
|         return $login_controller->processRequest(); | ||||
|         return $login_controller->handleRequest($request); | ||||
|       } | ||||
|  | ||||
|       $list = $ex->getMoreInfo(); | ||||
| @@ -297,12 +273,12 @@ class AphrontDefaultApplicationConfiguration | ||||
|   } | ||||
|  | ||||
|   public function build404Controller() { | ||||
|     return array(new Phabricator404Controller($this->getRequest()), array()); | ||||
|     return array(new Phabricator404Controller(), array()); | ||||
|   } | ||||
|  | ||||
|   public function buildRedirectController($uri, $external) { | ||||
|     return array( | ||||
|       new PhabricatorRedirectController($this->getRequest()), | ||||
|       new PhabricatorRedirectController(), | ||||
|       array( | ||||
|         'uri' => $uri, | ||||
|         'external' => $external, | ||||
|   | ||||
| @@ -30,12 +30,48 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function isLaunchable() { | ||||
|     return false; | ||||
|   public function getRoutes() { | ||||
|     return array( | ||||
|       '/almanac/' => array( | ||||
|         '' => 'AlmanacConsoleController', | ||||
|         'service/' => array( | ||||
|           '(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacServiceListController', | ||||
|           'edit/(?:(?P<id>\d+)/)?' => 'AlmanacServiceEditController', | ||||
|           'view/(?P<name>[^/]+)/' => 'AlmanacServiceViewController', | ||||
|         ), | ||||
|         'device/' => array( | ||||
|           '(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacDeviceListController', | ||||
|           'edit/(?:(?P<id>\d+)/)?' => 'AlmanacDeviceEditController', | ||||
|           'view/(?P<name>[^/]+)/' => 'AlmanacDeviceViewController', | ||||
|         ), | ||||
|         'interface/' => array( | ||||
|           'edit/(?:(?P<id>\d+)/)?' => 'AlmanacInterfaceEditController', | ||||
|         ), | ||||
|         'binding/' => array( | ||||
|           'edit/(?:(?P<id>\d+)/)?' => 'AlmanacBindingEditController', | ||||
|           '(?P<id>\d+)/' => 'AlmanacBindingViewController', | ||||
|         ), | ||||
|         'network/' => array( | ||||
|           '(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacNetworkListController', | ||||
|           'edit/(?:(?P<id>\d+)/)?' => 'AlmanacNetworkEditController', | ||||
|           '(?P<id>\d+)/' => 'AlmanacNetworkViewController', | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getRoutes() { | ||||
|     return array(); | ||||
|   protected function getCustomCapabilities() { | ||||
|     return array( | ||||
|       AlmanacCreateServicesCapability::CAPABILITY => array( | ||||
|         'default' => PhabricatorPolicies::POLICY_ADMIN, | ||||
|       ), | ||||
|       AlmanacCreateDevicesCapability::CAPABILITY => array( | ||||
|         'default' => PhabricatorPolicies::POLICY_ADMIN, | ||||
|       ), | ||||
|       AlmanacCreateNetworksCapability::CAPABILITY => array( | ||||
|         'default' => PhabricatorPolicies::POLICY_ADMIN, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacCreateDevicesCapability | ||||
|   extends PhabricatorPolicyCapability { | ||||
|  | ||||
|   const CAPABILITY = 'almanac.devices'; | ||||
|  | ||||
|   public function getCapabilityName() { | ||||
|     return pht('Can Create Devices'); | ||||
|   } | ||||
|  | ||||
|   public function describeCapabilityRejection() { | ||||
|     return pht('You do not have permission to create Almanac devices.'); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacCreateNetworksCapability | ||||
|   extends PhabricatorPolicyCapability { | ||||
|  | ||||
|   const CAPABILITY = 'almanac.networks'; | ||||
|  | ||||
|   public function getCapabilityName() { | ||||
|     return pht('Can Create Networks'); | ||||
|   } | ||||
|  | ||||
|   public function describeCapabilityRejection() { | ||||
|     return pht('You do not have permission to create Almanac networks.'); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacCreateServicesCapability | ||||
|   extends PhabricatorPolicyCapability { | ||||
|  | ||||
|   const CAPABILITY = 'almanac.services'; | ||||
|  | ||||
|   public function getCapabilityName() { | ||||
|     return pht('Can Create Services'); | ||||
|   } | ||||
|  | ||||
|   public function describeCapabilityRejection() { | ||||
|     return pht('You do not have permission to create Almanac services.'); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,128 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingEditController | ||||
|   extends AlmanacServiceController { | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $id = $request->getURIData('id'); | ||||
|     if ($id) { | ||||
|       $binding = id(new AlmanacBindingQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withIDs(array($id)) | ||||
|         ->requireCapabilities( | ||||
|           array( | ||||
|             PhabricatorPolicyCapability::CAN_VIEW, | ||||
|             PhabricatorPolicyCapability::CAN_EDIT, | ||||
|           )) | ||||
|         ->executeOne(); | ||||
|       if (!$binding) { | ||||
|         return new Aphront404Response(); | ||||
|       } | ||||
|  | ||||
|       $service = $binding->getService(); | ||||
|       $is_new = false; | ||||
|  | ||||
|       $service_uri = $service->getURI(); | ||||
|       $cancel_uri = $binding->getURI(); | ||||
|       $title = pht('Edit Binding'); | ||||
|       $save_button = pht('Save Changes'); | ||||
|     } else { | ||||
|       $service = id(new AlmanacServiceQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withIDs(array($request->getStr('serviceID'))) | ||||
|         ->requireCapabilities( | ||||
|           array( | ||||
|             PhabricatorPolicyCapability::CAN_VIEW, | ||||
|             PhabricatorPolicyCapability::CAN_EDIT, | ||||
|           )) | ||||
|         ->executeOne(); | ||||
|  | ||||
|       $binding = AlmanacBinding::initializeNewBinding($service); | ||||
|       $is_new = true; | ||||
|  | ||||
|       $service_uri = $service->getURI(); | ||||
|       $cancel_uri = $service_uri; | ||||
|       $title = pht('Create Binding'); | ||||
|       $save_button = pht('Create Binding'); | ||||
|     } | ||||
|  | ||||
|     $v_interface = array(); | ||||
|     if ($binding->getInterfacePHID()) { | ||||
|       $v_interface = array($binding->getInterfacePHID()); | ||||
|     } | ||||
|     $e_interface = true; | ||||
|  | ||||
|     $validation_exception = null; | ||||
|     if ($request->isFormPost()) { | ||||
|       $v_interface = $request->getArr('interfacePHIDs'); | ||||
|  | ||||
|       $type_interface = AlmanacBindingTransaction::TYPE_INTERFACE; | ||||
|  | ||||
|       $xactions = array(); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacBindingTransaction()) | ||||
|         ->setTransactionType($type_interface) | ||||
|         ->setNewValue(head($v_interface)); | ||||
|  | ||||
|       $editor = id(new AlmanacBindingEditor()) | ||||
|         ->setActor($viewer) | ||||
|         ->setContentSourceFromRequest($request) | ||||
|         ->setContinueOnNoEffect(true); | ||||
|  | ||||
|       try { | ||||
|         $editor->applyTransactions($binding, $xactions); | ||||
|  | ||||
|         $binding_uri = $binding->getURI(); | ||||
|         return id(new AphrontRedirectResponse())->setURI($binding_uri); | ||||
|       } catch (PhabricatorApplicationTransactionValidationException $ex) { | ||||
|         $validation_exception = $ex; | ||||
|         $e_interface = $ex->getShortMessage($type_interface); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $interface_handles = array(); | ||||
|     if ($v_interface) { | ||||
|       $interface_handles = $this->loadViewerHandles($v_interface); | ||||
|     } | ||||
|  | ||||
|     $form = id(new AphrontFormView()) | ||||
|       ->setUser($viewer) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTokenizerControl()) | ||||
|           ->setName('interfacePHIDs') | ||||
|           ->setLabel('Interface') | ||||
|           ->setLimit(1) | ||||
|           ->setDatasource(new AlmanacInterfaceDatasource()) | ||||
|           ->setValue($interface_handles) | ||||
|           ->setError($e_interface)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormSubmitControl()) | ||||
|           ->addCancelButton($cancel_uri) | ||||
|           ->setValue($save_button)); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setValidationException($validation_exception) | ||||
|       ->setHeaderText($title) | ||||
|       ->appendChild($form); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($service->getName(), $service_uri); | ||||
|     if ($is_new) { | ||||
|       $crumbs->addTextCrumb(pht('Create Binding')); | ||||
|     } else { | ||||
|       $crumbs->addTextCrumb(pht('Edit Binding')); | ||||
|     } | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,122 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingViewController | ||||
|   extends AlmanacServiceController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $id = $request->getURIData('id'); | ||||
|  | ||||
|     $binding = id(new AlmanacBindingQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withIDs(array($id)) | ||||
|       ->executeOne(); | ||||
|     if (!$binding) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     $service = $binding->getService(); | ||||
|     $service_uri = $service->getURI(); | ||||
|  | ||||
|     $title = pht('Binding %s', $binding->getID()); | ||||
|  | ||||
|     $property_list = $this->buildPropertyList($binding); | ||||
|     $action_list = $this->buildActionList($binding); | ||||
|     $property_list->setActionList($action_list); | ||||
|  | ||||
|     $header = id(new PHUIHeaderView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setHeader($title) | ||||
|       ->setPolicyObject($binding); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setHeader($header) | ||||
|       ->addPropertyList($property_list); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($service->getName(), $service_uri); | ||||
|     $crumbs->addTextCrumb($title); | ||||
|  | ||||
|     $xactions = id(new AlmanacBindingTransactionQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withObjectPHIDs(array($binding->getPHID())) | ||||
|       ->execute(); | ||||
|  | ||||
|     $xaction_view = id(new PhabricatorApplicationTransactionView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setObjectPHID($binding->getPHID()) | ||||
|       ->setTransactions($xactions) | ||||
|       ->setShouldTerminate(true); | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|         $xaction_view, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
|   private function buildPropertyList(AlmanacBinding $binding) { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $properties = id(new PHUIPropertyListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $handles = $this->loadViewerHandles( | ||||
|       array( | ||||
|         $binding->getServicePHID(), | ||||
|         $binding->getDevicePHID(), | ||||
|         $binding->getInterface()->getNetworkPHID(), | ||||
|       )); | ||||
|  | ||||
|     $properties->addProperty( | ||||
|       pht('Service'), | ||||
|       $handles[$binding->getServicePHID()]->renderLink()); | ||||
|  | ||||
|     $properties->addProperty( | ||||
|       pht('Device'), | ||||
|       $handles[$binding->getDevicePHID()]->renderLink()); | ||||
|  | ||||
|     $properties->addProperty( | ||||
|       pht('Network'), | ||||
|       $handles[$binding->getInterface()->getNetworkPHID()]->renderLink()); | ||||
|  | ||||
|     $properties->addProperty( | ||||
|       pht('Interface'), | ||||
|       $binding->getInterface()->renderDisplayAddress()); | ||||
|  | ||||
|     return $properties; | ||||
|   } | ||||
|  | ||||
|   private function buildActionList(AlmanacBinding $binding) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $binding->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $binding, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $actions = id(new PhabricatorActionListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $actions->addAction( | ||||
|       id(new PhabricatorActionView()) | ||||
|         ->setIcon('fa-pencil') | ||||
|         ->setName(pht('Edit Binding')) | ||||
|         ->setHref($this->getApplicationURI("binding/edit/{$id}/")) | ||||
|         ->setWorkflow(!$can_edit) | ||||
|         ->setDisabled(!$can_edit)); | ||||
|  | ||||
|     return $actions; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacConsoleController extends AlmanacController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $menu = id(new PHUIObjectItemListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $menu->addItem( | ||||
|       id(new PHUIObjectItemView()) | ||||
|         ->setHeader(pht('Services')) | ||||
|         ->setHref($this->getApplicationURI('service/')) | ||||
|         ->addAttribute( | ||||
|           pht( | ||||
|             'Manage Almanac services.'))); | ||||
|  | ||||
|     $menu->addItem( | ||||
|       id(new PHUIObjectItemView()) | ||||
|         ->setHeader(pht('Devices')) | ||||
|         ->setHref($this->getApplicationURI('device/')) | ||||
|         ->addAttribute( | ||||
|           pht( | ||||
|             'Manage Almanac devices.'))); | ||||
|  | ||||
|     $menu->addItem( | ||||
|       id(new PHUIObjectItemView()) | ||||
|         ->setHeader(pht('Networks')) | ||||
|         ->setHref($this->getApplicationURI('network/')) | ||||
|         ->addAttribute( | ||||
|           pht( | ||||
|             'Manage Almanac networks.'))); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb(pht('Console')); | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $menu, | ||||
|       ), | ||||
|       array( | ||||
|         'title'  => pht('Almanac Console'), | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,4 @@ | ||||
| <?php | ||||
|  | ||||
| abstract class AlmanacController | ||||
|   extends PhabricatorController {} | ||||
| @@ -0,0 +1,14 @@ | ||||
| <?php | ||||
|  | ||||
| abstract class AlmanacDeviceController extends AlmanacController { | ||||
|  | ||||
|   public function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|  | ||||
|     $list_uri = $this->getApplicationURI('device/'); | ||||
|     $crumbs->addTextCrumb(pht('Devices'), $list_uri); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,142 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceEditController | ||||
|   extends AlmanacDeviceController { | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $list_uri = $this->getApplicationURI('device/'); | ||||
|  | ||||
|     $id = $request->getURIData('id'); | ||||
|     if ($id) { | ||||
|       $device = id(new AlmanacDeviceQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withIDs(array($id)) | ||||
|         ->requireCapabilities( | ||||
|           array( | ||||
|             PhabricatorPolicyCapability::CAN_VIEW, | ||||
|             PhabricatorPolicyCapability::CAN_EDIT, | ||||
|           )) | ||||
|         ->executeOne(); | ||||
|       if (!$device) { | ||||
|         return new Aphront404Response(); | ||||
|       } | ||||
|  | ||||
|       $is_new = false; | ||||
|       $device_uri = $device->getURI(); | ||||
|       $cancel_uri = $device_uri; | ||||
|       $title = pht('Edit Device'); | ||||
|       $save_button = pht('Save Changes'); | ||||
|     } else { | ||||
|       $this->requireApplicationCapability( | ||||
|         AlmanacCreateDevicesCapability::CAPABILITY); | ||||
|  | ||||
|       $device = AlmanacDevice::initializeNewDevice(); | ||||
|       $is_new = true; | ||||
|  | ||||
|       $cancel_uri = $list_uri; | ||||
|       $title = pht('Create Device'); | ||||
|       $save_button = pht('Create Device'); | ||||
|     } | ||||
|  | ||||
|     $v_name = $device->getName(); | ||||
|     $e_name = true; | ||||
|     $validation_exception = null; | ||||
|  | ||||
|     if ($request->isFormPost()) { | ||||
|       $v_name = $request->getStr('name'); | ||||
|       $v_view = $request->getStr('viewPolicy'); | ||||
|       $v_edit = $request->getStr('editPolicy'); | ||||
|  | ||||
|       $type_name = AlmanacDeviceTransaction::TYPE_NAME; | ||||
|       $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; | ||||
|       $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; | ||||
|  | ||||
|       $xactions = array(); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacDeviceTransaction()) | ||||
|         ->setTransactionType($type_name) | ||||
|         ->setNewValue($v_name); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacDeviceTransaction()) | ||||
|         ->setTransactionType($type_view) | ||||
|         ->setNewValue($v_view); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacDeviceTransaction()) | ||||
|         ->setTransactionType($type_edit) | ||||
|         ->setNewValue($v_edit); | ||||
|  | ||||
|       $editor = id(new AlmanacDeviceEditor()) | ||||
|         ->setActor($viewer) | ||||
|         ->setContentSourceFromRequest($request) | ||||
|         ->setContinueOnNoEffect(true); | ||||
|  | ||||
|       try { | ||||
|         $editor->applyTransactions($device, $xactions); | ||||
|  | ||||
|         $device_uri = $device->getURI(); | ||||
|         return id(new AphrontRedirectResponse())->setURI($device_uri); | ||||
|       } catch (PhabricatorApplicationTransactionValidationException $ex) { | ||||
|         $validation_exception = $ex; | ||||
|         $e_name = $ex->getShortMessage($type_name); | ||||
|  | ||||
|         $device->setViewPolicy($v_view); | ||||
|         $device->setEditPolicy($v_edit); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $policies = id(new PhabricatorPolicyQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->setObject($device) | ||||
|       ->execute(); | ||||
|  | ||||
|     $form = id(new AphrontFormView()) | ||||
|       ->setUser($viewer) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTextControl()) | ||||
|           ->setLabel(pht('Name')) | ||||
|           ->setName('name') | ||||
|           ->setValue($v_name) | ||||
|           ->setError($e_name)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormPolicyControl()) | ||||
|           ->setName('viewPolicy') | ||||
|           ->setPolicyObject($device) | ||||
|           ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) | ||||
|           ->setPolicies($policies)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormPolicyControl()) | ||||
|           ->setName('editPolicy') | ||||
|           ->setPolicyObject($device) | ||||
|           ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) | ||||
|           ->setPolicies($policies)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormSubmitControl()) | ||||
|           ->addCancelButton($cancel_uri) | ||||
|           ->setValue($save_button)); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setValidationException($validation_exception) | ||||
|       ->setHeaderText($title) | ||||
|       ->appendChild($form); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     if ($is_new) { | ||||
|       $crumbs->addTextCrumb(pht('Create Device')); | ||||
|     } else { | ||||
|       $crumbs->addTextCrumb($device->getName(), $device_uri); | ||||
|       $crumbs->addTextCrumb(pht('Edit')); | ||||
|     } | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceListController | ||||
|   extends AlmanacDeviceController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $controller = id(new PhabricatorApplicationSearchController()) | ||||
|       ->setQueryKey($request->getURIData('queryKey')) | ||||
|       ->setSearchEngine(new AlmanacDeviceSearchEngine()) | ||||
|       ->setNavigation($this->buildSideNavView()); | ||||
|  | ||||
|     return $this->delegateToController($controller); | ||||
|   } | ||||
|  | ||||
|   public function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|  | ||||
|     $can_create = $this->hasApplicationCapability( | ||||
|       AlmanacCreateDevicesCapability::CAPABILITY); | ||||
|  | ||||
|     $crumbs->addAction( | ||||
|       id(new PHUIListItemView()) | ||||
|         ->setName(pht('Create Device')) | ||||
|         ->setHref($this->getApplicationURI('device/edit/')) | ||||
|         ->setIcon('fa-plus-square') | ||||
|         ->setDisabled(!$can_create) | ||||
|         ->setWorkflow(!$can_create)); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
|   public function buildSideNavView() { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $nav = new AphrontSideNavFilterView(); | ||||
|     $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); | ||||
|  | ||||
|     id(new AlmanacDeviceSearchEngine()) | ||||
|       ->setViewer($viewer) | ||||
|       ->addNavigationItems($nav->getMenu()); | ||||
|  | ||||
|     $nav->selectFilter(null); | ||||
|  | ||||
|     return $nav; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,142 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceViewController | ||||
|   extends AlmanacDeviceController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $name = $request->getURIData('name'); | ||||
|  | ||||
|     $device = id(new AlmanacDeviceQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withNames(array($name)) | ||||
|       ->executeOne(); | ||||
|     if (!$device) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     $title = pht('Device %s', $device->getName()); | ||||
|  | ||||
|     $property_list = $this->buildPropertyList($device); | ||||
|     $action_list = $this->buildActionList($device); | ||||
|     $property_list->setActionList($action_list); | ||||
|  | ||||
|     $header = id(new PHUIHeaderView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setHeader($device->getName()) | ||||
|       ->setPolicyObject($device); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setHeader($header) | ||||
|       ->addPropertyList($property_list); | ||||
|  | ||||
|     $interfaces = $this->buildInterfaceList($device); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($device->getName()); | ||||
|  | ||||
|     $xactions = id(new AlmanacDeviceTransactionQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withObjectPHIDs(array($device->getPHID())) | ||||
|       ->execute(); | ||||
|  | ||||
|     $xaction_view = id(new PhabricatorApplicationTransactionView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setObjectPHID($device->getPHID()) | ||||
|       ->setTransactions($xactions) | ||||
|       ->setShouldTerminate(true); | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|         $interfaces, | ||||
|         $xaction_view, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
|   private function buildPropertyList(AlmanacDevice $device) { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $properties = id(new PHUIPropertyListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     return $properties; | ||||
|   } | ||||
|  | ||||
|   private function buildActionList(AlmanacDevice $device) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $device->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $device, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $actions = id(new PhabricatorActionListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $actions->addAction( | ||||
|       id(new PhabricatorActionView()) | ||||
|         ->setIcon('fa-pencil') | ||||
|         ->setName(pht('Edit Device')) | ||||
|         ->setHref($this->getApplicationURI("device/edit/{$id}/")) | ||||
|         ->setWorkflow(!$can_edit) | ||||
|         ->setDisabled(!$can_edit)); | ||||
|  | ||||
|     return $actions; | ||||
|   } | ||||
|  | ||||
|   private function buildInterfaceList(AlmanacDevice $device) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $device->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $device, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $interfaces = id(new AlmanacInterfaceQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withDevicePHIDs(array($device->getPHID())) | ||||
|       ->execute(); | ||||
|  | ||||
|     $phids = array(); | ||||
|     foreach ($interfaces as $interface) { | ||||
|       $phids[] = $interface->getNetworkPHID(); | ||||
|       $phids[] = $interface->getDevicePHID(); | ||||
|     } | ||||
|     $handles = $this->loadViewerHandles($phids); | ||||
|  | ||||
|     $table = id(new AlmanacInterfaceTableView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setInterfaces($interfaces) | ||||
|       ->setHandles($handles); | ||||
|  | ||||
|     $header = id(new PHUIHeaderView()) | ||||
|       ->setHeader(pht('Device Interfaces')) | ||||
|       ->addActionLink( | ||||
|         id(new PHUIButtonView()) | ||||
|           ->setTag('a') | ||||
|           ->setHref($this->getApplicationURI("interface/edit/?deviceID={$id}")) | ||||
|           ->setWorkflow(!$can_edit) | ||||
|           ->setDisabled(!$can_edit) | ||||
|           ->setText(pht('Add Interface')) | ||||
|           ->setIcon( | ||||
|             id(new PHUIIconView()) | ||||
|               ->setIconFont('fa-plus'))); | ||||
|  | ||||
|     return id(new PHUIObjectBoxView()) | ||||
|       ->setHeader($header) | ||||
|       ->appendChild($table); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,155 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacInterfaceEditController | ||||
|   extends AlmanacDeviceController { | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $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 { | ||||
|       $device = id(new AlmanacDeviceQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withIDs(array($request->getStr('deviceID'))) | ||||
|         ->requireCapabilities( | ||||
|           array( | ||||
|             PhabricatorPolicyCapability::CAN_VIEW, | ||||
|             PhabricatorPolicyCapability::CAN_EDIT, | ||||
|           )) | ||||
|         ->executeOne(); | ||||
|       if (!$device) { | ||||
|         return new Aphront404Response(); | ||||
|       } | ||||
|  | ||||
|       $interface = AlmanacInterface::initializeNewInterface(); | ||||
|       $is_new = true; | ||||
|  | ||||
|       $title = pht('Create Interface'); | ||||
|       $save_button = pht('Create Interface'); | ||||
|     } | ||||
|  | ||||
|     $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($title) | ||||
|       ->appendChild($form); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($device->getName(), $device_uri); | ||||
|     if ($is_new) { | ||||
|       $crumbs->addTextCrumb(pht('Create Interface')); | ||||
|     } else { | ||||
|       $crumbs->addTextCrumb(pht('Edit Interface')); | ||||
|     } | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,14 @@ | ||||
| <?php | ||||
|  | ||||
| abstract class AlmanacNetworkController extends AlmanacController { | ||||
|  | ||||
|   public function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|  | ||||
|     $list_uri = $this->getApplicationURI('network/'); | ||||
|     $crumbs->addTextCrumb(pht('Networks'), $list_uri); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,143 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkEditController | ||||
|   extends AlmanacNetworkController { | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $list_uri = $this->getApplicationURI('network/'); | ||||
|  | ||||
|     $id = $request->getURIData('id'); | ||||
|     if ($id) { | ||||
|       $network = id(new AlmanacNetworkQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withIDs(array($id)) | ||||
|         ->requireCapabilities( | ||||
|           array( | ||||
|             PhabricatorPolicyCapability::CAN_VIEW, | ||||
|             PhabricatorPolicyCapability::CAN_EDIT, | ||||
|           )) | ||||
|         ->executeOne(); | ||||
|       if (!$network) { | ||||
|         return new Aphront404Response(); | ||||
|       } | ||||
|  | ||||
|       $is_new = false; | ||||
|       $network_uri = $this->getApplicationURI('network/'.$network->getID().'/'); | ||||
|       $cancel_uri = $network_uri; | ||||
|       $title = pht('Edit Network'); | ||||
|       $save_button = pht('Save Changes'); | ||||
|     } else { | ||||
|       $this->requireApplicationCapability( | ||||
|         AlmanacCreateNetworksCapability::CAPABILITY); | ||||
|  | ||||
|       $network = AlmanacNetwork::initializeNewNetwork(); | ||||
|       $is_new = true; | ||||
|  | ||||
|       $cancel_uri = $list_uri; | ||||
|       $title = pht('Create Network'); | ||||
|       $save_button = pht('Create Network'); | ||||
|     } | ||||
|  | ||||
|     $v_name = $network->getName(); | ||||
|     $e_name = true; | ||||
|     $validation_exception = null; | ||||
|  | ||||
|     if ($request->isFormPost()) { | ||||
|       $v_name = $request->getStr('name'); | ||||
|       $v_view = $request->getStr('viewPolicy'); | ||||
|       $v_edit = $request->getStr('editPolicy'); | ||||
|  | ||||
|       $type_name = AlmanacNetworkTransaction::TYPE_NAME; | ||||
|       $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; | ||||
|       $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; | ||||
|  | ||||
|       $xactions = array(); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacNetworkTransaction()) | ||||
|         ->setTransactionType($type_name) | ||||
|         ->setNewValue($v_name); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacNetworkTransaction()) | ||||
|         ->setTransactionType($type_view) | ||||
|         ->setNewValue($v_view); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacNetworkTransaction()) | ||||
|         ->setTransactionType($type_edit) | ||||
|         ->setNewValue($v_edit); | ||||
|  | ||||
|       $editor = id(new AlmanacNetworkEditor()) | ||||
|         ->setActor($viewer) | ||||
|         ->setContentSourceFromRequest($request) | ||||
|         ->setContinueOnNoEffect(true); | ||||
|  | ||||
|       try { | ||||
|         $editor->applyTransactions($network, $xactions); | ||||
|  | ||||
|         $id = $network->getID(); | ||||
|         $network_uri = $this->getApplicationURI("network/{$id}/"); | ||||
|         return id(new AphrontRedirectResponse())->setURI($network_uri); | ||||
|       } catch (PhabricatorApplicationTransactionValidationException $ex) { | ||||
|         $validation_exception = $ex; | ||||
|         $e_name = $ex->getShortMessage($type_name); | ||||
|  | ||||
|         $network->setViewPolicy($v_view); | ||||
|         $network->setEditPolicy($v_edit); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $policies = id(new PhabricatorPolicyQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->setObject($network) | ||||
|       ->execute(); | ||||
|  | ||||
|     $form = id(new AphrontFormView()) | ||||
|       ->setUser($viewer) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTextControl()) | ||||
|           ->setLabel(pht('Name')) | ||||
|           ->setName('name') | ||||
|           ->setValue($v_name) | ||||
|           ->setError($e_name)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormPolicyControl()) | ||||
|           ->setName('viewPolicy') | ||||
|           ->setPolicyObject($network) | ||||
|           ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) | ||||
|           ->setPolicies($policies)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormPolicyControl()) | ||||
|           ->setName('editPolicy') | ||||
|           ->setPolicyObject($network) | ||||
|           ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) | ||||
|           ->setPolicies($policies)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormSubmitControl()) | ||||
|           ->addCancelButton($cancel_uri) | ||||
|           ->setValue($save_button)); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setValidationException($validation_exception) | ||||
|       ->setHeaderText($title) | ||||
|       ->appendChild($form); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     if ($is_new) { | ||||
|       $crumbs->addTextCrumb(pht('Create Network')); | ||||
|     } else { | ||||
|       $crumbs->addTextCrumb($network->getName(), $network_uri); | ||||
|       $crumbs->addTextCrumb(pht('Edit')); | ||||
|     } | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkListController | ||||
|   extends AlmanacNetworkController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $controller = id(new PhabricatorApplicationSearchController()) | ||||
|       ->setQueryKey($request->getURIData('queryKey')) | ||||
|       ->setSearchEngine(new AlmanacNetworkSearchEngine()) | ||||
|       ->setNavigation($this->buildSideNavView()); | ||||
|  | ||||
|     return $this->delegateToController($controller); | ||||
|   } | ||||
|  | ||||
|   public function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|  | ||||
|     $can_create = $this->hasApplicationCapability( | ||||
|       AlmanacCreateNetworksCapability::CAPABILITY); | ||||
|  | ||||
|     $crumbs->addAction( | ||||
|       id(new PHUIListItemView()) | ||||
|         ->setName(pht('Create Network')) | ||||
|         ->setHref($this->getApplicationURI('network/edit/')) | ||||
|         ->setIcon('fa-plus-square') | ||||
|         ->setDisabled(!$can_create) | ||||
|         ->setWorkflow(!$can_create)); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
|   public function buildSideNavView() { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $nav = new AphrontSideNavFilterView(); | ||||
|     $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); | ||||
|  | ||||
|     id(new AlmanacNetworkSearchEngine()) | ||||
|       ->setViewer($viewer) | ||||
|       ->addNavigationItems($nav->getMenu()); | ||||
|  | ||||
|     $nav->selectFilter(null); | ||||
|  | ||||
|     return $nav; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,95 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkViewController | ||||
|   extends AlmanacNetworkController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $id = $request->getURIData('id'); | ||||
|  | ||||
|     $network = id(new AlmanacNetworkQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withIDs(array($id)) | ||||
|       ->executeOne(); | ||||
|     if (!$network) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     $title = pht('Network %s', $network->getName()); | ||||
|  | ||||
|     $property_list = $this->buildPropertyList($network); | ||||
|     $action_list = $this->buildActionList($network); | ||||
|     $property_list->setActionList($action_list); | ||||
|  | ||||
|     $header = id(new PHUIHeaderView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setHeader($network->getName()) | ||||
|       ->setPolicyObject($network); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setHeader($header) | ||||
|       ->addPropertyList($property_list); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($network->getName()); | ||||
|  | ||||
|     $xactions = id(new AlmanacNetworkTransactionQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withObjectPHIDs(array($network->getPHID())) | ||||
|       ->execute(); | ||||
|  | ||||
|     $xaction_view = id(new PhabricatorApplicationTransactionView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setObjectPHID($network->getPHID()) | ||||
|       ->setTransactions($xactions) | ||||
|       ->setShouldTerminate(true); | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|         $xaction_view, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
|   private function buildPropertyList(AlmanacNetwork $network) { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $properties = id(new PHUIPropertyListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     return $properties; | ||||
|   } | ||||
|  | ||||
|   private function buildActionList(AlmanacNetwork $network) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $network->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $network, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $actions = id(new PhabricatorActionListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $actions->addAction( | ||||
|       id(new PhabricatorActionView()) | ||||
|         ->setIcon('fa-pencil') | ||||
|         ->setName(pht('Edit Network')) | ||||
|         ->setHref($this->getApplicationURI("network/edit/{$id}/")) | ||||
|         ->setWorkflow(!$can_edit) | ||||
|         ->setDisabled(!$can_edit)); | ||||
|  | ||||
|     return $actions; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,14 @@ | ||||
| <?php | ||||
|  | ||||
| abstract class AlmanacServiceController extends AlmanacController { | ||||
|  | ||||
|   public function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|  | ||||
|     $list_uri = $this->getApplicationURI('service/'); | ||||
|     $crumbs->addTextCrumb(pht('Services'), $list_uri); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,142 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceEditController | ||||
|   extends AlmanacServiceController { | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $list_uri = $this->getApplicationURI('service/'); | ||||
|  | ||||
|     $id = $request->getURIData('id'); | ||||
|     if ($id) { | ||||
|       $service = id(new AlmanacServiceQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withIDs(array($id)) | ||||
|         ->requireCapabilities( | ||||
|           array( | ||||
|             PhabricatorPolicyCapability::CAN_VIEW, | ||||
|             PhabricatorPolicyCapability::CAN_EDIT, | ||||
|           )) | ||||
|         ->executeOne(); | ||||
|       if (!$service) { | ||||
|         return new Aphront404Response(); | ||||
|       } | ||||
|  | ||||
|       $is_new = false; | ||||
|       $service_uri = $service->getURI(); | ||||
|       $cancel_uri = $service_uri; | ||||
|       $title = pht('Edit Service'); | ||||
|       $save_button = pht('Save Changes'); | ||||
|     } else { | ||||
|       $this->requireApplicationCapability( | ||||
|         AlmanacCreateServicesCapability::CAPABILITY); | ||||
|  | ||||
|       $service = AlmanacService::initializeNewService(); | ||||
|       $is_new = true; | ||||
|  | ||||
|       $cancel_uri = $list_uri; | ||||
|       $title = pht('Create Service'); | ||||
|       $save_button = pht('Create Service'); | ||||
|     } | ||||
|  | ||||
|     $v_name = $service->getName(); | ||||
|     $e_name = true; | ||||
|     $validation_exception = null; | ||||
|  | ||||
|     if ($request->isFormPost()) { | ||||
|       $v_name = $request->getStr('name'); | ||||
|       $v_view = $request->getStr('viewPolicy'); | ||||
|       $v_edit = $request->getStr('editPolicy'); | ||||
|  | ||||
|       $type_name = AlmanacServiceTransaction::TYPE_NAME; | ||||
|       $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; | ||||
|       $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; | ||||
|  | ||||
|       $xactions = array(); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacServiceTransaction()) | ||||
|         ->setTransactionType($type_name) | ||||
|         ->setNewValue($v_name); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacServiceTransaction()) | ||||
|         ->setTransactionType($type_view) | ||||
|         ->setNewValue($v_view); | ||||
|  | ||||
|       $xactions[] = id(new AlmanacServiceTransaction()) | ||||
|         ->setTransactionType($type_edit) | ||||
|         ->setNewValue($v_edit); | ||||
|  | ||||
|       $editor = id(new AlmanacServiceEditor()) | ||||
|         ->setActor($viewer) | ||||
|         ->setContentSourceFromRequest($request) | ||||
|         ->setContinueOnNoEffect(true); | ||||
|  | ||||
|       try { | ||||
|         $editor->applyTransactions($service, $xactions); | ||||
|  | ||||
|         $service_uri = $service->getURI(); | ||||
|         return id(new AphrontRedirectResponse())->setURI($service_uri); | ||||
|       } catch (PhabricatorApplicationTransactionValidationException $ex) { | ||||
|         $validation_exception = $ex; | ||||
|         $e_name = $ex->getShortMessage($type_name); | ||||
|  | ||||
|         $service->setViewPolicy($v_view); | ||||
|         $service->setEditPolicy($v_edit); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $policies = id(new PhabricatorPolicyQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->setObject($service) | ||||
|       ->execute(); | ||||
|  | ||||
|     $form = id(new AphrontFormView()) | ||||
|       ->setUser($viewer) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormTextControl()) | ||||
|           ->setLabel(pht('Name')) | ||||
|           ->setName('name') | ||||
|           ->setValue($v_name) | ||||
|           ->setError($e_name)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormPolicyControl()) | ||||
|           ->setName('viewPolicy') | ||||
|           ->setPolicyObject($service) | ||||
|           ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) | ||||
|           ->setPolicies($policies)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormPolicyControl()) | ||||
|           ->setName('editPolicy') | ||||
|           ->setPolicyObject($service) | ||||
|           ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) | ||||
|           ->setPolicies($policies)) | ||||
|       ->appendChild( | ||||
|         id(new AphrontFormSubmitControl()) | ||||
|           ->addCancelButton($cancel_uri) | ||||
|           ->setValue($save_button)); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setValidationException($validation_exception) | ||||
|       ->setHeaderText($title) | ||||
|       ->appendChild($form); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     if ($is_new) { | ||||
|       $crumbs->addTextCrumb(pht('Create Service')); | ||||
|     } else { | ||||
|       $crumbs->addTextCrumb($service->getName(), $service_uri); | ||||
|       $crumbs->addTextCrumb(pht('Edit')); | ||||
|     } | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceListController | ||||
|   extends AlmanacServiceController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $controller = id(new PhabricatorApplicationSearchController()) | ||||
|       ->setQueryKey($request->getURIData('queryKey')) | ||||
|       ->setSearchEngine(new AlmanacServiceSearchEngine()) | ||||
|       ->setNavigation($this->buildSideNavView()); | ||||
|  | ||||
|     return $this->delegateToController($controller); | ||||
|   } | ||||
|  | ||||
|   public function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|  | ||||
|     $can_create = $this->hasApplicationCapability( | ||||
|       AlmanacCreateServicesCapability::CAPABILITY); | ||||
|  | ||||
|     $crumbs->addAction( | ||||
|       id(new PHUIListItemView()) | ||||
|         ->setName(pht('Create Service')) | ||||
|         ->setHref($this->getApplicationURI('service/edit/')) | ||||
|         ->setIcon('fa-plus-square') | ||||
|         ->setDisabled(!$can_create) | ||||
|         ->setWorkflow(!$can_create)); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
|   public function buildSideNavView() { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $nav = new AphrontSideNavFilterView(); | ||||
|     $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); | ||||
|  | ||||
|     id(new AlmanacServiceSearchEngine()) | ||||
|       ->setViewer($viewer) | ||||
|       ->addNavigationItems($nav->getMenu()); | ||||
|  | ||||
|     $nav->selectFilter(null); | ||||
|  | ||||
|     return $nav; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,145 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceViewController | ||||
|   extends AlmanacServiceController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|  | ||||
|     $name = $request->getURIData('name'); | ||||
|  | ||||
|     $service = id(new AlmanacServiceQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withNames(array($name)) | ||||
|       ->executeOne(); | ||||
|     if (!$service) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     $title = pht('Service %s', $service->getName()); | ||||
|  | ||||
|     $property_list = $this->buildPropertyList($service); | ||||
|     $action_list = $this->buildActionList($service); | ||||
|     $property_list->setActionList($action_list); | ||||
|  | ||||
|     $header = id(new PHUIHeaderView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setHeader($service->getName()) | ||||
|       ->setPolicyObject($service); | ||||
|  | ||||
|     $box = id(new PHUIObjectBoxView()) | ||||
|       ->setHeader($header) | ||||
|       ->addPropertyList($property_list); | ||||
|  | ||||
|     $bindings = $this->buildBindingList($service); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($service->getName()); | ||||
|  | ||||
|     $xactions = id(new AlmanacServiceTransactionQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withObjectPHIDs(array($service->getPHID())) | ||||
|       ->execute(); | ||||
|  | ||||
|     $xaction_view = id(new PhabricatorApplicationTransactionView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setObjectPHID($service->getPHID()) | ||||
|       ->setTransactions($xactions) | ||||
|       ->setShouldTerminate(true); | ||||
|  | ||||
|     return $this->buildApplicationPage( | ||||
|       array( | ||||
|         $crumbs, | ||||
|         $box, | ||||
|         $bindings, | ||||
|         $xaction_view, | ||||
|       ), | ||||
|       array( | ||||
|         'title' => $title, | ||||
|       )); | ||||
|   } | ||||
|  | ||||
|   private function buildPropertyList(AlmanacService $service) { | ||||
|     $viewer = $this->getViewer(); | ||||
|  | ||||
|     $properties = id(new PHUIPropertyListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     return $properties; | ||||
|   } | ||||
|  | ||||
|   private function buildActionList(AlmanacService $service) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $service->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $service, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $actions = id(new PhabricatorActionListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     $actions->addAction( | ||||
|       id(new PhabricatorActionView()) | ||||
|         ->setIcon('fa-pencil') | ||||
|         ->setName(pht('Edit Service')) | ||||
|         ->setHref($this->getApplicationURI("service/edit/{$id}/")) | ||||
|         ->setWorkflow(!$can_edit) | ||||
|         ->setDisabled(!$can_edit)); | ||||
|  | ||||
|     return $actions; | ||||
|   } | ||||
|  | ||||
|   private function buildBindingList(AlmanacService $service) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $service->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $service, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $bindings = id(new AlmanacBindingQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withServicePHIDs(array($service->getPHID())) | ||||
|       ->execute(); | ||||
|  | ||||
|     $phids = array(); | ||||
|     foreach ($bindings as $binding) { | ||||
|       $phids[] = $binding->getServicePHID(); | ||||
|       $phids[] = $binding->getDevicePHID(); | ||||
|       $phids[] = $binding->getInterface()->getNetworkPHID(); | ||||
|     } | ||||
|     $handles = $this->loadViewerHandles($phids); | ||||
|  | ||||
|     $table = id(new AlmanacBindingTableView()) | ||||
|       ->setNoDataString( | ||||
|         pht('This service has not been bound to any device interfaces yet.')) | ||||
|       ->setUser($viewer) | ||||
|       ->setBindings($bindings) | ||||
|       ->setHandles($handles); | ||||
|  | ||||
|     $header = id(new PHUIHeaderView()) | ||||
|       ->setHeader(pht('Service Bindings')) | ||||
|       ->addActionLink( | ||||
|         id(new PHUIButtonView()) | ||||
|           ->setTag('a') | ||||
|           ->setHref($this->getApplicationURI("binding/edit/?serviceID={$id}")) | ||||
|           ->setWorkflow(!$can_edit) | ||||
|           ->setDisabled(!$can_edit) | ||||
|           ->setText(pht('Add Binding')) | ||||
|           ->setIcon( | ||||
|             id(new PHUIIconView()) | ||||
|               ->setIconFont('fa-plus'))); | ||||
|  | ||||
|     return id(new PHUIObjectBoxView()) | ||||
|       ->setHeader($header) | ||||
|       ->appendChild($table); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										139
									
								
								src/applications/almanac/editor/AlmanacBindingEditor.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/applications/almanac/editor/AlmanacBindingEditor.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingEditor | ||||
|   extends PhabricatorApplicationTransactionEditor { | ||||
|  | ||||
|   public function getEditorApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function getEditorObjectsDescription() { | ||||
|     return pht('Almanac Binding'); | ||||
|   } | ||||
|  | ||||
|   public function getTransactionTypes() { | ||||
|     $types = parent::getTransactionTypes(); | ||||
|  | ||||
|     $types[] = AlmanacBindingTransaction::TYPE_INTERFACE; | ||||
|  | ||||
|     return $types; | ||||
|   } | ||||
|  | ||||
|   protected function getCustomTransactionOldValue( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case AlmanacBindingTransaction::TYPE_INTERFACE: | ||||
|         return $object->getInterfacePHID(); | ||||
|     } | ||||
|  | ||||
|     return parent::getCustomTransactionOldValue($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function getCustomTransactionNewValue( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|  | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case AlmanacBindingTransaction::TYPE_INTERFACE: | ||||
|         return $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; | ||||
|     } | ||||
|  | ||||
|     return parent::applyCustomInternalTransaction($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function applyCustomExternalTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|  | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case AlmanacBindingTransaction::TYPE_INTERFACE: | ||||
|         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; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										292
									
								
								src/applications/almanac/editor/AlmanacDeviceEditor.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								src/applications/almanac/editor/AlmanacDeviceEditor.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,292 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceEditor | ||||
|   extends PhabricatorApplicationTransactionEditor { | ||||
|  | ||||
|   public function getEditorApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function getEditorObjectsDescription() { | ||||
|     return pht('Almanac Device'); | ||||
|   } | ||||
|  | ||||
|   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: | ||||
|       case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
|       case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     return parent::applyCustomInternalTransaction($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function applyCustomExternalTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|  | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case AlmanacDeviceTransaction::TYPE_NAME: | ||||
|       case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
|       case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
|         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']) | ||||
|             ->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::validateServiceOrDeviceName($name); | ||||
|             } catch (Exception $ex) { | ||||
|               $message = $ex->getMessage(); | ||||
|             } | ||||
|  | ||||
|             if ($message !== null) { | ||||
|               $error = new PhabricatorApplicationTransactionValidationError( | ||||
|                 $type, | ||||
|                 pht('Invalid'), | ||||
|                 $message, | ||||
|                 $xaction); | ||||
|               $errors[] = $error; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if ($xactions) { | ||||
|           $duplicate = id(new AlmanacDeviceQuery()) | ||||
|             ->setViewer(PhabricatorUser::getOmnipotentUser()) | ||||
|             ->withNames(array(last($xactions)->getNewValue())) | ||||
|             ->executeOne(); | ||||
|           if ($duplicate && ($duplicate->getID() != $object->getID())) { | ||||
|             $error = new PhabricatorApplicationTransactionValidationError( | ||||
|               $type, | ||||
|               pht('Not Unique'), | ||||
|               pht('Almanac devices must have unique names.'), | ||||
|               last($xactions)); | ||||
|             $errors[] = $error; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         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 trival | ||||
|               // 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; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         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; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|     return $errors; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										108
									
								
								src/applications/almanac/editor/AlmanacNetworkEditor.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/applications/almanac/editor/AlmanacNetworkEditor.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkEditor | ||||
|   extends PhabricatorApplicationTransactionEditor { | ||||
|  | ||||
|   public function getEditorApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function getEditorObjectsDescription() { | ||||
|     return pht('Almanac Network'); | ||||
|   } | ||||
|  | ||||
|   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; | ||||
|       case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
|       case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     return parent::applyCustomInternalTransaction($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function applyCustomExternalTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|  | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case AlmanacNetworkTransaction::TYPE_NAME: | ||||
|       case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
|       case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     return parent::applyCustomExternalTransaction($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function validateTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     $type, | ||||
|     array $xactions) { | ||||
|  | ||||
|     $errors = parent::validateTransaction($object, $type, $xactions); | ||||
|  | ||||
|     switch ($type) { | ||||
|       case AlmanacServiceTransaction::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; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										145
									
								
								src/applications/almanac/editor/AlmanacServiceEditor.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/applications/almanac/editor/AlmanacServiceEditor.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceEditor | ||||
|   extends PhabricatorApplicationTransactionEditor { | ||||
|  | ||||
|   public function getEditorApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function getEditorObjectsDescription() { | ||||
|     return pht('Almanac Service'); | ||||
|   } | ||||
|  | ||||
|   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; | ||||
|       case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
|       case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     return parent::applyCustomInternalTransaction($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function applyCustomExternalTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|  | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case AlmanacServiceTransaction::TYPE_NAME: | ||||
|       case PhabricatorTransactions::TYPE_VIEW_POLICY: | ||||
|       case PhabricatorTransactions::TYPE_EDIT_POLICY: | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     return parent::applyCustomExternalTransaction($object, $xaction); | ||||
|   } | ||||
|  | ||||
|   protected function validateTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     $type, | ||||
|     array $xactions) { | ||||
|  | ||||
|     $errors = parent::validateTransaction($object, $type, $xactions); | ||||
|  | ||||
|     switch ($type) { | ||||
|       case 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::validateServiceOrDeviceName($name); | ||||
|             } catch (Exception $ex) { | ||||
|               $message = $ex->getMessage(); | ||||
|             } | ||||
|  | ||||
|             if ($message !== null) { | ||||
|               $error = new PhabricatorApplicationTransactionValidationError( | ||||
|                 $type, | ||||
|                 pht('Invalid'), | ||||
|                 $message, | ||||
|                 $xaction); | ||||
|               $errors[] = $error; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if ($xactions) { | ||||
|           $duplicate = id(new AlmanacServiceQuery()) | ||||
|             ->setViewer(PhabricatorUser::getOmnipotentUser()) | ||||
|             ->withNames(array(last($xactions)->getNewValue())) | ||||
|             ->executeOne(); | ||||
|           if ($duplicate && ($duplicate->getID() != $object->getID())) { | ||||
|             $error = new PhabricatorApplicationTransactionValidationError( | ||||
|               $type, | ||||
|               pht('Not Unique'), | ||||
|               pht('Almanac services must have unique names.'), | ||||
|               last($xactions)); | ||||
|             $errors[] = $error; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return $errors; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/applications/almanac/phid/AlmanacBindingPHIDType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/applications/almanac/phid/AlmanacBindingPHIDType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingPHIDType extends PhabricatorPHIDType { | ||||
|  | ||||
|   const TYPECONST = 'ABND'; | ||||
|  | ||||
|   public function getTypeName() { | ||||
|     return pht('Almanac Binding'); | ||||
|   } | ||||
|  | ||||
|   public function newObject() { | ||||
|     return new AlmanacBinding(); | ||||
|   } | ||||
|  | ||||
|   protected function buildQueryForObjects( | ||||
|     PhabricatorObjectQuery $query, | ||||
|     array $phids) { | ||||
|  | ||||
|     return id(new AlmanacBindingQuery()) | ||||
|       ->withPHIDs($phids); | ||||
|   } | ||||
|  | ||||
|   public function loadHandles( | ||||
|     PhabricatorHandleQuery $query, | ||||
|     array $handles, | ||||
|     array $objects) { | ||||
|  | ||||
|     foreach ($handles as $phid => $handle) { | ||||
|       $binding = $objects[$phid]; | ||||
|  | ||||
|       $id = $binding->getID(); | ||||
|  | ||||
|       $handle->setObjectName(pht('Binding %d', $id)); | ||||
|       $handle->setName(pht('Binding %d', $id)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -33,6 +33,7 @@ final class AlmanacDevicePHIDType extends PhabricatorPHIDType { | ||||
|  | ||||
|       $handle->setObjectName(pht('Device %d', $id)); | ||||
|       $handle->setName($name); | ||||
|       $handle->setURI($device->getURI()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										50
									
								
								src/applications/almanac/phid/AlmanacInterfacePHIDType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/applications/almanac/phid/AlmanacInterfacePHIDType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacInterfacePHIDType extends PhabricatorPHIDType { | ||||
|  | ||||
|   const TYPECONST = 'AINT'; | ||||
|  | ||||
|   public function getTypeName() { | ||||
|     return pht('Almanac Interface'); | ||||
|   } | ||||
|  | ||||
|   public function newObject() { | ||||
|     return new AlmanacInterface(); | ||||
|   } | ||||
|  | ||||
|   protected function buildQueryForObjects( | ||||
|     PhabricatorObjectQuery $query, | ||||
|     array $phids) { | ||||
|  | ||||
|     return id(new AlmanacInterfaceQuery()) | ||||
|       ->withPHIDs($phids); | ||||
|   } | ||||
|  | ||||
|   public function loadHandles( | ||||
|     PhabricatorHandleQuery $query, | ||||
|     array $handles, | ||||
|     array $objects) { | ||||
|  | ||||
|     foreach ($handles as $phid => $handle) { | ||||
|       $interface = $objects[$phid]; | ||||
|  | ||||
|       $id = $interface->getID(); | ||||
|  | ||||
|       $device_name = $interface->getDevice()->getName(); | ||||
|       $address = $interface->getAddress(); | ||||
|       $port = $interface->getPort(); | ||||
|       $network = $interface->getNetwork()->getName(); | ||||
|  | ||||
|       $name = pht( | ||||
|         '%s:%s (%s on %s)', | ||||
|         $device_name, | ||||
|         $port, | ||||
|         $address, | ||||
|         $network); | ||||
|  | ||||
|       $handle->setObjectName(pht('Interface %d', $id)); | ||||
|       $handle->setName($name); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/applications/almanac/phid/AlmanacNetworkPHIDType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/applications/almanac/phid/AlmanacNetworkPHIDType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkPHIDType extends PhabricatorPHIDType { | ||||
|  | ||||
|   const TYPECONST = 'ANET'; | ||||
|  | ||||
|   public function getTypeName() { | ||||
|     return pht('Almanac Network'); | ||||
|   } | ||||
|  | ||||
|   public function newObject() { | ||||
|     return new AlmanacNetwork(); | ||||
|   } | ||||
|  | ||||
|   protected function buildQueryForObjects( | ||||
|     PhabricatorObjectQuery $query, | ||||
|     array $phids) { | ||||
|  | ||||
|     return id(new AlmanacNetworkQuery()) | ||||
|       ->withPHIDs($phids); | ||||
|   } | ||||
|  | ||||
|   public function loadHandles( | ||||
|     PhabricatorHandleQuery $query, | ||||
|     array $handles, | ||||
|     array $objects) { | ||||
|  | ||||
|     foreach ($handles as $phid => $handle) { | ||||
|       $network = $objects[$phid]; | ||||
|  | ||||
|       $id = $network->getID(); | ||||
|       $name = $network->getName(); | ||||
|  | ||||
|       $handle->setObjectName(pht('Network %d', $id)); | ||||
|       $handle->setName($name); | ||||
|       $handle->setURI($network->getURI()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/applications/almanac/phid/AlmanacServicePHIDType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/applications/almanac/phid/AlmanacServicePHIDType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServicePHIDType extends PhabricatorPHIDType { | ||||
|  | ||||
|   const TYPECONST = 'ASRV'; | ||||
|  | ||||
|   public function getTypeName() { | ||||
|     return pht('Almanac Service'); | ||||
|   } | ||||
|  | ||||
|   public function newObject() { | ||||
|     return new AlmanacService(); | ||||
|   } | ||||
|  | ||||
|   protected function buildQueryForObjects( | ||||
|     PhabricatorObjectQuery $query, | ||||
|     array $phids) { | ||||
|  | ||||
|     return id(new AlmanacServiceQuery()) | ||||
|       ->withPHIDs($phids); | ||||
|   } | ||||
|  | ||||
|   public function loadHandles( | ||||
|     PhabricatorHandleQuery $query, | ||||
|     array $handles, | ||||
|     array $objects) { | ||||
|  | ||||
|     foreach ($handles as $phid => $handle) { | ||||
|       $service = $objects[$phid]; | ||||
|  | ||||
|       $id = $service->getID(); | ||||
|       $name = $service->getName(); | ||||
|  | ||||
|       $handle->setObjectName(pht('Service %d', $id)); | ||||
|       $handle->setName($name); | ||||
|       $handle->setURI($service->getURI()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										143
									
								
								src/applications/almanac/query/AlmanacBindingQuery.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/applications/almanac/query/AlmanacBindingQuery.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingQuery | ||||
|   extends PhabricatorCursorPagedPolicyAwareQuery { | ||||
|  | ||||
|   private $ids; | ||||
|   private $phids; | ||||
|   private $servicePHIDs; | ||||
|   private $devicePHIDs; | ||||
|   private $interfacePHIDs; | ||||
|  | ||||
|   public function withIDs(array $ids) { | ||||
|     $this->ids = $ids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withPHIDs(array $phids) { | ||||
|     $this->phids = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withServicePHIDs(array $phids) { | ||||
|     $this->servicePHIDs = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withDevicePHIDs(array $phids) { | ||||
|     $this->devicePHIDs = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withInterfacePHIDs(array $phids) { | ||||
|     $this->interfacePHIDs = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   protected function loadPage() { | ||||
|     $table = new AlmanacBinding(); | ||||
|     $conn_r = $table->establishConnection('r'); | ||||
|  | ||||
|     $data = queryfx_all( | ||||
|       $conn_r, | ||||
|       'SELECT * FROM %T %Q %Q %Q', | ||||
|       $table->getTableName(), | ||||
|       $this->buildWhereClause($conn_r), | ||||
|       $this->buildOrderClause($conn_r), | ||||
|       $this->buildLimitClause($conn_r)); | ||||
|  | ||||
|     return $table->loadAllFromArray($data); | ||||
|   } | ||||
|  | ||||
|   protected function willFilterPage(array $bindings) { | ||||
|     $service_phids = mpull($bindings, 'getServicePHID'); | ||||
|     $device_phids = mpull($bindings, 'getDevicePHID'); | ||||
|     $interface_phids = mpull($bindings, 'getInterfacePHID'); | ||||
|  | ||||
|     $services = id(new AlmanacServiceQuery()) | ||||
|       ->setParentQuery($this) | ||||
|       ->setViewer($this->getViewer()) | ||||
|       ->withPHIDs($service_phids) | ||||
|       ->execute(); | ||||
|     $services = mpull($services, null, 'getPHID'); | ||||
|  | ||||
|     $devices = id(new AlmanacDeviceQuery()) | ||||
|       ->setParentQuery($this) | ||||
|       ->setViewer($this->getViewer()) | ||||
|       ->withPHIDs($device_phids) | ||||
|       ->execute(); | ||||
|     $devices = mpull($devices, null, 'getPHID'); | ||||
|  | ||||
|     $interfaces = id(new AlmanacInterfaceQuery()) | ||||
|       ->setParentQuery($this) | ||||
|       ->setViewer($this->getViewer()) | ||||
|       ->withPHIDs($interface_phids) | ||||
|       ->execute(); | ||||
|     $interfaces = mpull($interfaces, null, 'getPHID'); | ||||
|  | ||||
|     foreach ($bindings as $key => $binding) { | ||||
|       $service = idx($services, $binding->getServicePHID()); | ||||
|       $device = idx($devices, $binding->getDevicePHID()); | ||||
|       $interface = idx($interfaces, $binding->getInterfacePHID()); | ||||
|       if (!$service || !$device || !$interface) { | ||||
|         $this->didRejectResult($binding); | ||||
|         unset($bindings[$key]); | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       $binding->attachService($service); | ||||
|       $binding->attachDevice($device); | ||||
|       $binding->attachInterface($interface); | ||||
|     } | ||||
|  | ||||
|     return $bindings; | ||||
|   } | ||||
|  | ||||
|   protected function buildWhereClause($conn_r) { | ||||
|     $where = array(); | ||||
|  | ||||
|     if ($this->ids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'id IN (%Ld)', | ||||
|         $this->ids); | ||||
|     } | ||||
|  | ||||
|     if ($this->phids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'phid IN (%Ls)', | ||||
|         $this->phids); | ||||
|     } | ||||
|  | ||||
|     if ($this->servicePHIDs !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'servicePHID IN (%Ls)', | ||||
|         $this->servicePHIDs); | ||||
|     } | ||||
|  | ||||
|     if ($this->devicePHIDs !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'devicePHID IN (%Ls)', | ||||
|         $this->devicePHIDs); | ||||
|     } | ||||
|  | ||||
|     if ($this->interfacePHIDs !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'interfacePHID IN (%Ls)', | ||||
|         $this->interfacePHIDs); | ||||
|     } | ||||
|  | ||||
|     $where[] = $this->buildPagingClause($conn_r); | ||||
|  | ||||
|     return $this->formatWhereClause($where); | ||||
|   } | ||||
|  | ||||
|   public function getQueryApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingTransactionQuery | ||||
|   extends PhabricatorApplicationTransactionQuery { | ||||
|  | ||||
|   public function getTemplateApplicationTransaction() { | ||||
|     return new AlmanacBindingTransaction(); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -5,6 +5,8 @@ final class AlmanacDeviceQuery | ||||
|  | ||||
|   private $ids; | ||||
|   private $phids; | ||||
|   private $names; | ||||
|   private $datasourceQuery; | ||||
|  | ||||
|   public function withIDs(array $ids) { | ||||
|     $this->ids = $ids; | ||||
| @@ -16,6 +18,16 @@ final class AlmanacDeviceQuery | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withNames(array $names) { | ||||
|     $this->names = $names; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withDatasourceQuery($query) { | ||||
|     $this->datasourceQuery = $query; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   protected function loadPage() { | ||||
|     $table = new AlmanacDevice(); | ||||
|     $conn_r = $table->establishConnection('r'); | ||||
| @@ -48,6 +60,24 @@ final class AlmanacDeviceQuery | ||||
|         $this->phids); | ||||
|     } | ||||
|  | ||||
|     if ($this->names !== null) { | ||||
|       $hashes = array(); | ||||
|       foreach ($this->names as $name) { | ||||
|         $hashes[] = PhabricatorHash::digestForIndex($name); | ||||
|       } | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'nameIndex IN (%Ls)', | ||||
|         $hashes); | ||||
|     } | ||||
|  | ||||
|     if ($this->datasourceQuery !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'name LIKE %>', | ||||
|         $this->datasourceQuery); | ||||
|     } | ||||
|  | ||||
|     $where[] = $this->buildPagingClause($conn_r); | ||||
|  | ||||
|     return $this->formatWhereClause($where); | ||||
|   | ||||
							
								
								
									
										84
									
								
								src/applications/almanac/query/AlmanacDeviceSearchEngine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/applications/almanac/query/AlmanacDeviceSearchEngine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceSearchEngine | ||||
|   extends PhabricatorApplicationSearchEngine { | ||||
|  | ||||
|   public function getResultTypeDescription() { | ||||
|     return pht('Almanac Devices'); | ||||
|   } | ||||
|  | ||||
|   protected function getApplicationClassName() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function buildSavedQueryFromRequest(AphrontRequest $request) { | ||||
|     $saved = new PhabricatorSavedQuery(); | ||||
|  | ||||
|     return $saved; | ||||
|   } | ||||
|  | ||||
|   public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { | ||||
|     $query = id(new AlmanacDeviceQuery()); | ||||
|  | ||||
|     return $query; | ||||
|   } | ||||
|  | ||||
|   public function buildSearchForm( | ||||
|     AphrontFormView $form, | ||||
|     PhabricatorSavedQuery $saved_query) {} | ||||
|  | ||||
|   protected function getURI($path) { | ||||
|     return '/almanac/device/'.$path; | ||||
|   } | ||||
|  | ||||
|   public function getBuiltinQueryNames() { | ||||
|     $names = array( | ||||
|       'all' => pht('All Devices'), | ||||
|     ); | ||||
|  | ||||
|     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 getRequiredHandlePHIDsForResultList( | ||||
|     array $devices, | ||||
|     PhabricatorSavedQuery $query) { | ||||
|     return array(); | ||||
|   } | ||||
|  | ||||
|   protected function renderResultList( | ||||
|     array $devices, | ||||
|     PhabricatorSavedQuery $query, | ||||
|     array $handles) { | ||||
|     assert_instances_of($devices, 'AlmanacDevice'); | ||||
|  | ||||
|     $viewer = $this->requireViewer(); | ||||
|  | ||||
|     $list = new PHUIObjectItemListView(); | ||||
|     $list->setUser($viewer); | ||||
|     foreach ($devices as $device) { | ||||
|       $item = id(new PHUIObjectItemView()) | ||||
|         ->setObjectName(pht('Device %d', $device->getID())) | ||||
|         ->setHeader($device->getName()) | ||||
|         ->setHref($device->getURI()) | ||||
|         ->setObject($device); | ||||
|  | ||||
|       $list->addItem($item); | ||||
|     } | ||||
|  | ||||
|     return $list; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceTransactionQuery | ||||
|   extends PhabricatorApplicationTransactionQuery { | ||||
|  | ||||
|   public function getTemplateApplicationTransaction() { | ||||
|     return new AlmanacDeviceTransaction(); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										139
									
								
								src/applications/almanac/query/AlmanacInterfaceQuery.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/applications/almanac/query/AlmanacInterfaceQuery.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacInterfaceQuery | ||||
|   extends PhabricatorCursorPagedPolicyAwareQuery { | ||||
|  | ||||
|   private $ids; | ||||
|   private $phids; | ||||
|   private $networkPHIDs; | ||||
|   private $devicePHIDs; | ||||
|   private $addresses; | ||||
|  | ||||
|   public function withIDs(array $ids) { | ||||
|     $this->ids = $ids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withPHIDs(array $phids) { | ||||
|     $this->phids = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withNetworkPHIDs(array $phids) { | ||||
|     $this->networkPHIDs = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withDevicePHIDs(array $phids) { | ||||
|     $this->devicePHIDs = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withAddresses(array $addresses) { | ||||
|     $this->addresses = $addresses; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   protected function loadPage() { | ||||
|     $table = new AlmanacInterface(); | ||||
|     $conn_r = $table->establishConnection('r'); | ||||
|  | ||||
|     $data = queryfx_all( | ||||
|       $conn_r, | ||||
|       'SELECT * FROM %T %Q %Q %Q', | ||||
|       $table->getTableName(), | ||||
|       $this->buildWhereClause($conn_r), | ||||
|       $this->buildOrderClause($conn_r), | ||||
|       $this->buildLimitClause($conn_r)); | ||||
|  | ||||
|     return $table->loadAllFromArray($data); | ||||
|   } | ||||
|  | ||||
|   protected function willFilterPage(array $interfaces) { | ||||
|     $network_phids = mpull($interfaces, 'getNetworkPHID'); | ||||
|     $device_phids = mpull($interfaces, 'getDevicePHID'); | ||||
|  | ||||
|     $networks = id(new AlmanacNetworkQuery()) | ||||
|       ->setParentQuery($this) | ||||
|       ->setViewer($this->getViewer()) | ||||
|       ->withPHIDs($network_phids) | ||||
|       ->execute(); | ||||
|     $networks = mpull($networks, null, 'getPHID'); | ||||
|  | ||||
|     $devices = id(new AlmanacDeviceQuery()) | ||||
|       ->setParentQuery($this) | ||||
|       ->setViewer($this->getViewer()) | ||||
|       ->withPHIDs($device_phids) | ||||
|       ->execute(); | ||||
|     $devices = mpull($devices, null, 'getPHID'); | ||||
|  | ||||
|     foreach ($interfaces as $key => $interface) { | ||||
|       $network = idx($networks, $interface->getNetworkPHID()); | ||||
|       $device = idx($devices, $interface->getDevicePHID()); | ||||
|       if (!$network || !$device) { | ||||
|         $this->didRejectResult($interface); | ||||
|         unset($interfaces[$key]); | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       $interface->attachNetwork($network); | ||||
|       $interface->attachDevice($device); | ||||
|     } | ||||
|  | ||||
|     return $interfaces; | ||||
|   } | ||||
|  | ||||
|   protected function buildWhereClause($conn_r) { | ||||
|     $where = array(); | ||||
|  | ||||
|     if ($this->ids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'id IN (%Ld)', | ||||
|         $this->ids); | ||||
|     } | ||||
|  | ||||
|     if ($this->phids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'phid IN (%Ls)', | ||||
|         $this->phids); | ||||
|     } | ||||
|  | ||||
|     if ($this->networkPHIDs !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'networkPHID IN (%Ls)', | ||||
|         $this->networkPHIDs); | ||||
|     } | ||||
|  | ||||
|     if ($this->devicePHIDs !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'devicePHID IN (%Ls)', | ||||
|         $this->devicePHIDs); | ||||
|     } | ||||
|  | ||||
|     if ($this->addresses !== null) { | ||||
|       $parts = array(); | ||||
|       foreach ($this->addresses as $address) { | ||||
|         $parts[] = qsprintf( | ||||
|           $conn_r, | ||||
|           '(networkPHID = %s AND address = %s AND port = %d)', | ||||
|           $address->getNetworkPHID(), | ||||
|           $address->getAddress(), | ||||
|           $address->getPort()); | ||||
|       } | ||||
|       $where[] = implode(' OR ', $parts); | ||||
|     } | ||||
|  | ||||
|     $where[] = $this->buildPagingClause($conn_r); | ||||
|  | ||||
|     return $this->formatWhereClause($where); | ||||
|   } | ||||
|  | ||||
|   public function getQueryApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										60
									
								
								src/applications/almanac/query/AlmanacNetworkQuery.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/applications/almanac/query/AlmanacNetworkQuery.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkQuery | ||||
|   extends PhabricatorCursorPagedPolicyAwareQuery { | ||||
|  | ||||
|   private $ids; | ||||
|   private $phids; | ||||
|  | ||||
|   public function withIDs(array $ids) { | ||||
|     $this->ids = $ids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withPHIDs(array $phids) { | ||||
|     $this->phids = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   protected function loadPage() { | ||||
|     $table = new AlmanacNetwork(); | ||||
|     $conn_r = $table->establishConnection('r'); | ||||
|  | ||||
|     $data = queryfx_all( | ||||
|       $conn_r, | ||||
|       'SELECT * FROM %T %Q %Q %Q', | ||||
|       $table->getTableName(), | ||||
|       $this->buildWhereClause($conn_r), | ||||
|       $this->buildOrderClause($conn_r), | ||||
|       $this->buildLimitClause($conn_r)); | ||||
|  | ||||
|     return $table->loadAllFromArray($data); | ||||
|   } | ||||
|  | ||||
|   protected function buildWhereClause($conn_r) { | ||||
|     $where = array(); | ||||
|  | ||||
|     if ($this->ids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'id IN (%Ld)', | ||||
|         $this->ids); | ||||
|     } | ||||
|  | ||||
|     if ($this->phids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'phid IN (%Ls)', | ||||
|         $this->phids); | ||||
|     } | ||||
|  | ||||
|     $where[] = $this->buildPagingClause($conn_r); | ||||
|  | ||||
|     return $this->formatWhereClause($where); | ||||
|   } | ||||
|  | ||||
|   public function getQueryApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,85 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkSearchEngine | ||||
|   extends PhabricatorApplicationSearchEngine { | ||||
|  | ||||
|   public function getResultTypeDescription() { | ||||
|     return pht('Almanac Networks'); | ||||
|   } | ||||
|  | ||||
|   protected function getApplicationClassName() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function buildSavedQueryFromRequest(AphrontRequest $request) { | ||||
|     $saved = new PhabricatorSavedQuery(); | ||||
|  | ||||
|     return $saved; | ||||
|   } | ||||
|  | ||||
|   public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { | ||||
|     $query = id(new AlmanacNetworkQuery()); | ||||
|  | ||||
|     return $query; | ||||
|   } | ||||
|  | ||||
|   public function buildSearchForm( | ||||
|     AphrontFormView $form, | ||||
|     PhabricatorSavedQuery $saved_query) {} | ||||
|  | ||||
|   protected function getURI($path) { | ||||
|     return '/almanac/network/'.$path; | ||||
|   } | ||||
|  | ||||
|   public function getBuiltinQueryNames() { | ||||
|     $names = array( | ||||
|       'all' => pht('All Networks'), | ||||
|     ); | ||||
|  | ||||
|     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 getRequiredHandlePHIDsForResultList( | ||||
|     array $networks, | ||||
|     PhabricatorSavedQuery $query) { | ||||
|     return array(); | ||||
|   } | ||||
|  | ||||
|   protected function renderResultList( | ||||
|     array $networks, | ||||
|     PhabricatorSavedQuery $query, | ||||
|     array $handles) { | ||||
|     assert_instances_of($networks, 'AlmanacNetwork'); | ||||
|  | ||||
|     $viewer = $this->requireViewer(); | ||||
|  | ||||
|     $list = new PHUIObjectItemListView(); | ||||
|     $list->setUser($viewer); | ||||
|     foreach ($networks as $network) { | ||||
|       $id = $network->getID(); | ||||
|  | ||||
|       $item = id(new PHUIObjectItemView()) | ||||
|         ->setObjectName(pht('Network %d', $id)) | ||||
|         ->setHeader($network->getName()) | ||||
|         ->setHref($this->getApplicationURI("network/{$id}/")) | ||||
|         ->setObject($network); | ||||
|  | ||||
|       $list->addItem($item); | ||||
|     } | ||||
|  | ||||
|     return $list; | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkTransactionQuery | ||||
|   extends PhabricatorApplicationTransactionQuery { | ||||
|  | ||||
|   public function getTemplateApplicationTransaction() { | ||||
|     return new AlmanacNetworkTransaction(); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										78
									
								
								src/applications/almanac/query/AlmanacServiceQuery.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/applications/almanac/query/AlmanacServiceQuery.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceQuery | ||||
|   extends PhabricatorCursorPagedPolicyAwareQuery { | ||||
|  | ||||
|   private $ids; | ||||
|   private $phids; | ||||
|   private $names; | ||||
|  | ||||
|   public function withIDs(array $ids) { | ||||
|     $this->ids = $ids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withPHIDs(array $phids) { | ||||
|     $this->phids = $phids; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function withNames(array $names) { | ||||
|     $this->names = $names; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   protected function loadPage() { | ||||
|     $table = new AlmanacService(); | ||||
|     $conn_r = $table->establishConnection('r'); | ||||
|  | ||||
|     $data = queryfx_all( | ||||
|       $conn_r, | ||||
|       'SELECT * FROM %T %Q %Q %Q', | ||||
|       $table->getTableName(), | ||||
|       $this->buildWhereClause($conn_r), | ||||
|       $this->buildOrderClause($conn_r), | ||||
|       $this->buildLimitClause($conn_r)); | ||||
|  | ||||
|     return $table->loadAllFromArray($data); | ||||
|   } | ||||
|  | ||||
|   protected function buildWhereClause($conn_r) { | ||||
|     $where = array(); | ||||
|  | ||||
|     if ($this->ids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'id IN (%Ld)', | ||||
|         $this->ids); | ||||
|     } | ||||
|  | ||||
|     if ($this->phids !== null) { | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'phid IN (%Ls)', | ||||
|         $this->phids); | ||||
|     } | ||||
|  | ||||
|     if ($this->names !== null) { | ||||
|       $hashes = array(); | ||||
|       foreach ($this->names as $name) { | ||||
|         $hashes[] = PhabricatorHash::digestForIndex($name); | ||||
|       } | ||||
|  | ||||
|       $where[] = qsprintf( | ||||
|         $conn_r, | ||||
|         'nameIndex IN (%Ls)', | ||||
|         $hashes); | ||||
|     } | ||||
|  | ||||
|     $where[] = $this->buildPagingClause($conn_r); | ||||
|  | ||||
|     return $this->formatWhereClause($where); | ||||
|   } | ||||
|  | ||||
|   public function getQueryApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceSearchEngine | ||||
|   extends PhabricatorApplicationSearchEngine { | ||||
|  | ||||
|   public function getResultTypeDescription() { | ||||
|     return pht('Almanac Services'); | ||||
|   } | ||||
|  | ||||
|   protected function getApplicationClassName() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function buildSavedQueryFromRequest(AphrontRequest $request) { | ||||
|     $saved = new PhabricatorSavedQuery(); | ||||
|  | ||||
|     return $saved; | ||||
|   } | ||||
|  | ||||
|   public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { | ||||
|     $query = id(new AlmanacServiceQuery()); | ||||
|  | ||||
|     return $query; | ||||
|   } | ||||
|  | ||||
|   public function buildSearchForm( | ||||
|     AphrontFormView $form, | ||||
|     PhabricatorSavedQuery $saved_query) {} | ||||
|  | ||||
|   protected function getURI($path) { | ||||
|     return '/almanac/service/'.$path; | ||||
|   } | ||||
|  | ||||
|   public function getBuiltinQueryNames() { | ||||
|     $names = array( | ||||
|       'all' => pht('All Services'), | ||||
|     ); | ||||
|  | ||||
|     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 getRequiredHandlePHIDsForResultList( | ||||
|     array $services, | ||||
|     PhabricatorSavedQuery $query) { | ||||
|     return array(); | ||||
|   } | ||||
|  | ||||
|   protected function renderResultList( | ||||
|     array $services, | ||||
|     PhabricatorSavedQuery $query, | ||||
|     array $handles) { | ||||
|     assert_instances_of($services, 'AlmanacService'); | ||||
|  | ||||
|     $viewer = $this->requireViewer(); | ||||
|  | ||||
|     $list = new PHUIObjectItemListView(); | ||||
|     $list->setUser($viewer); | ||||
|     foreach ($services as $service) { | ||||
|       $item = id(new PHUIObjectItemView()) | ||||
|         ->setObjectName(pht('Service %d', $service->getID())) | ||||
|         ->setHeader($service->getName()) | ||||
|         ->setHref($service->getURI()) | ||||
|         ->setObject($service); | ||||
|  | ||||
|       $list->addItem($item); | ||||
|     } | ||||
|  | ||||
|     return $list; | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceTransactionQuery | ||||
|   extends PhabricatorApplicationTransactionQuery { | ||||
|  | ||||
|   public function getTemplateApplicationTransaction() { | ||||
|     return new AlmanacServiceTransaction(); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										112
									
								
								src/applications/almanac/storage/AlmanacBinding.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/applications/almanac/storage/AlmanacBinding.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBinding | ||||
|   extends AlmanacDAO | ||||
|   implements PhabricatorPolicyInterface { | ||||
|  | ||||
|   protected $servicePHID; | ||||
|   protected $devicePHID; | ||||
|   protected $interfacePHID; | ||||
|   protected $mailKey; | ||||
|  | ||||
|   private $service = self::ATTACHABLE; | ||||
|   private $device = self::ATTACHABLE; | ||||
|   private $interface = self::ATTACHABLE; | ||||
|  | ||||
|   public static function initializeNewBinding(AlmanacService $service) { | ||||
|     return id(new AlmanacBinding()) | ||||
|       ->setServicePHID($service->getPHID()); | ||||
|   } | ||||
|  | ||||
|   public function getConfiguration() { | ||||
|     return array( | ||||
|       self::CONFIG_AUX_PHID => true, | ||||
|       self::CONFIG_COLUMN_SCHEMA => array( | ||||
|         'mailKey' => 'bytes20', | ||||
|       ), | ||||
|       self::CONFIG_KEY_SCHEMA => array( | ||||
|         'key_service' => array( | ||||
|           'columns' => array('servicePHID', 'interfacePHID'), | ||||
|           'unique' => true, | ||||
|         ), | ||||
|         'key_device' => array( | ||||
|           'columns' => array('devicePHID'), | ||||
|         ), | ||||
|         'key_interface' => array( | ||||
|           'columns' => array('interfacePHID'), | ||||
|         ), | ||||
|       ), | ||||
|     ) + parent::getConfiguration(); | ||||
|   } | ||||
|  | ||||
|   public function generatePHID() { | ||||
|     return PhabricatorPHID::generateNewPHID(AlmanacBindingPHIDType::TYPECONST); | ||||
|   } | ||||
|  | ||||
|   public function save() { | ||||
|     if (!$this->mailKey) { | ||||
|       $this->mailKey = Filesystem::readRandomCharacters(20); | ||||
|     } | ||||
|     return parent::save(); | ||||
|   } | ||||
|  | ||||
|   public function getURI() { | ||||
|     return '/almanac/binding/'.$this->getID().'/'; | ||||
|   } | ||||
|  | ||||
|   public function getService() { | ||||
|     return $this->assertAttached($this->service); | ||||
|   } | ||||
|  | ||||
|   public function attachService(AlmanacService $service) { | ||||
|     $this->service = $service; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getDevice() { | ||||
|     return $this->assertAttached($this->device); | ||||
|   } | ||||
|  | ||||
|   public function attachDevice(AlmanacDevice $device) { | ||||
|     $this->device = $device; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getInterface() { | ||||
|     return $this->assertAttached($this->interface); | ||||
|   } | ||||
|  | ||||
|   public function attachInterface(AlmanacInterface $interface) { | ||||
|     $this->interface = $interface; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|  | ||||
| /* -(  PhabricatorPolicyInterface  )----------------------------------------- */ | ||||
|  | ||||
|  | ||||
|   public function getCapabilities() { | ||||
|     return array( | ||||
|       PhabricatorPolicyCapability::CAN_VIEW, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getPolicy($capability) { | ||||
|     return $this->getService()->getPolicy($capability); | ||||
|   } | ||||
|  | ||||
|   public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { | ||||
|     return $this->getService()->hasAutomaticCapability($capability, $viewer); | ||||
|   } | ||||
|  | ||||
|   public function describeAutomaticCapability($capability) { | ||||
|     return array( | ||||
|       pht('A binding inherits the policies of its service.'), | ||||
|       pht( | ||||
|         'To view a binding, you must also be able to view its device and '. | ||||
|         'interface.'), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,65 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingTransaction | ||||
|   extends PhabricatorApplicationTransaction { | ||||
|  | ||||
|   const TYPE_INTERFACE = 'almanac:binding:interface'; | ||||
|  | ||||
|   public function getApplicationName() { | ||||
|     return 'almanac'; | ||||
|   } | ||||
|  | ||||
|   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; | ||||
|     } | ||||
|  | ||||
|     return parent::getTitle(); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -5,12 +5,33 @@ final class AlmanacDevice | ||||
|   implements PhabricatorPolicyInterface { | ||||
|  | ||||
|   protected $name; | ||||
|   protected $nameIndex; | ||||
|   protected $mailKey; | ||||
|   protected $viewPolicy; | ||||
|   protected $editPolicy; | ||||
|  | ||||
|   public static function initializeNewDevice() { | ||||
|     return id(new AlmanacDevice()) | ||||
|       ->setViewPolicy(PhabricatorPolicies::POLICY_USER) | ||||
|       ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN); | ||||
|   } | ||||
|  | ||||
|   public function getConfiguration() { | ||||
|     return array( | ||||
|       self::CONFIG_AUX_PHID => true, | ||||
|       self::CONFIG_COLUMN_SCHEMA => array( | ||||
|         'name' => 'text255', | ||||
|         'name' => 'text128', | ||||
|         'nameIndex' => 'bytes12', | ||||
|         'mailKey' => 'bytes20', | ||||
|       ), | ||||
|       self::CONFIG_KEY_SCHEMA => array( | ||||
|         'key_name' => array( | ||||
|           'columns' => array('nameIndex'), | ||||
|           'unique' => true, | ||||
|         ), | ||||
|         'key_nametext' => array( | ||||
|           'columns' => array('name'), | ||||
|         ), | ||||
|       ), | ||||
|     ) + parent::getConfiguration(); | ||||
|   } | ||||
| @@ -19,6 +40,22 @@ final class AlmanacDevice | ||||
|     return PhabricatorPHID::generateNewPHID(AlmanacDevicePHIDType::TYPECONST); | ||||
|   } | ||||
|  | ||||
|   public function save() { | ||||
|     AlmanacNames::validateServiceOrDeviceName($this->getName()); | ||||
|  | ||||
|     $this->nameIndex = PhabricatorHash::digestForIndex($this->getName()); | ||||
|  | ||||
|     if (!$this->mailKey) { | ||||
|       $this->mailKey = Filesystem::readRandomCharacters(20); | ||||
|     } | ||||
|  | ||||
|     return parent::save(); | ||||
|   } | ||||
|  | ||||
|   public function getURI() { | ||||
|     return '/almanac/device/view/'.$this->getName().'/'; | ||||
|   } | ||||
|  | ||||
|  | ||||
| /* -(  PhabricatorPolicyInterface  )----------------------------------------- */ | ||||
|  | ||||
| @@ -26,16 +63,16 @@ final class AlmanacDevice | ||||
|   public function getCapabilities() { | ||||
|     return array( | ||||
|       PhabricatorPolicyCapability::CAN_VIEW, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getPolicy($capability) { | ||||
|     switch ($capability) { | ||||
|       case PhabricatorPolicyCapability::CAN_VIEW: | ||||
|         // Until we get a clearer idea on what's going to be stored in this | ||||
|         // table, don't allow anyone (other than the omnipotent user) to find | ||||
|         // these objects. | ||||
|         return PhabricatorPolicies::POLICY_NOONE; | ||||
|         return $this->getViewPolicy(); | ||||
|       case PhabricatorPolicyCapability::CAN_EDIT: | ||||
|         return $this->getEditPolicy(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										100
									
								
								src/applications/almanac/storage/AlmanacDeviceTransaction.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/applications/almanac/storage/AlmanacDeviceTransaction.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacDeviceTransaction | ||||
|   extends PhabricatorApplicationTransaction { | ||||
|  | ||||
|   const TYPE_NAME = 'almanac:device:name'; | ||||
|   const TYPE_INTERFACE = 'almanac:device:interface'; | ||||
|  | ||||
|   public function getApplicationName() { | ||||
|     return 'almanac'; | ||||
|   } | ||||
|  | ||||
|   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($new)); | ||||
|         } 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'])); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										103
									
								
								src/applications/almanac/storage/AlmanacInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/applications/almanac/storage/AlmanacInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacInterface | ||||
|   extends AlmanacDAO | ||||
|   implements PhabricatorPolicyInterface { | ||||
|  | ||||
|   protected $devicePHID; | ||||
|   protected $networkPHID; | ||||
|   protected $address; | ||||
|   protected $port; | ||||
|  | ||||
|   private $device = self::ATTACHABLE; | ||||
|   private $network = self::ATTACHABLE; | ||||
|  | ||||
|   public static function initializeNewInterface() { | ||||
|     return id(new AlmanacInterface()); | ||||
|   } | ||||
|  | ||||
|   public function getConfiguration() { | ||||
|     return array( | ||||
|       self::CONFIG_AUX_PHID => true, | ||||
|       self::CONFIG_COLUMN_SCHEMA => array( | ||||
|         'address' => 'text64', | ||||
|         'port' => 'uint32', | ||||
|       ), | ||||
|       self::CONFIG_KEY_SCHEMA => array( | ||||
|         'key_location' => array( | ||||
|           'columns' => array('networkPHID', 'address', 'port'), | ||||
|         ), | ||||
|         'key_device' => array( | ||||
|           'columns' => array('devicePHID'), | ||||
|         ), | ||||
|       ), | ||||
|     ) + parent::getConfiguration(); | ||||
|   } | ||||
|  | ||||
|   public function generatePHID() { | ||||
|     return PhabricatorPHID::generateNewPHID( | ||||
|       AlmanacInterfacePHIDType::TYPECONST); | ||||
|   } | ||||
|  | ||||
|   public function getDevice() { | ||||
|     return $this->assertAttached($this->device); | ||||
|   } | ||||
|  | ||||
|   public function attachDevice(AlmanacDevice $device) { | ||||
|     $this->device = $device; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getNetwork() { | ||||
|     return $this->assertAttached($this->network); | ||||
|   } | ||||
|  | ||||
|   public function attachNetwork(AlmanacNetwork $network) { | ||||
|     $this->network = $network; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function toAddress() { | ||||
|     return AlmanacAddress::newFromParts( | ||||
|       $this->getNetworkPHID(), | ||||
|       $this->getAddress(), | ||||
|       $this->getPort()); | ||||
|   } | ||||
|  | ||||
|   public function getAddressHash() { | ||||
|     return $this->toAddress()->toHash(); | ||||
|   } | ||||
|  | ||||
|   public function renderDisplayAddress() { | ||||
|     return $this->getAddress().':'.$this->getPort(); | ||||
|   } | ||||
|  | ||||
|  | ||||
| /* -(  PhabricatorPolicyInterface  )----------------------------------------- */ | ||||
|  | ||||
|  | ||||
|   public function getCapabilities() { | ||||
|     return array( | ||||
|       PhabricatorPolicyCapability::CAN_VIEW, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getPolicy($capability) { | ||||
|     return $this->getDevice()->getPolicy($capability); | ||||
|   } | ||||
|  | ||||
|   public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { | ||||
|     return $this->getDevice()->hasAutomaticCapability($capability, $viewer); | ||||
|   } | ||||
|  | ||||
|   public function describeAutomaticCapability($capability) { | ||||
|     return array( | ||||
|       pht('An interface inherits the policies of the device it belongs to.'), | ||||
|       pht( | ||||
|         'You must be able to view the network an interface resides on to '. | ||||
|         'view the interface.'), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										72
									
								
								src/applications/almanac/storage/AlmanacNetwork.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/applications/almanac/storage/AlmanacNetwork.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetwork | ||||
|   extends AlmanacDAO | ||||
|   implements PhabricatorPolicyInterface { | ||||
|  | ||||
|   protected $name; | ||||
|   protected $mailKey; | ||||
|   protected $viewPolicy; | ||||
|   protected $editPolicy; | ||||
|  | ||||
|   public static function initializeNewNetwork() { | ||||
|     return id(new AlmanacNetwork()) | ||||
|       ->setViewPolicy(PhabricatorPolicies::POLICY_USER) | ||||
|       ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN); | ||||
|   } | ||||
|  | ||||
|   public function getConfiguration() { | ||||
|     return array( | ||||
|       self::CONFIG_AUX_PHID => true, | ||||
|       self::CONFIG_COLUMN_SCHEMA => array( | ||||
|         'name' => 'text128', | ||||
|         'mailKey' => 'bytes20', | ||||
|       ), | ||||
|     ) + parent::getConfiguration(); | ||||
|   } | ||||
|  | ||||
|   public function generatePHID() { | ||||
|     return PhabricatorPHID::generateNewPHID(AlmanacNetworkPHIDType::TYPECONST); | ||||
|   } | ||||
|  | ||||
|   public function save() { | ||||
|     if (!$this->mailKey) { | ||||
|       $this->mailKey = Filesystem::readRandomCharacters(20); | ||||
|     } | ||||
|  | ||||
|     return parent::save(); | ||||
|   } | ||||
|  | ||||
|   public function getURI() { | ||||
|     return '/almanac/network/view/'.$this->getName().'/'; | ||||
|   } | ||||
|  | ||||
|  | ||||
| /* -(  PhabricatorPolicyInterface  )----------------------------------------- */ | ||||
|  | ||||
|  | ||||
|   public function getCapabilities() { | ||||
|     return array( | ||||
|       PhabricatorPolicyCapability::CAN_VIEW, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getPolicy($capability) { | ||||
|     switch ($capability) { | ||||
|       case PhabricatorPolicyCapability::CAN_VIEW: | ||||
|         return $this->getViewPolicy(); | ||||
|       case PhabricatorPolicyCapability::CAN_EDIT: | ||||
|         return $this->getEditPolicy(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   public function describeAutomaticCapability($capability) { | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNetworkTransaction | ||||
|   extends PhabricatorApplicationTransaction { | ||||
|  | ||||
|   const TYPE_NAME = 'almanac:network:name'; | ||||
|  | ||||
|   public function getApplicationName() { | ||||
|     return 'almanac'; | ||||
|   } | ||||
|  | ||||
|   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 self::TYPE_NAME: | ||||
|         if ($old === null) { | ||||
|           return pht( | ||||
|             '%s created this network.', | ||||
|             $this->renderHandleLink($author_phid)); | ||||
|         } else { | ||||
|           return pht( | ||||
|             '%s renamed this network from "%s" to "%s".', | ||||
|             $this->renderHandleLink($author_phid), | ||||
|             $old, | ||||
|             $new); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     return parent::getTitle(); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/applications/almanac/storage/AlmanacService.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/applications/almanac/storage/AlmanacService.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacService | ||||
|   extends AlmanacDAO | ||||
|   implements PhabricatorPolicyInterface { | ||||
|  | ||||
|   protected $name; | ||||
|   protected $nameIndex; | ||||
|   protected $mailKey; | ||||
|   protected $viewPolicy; | ||||
|   protected $editPolicy; | ||||
|  | ||||
|   public static function initializeNewService() { | ||||
|     return id(new AlmanacService()) | ||||
|       ->setViewPolicy(PhabricatorPolicies::POLICY_USER) | ||||
|       ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN); | ||||
|   } | ||||
|  | ||||
|   public function getConfiguration() { | ||||
|     return array( | ||||
|       self::CONFIG_AUX_PHID => true, | ||||
|       self::CONFIG_COLUMN_SCHEMA => array( | ||||
|         'name' => 'text128', | ||||
|         'nameIndex' => 'bytes12', | ||||
|         'mailKey' => 'bytes20', | ||||
|       ), | ||||
|       self::CONFIG_KEY_SCHEMA => array( | ||||
|         'key_name' => array( | ||||
|           'columns' => array('nameIndex'), | ||||
|           'unique' => true, | ||||
|         ), | ||||
|         'key_nametext' => array( | ||||
|           'columns' => array('name'), | ||||
|         ), | ||||
|       ), | ||||
|     ) + parent::getConfiguration(); | ||||
|   } | ||||
|  | ||||
|   public function generatePHID() { | ||||
|     return PhabricatorPHID::generateNewPHID(AlmanacServicePHIDType::TYPECONST); | ||||
|   } | ||||
|  | ||||
|   public function save() { | ||||
|     AlmanacNames::validateServiceOrDeviceName($this->getName()); | ||||
|  | ||||
|     $this->nameIndex = PhabricatorHash::digestForIndex($this->getName()); | ||||
|  | ||||
|     if (!$this->mailKey) { | ||||
|       $this->mailKey = Filesystem::readRandomCharacters(20); | ||||
|     } | ||||
|  | ||||
|     return parent::save(); | ||||
|   } | ||||
|  | ||||
|   public function getURI() { | ||||
|     return '/almanac/service/view/'.$this->getName().'/'; | ||||
|   } | ||||
|  | ||||
| /* -(  PhabricatorPolicyInterface  )----------------------------------------- */ | ||||
|  | ||||
|  | ||||
|   public function getCapabilities() { | ||||
|     return array( | ||||
|       PhabricatorPolicyCapability::CAN_VIEW, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function getPolicy($capability) { | ||||
|     switch ($capability) { | ||||
|       case PhabricatorPolicyCapability::CAN_VIEW: | ||||
|         return $this->getViewPolicy(); | ||||
|       case PhabricatorPolicyCapability::CAN_EDIT: | ||||
|         return $this->getEditPolicy(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   public function describeAutomaticCapability($capability) { | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacServiceTransaction | ||||
|   extends PhabricatorApplicationTransaction { | ||||
|  | ||||
|   const TYPE_NAME = 'almanac:service:name'; | ||||
|  | ||||
|   public function getApplicationName() { | ||||
|     return 'almanac'; | ||||
|   } | ||||
|  | ||||
|   public function getApplicationTransactionType() { | ||||
|     return AlmanacServicePHIDType::TYPECONST; | ||||
|   } | ||||
|  | ||||
|   public function getApplicationTransactionCommentObject() { | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   public function getTitle() { | ||||
|     $author_phid = $this->getAuthorPHID(); | ||||
|  | ||||
|     $old = $this->getOldValue(); | ||||
|     $new = $this->getNewValue(); | ||||
|  | ||||
|     switch ($this->getTransactionType()) { | ||||
|       case self::TYPE_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; | ||||
|     } | ||||
|  | ||||
|     return parent::getTitle(); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacInterfaceDatasource | ||||
|   extends PhabricatorTypeaheadDatasource { | ||||
|  | ||||
|   public function getPlaceholderText() { | ||||
|     return pht('Type an interface name...'); | ||||
|   } | ||||
|  | ||||
|   public function getDatasourceApplicationClass() { | ||||
|     return 'PhabricatorAlmanacApplication'; | ||||
|   } | ||||
|  | ||||
|   public function loadResults() { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $raw_query = $this->getRawQuery(); | ||||
|  | ||||
|     $devices = id(new AlmanacDeviceQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withDatasourceQuery($raw_query) | ||||
|       ->execute(); | ||||
|  | ||||
|     if ($devices) { | ||||
|       $interfaces = id(new AlmanacInterfaceQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withDevicePHIDs(mpull($devices, 'getPHID')) | ||||
|         ->execute(); | ||||
|     } else { | ||||
|       $interfaces = array(); | ||||
|     } | ||||
|  | ||||
|     if ($interfaces) { | ||||
|       $handles = id(new PhabricatorHandleQuery()) | ||||
|         ->setViewer($viewer) | ||||
|         ->withPHIDs(mpull($interfaces, 'getPHID')) | ||||
|         ->execute(); | ||||
|     } else { | ||||
|       $handles = array(); | ||||
|     } | ||||
|  | ||||
|     $results = array(); | ||||
|     foreach ($handles as $handle) { | ||||
|       $results[] = id(new PhabricatorTypeaheadResult()) | ||||
|         ->setName($handle->getName()) | ||||
|         ->setPHID($handle->getPHID()); | ||||
|     } | ||||
|  | ||||
|     return $results; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										54
									
								
								src/applications/almanac/util/AlmanacAddress.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/applications/almanac/util/AlmanacAddress.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacAddress extends Phobject { | ||||
|  | ||||
|   private $networkPHID; | ||||
|   private $address; | ||||
|   private $port; | ||||
|  | ||||
|   private function __construct() { | ||||
|     // <private> | ||||
|   } | ||||
|  | ||||
|   public function getNetworkPHID() { | ||||
|     return $this->networkPHID; | ||||
|   } | ||||
|  | ||||
|   public function getAddress() { | ||||
|     return $this->address; | ||||
|   } | ||||
|  | ||||
|   public function getPort() { | ||||
|     return $this->port; | ||||
|   } | ||||
|  | ||||
|   public static function newFromDictionary(array $dictionary) { | ||||
|     return self::newFromParts( | ||||
|       $dictionary['networkPHID'], | ||||
|       $dictionary['address'], | ||||
|       $dictionary['port']); | ||||
|   } | ||||
|  | ||||
|   public static function newFromParts($network_phid, $address, $port) { | ||||
|     $addr = new AlmanacAddress(); | ||||
|  | ||||
|     $addr->networkPHID = $network_phid; | ||||
|     $addr->address = $address; | ||||
|     $addr->port = (int)$port; | ||||
|  | ||||
|     return $addr; | ||||
|   } | ||||
|  | ||||
|   public function toDictionary() { | ||||
|     return array( | ||||
|       'networkPHID' => $this->getNetworkPHID(), | ||||
|       'address' => $this->getAddress(), | ||||
|       'port' => $this->getPort(), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public function toHash() { | ||||
|     return PhabricatorHash::digestForIndex(json_encode($this->toDictionary())); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/applications/almanac/util/AlmanacNames.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/applications/almanac/util/AlmanacNames.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNames extends Phobject { | ||||
|  | ||||
|   public static function validateServiceOrDeviceName($name) { | ||||
|     if (strlen($name) < 3) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Almanac service and device names must be at least 3 '. | ||||
|           'characters long.')); | ||||
|     } | ||||
|  | ||||
|     if (!preg_match('/^[a-z0-9.-]+\z/', $name)) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Almanac service and device names may only contain lowercase '. | ||||
|           'letters, numbers, hyphens, and periods.')); | ||||
|     } | ||||
|  | ||||
|     if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Almanac service and device names may not have any segments '. | ||||
|           'containing only digits.')); | ||||
|     } | ||||
|  | ||||
|     if (preg_match('/\.\./', $name)) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Almanac service and device names may not contain multiple '. | ||||
|           'consecutive periods.')); | ||||
|     } | ||||
|  | ||||
|     if (preg_match('/\\.-|-\\./', $name)) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Amanac service and device names may not contain hyphens adjacent '. | ||||
|           'to periods.')); | ||||
|     } | ||||
|  | ||||
|     if (preg_match('/--/', $name)) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Almanac service and device names may not contain multiple '. | ||||
|           'consecutive hyphens.')); | ||||
|     } | ||||
|  | ||||
|     if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) { | ||||
|       throw new Exception( | ||||
|         pht( | ||||
|           'Almanac service and device names must begin and end with a letter '. | ||||
|           'or number.')); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacNamesTestCase extends PhabricatorTestCase { | ||||
|  | ||||
|   public function testServiceOrDeviceNames() { | ||||
|     $map = array( | ||||
|       '' => false, | ||||
|       'a' => false, | ||||
|       'ab' => false, | ||||
|       '...' => false, | ||||
|       'ab.' => false, | ||||
|       '.ab' => false, | ||||
|       'A-B' => false, | ||||
|       'A!B' => false, | ||||
|       'A.B' => false, | ||||
|       'a..b' => false, | ||||
|       '1.2' => false, | ||||
|       '127.0.0.1' => false, | ||||
|       '1.b' => false, | ||||
|       'a.1' => false, | ||||
|       'a.1.b' => false, | ||||
|       '-.a' => false, | ||||
|       '-a.b' => false, | ||||
|       'a-.b' => false, | ||||
|       'a.-' => false, | ||||
|       'a.-b' => false, | ||||
|       'a.b-' => false, | ||||
|       '-.-' => false, | ||||
|       'a--b' => false, | ||||
|  | ||||
|       'abc' => true, | ||||
|       'a.b' => true, | ||||
|       'db.phacility.instance' => true, | ||||
|       'web002.useast.example.com' => true, | ||||
|       'master.example-corp.com' => true, | ||||
|     ); | ||||
|  | ||||
|     foreach ($map as $input => $expect) { | ||||
|       $caught = null; | ||||
|       try { | ||||
|         AlmanacNames::validateServiceOrDeviceName($input); | ||||
|       } catch (Exception $ex) { | ||||
|         $caught = $ex; | ||||
|       } | ||||
|       $this->assertEqual( | ||||
|         $expect, | ||||
|         !($caught instanceof Exception), | ||||
|         $input); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/applications/almanac/view/AlmanacBindingTableView.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/applications/almanac/view/AlmanacBindingTableView.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacBindingTableView extends AphrontView { | ||||
|  | ||||
|   private $bindings; | ||||
|   private $handles; | ||||
|   private $noDataString; | ||||
|  | ||||
|   public function setNoDataString($no_data_string) { | ||||
|     $this->noDataString = $no_data_string; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getNoDataString() { | ||||
|     return $this->noDataString; | ||||
|   } | ||||
|  | ||||
|   public function setHandles(array $handles) { | ||||
|     $this->handles = $handles; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getHandles() { | ||||
|     return $this->handles; | ||||
|   } | ||||
|  | ||||
|   public function setBindings(array $bindings) { | ||||
|     $this->bindings = $bindings; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getBindings() { | ||||
|     return $this->bindings; | ||||
|   } | ||||
|  | ||||
|   public function render() { | ||||
|     $bindings = $this->getBindings(); | ||||
|     $handles = $this->getHandles(); | ||||
|     $viewer = $this->getUser(); | ||||
|  | ||||
|     $rows = array(); | ||||
|     foreach ($bindings as $binding) { | ||||
|       $addr = $binding->getInterface()->getAddress(); | ||||
|       $port = $binding->getInterface()->getPort(); | ||||
|  | ||||
|       $rows[] = array( | ||||
|         $binding->getID(), | ||||
|         $handles[$binding->getServicePHID()]->renderLink(), | ||||
|         $handles[$binding->getDevicePHID()]->renderLink(), | ||||
|         $handles[$binding->getInterface()->getNetworkPHID()]->renderLink(), | ||||
|         $binding->getInterface()->renderDisplayAddress(), | ||||
|         phutil_tag( | ||||
|           'a', | ||||
|           array( | ||||
|             'class' => 'small grey button', | ||||
|             'href' => '/almanac/binding/'.$binding->getID().'/', | ||||
|           ), | ||||
|           pht('Details')), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     $table = id(new AphrontTableView($rows)) | ||||
|       ->setNoDataString($this->getNoDataString()) | ||||
|       ->setHeaders( | ||||
|         array( | ||||
|           pht('ID'), | ||||
|           pht('Service'), | ||||
|           pht('Device'), | ||||
|           pht('Network'), | ||||
|           pht('Interface'), | ||||
|           null, | ||||
|         )) | ||||
|       ->setColumnClasses( | ||||
|         array( | ||||
|           '', | ||||
|           '', | ||||
|           '', | ||||
|           '', | ||||
|           'wide', | ||||
|           'action', | ||||
|         )); | ||||
|  | ||||
|     return $table; | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										69
									
								
								src/applications/almanac/view/AlmanacInterfaceTableView.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/applications/almanac/view/AlmanacInterfaceTableView.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <?php | ||||
|  | ||||
| final class AlmanacInterfaceTableView extends AphrontView { | ||||
|  | ||||
|   private $interfaces; | ||||
|   private $handles; | ||||
|  | ||||
|   public function setHandles(array $handles) { | ||||
|     $this->handles = $handles; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getHandles() { | ||||
|     return $this->handles; | ||||
|   } | ||||
|  | ||||
|   public function setInterfaces(array $interfaces) { | ||||
|     $this->interfaces = $interfaces; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getInterfaces() { | ||||
|     return $this->interfaces; | ||||
|   } | ||||
|  | ||||
|   public function render() { | ||||
|     $interfaces = $this->getInterfaces(); | ||||
|     $handles = $this->getHandles(); | ||||
|     $viewer = $this->getUser(); | ||||
|  | ||||
|     $rows = array(); | ||||
|     foreach ($interfaces as $interface) { | ||||
|       $rows[] = array( | ||||
|         $interface->getID(), | ||||
|         $handles[$interface->getNetworkPHID()]->renderLink(), | ||||
|         $interface->getAddress(), | ||||
|         $interface->getPort(), | ||||
|         phutil_tag( | ||||
|           'a', | ||||
|           array( | ||||
|             'class' => 'small grey button', | ||||
|             'href' => '/almanac/interface/edit/'.$interface->getID().'/', | ||||
|           ), | ||||
|           pht('Edit')), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     $table = id(new AphrontTableView($rows)) | ||||
|       ->setHeaders( | ||||
|         array( | ||||
|           pht('ID'), | ||||
|           pht('Network'), | ||||
|           pht('Address'), | ||||
|           pht('Port'), | ||||
|           null, | ||||
|         )) | ||||
|       ->setColumnClasses( | ||||
|         array( | ||||
|           '', | ||||
|           'wide', | ||||
|           '', | ||||
|           '', | ||||
|           'action', | ||||
|         )); | ||||
|  | ||||
|     return $table; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -38,18 +38,50 @@ final class PhabricatorAuditStatusConstants { | ||||
|         $color = 'red'; | ||||
|         break; | ||||
|       case self::AUDIT_REQUIRED: | ||||
|       case self::AUDIT_REQUESTED: | ||||
|         $color = 'orange'; | ||||
|         break; | ||||
|       case self::ACCEPTED: | ||||
|         $color = 'green'; | ||||
|         break; | ||||
|       case self::AUDIT_NOT_REQUIRED: | ||||
|         $color = 'blue'; | ||||
|         break; | ||||
|       case self::RESIGNED: | ||||
|       case self::CLOSED: | ||||
|         $color = 'dark'; | ||||
|         break; | ||||
|       default: | ||||
|         $color = null; | ||||
|         $color = 'bluegrey'; | ||||
|         break; | ||||
|     } | ||||
|     return $color; | ||||
|   } | ||||
|  | ||||
|   public static function getStatusIcon($code) { | ||||
|     switch ($code) { | ||||
|       case PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED: | ||||
|       case PhabricatorAuditStatusConstants::RESIGNED: | ||||
|         $icon = PHUIStatusItemView::ICON_OPEN; | ||||
|         break; | ||||
|       case PhabricatorAuditStatusConstants::AUDIT_REQUIRED: | ||||
|       case PhabricatorAuditStatusConstants::AUDIT_REQUESTED: | ||||
|         $icon = PHUIStatusItemView::ICON_WARNING; | ||||
|         break; | ||||
|       case PhabricatorAuditStatusConstants::CONCERNED: | ||||
|         $icon = PHUIStatusItemView::ICON_REJECT; | ||||
|         break; | ||||
|       case PhabricatorAuditStatusConstants::ACCEPTED: | ||||
|       case PhabricatorAuditStatusConstants::CLOSED: | ||||
|         $icon = PHUIStatusItemView::ICON_ACCEPT; | ||||
|         break; | ||||
|       default: | ||||
|         $icon = PHUIStatusItemView::ICON_QUESTION; | ||||
|         break; | ||||
|     } | ||||
|     return $icon; | ||||
|   } | ||||
|  | ||||
|   public static function getOpenStatusConstants() { | ||||
|     return array( | ||||
|       self::AUDIT_REQUIRED, | ||||
|   | ||||
| @@ -3,22 +3,13 @@ | ||||
| final class PhabricatorAuditListController | ||||
|   extends PhabricatorAuditController { | ||||
|  | ||||
|   private $queryKey; | ||||
|   private $name; | ||||
|   private $filterStatus; | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function willProcessRequest(array $data) { | ||||
|     $this->queryKey = idx($data, 'queryKey'); | ||||
|   } | ||||
|  | ||||
|   public function processRequest() { | ||||
|     $request = $this->getRequest(); | ||||
|     $controller = id(new PhabricatorApplicationSearchController($request)) | ||||
|       ->setQueryKey($this->queryKey) | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $controller = id(new PhabricatorApplicationSearchController()) | ||||
|       ->setQueryKey($request->getURIData('queryKey')) | ||||
|       ->setSearchEngine(new PhabricatorCommitSearchEngine()) | ||||
|       ->setNavigation($this->buildSideNavView()); | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,42 @@ | ||||
| final class PhabricatorAuditEditor | ||||
|   extends PhabricatorApplicationTransactionEditor { | ||||
|  | ||||
|   const MAX_FILES_SHOWN_IN_EMAIL = 1000; | ||||
|  | ||||
|   private $auditReasonMap = array(); | ||||
|   private $heraldEmailPHIDs = array(); | ||||
|   private $affectedFiles; | ||||
|   private $rawPatch; | ||||
|  | ||||
|   public function addAuditReason($phid, $reason) { | ||||
|     if (!isset($this->auditReasonMap[$phid])) { | ||||
|       $this->auditReasonMap[$phid] = array(); | ||||
|     } | ||||
|     $this->auditReasonMap[$phid][] = $reason; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   private function getAuditReasons($phid) { | ||||
|     if (isset($this->auditReasonMap[$phid])) { | ||||
|       return $this->auditReasonMap[$phid]; | ||||
|     } | ||||
|     if ($this->getIsHeraldEditor()) { | ||||
|       $name = 'herald'; | ||||
|     } else { | ||||
|       $name = $this->getActor()->getUsername(); | ||||
|     } | ||||
|     return array('Added by '.$name.'.'); | ||||
|   } | ||||
|  | ||||
|   public function setRawPatch($patch) { | ||||
|     $this->rawPatch = $patch; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getRawPatch() { | ||||
|     return $this->rawPatch; | ||||
|   } | ||||
|  | ||||
|   public function getEditorApplicationClass() { | ||||
|     return 'PhabricatorAuditApplication'; | ||||
|   } | ||||
| @@ -17,6 +53,8 @@ final class PhabricatorAuditEditor | ||||
|     $types[] = PhabricatorTransactions::TYPE_COMMENT; | ||||
|     $types[] = PhabricatorTransactions::TYPE_EDGE; | ||||
|  | ||||
|     $types[] = PhabricatorAuditTransaction::TYPE_COMMIT; | ||||
|  | ||||
|     // TODO: These will get modernized eventually, but that can happen one | ||||
|     // at a time later on. | ||||
|     $types[] = PhabricatorAuditActionConstants::ACTION; | ||||
| @@ -44,6 +82,7 @@ final class PhabricatorAuditEditor | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case PhabricatorAuditActionConstants::ACTION: | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|         return null; | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|         // TODO: For now, just record the added PHIDs. Eventually, turn these | ||||
| @@ -62,6 +101,7 @@ final class PhabricatorAuditEditor | ||||
|       case PhabricatorAuditActionConstants::ACTION: | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|         return $xaction->getNewValue(); | ||||
|     } | ||||
|  | ||||
| @@ -79,6 +119,7 @@ final class PhabricatorAuditEditor | ||||
|       case PhabricatorAuditActionConstants::ACTION: | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| @@ -95,6 +136,7 @@ final class PhabricatorAuditEditor | ||||
|       case PhabricatorTransactions::TYPE_EDGE: | ||||
|       case PhabricatorAuditActionConstants::ACTION: | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|         return; | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|         $new = $xaction->getNewValue(); | ||||
| @@ -118,15 +160,19 @@ final class PhabricatorAuditEditor | ||||
|             continue; | ||||
|           } | ||||
|  | ||||
|           $audit_requested = PhabricatorAuditStatusConstants::AUDIT_REQUESTED; | ||||
|           if ($this->getIsHeraldEditor()) { | ||||
|             $audit_requested = $xaction->getMetadataValue('auditStatus'); | ||||
|             $audit_reason_map = $xaction->getMetadataValue('auditReasonMap'); | ||||
|             $audit_reason = $audit_reason_map[$phid]; | ||||
|           } else { | ||||
|             $audit_requested = PhabricatorAuditStatusConstants::AUDIT_REQUESTED; | ||||
|             $audit_reason = $this->getAuditReasons($phid); | ||||
|           } | ||||
|           $requests[] = id (new PhabricatorRepositoryAuditRequest()) | ||||
|             ->setCommitPHID($object->getPHID()) | ||||
|             ->setAuditorPHID($phid) | ||||
|             ->setAuditStatus($audit_requested) | ||||
|             ->setAuditReasons( | ||||
|               array( | ||||
|                 'Added by '.$actor->getUsername(), | ||||
|               )) | ||||
|             ->setAuditReasons($audit_reason) | ||||
|             ->save(); | ||||
|         } | ||||
|  | ||||
| @@ -165,8 +211,12 @@ final class PhabricatorAuditEditor | ||||
|     $actor_is_author = ($object->getAuthorPHID()) && | ||||
|       ($actor_phid == $object->getAuthorPHID()); | ||||
|  | ||||
|     $import_status_flag = null; | ||||
|     foreach ($xactions as $xaction) { | ||||
|       switch ($xaction->getTransactionType()) { | ||||
|         case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|           $import_status_flag = PhabricatorRepositoryCommit::IMPORTED_HERALD; | ||||
|           break; | ||||
|         case PhabricatorAuditActionConstants::ACTION: | ||||
|           $new = $xaction->getNewValue(); | ||||
|           switch ($new) { | ||||
| @@ -265,9 +315,67 @@ final class PhabricatorAuditEditor | ||||
|     $object->updateAuditStatus($requests); | ||||
|     $object->save(); | ||||
|  | ||||
|     if ($import_status_flag) { | ||||
|       $object->writeImportStatusFlag($import_status_flag); | ||||
|     } | ||||
|  | ||||
|     return $xactions; | ||||
|   } | ||||
|  | ||||
|   protected function expandTransaction( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     PhabricatorApplicationTransaction $xaction) { | ||||
|  | ||||
|     $xactions = parent::expandTransaction($object, $xaction); | ||||
|     switch ($xaction->getTransactionType()) { | ||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|         $request = $this->createAuditRequestTransactionFromCommitMessage( | ||||
|           $object); | ||||
|         if ($request) { | ||||
|           $xactions[] = $request; | ||||
|           $this->setUnmentionablePHIDMap($request->getNewValue()); | ||||
|         } | ||||
|         break; | ||||
|       default: | ||||
|         break; | ||||
|     } | ||||
|     return $xactions; | ||||
|   } | ||||
|  | ||||
|   private function createAuditRequestTransactionFromCommitMessage( | ||||
|     PhabricatorRepositoryCommit $commit) { | ||||
|  | ||||
|     $data = $commit->getCommitData(); | ||||
|     $message = $data->getCommitMessage(); | ||||
|  | ||||
|     $matches = null; | ||||
|     if (!preg_match('/^Auditors:\s*(.*)$/im', $message, $matches)) { | ||||
|       return array(); | ||||
|     } | ||||
|  | ||||
|     $phids = id(new PhabricatorObjectListQuery()) | ||||
|       ->setViewer($this->getActor()) | ||||
|       ->setAllowPartialResults(true) | ||||
|       ->setAllowedTypes( | ||||
|         array( | ||||
|           PhabricatorPeopleUserPHIDType::TYPECONST, | ||||
|           PhabricatorProjectProjectPHIDType::TYPECONST, | ||||
|         )) | ||||
|       ->setObjectList($matches[1]) | ||||
|       ->execute(); | ||||
|  | ||||
|     if (!$phids) { | ||||
|       return array(); | ||||
|     } | ||||
|  | ||||
|     foreach ($phids as $phid) { | ||||
|       $this->addAuditReason($phid, 'Requested by Author'); | ||||
|     } | ||||
|     return id(new PhabricatorAuditTransaction()) | ||||
|       ->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS) | ||||
|       ->setNewValue(array_fuse($phids)); | ||||
|   } | ||||
|  | ||||
|   protected function sortTransactions(array $xactions) { | ||||
|     $xactions = parent::sortTransactions($xactions); | ||||
|  | ||||
| @@ -353,9 +461,75 @@ final class PhabricatorAuditEditor | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   protected function expandCustomRemarkupBlockTransactions( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     array $xactions, | ||||
|     $blocks, | ||||
|     PhutilMarkupEngine $engine) { | ||||
|  | ||||
|     // we are only really trying to find unmentionable phids here... | ||||
|     // don't bother with this outside initial commit (i.e. create) | ||||
|     // transaction | ||||
|     $is_commit = false; | ||||
|     foreach ($xactions as $xaction) { | ||||
|       switch ($xaction->getTransactionType()) { | ||||
|         case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|           $is_commit = true; | ||||
|           break; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // "result" is always an array.... | ||||
|     $result = array(); | ||||
|     if (!$is_commit) { | ||||
|       return $result; | ||||
|     } | ||||
|  | ||||
|     $flat_blocks = array_mergev($blocks); | ||||
|     $huge_block = implode("\n\n", $flat_blocks); | ||||
|     $phid_map = array(); | ||||
|     $phid_map[] = $this->getUnmentionablePHIDMap(); | ||||
|     $monograms = array(); | ||||
|  | ||||
|     $task_refs = id(new ManiphestCustomFieldStatusParser()) | ||||
|       ->parseCorpus($huge_block); | ||||
|     foreach ($task_refs as $match) { | ||||
|       foreach ($match['monograms'] as $monogram) { | ||||
|         $monograms[] = $monogram; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $rev_refs = id(new DifferentialCustomFieldDependsOnParser()) | ||||
|       ->parseCorpus($huge_block); | ||||
|     foreach ($rev_refs as $match) { | ||||
|       foreach ($match['monograms'] as $monogram) { | ||||
|         $monograms[] = $monogram; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $objects = id(new PhabricatorObjectQuery()) | ||||
|       ->setViewer($this->getActor()) | ||||
|       ->withNames($monograms) | ||||
|       ->execute(); | ||||
|     $phid_map[] = mpull($objects, 'getPHID', 'getPHID'); | ||||
|     $phid_map = array_mergev($phid_map); | ||||
|     $this->setUnmentionablePHIDMap($phid_map); | ||||
|  | ||||
|     return $result; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   protected function shouldSendMail( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     array $xactions) { | ||||
|  | ||||
|     // not every code path loads the repository so tread carefully | ||||
|     if ($object->getRepository($assert_attached = false)) { | ||||
|       $repository = $object->getRepository(); | ||||
|       if ($repository->isImporting()) { | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
|     return $this->isCommitMostlyImported($object); | ||||
|   } | ||||
|  | ||||
| @@ -386,13 +560,23 @@ final class PhabricatorAuditEditor | ||||
|     $subject = "{$name}: {$summary}"; | ||||
|     $thread_topic = "Commit {$monogram}{$identifier}"; | ||||
|  | ||||
|     return id(new PhabricatorMetaMTAMail()) | ||||
|     $template = id(new PhabricatorMetaMTAMail()) | ||||
|       ->setSubject($subject) | ||||
|       ->addHeader('Thread-Topic', $thread_topic); | ||||
|  | ||||
|     $this->attachPatch( | ||||
|       $template, | ||||
|       $object); | ||||
|  | ||||
|     return $template; | ||||
|   } | ||||
|  | ||||
|   protected function getMailTo(PhabricatorLiskDAO $object) { | ||||
|     $phids = array(); | ||||
|     if ($this->heraldEmailPHIDs) { | ||||
|       $phids = $this->heraldEmailPHIDs; | ||||
|     } | ||||
|  | ||||
|     if ($object->getAuthorPHID()) { | ||||
|       $phids[] = $object->getAuthorPHID(); | ||||
|     } | ||||
| @@ -414,12 +598,17 @@ final class PhabricatorAuditEditor | ||||
|     $body = parent::buildMailBody($object, $xactions); | ||||
|  | ||||
|     $type_inline = PhabricatorAuditActionConstants::INLINE; | ||||
|     $type_push = PhabricatorAuditTransaction::TYPE_COMMIT; | ||||
|  | ||||
|     $is_commit = false; | ||||
|     $inlines = array(); | ||||
|     foreach ($xactions as $xaction) { | ||||
|       if ($xaction->getTransactionType() == $type_inline) { | ||||
|         $inlines[] = $xaction; | ||||
|       } | ||||
|       if ($xaction->getTransactionType() == $type_push) { | ||||
|         $is_commit = true; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if ($inlines) { | ||||
| @@ -428,6 +617,14 @@ final class PhabricatorAuditEditor | ||||
|         $this->renderInlineCommentsForMail($object, $inlines)); | ||||
|     } | ||||
|  | ||||
|     if ($is_commit) { | ||||
|       $data = $object->getCommitData(); | ||||
|       $body->addTextSection(pht('AFFECTED FILES'), $this->affectedFiles); | ||||
|       $this->inlinePatch( | ||||
|         $body, | ||||
|         $object); | ||||
|     } | ||||
|  | ||||
|     // Reload the commit to pull commit data. | ||||
|     $commit = id(new DiffusionCommitQuery()) | ||||
|       ->setViewer($this->requireActor()) | ||||
| @@ -440,7 +637,7 @@ final class PhabricatorAuditEditor | ||||
|  | ||||
|     $author_phid = $commit->getAuthorPHID(); | ||||
|     if ($author_phid) { | ||||
|       $user_phids[$commit->getAuthorPHID()][] = pht('Author'); | ||||
|       $user_phids[$author_phid][] = pht('Author'); | ||||
|     } | ||||
|  | ||||
|     $committer_phid = $data->getCommitDetail('committerPHID'); | ||||
| @@ -448,6 +645,13 @@ final class PhabricatorAuditEditor | ||||
|       $user_phids[$committer_phid][] = pht('Committer'); | ||||
|     } | ||||
|  | ||||
|     // we loaded this in applyFinalEffects | ||||
|     $audit_requests = $object->getAudits(); | ||||
|     $auditor_phids = mpull($audit_requests, 'getAuditorPHID'); | ||||
|     foreach ($auditor_phids as $auditor_phid) { | ||||
|       $user_phids[$auditor_phid][] = pht('Auditor'); | ||||
|     } | ||||
|  | ||||
|     // TODO: It would be nice to show pusher here too, but that information | ||||
|     // is a little tricky to get at right now. | ||||
|  | ||||
| @@ -474,13 +678,75 @@ final class PhabricatorAuditEditor | ||||
|     $monogram = $object->getRepository()->formatCommitName( | ||||
|       $object->getCommitIdentifier()); | ||||
|  | ||||
|     $body->addTextSection( | ||||
|     $body->addLinkSection( | ||||
|       pht('COMMIT'), | ||||
|       PhabricatorEnv::getProductionURI('/'.$monogram)); | ||||
|  | ||||
|     return $body; | ||||
|   } | ||||
|  | ||||
|   private function attachPatch( | ||||
|     PhabricatorMetaMTAMail $template, | ||||
|     PhabricatorRepositoryCommit $commit) { | ||||
|  | ||||
|     if (!$this->getRawPatch()) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     $attach_key = 'metamta.diffusion.attach-patches'; | ||||
|     $attach_patches = PhabricatorEnv::getEnvConfig($attach_key); | ||||
|     if (!$attach_patches) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     $repository = $commit->getRepository(); | ||||
|     $encoding = $repository->getDetail('encoding', 'UTF-8'); | ||||
|  | ||||
|     $raw_patch = $this->getRawPatch(); | ||||
|     $commit_name = $repository->formatCommitName( | ||||
|       $commit->getCommitIdentifier()); | ||||
|  | ||||
|     $template->addAttachment( | ||||
|       new PhabricatorMetaMTAAttachment( | ||||
|         $raw_patch, | ||||
|         $commit_name.'.patch', | ||||
|         'text/x-patch; charset='.$encoding)); | ||||
|   } | ||||
|  | ||||
|   private function inlinePatch( | ||||
|     PhabricatorMetaMTAMailBody $body, | ||||
|     PhabricatorRepositoryCommit $commit) { | ||||
|  | ||||
|     if (!$this->getRawPatch()) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     $inline_key = 'metamta.diffusion.inline-patches'; | ||||
|     $inline_patches = PhabricatorEnv::getEnvConfig($inline_key); | ||||
|     if (!$inline_patches) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     $repository = $commit->getRepository(); | ||||
|     $raw_patch = $this->getRawPatch(); | ||||
|     $result = null; | ||||
|     $len = substr_count($raw_patch, "\n"); | ||||
|     if ($len <= $inline_patches) { | ||||
|       // We send email as utf8, so we need to convert the text to utf8 if | ||||
|       // we can. | ||||
|       $encoding = $repository->getDetail('encoding', 'UTF-8'); | ||||
|       if ($encoding) { | ||||
|         $raw_patch = phutil_utf8_convert($raw_patch, 'UTF-8', $encoding); | ||||
|       } | ||||
|       $result = phutil_utf8ize($raw_patch); | ||||
|     } | ||||
|  | ||||
|     if ($result) { | ||||
|       $result = "PATCH\n\n{$result}\n"; | ||||
|     } | ||||
|     $body->addRawSection($result); | ||||
|   } | ||||
|  | ||||
|   private function renderInlineCommentsForMail( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     array $inline_xactions) { | ||||
| @@ -515,10 +781,127 @@ final class PhabricatorAuditEditor | ||||
|     return implode("\n", $block); | ||||
|   } | ||||
|  | ||||
|   public function getMailTagsMap() { | ||||
|     return array( | ||||
|       PhabricatorAuditTransaction::MAILTAG_COMMIT => | ||||
|         pht('A commit is created.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_ACTION_CONCERN => | ||||
|         pht('A commit has a concerned raised against it.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_ACTION_ACCEPT => | ||||
|         pht('A commit is accepted.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_ACTION_RESIGN => | ||||
|         pht('A commit has an auditor resign.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_ACTION_CLOSE => | ||||
|         pht('A commit is closed.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_ADD_AUDITORS => | ||||
|         pht('A commit has auditors added.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_ADD_CCS => | ||||
|         pht("A commit's subscribers change."), | ||||
|       PhabricatorAuditTransaction::MAILTAG_PROJECTS => | ||||
|         pht("A commit's projects change."), | ||||
|       PhabricatorAuditTransaction::MAILTAG_COMMENT => | ||||
|         pht('Someone comments on a commit.'), | ||||
|       PhabricatorAuditTransaction::MAILTAG_OTHER => | ||||
|         pht('Other commit activity not listed above occurs.'), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
|   protected function shouldPublishFeedStory( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     array $xactions) { | ||||
|     return $this->isCommitMostlyImported($object); | ||||
|     return $this->shouldSendMail($object, $xactions); | ||||
|   } | ||||
|  | ||||
|   protected function shouldApplyHeraldRules( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     array $xactions) { | ||||
|  | ||||
|     foreach ($xactions as $xaction) { | ||||
|       switch ($xaction->getTransactionType()) { | ||||
|         case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||
|           $repository = $object->getRepository(); | ||||
|           if ($repository->isImporting()) { | ||||
|             return false; | ||||
|           } | ||||
|           if ($repository->getDetail('herald-disabled')) { | ||||
|             return false; | ||||
|           } | ||||
|           return true; | ||||
|         default: | ||||
|           break; | ||||
|       } | ||||
|     } | ||||
|     return parent::shouldApplyHeraldRules($object, $xactions); | ||||
|   } | ||||
|  | ||||
|   protected function buildHeraldAdapter( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     array $xactions) { | ||||
|  | ||||
|     return id(new HeraldCommitAdapter()) | ||||
|       ->setCommit($object); | ||||
|   } | ||||
|  | ||||
|   protected function didApplyHeraldRules( | ||||
|     PhabricatorLiskDAO $object, | ||||
|     HeraldAdapter $adapter, | ||||
|     HeraldTranscript $transcript) { | ||||
|  | ||||
|     $xactions = array(); | ||||
|  | ||||
|     $audit_phids = $adapter->getAuditMap(); | ||||
|     foreach ($audit_phids as $phid => $rule_ids) { | ||||
|       foreach ($rule_ids as $rule_id) { | ||||
|         $this->addAuditReason( | ||||
|           $phid, | ||||
|           pht( | ||||
|             '%s Triggered Audit', | ||||
|             "H{$rule_id}")); | ||||
|       } | ||||
|     } | ||||
|     if ($audit_phids) { | ||||
|       $xactions[] = id(new PhabricatorAuditTransaction()) | ||||
|         ->setTransactionType(PhabricatorAuditActionConstants::ADD_AUDITORS) | ||||
|         ->setNewValue(array_fuse(array_keys($audit_phids))) | ||||
|         ->setMetadataValue( | ||||
|           'auditStatus', | ||||
|           PhabricatorAuditStatusConstants::AUDIT_REQUIRED) | ||||
|         ->setMetadataValue( | ||||
|           'auditReasonMap', $this->auditReasonMap); | ||||
|     } | ||||
|  | ||||
|     $cc_phids = $adapter->getAddCCMap(); | ||||
|     $add_ccs = array('+' => array()); | ||||
|     foreach ($cc_phids as $phid => $rule_ids) { | ||||
|       $add_ccs['+'][$phid] = $phid; | ||||
|     } | ||||
|     $xactions[] = id(new PhabricatorAuditTransaction()) | ||||
|       ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) | ||||
|       ->setNewValue($add_ccs); | ||||
|  | ||||
|     $this->heraldEmailPHIDs = $adapter->getEmailPHIDs(); | ||||
|  | ||||
|     HarbormasterBuildable::applyBuildPlans( | ||||
|       $object->getPHID(), | ||||
|       $object->getRepository()->getPHID(), | ||||
|       $adapter->getBuildPlans()); | ||||
|  | ||||
|     $limit = self::MAX_FILES_SHOWN_IN_EMAIL; | ||||
|     $files = $adapter->loadAffectedPaths(); | ||||
|     sort($files); | ||||
|     if (count($files) > $limit) { | ||||
|       array_splice($files, $limit); | ||||
|       $files[] = pht( | ||||
|         '(This commit affected more than %d files. Only %d are shown here '. | ||||
|         'and additional ones are truncated.)', | ||||
|         $limit, | ||||
|         $limit); | ||||
|     } | ||||
|     $this->affectedFiles = implode("\n", $files); | ||||
|  | ||||
|     return $xactions; | ||||
|   } | ||||
|  | ||||
|   private function isCommitMostlyImported(PhabricatorLiskDAO $object) { | ||||
|   | ||||
| @@ -3,6 +3,19 @@ | ||||
| final class PhabricatorAuditTransaction | ||||
|   extends PhabricatorApplicationTransaction { | ||||
|  | ||||
|   const TYPE_COMMIT = 'audit:commit'; | ||||
|  | ||||
|   const MAILTAG_ACTION_CONCERN = 'audit-action-concern'; | ||||
|   const MAILTAG_ACTION_ACCEPT  = 'audit-action-accept'; | ||||
|   const MAILTAG_ACTION_RESIGN  = 'audit-action-resign'; | ||||
|   const MAILTAG_ACTION_CLOSE   = 'audit-action-close'; | ||||
|   const MAILTAG_ADD_AUDITORS   = 'audit-add-auditors'; | ||||
|   const MAILTAG_ADD_CCS        = 'audit-add-ccs'; | ||||
|   const MAILTAG_COMMENT        = 'audit-comment'; | ||||
|   const MAILTAG_COMMIT         = 'audit-commit'; | ||||
|   const MAILTAG_PROJECTS       = 'audit-projects'; | ||||
|   const MAILTAG_OTHER          = 'audit-other'; | ||||
|  | ||||
|   public function getApplicationName() { | ||||
|     return 'audit'; | ||||
|   } | ||||
| @@ -15,12 +28,35 @@ final class PhabricatorAuditTransaction | ||||
|     return new PhabricatorAuditTransactionComment(); | ||||
|   } | ||||
|  | ||||
|   public function getRemarkupBlocks() { | ||||
|     $blocks = parent::getRemarkupBlocks(); | ||||
|  | ||||
|     switch ($this->getTransactionType()) { | ||||
|     case self::TYPE_COMMIT: | ||||
|       $data = $this->getNewValue(); | ||||
|       $blocks[] = $data['description']; | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|     return $blocks; | ||||
|   } | ||||
|  | ||||
|   public function getRequiredHandlePHIDs() { | ||||
|     $phids = parent::getRequiredHandlePHIDs(); | ||||
|  | ||||
|     $type = $this->getTransactionType(); | ||||
|  | ||||
|     switch ($type) { | ||||
|       case self::TYPE_COMMIT: | ||||
|         $phids[] = $this->getObjectPHID(); | ||||
|         $data = $this->getNewValue(); | ||||
|         if ($data['authorPHID']) { | ||||
|           $phids[] = $data['authorPHID']; | ||||
|         } | ||||
|         if ($data['committerPHID']) { | ||||
|           $phids[] = $data['committerPHID']; | ||||
|         } | ||||
|         break; | ||||
|       case PhabricatorAuditActionConstants::ADD_CCS: | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|         $old = $this->getOldValue(); | ||||
| @@ -59,6 +95,8 @@ final class PhabricatorAuditTransaction | ||||
|         break; | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|         return pht('Added Auditors'); | ||||
|       case self::TYPE_COMMIT: | ||||
|         return pht('Committed'); | ||||
|     } | ||||
|  | ||||
|     return parent::getActionName(); | ||||
| @@ -104,10 +142,47 @@ final class PhabricatorAuditTransaction | ||||
|     } | ||||
|  | ||||
|     switch ($type) { | ||||
|       case self::TYPE_COMMIT: | ||||
|         $author = null; | ||||
|         if ($new['authorPHID']) { | ||||
|           $author = $this->renderHandleLink($new['authorPHID']); | ||||
|         } else { | ||||
|           $author = $new['authorName']; | ||||
|         } | ||||
|  | ||||
|         $committer = null; | ||||
|         if ($new['committerPHID']) { | ||||
|           $committer = $this->renderHandleLink($new['committerPHID']); | ||||
|         } else if ($new['committerName']) { | ||||
|           $committer = $new['committerName']; | ||||
|         } | ||||
|  | ||||
|         $commit = $this->renderHandleLink($this->getObjectPHID()); | ||||
|  | ||||
|         if (!$committer) { | ||||
|           $committer = $author; | ||||
|           $author = null; | ||||
|         } | ||||
|  | ||||
|         if ($author) { | ||||
|           $title = pht( | ||||
|             '%s committed %s (authored by %s).', | ||||
|             $committer, | ||||
|             $commit, | ||||
|             $author); | ||||
|         } else { | ||||
|           $title = pht( | ||||
|             '%s committed %s.', | ||||
|             $committer, | ||||
|             $commit); | ||||
|         } | ||||
|         return $title; | ||||
|  | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|         return pht( | ||||
|           '%s added inline comments.', | ||||
|           $author_handle); | ||||
|  | ||||
|       case PhabricatorAuditActionConstants::ADD_CCS: | ||||
|         if ($add && $rem) { | ||||
|           return pht( | ||||
| @@ -203,6 +278,40 @@ final class PhabricatorAuditTransaction | ||||
|     } | ||||
|  | ||||
|     switch ($type) { | ||||
|       case self::TYPE_COMMIT: | ||||
|         $author = null; | ||||
|         if ($new['authorPHID']) { | ||||
|           $author = $this->renderHandleLink($new['authorPHID']); | ||||
|         } else { | ||||
|           $author = $new['authorName']; | ||||
|         } | ||||
|  | ||||
|         $committer = null; | ||||
|         if ($new['committerPHID']) { | ||||
|           $committer = $this->renderHandleLink($new['committerPHID']); | ||||
|         } else if ($new['committerName']) { | ||||
|           $committer = $new['committerName']; | ||||
|         } | ||||
|  | ||||
|         if (!$committer) { | ||||
|           $committer = $author; | ||||
|           $author = null; | ||||
|         } | ||||
|  | ||||
|         if ($author) { | ||||
|           $title = pht( | ||||
|             '%s committed %s (authored by %s).', | ||||
|             $committer, | ||||
|             $object_handle, | ||||
|             $author); | ||||
|         } else { | ||||
|           $title = pht( | ||||
|             '%s committed %s.', | ||||
|             $committer, | ||||
|             $object_handle); | ||||
|         } | ||||
|         return $title; | ||||
|  | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|         return pht( | ||||
|           '%s added inline comments to %s.', | ||||
| @@ -265,6 +374,15 @@ final class PhabricatorAuditTransaction | ||||
|     return parent::getTitleForFeed($story); | ||||
|   } | ||||
|  | ||||
|   public function getBodyForFeed(PhabricatorFeedStory $story) { | ||||
|     switch ($this->getTransactionType()) { | ||||
|       case self::TYPE_COMMIT: | ||||
|         $data = $this->getNewValue(); | ||||
|         return $story->renderSummary($data['summary']); | ||||
|     } | ||||
|     return parent::getBodyForFeed($story); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   // TODO: These two mail methods can likely be abstracted by introducing a | ||||
|   // formal concept of "inline comment" transactions. | ||||
| @@ -288,9 +406,63 @@ final class PhabricatorAuditTransaction | ||||
|     switch ($this->getTransactionType()) { | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|         return null; | ||||
|       case self::TYPE_COMMIT: | ||||
|         $data = $this->getNewValue(); | ||||
|         return $data['description']; | ||||
|     } | ||||
|  | ||||
|     return parent::getBodyForMail(); | ||||
|   } | ||||
|  | ||||
|   public function getMailTags() { | ||||
|     $tags = array(); | ||||
|     switch ($this->getTransactionType()) { | ||||
|       case PhabricatorAuditActionConstants::ACTION: | ||||
|         switch ($this->getNewValue()) { | ||||
|           case PhabricatorAuditActionConstants::CONCERN: | ||||
|             $tags[] = self::MAILTAG_ACTION_CONCERN; | ||||
|             break; | ||||
|           case PhabricatorAuditActionConstants::ACCEPT: | ||||
|             $tags[] = self::MAILTAG_ACTION_ACCEPT; | ||||
|             break; | ||||
|           case PhabricatorAuditActionConstants::RESIGN: | ||||
|             $tags[] = self::MAILTAG_ACTION_RESIGN; | ||||
|             break; | ||||
|           case PhabricatorAuditActionConstants::CLOSE: | ||||
|             $tags[] = self::MAILTAG_ACTION_CLOSE; | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|       case PhabricatorAuditActionConstants::ADD_AUDITORS: | ||||
|         $tags[] = self::MAILTAG_ADD_AUDITORS; | ||||
|         break; | ||||
|       case PhabricatorAuditActionConstants::ADD_CCS: | ||||
|         $tags[] = self::MAILTAG_ADD_CCS; | ||||
|         break; | ||||
|       case PhabricatorAuditActionConstants::INLINE: | ||||
|       case PhabricatorTransactions::TYPE_COMMENT: | ||||
|         $tags[] = self::MAILTAG_COMMENT; | ||||
|         break; | ||||
|       case self::TYPE_COMMIT: | ||||
|         $tags[] = self::MAILTAG_COMMIT; | ||||
|         break; | ||||
|       case PhabricatorTransactions::TYPE_EDGE: | ||||
|         switch ($this->getMetadataValue('edge:type')) { | ||||
|           case PhabricatorProjectObjectHasProjectEdgeType::EDGECONST: | ||||
|             $tags[] = self::MAILTAG_PROJECTS; | ||||
|             break; | ||||
|           case PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER: | ||||
|             $tags[] = self::MAILTAG_ADD_CCS; | ||||
|             break; | ||||
|           default: | ||||
|             $tags[] = self::MAILTAG_OTHER; | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|       default: | ||||
|         $tags[] = self::MAILTAG_OTHER; | ||||
|         break; | ||||
|     } | ||||
|     return $tags; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -137,11 +137,11 @@ abstract class PhabricatorController extends AphrontController { | ||||
|  | ||||
|     if ($this->shouldRequireEnabledUser()) { | ||||
|       if ($user->isLoggedIn() && !$user->getIsApproved()) { | ||||
|         $controller = new PhabricatorAuthNeedsApprovalController($request); | ||||
|         $controller = new PhabricatorAuthNeedsApprovalController(); | ||||
|         return $this->delegateToController($controller); | ||||
|       } | ||||
|       if ($user->getIsDisabled()) { | ||||
|         $controller = new PhabricatorDisabledUserController($request); | ||||
|         $controller = new PhabricatorDisabledUserController(); | ||||
|         return $this->delegateToController($controller); | ||||
|       } | ||||
|     } | ||||
| @@ -166,7 +166,7 @@ abstract class PhabricatorController extends AphrontController { | ||||
|     if (!$this->shouldAllowPartialSessions()) { | ||||
|       if ($user->hasSession() && | ||||
|           $user->getSession()->getIsPartial()) { | ||||
|         $login_controller = new PhabricatorAuthFinishController($request); | ||||
|         $login_controller = new PhabricatorAuthFinishController(); | ||||
|         $this->setCurrentApplication($auth_application); | ||||
|         return $this->delegateToController($login_controller); | ||||
|       } | ||||
| @@ -180,8 +180,7 @@ abstract class PhabricatorController extends AphrontController { | ||||
|       // and require MFA enrollment. | ||||
|       $user->updateMultiFactorEnrollment(); | ||||
|       if (!$user->getIsEnrolledInMultiFactor()) { | ||||
|         $mfa_controller = new PhabricatorAuthNeedsMultiFactorController( | ||||
|           $request); | ||||
|         $mfa_controller = new PhabricatorAuthNeedsMultiFactorController(); | ||||
|         $this->setCurrentApplication($auth_application); | ||||
|         return $this->delegateToController($mfa_controller); | ||||
|       } | ||||
| @@ -198,7 +197,7 @@ abstract class PhabricatorController extends AphrontController { | ||||
|       // If this controller isn't public, and the user isn't logged in, require | ||||
|       // login. | ||||
|       if (!$allow_public && !$user->isLoggedIn()) { | ||||
|         $login_controller = new PhabricatorAuthStartController($request); | ||||
|         $login_controller = new PhabricatorAuthStartController(); | ||||
|         $this->setCurrentApplication($auth_application); | ||||
|         return $this->delegateToController($login_controller); | ||||
|       } | ||||
| @@ -206,7 +205,7 @@ abstract class PhabricatorController extends AphrontController { | ||||
|       if ($user->isLoggedIn()) { | ||||
|         if ($this->shouldRequireEmailVerification()) { | ||||
|           if (!$user->getIsEmailVerified()) { | ||||
|             $controller = new PhabricatorMustVerifyEmailController($request); | ||||
|             $controller = new PhabricatorMustVerifyEmailController(); | ||||
|             $this->setCurrentApplication($auth_application); | ||||
|             return $this->delegateToController($controller); | ||||
|           } | ||||
|   | ||||
| @@ -22,7 +22,8 @@ final class PhabricatorAccessControlTestCase extends PhabricatorTestCase { | ||||
|       ->setApplicationConfiguration($application_configuration) | ||||
|       ->setRequestData(array()); | ||||
|  | ||||
|     $controller = new PhabricatorTestController($request); | ||||
|     $controller = new PhabricatorTestController(); | ||||
|     $controller->setRequest($request); | ||||
|  | ||||
|     $u_public = id(new PhabricatorUser()) | ||||
|       ->setUsername('public'); | ||||
|   | ||||
| @@ -14,8 +14,7 @@ final class PhabricatorCalendarEventListController | ||||
|   } | ||||
|  | ||||
|   public function processRequest() { | ||||
|     $request = $this->getRequest(); | ||||
|     $controller = id(new PhabricatorApplicationSearchController($request)) | ||||
|     $controller = id(new PhabricatorApplicationSearchController()) | ||||
|       ->setQueryKey($this->queryKey) | ||||
|       ->setSearchEngine(new PhabricatorCalendarEventSearchEngine()) | ||||
|       ->setNavigation($this->buildSideNav()); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user