mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 18:22:41 +01:00
Detect and raise setup warnings from within Phabricator
Summary: This is basicaly a light version of D4286. The major problem with D4286 is that it's a huge leap and completely replaces the setup process in one step. Instead, I want to do this: - Add the post-setup warnings (yellow bar with "6 unresolved warnings..."). - Copy all setup checks into post-setup warnings (so every check has an old-style check and a new-style check). - Run that for a little bit and make sure it's stable. - Implement fatal post-setup checks (the red screen, vs the yellow bar). - Run that for a little bit. - Nuke setup mode and delete all the old checks. This should give us a bunch of very gradual steps toward the brave new world of simpler setup. Test Plan: - Faked APC setup failures, saw warnings raise. - Verified that this runs after restart (get + set). - Verified that this costs us only one cache hit after first-run (get only). Reviewers: btrahan, codeblock, vrana, chad Reviewed By: codeblock CC: aran Maniphest Tasks: T2228 Differential Revision: https://secure.phabricator.com/D4295
This commit is contained in:
parent
ba489f9d85
commit
96839d35f4
10 changed files with 768 additions and 1 deletions
|
@ -686,6 +686,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php',
|
'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php',
|
||||||
'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php',
|
'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php',
|
||||||
'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php',
|
'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php',
|
||||||
|
'PhabricatorConfigIssueListController' => 'applications/config/controller/PhabricatorConfigIssueListController.php',
|
||||||
|
'PhabricatorConfigIssueViewController' => 'applications/config/controller/PhabricatorConfigIssueViewController.php',
|
||||||
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
|
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
|
||||||
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
|
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
|
||||||
'PhabricatorConfigManagementSetWorkflow' => 'infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php',
|
'PhabricatorConfigManagementSetWorkflow' => 'infrastructure/env/management/PhabricatorConfigManagementSetWorkflow.php',
|
||||||
|
@ -1135,6 +1137,10 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
|
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
|
||||||
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
|
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
|
||||||
'PhabricatorSetup' => 'infrastructure/PhabricatorSetup.php',
|
'PhabricatorSetup' => 'infrastructure/PhabricatorSetup.php',
|
||||||
|
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
|
||||||
|
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
|
||||||
|
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
|
||||||
|
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
|
||||||
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
|
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
|
||||||
'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php',
|
'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php',
|
||||||
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php',
|
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php',
|
||||||
|
@ -2002,6 +2008,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorConfigEntry' => 'PhabricatorConfigEntryDAO',
|
'PhabricatorConfigEntry' => 'PhabricatorConfigEntryDAO',
|
||||||
'PhabricatorConfigEntryDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorConfigEntryDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource',
|
'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource',
|
||||||
|
'PhabricatorConfigIssueListController' => 'PhabricatorConfigController',
|
||||||
|
'PhabricatorConfigIssueViewController' => 'PhabricatorConfigController',
|
||||||
'PhabricatorConfigListController' => 'PhabricatorConfigController',
|
'PhabricatorConfigListController' => 'PhabricatorConfigController',
|
||||||
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
|
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
|
||||||
'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow',
|
||||||
|
@ -2409,6 +2417,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSettingsPanelProfile' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelProfile' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
|
||||||
|
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
|
||||||
|
'PhabricatorSetupIssueView' => 'AphrontView',
|
||||||
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
|
||||||
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
|
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
|
||||||
'PhabricatorSlowvoteController' => 'PhabricatorController',
|
'PhabricatorSlowvoteController' => 'PhabricatorController',
|
||||||
|
|
|
@ -25,8 +25,12 @@ final class PhabricatorApplicationConfig extends PhabricatorApplication {
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
return array(
|
return array(
|
||||||
'/config/' => array(
|
'/config/' => array(
|
||||||
'' => 'PhabricatorConfigListController',
|
'' => 'PhabricatorConfigListController',
|
||||||
'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController',
|
'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController',
|
||||||
|
'issue/' => array(
|
||||||
|
'' => 'PhabricatorConfigIssueListController',
|
||||||
|
'(?P<key>[^/]+)/' => 'PhabricatorConfigIssueViewController',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
79
src/applications/config/check/PhabricatorSetupCheck.php
Normal file
79
src/applications/config/check/PhabricatorSetupCheck.php
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorSetupCheck {
|
||||||
|
|
||||||
|
private $issues;
|
||||||
|
|
||||||
|
abstract protected function executeChecks();
|
||||||
|
|
||||||
|
final protected function newIssue($key) {
|
||||||
|
$issue = id(new PhabricatorSetupIssue())
|
||||||
|
->setIssueKey($key);
|
||||||
|
|
||||||
|
$this->issues[$key] = $issue;
|
||||||
|
|
||||||
|
return $issue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getIssues() {
|
||||||
|
return $this->issues;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function runSetupChecks() {
|
||||||
|
$this->issues = array();
|
||||||
|
$this->executeChecks();
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function getOpenSetupIssueCount() {
|
||||||
|
$cache = PhabricatorCaches::getSetupCache();
|
||||||
|
return $cache->getKey('phabricator.setup.issues');
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function setOpenSetupIssueCount($count) {
|
||||||
|
$cache = PhabricatorCaches::getSetupCache();
|
||||||
|
$cache->setKey('phabricator.setup.issues', $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function willProcessRequest() {
|
||||||
|
$issue_count = self::getOpenSetupIssueCount();
|
||||||
|
if ($issue_count !== null) {
|
||||||
|
// We've already run setup checks, didn't hit any fatals, and then set
|
||||||
|
// an issue count. This means we're good and don't need to do any extra
|
||||||
|
// work.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$issues = self::runAllChecks();
|
||||||
|
|
||||||
|
self::setOpenSetupIssueCount(count($issues));
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public static function runAllChecks() {
|
||||||
|
$symbols = id(new PhutilSymbolLoader())
|
||||||
|
->setAncestorClass('PhabricatorSetupCheck')
|
||||||
|
->setConcreteOnly(true)
|
||||||
|
->selectAndLoadSymbols();
|
||||||
|
|
||||||
|
$checks = array();
|
||||||
|
foreach ($symbols as $symbol) {
|
||||||
|
$checks[] = newv($symbol['name'], array());
|
||||||
|
}
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
foreach ($checks as $check) {
|
||||||
|
$check->runSetupChecks();
|
||||||
|
foreach ($check->getIssues() as $key => $issue) {
|
||||||
|
if (isset($issues[$key])) {
|
||||||
|
throw new Exception(
|
||||||
|
"Two setup checks raised an issue with key '{$key}'!");
|
||||||
|
}
|
||||||
|
$issues[$key] = $issue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $issues;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/applications/config/check/PhabricatorSetupCheckAPC.php
Normal file
37
src/applications/config/check/PhabricatorSetupCheckAPC.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSetupCheckAPC extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
|
protected function executeChecks() {
|
||||||
|
if (!extension_loaded('apc')) {
|
||||||
|
$message = pht(
|
||||||
|
"Installing the PHP extension 'APC' (Alternative PHP Cache) will ".
|
||||||
|
"dramatically improve performance.");
|
||||||
|
|
||||||
|
$this
|
||||||
|
->newIssue('extension.apc')
|
||||||
|
->setShortName(pht('APC'))
|
||||||
|
->setName(pht("PHP Extension 'APC' Not Installed"))
|
||||||
|
->setMessage($message)
|
||||||
|
->addPHPExtension('apc');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ini_get('apc.enabled')) {
|
||||||
|
$summary = pht("Enabling APC will dramatically improve performance.");
|
||||||
|
$message = pht(
|
||||||
|
"The PHP extension 'APC' is installed, but not enabled in your PHP ".
|
||||||
|
"configuration. Enabling it will dramatically improve Phabricator ".
|
||||||
|
"performance. Edit the 'apc.enabled' setting to enable the extension.");
|
||||||
|
|
||||||
|
$this
|
||||||
|
->newIssue('extension.apc.enabled')
|
||||||
|
->setShortName(pht('APC Disabled'))
|
||||||
|
->setName(pht("PHP Extension 'APC' Not Enabled"))
|
||||||
|
->setSummary($summary)
|
||||||
|
->setMessage($message)
|
||||||
|
->addPHPConfig('apc.enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConfigIssueListController
|
||||||
|
extends PhabricatorConfigController {
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$nav = $this->buildSideNavView();
|
||||||
|
|
||||||
|
$issues = PhabricatorSetupCheck::runAllChecks();
|
||||||
|
PhabricatorSetupCheck::setOpenSetupIssueCount(count($issues));
|
||||||
|
|
||||||
|
$list = $this->buildIssueList($issues);
|
||||||
|
$list->setNoDataString(pht("There are no open setup issues."));
|
||||||
|
|
||||||
|
$header = id(new PhabricatorHeaderView())
|
||||||
|
->setHeader(pht('Open Phabricator Setup Issues'));
|
||||||
|
|
||||||
|
$nav->appendChild(
|
||||||
|
array(
|
||||||
|
$header,
|
||||||
|
$list,
|
||||||
|
));
|
||||||
|
|
||||||
|
$title = pht('Setup Issues');
|
||||||
|
|
||||||
|
$crumbs = $this
|
||||||
|
->buildApplicationCrumbs($nav)
|
||||||
|
->addCrumb(
|
||||||
|
id(new PhabricatorCrumbView())
|
||||||
|
->setName($title)
|
||||||
|
->setHref($this->getApplicationURI('issue/')));
|
||||||
|
|
||||||
|
$nav->setCrumbs($crumbs);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
$nav,
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
'device' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildIssueList(array $issues) {
|
||||||
|
assert_instances_of($issues, 'PhabricatorSetupIssue');
|
||||||
|
$list = new PhabricatorObjectItemListView();
|
||||||
|
|
||||||
|
foreach ($issues as $issue) {
|
||||||
|
$href = $this->getApplicationURI('/issue/'.$issue->getIssueKey().'/');
|
||||||
|
$item = id(new PhabricatorObjectItemView())
|
||||||
|
->setHeader($issue->getName())
|
||||||
|
->setHref($href)
|
||||||
|
->setBarColor('yellow')
|
||||||
|
->addIcon('warning', pht('Setup Warning'))
|
||||||
|
->addAttribute($issue->getSummary());
|
||||||
|
$list->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorConfigIssueViewController
|
||||||
|
extends PhabricatorConfigController {
|
||||||
|
|
||||||
|
private $issueKey;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->issueKey = $data['key'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$nav = $this->buildSideNavView();
|
||||||
|
|
||||||
|
$issues = PhabricatorSetupCheck::runAllChecks();
|
||||||
|
PhabricatorSetupCheck::setOpenSetupIssueCount(count($issues));
|
||||||
|
|
||||||
|
if (empty($issues[$this->issueKey])) {
|
||||||
|
$content = id(new AphrontErrorView())
|
||||||
|
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
||||||
|
->setTitle(pht('Issue Resolved'))
|
||||||
|
->appendChild(pht('This setup issue has been resolved. '))
|
||||||
|
->appendChild(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $this->getApplicationURI('issue/'),
|
||||||
|
),
|
||||||
|
pht('Return to Open Issue List')));
|
||||||
|
$title = pht('Resolved Issue');
|
||||||
|
} else {
|
||||||
|
$issue = $issues[$this->issueKey];
|
||||||
|
$content = $this->renderIssue($issue);
|
||||||
|
$title = $issue->getShortName();
|
||||||
|
}
|
||||||
|
|
||||||
|
$nav->appendChild($content);
|
||||||
|
|
||||||
|
$crumbs = $this
|
||||||
|
->buildApplicationCrumbs($nav)
|
||||||
|
->addCrumb(
|
||||||
|
id(new PhabricatorCrumbView())
|
||||||
|
->setName(pht('Setup Issues'))
|
||||||
|
->setHref($this->getApplicationURI('issue/')))
|
||||||
|
->addCrumb(
|
||||||
|
id(new PhabricatorCrumbView())
|
||||||
|
->setName($title)
|
||||||
|
->setHref($request->getRequestURI()));
|
||||||
|
|
||||||
|
$nav->setCrumbs($crumbs);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
$nav,
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
'device' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderIssue(PhabricatorSetupIssue $issue) {
|
||||||
|
require_celerity_resource('setup-issue-css');
|
||||||
|
|
||||||
|
$view = new PhabricatorSetupIssueView();
|
||||||
|
$view->setIssue($issue);
|
||||||
|
$view;
|
||||||
|
|
||||||
|
$container = phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-background',
|
||||||
|
),
|
||||||
|
$view->render());
|
||||||
|
|
||||||
|
return $container;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
113
src/applications/config/issue/PhabricatorSetupIssue.php
Normal file
113
src/applications/config/issue/PhabricatorSetupIssue.php
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSetupIssue {
|
||||||
|
|
||||||
|
private $issueKey;
|
||||||
|
private $name;
|
||||||
|
private $message;
|
||||||
|
private $isFatal;
|
||||||
|
private $summary;
|
||||||
|
private $shortName;
|
||||||
|
|
||||||
|
private $phpExtensions = array();
|
||||||
|
private $phabricatorConfig = array();
|
||||||
|
private $phpConfig = array();
|
||||||
|
private $commands = array();
|
||||||
|
|
||||||
|
public function addCommand($command) {
|
||||||
|
$this->commands[] = $command;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommands() {
|
||||||
|
return $this->commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setShortName($short_name) {
|
||||||
|
$this->shortName = $short_name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShortName() {
|
||||||
|
if ($this->shortName === null) {
|
||||||
|
return $this->getName();
|
||||||
|
}
|
||||||
|
return $this->shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name) {
|
||||||
|
$this->name = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() {
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSummary($summary) {
|
||||||
|
$this->summary = $summary;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSummary() {
|
||||||
|
if ($this->summary === null) {
|
||||||
|
return $this->getMessage();
|
||||||
|
}
|
||||||
|
return $this->summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIssueKey($issue_key) {
|
||||||
|
$this->issueKey = $issue_key;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIssueKey() {
|
||||||
|
return $this->issueKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIsFatal($is_fatal) {
|
||||||
|
$this->isFatal = $is_fatal;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIsFatal() {
|
||||||
|
return $this->isFatal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPHPConfig($php_config) {
|
||||||
|
$this->phpConfig[] = $php_config;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPHPConfig() {
|
||||||
|
return $this->phpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPhabricatorConfig($phabricator_config) {
|
||||||
|
$this->phabricatorConfig[] = $phabricator_config;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPhabricatorConfig() {
|
||||||
|
return $this->phabricatorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addPHPExtension($php_extension) {
|
||||||
|
$this->phpExtensions[] = $php_extension;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPHPExtensions() {
|
||||||
|
return $this->phpExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMessage($message) {
|
||||||
|
$this->message = $message;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessage() {
|
||||||
|
return $this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
290
src/applications/config/view/PhabricatorSetupIssueView.php
Normal file
290
src/applications/config/view/PhabricatorSetupIssueView.php
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
|
|
||||||
|
private $issue;
|
||||||
|
|
||||||
|
public function setIssue(PhabricatorSetupIssue $issue) {
|
||||||
|
$this->issue = $issue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIssue() {
|
||||||
|
return $this->issue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
$issue = $this->getIssue();
|
||||||
|
|
||||||
|
$description = phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-instructions',
|
||||||
|
),
|
||||||
|
nl2br(phutil_escape_html($issue->getMessage())));
|
||||||
|
|
||||||
|
$configs = $issue->getPhabricatorConfig();
|
||||||
|
if ($configs) {
|
||||||
|
$description .= $this->renderPhabricatorConfig($configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
$configs = $issue->getPHPConfig();
|
||||||
|
if ($configs) {
|
||||||
|
$description .= $this->renderPHPConfig($configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
$commands = $issue->getCommands();
|
||||||
|
if ($commands) {
|
||||||
|
$run_these = pht("Run these %d command(s):", count($commands));
|
||||||
|
$description .= phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-config',
|
||||||
|
),
|
||||||
|
phutil_render_tag('p', array(), $run_these).
|
||||||
|
phutil_render_tag('pre', array(), implode("\n", $commands)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$extensions = $issue->getPHPExtensions();
|
||||||
|
if ($extensions) {
|
||||||
|
$install_these = pht(
|
||||||
|
"Install these %d PHP extension(s):", count($extensions));
|
||||||
|
|
||||||
|
$install_info = pht(
|
||||||
|
"You can usually install a PHP extension using <tt>apt-get</tt> or ".
|
||||||
|
"<tt>yum</tt>. Common package names are ".
|
||||||
|
"<tt>php-<em>extname</em></tt> or <tt>php5-<em>extname</em></tt>. ".
|
||||||
|
"Try commands like these:");
|
||||||
|
|
||||||
|
// TODO: We should do a better job of detecting how to install extensions
|
||||||
|
// on the current system.
|
||||||
|
$install_commands = array(
|
||||||
|
"$ sudo apt-get install php5-<em>extname</em> # Debian / Ubuntu",
|
||||||
|
"$ sudo yum install php5-<em>extname</em> # Red Hat / Derivatives",
|
||||||
|
);
|
||||||
|
$install_commands = implode("\n", $install_commands);
|
||||||
|
|
||||||
|
$fallback_info = pht(
|
||||||
|
"If those commands don't work, try Google. The process of installing ".
|
||||||
|
"PHP extensions is not specific to Phabricator, and any instructions ".
|
||||||
|
"you can find for installing them on your system should work. On Mac ".
|
||||||
|
"OS X, you might want to try Homebrew.");
|
||||||
|
|
||||||
|
$restart_info = pht(
|
||||||
|
"After installing new PHP extensions, <strong>restart your webserver ".
|
||||||
|
"for the changes to take effect</strong>.");
|
||||||
|
|
||||||
|
$description .= phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-config',
|
||||||
|
),
|
||||||
|
phutil_render_tag('p', array(), $install_these).
|
||||||
|
phutil_render_tag('pre', array(), implode("\n", $extensions)).
|
||||||
|
phutil_render_tag('p', array(), $install_info).
|
||||||
|
phutil_render_tag('pre', array(), $install_commands).
|
||||||
|
phutil_render_tag('p', array(), $fallback_info).
|
||||||
|
phutil_render_tag('p', array(), $restart_info));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$next = phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-next',
|
||||||
|
),
|
||||||
|
pht('To continue, resolve this problem and reload the page.'));
|
||||||
|
|
||||||
|
$name = phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-name',
|
||||||
|
),
|
||||||
|
phutil_escape_html($issue->getName()));
|
||||||
|
|
||||||
|
return phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue',
|
||||||
|
),
|
||||||
|
$name.$description.$next);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderPhabricatorConfig(array $configs) {
|
||||||
|
$table_info = phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"The current Phabricator configuration has these %d value(s):",
|
||||||
|
count($configs)));
|
||||||
|
|
||||||
|
$table = array();
|
||||||
|
foreach ($configs as $key) {
|
||||||
|
$table[] = '<tr>';
|
||||||
|
$table[] = '<th>'.phutil_escape_html($key).'</th>';
|
||||||
|
|
||||||
|
$value = PhabricatorEnv::getEnvConfig($key);
|
||||||
|
if ($value === null) {
|
||||||
|
$value = '<em>null</em>';
|
||||||
|
} else if ($value === false) {
|
||||||
|
$value = '<em>false</em>';
|
||||||
|
} else if ($value === true) {
|
||||||
|
$value = '<em>true</em>';
|
||||||
|
} else {
|
||||||
|
$value = phutil_escape_html($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table[] = '<td>'.$value.'</td>';
|
||||||
|
$table[] = '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = phutil_render_tag(
|
||||||
|
'table',
|
||||||
|
array(
|
||||||
|
|
||||||
|
),
|
||||||
|
implode("\n", $table));
|
||||||
|
|
||||||
|
$update_info = phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"To update these %d value(s), run these command(s) from the command ".
|
||||||
|
"line:",
|
||||||
|
count($configs)));
|
||||||
|
|
||||||
|
$update = array();
|
||||||
|
foreach ($configs as $key) {
|
||||||
|
$cmd = '<tt>phabricator/ $</tt> ./bin/config set '.
|
||||||
|
phutil_escape_html($key).' '.
|
||||||
|
'<em>value</em>';
|
||||||
|
$update[] = $cmd;
|
||||||
|
}
|
||||||
|
$update = phutil_render_tag('pre', array(), implode("\n", $update));
|
||||||
|
|
||||||
|
return phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-config',
|
||||||
|
),
|
||||||
|
self::renderSingleView(
|
||||||
|
array(
|
||||||
|
$table_info,
|
||||||
|
$table,
|
||||||
|
$update_info,
|
||||||
|
$update,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderPHPConfig(array $configs) {
|
||||||
|
$table_info = phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"The current PHP configuration has these %d value(s):",
|
||||||
|
count($configs)));
|
||||||
|
|
||||||
|
$table = array();
|
||||||
|
foreach ($configs as $key) {
|
||||||
|
$table[] = '<tr>';
|
||||||
|
$table[] = '<th>'.phutil_escape_html($key).'</th>';
|
||||||
|
|
||||||
|
$value = ini_get($key);
|
||||||
|
if ($value === null) {
|
||||||
|
$value = '<em>null</em>';
|
||||||
|
} else if ($value === false) {
|
||||||
|
$value = '<em>false</em>';
|
||||||
|
} else if ($value === true) {
|
||||||
|
$value = '<em>true</em>';
|
||||||
|
} else if ($value === '') {
|
||||||
|
$value = '<em>(empty string)</em>';
|
||||||
|
} else {
|
||||||
|
$value = phutil_escape_html($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table[] = '<td>'.$value.'</td>';
|
||||||
|
$table[] = '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = phutil_render_tag(
|
||||||
|
'table',
|
||||||
|
array(
|
||||||
|
|
||||||
|
),
|
||||||
|
implode("\n", $table));
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
phpinfo();
|
||||||
|
$phpinfo = ob_get_clean();
|
||||||
|
|
||||||
|
|
||||||
|
$rex = '@Loaded Configuration File\s*</td><td class="v">(.*?)</td>@i';
|
||||||
|
$matches = null;
|
||||||
|
|
||||||
|
$ini_loc = null;
|
||||||
|
if (preg_match($rex, $phpinfo, $matches)) {
|
||||||
|
$ini_loc = trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rex = '@Additional \.ini files parsed\s*</td><td class="v">(.*?)</td>@i';
|
||||||
|
|
||||||
|
$more_loc = array();
|
||||||
|
if (preg_match($rex, $phpinfo, $matches)) {
|
||||||
|
$more_loc = trim($matches[1]);
|
||||||
|
if ($more_loc == '(none)') {
|
||||||
|
$more_loc = array();
|
||||||
|
} else {
|
||||||
|
$more_loc = preg_split('/\s*,\s*/', $more_loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ini_loc) {
|
||||||
|
$info = phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"To update these %d value(s), edit your PHP configuration file.",
|
||||||
|
count($configs)));
|
||||||
|
} else {
|
||||||
|
$info = phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"To update these %d value(s), edit your PHP configuration file, ".
|
||||||
|
"located here:",
|
||||||
|
count($configs)));
|
||||||
|
$info .= phutil_render_tag(
|
||||||
|
'pre',
|
||||||
|
array(),
|
||||||
|
phutil_escape_html($ini_loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($more_loc) {
|
||||||
|
$info .= phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"PHP also loaded these configuration file(s):",
|
||||||
|
count($more_loc)));
|
||||||
|
$info .= phutil_render_tag(
|
||||||
|
'pre',
|
||||||
|
array(),
|
||||||
|
phutil_escape_html(implode("\n", $more_loc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$info .= phutil_render_tag(
|
||||||
|
'p',
|
||||||
|
array(),
|
||||||
|
pht(
|
||||||
|
"After editing the PHP configuration, <strong>restart your webserver ".
|
||||||
|
"for the changes to take effect</strong>."));
|
||||||
|
|
||||||
|
return phutil_render_tag(
|
||||||
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => 'setup-issue-config',
|
||||||
|
),
|
||||||
|
$table_info.$table.$info);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -38,6 +38,8 @@ try {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhabricatorSetupCheck::willProcessRequest();
|
||||||
|
|
||||||
phabricator_detect_bad_base_uri();
|
phabricator_detect_bad_base_uri();
|
||||||
|
|
||||||
$host = $_SERVER['HTTP_HOST'];
|
$host = $_SERVER['HTTP_HOST'];
|
||||||
|
|
86
webroot/rsrc/css/application/config/setup-issue.css
Normal file
86
webroot/rsrc/css/application/config/setup-issue.css
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* @provides setup-issue-css
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.setup-issue-background {
|
||||||
|
background-color: #edecef;
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue {
|
||||||
|
border: 1px solid #35393d;
|
||||||
|
margin: 15px auto;
|
||||||
|
max-width: 760px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue p {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue table {
|
||||||
|
width: 90%;
|
||||||
|
margin: auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 1px solid #dfdfdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue table th {
|
||||||
|
text-align: right;
|
||||||
|
width: 30%;
|
||||||
|
background: #efefef;
|
||||||
|
border: 1px solid #dfdfdf;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue table td {
|
||||||
|
border: 1px solid #dfdfdf;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue pre {
|
||||||
|
width: 84%;
|
||||||
|
margin: auto;
|
||||||
|
border: 1px solid #dfdfdf;
|
||||||
|
padding: 10px 3%;
|
||||||
|
background: #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue tt {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue em {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue-instructions {
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 20px;
|
||||||
|
line-height: 1.4em;
|
||||||
|
background: #efefef;
|
||||||
|
border-bottom: 1px solid #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue-name {
|
||||||
|
padding: 15px;
|
||||||
|
background: #35393d;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue-next {
|
||||||
|
padding: 15px;
|
||||||
|
background: #35393d;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-issue-config {
|
||||||
|
margin: 15px 0;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
Loading…
Reference in a new issue