[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/config/option/ -> PhabricatorApplicationConfigOptions.php (source)

   1  <?php
   2  
   3  abstract class PhabricatorApplicationConfigOptions extends Phobject {
   4  
   5    abstract public function getName();
   6    abstract public function getDescription();
   7    abstract public function getOptions();
   8  
   9    public function validateOption(PhabricatorConfigOption $option, $value) {
  10      if ($value === $option->getDefault()) {
  11        return;
  12      }
  13  
  14      if ($value === null) {
  15        return;
  16      }
  17  
  18      if ($option->isCustomType()) {
  19        return $option->getCustomObject()->validateOption($option, $value);
  20      }
  21  
  22      switch ($option->getType()) {
  23        case 'bool':
  24          if ($value !== true &&
  25              $value !== false) {
  26            throw new PhabricatorConfigValidationException(
  27              pht(
  28                "Option '%s' is of type bool, but value is not true or false.",
  29                $option->getKey()));
  30          }
  31          break;
  32        case 'int':
  33          if (!is_int($value)) {
  34            throw new PhabricatorConfigValidationException(
  35              pht(
  36                "Option '%s' is of type int, but value is not an integer.",
  37                $option->getKey()));
  38          }
  39          break;
  40        case 'string':
  41          if (!is_string($value)) {
  42            throw new PhabricatorConfigValidationException(
  43              pht(
  44                "Option '%s' is of type string, but value is not a string.",
  45                $option->getKey()));
  46          }
  47          break;
  48        case 'class':
  49          $symbols = id(new PhutilSymbolLoader())
  50            ->setType('class')
  51            ->setAncestorClass($option->getBaseClass())
  52            ->setConcreteOnly(true)
  53            ->selectSymbolsWithoutLoading();
  54          $names = ipull($symbols, 'name', 'name');
  55          if (empty($names[$value])) {
  56            throw new PhabricatorConfigValidationException(
  57              pht(
  58                "Option '%s' value must name a class extending '%s'.",
  59                $option->getKey(),
  60                $option->getBaseClass()));
  61          }
  62          break;
  63        case 'set':
  64          $valid = true;
  65          if (!is_array($value)) {
  66            throw new PhabricatorConfigValidationException(
  67              pht(
  68                "Option '%s' must be a set, but value is not an array.",
  69                $option->getKey()));
  70          }
  71          foreach ($value as $v) {
  72            if ($v !== true) {
  73              throw new PhabricatorConfigValidationException(
  74                pht(
  75                  "Option '%s' must be a set, but array contains values other ".
  76                  "than 'true'.",
  77                  $option->getKey()));
  78            }
  79          }
  80          break;
  81        case 'list<regex>':
  82          $valid = true;
  83          if (!is_array($value)) {
  84            throw new PhabricatorConfigValidationException(
  85              pht(
  86                "Option '%s' must be a list of regular expressions, but value ".
  87                "is not an array.",
  88                $option->getKey()));
  89          }
  90          if ($value && array_keys($value) != range(0, count($value) - 1)) {
  91            throw new PhabricatorConfigValidationException(
  92              pht(
  93                "Option '%s' must be a list of regular expressions, but the ".
  94                "value is a map with unnatural keys.",
  95                $option->getKey()));
  96          }
  97          foreach ($value as $v) {
  98            $ok = @preg_match($v, '');
  99            if ($ok === false) {
 100              throw new PhabricatorConfigValidationException(
 101                pht(
 102                  "Option '%s' must be a list of regular expressions, but the ".
 103                  "value '%s' is not a valid regular expression.",
 104                  $option->getKey(),
 105                  $v));
 106            }
 107          }
 108          break;
 109        case 'list<string>':
 110          $valid = true;
 111          if (!is_array($value)) {
 112            throw new PhabricatorConfigValidationException(
 113              pht(
 114                "Option '%s' must be a list of strings, but value is not ".
 115                "an array.",
 116                $option->getKey()));
 117          }
 118          if ($value && array_keys($value) != range(0, count($value) - 1)) {
 119            throw new PhabricatorConfigValidationException(
 120              pht(
 121                "Option '%s' must be a list of strings, but the value is a ".
 122                "map with unnatural keys.",
 123                $option->getKey()));
 124          }
 125          foreach ($value as $v) {
 126            if (!is_string($v)) {
 127              throw new PhabricatorConfigValidationException(
 128                pht(
 129                  "Option '%s' must be a list of strings, but it contains one ".
 130                  "or more non-strings.",
 131                  $option->getKey()));
 132            }
 133          }
 134          break;
 135        case 'wild':
 136        default:
 137          break;
 138      }
 139  
 140      $this->didValidateOption($option, $value);
 141    }
 142  
 143    protected function didValidateOption(
 144      PhabricatorConfigOption $option,
 145      $value) {
 146      // Hook for subclasses to do complex validation.
 147      return;
 148    }
 149  
 150    /**
 151     * Hook to render additional hints based on, e.g., the viewing user, request,
 152     * or other context. For example, this is used to show workspace IDs when
 153     * configuring `asana.workspace-id`.
 154     *
 155     * @param   PhabricatorConfigOption   Option being rendered.
 156     * @param   AphrontRequest            Active request.
 157     * @return  wild                      Additional contextual description
 158     *                                    information.
 159     */
 160    public function renderContextualDescription(
 161      PhabricatorConfigOption $option,
 162      AphrontRequest $request) {
 163      return null;
 164    }
 165  
 166    public function getKey() {
 167      $class = get_class($this);
 168      $matches = null;
 169      if (preg_match('/^Phabricator(.*)ConfigOptions$/', $class, $matches)) {
 170        return strtolower($matches[1]);
 171      }
 172      return strtolower(get_class($this));
 173    }
 174  
 175    final protected function newOption($key, $type, $default) {
 176      return id(new PhabricatorConfigOption())
 177        ->setKey($key)
 178        ->setType($type)
 179        ->setDefault($default)
 180        ->setGroup($this);
 181    }
 182  
 183    final public static function loadAll($external_only = false) {
 184      $symbols = id(new PhutilSymbolLoader())
 185        ->setAncestorClass('PhabricatorApplicationConfigOptions')
 186        ->setConcreteOnly(true)
 187        ->selectAndLoadSymbols();
 188  
 189      $groups = array();
 190      foreach ($symbols as $symbol) {
 191        if ($external_only && $symbol['library'] == 'phabricator') {
 192          continue;
 193        }
 194  
 195        $obj = newv($symbol['name'], array());
 196        $key = $obj->getKey();
 197        if (isset($groups[$key])) {
 198          $pclass = get_class($groups[$key]);
 199          $nclass = $symbol['name'];
 200  
 201          throw new Exception(
 202            "Multiple PhabricatorApplicationConfigOptions subclasses have the ".
 203            "same key ('{$key}'): {$pclass}, {$nclass}.");
 204        }
 205        $groups[$key] = $obj;
 206      }
 207  
 208      return $groups;
 209    }
 210  
 211    final public static function loadAllOptions($external_only = false) {
 212      $groups = self::loadAll($external_only);
 213  
 214      $options = array();
 215      foreach ($groups as $group) {
 216        foreach ($group->getOptions() as $option) {
 217          $key = $option->getKey();
 218          if (isset($options[$key])) {
 219            throw new Exception(
 220              "Mulitple PhabricatorApplicationConfigOptions subclasses contain ".
 221              "an option named '{$key}'!");
 222          }
 223          $options[$key] = $option;
 224        }
 225      }
 226  
 227      return $options;
 228    }
 229  
 230    /**
 231     * Deformat a HEREDOC for use in remarkup by converting line breaks to
 232     * spaces.
 233     */
 234    final protected function deformat($string) {
 235      return preg_replace('/(?<=\S)\n(?=\S)/', ' ', $string);
 236    }
 237  
 238  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1