Skip to content

Commit 0afdabf

Browse files
author
epriestley
committedJun 27, 2017
Convert 'class' config options to new validation
Summary: Ref T12845. These options prompt the user to select from among concrete subclasses of some base class. Test Plan: Set, deleted and mangled these values from the web UI and CLI. Reviewers: chad, amckinley Reviewed By: amckinley Maniphest Tasks: T12845 Differential Revision: https://secure.phabricator.com/D18159
1 parent 72119e7 commit 0afdabf

5 files changed

+78
-49
lines changed
 

‎src/__phutil_library_map__.php

+2
Original file line numberDiff line numberDiff line change
@@ -2329,6 +2329,7 @@
23292329
'PhabricatorChatLogEvent' => 'applications/chatlog/storage/PhabricatorChatLogEvent.php',
23302330
'PhabricatorChatLogQuery' => 'applications/chatlog/query/PhabricatorChatLogQuery.php',
23312331
'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php',
2332+
'PhabricatorClassConfigType' => 'applications/config/type/PhabricatorClassConfigType.php',
23322333
'PhabricatorClusterConfigOptions' => 'applications/config/option/PhabricatorClusterConfigOptions.php',
23332334
'PhabricatorClusterDatabasesConfigOptionType' => 'infrastructure/cluster/config/PhabricatorClusterDatabasesConfigOptionType.php',
23342335
'PhabricatorClusterException' => 'infrastructure/cluster/exception/PhabricatorClusterException.php',
@@ -7575,6 +7576,7 @@
75757576
),
75767577
'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
75777578
'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine',
7579+
'PhabricatorClassConfigType' => 'PhabricatorTextConfigType',
75787580
'PhabricatorClusterConfigOptions' => 'PhabricatorApplicationConfigOptions',
75797581
'PhabricatorClusterDatabasesConfigOptionType' => 'PhabricatorConfigJSONOptionType',
75807582
'PhabricatorClusterException' => 'Exception',

‎src/applications/config/controller/PhabricatorConfigEditController.php

-31
Original file line numberDiff line numberDiff line change
@@ -350,20 +350,6 @@ private function readRequest(
350350
case 'set':
351351
$set_value = array_fill_keys($request->getStrList('value'), true);
352352
break;
353-
case 'class':
354-
if (!class_exists($value)) {
355-
$e_value = pht('Invalid');
356-
$errors[] = pht('Class does not exist.');
357-
} else {
358-
$base = $option->getBaseClass();
359-
if (!is_subclass_of($value, $base)) {
360-
$e_value = pht('Invalid');
361-
$errors[] = pht('Class is not of valid type.');
362-
} else {
363-
$set_value = $value;
364-
}
365-
}
366-
break;
367353
default:
368354
$json = json_decode($value, true);
369355
if ($json === null && strtolower($value) != 'null') {
@@ -409,8 +395,6 @@ private function getDisplayValue(
409395
} else {
410396
$type = $option->getType();
411397
switch ($type) {
412-
case 'class':
413-
return $value;
414398
case 'set':
415399
return implode("\n", nonempty(array_keys($value), array()));
416400
default:
@@ -440,21 +424,6 @@ private function renderControls(
440424
} else {
441425
$type = $option->getType();
442426
switch ($type) {
443-
case 'class':
444-
$symbols = id(new PhutilSymbolLoader())
445-
->setType('class')
446-
->setAncestorClass($option->getBaseClass())
447-
->setConcreteOnly(true)
448-
->selectSymbolsWithoutLoading();
449-
$names = ipull($symbols, 'name', 'name');
450-
asort($names);
451-
$names = array(
452-
'' => pht('(Use Default)'),
453-
) + $names;
454-
455-
$control = id(new AphrontFormSelectControl())
456-
->setOptions($names);
457-
break;
458427
case 'set':
459428
$control = id(new AphrontFormTextAreaControl())
460429
->setCaption(pht('Separate values with newlines or commas.'));

‎src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php

-3
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ public function execute(PhutilArgumentParser $args) {
7272
} else {
7373
$type = $option->getType();
7474
switch ($type) {
75-
case 'class':
76-
$value = (string)$value;
77-
break;
7875
default:
7976
$value = json_decode($value, true);
8077
if (!is_array($value)) {

‎src/applications/config/option/PhabricatorApplicationConfigOptions.php

-15
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,6 @@ public function validateOption(PhabricatorConfigOption $option, $value) {
4343
}
4444

4545
switch ($option->getType()) {
46-
case 'class':
47-
$symbols = id(new PhutilSymbolLoader())
48-
->setType('class')
49-
->setAncestorClass($option->getBaseClass())
50-
->setConcreteOnly(true)
51-
->selectSymbolsWithoutLoading();
52-
$names = ipull($symbols, 'name', 'name');
53-
if (empty($names[$value])) {
54-
throw new PhabricatorConfigValidationException(
55-
pht(
56-
"Option '%s' value must name a class extending '%s'.",
57-
$option->getKey(),
58-
$option->getBaseClass()));
59-
}
60-
break;
6146
case 'set':
6247
$valid = true;
6348
if (!is_array($value)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
final class PhabricatorClassConfigType
4+
extends PhabricatorTextConfigType {
5+
6+
const TYPEKEY = 'class';
7+
8+
public function validateStoredValue(
9+
PhabricatorConfigOption $option,
10+
$value) {
11+
12+
if (!is_string($value)) {
13+
throw $this->newException(
14+
pht(
15+
'Option "%s" is of type "%s", but the configured value is not '.
16+
'a string.',
17+
$option->getKey(),
18+
$this->getTypeKey()));
19+
}
20+
21+
$base = $option->getBaseClass();
22+
$map = $this->getClassOptions($option);
23+
24+
try {
25+
$ok = class_exists($value);
26+
} catch (Exception $ex) {
27+
$ok = false;
28+
}
29+
30+
if (!$ok) {
31+
throw $this->newException(
32+
pht(
33+
'Option "%s" is of type "%s", but the configured value is not the '.
34+
'name of a known class. Valid selections are: %s.',
35+
$option->getKey(),
36+
$this->getTypeKey(),
37+
implode(', ', array_keys($map))));
38+
}
39+
40+
if (!isset($map[$value])) {
41+
throw $this->newException(
42+
pht(
43+
'Option "%s" is of type "%s", but the current value ("%s") is not '.
44+
'a known, concrete subclass of base class "%s". Valid selections '.
45+
'are: %s.',
46+
$option->getKey(),
47+
$this->getTypeKey(),
48+
$value,
49+
$base,
50+
implode(', ', array_keys($map))));
51+
}
52+
}
53+
54+
protected function newControl(PhabricatorConfigOption $option) {
55+
$map = array(
56+
'' => pht('(Use Default)'),
57+
) + $this->getClassOptions($option);
58+
59+
return id(new AphrontFormSelectControl())
60+
->setOptions($map);
61+
}
62+
63+
private function getClassOptions(PhabricatorConfigOption $option) {
64+
$symbols = id(new PhutilSymbolLoader())
65+
->setType('class')
66+
->setAncestorClass($option->getBaseClass())
67+
->setConcreteOnly(true)
68+
->selectSymbolsWithoutLoading();
69+
70+
$map = ipull($symbols, 'name', 'name');
71+
asort($map);
72+
73+
return $map;
74+
}
75+
76+
}

0 commit comments

Comments
 (0)
Failed to load comments.