mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-24 12:39:04 +01:00
(stable) Promote 2020 Week 6
This commit is contained in:
commit
ff6f24db2b
61 changed files with 1761 additions and 965 deletions
|
@ -9,7 +9,7 @@ return array(
|
|||
'names' => array(
|
||||
'conpherence.pkg.css' => '3c8a0668',
|
||||
'conpherence.pkg.js' => '020aebcf',
|
||||
'core.pkg.css' => 'ad8fc332',
|
||||
'core.pkg.css' => '5edb4679',
|
||||
'core.pkg.js' => '705aec2c',
|
||||
'differential.pkg.css' => '607c84be',
|
||||
'differential.pkg.js' => '1b97518d',
|
||||
|
@ -146,6 +146,7 @@ return array(
|
|||
'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
|
||||
'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
|
||||
'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf',
|
||||
'rsrc/css/phui/phui-curtain-object-ref-view.css' => '12404744',
|
||||
'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6',
|
||||
'rsrc/css/phui/phui-document-pro.css' => 'b9613a10',
|
||||
'rsrc/css/phui/phui-document-summary.css' => 'b068eed1',
|
||||
|
@ -165,7 +166,7 @@ return array(
|
|||
'rsrc/css/phui/phui-left-right.css' => '68513c34',
|
||||
'rsrc/css/phui/phui-lightbox.css' => '4ebf22da',
|
||||
'rsrc/css/phui/phui-list.css' => 'b05144dd',
|
||||
'rsrc/css/phui/phui-object-box.css' => 'f434b6be',
|
||||
'rsrc/css/phui/phui-object-box.css' => 'b8d7eea0',
|
||||
'rsrc/css/phui/phui-pager.css' => 'd022c7ad',
|
||||
'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8',
|
||||
'rsrc/css/phui/phui-policy-section-view.css' => '139fdc64',
|
||||
|
@ -176,7 +177,7 @@ return array(
|
|||
'rsrc/css/phui/phui-status.css' => 'e5ff8be0',
|
||||
'rsrc/css/phui/phui-tag-view.css' => '8519160a',
|
||||
'rsrc/css/phui/phui-timeline-view.css' => '1e348e4b',
|
||||
'rsrc/css/phui/phui-two-column-view.css' => '0a876b9e',
|
||||
'rsrc/css/phui/phui-two-column-view.css' => 'f96d319f',
|
||||
'rsrc/css/phui/workboards/phui-workboard-color.css' => 'e86de308',
|
||||
'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98',
|
||||
'rsrc/css/phui/workboards/phui-workcard.css' => '913441b6',
|
||||
|
@ -833,6 +834,7 @@ return array(
|
|||
'phui-comment-form-css' => '68a2d99a',
|
||||
'phui-comment-panel-css' => 'ec4e31c0',
|
||||
'phui-crumbs-view-css' => '614f43cf',
|
||||
'phui-curtain-object-ref-view-css' => '12404744',
|
||||
'phui-curtain-view-css' => '68c5efb6',
|
||||
'phui-document-summary-view-css' => 'b068eed1',
|
||||
'phui-document-view-css' => '52b748a5',
|
||||
|
@ -855,7 +857,7 @@ return array(
|
|||
'phui-left-right-css' => '68513c34',
|
||||
'phui-lightbox-css' => '4ebf22da',
|
||||
'phui-list-view-css' => 'b05144dd',
|
||||
'phui-object-box-css' => 'f434b6be',
|
||||
'phui-object-box-css' => 'b8d7eea0',
|
||||
'phui-oi-big-ui-css' => 'fa74cc35',
|
||||
'phui-oi-color-css' => 'b517bfa0',
|
||||
'phui-oi-drag-ui-css' => 'da15d3dc',
|
||||
|
@ -873,7 +875,7 @@ return array(
|
|||
'phui-tag-view-css' => '8519160a',
|
||||
'phui-theme-css' => '35883b37',
|
||||
'phui-timeline-view-css' => '1e348e4b',
|
||||
'phui-two-column-view-css' => '0a876b9e',
|
||||
'phui-two-column-view-css' => 'f96d319f',
|
||||
'phui-workboard-color-css' => 'e86de308',
|
||||
'phui-workboard-view-css' => '74fc9d98',
|
||||
'phui-workcard-view-css' => '913441b6',
|
||||
|
|
|
@ -1991,6 +1991,8 @@ phutil_register_library_map(array(
|
|||
'PHUICrumbView' => 'view/phui/PHUICrumbView.php',
|
||||
'PHUICrumbsView' => 'view/phui/PHUICrumbsView.php',
|
||||
'PHUICurtainExtension' => 'view/extension/PHUICurtainExtension.php',
|
||||
'PHUICurtainObjectRefListView' => 'view/phui/PHUICurtainObjectRefListView.php',
|
||||
'PHUICurtainObjectRefView' => 'view/phui/PHUICurtainObjectRefView.php',
|
||||
'PHUICurtainPanelView' => 'view/layout/PHUICurtainPanelView.php',
|
||||
'PHUICurtainView' => 'view/layout/PHUICurtainView.php',
|
||||
'PHUIDiffGraphView' => 'infrastructure/diff/view/PHUIDiffGraphView.php',
|
||||
|
@ -2037,8 +2039,10 @@ phutil_register_library_map(array(
|
|||
'PHUIInfoView' => 'view/phui/PHUIInfoView.php',
|
||||
'PHUIInvisibleCharacterTestCase' => 'view/phui/__tests__/PHUIInvisibleCharacterTestCase.php',
|
||||
'PHUIInvisibleCharacterView' => 'view/phui/PHUIInvisibleCharacterView.php',
|
||||
'PHUILauncherView' => 'view/phui/PHUILauncherView.php',
|
||||
'PHUILeftRightExample' => 'applications/uiexample/examples/PHUILeftRightExample.php',
|
||||
'PHUILeftRightView' => 'view/phui/PHUILeftRightView.php',
|
||||
'PHUILinkView' => 'view/phui/PHUILinkView.php',
|
||||
'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php',
|
||||
'PHUIListItemView' => 'view/phui/PHUIListItemView.php',
|
||||
'PHUIListView' => 'view/phui/PHUIListView.php',
|
||||
|
@ -2798,46 +2802,42 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitTokenQuery' => 'applications/conduit/query/PhabricatorConduitTokenQuery.php',
|
||||
'PhabricatorConduitTokenTerminateController' => 'applications/conduit/controller/PhabricatorConduitTokenTerminateController.php',
|
||||
'PhabricatorConduitTokensSettingsPanel' => 'applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php',
|
||||
'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php',
|
||||
'PhabricatorConfigApplication' => 'applications/config/application/PhabricatorConfigApplication.php',
|
||||
'PhabricatorConfigApplicationController' => 'applications/config/controller/PhabricatorConfigApplicationController.php',
|
||||
'PhabricatorConfigCacheController' => 'applications/config/controller/PhabricatorConfigCacheController.php',
|
||||
'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/PhabricatorConfigClusterDatabasesController.php',
|
||||
'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/PhabricatorConfigClusterNotificationsController.php',
|
||||
'PhabricatorConfigClusterRepositoriesController' => 'applications/config/controller/PhabricatorConfigClusterRepositoriesController.php',
|
||||
'PhabricatorConfigClusterSearchController' => 'applications/config/controller/PhabricatorConfigClusterSearchController.php',
|
||||
'PhabricatorConfigCacheController' => 'applications/config/controller/services/PhabricatorConfigCacheController.php',
|
||||
'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/services/PhabricatorConfigClusterDatabasesController.php',
|
||||
'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/services/PhabricatorConfigClusterNotificationsController.php',
|
||||
'PhabricatorConfigClusterRepositoriesController' => 'applications/config/controller/services/PhabricatorConfigClusterRepositoriesController.php',
|
||||
'PhabricatorConfigClusterSearchController' => 'applications/config/controller/services/PhabricatorConfigClusterSearchController.php',
|
||||
'PhabricatorConfigCollectorsModule' => 'applications/config/module/PhabricatorConfigCollectorsModule.php',
|
||||
'PhabricatorConfigColumnSchema' => 'applications/config/schema/PhabricatorConfigColumnSchema.php',
|
||||
'PhabricatorConfigConfigPHIDType' => 'applications/config/phid/PhabricatorConfigConfigPHIDType.php',
|
||||
'PhabricatorConfigConsoleController' => 'applications/config/controller/PhabricatorConfigConsoleController.php',
|
||||
'PhabricatorConfigConstants' => 'applications/config/constants/PhabricatorConfigConstants.php',
|
||||
'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php',
|
||||
'PhabricatorConfigCoreSchemaSpec' => 'applications/config/schema/PhabricatorConfigCoreSchemaSpec.php',
|
||||
'PhabricatorConfigDatabaseController' => 'applications/config/controller/PhabricatorConfigDatabaseController.php',
|
||||
'PhabricatorConfigDatabaseIssueController' => 'applications/config/controller/PhabricatorConfigDatabaseIssueController.php',
|
||||
'PhabricatorConfigDatabaseController' => 'applications/config/controller/services/PhabricatorConfigDatabaseController.php',
|
||||
'PhabricatorConfigDatabaseIssueController' => 'applications/config/controller/services/PhabricatorConfigDatabaseIssueController.php',
|
||||
'PhabricatorConfigDatabaseSchema' => 'applications/config/schema/PhabricatorConfigDatabaseSchema.php',
|
||||
'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php',
|
||||
'PhabricatorConfigDatabaseStatusController' => 'applications/config/controller/PhabricatorConfigDatabaseStatusController.php',
|
||||
'PhabricatorConfigDatabaseStatusController' => 'applications/config/controller/services/PhabricatorConfigDatabaseStatusController.php',
|
||||
'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php',
|
||||
'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php',
|
||||
'PhabricatorConfigEdgeModule' => 'applications/config/module/PhabricatorConfigEdgeModule.php',
|
||||
'PhabricatorConfigEditController' => 'applications/config/controller/PhabricatorConfigEditController.php',
|
||||
'PhabricatorConfigEditController' => 'applications/config/controller/settings/PhabricatorConfigEditController.php',
|
||||
'PhabricatorConfigEditor' => 'applications/config/editor/PhabricatorConfigEditor.php',
|
||||
'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php',
|
||||
'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php',
|
||||
'PhabricatorConfigEntryQuery' => 'applications/config/query/PhabricatorConfigEntryQuery.php',
|
||||
'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php',
|
||||
'PhabricatorConfigGroupConstants' => 'applications/config/constants/PhabricatorConfigGroupConstants.php',
|
||||
'PhabricatorConfigGroupController' => 'applications/config/controller/PhabricatorConfigGroupController.php',
|
||||
'PhabricatorConfigHTTPParameterTypesModule' => 'applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php',
|
||||
'PhabricatorConfigHistoryController' => 'applications/config/controller/PhabricatorConfigHistoryController.php',
|
||||
'PhabricatorConfigIgnoreController' => 'applications/config/controller/PhabricatorConfigIgnoreController.php',
|
||||
'PhabricatorConfigIssueListController' => 'applications/config/controller/PhabricatorConfigIssueListController.php',
|
||||
'PhabricatorConfigIssuePanelController' => 'applications/config/controller/PhabricatorConfigIssuePanelController.php',
|
||||
'PhabricatorConfigIssueViewController' => 'applications/config/controller/PhabricatorConfigIssueViewController.php',
|
||||
'PhabricatorConfigIgnoreController' => 'applications/config/controller/issue/PhabricatorConfigIgnoreController.php',
|
||||
'PhabricatorConfigIssueListController' => 'applications/config/controller/issue/PhabricatorConfigIssueListController.php',
|
||||
'PhabricatorConfigIssuePanelController' => 'applications/config/controller/issue/PhabricatorConfigIssuePanelController.php',
|
||||
'PhabricatorConfigIssueViewController' => 'applications/config/controller/issue/PhabricatorConfigIssueViewController.php',
|
||||
'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php',
|
||||
'PhabricatorConfigJSONOptionType' => 'applications/config/custom/PhabricatorConfigJSONOptionType.php',
|
||||
'PhabricatorConfigKeySchema' => 'applications/config/schema/PhabricatorConfigKeySchema.php',
|
||||
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
|
||||
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
|
||||
'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php',
|
||||
'PhabricatorConfigManagementDoneWorkflow' => 'applications/config/management/PhabricatorConfigManagementDoneWorkflow.php',
|
||||
|
@ -2848,12 +2848,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php',
|
||||
'PhabricatorConfigManualActivity' => 'applications/config/storage/PhabricatorConfigManualActivity.php',
|
||||
'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php',
|
||||
'PhabricatorConfigModuleController' => 'applications/config/controller/PhabricatorConfigModuleController.php',
|
||||
'PhabricatorConfigModuleController' => 'applications/config/controller/module/PhabricatorConfigModuleController.php',
|
||||
'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php',
|
||||
'PhabricatorConfigOptionType' => 'applications/config/custom/PhabricatorConfigOptionType.php',
|
||||
'PhabricatorConfigPHIDModule' => 'applications/config/module/PhabricatorConfigPHIDModule.php',
|
||||
'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php',
|
||||
'PhabricatorConfigPurgeCacheController' => 'applications/config/controller/PhabricatorConfigPurgeCacheController.php',
|
||||
'PhabricatorConfigPurgeCacheController' => 'applications/config/controller/services/PhabricatorConfigPurgeCacheController.php',
|
||||
'PhabricatorConfigRegexOptionType' => 'applications/config/custom/PhabricatorConfigRegexOptionType.php',
|
||||
'PhabricatorConfigRemarkupRule' => 'infrastructure/markup/rule/PhabricatorConfigRemarkupRule.php',
|
||||
'PhabricatorConfigRequestExceptionHandlerModule' => 'applications/config/module/PhabricatorConfigRequestExceptionHandlerModule.php',
|
||||
|
@ -2861,6 +2861,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php',
|
||||
'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php',
|
||||
'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php',
|
||||
'PhabricatorConfigServicesController' => 'applications/config/controller/services/PhabricatorConfigServicesController.php',
|
||||
'PhabricatorConfigSettingsController' => 'applications/config/controller/settings/PhabricatorConfigSettingsController.php',
|
||||
'PhabricatorConfigSettingsHistoryController' => 'applications/config/controller/settings/PhabricatorConfigSettingsHistoryController.php',
|
||||
'PhabricatorConfigSettingsListController' => 'applications/config/controller/settings/PhabricatorConfigSettingsListController.php',
|
||||
'PhabricatorConfigSetupCheckModule' => 'applications/config/module/PhabricatorConfigSetupCheckModule.php',
|
||||
'PhabricatorConfigSiteModule' => 'applications/config/module/PhabricatorConfigSiteModule.php',
|
||||
'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php',
|
||||
|
@ -2872,7 +2876,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php',
|
||||
'PhabricatorConfigType' => 'applications/config/type/PhabricatorConfigType.php',
|
||||
'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php',
|
||||
'PhabricatorConfigVersionController' => 'applications/config/controller/PhabricatorConfigVersionController.php',
|
||||
'PhabricatorConpherenceApplication' => 'applications/conpherence/application/PhabricatorConpherenceApplication.php',
|
||||
'PhabricatorConpherenceColumnMinimizeSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnMinimizeSetting.php',
|
||||
'PhabricatorConpherenceColumnVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnVisibleSetting.php',
|
||||
|
@ -8189,6 +8192,8 @@ phutil_register_library_map(array(
|
|||
'PHUICrumbView' => 'AphrontView',
|
||||
'PHUICrumbsView' => 'AphrontView',
|
||||
'PHUICurtainExtension' => 'Phobject',
|
||||
'PHUICurtainObjectRefListView' => 'AphrontTagView',
|
||||
'PHUICurtainObjectRefView' => 'AphrontTagView',
|
||||
'PHUICurtainPanelView' => 'AphrontTagView',
|
||||
'PHUICurtainView' => 'AphrontTagView',
|
||||
'PHUIDiffGraphView' => 'Phobject',
|
||||
|
@ -8235,8 +8240,10 @@ phutil_register_library_map(array(
|
|||
'PHUIInfoView' => 'AphrontTagView',
|
||||
'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase',
|
||||
'PHUIInvisibleCharacterView' => 'AphrontView',
|
||||
'PHUILauncherView' => 'AphrontTagView',
|
||||
'PHUILeftRightExample' => 'PhabricatorUIExample',
|
||||
'PHUILeftRightView' => 'AphrontTagView',
|
||||
'PHUILinkView' => 'AphrontTagView',
|
||||
'PHUIListExample' => 'PhabricatorUIExample',
|
||||
'PHUIListItemView' => 'AphrontTagView',
|
||||
'PHUIListView' => 'AphrontTagView',
|
||||
|
@ -9131,21 +9138,20 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorConduitTokenTerminateController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitTokensSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorConfigAllController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorConfigApplicationController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigCacheController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigClusterRepositoriesController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigClusterSearchController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigCacheController' => 'PhabricatorConfigServicesController',
|
||||
'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigServicesController',
|
||||
'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigServicesController',
|
||||
'PhabricatorConfigClusterRepositoriesController' => 'PhabricatorConfigServicesController',
|
||||
'PhabricatorConfigClusterSearchController' => 'PhabricatorConfigServicesController',
|
||||
'PhabricatorConfigCollectorsModule' => 'PhabricatorConfigModule',
|
||||
'PhabricatorConfigColumnSchema' => 'PhabricatorConfigStorageSchema',
|
||||
'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorConfigConsoleController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigConstants' => 'Phobject',
|
||||
'PhabricatorConfigController' => 'PhabricatorController',
|
||||
'PhabricatorConfigCoreSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'PhabricatorConfigDatabaseController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigDatabaseController' => 'PhabricatorConfigServicesController',
|
||||
'PhabricatorConfigDatabaseIssueController' => 'PhabricatorConfigDatabaseController',
|
||||
'PhabricatorConfigDatabaseSchema' => 'PhabricatorConfigStorageSchema',
|
||||
'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource',
|
||||
|
@ -9153,7 +9159,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource',
|
||||
'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource',
|
||||
'PhabricatorConfigEdgeModule' => 'PhabricatorConfigModule',
|
||||
'PhabricatorConfigEditController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigEditController' => 'PhabricatorConfigSettingsController',
|
||||
'PhabricatorConfigEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorConfigEntry' => array(
|
||||
'PhabricatorConfigEntryDAO',
|
||||
|
@ -9164,9 +9170,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigEntryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource',
|
||||
'PhabricatorConfigGroupConstants' => 'PhabricatorConfigConstants',
|
||||
'PhabricatorConfigGroupController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigHTTPParameterTypesModule' => 'PhabricatorConfigModule',
|
||||
'PhabricatorConfigHistoryController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigIgnoreController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigIssueListController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigIssuePanelController' => 'PhabricatorConfigController',
|
||||
|
@ -9174,7 +9178,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigJSON' => 'Phobject',
|
||||
'PhabricatorConfigJSONOptionType' => 'PhabricatorConfigOptionType',
|
||||
'PhabricatorConfigKeySchema' => 'PhabricatorConfigStorageSchema',
|
||||
'PhabricatorConfigListController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
|
||||
'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||
'PhabricatorConfigManagementDoneWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||
|
@ -9198,6 +9201,10 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigSchemaQuery' => 'Phobject',
|
||||
'PhabricatorConfigSchemaSpec' => 'Phobject',
|
||||
'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema',
|
||||
'PhabricatorConfigServicesController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigSettingsController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConfigSettingsHistoryController' => 'PhabricatorConfigSettingsController',
|
||||
'PhabricatorConfigSettingsListController' => 'PhabricatorConfigSettingsController',
|
||||
'PhabricatorConfigSetupCheckModule' => 'PhabricatorConfigModule',
|
||||
'PhabricatorConfigSiteModule' => 'PhabricatorConfigModule',
|
||||
'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource',
|
||||
|
@ -9209,7 +9216,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhabricatorConfigType' => 'Phobject',
|
||||
'PhabricatorConfigValidationException' => 'Exception',
|
||||
'PhabricatorConfigVersionController' => 'PhabricatorConfigController',
|
||||
'PhabricatorConpherenceApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorConpherenceColumnMinimizeSetting' => 'PhabricatorInternalSetting',
|
||||
'PhabricatorConpherenceColumnVisibleSetting' => 'PhabricatorInternalSetting',
|
||||
|
|
|
@ -10,13 +10,15 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
$viewer = $request->getViewer();
|
||||
|
||||
$menu = id(new PHUIObjectItemListView())
|
||||
->setUser($viewer);
|
||||
->setViewer($viewer)
|
||||
->setBig(true);
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Devices'))
|
||||
->setHref($this->getApplicationURI('device/'))
|
||||
->setImageIcon('fa-server')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Create an inventory of physical and virtual hosts and '.
|
||||
|
@ -27,6 +29,7 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
->setHeader(pht('Services'))
|
||||
->setHref($this->getApplicationURI('service/'))
|
||||
->setImageIcon('fa-plug')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Create and update services, and map them to interfaces on '.
|
||||
|
@ -37,6 +40,7 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
->setHeader(pht('Networks'))
|
||||
->setHref($this->getApplicationURI('network/'))
|
||||
->setImageIcon('fa-globe')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Manage public and private networks.')));
|
||||
|
@ -46,6 +50,7 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
->setHeader(pht('Namespaces'))
|
||||
->setHref($this->getApplicationURI('namespace/'))
|
||||
->setImageIcon('fa-asterisk')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht('Control who can create new named services and devices.')));
|
||||
|
||||
|
@ -57,6 +62,7 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
->setHeader(pht('Documentation'))
|
||||
->setHref($docs_uri)
|
||||
->setImageIcon('fa-book')
|
||||
->setClickable(true)
|
||||
->addAttribute(pht('Browse documentation for Almanac.')));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
@ -64,23 +70,20 @@ final class AlmanacConsoleController extends AlmanacController {
|
|||
$crumbs->setBorder(true);
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Almanac Console'))
|
||||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setObjectList($menu);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Almanac Console'))
|
||||
->setHeaderIcon('fa-server');
|
||||
$launcher_view = id(new PHUILauncherView())
|
||||
->appendChild($box);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter(array(
|
||||
$box,
|
||||
));
|
||||
->setFooter($launcher_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle(pht('Almanac Console'))
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($view);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -405,6 +405,31 @@ final class PhabricatorAuditEditor
|
|||
$phid_map[] = $reverted_phids;
|
||||
}
|
||||
|
||||
// See T13463. Copy "related task" edges from the associated revision, if
|
||||
// one exists.
|
||||
|
||||
$revision = DiffusionCommitRevisionQuery::loadRevisionForCommit(
|
||||
$actor,
|
||||
$object);
|
||||
if ($revision) {
|
||||
$task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
||||
$revision->getPHID(),
|
||||
DifferentialRevisionHasTaskEdgeType::EDGECONST);
|
||||
$task_phids = array_fuse($task_phids);
|
||||
|
||||
if ($task_phids) {
|
||||
$related_edge = DiffusionCommitHasTaskEdgeType::EDGECONST;
|
||||
$result[] = id(new PhabricatorAuditTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
|
||||
->setMetadataValue('edge:type', $related_edge)
|
||||
->setNewValue(array('+' => $task_phids));
|
||||
}
|
||||
|
||||
// Mark these objects as unmentionable, since the explicit relationship
|
||||
// is stronger and any mentions are redundant.
|
||||
$phid_map[] = $task_phids;
|
||||
}
|
||||
|
||||
$phid_map = array_mergev($phid_map);
|
||||
$this->addUnmentionablePHIDs($phid_map);
|
||||
|
||||
|
|
|
@ -51,13 +51,17 @@ final class PhutilGitHubAuthAdapter extends PhutilOAuthAuthAdapter {
|
|||
|
||||
protected function loadOAuthAccountData() {
|
||||
$uri = new PhutilURI('https://api.github.com/user');
|
||||
$uri->replaceQueryParam('access_token', $this->getAccessToken());
|
||||
|
||||
$future = new HTTPSFuture($uri);
|
||||
|
||||
// NOTE: GitHub requires a User-Agent string.
|
||||
$future->addHeader('User-Agent', __CLASS__);
|
||||
|
||||
// See T13485. Circa early 2020, GitHub has deprecated use of the
|
||||
// "access_token" URI parameter.
|
||||
$token_header = sprintf('token %s', $this->getAccessToken());
|
||||
$future->addHeader('Authorization', $token_header);
|
||||
|
||||
list($body) = $future->resolvex();
|
||||
|
||||
try {
|
||||
|
|
|
@ -37,13 +37,12 @@ final class PhabricatorConfigApplication extends PhabricatorApplication {
|
|||
public function getRoutes() {
|
||||
return array(
|
||||
'/config/' => array(
|
||||
'' => 'PhabricatorConfigListController',
|
||||
'' => 'PhabricatorConfigConsoleController',
|
||||
'application/' => 'PhabricatorConfigApplicationController',
|
||||
'all/' => 'PhabricatorConfigAllController',
|
||||
'history/' => 'PhabricatorConfigHistoryController',
|
||||
'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController',
|
||||
'group/(?P<key>[^/]+)/' => 'PhabricatorConfigGroupController',
|
||||
'version/' => 'PhabricatorConfigVersionController',
|
||||
'database/'.
|
||||
'(?:(?P<ref>[^/]+)/'.
|
||||
'(?:(?P<database>[^/]+)/'.
|
||||
|
@ -63,7 +62,7 @@ final class PhabricatorConfigApplication extends PhabricatorApplication {
|
|||
'purge/' => 'PhabricatorConfigPurgeCacheController',
|
||||
),
|
||||
'module/' => array(
|
||||
'(?P<module>[^/]+)/' => 'PhabricatorConfigModuleController',
|
||||
'(?:(?P<module>[^/]+)/)?' => 'PhabricatorConfigModuleController',
|
||||
),
|
||||
'cluster/' => array(
|
||||
'databases/' => 'PhabricatorConfigClusterDatabasesController',
|
||||
|
@ -71,6 +70,12 @@ final class PhabricatorConfigApplication extends PhabricatorApplication {
|
|||
'repositories/' => 'PhabricatorConfigClusterRepositoriesController',
|
||||
'search/' => 'PhabricatorConfigClusterSearchController',
|
||||
),
|
||||
'settings/' => array(
|
||||
'' => 'PhabricatorConfigSettingsListController',
|
||||
'(?P<filter>advanced|all)/'
|
||||
=> 'PhabricatorConfigSettingsListController',
|
||||
'history/' => 'PhabricatorConfigSettingsHistoryController',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -53,20 +53,23 @@ final class PhabricatorAuthSetupCheck extends PhabricatorSetupCheck {
|
|||
"\n\n".
|
||||
'Leaving your authentication provider configuration unlocked '.
|
||||
'increases the damage that a compromised administrator account can '.
|
||||
'do to your install, by, for example, changing the authentication '.
|
||||
'provider to a server they control and intercepting usernames and '.
|
||||
'do to your install. For example, an attacker who compromises an '.
|
||||
'administrator account can change authentication providers to point '.
|
||||
'at a server they control and attempt to intercept usernames and '.
|
||||
'passwords.'.
|
||||
"\n\n".
|
||||
'To prevent this attack, you should configure your authentication '.
|
||||
'providers, and then lock the configuration by doing `%s` '.
|
||||
'from the command line. This will prevent changing the '.
|
||||
'authentication provider config without first doing `%s`.',
|
||||
'bin/auth lock',
|
||||
'bin/auth unlock');
|
||||
'To prevent this attack, you should configure authentication, and '.
|
||||
'then lock the configuration by running "bin/auth lock" from the '.
|
||||
'command line. This will prevent changing the authentication config '.
|
||||
'without first running "bin/auth unlock".');
|
||||
$this
|
||||
->newIssue('auth.config-unlocked')
|
||||
->setShortName(pht('Auth Config Unlocked'))
|
||||
->setName(pht('Authenticaton Provider Configuration Unlocked'))
|
||||
->setName(pht('Authenticaton Configuration Unlocked'))
|
||||
->setSummary(
|
||||
pht(
|
||||
'Authentication configuration is currently unlocked. Once you '.
|
||||
'finish configuring authentication, you should lock it.'))
|
||||
->setMessage($message)
|
||||
->addRelatedPhabricatorConfig('auth.lock-config')
|
||||
->addCommand(
|
||||
|
|
|
@ -58,8 +58,7 @@ final class PhabricatorSecuritySetupCheck extends PhabricatorSetupCheck {
|
|||
->setName(pht('Alternate File Domain Not Configured'))
|
||||
->setSummary(
|
||||
pht(
|
||||
'Increase security (and improve performance) by configuring '.
|
||||
'a CDN or alternate file domain.'))
|
||||
'Improve security by configuring an alternate file domain.'))
|
||||
->setMessage(
|
||||
pht(
|
||||
'Phabricator is currently configured to serve user uploads '.
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigAllController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$db_values = id(new PhabricatorConfigEntry())
|
||||
->loadAllWhere('namespace = %s', 'default');
|
||||
$db_values = mpull($db_values, null, 'getConfigKey');
|
||||
|
||||
$rows = array();
|
||||
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
||||
ksort($options);
|
||||
foreach ($options as $option) {
|
||||
$key = $option->getKey();
|
||||
|
||||
if ($option->getHidden()) {
|
||||
$value = phutil_tag('em', array(), pht('Hidden'));
|
||||
} else {
|
||||
$value = PhabricatorEnv::getEnvConfig($key);
|
||||
$value = PhabricatorConfigJSON::prettyPrintJSON($value);
|
||||
}
|
||||
|
||||
$db_value = idx($db_values, $key);
|
||||
$rows[] = array(
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $this->getApplicationURI('edit/'.$key.'/'),
|
||||
),
|
||||
$key),
|
||||
$value,
|
||||
$db_value && !$db_value->getIsDeleted() ? pht('Customized') : '',
|
||||
);
|
||||
}
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'wide',
|
||||
))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Key'),
|
||||
pht('Value'),
|
||||
pht('Customized'),
|
||||
));
|
||||
|
||||
$title = pht('Current Settings');
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('all/');
|
||||
|
||||
$view = $this->buildConfigBoxView(
|
||||
pht('All Settings'),
|
||||
$table);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigApplicationController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('application/');
|
||||
|
||||
$groups = PhabricatorApplicationConfigOptions::loadAll();
|
||||
$apps_list = $this->buildConfigOptionsList($groups, 'apps');
|
||||
$apps_list = $this->buildConfigBoxView(pht('Applications'), $apps_list);
|
||||
|
||||
$title = pht('Application Settings');
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($apps_list);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
||||
private function buildConfigOptionsList(array $groups, $type) {
|
||||
assert_instances_of($groups, 'PhabricatorApplicationConfigOptions');
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
$list->setBig(true);
|
||||
$groups = msort($groups, 'getName');
|
||||
foreach ($groups as $group) {
|
||||
if ($group->getGroup() == $type) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon($group->getIcon())
|
||||
->setBackground('bg-violet');
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($group->getName())
|
||||
->setHref('/config/group/'.$group->getKey().'/')
|
||||
->addAttribute($group->getDescription())
|
||||
->setImageIcon($icon);
|
||||
$list->addItem($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,92 +1,139 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigVersionController
|
||||
final class PhabricatorConfigConsoleController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$title = pht('Version Information');
|
||||
$versions = $this->renderModuleStatus($viewer);
|
||||
$menu = id(new PHUIObjectItemListView())
|
||||
->setViewer($viewer)
|
||||
->setBig(true);
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('version/');
|
||||
$header = $this->buildHeaderView($title);
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Settings'))
|
||||
->setHref($this->getApplicationURI('settings/'))
|
||||
->setImageIcon('fa-wrench')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Review and modify configuration settings.')));
|
||||
|
||||
$view = $this->buildConfigBoxView(
|
||||
pht('Installed Versions'),
|
||||
$versions);
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Setup Issues'))
|
||||
->setHref($this->getApplicationURI('issue/'))
|
||||
->setImageIcon('fa-exclamation-triangle')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Show unresolved issues with setup and configuration.')));
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Services'))
|
||||
->setHref($this->getApplicationURI('cluster/databases/'))
|
||||
->setImageIcon('fa-server')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'View status information for databases, caches, repositories, '.
|
||||
'and other services.')));
|
||||
|
||||
$menu->addItem(
|
||||
id(new PHUIObjectItemView())
|
||||
->setHeader(pht('Extensions/Modules'))
|
||||
->setHref($this->getApplicationURI('module/'))
|
||||
->setImageIcon('fa-gear')
|
||||
->setClickable(true)
|
||||
->addAttribute(
|
||||
pht(
|
||||
'Show installed extensions and modules.')));
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->addTextCrumb(pht('Console'))
|
||||
->setBorder(true);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($view);
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Phabricator Configuation'))
|
||||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setObjectList($menu);
|
||||
|
||||
$versions = $this->newLibraryVersionTable($viewer);
|
||||
$binary_versions = $this->newBinaryVersionTable();
|
||||
|
||||
$launcher_view = id(new PHUILauncherView())
|
||||
->appendChild($box)
|
||||
->appendChild($versions)
|
||||
->appendChild($binary_versions);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFooter($launcher_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setTitle(pht('Phabricator Configuation'))
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
->appendChild($view);
|
||||
}
|
||||
|
||||
public function renderModuleStatus($viewer) {
|
||||
public function newLibraryVersionTable() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$versions = $this->loadVersions($viewer);
|
||||
|
||||
$version_property_list = id(new PHUIPropertyListView());
|
||||
$rows = array();
|
||||
foreach ($versions as $name => $info) {
|
||||
$version = $info['version'];
|
||||
$branchpoint = $info['branchpoint'];
|
||||
if (strlen($branchpoint)) {
|
||||
$branchpoint = substr($branchpoint, 0, 12);
|
||||
} else {
|
||||
$branchpoint = null;
|
||||
}
|
||||
|
||||
if ($info['branchpoint']) {
|
||||
$display = pht(
|
||||
'%s (branched from %s on %s)',
|
||||
$version = $info['hash'];
|
||||
if (strlen($version)) {
|
||||
$version = substr($version, 0, 12);
|
||||
} else {
|
||||
$version = pht('Unknown');
|
||||
}
|
||||
|
||||
|
||||
$epoch = $info['epoch'];
|
||||
if ($epoch) {
|
||||
$epoch = phabricator_date($epoch, $viewer);
|
||||
} else {
|
||||
$epoch = null;
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$name,
|
||||
$version,
|
||||
$info['branchpoint'],
|
||||
$info['upstream']);
|
||||
} else {
|
||||
$display = $version;
|
||||
$epoch,
|
||||
$branchpoint,
|
||||
);
|
||||
}
|
||||
|
||||
$version_property_list->addProperty($name, $display);
|
||||
}
|
||||
$table_view = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Library'),
|
||||
pht('Version'),
|
||||
pht('Date'),
|
||||
pht('Branchpoint'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pri',
|
||||
null,
|
||||
null,
|
||||
'wide',
|
||||
));
|
||||
|
||||
$phabricator_root = dirname(phutil_get_library_root('phabricator'));
|
||||
$version_path = $phabricator_root.'/conf/local/VERSION';
|
||||
if (Filesystem::pathExists($version_path)) {
|
||||
$version_from_file = Filesystem::readFile($version_path);
|
||||
$version_property_list->addProperty(
|
||||
pht('Local Version'),
|
||||
$version_from_file);
|
||||
}
|
||||
|
||||
$version_property_list->addProperty('php', phpversion());
|
||||
|
||||
$binaries = PhutilBinaryAnalyzer::getAllBinaries();
|
||||
foreach ($binaries as $binary) {
|
||||
if (!$binary->isBinaryAvailable()) {
|
||||
$binary_info = pht('Not Available');
|
||||
} else {
|
||||
$version = $binary->getBinaryVersion();
|
||||
$path = $binary->getBinaryPath();
|
||||
if ($path === null && $version === null) {
|
||||
$binary_info = pht('-');
|
||||
} else if ($path === null) {
|
||||
$binary_info = $version;
|
||||
} else if ($version === null) {
|
||||
$binary_info = pht('- at %s', $path);
|
||||
} else {
|
||||
$binary_info = pht('%s at %s', $version, $path);
|
||||
}
|
||||
}
|
||||
|
||||
$version_property_list->addProperty(
|
||||
$binary->getBinaryName(),
|
||||
$binary_info);
|
||||
}
|
||||
|
||||
return $version_property_list;
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Phabricator Version Information'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->appendChild($table_view);
|
||||
}
|
||||
|
||||
private function loadVersions(PhabricatorUser $viewer) {
|
||||
|
@ -207,13 +254,14 @@ final class PhabricatorConfigVersionController
|
|||
list($err, $stdout) = $future->resolve();
|
||||
if (!$err) {
|
||||
list($hash, $epoch) = explode(' ', $stdout);
|
||||
$version = pht('%s (%s)', $hash, phabricator_date($epoch, $viewer));
|
||||
} else {
|
||||
$version = pht('Unknown');
|
||||
$hash = null;
|
||||
$epoch = null;
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'version' => $version,
|
||||
'hash' => $hash,
|
||||
'epoch' => $epoch,
|
||||
'upstream' => null,
|
||||
'branchpoint' => null,
|
||||
);
|
||||
|
@ -239,4 +287,51 @@ final class PhabricatorConfigVersionController
|
|||
return $results;
|
||||
}
|
||||
|
||||
private function newBinaryVersionTable() {
|
||||
$rows = array();
|
||||
|
||||
$rows[] = array(
|
||||
'php',
|
||||
phpversion(),
|
||||
php_sapi_name(),
|
||||
);
|
||||
|
||||
$binaries = PhutilBinaryAnalyzer::getAllBinaries();
|
||||
foreach ($binaries as $binary) {
|
||||
if (!$binary->isBinaryAvailable()) {
|
||||
$binary_version = pht('Not Available');
|
||||
$binary_path = null;
|
||||
} else {
|
||||
$binary_version = $binary->getBinaryVersion();
|
||||
$binary_path = $binary->getBinaryPath();
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$binary->getBinaryName(),
|
||||
$binary_version,
|
||||
$binary_path,
|
||||
);
|
||||
}
|
||||
|
||||
$table_view = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Binary'),
|
||||
pht('Version'),
|
||||
pht('Path'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pri',
|
||||
null,
|
||||
'wide',
|
||||
));
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Other Version Information'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->appendChild($table_view);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -6,57 +6,6 @@ abstract class PhabricatorConfigController extends PhabricatorController {
|
|||
return true;
|
||||
}
|
||||
|
||||
public function buildSideNavView($filter = null, $for_app = false) {
|
||||
$guide_href = new PhutilURI('/guides/');
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
$nav->addFilter('/',
|
||||
pht('Core Settings'), null, 'fa-gear');
|
||||
$nav->addFilter('application/',
|
||||
pht('Application Settings'), null, 'fa-globe');
|
||||
$nav->addFilter('history/',
|
||||
pht('Settings History'), null, 'fa-history');
|
||||
$nav->addFilter('version/',
|
||||
pht('Version Information'), null, 'fa-download');
|
||||
$nav->addFilter('all/',
|
||||
pht('All Settings'), null, 'fa-list-ul');
|
||||
$nav->addLabel(pht('Setup'));
|
||||
$nav->addFilter('issue/',
|
||||
pht('Setup Issues'), null, 'fa-warning');
|
||||
$nav->addFilter(null,
|
||||
pht('Installation Guide'), $guide_href, 'fa-book');
|
||||
$nav->addLabel(pht('Database'));
|
||||
$nav->addFilter('database/',
|
||||
pht('Database Status'), null, 'fa-heartbeat');
|
||||
$nav->addFilter('dbissue/',
|
||||
pht('Database Issues'), null, 'fa-exclamation-circle');
|
||||
$nav->addLabel(pht('Cache'));
|
||||
$nav->addFilter('cache/',
|
||||
pht('Cache Status'), null, 'fa-home');
|
||||
$nav->addLabel(pht('Cluster'));
|
||||
$nav->addFilter('cluster/databases/',
|
||||
pht('Database Servers'), null, 'fa-database');
|
||||
$nav->addFilter('cluster/notifications/',
|
||||
pht('Notification Servers'), null, 'fa-bell-o');
|
||||
$nav->addFilter('cluster/repositories/',
|
||||
pht('Repository Servers'), null, 'fa-code');
|
||||
$nav->addFilter('cluster/search/',
|
||||
pht('Search Servers'), null, 'fa-search');
|
||||
$nav->addLabel(pht('Modules'));
|
||||
|
||||
$modules = PhabricatorConfigModule::getAllModules();
|
||||
foreach ($modules as $key => $module) {
|
||||
$nav->addFilter('module/'.$key.'/',
|
||||
$module->getModuleName(), null, 'fa-puzzle-piece');
|
||||
}
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function buildApplicationMenu() {
|
||||
return $this->buildSideNavView(null, true)->getMenu();
|
||||
}
|
||||
|
||||
public function buildHeaderView($text, $action = null) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigGroupController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$group_key = $request->getURIData('key');
|
||||
|
||||
$groups = PhabricatorApplicationConfigOptions::loadAll();
|
||||
$options = idx($groups, $group_key);
|
||||
if (!$options) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$group_uri = PhabricatorConfigGroupConstants::getGroupFullURI(
|
||||
$options->getGroup());
|
||||
$group_name = PhabricatorConfigGroupConstants::getGroupShortName(
|
||||
$options->getGroup());
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter($group_uri);
|
||||
|
||||
$title = pht('%s Configuration', $options->getName());
|
||||
$header = $this->buildHeaderView($title);
|
||||
$list = $this->buildOptionList($options->getOptions());
|
||||
$group_url = phutil_tag('a', array('href' => $group_uri), $group_name);
|
||||
|
||||
$box_header = pht("%s \xC2\xBB %s", $group_url, $options->getName());
|
||||
$view = $this->buildConfigBoxView($box_header, $list);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($group_name, $group_uri)
|
||||
->addTextCrumb($options->getName())
|
||||
->setBorder(true);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
||||
private function buildOptionList(array $options) {
|
||||
assert_instances_of($options, 'PhabricatorConfigOption');
|
||||
|
||||
require_celerity_resource('config-options-css');
|
||||
|
||||
$db_values = array();
|
||||
if ($options) {
|
||||
$db_values = id(new PhabricatorConfigEntry())->loadAllWhere(
|
||||
'configKey IN (%Ls) AND namespace = %s',
|
||||
mpull($options, 'getKey'),
|
||||
'default');
|
||||
$db_values = mpull($db_values, null, 'getConfigKey');
|
||||
}
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
$list->setBig(true);
|
||||
foreach ($options as $option) {
|
||||
$summary = $option->getSummary();
|
||||
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($option->getKey())
|
||||
->setHref('/config/edit/'.$option->getKey().'/')
|
||||
->addAttribute($summary);
|
||||
|
||||
$color = null;
|
||||
$db_value = idx($db_values, $option->getKey());
|
||||
if ($db_value && !$db_value->getIsDeleted()) {
|
||||
$item->setEffect('visited');
|
||||
$color = 'violet';
|
||||
}
|
||||
|
||||
if ($option->getHidden()) {
|
||||
$item->setStatusIcon('fa-eye-slash grey', pht('Hidden'));
|
||||
$item->setDisabled(true);
|
||||
} else if ($option->getLocked()) {
|
||||
$item->setStatusIcon('fa-lock '.$color, pht('Locked'));
|
||||
} else if ($color) {
|
||||
$item->setStatusIcon('fa-pencil '.$color, pht('Editable'));
|
||||
} else {
|
||||
$item->setStatusIcon('fa-pencil-square-o '.$color, pht('Editable'));
|
||||
}
|
||||
|
||||
if (!$option->getHidden()) {
|
||||
$current_value = PhabricatorEnv::getEnvConfig($option->getKey());
|
||||
$current_value = PhabricatorConfigJSON::prettyPrintJSON(
|
||||
$current_value);
|
||||
$current_value = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'config-options-current-value '.$color,
|
||||
),
|
||||
array(
|
||||
$current_value,
|
||||
));
|
||||
|
||||
$item->setSideColumn($current_value);
|
||||
}
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigListController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('/');
|
||||
|
||||
$groups = PhabricatorApplicationConfigOptions::loadAll();
|
||||
$core_list = $this->buildConfigOptionsList($groups, 'core');
|
||||
$core_list = $this->buildConfigBoxView(pht('Core'), $core_list);
|
||||
|
||||
$title = pht('Core Settings');
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($core_list);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
||||
private function buildConfigOptionsList(array $groups, $type) {
|
||||
assert_instances_of($groups, 'PhabricatorApplicationConfigOptions');
|
||||
|
||||
$list = new PHUIObjectItemListView();
|
||||
$list->setBig(true);
|
||||
$groups = msort($groups, 'getName');
|
||||
foreach ($groups as $group) {
|
||||
if ($group->getGroup() == $type) {
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIcon($group->getIcon())
|
||||
->setBackground('bg-blue');
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($group->getName())
|
||||
->setHref('/config/group/'.$group->getKey().'/')
|
||||
->addAttribute($group->getDescription())
|
||||
->setImageIcon($icon);
|
||||
$list->addItem($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,9 +6,6 @@ final class PhabricatorConfigIssueListController
|
|||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('issue/');
|
||||
|
||||
$engine = new PhabricatorSetupEngine();
|
||||
$response = $engine->execute();
|
||||
if ($response) {
|
||||
|
@ -34,7 +31,6 @@ final class PhabricatorConfigIssueListController
|
|||
'fa-question-circle');
|
||||
|
||||
$title = pht('Setup Issues');
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
if (!$issues) {
|
||||
$issue_list = id(new PHUIInfoView())
|
||||
|
@ -50,21 +46,24 @@ final class PhabricatorConfigIssueListController
|
|||
$other,
|
||||
);
|
||||
|
||||
$issue_list = $this->buildConfigBoxView(pht('Issues'), $issue_list);
|
||||
$issue_list = $this->buildConfigBoxView(
|
||||
pht('Unresolved Setup Issues'),
|
||||
$issue_list);
|
||||
}
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
|
||||
$launcher_view = id(new PHUILauncherView())
|
||||
->appendChild($issue_list);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($issue_list);
|
||||
->setFooter($launcher_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
||||
|
@ -76,12 +75,16 @@ final class PhabricatorConfigIssueListController
|
|||
$items = 0;
|
||||
|
||||
foreach ($issues as $issue) {
|
||||
if ($issue->getGroup() == $group) {
|
||||
if ($issue->getGroup() != $group) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$items++;
|
||||
$href = $this->getApplicationURI('/issue/'.$issue->getIssueKey().'/');
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($issue->getName())
|
||||
->setHref($href)
|
||||
->setClickable(true)
|
||||
->addAttribute($issue->getSummary());
|
||||
if (!$issue->getIsIgnored()) {
|
||||
$icon = id(new PHUIIconView())
|
||||
|
@ -98,7 +101,6 @@ final class PhabricatorConfigIssueListController
|
|||
$ignored_items[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ignored_items as $item) {
|
||||
$list->addItem($item);
|
|
@ -14,9 +14,6 @@ final class PhabricatorConfigIssueViewController
|
|||
}
|
||||
$issues = $engine->getIssues();
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('issue/');
|
||||
|
||||
if (empty($issues[$issue_key])) {
|
||||
$content = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
|
||||
|
@ -36,23 +33,21 @@ final class PhabricatorConfigIssueViewController
|
|||
$title = $issue->getShortName();
|
||||
}
|
||||
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$crumbs = $this
|
||||
->buildApplicationCrumbs()
|
||||
->setBorder(true)
|
||||
->addTextCrumb(pht('Setup Issues'), $this->getApplicationURI('issue/'))
|
||||
->addTextCrumb($title, $request->getRequestURI())
|
||||
->setBorder(true);
|
||||
|
||||
$launcher_view = id(new PHUILauncherView())
|
||||
->appendChild($content);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($content);
|
||||
->setFooter($launcher_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
|
@ -8,6 +8,11 @@ final class PhabricatorConfigModuleController
|
|||
$key = $request->getURIData('module');
|
||||
|
||||
$all_modules = PhabricatorConfigModule::getAllModules();
|
||||
|
||||
if (!strlen($key)) {
|
||||
$key = head_key($all_modules);
|
||||
}
|
||||
|
||||
if (empty($all_modules[$key])) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
@ -16,13 +21,27 @@ final class PhabricatorConfigModuleController
|
|||
$content = $module->renderModuleStatus($request);
|
||||
$title = $module->getModuleName();
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('module/'.$key.'/');
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
||||
$modules_uri = $this->getApplicationURI('module/');
|
||||
|
||||
$modules = PhabricatorConfigModule::getAllModules();
|
||||
|
||||
foreach ($modules as $module_key => $module) {
|
||||
$nav->newLink($module_key)
|
||||
->setName($module->getModuleName())
|
||||
->setHref(urisprintf('%s%s/', $modules_uri, $module_key))
|
||||
->setIcon('fa-puzzle-piece');
|
||||
}
|
||||
|
||||
$nav->selectFilter($key);
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$view = $this->buildConfigBoxView($title, $content);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Extensions/Modules'), $modules_uri)
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigCacheController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigServicesController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('cache/');
|
||||
|
||||
$purge_button = id(new PHUIButtonView())
|
||||
->setText(pht('Purge Caches'))
|
||||
|
@ -27,14 +25,15 @@ final class PhabricatorConfigCacheController
|
|||
$data_box,
|
||||
);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($page);
|
||||
|
||||
$nav = $this->newNavigation('cache');
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
|
@ -92,10 +91,12 @@ final class PhabricatorConfigCacheController
|
|||
'n',
|
||||
'n',
|
||||
));
|
||||
|
||||
$table = $this->buildConfigBoxView(pht('Cache Storage'), $table);
|
||||
}
|
||||
|
||||
$properties = $this->buildConfigBoxView(pht('Data Cache'), $properties);
|
||||
$table = $this->buildConfigBoxView(pht('Cache Storage'), $table);
|
||||
|
||||
return array($properties, $table);
|
||||
}
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigClusterDatabasesController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigServicesController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('cluster/databases/');
|
||||
$nav = $this->newNavigation('database-servers');
|
||||
|
||||
$title = pht('Cluster Database Status');
|
||||
$title = pht('Database Servers');
|
||||
$doc_href = PhabricatorEnv::getDoclink('Cluster: Databases');
|
||||
$button = id(new PHUIButtonView())
|
||||
->setIcon('fa-book')
|
||||
|
@ -20,9 +19,8 @@ final class PhabricatorConfigClusterDatabasesController
|
|||
$database_status = $this->buildClusterDatabaseStatus();
|
||||
$status = $this->buildConfigBoxView(pht('Status'), $database_status);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
|
@ -1,13 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigClusterNotificationsController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigServicesController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('cluster/notifications/');
|
||||
|
||||
$title = pht('Cluster Notifications');
|
||||
$title = pht('Notification Servers');
|
||||
$doc_href = PhabricatorEnv::getDoclink('Cluster: Notifications');
|
||||
$button = id(new PHUIButtonView())
|
||||
->setIcon('fa-book')
|
||||
|
@ -22,14 +19,15 @@ final class PhabricatorConfigClusterNotificationsController
|
|||
pht('Notifications Status'),
|
||||
$notification_status);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($status);
|
||||
|
||||
$nav = $this->newNavigation('notification-servers');
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
|
@ -1,13 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigClusterRepositoriesController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigServicesController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('cluster/repositories/');
|
||||
|
||||
$title = pht('Cluster Repository Status');
|
||||
$title = pht('Repository Services');
|
||||
|
||||
$doc_href = PhabricatorEnv::getDoclink('Cluster: Repositories');
|
||||
$button = id(new PHUIButtonView())
|
||||
|
@ -26,9 +23,8 @@ final class PhabricatorConfigClusterRepositoriesController
|
|||
$repo_errors = $this->buildConfigBoxView(
|
||||
pht('Repository Errors'), $repository_errors);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
|
@ -38,6 +34,8 @@ final class PhabricatorConfigClusterRepositoriesController
|
|||
$repo_errors,
|
||||
));
|
||||
|
||||
$nav = $this->newNavigation('repository-servers');
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
|
@ -1,13 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigClusterSearchController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigServicesController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('cluster/search/');
|
||||
|
||||
$title = pht('Cluster Search');
|
||||
$title = pht('Search Servers');
|
||||
$doc_href = PhabricatorEnv::getDoclink('Cluster: Search');
|
||||
|
||||
$button = id(new PHUIButtonView())
|
||||
|
@ -20,14 +17,15 @@ final class PhabricatorConfigClusterSearchController
|
|||
|
||||
$search_status = $this->buildClusterSearchStatus();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($search_status);
|
||||
|
||||
$nav = $this->newNavigation('search-servers');
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorConfigDatabaseController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigServicesController {
|
||||
|
||||
protected function renderIcon($status) {
|
||||
switch ($status) {
|
|
@ -153,15 +153,14 @@ final class PhabricatorConfigDatabaseIssueController
|
|||
new PhutilNumber($counts[PhabricatorConfigStorageSchema::STATUS_WARN]));
|
||||
}
|
||||
|
||||
$title = pht('Database Issues');
|
||||
$title = pht('Schemata Issues');
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('dbissue/');
|
||||
$nav = $this->newNavigation('schemata-issues');
|
||||
|
||||
$view = $this->buildConfigBoxView(pht('Issues'), $table);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
|
|
@ -71,8 +71,7 @@ final class PhabricatorConfigDatabaseStatusController
|
|||
}
|
||||
|
||||
private function buildResponse($title, $body) {
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('database/');
|
||||
$nav = $this->newNavigation('schemata');
|
||||
|
||||
if (!$title) {
|
||||
$title = pht('Database Status');
|
||||
|
@ -118,8 +117,7 @@ final class PhabricatorConfigDatabaseStatusController
|
|||
);
|
||||
}
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->setBorder(true);
|
||||
$crumbs = $this->newCrumbs();
|
||||
|
||||
$last_key = last_key($links);
|
||||
foreach ($links as $link_key => $link) {
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorConfigServicesController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function newNavigation($select_filter) {
|
||||
$services_uri = $this->getApplicationURI();
|
||||
|
||||
$nav = id(new AphrontSideNavFilterView())
|
||||
->setBaseURI(new PhutilURI($services_uri));
|
||||
|
||||
$nav->addLabel(pht('Databases'));
|
||||
|
||||
$nav->newLink('database-servers')
|
||||
->setName(pht('Database Servers'))
|
||||
->setIcon('fa-database')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'cluster/databases'));
|
||||
|
||||
$nav->newLink('schemata')
|
||||
->setName(pht('Database Schemata'))
|
||||
->setIcon('fa-table')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'database'));
|
||||
|
||||
$nav->newLink('schemata-issues')
|
||||
->setName(pht('Schemata Issues'))
|
||||
->setIcon('fa-exclamation-circle')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'dbissue'));
|
||||
|
||||
|
||||
$nav->addLabel(pht('Cache'));
|
||||
|
||||
$nav->newLink('cache')
|
||||
->setName(pht('Cache Status'))
|
||||
->setIcon('fa-archive')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'cache'));
|
||||
|
||||
$nav->addLabel(pht('Other Services'));
|
||||
|
||||
$nav->newLink('notification-servers')
|
||||
->setName(pht('Notification Servers'))
|
||||
->setIcon('fa-bell-o')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'cluster/notifications'));
|
||||
|
||||
$nav->newLink('repository-servers')
|
||||
->setName(pht('Repository Servers'))
|
||||
->setIcon('fa-code')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'cluster/repositories'));
|
||||
|
||||
$nav->newLink('search-servers')
|
||||
->setName(pht('Search Servers'))
|
||||
->setIcon('fa-search')
|
||||
->setHref(urisprintf('%s%s/', $services_uri, 'cluster/search'));
|
||||
|
||||
if ($select_filter) {
|
||||
$nav->selectFilter($select_filter);
|
||||
}
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function newCrumbs() {
|
||||
$services_uri = $this->getApplicationURI('cluster/databases/');
|
||||
|
||||
return $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Services'))
|
||||
->setBorder(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigEditController
|
||||
extends PhabricatorConfigController {
|
||||
extends PhabricatorConfigSettingsController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
@ -30,11 +30,9 @@ final class PhabricatorConfigEditController
|
|||
->setDefault(null)
|
||||
->setDescription($desc);
|
||||
$group = null;
|
||||
$group_uri = $this->getApplicationURI();
|
||||
} else {
|
||||
$option = $options[$key];
|
||||
$group = $option->getGroup();
|
||||
$group_uri = $this->getApplicationURI('group/'.$group->getKey().'/');
|
||||
}
|
||||
|
||||
$issue = $request->getStr('issue');
|
||||
|
@ -42,7 +40,7 @@ final class PhabricatorConfigEditController
|
|||
// If the user came here from an open setup issue, send them back.
|
||||
$done_uri = $this->getApplicationURI('issue/'.$issue.'/');
|
||||
} else {
|
||||
$done_uri = $group_uri;
|
||||
$done_uri = $this->getApplicationURI('settings/');
|
||||
}
|
||||
|
||||
// Check if the config key is already stored in the database.
|
||||
|
@ -205,23 +203,10 @@ final class PhabricatorConfigEditController
|
|||
$title = $key;
|
||||
|
||||
$box_header = array();
|
||||
if ($group) {
|
||||
$box_header[] = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $group_uri,
|
||||
),
|
||||
$group->getName());
|
||||
$box_header[] = " \xC2\xBB ";
|
||||
}
|
||||
$box_header[] = $key;
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
if ($group) {
|
||||
$crumbs->addTextCrumb($group->getName(), $group_uri);
|
||||
}
|
||||
$crumbs->addTextCrumb($key, '/config/edit/'.$key);
|
||||
$crumbs->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($key, '/config/edit/'.$key);
|
||||
|
||||
$form_box = $this->buildConfigBoxView($box_header, $form, $tag);
|
||||
|
||||
|
@ -230,9 +215,6 @@ final class PhabricatorConfigEditController
|
|||
new PhabricatorConfigTransactionQuery());
|
||||
$timeline->setShouldTerminate(true);
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter($group_uri);
|
||||
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
|
@ -249,7 +231,6 @@ final class PhabricatorConfigEditController
|
|||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($view);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorConfigSettingsController
|
||||
extends PhabricatorConfigController {
|
||||
|
||||
public function newNavigation($select_filter) {
|
||||
$settings_uri = $this->getApplicationURI('settings/');
|
||||
|
||||
$nav = id(new AphrontSideNavFilterView())
|
||||
->setBaseURI(new PhutilURI($settings_uri));
|
||||
|
||||
$nav->addLabel(pht('Configuration'));
|
||||
|
||||
$nav->newLink('settings')
|
||||
->setName(pht('Core Settings'))
|
||||
->setIcon('fa-wrench')
|
||||
->setHref($settings_uri);
|
||||
|
||||
$nav->newLink('advanced')
|
||||
->setName(pht('Advanced Settings'))
|
||||
->setIcon('fa-cogs')
|
||||
->setHref(urisprintf('%s%s/', $settings_uri, 'advanced'));
|
||||
|
||||
$nav->newLink('all')
|
||||
->setName(pht('All Settings'))
|
||||
->setIcon('fa-list')
|
||||
->setHref(urisprintf('%s%s/', $settings_uri, 'all'));
|
||||
|
||||
$nav->addLabel(pht('History'));
|
||||
|
||||
$nav->newLink('history')
|
||||
->setName(pht('View History'))
|
||||
->setIcon('fa-history')
|
||||
->setHref(urisprintf('%s%s/', $settings_uri, 'history'));
|
||||
|
||||
if ($select_filter) {
|
||||
$nav->selectFilter($select_filter);
|
||||
}
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
public function newCrumbs() {
|
||||
$settings_uri = $this->getApplicationURI('settings/');
|
||||
|
||||
return $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Settings'), $settings_uri)
|
||||
->setBorder(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigHistoryController
|
||||
extends PhabricatorConfigController {
|
||||
final class PhabricatorConfigSettingsHistoryController
|
||||
extends PhabricatorConfigSettingsController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
@ -27,12 +27,10 @@ final class PhabricatorConfigHistoryController
|
|||
$title = pht('Settings History');
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$nav = $this->buildSideNavView();
|
||||
$nav->selectFilter('history/');
|
||||
$nav = $this->newNavigation('history');
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb($title)
|
||||
->setBorder(true);
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConfigSettingsListController
|
||||
extends PhabricatorConfigSettingsController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$filter = $request->getURIData('filter');
|
||||
if (!strlen($filter)) {
|
||||
$filter = 'settings';
|
||||
}
|
||||
|
||||
$is_core = ($filter === 'settings');
|
||||
$is_advanced = ($filter === 'advanced');
|
||||
$is_all = ($filter === 'all');
|
||||
|
||||
$show_core = ($is_core || $is_all);
|
||||
$show_advanced = ($is_advanced || $is_all);
|
||||
|
||||
if ($is_core) {
|
||||
$title = pht('Core Settings');
|
||||
} else if ($is_advanced) {
|
||||
$title = pht('Advanced Settings');
|
||||
} else {
|
||||
$title = pht('All Settings');
|
||||
}
|
||||
|
||||
$db_values = id(new PhabricatorConfigEntry())
|
||||
->loadAllWhere('namespace = %s', 'default');
|
||||
$db_values = mpull($db_values, null, 'getConfigKey');
|
||||
|
||||
$list = id(new PHUIObjectItemListView())
|
||||
->setBig(true)
|
||||
->setFlush(true);
|
||||
|
||||
$rows = array();
|
||||
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
||||
ksort($options);
|
||||
foreach ($options as $option) {
|
||||
$key = $option->getKey();
|
||||
|
||||
$is_advanced = (bool)$option->getLocked();
|
||||
if ($is_advanced && !$show_advanced) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$is_advanced && !$show_core) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$db_value = idx($db_values, $key);
|
||||
|
||||
$item = $this->newConfigOptionView($option, $db_value);
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
$header = $this->buildHeaderView($title);
|
||||
|
||||
$crumbs = $this->newCrumbs()
|
||||
->addTextCrumb($title);
|
||||
|
||||
$content = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter($list);
|
||||
|
||||
$nav = $this->newNavigation($filter);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($nav)
|
||||
->appendChild($content);
|
||||
}
|
||||
|
||||
private function newConfigOptionView(
|
||||
PhabricatorConfigOption $option,
|
||||
PhabricatorConfigEntry $stored_value = null) {
|
||||
|
||||
$summary = $option->getSummary();
|
||||
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($option->getKey())
|
||||
->setClickable(true)
|
||||
->setHref('/config/edit/'.$option->getKey().'/')
|
||||
->addAttribute($summary);
|
||||
|
||||
$color = null;
|
||||
if ($stored_value && !$stored_value->getIsDeleted()) {
|
||||
$item->setEffect('visited');
|
||||
$color = 'violet';
|
||||
}
|
||||
|
||||
if ($option->getHidden()) {
|
||||
$item->setStatusIcon('fa-eye-slash', pht('Hidden'));
|
||||
} else if ($option->getLocked()) {
|
||||
$item->setStatusIcon('fa-lock '.$color, pht('Locked'));
|
||||
} else if ($color) {
|
||||
$item->setStatusIcon('fa-pencil '.$color, pht('Editable'));
|
||||
} else {
|
||||
$item->setStatusIcon('fa-circle-o grey', pht('Default'));
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
}
|
|
@ -59,9 +59,11 @@ final class PhabricatorDashboardConsoleController
|
|||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setObjectList($menu);
|
||||
|
||||
$launch_view = id(new PHUILauncherView())
|
||||
->appendChild($box);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFixed(true)
|
||||
->setFooter($box);
|
||||
->setFooter($launch_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
|
|
|
@ -78,14 +78,16 @@ final class DiffusionRepositoryEditController
|
|||
->addClass('diffusion-create-repo')
|
||||
->appendChild($layout);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFixed(true)
|
||||
->setFooter(
|
||||
$launcher_view = id(new PHUILauncherView())
|
||||
->appendChild(
|
||||
array(
|
||||
$layout,
|
||||
$hints,
|
||||
));
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFooter($launcher_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
|
|
|
@ -76,9 +76,11 @@ final class DrydockConsoleController extends DrydockController {
|
|||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setObjectList($menu);
|
||||
|
||||
$launcher_view = id(new PHUILauncherView())
|
||||
->appendChild($box);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFixed(true)
|
||||
->setFooter($box);
|
||||
->setFooter($launcher_view);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
|
|
|
@ -179,18 +179,23 @@ final class HarbormasterBuildUnitMessage
|
|||
|
||||
$is_text = ($format !== self::FORMAT_REMARKUP);
|
||||
$is_remarkup = ($format === self::FORMAT_REMARKUP);
|
||||
$message = null;
|
||||
|
||||
$full_details = $this->getUnitMessageDetails();
|
||||
$byte_length = strlen($full_details);
|
||||
|
||||
if (!strlen($full_details)) {
|
||||
$text_limit = 1024 * 2;
|
||||
$remarkup_limit = 1024 * 8;
|
||||
|
||||
if (!$byte_length) {
|
||||
if ($summarize) {
|
||||
return null;
|
||||
}
|
||||
$details = phutil_tag('em', array(), pht('No details provided.'));
|
||||
$message = phutil_tag('em', array(), pht('No details provided.'));
|
||||
} else if ($summarize) {
|
||||
if ($is_text) {
|
||||
$details = id(new PhutilUTF8StringTruncator())
|
||||
->setMaximumBytes(2048)
|
||||
->setMaximumBytes($text_limit)
|
||||
->truncateString($full_details);
|
||||
$details = phutil_split_lines($details);
|
||||
|
||||
|
@ -200,9 +205,36 @@ final class HarbormasterBuildUnitMessage
|
|||
}
|
||||
|
||||
$details = implode('', $details);
|
||||
} else {
|
||||
if ($byte_length > $remarkup_limit) {
|
||||
$uri = $this->getURI();
|
||||
|
||||
if ($uri) {
|
||||
$link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $uri,
|
||||
'target' => '_blank',
|
||||
),
|
||||
pht('View Details'));
|
||||
} else {
|
||||
$link = null;
|
||||
}
|
||||
|
||||
$message = array();
|
||||
$message[] = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht('This test has too much data to display inline.'));
|
||||
if ($link) {
|
||||
$message[] = $link;
|
||||
}
|
||||
|
||||
$message = phutil_implode_html(" \xC2\xB7 ", $message);
|
||||
} else {
|
||||
$details = $full_details;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$details = $full_details;
|
||||
}
|
||||
|
@ -212,19 +244,47 @@ final class HarbormasterBuildUnitMessage
|
|||
$classes = array();
|
||||
$classes[] = 'harbormaster-unit-details';
|
||||
|
||||
if ($is_remarkup) {
|
||||
if ($message !== null) {
|
||||
// If we have a message, show that instead of rendering any test details.
|
||||
$details = $message;
|
||||
} else if ($is_remarkup) {
|
||||
$details = new PHUIRemarkupView($viewer, $details);
|
||||
} else {
|
||||
$classes[] = 'harbormaster-unit-details-text';
|
||||
$classes[] = 'PhabricatorMonospaced';
|
||||
}
|
||||
|
||||
return phutil_tag(
|
||||
$warning = null;
|
||||
if (!$summarize) {
|
||||
$warnings = array();
|
||||
|
||||
if ($is_remarkup && ($byte_length > $remarkup_limit)) {
|
||||
$warnings[] = pht(
|
||||
'This test result has %s bytes of Remarkup test details. Remarkup '.
|
||||
'blocks longer than %s bytes are not rendered inline when showing '.
|
||||
'test summaries.',
|
||||
new PhutilNumber($byte_length),
|
||||
new PhutilNumber($remarkup_limit));
|
||||
}
|
||||
|
||||
if ($warnings) {
|
||||
$warning = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||
->setErrors($warnings);
|
||||
}
|
||||
}
|
||||
|
||||
$content = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => implode(' ', $classes),
|
||||
),
|
||||
$details);
|
||||
|
||||
return array(
|
||||
$warning,
|
||||
$content,
|
||||
);
|
||||
}
|
||||
|
||||
public function getUnitMessageDisplayName() {
|
||||
|
@ -262,6 +322,18 @@ final class HarbormasterBuildUnitMessage
|
|||
return implode("\0", $parts);
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
$id = $this->getID();
|
||||
|
||||
if (!$id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return urisprintf(
|
||||
'/harbormaster/unit/view/%d/',
|
||||
$id);
|
||||
}
|
||||
|
||||
public function save() {
|
||||
if ($this->nameIndex === null) {
|
||||
$this->nameIndex = HarbormasterString::newIndex($this->getName());
|
||||
|
|
|
@ -72,13 +72,13 @@ final class HarbormasterUnitPropertyView extends AphrontView {
|
|||
}
|
||||
|
||||
$name = $message->getUnitMessageDisplayName();
|
||||
$id = $message->getID();
|
||||
$uri = $message->getURI();
|
||||
|
||||
if ($id) {
|
||||
if ($uri) {
|
||||
$name = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => "/harbormaster/unit/view/{$id}/",
|
||||
'href' => $uri,
|
||||
),
|
||||
$name);
|
||||
}
|
||||
|
|
|
@ -243,6 +243,12 @@ abstract class HeraldAdapter extends Phobject {
|
|||
abstract public function getAdapterApplicationClass();
|
||||
abstract public function getObject();
|
||||
|
||||
public function getAdapterContentIcon() {
|
||||
$application_class = $this->getAdapterApplicationClass();
|
||||
$application = newv($application_class, array());
|
||||
return $application->getIcon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new characteristic object for this adapter.
|
||||
*
|
||||
|
|
|
@ -3,42 +3,39 @@
|
|||
final class HeraldNewController extends HeraldController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$adapter_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);
|
||||
$adapter_type = $request->getStr('adapter');
|
||||
|
||||
if (!isset($adapter_type_map[$adapter_type])) {
|
||||
$title = pht('Create Herald Rule');
|
||||
$content = $this->newAdapterMenu($title);
|
||||
} else {
|
||||
$adapter = HeraldAdapter::getAdapterForContentType($adapter_type);
|
||||
|
||||
$content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);
|
||||
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
|
||||
$rule_type = $request->getStr('type');
|
||||
|
||||
if (!isset($rule_type_map[$rule_type])) {
|
||||
$title = pht(
|
||||
'Create Herald Rule: %s',
|
||||
$adapter->getAdapterContentName());
|
||||
|
||||
$content = $this->newTypeMenu($adapter, $title);
|
||||
} else {
|
||||
if ($rule_type !== HeraldRuleTypeConfig::RULE_TYPE_OBJECT) {
|
||||
$target_phid = null;
|
||||
$target_okay = true;
|
||||
} else {
|
||||
$object_name = $request->getStr('objectName');
|
||||
$target_okay = false;
|
||||
|
||||
$errors = array();
|
||||
|
||||
$e_type = null;
|
||||
$e_rule = null;
|
||||
$e_object = null;
|
||||
|
||||
$step = $request->getInt('step');
|
||||
if ($request->isFormPost()) {
|
||||
$content_type = $request->getStr('content_type');
|
||||
if (empty($content_type_map[$content_type])) {
|
||||
$errors[] = pht('You must choose a content type for this rule.');
|
||||
$e_type = pht('Required');
|
||||
$step = 0;
|
||||
}
|
||||
|
||||
if (!$errors && $step > 1) {
|
||||
$rule_type = $request->getStr('rule_type');
|
||||
if (empty($rule_type_map[$rule_type])) {
|
||||
$errors[] = pht('You must choose a rule type for this rule.');
|
||||
$e_rule = pht('Required');
|
||||
$step = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors && $step >= 2) {
|
||||
$target_phid = null;
|
||||
$object_name = $request->getStr('objectName');
|
||||
$done = false;
|
||||
if ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_OBJECT) {
|
||||
$done = true;
|
||||
} else if (strlen($object_name)) {
|
||||
if (strlen($object_name)) {
|
||||
$target_object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($object_name))
|
||||
|
@ -50,99 +47,255 @@ final class HeraldNewController extends HeraldController {
|
|||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
if (!$can_edit) {
|
||||
$errors[] = pht(
|
||||
'You can not create a rule for that object, because you do '.
|
||||
'not have permission to edit it. You can only create rules '.
|
||||
'for objects you can edit.');
|
||||
'You can not create a rule for that object, because you '.
|
||||
'do not have permission to edit it. You can only create '.
|
||||
'rules for objects you can edit.');
|
||||
$e_object = pht('Not Editable');
|
||||
$step = 2;
|
||||
} else {
|
||||
$adapter = HeraldAdapter::getAdapterForContentType($content_type);
|
||||
if (!$adapter->canTriggerOnObject($target_object)) {
|
||||
$errors[] = pht(
|
||||
'This object is not of an allowed type for the rule. '.
|
||||
'Rules can only trigger on certain objects.');
|
||||
$e_object = pht('Invalid');
|
||||
$step = 2;
|
||||
} else {
|
||||
$target_phid = $target_object->getPHID();
|
||||
$done = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$errors[] = pht('No object exists by that name.');
|
||||
$e_object = pht('Invalid');
|
||||
$step = 2;
|
||||
}
|
||||
} else if ($step > 2) {
|
||||
} else {
|
||||
$errors[] = pht(
|
||||
'You must choose an object to associate this rule with.');
|
||||
$e_object = pht('Required');
|
||||
$step = 2;
|
||||
}
|
||||
|
||||
if (!$errors && $done) {
|
||||
$target_okay = !$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$target_okay) {
|
||||
$title = pht('Choose Object');
|
||||
$content = $this->newTargetForm(
|
||||
$adapter,
|
||||
$rule_type,
|
||||
$object_name,
|
||||
$errors,
|
||||
$e_object,
|
||||
$title);
|
||||
} else {
|
||||
$params = array(
|
||||
'content_type' => $content_type,
|
||||
'content_type' => $adapter_type,
|
||||
'rule_type' => $rule_type,
|
||||
'targetPHID' => $target_phid,
|
||||
);
|
||||
|
||||
$uri = new PhutilURI('edit/', $params);
|
||||
$uri = $this->getApplicationURI($uri);
|
||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||
$edit_uri = $this->getApplicationURI('edit/');
|
||||
$edit_uri = new PhutilURI($edit_uri, $params);
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($edit_uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$content_type = $request->getStr('content_type');
|
||||
$rule_type = $request->getStr('rule_type');
|
||||
$crumbs = $this
|
||||
->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Create Rule'))
|
||||
->setBorder(true);
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->setAction($this->getApplicationURI('new/'));
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFooter($content);
|
||||
|
||||
switch ($step) {
|
||||
case 0:
|
||||
default:
|
||||
$content_types = $this->renderContentTypeControl(
|
||||
$content_type_map,
|
||||
$e_type);
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($view);
|
||||
}
|
||||
|
||||
$form
|
||||
->addHiddenInput('step', 1)
|
||||
->appendChild($content_types);
|
||||
private function newAdapterMenu($title) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$cancel_text = null;
|
||||
$cancel_uri = $this->getApplicationURI();
|
||||
$title = pht('Create Herald Rule');
|
||||
break;
|
||||
case 1:
|
||||
$rule_types = $this->renderRuleTypeControl(
|
||||
$rule_type_map,
|
||||
$e_rule);
|
||||
$types = HeraldAdapter::getEnabledAdapterMap($viewer);
|
||||
|
||||
$form
|
||||
->addHiddenInput('content_type', $content_type)
|
||||
->addHiddenInput('step', 2)
|
||||
->appendChild($rule_types);
|
||||
foreach ($types as $key => $type) {
|
||||
$types[$key] = HeraldAdapter::getAdapterForContentType($key);
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'content_type' => $content_type,
|
||||
'step' => '0',
|
||||
$types = msort($types, 'getAdapterContentName');
|
||||
|
||||
$base_uri = $this->getApplicationURI('create/');
|
||||
|
||||
$menu = id(new PHUIObjectItemListView())
|
||||
->setViewer($viewer)
|
||||
->setBig(true);
|
||||
|
||||
foreach ($types as $key => $adapter) {
|
||||
$adapter_uri = id(new PhutilURI($base_uri))
|
||||
->replaceQueryParam('adapter', $key);
|
||||
|
||||
$description = $adapter->getAdapterContentDescription();
|
||||
$description = phutil_escape_html_newlines($description);
|
||||
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($adapter->getAdapterContentName())
|
||||
->setImageIcon($adapter->getAdapterContentIcon())
|
||||
->addAttribute($description)
|
||||
->setHref($adapter_uri)
|
||||
->setClickable(true);
|
||||
|
||||
$menu->addItem($item);
|
||||
}
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText($title)
|
||||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setObjectList($menu);
|
||||
|
||||
return id(new PHUILauncherView())
|
||||
->appendChild($box);
|
||||
}
|
||||
|
||||
private function newTypeMenu(HeraldAdapter $adapter, $title) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$global_capability = HeraldManageGlobalRulesCapability::CAPABILITY;
|
||||
$can_global = $this->hasApplicationCapability($global_capability);
|
||||
|
||||
if ($can_global) {
|
||||
$global_note = pht(
|
||||
'You have permission to create and manage global rules.');
|
||||
} else {
|
||||
$global_note = pht(
|
||||
'You do not have permission to create or manage global rules.');
|
||||
}
|
||||
$global_note = phutil_tag('em', array(), $global_note);
|
||||
|
||||
$specs = array(
|
||||
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL => array(
|
||||
'name' => pht('Personal Rule'),
|
||||
'icon' => 'fa-user',
|
||||
'help' => pht(
|
||||
'Personal rules notify you about events. You own them, but they can '.
|
||||
'only affect you. Personal rules only trigger for objects you have '.
|
||||
'permission to see.'),
|
||||
'enabled' => true,
|
||||
),
|
||||
HeraldRuleTypeConfig::RULE_TYPE_OBJECT => array(
|
||||
'name' => pht('Object Rule'),
|
||||
'icon' => 'fa-cube',
|
||||
'help' => pht(
|
||||
'Object rules notify anyone about events. They are bound to an '.
|
||||
'object (like a repository) and can only act on that object. You '.
|
||||
'must be able to edit an object to create object rules for it. '.
|
||||
'Other users who can edit the object can edit its rules.'),
|
||||
'enabled' => true,
|
||||
),
|
||||
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL => array(
|
||||
'name' => pht('Global Rule'),
|
||||
'icon' => 'fa-globe',
|
||||
'help' => array(
|
||||
pht(
|
||||
'Global rules notify anyone about events. Global rules can '.
|
||||
'bypass access control policies and act on any object.'),
|
||||
$global_note,
|
||||
),
|
||||
'enabled' => $can_global,
|
||||
),
|
||||
);
|
||||
|
||||
$cancel_text = pht('Back');
|
||||
$cancel_uri = new PhutilURI('new/', $params);
|
||||
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
||||
$title = pht('Create Herald Rule: %s',
|
||||
idx($content_type_map, $content_type));
|
||||
break;
|
||||
case 2:
|
||||
$adapter = HeraldAdapter::getAdapterForContentType($content_type);
|
||||
$form
|
||||
->addHiddenInput('content_type', $content_type)
|
||||
->addHiddenInput('rule_type', $rule_type)
|
||||
->addHiddenInput('step', 3)
|
||||
$adapter_type = $adapter->getAdapterContentType();
|
||||
|
||||
$base_uri = new PhutilURI($this->getApplicationURI('create/'));
|
||||
|
||||
$adapter_uri = id(clone $base_uri)
|
||||
->replaceQueryParam('adapter', $adapter_type);
|
||||
|
||||
$menu = id(new PHUIObjectItemListView())
|
||||
->setUser($viewer)
|
||||
->setBig(true);
|
||||
|
||||
foreach ($specs as $rule_type => $spec) {
|
||||
$type_uri = id(clone $adapter_uri)
|
||||
->replaceQueryParam('type', $rule_type);
|
||||
|
||||
$name = $spec['name'];
|
||||
$icon = $spec['icon'];
|
||||
|
||||
$description = $spec['help'];
|
||||
$description = (array)$description;
|
||||
|
||||
$enabled = $spec['enabled'];
|
||||
if ($enabled) {
|
||||
$enabled = $adapter->supportsRuleType($rule_type);
|
||||
if (!$enabled) {
|
||||
$description[] = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht(
|
||||
'This rule type is not supported by the selected '.
|
||||
'content type.'));
|
||||
}
|
||||
}
|
||||
|
||||
$description = phutil_implode_html(
|
||||
array(
|
||||
phutil_tag('br'),
|
||||
phutil_tag('br'),
|
||||
),
|
||||
$description);
|
||||
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setHeader($name)
|
||||
->setImageIcon($icon)
|
||||
->addAttribute($description);
|
||||
|
||||
if ($enabled) {
|
||||
$item
|
||||
->setHref($type_uri)
|
||||
->setClickable(true);
|
||||
} else {
|
||||
$item->setDisabled(true);
|
||||
}
|
||||
|
||||
$menu->addItem($item);
|
||||
}
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText($title)
|
||||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setObjectList($menu);
|
||||
|
||||
$box->newTailButton()
|
||||
->setText(pht('Back to Content Types'))
|
||||
->setIcon('fa-chevron-left')
|
||||
->setHref($base_uri);
|
||||
|
||||
return id(new PHUILauncherView())
|
||||
->appendChild($box);
|
||||
}
|
||||
|
||||
|
||||
private function newTargetForm(
|
||||
HeraldAdapter $adapter,
|
||||
$rule_type,
|
||||
$object_name,
|
||||
$errors,
|
||||
$e_object,
|
||||
$title) {
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$content_type = $adapter->getAdapterContentType();
|
||||
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
|
||||
|
||||
$params = array(
|
||||
'adapter' => $content_type,
|
||||
'type' => $rule_type,
|
||||
);
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setViewer($viewer)
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel(pht('Rule for'))
|
||||
|
@ -150,7 +303,7 @@ final class HeraldNewController extends HeraldController {
|
|||
phutil_tag(
|
||||
'strong',
|
||||
array(),
|
||||
idx($content_type_map, $content_type))))
|
||||
$adapter->getAdapterContentName())))
|
||||
->appendChild(
|
||||
id(new AphrontFormStaticControl())
|
||||
->setLabel(pht('Rule Type'))
|
||||
|
@ -170,28 +323,23 @@ final class HeraldNewController extends HeraldController {
|
|||
id(new AphrontFormTextControl())
|
||||
->setName('objectName')
|
||||
->setError($e_object)
|
||||
->setValue($request->getStr('objectName'))
|
||||
->setValue($object_name)
|
||||
->setLabel(pht('Object')));
|
||||
|
||||
$params = array(
|
||||
'content_type' => $content_type,
|
||||
'rule_type' => $rule_type,
|
||||
'step' => 1,
|
||||
);
|
||||
|
||||
$cancel_text = pht('Back');
|
||||
$cancel_uri = new PhutilURI('new/', $params);
|
||||
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
||||
$title = pht('Create Herald Rule: %s',
|
||||
idx($content_type_map, $content_type));
|
||||
break;
|
||||
foreach ($params as $key => $value) {
|
||||
$form->addHiddenInput($key, $value);
|
||||
}
|
||||
|
||||
$form
|
||||
->appendChild(
|
||||
$cancel_params = $params;
|
||||
unset($cancel_params['type']);
|
||||
|
||||
$cancel_uri = $this->getApplicationURI('new/');
|
||||
$cancel_uri = new PhutilURI($cancel_uri, $params);
|
||||
|
||||
$form->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue(pht('Continue'))
|
||||
->addCancelButton($cancel_uri, $cancel_text));
|
||||
->addCancelButton($cancel_uri, pht('Back')));
|
||||
|
||||
$form_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText($title)
|
||||
|
@ -199,118 +347,7 @@ final class HeraldNewController extends HeraldController {
|
|||
->setBackground(PHUIObjectBoxView::WHITE_CONFIG)
|
||||
->setForm($form);
|
||||
|
||||
$crumbs = $this
|
||||
->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Create Rule'))
|
||||
->setBorder(true);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setFooter($form_box);
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild(
|
||||
array(
|
||||
$view,
|
||||
));
|
||||
}
|
||||
|
||||
private function renderContentTypeControl(array $content_type_map, $e_type) {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$radio = id(new AphrontFormRadioButtonControl())
|
||||
->setLabel(pht('New Rule for'))
|
||||
->setName('content_type')
|
||||
->setValue($request->getStr('content_type'))
|
||||
->setError($e_type);
|
||||
|
||||
foreach ($content_type_map as $value => $name) {
|
||||
$adapter = HeraldAdapter::getAdapterForContentType($value);
|
||||
$radio->addButton(
|
||||
$value,
|
||||
$name,
|
||||
phutil_escape_html_newlines($adapter->getAdapterContentDescription()));
|
||||
}
|
||||
|
||||
return $radio;
|
||||
}
|
||||
|
||||
|
||||
private function renderRuleTypeControl(array $rule_type_map, $e_rule) {
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Reorder array to put less powerful rules first.
|
||||
$rule_type_map = array_select_keys(
|
||||
$rule_type_map,
|
||||
array(
|
||||
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL,
|
||||
HeraldRuleTypeConfig::RULE_TYPE_OBJECT,
|
||||
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL,
|
||||
)) + $rule_type_map;
|
||||
|
||||
list($can_global, $global_link) = $this->explainApplicationCapability(
|
||||
HeraldManageGlobalRulesCapability::CAPABILITY,
|
||||
pht('You have permission to create and manage global rules.'),
|
||||
pht('You do not have permission to create or manage global rules.'));
|
||||
|
||||
$captions = array(
|
||||
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL =>
|
||||
pht(
|
||||
'Personal rules notify you about events. You own them, but they can '.
|
||||
'only affect you. Personal rules only trigger for objects you have '.
|
||||
'permission to see.'),
|
||||
HeraldRuleTypeConfig::RULE_TYPE_OBJECT =>
|
||||
pht(
|
||||
'Object rules notify anyone about events. They are bound to an '.
|
||||
'object (like a repository) and can only act on that object. You '.
|
||||
'must be able to edit an object to create object rules for it. '.
|
||||
'Other users who can edit the object can edit its rules.'),
|
||||
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL =>
|
||||
array(
|
||||
pht(
|
||||
'Global rules notify anyone about events. Global rules can '.
|
||||
'bypass access control policies and act on any object.'),
|
||||
$global_link,
|
||||
),
|
||||
);
|
||||
|
||||
$radio = id(new AphrontFormRadioButtonControl())
|
||||
->setLabel(pht('Rule Type'))
|
||||
->setName('rule_type')
|
||||
->setValue($request->getStr('rule_type'))
|
||||
->setError($e_rule);
|
||||
|
||||
$adapter = HeraldAdapter::getAdapterForContentType(
|
||||
$request->getStr('content_type'));
|
||||
|
||||
foreach ($rule_type_map as $value => $name) {
|
||||
$caption = idx($captions, $value);
|
||||
$disabled = ($value == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) &&
|
||||
(!$can_global);
|
||||
|
||||
if (!$adapter->supportsRuleType($value)) {
|
||||
$disabled = true;
|
||||
$caption = array(
|
||||
$caption,
|
||||
"\n\n",
|
||||
phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht(
|
||||
'This rule type is not supported by the selected content type.')),
|
||||
);
|
||||
}
|
||||
|
||||
$radio->addButton(
|
||||
$value,
|
||||
$name,
|
||||
phutil_escape_html_newlines($caption),
|
||||
$disabled ? 'disabled' : null,
|
||||
$disabled);
|
||||
}
|
||||
|
||||
return $radio;
|
||||
return $form_box;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -336,41 +336,36 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
|||
$curtain->addAction($relationship_submenu);
|
||||
}
|
||||
|
||||
$viewer_phid = $viewer->getPHID();
|
||||
$owner_phid = $task->getOwnerPHID();
|
||||
$author_phid = $task->getAuthorPHID();
|
||||
$handles = $viewer->loadHandles(array($owner_phid, $author_phid));
|
||||
|
||||
$assigned_refs = id(new PHUICurtainObjectRefListView())
|
||||
->setViewer($viewer)
|
||||
->setEmptyMessage(pht('None'));
|
||||
|
||||
if ($owner_phid) {
|
||||
$image_uri = $handles[$owner_phid]->getImageURI();
|
||||
$image_href = $handles[$owner_phid]->getURI();
|
||||
$owner = $viewer->renderHandle($owner_phid)->render();
|
||||
$content = phutil_tag('strong', array(), $owner);
|
||||
$assigned_to = id(new PHUIHeadThingView())
|
||||
->setImage($image_uri)
|
||||
->setImageHref($image_href)
|
||||
->setContent($content);
|
||||
} else {
|
||||
$assigned_to = phutil_tag('em', array(), pht('None'));
|
||||
$assigned_ref = $assigned_refs->newObjectRefView()
|
||||
->setHandle($handles[$owner_phid])
|
||||
->setHighlighted($owner_phid === $viewer_phid);
|
||||
}
|
||||
|
||||
$curtain->newPanel()
|
||||
->setHeaderText(pht('Assigned To'))
|
||||
->appendChild($assigned_to);
|
||||
->appendChild($assigned_refs);
|
||||
|
||||
$author_uri = $handles[$author_phid]->getImageURI();
|
||||
$author_href = $handles[$author_phid]->getURI();
|
||||
$author = $viewer->renderHandle($author_phid)->render();
|
||||
$content = phutil_tag('strong', array(), $author);
|
||||
$date = phabricator_date($task->getDateCreated(), $viewer);
|
||||
$content = pht('%s, %s', $content, $date);
|
||||
$authored_by = id(new PHUIHeadThingView())
|
||||
->setImage($author_uri)
|
||||
->setImageHref($author_href)
|
||||
->setContent($content);
|
||||
$author_refs = id(new PHUICurtainObjectRefListView())
|
||||
->setViewer($viewer);
|
||||
|
||||
$author_ref = $author_refs->newObjectRefView()
|
||||
->setHandle($handles[$author_phid])
|
||||
->setEpoch($task->getDateCreated())
|
||||
->setHighlighted($author_phid === $viewer_phid);
|
||||
|
||||
$curtain->newPanel()
|
||||
->setHeaderText(pht('Authored By'))
|
||||
->appendChild($authored_by);
|
||||
->appendChild($author_refs);
|
||||
|
||||
return $curtain;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ final class PhabricatorAphlictSetupCheck extends PhabricatorSetupCheck {
|
|||
$this->newIssue('aphlict.connect')
|
||||
->setShortName(pht('Notification Server Down'))
|
||||
->setName(pht('Unable to Connect to Notification Server'))
|
||||
->setSummary(
|
||||
pht(
|
||||
'Phabricator is configured to use a notification server, '.
|
||||
'but is not able to connect to it.'))
|
||||
->setMessage($message)
|
||||
->addRelatedPhabricatorConfig('notification.servers')
|
||||
->addCommand(
|
||||
|
|
|
@ -271,6 +271,25 @@ final class PhabricatorProjectQuery
|
|||
|
||||
$all_graph = $this->getAllReachableAncestors($projects);
|
||||
|
||||
// See T13484. If the graph is damaged (and contains a cycle or an edge
|
||||
// pointing at a project which has been destroyed), some of the nodes we
|
||||
// started with may be filtered out by reachability tests. If any of the
|
||||
// projects we are linking up don't have available ancestors, filter them
|
||||
// out.
|
||||
|
||||
foreach ($projects as $key => $project) {
|
||||
$project_phid = $project->getPHID();
|
||||
if (!isset($all_graph[$project_phid])) {
|
||||
$this->didRejectResult($project);
|
||||
unset($projects[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$projects) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// NOTE: Although we may not need much information about ancestors, we
|
||||
// always need to test if the viewer is a member, because we will return
|
||||
// ancestor projects to the policy filter via ExtendedPolicy calls. If
|
||||
|
|
|
@ -15,25 +15,131 @@ final class PhabricatorSubscriptionsCurtainExtension
|
|||
|
||||
public function buildCurtainPanel($object) {
|
||||
$viewer = $this->getViewer();
|
||||
$viewer_phid = $viewer->getPHID();
|
||||
$object_phid = $object->getPHID();
|
||||
|
||||
$max_handles = 100;
|
||||
$max_visible = 8;
|
||||
|
||||
// TODO: We should limit the number of subscriber PHIDs we'll load, so
|
||||
// we degrade gracefully when objects have thousands of subscribers.
|
||||
|
||||
$subscriber_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
||||
$object_phid);
|
||||
$subscriber_count = count($subscriber_phids);
|
||||
|
||||
$subscriber_phids = $this->sortSubscriberPHIDs(
|
||||
$subscriber_phids,
|
||||
null);
|
||||
|
||||
// If we have fewer subscribers than the maximum number of handles we're
|
||||
// willing to load, load all the handles and then sort the list based on
|
||||
// complete handle data.
|
||||
|
||||
// If we have too many PHIDs, we'll skip this step and accept a less
|
||||
// useful ordering.
|
||||
$handles = null;
|
||||
if ($subscriber_count <= $max_handles) {
|
||||
$handles = $viewer->loadHandles($subscriber_phids);
|
||||
|
||||
// TODO: This class can't accept a HandleList yet.
|
||||
$handles = iterator_to_array($handles);
|
||||
$subscriber_phids = $this->sortSubscriberPHIDs(
|
||||
$subscriber_phids,
|
||||
$handles);
|
||||
}
|
||||
|
||||
$susbscribers_view = id(new SubscriptionListStringBuilder())
|
||||
->setObjectPHID($object_phid)
|
||||
->setHandles($handles)
|
||||
->buildPropertyString();
|
||||
// If we have more PHIDs to show than visible slots, slice the list.
|
||||
if ($subscriber_count > $max_visible) {
|
||||
$visible_phids = array_slice($subscriber_phids, 0, $max_visible - 1);
|
||||
$show_all = true;
|
||||
} else {
|
||||
$visible_phids = $subscriber_phids;
|
||||
$show_all = false;
|
||||
}
|
||||
|
||||
// If we didn't load handles earlier because we had too many PHIDs,
|
||||
// load them now.
|
||||
if ($handles === null) {
|
||||
$handles = $viewer->loadHandles($visible_phids);
|
||||
}
|
||||
|
||||
$ref_list = id(new PHUICurtainObjectRefListView())
|
||||
->setViewer($viewer)
|
||||
->setEmptyMessage(pht('None'));
|
||||
|
||||
foreach ($visible_phids as $phid) {
|
||||
$ref = $ref_list->newObjectRefView()
|
||||
->setHandle($handles[$phid]);
|
||||
|
||||
if ($phid === $viewer_phid) {
|
||||
$ref->setHighlighted(true);
|
||||
}
|
||||
}
|
||||
|
||||
if ($show_all) {
|
||||
$view_all_uri = urisprintf(
|
||||
'/subscriptions/list/%s/',
|
||||
$object_phid);
|
||||
|
||||
$ref_list->newTailLink()
|
||||
->setURI($view_all_uri)
|
||||
->setText(pht('View All %d Subscriber(s)', $subscriber_count))
|
||||
->setWorkflow(true);
|
||||
}
|
||||
|
||||
return $this->newPanel()
|
||||
->setHeaderText(pht('Subscribers'))
|
||||
->setOrder(20000)
|
||||
->appendChild($susbscribers_view);
|
||||
->appendChild($ref_list);
|
||||
}
|
||||
|
||||
private function sortSubscriberPHIDs(array $subscriber_phids, $handles) {
|
||||
|
||||
// Sort subscriber PHIDs with or without handle data. If we have handles,
|
||||
// we can sort results more comprehensively.
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$user_type = PhabricatorPeopleUserPHIDType::TYPECONST;
|
||||
$viewer_phid = $viewer->getPHID();
|
||||
|
||||
$type_order_map = array(
|
||||
PhabricatorPeopleUserPHIDType::TYPECONST => 0,
|
||||
PhabricatorProjectProjectPHIDType::TYPECONST => 1,
|
||||
PhabricatorOwnersPackagePHIDType::TYPECONST => 2,
|
||||
);
|
||||
$default_type_order = count($type_order_map);
|
||||
|
||||
$subscriber_map = array();
|
||||
foreach ($subscriber_phids as $subscriber_phid) {
|
||||
$is_viewer = ($viewer_phid === $subscriber_phid);
|
||||
|
||||
$subscriber_type = phid_get_type($subscriber_phid);
|
||||
$type_order = idx($type_order_map, $subscriber_type, $default_type_order);
|
||||
|
||||
$sort_name = '';
|
||||
$is_complete = false;
|
||||
if ($handles) {
|
||||
if (isset($handles[$subscriber_phid])) {
|
||||
$handle = $handles[$subscriber_phid];
|
||||
if ($handle->isComplete()) {
|
||||
$is_complete = true;
|
||||
|
||||
$sort_name = $handle->getLinkName();
|
||||
$sort_name = phutil_utf8_strtolower($sort_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$subscriber_map[$subscriber_phid] = id(new PhutilSortVector())
|
||||
->addInt($is_viewer ? 0 : 1)
|
||||
->addInt($is_complete ? 0 : 1)
|
||||
->addInt($type_order)
|
||||
->addString($sort_name);
|
||||
}
|
||||
|
||||
$subscriber_map = msortv($subscriber_map, 'getSelf');
|
||||
|
||||
return array_keys($subscriber_map);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,13 @@ final class PhabricatorEdgeQuery extends PhabricatorQuery {
|
|||
* @task config
|
||||
*/
|
||||
public function withSourcePHIDs(array $source_phids) {
|
||||
if (!$source_phids) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Edge list passed to "withSourcePHIDs(...)" is empty, but it must '.
|
||||
'be nonempty.'));
|
||||
}
|
||||
|
||||
$this->sourcePHIDs = $source_phids;
|
||||
return $this;
|
||||
}
|
||||
|
@ -158,11 +165,10 @@ final class PhabricatorEdgeQuery extends PhabricatorQuery {
|
|||
* @task exec
|
||||
*/
|
||||
public function execute() {
|
||||
if (!$this->sourcePHIDs) {
|
||||
if ($this->sourcePHIDs === null) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'You must use %s to query edges.',
|
||||
'withSourcePHIDs()'));
|
||||
'You must use "withSourcePHIDs()" to query edges.'));
|
||||
}
|
||||
|
||||
$sources = phid_group_by_type($this->sourcePHIDs);
|
||||
|
|
|
@ -1718,6 +1718,11 @@ final class PhabricatorUSEnglishTranslation
|
|||
'then try again.',
|
||||
),
|
||||
|
||||
'View All %d Subscriber(s)' => array(
|
||||
'View Subscriber',
|
||||
'View All %d Subscribers',
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ final class PhabricatorMarkupEngine extends Phobject {
|
|||
private $objects = array();
|
||||
private $viewer;
|
||||
private $contextObject;
|
||||
private $version = 19;
|
||||
private $version = 20;
|
||||
private $engineCaches = array();
|
||||
private $auxiliaryConfig = array();
|
||||
|
||||
|
|
|
@ -100,6 +100,9 @@ final class PhutilRemarkupNoteBlockRule extends PhutilRemarkupBlockRule {
|
|||
}
|
||||
|
||||
private function getRegEx() {
|
||||
static $regex;
|
||||
|
||||
if ($regex === null) {
|
||||
$words = array(
|
||||
'NOTE',
|
||||
'IMPORTANT',
|
||||
|
@ -111,11 +114,14 @@ final class PhutilRemarkupNoteBlockRule extends PhutilRemarkupBlockRule {
|
|||
}
|
||||
$words = implode('|', $words);
|
||||
|
||||
return
|
||||
$regex =
|
||||
'/^(?:'.
|
||||
'(?:\((?P<hideword>'.$words.')\))'.
|
||||
'|'.
|
||||
'(?:(?P<showword>'.$words.'):))\s*'.
|
||||
'/';
|
||||
}
|
||||
|
||||
return $regex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ abstract class PhutilRemarkupQuotedBlockRule
|
|||
foreach ($text as $key => $line) {
|
||||
if (!strlen(trim($line))) {
|
||||
unset($text[$key]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,8 +121,19 @@ final class PhutilRemarkupTableBlockRule extends PhutilRemarkupBlockRule {
|
|||
return $table->newRawString();
|
||||
}
|
||||
|
||||
// Respect newlines in table cells as literal linebreaks.
|
||||
|
||||
$content = $cell->newRawContentString();
|
||||
$content = $this->applyRules($content);
|
||||
$content = trim($content, "\r\n");
|
||||
|
||||
$lines = phutil_split_lines($content, $retain_endings = false);
|
||||
foreach ($lines as $key => $line) {
|
||||
$lines[$key] = $this->applyRules($line);
|
||||
}
|
||||
|
||||
$content = phutil_implode_html(
|
||||
phutil_tag('br'),
|
||||
$lines);
|
||||
|
||||
$cell_specs[] = array(
|
||||
'type' => $cell->getTagName(),
|
||||
|
|
|
@ -153,33 +153,54 @@ final class PhutilRemarkupEngine extends PhutilMarkupEngine {
|
|||
$block_rules = $this->blockRules;
|
||||
$blocks = array();
|
||||
$cursor = 0;
|
||||
$prev_block = array();
|
||||
|
||||
$can_merge = array();
|
||||
foreach ($block_rules as $key => $block_rule) {
|
||||
if ($block_rule instanceof PhutilRemarkupDefaultBlockRule) {
|
||||
$can_merge[$key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$last_block = null;
|
||||
$last_block_key = -1;
|
||||
|
||||
// See T13487. For very large inputs, block separation can dominate
|
||||
// runtime. This is written somewhat clumsily to attempt to handle
|
||||
// very large inputs as gracefully as is practical.
|
||||
|
||||
while (isset($text[$cursor])) {
|
||||
$starting_cursor = $cursor;
|
||||
foreach ($block_rules as $block_rule) {
|
||||
foreach ($block_rules as $block_key => $block_rule) {
|
||||
$num_lines = $block_rule->getMatchingLineCount($text, $cursor);
|
||||
|
||||
if ($num_lines) {
|
||||
if ($blocks) {
|
||||
$prev_block = last($blocks);
|
||||
}
|
||||
|
||||
$curr_block = array(
|
||||
$current_block = array(
|
||||
'start' => $cursor,
|
||||
'num_lines' => $num_lines,
|
||||
'rule' => $block_rule,
|
||||
'is_empty' => self::isEmptyBlock($text, $cursor, $num_lines),
|
||||
'empty' => self::isEmptyBlock($text, $cursor, $num_lines),
|
||||
'children' => array(),
|
||||
'merge' => isset($can_merge[$block_key]),
|
||||
);
|
||||
|
||||
if ($prev_block
|
||||
&& self::shouldMergeBlocks($text, $prev_block, $curr_block)) {
|
||||
$blocks[last_key($blocks)]['num_lines'] += $curr_block['num_lines'];
|
||||
$blocks[last_key($blocks)]['is_empty'] =
|
||||
$blocks[last_key($blocks)]['is_empty'] && $curr_block['is_empty'];
|
||||
$should_merge = self::shouldMergeParagraphBlocks(
|
||||
$text,
|
||||
$last_block,
|
||||
$current_block);
|
||||
|
||||
if ($should_merge) {
|
||||
$last_block['num_lines'] =
|
||||
($last_block['num_lines'] + $current_block['num_lines']);
|
||||
|
||||
$last_block['empty'] =
|
||||
($last_block['empty'] && $current_block['empty']);
|
||||
|
||||
$blocks[$last_block_key] = $last_block;
|
||||
} else {
|
||||
$blocks[] = $curr_block;
|
||||
$blocks[] = $current_block;
|
||||
|
||||
$last_block = $current_block;
|
||||
$last_block_key++;
|
||||
}
|
||||
|
||||
$cursor += $num_lines;
|
||||
|
@ -192,9 +213,20 @@ final class PhutilRemarkupEngine extends PhutilMarkupEngine {
|
|||
}
|
||||
}
|
||||
|
||||
// See T13487. It's common for blocks to be small, and this loop seems to
|
||||
// measure as faster if we manually concatenate blocks than if we
|
||||
// "array_slice()" and "implode()" blocks. This is a bit muddy.
|
||||
|
||||
foreach ($blocks as $key => $block) {
|
||||
$lines = array_slice($text, $block['start'], $block['num_lines']);
|
||||
$blocks[$key]['text'] = implode('', $lines);
|
||||
$min = $block['start'];
|
||||
$max = $min + $block['num_lines'];
|
||||
|
||||
$lines = '';
|
||||
for ($ii = $min; $ii < $max; $ii++) {
|
||||
$lines .= $text[$ii];
|
||||
}
|
||||
|
||||
$blocks[$key]['text'] = $lines;
|
||||
}
|
||||
|
||||
// Stop splitting child blocks apart if we get too deep. This arrests
|
||||
|
@ -246,30 +278,48 @@ final class PhutilRemarkupEngine extends PhutilMarkupEngine {
|
|||
return $output;
|
||||
}
|
||||
|
||||
private static function shouldMergeBlocks($text, $prev_block, $curr_block) {
|
||||
$block_rules = ipull(array($prev_block, $curr_block), 'rule');
|
||||
private static function shouldMergeParagraphBlocks(
|
||||
$text,
|
||||
$last_block,
|
||||
$current_block) {
|
||||
|
||||
$default_rule = 'PhutilRemarkupDefaultBlockRule';
|
||||
try {
|
||||
assert_instances_of($block_rules, $default_rule);
|
||||
// If we're at the beginning of the input, we can't merge.
|
||||
if ($last_block === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the last block was empty keep merging
|
||||
if ($prev_block['is_empty']) {
|
||||
// If the previous block wasn't a default block, we can't merge.
|
||||
if (!$last_block['merge']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the current block isn't a default block, we can't merge.
|
||||
if (!$current_block['merge']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the last block was empty, we definitely want to merge.
|
||||
if ($last_block['empty']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If this line is blank keep merging
|
||||
if ($curr_block['is_empty']) {
|
||||
// If this block is empty, we definitely want to merge.
|
||||
if ($current_block['empty']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the current line and the last line have content, keep merging
|
||||
if (strlen(trim($text[$curr_block['start'] - 1]))) {
|
||||
if (strlen(trim($text[$curr_block['start']]))) {
|
||||
// Check if the last line of the previous block or the first line of this
|
||||
// block have any non-whitespace text. If they both do, we're going to
|
||||
// merge.
|
||||
|
||||
// If either of them are a blank line or a line with only whitespace, we
|
||||
// do not merge: this means we've found a paragraph break.
|
||||
|
||||
$tail = $text[$current_block['start'] - 1];
|
||||
$head = $text[$current_block['start']];
|
||||
if (strlen(trim($tail)) && strlen(trim($head))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
> x
|
||||
>
|
||||
> y
|
||||
~~~~~~~~~~
|
||||
<blockquote><p>x</p>
|
||||
|
||||
<p>y</p></blockquote>
|
||||
~~~~~~~~~~
|
||||
> x
|
||||
>
|
||||
> y
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
|
||||
|
||||
private $referencePattern;
|
||||
private $embedPattern;
|
||||
|
||||
const KEY_RULE_OBJECT = 'rule.object';
|
||||
const KEY_MENTIONED_OBJECTS = 'rule.object.mentioned';
|
||||
|
||||
|
@ -192,14 +195,20 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
|
|||
}
|
||||
|
||||
private function getObjectEmbedPattern() {
|
||||
if ($this->embedPattern === null) {
|
||||
$prefix = $this->getObjectNamePrefix();
|
||||
$prefix = preg_quote($prefix);
|
||||
$id = $this->getObjectIDPattern();
|
||||
|
||||
return '(\B{'.$prefix.'('.$id.')([,\s](?:[^}\\\\]|\\\\.)*)?}\B)u';
|
||||
$this->embedPattern =
|
||||
'(\B{'.$prefix.'('.$id.')([,\s](?:[^}\\\\]|\\\\.)*)?}\B)u';
|
||||
}
|
||||
|
||||
return $this->embedPattern;
|
||||
}
|
||||
|
||||
private function getObjectReferencePattern() {
|
||||
if ($this->referencePattern === null) {
|
||||
$prefix = $this->getObjectNamePrefix();
|
||||
$prefix = preg_quote($prefix);
|
||||
|
||||
|
@ -223,7 +232,11 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
|
|||
// The "\b" allows us to link "(abcdef)" or similar without linking things
|
||||
// in the middle of words.
|
||||
|
||||
return '((?<![#@-])'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?(?!\w))u';
|
||||
$this->referencePattern =
|
||||
'((?<![#@-])'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?(?!\w))u';
|
||||
}
|
||||
|
||||
return $this->referencePattern;
|
||||
}
|
||||
|
||||
|
||||
|
|
68
src/view/phui/PHUICurtainObjectRefListView.php
Normal file
68
src/view/phui/PHUICurtainObjectRefListView.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
final class PHUICurtainObjectRefListView
|
||||
extends AphrontTagView {
|
||||
|
||||
private $refs = array();
|
||||
private $emptyMessage;
|
||||
private $tail = array();
|
||||
|
||||
protected function getTagAttributes() {
|
||||
return array(
|
||||
'class' => 'phui-curtain-object-ref-list-view',
|
||||
);
|
||||
}
|
||||
|
||||
public function setEmptyMessage($empty_message) {
|
||||
$this->emptyMessage = $empty_message;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getTagContent() {
|
||||
$refs = $this->refs;
|
||||
|
||||
if (!$refs && ($this->emptyMessage !== null)) {
|
||||
$view = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phui-curtain-object-ref-list-view-empty',
|
||||
),
|
||||
$this->emptyMessage);
|
||||
} else {
|
||||
$view = $refs;
|
||||
}
|
||||
|
||||
$tail = null;
|
||||
if ($this->tail) {
|
||||
$tail = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phui-curtain-object-ref-list-view-tail',
|
||||
),
|
||||
$this->tail);
|
||||
}
|
||||
|
||||
return array(
|
||||
$view,
|
||||
$tail,
|
||||
);
|
||||
}
|
||||
|
||||
public function newObjectRefView() {
|
||||
$ref_view = id(new PHUICurtainObjectRefView())
|
||||
->setViewer($this->getViewer());
|
||||
|
||||
$this->refs[] = $ref_view;
|
||||
|
||||
return $ref_view;
|
||||
}
|
||||
|
||||
public function newTailLink() {
|
||||
$link = new PHUILinkView();
|
||||
|
||||
$this->tail[] = $link;
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
}
|
194
src/view/phui/PHUICurtainObjectRefView.php
Normal file
194
src/view/phui/PHUICurtainObjectRefView.php
Normal file
|
@ -0,0 +1,194 @@
|
|||
<?php
|
||||
|
||||
final class PHUICurtainObjectRefView
|
||||
extends AphrontTagView {
|
||||
|
||||
private $handle;
|
||||
private $epoch;
|
||||
private $highlighted;
|
||||
|
||||
public function setHandle(PhabricatorObjectHandle $handle) {
|
||||
$this->handle = $handle;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEpoch($epoch) {
|
||||
$this->epoch = $epoch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHighlighted($highlighted) {
|
||||
$this->highlighted = $highlighted;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getTagAttributes() {
|
||||
$classes = array();
|
||||
$classes[] = 'phui-curtain-object-ref-view';
|
||||
|
||||
if ($this->highlighted) {
|
||||
$classes[] = 'phui-curtain-object-ref-view-highlighted';
|
||||
}
|
||||
$classes = implode(' ', $classes);
|
||||
|
||||
return array(
|
||||
'class' => $classes,
|
||||
);
|
||||
}
|
||||
|
||||
protected function getTagContent() {
|
||||
require_celerity_resource('phui-curtain-object-ref-view-css');
|
||||
|
||||
$viewer = $this->getViewer();
|
||||
$handle = $this->handle;
|
||||
|
||||
$more_rows = array();
|
||||
|
||||
$epoch = $this->epoch;
|
||||
if ($epoch !== null) {
|
||||
$epoch_view = phabricator_datetime($epoch, $viewer);
|
||||
|
||||
$epoch_cells = array();
|
||||
|
||||
$epoch_cells[] = phutil_tag(
|
||||
'td',
|
||||
array(
|
||||
'class' => 'phui-curtain-object-ref-view-epoch-cell',
|
||||
),
|
||||
$epoch_view);
|
||||
|
||||
$more_rows[] = phutil_tag('tr', array(), $epoch_cells);
|
||||
}
|
||||
|
||||
$header_cells = array();
|
||||
|
||||
$image_view = $this->newImage();
|
||||
|
||||
if ($more_rows) {
|
||||
$row_count = 1 + count($more_rows);
|
||||
} else {
|
||||
$row_count = null;
|
||||
}
|
||||
|
||||
$header_cells[] = phutil_tag(
|
||||
'td',
|
||||
array(
|
||||
'rowspan' => $row_count,
|
||||
'class' => 'phui-curtain-object-ref-view-image-cell',
|
||||
),
|
||||
$image_view);
|
||||
|
||||
$title_view = $this->newTitle();
|
||||
|
||||
$header_cells[] = phutil_tag(
|
||||
'td',
|
||||
array(
|
||||
'class' => 'phui-curtain-object-ref-view-title-cell',
|
||||
),
|
||||
$title_view);
|
||||
|
||||
$rows = array();
|
||||
|
||||
if (!$more_rows) {
|
||||
$title_row_class = 'phui-curtain-object-ref-view-without-content';
|
||||
} else {
|
||||
$title_row_class = 'phui-curtain-object-ref-view-with-content';
|
||||
}
|
||||
|
||||
$rows[] = phutil_tag(
|
||||
'tr',
|
||||
array(
|
||||
'class' => $title_row_class,
|
||||
),
|
||||
$header_cells);
|
||||
|
||||
$body = phutil_tag(
|
||||
'tbody',
|
||||
array(),
|
||||
array(
|
||||
$rows,
|
||||
$more_rows,
|
||||
));
|
||||
|
||||
return phutil_tag('table', array(), $body);
|
||||
}
|
||||
|
||||
private function newTitle() {
|
||||
$title_view = null;
|
||||
$handle = $this->handle;
|
||||
|
||||
if ($handle) {
|
||||
$title_view = $handle->renderLink();
|
||||
}
|
||||
|
||||
return $title_view;
|
||||
}
|
||||
|
||||
private function newImage() {
|
||||
$image_uri = $this->getImageURI();
|
||||
$target_uri = $this->getTargetURI();
|
||||
|
||||
$icon_view = null;
|
||||
if ($image_uri == null) {
|
||||
$icon_view = $this->newIconView();
|
||||
}
|
||||
|
||||
if ($image_uri !== null) {
|
||||
$image_view = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'style' => sprintf('background-image: url(%s)', $image_uri),
|
||||
'href' => $target_uri,
|
||||
'aural' => false,
|
||||
));
|
||||
} else if ($icon_view !== null) {
|
||||
$image_view = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $target_uri,
|
||||
'class' => 'phui-curtain-object-ref-view-icon-image',
|
||||
'aural' => false,
|
||||
),
|
||||
$icon_view);
|
||||
} else {
|
||||
$image_view = null;
|
||||
}
|
||||
|
||||
return $image_view;
|
||||
}
|
||||
|
||||
private function getTargetURI() {
|
||||
$target_uri = null;
|
||||
$handle = $this->handle;
|
||||
|
||||
if ($handle) {
|
||||
$target_uri = $handle->getURI();
|
||||
}
|
||||
|
||||
return $target_uri;
|
||||
}
|
||||
|
||||
private function getImageURI() {
|
||||
$image_uri = null;
|
||||
$handle = $this->handle;
|
||||
|
||||
if ($handle) {
|
||||
$image_uri = $handle->getImageURI();
|
||||
}
|
||||
|
||||
return $image_uri;
|
||||
}
|
||||
|
||||
private function newIconView() {
|
||||
$handle = $this->handle;
|
||||
|
||||
if ($handle) {
|
||||
$icon_view = id(new PHUIIconView())
|
||||
->setIcon($handle->getIcon());
|
||||
}
|
||||
|
||||
return $icon_view;
|
||||
}
|
||||
|
||||
|
||||
}
|
20
src/view/phui/PHUILauncherView.php
Normal file
20
src/view/phui/PHUILauncherView.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
final class PHUILauncherView
|
||||
extends AphrontTagView {
|
||||
|
||||
protected function getTagName() {
|
||||
return 'div';
|
||||
}
|
||||
|
||||
protected function getTagAttributes() {
|
||||
$classes = array();
|
||||
|
||||
$classes[] = 'phui-launcher-view';
|
||||
|
||||
return array(
|
||||
'class' => implode(' ', $classes),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
50
src/view/phui/PHUILinkView.php
Normal file
50
src/view/phui/PHUILinkView.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
final class PHUILinkView
|
||||
extends AphrontTagView {
|
||||
|
||||
private $uri;
|
||||
private $text;
|
||||
private $workflow;
|
||||
|
||||
public function setURI($uri) {
|
||||
$this->uri = $uri;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
public function setText($text) {
|
||||
$this->text = $text;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setWorkflow($workflow) {
|
||||
$this->workflow = $workflow;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getTagName() {
|
||||
return 'a';
|
||||
}
|
||||
|
||||
protected function getTagAttributes() {
|
||||
$sigil = array();
|
||||
|
||||
if ($this->workflow) {
|
||||
$sigil[] = 'workflow';
|
||||
}
|
||||
|
||||
return array(
|
||||
'href' => $this->getURI(),
|
||||
'sigil' => $sigil,
|
||||
);
|
||||
}
|
||||
|
||||
protected function getTagContent() {
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,6 +27,7 @@ final class PHUIObjectBoxView extends AphrontTagView {
|
|||
private $showHideOpen;
|
||||
|
||||
private $propertyLists = array();
|
||||
private $tailButtons = array();
|
||||
|
||||
const COLOR_RED = 'red';
|
||||
const COLOR_BLUE = 'blue';
|
||||
|
@ -153,6 +154,16 @@ final class PHUIObjectBoxView extends AphrontTagView {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function newTailButton() {
|
||||
$button = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setColor(PHUIButtonView::GREY);
|
||||
|
||||
$this->tailButtons[] = $button;
|
||||
|
||||
return $button;
|
||||
}
|
||||
|
||||
protected function getTagAttributes() {
|
||||
$classes = array();
|
||||
$classes[] = 'phui-box';
|
||||
|
@ -329,6 +340,15 @@ final class PHUIObjectBoxView extends AphrontTagView {
|
|||
$content[] = $this->objectList;
|
||||
}
|
||||
|
||||
if ($this->tailButtons) {
|
||||
$content[] = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'phui-object-box-tail-buttons',
|
||||
),
|
||||
$this->tailButtons);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
|
84
webroot/rsrc/css/phui/phui-curtain-object-ref-view.css
Normal file
84
webroot/rsrc/css/phui/phui-curtain-object-ref-view.css
Normal file
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* @provides phui-curtain-object-ref-view-css
|
||||
*/
|
||||
|
||||
.phui-curtain-object-ref-list-view-empty {
|
||||
font-style: italic;
|
||||
color: {$greytext};
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view {
|
||||
padding: 4px 6px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-image-cell {
|
||||
min-width: 32px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-image-cell > a {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-size: 100%;
|
||||
border-radius: 3px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-image-cell .phui-icon-view {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 3px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-icon-image {
|
||||
background-color: {$backdrop};
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-title-cell {
|
||||
font-weight: bold;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
/* This is forcing "text-overflow: ellipsis" to actually work. */
|
||||
max-width: 210px;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-without-content >
|
||||
.phui-curtain-object-ref-view-title-cell {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-with-content >
|
||||
.phui-curtain-object-ref-view-image-cell > a {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-title-cell > a {
|
||||
color: {$darkgreytext};
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-epoch-cell {
|
||||
color: {$greytext};
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-list-view-tail {
|
||||
text-align: center;
|
||||
margin-top: 8px;
|
||||
padding: 4px;
|
||||
background: {$lightgreybackground};
|
||||
border-top: 1px dashed {$thinblueborder};
|
||||
box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.phui-curtain-object-ref-view-highlighted {
|
||||
background: {$bluebackground};
|
||||
}
|
|
@ -62,6 +62,12 @@ div.phui-object-box.phui-object-box-flush {
|
|||
font-size: {$normalfontsize};
|
||||
}
|
||||
|
||||
.phui-object-box-tail-buttons {
|
||||
padding: 8px;
|
||||
background: {$lightgreybackground};
|
||||
border-top: 1px solid {$lightgreyborder};
|
||||
}
|
||||
|
||||
/* - Object Box Colors ------------------------------------------------------ */
|
||||
|
||||
.phui-box-border.phui-object-box-green {
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
* @provides phui-two-column-view-css
|
||||
*/
|
||||
|
||||
.phui-launcher-view {
|
||||
max-width: 1140px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.phui-two-column-fixed {
|
||||
max-width: 1140px;
|
||||
margin: 0 auto;
|
||||
|
|
Loading…
Add table
Reference in a new issue