@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 the "list<string>" and "list<regex>" Config option types

Summary: Ref T12845. This updates the "list<string>" and "list<regex>" options.

Test Plan: Set, deleted, and mangled options of these types from the web UI and CLI.

Reviewers: chad, amckinley

Reviewed By: amckinley

Maniphest Tasks: T12845

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

+141 -96
+6
src/__phutil_library_map__.php
··· 3746 3746 'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php', 3747 3747 'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php', 3748 3748 'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php', 3749 + 'PhabricatorRegexListConfigType' => 'applications/config/type/PhabricatorRegexListConfigType.php', 3749 3750 'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php', 3750 3751 'PhabricatorReleephApplication' => 'applications/releeph/application/PhabricatorReleephApplication.php', 3751 3752 'PhabricatorReleephApplicationConfigOptions' => 'applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php', ··· 4071 4072 'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php', 4072 4073 'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php', 4073 4074 'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php', 4075 + 'PhabricatorStringListConfigType' => 'applications/config/type/PhabricatorStringListConfigType.php', 4074 4076 'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php', 4075 4077 'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php', 4076 4078 'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php', ··· 4133 4135 'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php', 4134 4136 'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php', 4135 4137 'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php', 4138 + 'PhabricatorTextListConfigType' => 'applications/config/type/PhabricatorTextListConfigType.php', 4136 4139 'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php', 4137 4140 'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php', 4138 4141 'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php', ··· 9207 9210 'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions', 9208 9211 'PhabricatorRedirectController' => 'PhabricatorController', 9209 9212 'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController', 9213 + 'PhabricatorRegexListConfigType' => 'PhabricatorTextListConfigType', 9210 9214 'PhabricatorRegistrationProfile' => 'Phobject', 9211 9215 'PhabricatorReleephApplication' => 'PhabricatorApplication', 9212 9216 'PhabricatorReleephApplicationConfigOptions' => 'PhabricatorApplicationConfigOptions', ··· 9609 9613 'PhabricatorStorageSchemaSpec' => 'PhabricatorConfigSchemaSpec', 9610 9614 'PhabricatorStorageSetupCheck' => 'PhabricatorSetupCheck', 9611 9615 'PhabricatorStringConfigType' => 'PhabricatorTextConfigType', 9616 + 'PhabricatorStringListConfigType' => 'PhabricatorTextListConfigType', 9612 9617 'PhabricatorStringListEditField' => 'PhabricatorEditField', 9613 9618 'PhabricatorStringSetting' => 'PhabricatorSetting', 9614 9619 'PhabricatorSubmitEditField' => 'PhabricatorEditField', ··· 9670 9675 'PhabricatorTextAreaEditField' => 'PhabricatorEditField', 9671 9676 'PhabricatorTextConfigType' => 'PhabricatorConfigType', 9672 9677 'PhabricatorTextEditField' => 'PhabricatorEditField', 9678 + 'PhabricatorTextListConfigType' => 'PhabricatorTextConfigType', 9673 9679 'PhabricatorTime' => 'Phobject', 9674 9680 'PhabricatorTimeFormatSetting' => 'PhabricatorSelectSetting', 9675 9681 'PhabricatorTimeGuard' => 'Phobject',
-22
src/applications/config/controller/PhabricatorConfigEditController.php
··· 347 347 $set_value = null; 348 348 349 349 switch ($type) { 350 - case 'list<string>': 351 - case 'list<regex>': 352 - $set_value = phutil_split_lines( 353 - $request->getStr('value'), 354 - $retain_endings = false); 355 - 356 - foreach ($set_value as $key => $v) { 357 - if (!strlen($v)) { 358 - unset($set_value[$key]); 359 - } 360 - } 361 - $set_value = array_values($set_value); 362 - 363 - break; 364 350 case 'set': 365 351 $set_value = array_fill_keys($request->getStrList('value'), true); 366 352 break; ··· 441 427 return $value; 442 428 case 'bool': 443 429 return $value ? 'true' : 'false'; 444 - case 'list<string>': 445 - case 'list<regex>': 446 - return implode("\n", nonempty($value, array())); 447 430 case 'set': 448 431 return implode("\n", nonempty(array_keys($value), array())); 449 432 default: ··· 496 479 497 480 $control = id(new AphrontFormSelectControl()) 498 481 ->setOptions($names); 499 - break; 500 - case 'list<string>': 501 - case 'list<regex>': 502 - $control = id(new AphrontFormTextAreaControl()) 503 - ->setCaption(pht('Separate values with newlines.')); 504 482 break; 505 483 case 'set': 506 484 $control = id(new AphrontFormTextAreaControl())
+5 -20
src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php
··· 65 65 $value = $type->newValueFromCommandLineValue( 66 66 $option, 67 67 $value); 68 + $type->validateStoredValue($option, $value); 68 69 } catch (PhabricatorConfigValidationException $ex) { 69 70 throw new PhutilArgumentUsageException($ex->getMessage()); 70 71 } ··· 109 110 $command); 110 111 break; 111 112 default: 112 - if (preg_match('/^list</', $type)) { 113 - $command = csprintf( 114 - './bin/config set %R %s', 115 - $key, 116 - '["a", "b", "c"]'); 117 - 118 - $message = sprintf( 119 - "%s\n\n %s\n", 120 - pht( 121 - 'Config key "%s" is of type "%s". Specify it in JSON. '. 122 - 'For example:', 123 - $key, 124 - $type), 125 - $command); 126 - } else { 127 - $message = pht( 128 - 'Config key "%s" is of type "%s". Specify it in JSON.', 129 - $key, 130 - $type); 131 - } 113 + $message = pht( 114 + 'Config key "%s" is of type "%s". Specify it in JSON.', 115 + $key, 116 + $type); 132 117 break; 133 118 } 134 119 throw new PhutilArgumentUsageException($message);
-54
src/applications/config/option/PhabricatorApplicationConfigOptions.php
··· 85 85 } 86 86 } 87 87 break; 88 - case 'list<regex>': 89 - $valid = true; 90 - if (!is_array($value)) { 91 - throw new PhabricatorConfigValidationException( 92 - pht( 93 - "Option '%s' must be a list of regular expressions, but value ". 94 - "is not an array.", 95 - $option->getKey())); 96 - } 97 - if ($value && array_keys($value) != range(0, count($value) - 1)) { 98 - throw new PhabricatorConfigValidationException( 99 - pht( 100 - "Option '%s' must be a list of regular expressions, but the ". 101 - "value is a map with unnatural keys.", 102 - $option->getKey())); 103 - } 104 - foreach ($value as $v) { 105 - $ok = @preg_match($v, ''); 106 - if ($ok === false) { 107 - throw new PhabricatorConfigValidationException( 108 - pht( 109 - "Option '%s' must be a list of regular expressions, but the ". 110 - "value '%s' is not a valid regular expression.", 111 - $option->getKey(), 112 - $v)); 113 - } 114 - } 115 - break; 116 - case 'list<string>': 117 - $valid = true; 118 - if (!is_array($value)) { 119 - throw new PhabricatorConfigValidationException( 120 - pht( 121 - "Option '%s' must be a list of strings, but value is not ". 122 - "an array.", 123 - $option->getKey())); 124 - } 125 - if ($value && array_keys($value) != range(0, count($value) - 1)) { 126 - throw new PhabricatorConfigValidationException( 127 - pht( 128 - "Option '%s' must be a list of strings, but the value is a ". 129 - "map with unnatural keys.", 130 - $option->getKey())); 131 - } 132 - foreach ($value as $v) { 133 - if (!is_string($v)) { 134 - throw new PhabricatorConfigValidationException( 135 - pht( 136 - "Option '%s' must be a list of strings, but it contains one ". 137 - "or more non-strings.", 138 - $option->getKey())); 139 - } 140 - } 141 - break; 142 88 case 'wild': 143 89 default: 144 90 break;
+24
src/applications/config/type/PhabricatorRegexListConfigType.php
··· 1 + <?php 2 + 3 + final class PhabricatorRegexListConfigType 4 + extends PhabricatorTextListConfigType { 5 + 6 + const TYPEKEY = 'list<regex>'; 7 + 8 + protected function validateStoredItem( 9 + PhabricatorConfigOption $option, 10 + $value) { 11 + 12 + $ok = @preg_match($value, ''); 13 + if ($ok === false) { 14 + throw $this->newException( 15 + pht( 16 + 'Option "%s" is of type "%s" and must be set to a list of valid '. 17 + 'regular expressions, but "%s" is not a valid regular expression.', 18 + $option->getKey(), 19 + $this->getTypeKey(), 20 + $value)); 21 + } 22 + } 23 + 24 + }
+8
src/applications/config/type/PhabricatorStringListConfigType.php
··· 1 + <?php 2 + 3 + final class PhabricatorStringListConfigType 4 + extends PhabricatorTextListConfigType { 5 + 6 + const TYPEKEY = 'list<string>'; 7 + 8 + }
+98
src/applications/config/type/PhabricatorTextListConfigType.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorTextListConfigType 4 + extends PhabricatorTextConfigType { 5 + 6 + protected function newControl(PhabricatorConfigOption $option) { 7 + return id(new AphrontFormTextAreaControl()) 8 + ->setCaption(pht('Separate values with newlines.')); 9 + } 10 + 11 + protected function newCanonicalValue( 12 + PhabricatorConfigOption $option, 13 + $value) { 14 + 15 + $value = phutil_split_lines($value, $retain_endings = false); 16 + foreach ($value as $k => $v) { 17 + if (!strlen($v)) { 18 + unset($value[$k]); 19 + } 20 + } 21 + 22 + return array_values($value); 23 + } 24 + 25 + public function newValueFromCommandLineValue( 26 + PhabricatorConfigOption $option, 27 + $value) { 28 + 29 + try { 30 + $value = phutil_json_decode($value); 31 + } catch (Exception $ex) { 32 + throw $this->newException( 33 + pht( 34 + 'Option "%s" is of type "%s", but the value you provided is not a '. 35 + 'valid JSON list. When setting a list option from the command '. 36 + 'line, specify the value in JSON. You may need to quote the '. 37 + 'value for your shell (for example: \'["a", "b", ...]\').', 38 + $option->getKey(), 39 + $this->getTypeKey())); 40 + } 41 + 42 + return $value; 43 + } 44 + 45 + public function newDisplayValue( 46 + PhabricatorConfigOption $option, 47 + $value) { 48 + return implode("\n", $value); 49 + } 50 + 51 + public function validateStoredValue( 52 + PhabricatorConfigOption $option, 53 + $value) { 54 + 55 + if (!is_array($value)) { 56 + throw $this->newException( 57 + pht( 58 + 'Option "%s" is of type "%s", but the configured value is not '. 59 + 'a list.', 60 + $option->getKey(), 61 + $this->getTypeKey())); 62 + } 63 + 64 + $expect_key = 0; 65 + foreach ($value as $k => $v) { 66 + if (!is_string($v)) { 67 + throw $this->newException( 68 + pht( 69 + 'Option "%s" is of type "%s", but the item at index "%s" of the '. 70 + 'list is not a string.', 71 + $option->getKey(), 72 + $this->getTypeKey(), 73 + $k)); 74 + } 75 + 76 + // Make sure this is a list with keys "0, 1, 2, ...", not a map with 77 + // arbitrary keys. 78 + if ($k != $expect_key) { 79 + throw $this->newException( 80 + pht( 81 + 'Option "%s" is of type "%s", but the value is not a list: it '. 82 + 'is a map with unnatural or sparse keys.', 83 + $option->getKey(), 84 + $this->getTypeKey())); 85 + } 86 + $expect_key++; 87 + 88 + $this->validateStoredItem($option, $v); 89 + } 90 + } 91 + 92 + protected function validateStoredItem( 93 + PhabricatorConfigOption $option, 94 + $value) { 95 + return; 96 + } 97 + 98 + }