mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 16:52:41 +01:00
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
This commit is contained in:
parent
9d30d49cfc
commit
467be5e53f
7 changed files with 141 additions and 96 deletions
|
@ -3746,6 +3746,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
|
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
|
||||||
'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php',
|
'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php',
|
||||||
'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php',
|
'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php',
|
||||||
|
'PhabricatorRegexListConfigType' => 'applications/config/type/PhabricatorRegexListConfigType.php',
|
||||||
'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php',
|
'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php',
|
||||||
'PhabricatorReleephApplication' => 'applications/releeph/application/PhabricatorReleephApplication.php',
|
'PhabricatorReleephApplication' => 'applications/releeph/application/PhabricatorReleephApplication.php',
|
||||||
'PhabricatorReleephApplicationConfigOptions' => 'applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php',
|
'PhabricatorReleephApplicationConfigOptions' => 'applications/releeph/config/PhabricatorReleephApplicationConfigOptions.php',
|
||||||
|
@ -4071,6 +4072,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php',
|
'PhabricatorStorageSchemaSpec' => 'infrastructure/storage/schema/PhabricatorStorageSchemaSpec.php',
|
||||||
'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php',
|
'PhabricatorStorageSetupCheck' => 'applications/config/check/PhabricatorStorageSetupCheck.php',
|
||||||
'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php',
|
'PhabricatorStringConfigType' => 'applications/config/type/PhabricatorStringConfigType.php',
|
||||||
|
'PhabricatorStringListConfigType' => 'applications/config/type/PhabricatorStringListConfigType.php',
|
||||||
'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php',
|
'PhabricatorStringListEditField' => 'applications/transactions/editfield/PhabricatorStringListEditField.php',
|
||||||
'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php',
|
'PhabricatorStringSetting' => 'applications/settings/setting/PhabricatorStringSetting.php',
|
||||||
'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php',
|
'PhabricatorSubmitEditField' => 'applications/transactions/editfield/PhabricatorSubmitEditField.php',
|
||||||
|
@ -4133,6 +4135,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php',
|
'PhabricatorTextAreaEditField' => 'applications/transactions/editfield/PhabricatorTextAreaEditField.php',
|
||||||
'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php',
|
'PhabricatorTextConfigType' => 'applications/config/type/PhabricatorTextConfigType.php',
|
||||||
'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php',
|
'PhabricatorTextEditField' => 'applications/transactions/editfield/PhabricatorTextEditField.php',
|
||||||
|
'PhabricatorTextListConfigType' => 'applications/config/type/PhabricatorTextListConfigType.php',
|
||||||
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
|
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
|
||||||
'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php',
|
'PhabricatorTimeFormatSetting' => 'applications/settings/setting/PhabricatorTimeFormatSetting.php',
|
||||||
'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php',
|
'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php',
|
||||||
|
@ -9207,6 +9210,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
'PhabricatorRedirectController' => 'PhabricatorController',
|
'PhabricatorRedirectController' => 'PhabricatorController',
|
||||||
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
|
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
|
||||||
|
'PhabricatorRegexListConfigType' => 'PhabricatorTextListConfigType',
|
||||||
'PhabricatorRegistrationProfile' => 'Phobject',
|
'PhabricatorRegistrationProfile' => 'Phobject',
|
||||||
'PhabricatorReleephApplication' => 'PhabricatorApplication',
|
'PhabricatorReleephApplication' => 'PhabricatorApplication',
|
||||||
'PhabricatorReleephApplicationConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
'PhabricatorReleephApplicationConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||||
|
@ -9609,6 +9613,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorStorageSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'PhabricatorStorageSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
'PhabricatorStorageSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorStorageSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorStringConfigType' => 'PhabricatorTextConfigType',
|
'PhabricatorStringConfigType' => 'PhabricatorTextConfigType',
|
||||||
|
'PhabricatorStringListConfigType' => 'PhabricatorTextListConfigType',
|
||||||
'PhabricatorStringListEditField' => 'PhabricatorEditField',
|
'PhabricatorStringListEditField' => 'PhabricatorEditField',
|
||||||
'PhabricatorStringSetting' => 'PhabricatorSetting',
|
'PhabricatorStringSetting' => 'PhabricatorSetting',
|
||||||
'PhabricatorSubmitEditField' => 'PhabricatorEditField',
|
'PhabricatorSubmitEditField' => 'PhabricatorEditField',
|
||||||
|
@ -9670,6 +9675,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorTextAreaEditField' => 'PhabricatorEditField',
|
'PhabricatorTextAreaEditField' => 'PhabricatorEditField',
|
||||||
'PhabricatorTextConfigType' => 'PhabricatorConfigType',
|
'PhabricatorTextConfigType' => 'PhabricatorConfigType',
|
||||||
'PhabricatorTextEditField' => 'PhabricatorEditField',
|
'PhabricatorTextEditField' => 'PhabricatorEditField',
|
||||||
|
'PhabricatorTextListConfigType' => 'PhabricatorTextConfigType',
|
||||||
'PhabricatorTime' => 'Phobject',
|
'PhabricatorTime' => 'Phobject',
|
||||||
'PhabricatorTimeFormatSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorTimeFormatSetting' => 'PhabricatorSelectSetting',
|
||||||
'PhabricatorTimeGuard' => 'Phobject',
|
'PhabricatorTimeGuard' => 'Phobject',
|
||||||
|
|
|
@ -347,20 +347,6 @@ final class PhabricatorConfigEditController
|
||||||
$set_value = null;
|
$set_value = null;
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'list<string>':
|
|
||||||
case 'list<regex>':
|
|
||||||
$set_value = phutil_split_lines(
|
|
||||||
$request->getStr('value'),
|
|
||||||
$retain_endings = false);
|
|
||||||
|
|
||||||
foreach ($set_value as $key => $v) {
|
|
||||||
if (!strlen($v)) {
|
|
||||||
unset($set_value[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$set_value = array_values($set_value);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'set':
|
case 'set':
|
||||||
$set_value = array_fill_keys($request->getStrList('value'), true);
|
$set_value = array_fill_keys($request->getStrList('value'), true);
|
||||||
break;
|
break;
|
||||||
|
@ -441,9 +427,6 @@ final class PhabricatorConfigEditController
|
||||||
return $value;
|
return $value;
|
||||||
case 'bool':
|
case 'bool':
|
||||||
return $value ? 'true' : 'false';
|
return $value ? 'true' : 'false';
|
||||||
case 'list<string>':
|
|
||||||
case 'list<regex>':
|
|
||||||
return implode("\n", nonempty($value, array()));
|
|
||||||
case 'set':
|
case 'set':
|
||||||
return implode("\n", nonempty(array_keys($value), array()));
|
return implode("\n", nonempty(array_keys($value), array()));
|
||||||
default:
|
default:
|
||||||
|
@ -497,11 +480,6 @@ final class PhabricatorConfigEditController
|
||||||
$control = id(new AphrontFormSelectControl())
|
$control = id(new AphrontFormSelectControl())
|
||||||
->setOptions($names);
|
->setOptions($names);
|
||||||
break;
|
break;
|
||||||
case 'list<string>':
|
|
||||||
case 'list<regex>':
|
|
||||||
$control = id(new AphrontFormTextAreaControl())
|
|
||||||
->setCaption(pht('Separate values with newlines.'));
|
|
||||||
break;
|
|
||||||
case 'set':
|
case 'set':
|
||||||
$control = id(new AphrontFormTextAreaControl())
|
$control = id(new AphrontFormTextAreaControl())
|
||||||
->setCaption(pht('Separate values with newlines or commas.'));
|
->setCaption(pht('Separate values with newlines or commas.'));
|
||||||
|
|
|
@ -65,6 +65,7 @@ final class PhabricatorConfigManagementSetWorkflow
|
||||||
$value = $type->newValueFromCommandLineValue(
|
$value = $type->newValueFromCommandLineValue(
|
||||||
$option,
|
$option,
|
||||||
$value);
|
$value);
|
||||||
|
$type->validateStoredValue($option, $value);
|
||||||
} catch (PhabricatorConfigValidationException $ex) {
|
} catch (PhabricatorConfigValidationException $ex) {
|
||||||
throw new PhutilArgumentUsageException($ex->getMessage());
|
throw new PhutilArgumentUsageException($ex->getMessage());
|
||||||
}
|
}
|
||||||
|
@ -109,26 +110,10 @@ final class PhabricatorConfigManagementSetWorkflow
|
||||||
$command);
|
$command);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (preg_match('/^list</', $type)) {
|
$message = pht(
|
||||||
$command = csprintf(
|
'Config key "%s" is of type "%s". Specify it in JSON.',
|
||||||
'./bin/config set %R %s',
|
$key,
|
||||||
$key,
|
$type);
|
||||||
'["a", "b", "c"]');
|
|
||||||
|
|
||||||
$message = sprintf(
|
|
||||||
"%s\n\n %s\n",
|
|
||||||
pht(
|
|
||||||
'Config key "%s" is of type "%s". Specify it in JSON. '.
|
|
||||||
'For example:',
|
|
||||||
$key,
|
|
||||||
$type),
|
|
||||||
$command);
|
|
||||||
} else {
|
|
||||||
$message = pht(
|
|
||||||
'Config key "%s" is of type "%s". Specify it in JSON.',
|
|
||||||
$key,
|
|
||||||
$type);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw new PhutilArgumentUsageException($message);
|
throw new PhutilArgumentUsageException($message);
|
||||||
|
|
|
@ -85,60 +85,6 @@ abstract class PhabricatorApplicationConfigOptions extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'list<regex>':
|
|
||||||
$valid = true;
|
|
||||||
if (!is_array($value)) {
|
|
||||||
throw new PhabricatorConfigValidationException(
|
|
||||||
pht(
|
|
||||||
"Option '%s' must be a list of regular expressions, but value ".
|
|
||||||
"is not an array.",
|
|
||||||
$option->getKey()));
|
|
||||||
}
|
|
||||||
if ($value && array_keys($value) != range(0, count($value) - 1)) {
|
|
||||||
throw new PhabricatorConfigValidationException(
|
|
||||||
pht(
|
|
||||||
"Option '%s' must be a list of regular expressions, but the ".
|
|
||||||
"value is a map with unnatural keys.",
|
|
||||||
$option->getKey()));
|
|
||||||
}
|
|
||||||
foreach ($value as $v) {
|
|
||||||
$ok = @preg_match($v, '');
|
|
||||||
if ($ok === false) {
|
|
||||||
throw new PhabricatorConfigValidationException(
|
|
||||||
pht(
|
|
||||||
"Option '%s' must be a list of regular expressions, but the ".
|
|
||||||
"value '%s' is not a valid regular expression.",
|
|
||||||
$option->getKey(),
|
|
||||||
$v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'list<string>':
|
|
||||||
$valid = true;
|
|
||||||
if (!is_array($value)) {
|
|
||||||
throw new PhabricatorConfigValidationException(
|
|
||||||
pht(
|
|
||||||
"Option '%s' must be a list of strings, but value is not ".
|
|
||||||
"an array.",
|
|
||||||
$option->getKey()));
|
|
||||||
}
|
|
||||||
if ($value && array_keys($value) != range(0, count($value) - 1)) {
|
|
||||||
throw new PhabricatorConfigValidationException(
|
|
||||||
pht(
|
|
||||||
"Option '%s' must be a list of strings, but the value is a ".
|
|
||||||
"map with unnatural keys.",
|
|
||||||
$option->getKey()));
|
|
||||||
}
|
|
||||||
foreach ($value as $v) {
|
|
||||||
if (!is_string($v)) {
|
|
||||||
throw new PhabricatorConfigValidationException(
|
|
||||||
pht(
|
|
||||||
"Option '%s' must be a list of strings, but it contains one ".
|
|
||||||
"or more non-strings.",
|
|
||||||
$option->getKey()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'wild':
|
case 'wild':
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorRegexListConfigType
|
||||||
|
extends PhabricatorTextListConfigType {
|
||||||
|
|
||||||
|
const TYPEKEY = 'list<regex>';
|
||||||
|
|
||||||
|
protected function validateStoredItem(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
|
||||||
|
$ok = @preg_match($value, '');
|
||||||
|
if ($ok === false) {
|
||||||
|
throw $this->newException(
|
||||||
|
pht(
|
||||||
|
'Option "%s" is of type "%s" and must be set to a list of valid '.
|
||||||
|
'regular expressions, but "%s" is not a valid regular expression.',
|
||||||
|
$option->getKey(),
|
||||||
|
$this->getTypeKey(),
|
||||||
|
$value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorStringListConfigType
|
||||||
|
extends PhabricatorTextListConfigType {
|
||||||
|
|
||||||
|
const TYPEKEY = 'list<string>';
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorTextListConfigType
|
||||||
|
extends PhabricatorTextConfigType {
|
||||||
|
|
||||||
|
protected function newControl(PhabricatorConfigOption $option) {
|
||||||
|
return id(new AphrontFormTextAreaControl())
|
||||||
|
->setCaption(pht('Separate values with newlines.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newCanonicalValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
|
||||||
|
$value = phutil_split_lines($value, $retain_endings = false);
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
if (!strlen($v)) {
|
||||||
|
unset($value[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newValueFromCommandLineValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$value = phutil_json_decode($value);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
throw $this->newException(
|
||||||
|
pht(
|
||||||
|
'Option "%s" is of type "%s", but the value you provided is not a '.
|
||||||
|
'valid JSON list. When setting a list option from the command '.
|
||||||
|
'line, specify the value in JSON. You may need to quote the '.
|
||||||
|
'value for your shell (for example: \'["a", "b", ...]\').',
|
||||||
|
$option->getKey(),
|
||||||
|
$this->getTypeKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDisplayValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
return implode("\n", $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validateStoredValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
|
||||||
|
if (!is_array($value)) {
|
||||||
|
throw $this->newException(
|
||||||
|
pht(
|
||||||
|
'Option "%s" is of type "%s", but the configured value is not '.
|
||||||
|
'a list.',
|
||||||
|
$option->getKey(),
|
||||||
|
$this->getTypeKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
$expect_key = 0;
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
if (!is_string($v)) {
|
||||||
|
throw $this->newException(
|
||||||
|
pht(
|
||||||
|
'Option "%s" is of type "%s", but the item at index "%s" of the '.
|
||||||
|
'list is not a string.',
|
||||||
|
$option->getKey(),
|
||||||
|
$this->getTypeKey(),
|
||||||
|
$k));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure this is a list with keys "0, 1, 2, ...", not a map with
|
||||||
|
// arbitrary keys.
|
||||||
|
if ($k != $expect_key) {
|
||||||
|
throw $this->newException(
|
||||||
|
pht(
|
||||||
|
'Option "%s" is of type "%s", but the value is not a list: it '.
|
||||||
|
'is a map with unnatural or sparse keys.',
|
||||||
|
$option->getKey(),
|
||||||
|
$this->getTypeKey()));
|
||||||
|
}
|
||||||
|
$expect_key++;
|
||||||
|
|
||||||
|
$this->validateStoredItem($option, $v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateStoredItem(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue