2012-12-28 00:20:09 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class PhabricatorConfigEditController
|
|
|
|
extends PhabricatorConfigController {
|
|
|
|
|
|
|
|
private $key;
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
2012-12-31 00:36:06 +01:00
|
|
|
$this->key = $data['key'];
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
$user = $request->getUser();
|
|
|
|
|
2012-12-31 00:36:06 +01:00
|
|
|
|
|
|
|
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
|
|
|
|
if (empty($options[$this->key])) {
|
2013-06-26 20:01:19 +02:00
|
|
|
$ancient = PhabricatorSetupCheckExtraConfig::getAncientConfig();
|
|
|
|
if (isset($ancient[$this->key])) {
|
|
|
|
$desc = pht(
|
|
|
|
"This configuration has been removed. You can safely delete ".
|
|
|
|
"it.\n\n%s",
|
|
|
|
$ancient[$this->key]);
|
|
|
|
} else {
|
|
|
|
$desc = pht(
|
|
|
|
"This configuration option is unknown. It may be misspelled, ".
|
|
|
|
"or have existed in a previous version of Phabricator.");
|
|
|
|
}
|
|
|
|
|
2013-01-01 23:09:29 +01:00
|
|
|
// This may be a dead config entry, which existed in the past but no
|
|
|
|
// longer exists. Allow it to be edited so it can be reviewed and
|
|
|
|
// deleted.
|
|
|
|
$option = id(new PhabricatorConfigOption())
|
|
|
|
->setKey($this->key)
|
|
|
|
->setType('wild')
|
|
|
|
->setDefault(null)
|
2013-06-26 20:01:19 +02:00
|
|
|
->setDescription($desc);
|
2013-01-01 23:09:29 +01:00
|
|
|
$group = null;
|
|
|
|
$group_uri = $this->getApplicationURI();
|
|
|
|
} else {
|
|
|
|
$option = $options[$this->key];
|
|
|
|
$group = $option->getGroup();
|
|
|
|
$group_uri = $this->getApplicationURI('group/'.$group->getKey().'/');
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|
2012-12-31 00:36:06 +01:00
|
|
|
|
2012-12-31 02:04:38 +01:00
|
|
|
$issue = $request->getStr('issue');
|
|
|
|
if ($issue) {
|
|
|
|
// If the user came here from an open setup issue, send them back.
|
|
|
|
$done_uri = $this->getApplicationURI('issue/'.$issue.'/');
|
|
|
|
} else {
|
|
|
|
$done_uri = $group_uri;
|
|
|
|
}
|
|
|
|
|
2012-12-28 00:20:09 +01:00
|
|
|
// Check if the config key is already stored in the database.
|
|
|
|
// Grab the value if it is.
|
|
|
|
$config_entry = id(new PhabricatorConfigEntry())
|
|
|
|
->loadOneWhere(
|
2012-12-31 00:36:06 +01:00
|
|
|
'configKey = %s AND namespace = %s',
|
2012-12-28 00:20:09 +01:00
|
|
|
$this->key,
|
|
|
|
'default');
|
2013-01-01 23:09:17 +01:00
|
|
|
if (!$config_entry) {
|
2012-12-28 00:20:09 +01:00
|
|
|
$config_entry = id(new PhabricatorConfigEntry())
|
2013-01-01 23:09:17 +01:00
|
|
|
->setConfigKey($this->key)
|
|
|
|
->setNamespace('default')
|
|
|
|
->setIsDeleted(true);
|
2013-07-30 22:26:55 +02:00
|
|
|
$config_entry->setPHID($config_entry->generatePHID());
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$e_value = null;
|
|
|
|
$errors = array();
|
2013-01-02 23:02:43 +01:00
|
|
|
if ($request->isFormPost() && !$option->getLocked()) {
|
2012-12-31 00:36:06 +01:00
|
|
|
|
2013-01-02 03:14:41 +01:00
|
|
|
$result = $this->readRequest(
|
2013-01-01 23:09:17 +01:00
|
|
|
$option,
|
|
|
|
$request);
|
2012-12-28 00:20:09 +01:00
|
|
|
|
2013-01-02 03:14:41 +01:00
|
|
|
list($e_value, $value_errors, $display_value, $xaction) = $result;
|
2013-01-01 23:09:17 +01:00
|
|
|
$errors = array_merge($errors, $value_errors);
|
2012-12-28 00:20:09 +01:00
|
|
|
|
|
|
|
if (!$errors) {
|
2013-01-02 03:14:41 +01:00
|
|
|
|
|
|
|
$editor = id(new PhabricatorConfigEditor())
|
|
|
|
->setActor($user)
|
|
|
|
->setContinueOnNoEffect(true)
|
2013-05-24 19:48:34 +02:00
|
|
|
->setContentSourceFromRequest($request);
|
2013-01-02 03:14:41 +01:00
|
|
|
|
2013-01-02 03:15:03 +01:00
|
|
|
try {
|
|
|
|
$editor->applyTransactions($config_entry, array($xaction));
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($done_uri);
|
|
|
|
} catch (PhabricatorConfigValidationException $ex) {
|
|
|
|
$e_value = pht('Invalid');
|
|
|
|
$errors[] = $ex->getMessage();
|
|
|
|
}
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
} else {
|
|
|
|
$display_value = $this->getDisplayValue($option, $config_entry);
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$form = new AphrontFormView();
|
|
|
|
|
|
|
|
$error_view = null;
|
|
|
|
if ($errors) {
|
|
|
|
$error_view = id(new AphrontErrorView())
|
2013-01-01 23:09:17 +01:00
|
|
|
->setTitle(pht('You broke everything!'))
|
2012-12-28 00:20:09 +01:00
|
|
|
->setErrors($errors);
|
2013-01-03 15:01:14 +01:00
|
|
|
} else if ($option->getHidden()) {
|
|
|
|
$msg = pht(
|
|
|
|
"This configuration is hidden and can not be edited or viewed from ".
|
|
|
|
"the web interface.");
|
|
|
|
|
|
|
|
$error_view = id(new AphrontErrorView())
|
|
|
|
->setTitle(pht('Configuration Hidden'))
|
|
|
|
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
|
2013-02-07 01:53:49 +01:00
|
|
|
->appendChild(phutil_tag('p', array(), $msg));
|
2013-01-02 23:02:43 +01:00
|
|
|
} else if ($option->getLocked()) {
|
|
|
|
$msg = pht(
|
|
|
|
"This configuration is locked and can not be edited from the web ".
|
2013-07-22 21:21:08 +02:00
|
|
|
"interface. Use `./bin/config` in `phabricator/` to edit it.");
|
2013-01-02 23:02:43 +01:00
|
|
|
|
|
|
|
$error_view = id(new AphrontErrorView())
|
|
|
|
->setTitle(pht('Configuration Locked'))
|
|
|
|
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
2013-02-07 01:53:49 +01:00
|
|
|
->appendChild(phutil_tag('p', array(), $msg));
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|
|
|
|
|
2013-01-03 15:01:14 +01:00
|
|
|
if ($option->getHidden()) {
|
|
|
|
$control = null;
|
|
|
|
} else {
|
|
|
|
$control = $this->renderControl(
|
|
|
|
$option,
|
|
|
|
$display_value,
|
|
|
|
$e_value);
|
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
|
|
|
|
$engine = new PhabricatorMarkupEngine();
|
2013-03-04 21:33:05 +01:00
|
|
|
$engine->setViewer($user);
|
2013-01-01 23:09:17 +01:00
|
|
|
$engine->addObject($option, 'description');
|
|
|
|
$engine->process();
|
2013-01-18 09:32:58 +01:00
|
|
|
$description = phutil_tag(
|
2013-01-01 23:09:17 +01:00
|
|
|
'div',
|
|
|
|
array(
|
|
|
|
'class' => 'phabricator-remarkup',
|
|
|
|
),
|
2013-02-05 23:30:29 +01:00
|
|
|
$engine->getOutput($option, 'description'));
|
2013-01-01 23:09:17 +01:00
|
|
|
|
2012-12-28 00:20:09 +01:00
|
|
|
$form
|
|
|
|
->setUser($user)
|
2012-12-31 02:04:38 +01:00
|
|
|
->addHiddenInput('issue', $request->getStr('issue'))
|
2012-12-28 00:20:09 +01:00
|
|
|
->appendChild(
|
2013-01-01 23:09:17 +01:00
|
|
|
id(new AphrontFormMarkupControl())
|
2013-01-01 23:09:59 +01:00
|
|
|
->setLabel(pht('Description'))
|
2013-07-12 22:10:03 +02:00
|
|
|
->setValue($description));
|
|
|
|
|
|
|
|
if ($group) {
|
|
|
|
$extra = $group->renderContextualDescription(
|
|
|
|
$option,
|
|
|
|
$request);
|
|
|
|
if ($extra !== null) {
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormMarkupControl())
|
|
|
|
->setValue($extra));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$form
|
2013-01-02 23:02:43 +01:00
|
|
|
->appendChild($control);
|
|
|
|
|
2013-01-03 15:01:14 +01:00
|
|
|
$submit_control = id(new AphrontFormSubmitControl())
|
|
|
|
->addCancelButton($done_uri);
|
|
|
|
|
2013-01-02 23:02:43 +01:00
|
|
|
if (!$option->getLocked()) {
|
2013-01-03 15:01:14 +01:00
|
|
|
$submit_control->setValue(pht('Save Config Entry'));
|
2013-01-02 23:02:43 +01:00
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
|
2013-01-03 15:01:14 +01:00
|
|
|
$form->appendChild($submit_control);
|
|
|
|
|
2013-01-01 23:09:59 +01:00
|
|
|
$examples = $this->renderExamples($option);
|
|
|
|
if ($examples) {
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormMarkupControl())
|
|
|
|
->setLabel(pht('Examples'))
|
|
|
|
->setValue($examples));
|
|
|
|
}
|
|
|
|
|
2013-01-03 15:01:14 +01:00
|
|
|
if (!$option->getHidden()) {
|
|
|
|
$form->appendChild(
|
|
|
|
id(new AphrontFormMarkupControl())
|
|
|
|
->setLabel(pht('Default'))
|
|
|
|
->setValue($this->renderDefaults($option)));
|
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
|
2013-01-01 23:10:33 +01:00
|
|
|
$title = pht('Edit %s', $this->key);
|
|
|
|
$short = pht('Edit');
|
2012-12-28 00:20:09 +01:00
|
|
|
|
2013-08-26 20:53:11 +02:00
|
|
|
$form_box = id(new PHUIFormBoxView())
|
|
|
|
->setHeaderText($title)
|
|
|
|
->setFormError($error_view)
|
|
|
|
->setForm($form);
|
|
|
|
|
2012-12-31 00:36:06 +01:00
|
|
|
$crumbs = $this->buildApplicationCrumbs();
|
2013-01-01 23:09:29 +01:00
|
|
|
$crumbs->addCrumb(
|
|
|
|
id(new PhabricatorCrumbView())
|
|
|
|
->setName(pht('Config'))
|
|
|
|
->setHref($this->getApplicationURI()));
|
|
|
|
|
|
|
|
if ($group) {
|
|
|
|
$crumbs->addCrumb(
|
2012-12-31 00:36:06 +01:00
|
|
|
id(new PhabricatorCrumbView())
|
|
|
|
->setName($group->getName())
|
2013-01-01 23:09:29 +01:00
|
|
|
->setHref($group_uri));
|
|
|
|
}
|
|
|
|
|
|
|
|
$crumbs->addCrumb(
|
|
|
|
id(new PhabricatorCrumbView())
|
|
|
|
->setName($this->key)
|
|
|
|
->setHref('/config/edit/'.$this->key));
|
2012-12-28 00:20:09 +01:00
|
|
|
|
2013-01-02 03:14:41 +01:00
|
|
|
$xactions = id(new PhabricatorConfigTransactionQuery())
|
|
|
|
->withObjectPHIDs(array($config_entry->getPHID()))
|
|
|
|
->setViewer($user)
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
$xaction_view = id(new PhabricatorApplicationTransactionView())
|
|
|
|
->setUser($user)
|
2013-07-29 03:21:22 +02:00
|
|
|
->setObjectPHID($config_entry->getPHID())
|
2013-01-02 03:14:41 +01:00
|
|
|
->setTransactions($xactions);
|
|
|
|
|
2012-12-28 00:20:09 +01:00
|
|
|
return $this->buildApplicationPage(
|
|
|
|
array(
|
|
|
|
$crumbs,
|
2013-08-26 20:53:11 +02:00
|
|
|
$form_box,
|
2013-01-02 03:14:41 +01:00
|
|
|
$xaction_view,
|
2012-12-28 00:20:09 +01:00
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => $title,
|
|
|
|
'device' => true,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2013-01-01 23:09:17 +01:00
|
|
|
private function readRequest(
|
|
|
|
PhabricatorConfigOption $option,
|
|
|
|
AphrontRequest $request) {
|
|
|
|
|
2013-01-02 03:14:41 +01:00
|
|
|
$xaction = new PhabricatorConfigTransaction();
|
|
|
|
$xaction->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT);
|
|
|
|
|
2013-01-01 23:09:17 +01:00
|
|
|
$e_value = null;
|
|
|
|
$errors = array();
|
|
|
|
|
|
|
|
$value = $request->getStr('value');
|
|
|
|
if (!strlen($value)) {
|
|
|
|
$value = null;
|
2013-01-02 03:14:41 +01:00
|
|
|
|
|
|
|
$xaction->setNewValue(
|
|
|
|
array(
|
|
|
|
'deleted' => true,
|
|
|
|
'value' => null,
|
|
|
|
));
|
|
|
|
|
|
|
|
return array($e_value, $errors, $value, $xaction);
|
2013-01-01 23:09:17 +01:00
|
|
|
}
|
|
|
|
|
2013-06-07 21:36:18 +02:00
|
|
|
if ($option->isCustomType()) {
|
|
|
|
$info = $option->getCustomObject()->readRequest($option, $request);
|
|
|
|
list($e_value, $errors, $set_value, $value) = $info;
|
|
|
|
} else {
|
|
|
|
$type = $option->getType();
|
|
|
|
$set_value = null;
|
|
|
|
|
|
|
|
switch ($type) {
|
|
|
|
case 'int':
|
|
|
|
if (preg_match('/^-?[0-9]+$/', trim($value))) {
|
|
|
|
$set_value = (int)$value;
|
|
|
|
} else {
|
2013-01-01 23:09:17 +01:00
|
|
|
$e_value = pht('Invalid');
|
2013-06-07 21:36:18 +02:00
|
|
|
$errors[] = pht('Value must be an integer.');
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'string':
|
|
|
|
case 'enum':
|
|
|
|
$set_value = (string)$value;
|
|
|
|
break;
|
|
|
|
case 'list<string>':
|
|
|
|
$set_value = $request->getStrList('value');
|
|
|
|
break;
|
|
|
|
case 'set':
|
|
|
|
$set_value = array_fill_keys($request->getStrList('value'), true);
|
|
|
|
break;
|
|
|
|
case 'bool':
|
|
|
|
switch ($value) {
|
|
|
|
case 'true':
|
|
|
|
$set_value = true;
|
|
|
|
break;
|
|
|
|
case 'false':
|
|
|
|
$set_value = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$e_value = pht('Invalid');
|
|
|
|
$errors[] = pht('Value must be boolean, "true" or "false".');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'class':
|
|
|
|
if (!class_exists($value)) {
|
2013-01-03 15:01:14 +01:00
|
|
|
$e_value = pht('Invalid');
|
2013-06-07 21:36:18 +02:00
|
|
|
$errors[] = pht('Class does not exist.');
|
2013-01-03 15:01:14 +01:00
|
|
|
} else {
|
2013-06-07 21:36:18 +02:00
|
|
|
$base = $option->getBaseClass();
|
|
|
|
if (!is_subclass_of($value, $base)) {
|
|
|
|
$e_value = pht('Invalid');
|
|
|
|
$errors[] = pht('Class is not of valid type.');
|
|
|
|
} else {
|
|
|
|
$set_value = $value;
|
|
|
|
}
|
2013-01-03 15:01:14 +01:00
|
|
|
}
|
2013-06-07 21:36:18 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$json = json_decode($value, true);
|
|
|
|
if ($json === null && strtolower($value) != 'null') {
|
|
|
|
$e_value = pht('Invalid');
|
|
|
|
$errors[] = pht(
|
|
|
|
'The given value must be valid JSON. This means, among '.
|
|
|
|
'other things, that you must wrap strings in double-quotes.');
|
|
|
|
} else {
|
|
|
|
$set_value = $json;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
}
|
|
|
|
|
2013-01-02 03:14:41 +01:00
|
|
|
if (!$errors) {
|
|
|
|
$xaction->setNewValue(
|
|
|
|
array(
|
|
|
|
'deleted' => false,
|
|
|
|
'value' => $set_value,
|
|
|
|
));
|
|
|
|
} else {
|
|
|
|
$xaction = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return array($e_value, $errors, $value, $xaction);
|
2013-01-01 23:09:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function getDisplayValue(
|
|
|
|
PhabricatorConfigOption $option,
|
|
|
|
PhabricatorConfigEntry $entry) {
|
|
|
|
|
|
|
|
if ($entry->getIsDeleted()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-06-07 21:36:18 +02:00
|
|
|
if ($option->isCustomType()) {
|
|
|
|
return $option->getCustomObject()->getDisplayValue($option, $entry);
|
|
|
|
} else {
|
|
|
|
$type = $option->getType();
|
|
|
|
$value = $entry->getValue();
|
|
|
|
switch ($type) {
|
|
|
|
case 'int':
|
|
|
|
case 'string':
|
|
|
|
case 'enum':
|
|
|
|
case 'class':
|
|
|
|
return $value;
|
|
|
|
case 'bool':
|
|
|
|
return $value ? 'true' : 'false';
|
|
|
|
case 'list<string>':
|
|
|
|
return implode("\n", nonempty($value, array()));
|
|
|
|
case 'set':
|
|
|
|
return implode("\n", nonempty(array_keys($value), array()));
|
|
|
|
default:
|
|
|
|
return PhabricatorConfigJSON::prettyPrintJSON($value);
|
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private function renderControl(
|
|
|
|
PhabricatorConfigOption $option,
|
|
|
|
$display_value,
|
|
|
|
$e_value) {
|
|
|
|
|
2013-06-07 21:36:18 +02:00
|
|
|
if ($option->isCustomType()) {
|
|
|
|
$control = $option->getCustomObject()->renderControl(
|
|
|
|
$option,
|
|
|
|
$display_value,
|
|
|
|
$e_value);
|
|
|
|
} else {
|
|
|
|
$type = $option->getType();
|
|
|
|
switch ($type) {
|
|
|
|
case 'int':
|
|
|
|
case 'string':
|
|
|
|
$control = id(new AphrontFormTextControl());
|
|
|
|
break;
|
|
|
|
case 'bool':
|
|
|
|
$control = id(new AphrontFormSelectControl())
|
|
|
|
->setOptions(
|
|
|
|
array(
|
|
|
|
'' => pht('(Use Default)'),
|
|
|
|
'true' => idx($option->getBoolOptions(), 0),
|
|
|
|
'false' => idx($option->getBoolOptions(), 1),
|
|
|
|
));
|
|
|
|
break;
|
|
|
|
case 'enum':
|
|
|
|
$options = array_mergev(
|
2013-01-01 23:09:17 +01:00
|
|
|
array(
|
2013-06-07 21:36:18 +02:00
|
|
|
array('' => pht('(Use Default)')),
|
|
|
|
$option->getEnumOptions(),
|
2013-01-01 23:09:17 +01:00
|
|
|
));
|
2013-06-07 21:36:18 +02:00
|
|
|
$control = id(new AphrontFormSelectControl())
|
|
|
|
->setOptions($options);
|
|
|
|
break;
|
|
|
|
case 'class':
|
|
|
|
$symbols = id(new PhutilSymbolLoader())
|
|
|
|
->setType('class')
|
|
|
|
->setAncestorClass($option->getBaseClass())
|
|
|
|
->setConcreteOnly(true)
|
|
|
|
->selectSymbolsWithoutLoading();
|
|
|
|
$names = ipull($symbols, 'name', 'name');
|
|
|
|
asort($names);
|
|
|
|
$names = array(
|
|
|
|
'' => pht('(Use Default)'),
|
|
|
|
) + $names;
|
|
|
|
|
|
|
|
$control = id(new AphrontFormSelectControl())
|
|
|
|
->setOptions($names);
|
|
|
|
break;
|
|
|
|
case 'list<string>':
|
|
|
|
case 'set':
|
|
|
|
$control = id(new AphrontFormTextAreaControl())
|
|
|
|
->setCaption(pht('Separate values with newlines or commas.'));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$control = id(new AphrontFormTextAreaControl())
|
|
|
|
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
|
|
|
|
->setCustomClass('PhabricatorMonospaced')
|
|
|
|
->setCaption(pht('Enter value in JSON.'));
|
|
|
|
break;
|
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
|
2013-06-07 21:36:18 +02:00
|
|
|
$control
|
|
|
|
->setLabel(pht('Value'))
|
|
|
|
->setError($e_value)
|
|
|
|
->setValue($display_value)
|
|
|
|
->setName('value');
|
|
|
|
}
|
2013-01-01 23:09:17 +01:00
|
|
|
|
2013-01-02 23:02:43 +01:00
|
|
|
if ($option->getLocked()) {
|
|
|
|
$control->setDisabled(true);
|
|
|
|
}
|
|
|
|
|
2013-01-01 23:09:17 +01:00
|
|
|
return $control;
|
|
|
|
}
|
|
|
|
|
2013-01-01 23:09:59 +01:00
|
|
|
private function renderExamples(PhabricatorConfigOption $option) {
|
|
|
|
$examples = $option->getExamples();
|
|
|
|
if (!$examples) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = array();
|
2013-02-05 23:30:29 +01:00
|
|
|
$table[] = hsprintf(
|
|
|
|
'<tr class="column-labels"><th>%s</th><th>%s</th></tr>',
|
|
|
|
pht('Example'),
|
|
|
|
pht('Value'));
|
2013-01-01 23:09:59 +01:00
|
|
|
foreach ($examples as $example) {
|
|
|
|
list($value, $description) = $example;
|
|
|
|
|
|
|
|
if ($value === null) {
|
2013-02-05 23:30:29 +01:00
|
|
|
$value = phutil_tag('em', array(), pht('(empty)'));
|
2013-01-01 23:09:59 +01:00
|
|
|
} else {
|
2013-08-06 18:29:22 +02:00
|
|
|
if (is_array($value)) {
|
|
|
|
$value = implode("\n", $value);
|
|
|
|
}
|
2013-02-05 23:30:29 +01:00
|
|
|
$value = phutil_escape_html_newlines($value);
|
2013-01-01 23:09:59 +01:00
|
|
|
}
|
|
|
|
|
2013-02-05 23:30:29 +01:00
|
|
|
$table[] = hsprintf(
|
|
|
|
'<tr><th>%s</th><td>%s</td></tr>',
|
|
|
|
$description,
|
|
|
|
$value);
|
2013-01-01 23:10:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
require_celerity_resource('config-options-css');
|
|
|
|
|
2013-01-18 09:32:58 +01:00
|
|
|
return phutil_tag(
|
2013-01-01 23:10:33 +01:00
|
|
|
'table',
|
|
|
|
array(
|
|
|
|
'class' => 'config-option-table',
|
|
|
|
),
|
2013-02-05 23:30:29 +01:00
|
|
|
$table);
|
2013-01-01 23:10:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function renderDefaults(PhabricatorConfigOption $option) {
|
|
|
|
$stack = PhabricatorEnv::getConfigSourceStack();
|
|
|
|
$stack = $stack->getStack();
|
|
|
|
|
|
|
|
$table = array();
|
2013-02-05 23:30:29 +01:00
|
|
|
$table[] = hsprintf(
|
|
|
|
'<tr class="column-labels"><th>%s</th><th>%s</th></tr>',
|
|
|
|
pht('Source'),
|
|
|
|
pht('Value'));
|
2013-01-01 23:10:33 +01:00
|
|
|
foreach ($stack as $key => $source) {
|
|
|
|
$value = $source->getKeys(
|
|
|
|
array(
|
|
|
|
$option->getKey(),
|
|
|
|
));
|
|
|
|
|
|
|
|
if (!array_key_exists($option->getKey(), $value)) {
|
2013-02-05 23:30:29 +01:00
|
|
|
$value = phutil_tag('em', array(), pht('(empty)'));
|
2013-01-01 23:10:33 +01:00
|
|
|
} else {
|
2013-01-12 00:28:33 +01:00
|
|
|
$value = PhabricatorConfigJSON::prettyPrintJSON(
|
|
|
|
$value[$option->getKey()]);
|
2013-01-01 23:10:33 +01:00
|
|
|
}
|
|
|
|
|
2013-02-05 23:30:29 +01:00
|
|
|
$table[] = hsprintf(
|
|
|
|
'<tr><th>%s</th><td>%s</td></tr>',
|
|
|
|
$source->getName(),
|
|
|
|
$value);
|
2013-01-01 23:09:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
require_celerity_resource('config-options-css');
|
|
|
|
|
2013-01-18 09:32:58 +01:00
|
|
|
return phutil_tag(
|
2013-01-01 23:09:59 +01:00
|
|
|
'table',
|
|
|
|
array(
|
2013-01-01 23:10:33 +01:00
|
|
|
'class' => 'config-option-table',
|
2013-01-01 23:09:59 +01:00
|
|
|
),
|
2013-02-05 23:30:29 +01:00
|
|
|
$table);
|
2013-01-01 23:09:59 +01:00
|
|
|
}
|
|
|
|
|
2012-12-28 00:20:09 +01:00
|
|
|
}
|