@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Convert "Account" and "Date and Time" settings to EditEngine

Summary:
Ref T4103. This pretty much replaces these panels in-place with similar looking ones that go through EditEngine.

This has a few rough edges but they're pretty minor and/or hard to hit (for example, when editing another user's settings, the crumbs have a redundant link in them).

Test Plan:
- Edited my own settings.
- Edited a bot user's settings.
- Tried to edit another user's settings (failed).

{F1674465}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4103

Differential Revision: https://secure.phabricator.com/D16017

+370 -327
+4 -2
src/__phutil_library_map__.php
··· 2372 2372 'PhabricatorEditEngineQuery' => 'applications/transactions/query/PhabricatorEditEngineQuery.php', 2373 2373 'PhabricatorEditEngineSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineSearchEngine.php', 2374 2374 'PhabricatorEditEngineSelectCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineSelectCommentAction.php', 2375 + 'PhabricatorEditEngineSettingsPanel' => 'applications/settings/panel/PhabricatorEditEngineSettingsPanel.php', 2375 2376 'PhabricatorEditEngineTokenizerCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEngineTokenizerCommentAction.php', 2376 2377 'PhabricatorEditField' => 'applications/transactions/editfield/PhabricatorEditField.php', 2377 2378 'PhabricatorEditPage' => 'applications/transactions/editengine/PhabricatorEditPage.php', ··· 6167 6168 'PhabricatorAccessLog' => 'Phobject', 6168 6169 'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions', 6169 6170 'PhabricatorAccessibilitySetting' => 'PhabricatorSelectSetting', 6170 - 'PhabricatorAccountSettingsPanel' => 'PhabricatorSettingsPanel', 6171 + 'PhabricatorAccountSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 6171 6172 'PhabricatorActionListView' => 'AphrontView', 6172 6173 'PhabricatorActionView' => 'AphrontView', 6173 6174 'PhabricatorActivitySettingsPanel' => 'PhabricatorSettingsPanel', ··· 6863 6864 'PhabricatorDatasourceEditField' => 'PhabricatorTokenizerEditField', 6864 6865 'PhabricatorDatasourceEditType' => 'PhabricatorPHIDListEditType', 6865 6866 'PhabricatorDateFormatSetting' => 'PhabricatorSelectSetting', 6866 - 'PhabricatorDateTimeSettingsPanel' => 'PhabricatorSettingsPanel', 6867 + 'PhabricatorDateTimeSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 6867 6868 'PhabricatorDebugController' => 'PhabricatorController', 6868 6869 'PhabricatorDefaultRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler', 6869 6870 'PhabricatorDefaultSyntaxStyle' => 'PhabricatorSyntaxStyle', ··· 6942 6943 'PhabricatorEditEngineQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6943 6944 'PhabricatorEditEngineSearchEngine' => 'PhabricatorApplicationSearchEngine', 6944 6945 'PhabricatorEditEngineSelectCommentAction' => 'PhabricatorEditEngineCommentAction', 6946 + 'PhabricatorEditEngineSettingsPanel' => 'PhabricatorSettingsPanel', 6945 6947 'PhabricatorEditEngineTokenizerCommentAction' => 'PhabricatorEditEngineCommentAction', 6946 6948 'PhabricatorEditField' => 'Phobject', 6947 6949 'PhabricatorEditPage' => 'Phobject',
+4 -1
src/applications/settings/application/PhabricatorSettingsApplication.php
··· 29 29 public function getRoutes() { 30 30 return array( 31 31 '/settings/' => array( 32 - '(?:(?P<id>\d+)/)?(?:panel/(?P<key>[^/]+)/)?' 32 + '(?:(?P<id>\d+)/)?'. 33 + '(?:panel/(?P<pageKey>(?P<key>[^/]+))/'. 34 + '(?:(?P<formSaved>saved)/)?'. 35 + ')?' 33 36 => 'PhabricatorSettingsMainController', 34 37 'adjust/' => 'PhabricatorSettingsAdjustController', 35 38 'timezone/(?P<offset>[^/]+)/'
+27 -17
src/applications/settings/controller/PhabricatorSettingsMainController.php
··· 10 10 } 11 11 12 12 private function isSelf() { 13 + $user = $this->getUser(); 14 + if (!$user) { 15 + return false; 16 + } 17 + 18 + $user_phid = $user->getPHID(); 19 + 13 20 $viewer_phid = $this->getViewer()->getPHID(); 14 - $user_phid = $this->getUser()->getPHID(); 15 21 return ($viewer_phid == $user_phid); 16 22 } 17 23 ··· 45 51 46 52 $key = $nav->selectFilter($key, head($panels)->getPanelKey()); 47 53 48 - $panel = $panels[$key]; 49 - $panel->setUser($this->getUser()); 50 - $panel->setViewer($viewer); 54 + $panel = $panels[$key] 55 + ->setUser($this->getUser()) 56 + ->setViewer($viewer) 57 + ->setController($this) 58 + ->setNavigation($nav); 51 59 52 60 $response = $panel->processRequest($request); 53 - if ($response instanceof AphrontResponse) { 61 + if (($response instanceof AphrontResponse) || 62 + ($response instanceof AphrontResponseProducerInterface)) { 54 63 return $response; 55 64 } 56 65 57 66 $crumbs = $this->buildApplicationCrumbs(); 58 - if (!$this->isSelf()) { 59 - $crumbs->addTextCrumb( 60 - $this->getUser()->getUsername(), 61 - '/p/'.$this->getUser()->getUsername().'/'); 62 - } 63 67 $crumbs->addTextCrumb($panel->getPanelName()); 64 68 65 69 $title = $panel->getPanelName(); ··· 76 80 } 77 81 78 82 private function buildPanels() { 79 - $panels = id(new PhutilClassMapQuery()) 80 - ->setAncestorClass('PhabricatorSettingsPanel') 81 - ->setExpandMethod('buildPanels') 82 - ->setUniqueMethod('getPanelKey') 83 - ->execute(); 83 + $panels = PhabricatorSettingsPanel::getAllPanels(); 84 84 85 85 $result = array(); 86 86 foreach ($panels as $key => $panel) { ··· 106 106 107 107 $result[$key] = $panel; 108 108 } 109 - 110 - $result = msort($result, 'getPanelSortKey'); 111 109 112 110 if (!$result) { 113 111 throw new Exception(pht('No settings panels are available.')); ··· 143 141 public function buildApplicationMenu() { 144 142 $panels = $this->buildPanels(); 145 143 return $this->renderSideNav($panels)->getMenu(); 144 + } 145 + 146 + protected function buildApplicationCrumbs() { 147 + $crumbs = parent::buildApplicationCrumbs(); 148 + 149 + $user = $this->getUser(); 150 + if (!$this->isSelf() && $user) { 151 + $username = $user->getUsername(); 152 + $crumbs->addTextCrumb($username, "/p/{$username}/"); 153 + } 154 + 155 + return $crumbs; 146 156 } 147 157 148 158 }
+85
src/applications/settings/editor/PhabricatorSettingsEditEngine.php
··· 5 5 6 6 const ENGINECONST = 'settings.settings'; 7 7 8 + private $isSelfEdit; 9 + private $profileURI; 10 + 11 + public function setIsSelfEdit($is_self_edit) { 12 + $this->isSelfEdit = $is_self_edit; 13 + return $this; 14 + } 15 + 16 + public function getIsSelfEdit() { 17 + return $this->isSelfEdit; 18 + } 19 + 20 + public function setProfileURI($profile_uri) { 21 + $this->profileURI = $profile_uri; 22 + return $this; 23 + } 24 + 25 + public function getProfileURI() { 26 + return $this->profileURI; 27 + } 28 + 8 29 public function isEngineConfigurable() { 9 30 return false; 10 31 } ··· 54 75 } 55 76 56 77 protected function getObjectName() { 78 + $page = $this->getSelectedPage(); 79 + 80 + if ($page) { 81 + return $page->getLabel(); 82 + } 83 + 57 84 return pht('Settings'); 58 85 } 59 86 ··· 74 101 return PhabricatorPolicies::POLICY_ADMIN; 75 102 } 76 103 104 + public function getEffectiveObjectEditCancelURI($object) { 105 + if ($this->getIsSelfEdit()) { 106 + return null; 107 + } 108 + 109 + if ($this->getProfileURI()) { 110 + return $this->getProfileURI(); 111 + } 112 + 113 + return parent::getEffectiveObjectEditCancelURI($object); 114 + } 115 + 116 + protected function newPages($object) { 117 + $viewer = $this->getViewer(); 118 + $user = $object->getUser(); 119 + 120 + $panels = PhabricatorSettingsPanel::getAllPanels(); 121 + 122 + foreach ($panels as $key => $panel) { 123 + if (!($panel instanceof PhabricatorEditEngineSettingsPanel)) { 124 + unset($panels[$key]); 125 + continue; 126 + } 127 + 128 + $panel->setViewer($viewer); 129 + if ($user) { 130 + $panel->setUser($user); 131 + } 132 + } 133 + 134 + $pages = array(); 135 + $uris = array(); 136 + foreach ($panels as $key => $panel) { 137 + $uris[$key] = $panel->getPanelURI(); 138 + 139 + $page = $panel->newEditEnginePage(); 140 + if (!$page) { 141 + continue; 142 + } 143 + $pages[] = $page; 144 + } 145 + 146 + $more_pages = array( 147 + id(new PhabricatorEditPage()) 148 + ->setKey('extra') 149 + ->setLabel(pht('Extra Settings')) 150 + ->setIsDefault(true), 151 + ); 152 + 153 + foreach ($more_pages as $page) { 154 + $pages[] = $page; 155 + } 156 + 157 + return $pages; 158 + } 159 + 77 160 protected function buildCustomEditFields($object) { 78 161 $viewer = $this->getViewer(); 79 162 $settings = PhabricatorSetting::getAllEnabledSettings($viewer); ··· 83 166 $setting->setViewer($viewer); 84 167 $settings[$key] = $setting; 85 168 } 169 + 170 + $settings = msortv($settings, 'getSettingOrderVector'); 86 171 87 172 $fields = array(); 88 173 foreach ($settings as $setting) {
+3 -162
src/applications/settings/panel/PhabricatorAccountSettingsPanel.php
··· 1 1 <?php 2 2 3 - final class PhabricatorAccountSettingsPanel extends PhabricatorSettingsPanel { 3 + final class PhabricatorAccountSettingsPanel 4 + extends PhabricatorEditEngineSettingsPanel { 4 5 5 - public function getPanelKey() { 6 - return 'account'; 7 - } 6 + const PANELKEY = 'account'; 8 7 9 8 public function getPanelName() { 10 9 return pht('Account'); ··· 16 15 17 16 public function isEditableByAdministrators() { 18 17 return true; 19 - } 20 - 21 - public function processRequest(AphrontRequest $request) { 22 - $viewer = $this->getViewer(); 23 - $user = $this->getUser(); 24 - $username = $user->getUsername(); 25 - 26 - $preferences = $user->loadPreferences(); 27 - 28 - $errors = array(); 29 - if ($request->isFormPost()) { 30 - $sex = $request->getStr('sex'); 31 - $sexes = array(PhutilPerson::SEX_MALE, PhutilPerson::SEX_FEMALE); 32 - if (in_array($sex, $sexes)) { 33 - $new_value = $sex; 34 - } else { 35 - $new_value = null; 36 - } 37 - 38 - $preferences->setPreference( 39 - PhabricatorPronounSetting::SETTINGKEY, 40 - $new_value); 41 - 42 - $preferences->setPreference( 43 - PhabricatorTranslationSetting::SETTINGKEY, 44 - $request->getStr('translation')); 45 - 46 - if (!$errors) { 47 - $preferences->save(); 48 - 49 - return id(new AphrontRedirectResponse()) 50 - ->setURI($this->getPanelURI('?saved=true')); 51 - } 52 - } 53 - 54 - $label_unknown = pht('%s updated their profile', $username); 55 - $label_her = pht('%s updated her profile', $username); 56 - $label_his = pht('%s updated his profile', $username); 57 - 58 - $sexes = array( 59 - PhutilPerson::SEX_UNKNOWN => $label_unknown, 60 - PhutilPerson::SEX_MALE => $label_his, 61 - PhutilPerson::SEX_FEMALE => $label_her, 62 - ); 63 - 64 - $translations = $this->getTranslationOptions(); 65 - 66 - $form = new AphrontFormView(); 67 - $form 68 - ->setUser($viewer) 69 - ->appendChild( 70 - id(new AphrontFormSelectControl()) 71 - ->setOptions($translations) 72 - ->setLabel(pht('Translation')) 73 - ->setName('translation') 74 - ->setValue($user->getTranslation())) 75 - ->appendRemarkupInstructions(pht('**Choose the pronoun you prefer:**')) 76 - ->appendChild( 77 - id(new AphrontFormSelectControl()) 78 - ->setOptions($sexes) 79 - ->setLabel(pht('Pronoun')) 80 - ->setName('sex') 81 - ->setValue($user->getSex())) 82 - ->appendChild( 83 - id(new AphrontFormSubmitControl()) 84 - ->setValue(pht('Save Account Settings'))); 85 - 86 - $form_box = id(new PHUIObjectBoxView()) 87 - ->setHeaderText(pht('Account Settings')) 88 - ->setFormSaved($request->getStr('saved')) 89 - ->setFormErrors($errors) 90 - ->setForm($form); 91 - 92 - return array( 93 - $form_box, 94 - ); 95 - } 96 - 97 - private function getTranslationOptions() { 98 - $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); 99 - $locales = PhutilLocale::loadAllLocales(); 100 - 101 - $group_labels = array( 102 - 'normal' => pht('Translations'), 103 - 'limited' => pht('Limited Translations'), 104 - 'silly' => pht('Silly Translations'), 105 - 'test' => pht('Developer/Test Translations'), 106 - ); 107 - 108 - $groups = array_fill_keys(array_keys($group_labels), array()); 109 - 110 - $translations = array(); 111 - foreach ($locales as $locale) { 112 - $code = $locale->getLocaleCode(); 113 - 114 - // Get the locale's localized name if it's available. For example, 115 - // "Deutsch" instead of "German". This helps users who do not speak the 116 - // current language to find the correct setting. 117 - $raw_scope = PhabricatorEnv::beginScopedLocale($code); 118 - $name = $locale->getLocaleName(); 119 - unset($raw_scope); 120 - 121 - if ($locale->isSillyLocale()) { 122 - if ($is_serious) { 123 - // Omit silly locales on serious business installs. 124 - continue; 125 - } 126 - $groups['silly'][$code] = $name; 127 - continue; 128 - } 129 - 130 - if ($locale->isTestLocale()) { 131 - $groups['test'][$code] = $name; 132 - continue; 133 - } 134 - 135 - $strings = PhutilTranslation::getTranslationMapForLocale($code); 136 - $size = count($strings); 137 - 138 - // If a translation is English, assume it can fall back to the default 139 - // strings and don't caveat its completeness. 140 - $is_english = (substr($code, 0, 3) == 'en_'); 141 - 142 - // Arbitrarily pick some number of available strings to promote a 143 - // translation out of the "limited" group. The major goal is just to 144 - // keep locales with very few strings out of the main group, so users 145 - // aren't surprised if a locale has no upstream translations available. 146 - if ($size > 512 || $is_english) { 147 - $type = 'normal'; 148 - } else { 149 - $type = 'limited'; 150 - } 151 - 152 - $groups[$type][$code] = $name; 153 - } 154 - 155 - // TODO: Select a default properly. 156 - $default = 'en_US'; 157 - 158 - $results = array(); 159 - foreach ($groups as $key => $group) { 160 - $label = $group_labels[$key]; 161 - if (!$group) { 162 - continue; 163 - } 164 - 165 - asort($group); 166 - 167 - if ($key == 'normal') { 168 - $group = array( 169 - '' => pht('Server Default: %s', $locales[$default]->getLocaleName()), 170 - ) + $group; 171 - } 172 - 173 - $results[$label] = $group; 174 - } 175 - 176 - return $results; 177 18 } 178 19 179 20 }
+5 -110
src/applications/settings/panel/PhabricatorDateTimeSettingsPanel.php
··· 1 1 <?php 2 2 3 - final class PhabricatorDateTimeSettingsPanel extends PhabricatorSettingsPanel { 3 + final class PhabricatorDateTimeSettingsPanel 4 + extends PhabricatorEditEngineSettingsPanel { 4 5 5 - public function getPanelKey() { 6 - return 'datetime'; 7 - } 6 + const PANELKEY = 'datetime'; 8 7 9 8 public function getPanelName() { 10 9 return pht('Date and Time'); ··· 14 13 return pht('Account Information'); 15 14 } 16 15 17 - public function processRequest(AphrontRequest $request) { 18 - $user = $request->getUser(); 19 - $username = $user->getUsername(); 20 - 21 - $pref_timezone = PhabricatorTimezoneSetting::SETTINGKEY; 22 - $pref_time = PhabricatorUserPreferences::PREFERENCE_TIME_FORMAT; 23 - $pref_date = PhabricatorUserPreferences::PREFERENCE_DATE_FORMAT; 24 - $pref_week_start = PhabricatorUserPreferences::PREFERENCE_WEEK_START_DAY; 25 - $pref_ignore = PhabricatorTimezoneIgnoreOffsetSetting::SETTINGKEY; 26 - $preferences = $user->loadPreferences(); 27 - 28 - $errors = array(); 29 - if ($request->isFormPost()) { 30 - $new_timezone = $request->getStr('timezone'); 31 - if (!in_array($new_timezone, DateTimeZone::listIdentifiers(), true)) { 32 - $errors[] = pht('The selected timezone is not a valid timezone.'); 33 - } 34 - 35 - $preferences 36 - ->setPreference($pref_timezone, $new_timezone) 37 - ->setPreference( 38 - $pref_time, 39 - $request->getStr($pref_time)) 40 - ->setPreference( 41 - $pref_date, 42 - $request->getStr($pref_date)) 43 - ->setPreference( 44 - $pref_week_start, 45 - $request->getStr($pref_week_start)) 46 - ->setPreference($pref_ignore, null); 47 - 48 - if (!$errors) { 49 - $preferences->save(); 50 - 51 - return id(new AphrontRedirectResponse()) 52 - ->setURI($this->getPanelURI('?saved=true')); 53 - } 54 - } 55 - 56 - $timezone_ids = DateTimeZone::listIdentifiers(); 57 - $timezone_id_map = array_fuse($timezone_ids); 58 - 59 - $form = new AphrontFormView(); 60 - $form 61 - ->setUser($user) 62 - ->appendChild( 63 - id(new AphrontFormSelectControl()) 64 - ->setLabel(pht('Timezone')) 65 - ->setName('timezone') 66 - ->setOptions($timezone_id_map) 67 - ->setValue($user->getTimezoneIdentifier())) 68 - ->appendChild( 69 - id(new AphrontFormSelectControl()) 70 - ->setLabel(pht('Time-of-Day Format')) 71 - ->setName($pref_time) 72 - ->setOptions(array( 73 - 'g:i A' => pht('12-hour (2:34 PM)'), 74 - 'H:i' => pht('24-hour (14:34)'), 75 - )) 76 - ->setCaption( 77 - pht('Format used when rendering a time of day.')) 78 - ->setValue($preferences->getPreference($pref_time))) 79 - ->appendChild( 80 - id(new AphrontFormSelectControl()) 81 - ->setLabel(pht('Date Format')) 82 - ->setName($pref_date) 83 - ->setOptions(array( 84 - 'Y-m-d' => pht('ISO 8601 (2000-02-28)'), 85 - 'n/j/Y' => pht('US (2/28/2000)'), 86 - 'd-m-Y' => pht('European (28-02-2000)'), 87 - )) 88 - ->setCaption( 89 - pht('Format used when rendering a date.')) 90 - ->setValue($preferences->getPreference($pref_date))) 91 - ->appendChild( 92 - id(new AphrontFormSelectControl()) 93 - ->setLabel(pht('Week Starts On')) 94 - ->setOptions($this->getWeekDays()) 95 - ->setName($pref_week_start) 96 - ->setCaption( 97 - pht('Calendar weeks will start with this day.')) 98 - ->setValue($preferences->getPreference($pref_week_start, 0))) 99 - ->appendChild( 100 - id(new AphrontFormSubmitControl()) 101 - ->setValue(pht('Save Account Settings'))); 102 - 103 - $form_box = id(new PHUIObjectBoxView()) 104 - ->setHeaderText(pht('Date and Time Settings')) 105 - ->setFormSaved($request->getStr('saved')) 106 - ->setFormErrors($errors) 107 - ->setForm($form); 108 - 109 - return array( 110 - $form_box, 111 - ); 16 + public function isEditableByAdministrators() { 17 + return true; 112 18 } 113 19 114 - private function getWeekDays() { 115 - return array( 116 - pht('Sunday'), 117 - pht('Monday'), 118 - pht('Tuesday'), 119 - pht('Wednesday'), 120 - pht('Thursday'), 121 - pht('Friday'), 122 - pht('Saturday'), 123 - ); 124 - } 125 20 }
+74
src/applications/settings/panel/PhabricatorEditEngineSettingsPanel.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorEditEngineSettingsPanel 4 + extends PhabricatorSettingsPanel { 5 + 6 + final public function processRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + $user = $this->getUser(); 9 + 10 + if ($user->getPHID() === $viewer->getPHID()) { 11 + $is_self = true; 12 + } else { 13 + $is_self = false; 14 + } 15 + 16 + if ($user->getPHID()) { 17 + $profile_uri = '/people/manage/'.$user->getID().'/'; 18 + } else { 19 + $profile_uri = null; 20 + } 21 + 22 + $engine = id(new PhabricatorSettingsEditEngine()) 23 + ->setController($this->getController()) 24 + ->setNavigation($this->getNavigation()) 25 + ->setHideHeader(true) 26 + ->setIsSelfEdit($is_self) 27 + ->setProfileURI($profile_uri); 28 + 29 + $preferences = $user->loadPreferences(); 30 + 31 + PhabricatorPolicyFilter::requireCapability( 32 + $viewer, 33 + $preferences, 34 + PhabricatorPolicyCapability::CAN_EDIT); 35 + 36 + $engine->setTargetObject($preferences); 37 + 38 + return $engine->buildResponse(); 39 + } 40 + 41 + final public function newEditEnginePage() { 42 + $field_keys = $this->getPanelSettingsKeys(); 43 + if (!$field_keys) { 44 + return null; 45 + } 46 + 47 + $key = $this->getPanelKey(); 48 + $label = $this->getPanelName(); 49 + $panel_uri = $this->getPanelURI().'saved/'; 50 + 51 + return id(new PhabricatorEditPage()) 52 + ->setKey($key) 53 + ->setLabel($label) 54 + ->setViewURI($panel_uri) 55 + ->setFieldKeys($field_keys); 56 + } 57 + 58 + final public function getPanelSettingsKeys() { 59 + $viewer = $this->getViewer(); 60 + $settings = PhabricatorSetting::getAllEnabledSettings($viewer); 61 + 62 + $this_key = $this->getPanelKey(); 63 + 64 + $panel_settings = array(); 65 + foreach ($settings as $setting) { 66 + if ($setting->getSettingPanelKey() == $this_key) { 67 + $panel_settings[] = $setting; 68 + } 69 + } 70 + 71 + return mpull($panel_settings, 'getSettingKey'); 72 + } 73 + 74 + }
+31 -19
src/applications/settings/panel/PhabricatorSettingsPanel.php
··· 17 17 18 18 private $user; 19 19 private $viewer; 20 + private $controller; 21 + private $navigation; 20 22 private $overrideURI; 21 - 22 23 23 24 public function setUser(PhabricatorUser $user) { 24 25 $this->user = $user; ··· 43 44 return $this; 44 45 } 45 46 47 + final public function setController(PhabricatorController $controller) { 48 + $this->controller = $controller; 49 + return $this; 50 + } 51 + 52 + final public function getController() { 53 + return $this->controller; 54 + } 55 + 56 + final public function setNavigation(AphrontSideNavFilterView $navigation) { 57 + $this->navigation = $navigation; 58 + return $this; 59 + } 60 + 61 + final public function getNavigation() { 62 + return $this->navigation; 63 + } 64 + 65 + final public static function getAllPanels() { 66 + return id(new PhutilClassMapQuery()) 67 + ->setAncestorClass(__CLASS__) 68 + ->setUniqueMethod('getPanelKey') 69 + ->setSortMethod('getPanelSortKey') 70 + ->execute(); 71 + } 72 + 46 73 47 74 /* -( Panel Configuration )------------------------------------------------ */ 48 75 ··· 54 81 * @return string Unique panel identifier (used in URIs). 55 82 * @task config 56 83 */ 57 - abstract public function getPanelKey(); 84 + public function getPanelKey() { 85 + return $this->getPhobjectClassConstant('PANELKEY'); 86 + } 58 87 59 88 60 89 /** ··· 92 121 */ 93 122 public function isEnabled() { 94 123 return true; 95 - } 96 - 97 - 98 - /** 99 - * You can use this callback to generate multiple similar panels which all 100 - * share the same implementation. For example, OAuth providers each have a 101 - * separate panel, but the implementation for each panel is the same. 102 - * 103 - * To generate multiple panels, build them here and return a list. By default, 104 - * the current panel (`$this`) is returned alone. For most panels, this 105 - * is the right implementation. 106 - * 107 - * @return list<PhabricatorSettingsPanel> Zero or more panels. 108 - * @task config 109 - */ 110 - public function buildPanels() { 111 - return array($this); 112 124 } 113 125 114 126
+8
src/applications/settings/setting/PhabricatorDateFormatSetting.php
··· 13 13 return pht('Date Format'); 14 14 } 15 15 16 + public function getSettingPanelKey() { 17 + return PhabricatorDateTimeSettingsPanel::PANELKEY; 18 + } 19 + 20 + protected function getSettingOrder() { 21 + return 200; 22 + } 23 + 16 24 protected function getControlInstructions() { 17 25 return pht( 18 26 'Select the format you prefer for editing dates.');
+11
src/applications/settings/setting/PhabricatorPronounSetting.php
··· 9 9 return pht('Pronoun'); 10 10 } 11 11 12 + public function getSettingPanelKey() { 13 + return PhabricatorAccountSettingsPanel::PANELKEY; 14 + } 15 + 16 + protected function getSettingOrder() { 17 + return 200; 18 + } 19 + 12 20 protected function getControlInstructions() { 13 21 return pht('Choose the pronoun you prefer.'); 14 22 } ··· 18 26 } 19 27 20 28 protected function getSelectOptions() { 29 + // TODO: When editing another user's settings as an administrator, this 30 + // is not the best username: the user's username would be better. 31 + 21 32 $viewer = $this->getViewer(); 22 33 $username = $viewer->getUsername(); 23 34
+14
src/applications/settings/setting/PhabricatorSetting.php
··· 15 15 16 16 abstract public function getSettingName(); 17 17 18 + public function getSettingPanelKey() { 19 + return null; 20 + } 21 + 22 + protected function getSettingOrder() { 23 + return 1000; 24 + } 25 + 26 + public function getSettingOrderVector() { 27 + return id(new PhutilSortVector()) 28 + ->addInt($this->getSettingOrder()) 29 + ->addString($this->getSettingName()); 30 + } 31 + 18 32 protected function getControlInstructions() { 19 33 return null; 20 34 }
+8
src/applications/settings/setting/PhabricatorTimeFormatSetting.php
··· 12 12 return pht('Time Format'); 13 13 } 14 14 15 + public function getSettingPanelKey() { 16 + return PhabricatorDateTimeSettingsPanel::PANELKEY; 17 + } 18 + 19 + protected function getSettingOrder() { 20 + return 300; 21 + } 22 + 15 23 protected function getControlInstructions() { 16 24 return pht( 17 25 'Select the format you prefer for editing and displaying time.');
+12
src/applications/settings/setting/PhabricatorTimezoneSetting.php
··· 9 9 return pht('Timezone'); 10 10 } 11 11 12 + public function getSettingPanelKey() { 13 + return PhabricatorDateTimeSettingsPanel::PANELKEY; 14 + } 15 + 16 + protected function getSettingOrder() { 17 + return 100; 18 + } 19 + 20 + protected function getControlInstructions() { 21 + return pht('Select your local timezone.'); 22 + } 23 + 12 24 public function getSettingDefaultValue() { 13 25 return date_default_timezone_get(); 14 26 }
+13
src/applications/settings/setting/PhabricatorTranslationSetting.php
··· 9 9 return pht('Translation'); 10 10 } 11 11 12 + public function getSettingPanelKey() { 13 + return PhabricatorAccountSettingsPanel::PANELKEY; 14 + } 15 + 16 + protected function getSettingOrder() { 17 + return 100; 18 + } 19 + 12 20 public function getSettingDefaultValue() { 13 21 return 'en_US'; 22 + } 23 + 24 + protected function getControlInstructions() { 25 + return pht( 26 + 'Choose which language you would like the Phabricator UI to use.'); 14 27 } 15 28 16 29 protected function getSelectOptionGroups() {
+8
src/applications/settings/setting/PhabricatorWeekStartDaySetting.php
··· 9 9 return pht('Week Starts On'); 10 10 } 11 11 12 + public function getSettingPanelKey() { 13 + return PhabricatorDateTimeSettingsPanel::PANELKEY; 14 + } 15 + 16 + protected function getSettingOrder() { 17 + return 400; 18 + } 19 + 12 20 protected function getControlInstructions() { 13 21 return pht( 14 22 'Choose which day a calendar week should begin on.');
+63 -16
src/applications/transactions/editengine/PhabricatorEditEngine.php
··· 26 26 private $targetObject; 27 27 private $page; 28 28 private $pages; 29 + private $navigation; 30 + private $hideHeader; 29 31 30 32 final public function setViewer(PhabricatorUser $viewer) { 31 33 $this->viewer = $viewer; ··· 78 80 79 81 public function getTargetObject() { 80 82 return $this->targetObject; 83 + } 84 + 85 + public function setNavigation(AphrontSideNavFilterView $navigation) { 86 + $this->navigation = $navigation; 87 + return $this; 88 + } 89 + 90 + public function getNavigation() { 91 + return $this->navigation; 92 + } 93 + 94 + public function setHideHeader($hide_header) { 95 + $this->hideHeader = $hide_header; 96 + return $this; 97 + } 98 + 99 + public function getHideHeader() { 100 + return $this->hideHeader; 81 101 } 82 102 83 103 ··· 1090 1110 ->addSubmitButton($submit_button); 1091 1111 } 1092 1112 1093 - $header = id(new PHUIHeaderView()) 1094 - ->setHeader($header_text) 1095 - ->setHeaderIcon($header_icon); 1113 + $crumbs = $this->buildCrumbs($object, $final = true); 1114 + 1115 + if ($this->getHideHeader()) { 1116 + $header = null; 1117 + $crumbs->setBorder(false); 1118 + } else { 1119 + $header = id(new PHUIHeaderView()) 1120 + ->setHeader($header_text) 1121 + ->setHeaderIcon($header_icon); 1122 + $crumbs->setBorder(true); 1123 + } 1096 1124 1097 1125 if ($action_button) { 1098 1126 $header->addActionLink($action_button); 1099 1127 } 1100 1128 1101 - $crumbs = $this->buildCrumbs($object, $final = true); 1102 - $crumbs->setBorder(true); 1103 - 1104 1129 $box = id(new PHUIObjectBoxView()) 1105 1130 ->setUser($viewer) 1106 1131 ->setHeaderText($this->getObjectName()) ··· 1108 1133 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 1109 1134 ->appendChild($form); 1110 1135 1111 - $view = id(new PHUITwoColumnView()) 1112 - ->setHeader($header) 1113 - ->setFooter(array( 1114 - $box, 1115 - $previews, 1116 - )); 1136 + // This is fairly questionable, but in use by Settings. 1137 + if ($request->getURIData('formSaved')) { 1138 + $box->setFormSaved(true); 1139 + } 1140 + 1141 + $content = array( 1142 + $box, 1143 + $previews, 1144 + ); 1145 + 1146 + $view = new PHUITwoColumnView(); 1147 + 1148 + if ($header) { 1149 + $view->setHeader($header); 1150 + } 1151 + 1152 + $navigation = $this->getNavigation(); 1153 + if ($navigation) { 1154 + $view 1155 + ->setNavigation($navigation) 1156 + ->setMainColumn($content); 1157 + } else { 1158 + $view->setFooter($content); 1159 + } 1117 1160 1118 1161 return $controller->newPage() 1119 1162 ->setTitle($header_text) ··· 1155 1198 } 1156 1199 1157 1200 if (!$request->isAjax()) { 1158 - $form->appendControl( 1159 - id(new AphrontFormSubmitControl()) 1160 - ->addCancelButton($cancel_uri) 1161 - ->setValue($submit_button)); 1201 + $buttons = id(new AphrontFormSubmitControl()) 1202 + ->setValue($submit_button); 1203 + 1204 + if ($cancel_uri) { 1205 + $buttons->addCancelButton($cancel_uri); 1206 + } 1207 + 1208 + $form->appendControl($buttons); 1162 1209 } 1163 1210 1164 1211 return $form;