@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 '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

+78 -49
+2
src/__phutil_library_map__.php
··· 2329 2329 'PhabricatorChatLogEvent' => 'applications/chatlog/storage/PhabricatorChatLogEvent.php', 2330 2330 'PhabricatorChatLogQuery' => 'applications/chatlog/query/PhabricatorChatLogQuery.php', 2331 2331 'PhabricatorChunkedFileStorageEngine' => 'applications/files/engine/PhabricatorChunkedFileStorageEngine.php', 2332 + 'PhabricatorClassConfigType' => 'applications/config/type/PhabricatorClassConfigType.php', 2332 2333 'PhabricatorClusterConfigOptions' => 'applications/config/option/PhabricatorClusterConfigOptions.php', 2333 2334 'PhabricatorClusterDatabasesConfigOptionType' => 'infrastructure/cluster/config/PhabricatorClusterDatabasesConfigOptionType.php', 2334 2335 'PhabricatorClusterException' => 'infrastructure/cluster/exception/PhabricatorClusterException.php', ··· 7575 7576 ), 7576 7577 'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 7577 7578 'PhabricatorChunkedFileStorageEngine' => 'PhabricatorFileStorageEngine', 7579 + 'PhabricatorClassConfigType' => 'PhabricatorTextConfigType', 7578 7580 'PhabricatorClusterConfigOptions' => 'PhabricatorApplicationConfigOptions', 7579 7581 'PhabricatorClusterDatabasesConfigOptionType' => 'PhabricatorConfigJSONOptionType', 7580 7582 'PhabricatorClusterException' => 'Exception',
-31
src/applications/config/controller/PhabricatorConfigEditController.php
··· 350 350 case 'set': 351 351 $set_value = array_fill_keys($request->getStrList('value'), true); 352 352 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; 367 353 default: 368 354 $json = json_decode($value, true); 369 355 if ($json === null && strtolower($value) != 'null') { ··· 409 395 } else { 410 396 $type = $option->getType(); 411 397 switch ($type) { 412 - case 'class': 413 - return $value; 414 398 case 'set': 415 399 return implode("\n", nonempty(array_keys($value), array())); 416 400 default: ··· 440 424 } else { 441 425 $type = $option->getType(); 442 426 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; 458 427 case 'set': 459 428 $control = id(new AphrontFormTextAreaControl()) 460 429 ->setCaption(pht('Separate values with newlines or commas.'));
-3
src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php
··· 72 72 } else { 73 73 $type = $option->getType(); 74 74 switch ($type) { 75 - case 'class': 76 - $value = (string)$value; 77 - break; 78 75 default: 79 76 $value = json_decode($value, true); 80 77 if (!is_array($value)) {
-15
src/applications/config/option/PhabricatorApplicationConfigOptions.php
··· 43 43 } 44 44 45 45 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; 61 46 case 'set': 62 47 $valid = true; 63 48 if (!is_array($value)) {
+76
src/applications/config/type/PhabricatorClassConfigType.php
··· 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 + }