protected function didValidateOption(PhabricatorConfigOption $option, $value) { $key = $option->getKey(); if ($key == 'phabricator.base-uri' || $key == 'phabricator.production-uri') { $uri = new PhutilURI($value); $protocol = $uri->getProtocol(); if ($protocol !== 'http' && $protocol !== 'https') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must start with " . "%s' or '%s'.", 'http://', 'https://', $key)); } $domain = $uri->getDomain(); if (strpos($domain, '.') === false) { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must contain a dot " . "('%s'), like '%s', not just a bare name like '%s'. Some web " . "browsers will not set cookies on domains with no TLD.", '.', 'http://example.com/', 'http://example/', $key)); } $path = $uri->getPath(); if ($path !== '' && $path !== '/') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must NOT have a path, " . "e.g. '%s' is OK, but '%s' is not. Phabricator must be installed " . "on an entire domain; it can not be installed on a path.", $key, 'http://phabricator.example.com/', 'http://example.com/phabricator/')); } } if ($key === 'phabricator.timezone') { $old = date_default_timezone_get(); $ok = @date_default_timezone_set($value); @date_default_timezone_set($old); if (!$ok) { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The timezone identifier must " . "be a valid timezone identifier recognized by PHP, like '%s'. " . "\n You can find a list of valid identifiers here: %s", $key, 'America/Los_Angeles', 'http://php.net/manual/timezones.php')); } } }
public function renderControl(PhabricatorConfigOption $option, $display_value, $e_value) { $field_base_class = $option->getCustomData(); $field_spec = $display_value; if (!is_array($field_spec)) { $field_spec = PhabricatorEnv::getEnvConfig($option->getKey()); } // Get all of the fields (including disabled fields) by querying for them // with a faux spec where no fields are disabled. $faux_spec = $field_spec; foreach ($faux_spec as $key => $spec) { unset($faux_spec[$key]['disabled']); } // TODO: We might need to build a real object here eventually. $faux_object = null; $fields = PhabricatorCustomField::buildFieldList($field_base_class, $faux_spec, $faux_object); $list_id = celerity_generate_unique_node_id(); $input_id = celerity_generate_unique_node_id(); $list = id(new PHUIObjectItemListView())->setFlush(true)->setID($list_id); foreach ($fields as $key => $field) { $item = id(new PHUIObjectItemView())->addSigil('field-spec')->setMetadata(array('fieldKey' => $key))->setGrippable(true)->addAttribute($field->getFieldDescription())->setHeader($field->getFieldName()); $is_disabled = !empty($field_spec[$key]['disabled']); $disabled_item = clone $item; $enabled_item = clone $item; if ($is_disabled) { $list->addItem($disabled_item); } else { $list->addItem($enabled_item); } $disabled_item->addIcon('none', pht('Disabled')); $disabled_item->setDisabled(true); $disabled_item->addAction(id(new PHUIListItemView())->setHref('#')->addSigil('field-spec-toggle')->setIcon('fa-plus')); $enabled_item->setBarColor('green'); if (!$field->canDisableField()) { $enabled_item->addAction(id(new PHUIListItemView())->setIcon('fa-lock grey')); $enabled_item->addIcon('none', pht('Permanent Field')); } else { $enabled_item->addAction(id(new PHUIListItemView())->setHref('#')->addSigil('field-spec-toggle')->setIcon('fa-times')); } $fields[$key] = array('disabled' => $is_disabled, 'disabledMarkup' => $disabled_item->render(), 'enabledMarkup' => $enabled_item->render()); } $input = phutil_tag('input', array('id' => $input_id, 'type' => 'hidden', 'name' => 'value', 'value' => json_encode($display_value))); Javelin::initBehavior('config-reorder-fields', array('listID' => $list_id, 'inputID' => $input_id, 'fields' => $fields)); return id(new AphrontFormMarkupControl())->setLabel(pht('Value'))->setError($e_value)->setValue(array($list, $input)); }
protected function didValidateOption(PhabricatorConfigOption $option, $value) { $key = $option->getKey(); if ($key == 'security.alternate-file-domain') { $uri = new PhutilURI($value); $protocol = $uri->getProtocol(); if ($protocol !== 'http' && $protocol !== 'https') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must start with " . "'%s' or '%s'.", $key, 'http://', 'https://')); } $domain = $uri->getDomain(); if (strpos($domain, '.') === false) { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must contain a dot ('.'), " . "like '%s', not just a bare name like '%s'. " . "Some web browsers will not set cookies on domains with no TLD.", $key, 'http://example.com/', 'http://example/')); } $path = $uri->getPath(); if ($path !== '' && $path !== '/') { throw new PhabricatorConfigValidationException(pht("Config option '%s' is invalid. The URI must NOT have a path, " . "e.g. '%s' is OK, but '%s' is not. Phabricator must be installed " . "on an entire domain; it can not be installed on a path.", $key, 'http://phabricator.example.com/', 'http://example.com/phabricator/')); } } }
public function renderContextualDescription(PhabricatorConfigOption $option, AphrontRequest $request) { switch ($option->getKey()) { case 'asana.workspace-id': break; case 'asana.project-ids': return $this->renderContextualProjectDescription($option, $request); default: return parent::renderContextualDescription($option, $request); } $viewer = $request->getUser(); $provider = PhabricatorAsanaAuthProvider::getAsanaProvider(); if (!$provider) { return null; } $account = id(new PhabricatorExternalAccountQuery())->setViewer($viewer)->withUserPHIDs(array($viewer->getPHID()))->withAccountTypes(array($provider->getProviderType()))->withAccountDomains(array($provider->getProviderDomain()))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne(); if (!$account) { return null; } $token = $provider->getOAuthAccessToken($account); if (!$token) { return null; } try { $workspaces = id(new PhutilAsanaFuture())->setAccessToken($token)->setRawAsanaQuery('workspaces')->resolve(); } catch (Exception $ex) { return null; } if (!$workspaces) { return null; } $out = array(); $out[] = pht('| Workspace ID | Workspace Name |'); $out[] = '| ------------ | -------------- |'; foreach ($workspaces as $workspace) { $out[] = sprintf('| `%s` | `%s` |', $workspace['id'], $workspace['name']); } $out = implode("\n", $out); $out = pht("The Asana Workspaces your linked account has access to are:\n\n%s", $out); return PhabricatorMarkupEngine::renderOneObject(id(new PhabricatorMarkupOneOff())->setContent($out), 'default', $viewer); }
public function validateOption(PhabricatorConfigOption $option, $value) { if ($value === $option->getDefault()) { return; } if ($value === null) { return; } if ($option->isCustomType()) { try { return $option->getCustomObject()->validateOption($option, $value); } catch (Exception $ex) { // If custom validators threw exceptions, convert them to configuation // validation exceptions so we repair the configuration and raise // an error. throw new PhabricatorConfigValidationException($ex->getMessage()); } } switch ($option->getType()) { case 'bool': if ($value !== true && $value !== false) { throw new PhabricatorConfigValidationException(pht("Option '%s' is of type bool, but value is not true or false.", $option->getKey())); } break; case 'int': if (!is_int($value)) { throw new PhabricatorConfigValidationException(pht("Option '%s' is of type int, but value is not an integer.", $option->getKey())); } break; case 'string': if (!is_string($value)) { throw new PhabricatorConfigValidationException(pht("Option '%s' is of type string, but value is not a string.", $option->getKey())); } break; case 'class': $symbols = id(new PhutilSymbolLoader())->setType('class')->setAncestorClass($option->getBaseClass())->setConcreteOnly(true)->selectSymbolsWithoutLoading(); $names = ipull($symbols, 'name', 'name'); if (empty($names[$value])) { throw new PhabricatorConfigValidationException(pht("Option '%s' value must name a class extending '%s'.", $option->getKey(), $option->getBaseClass())); } break; case 'set': $valid = true; if (!is_array($value)) { throw new PhabricatorConfigValidationException(pht("Option '%s' must be a set, but value is not an array.", $option->getKey())); } foreach ($value as $v) { if ($v !== true) { throw new PhabricatorConfigValidationException(pht("Option '%s' must be a set, but array contains values other " . "than 'true'.", $option->getKey())); } } 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': default: break; } $this->didValidateOption($option, $value); }
private function renderDefaults(PhabricatorConfigOption $option, PhabricatorConfigEntry $entry) { $stack = PhabricatorEnv::getConfigSourceStack(); $stack = $stack->getStack(); $table = array(); $table[] = phutil_tag('tr', array('class' => 'column-labels'), array(phutil_tag('th', array(), pht('Source')), phutil_tag('th', array(), pht('Value')))); foreach ($stack as $key => $source) { $value = $source->getKeys(array($option->getKey())); if (!array_key_exists($option->getKey(), $value)) { $value = phutil_tag('em', array(), pht('(empty)')); } else { $value = $this->getDisplayValue($option, $entry, $value[$option->getKey()]); } $table[] = phutil_tag('tr', array('class' => 'column-labels'), array(phutil_tag('th', array(), $source->getName()), phutil_tag('td', array(), $value))); } require_celerity_resource('config-options-css'); return phutil_tag('table', array('class' => 'config-option-table'), $table); }