Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/config/check/PhabricatorSetupCheck.php b/src/applications/config/check/PhabricatorSetupCheck.php
index 4c6c0b581c..a657c52799 100644
--- a/src/applications/config/check/PhabricatorSetupCheck.php
+++ b/src/applications/config/check/PhabricatorSetupCheck.php
@@ -1,169 +1,209 @@
<?php
abstract class PhabricatorSetupCheck extends Phobject {
private $issues;
abstract protected function executeChecks();
const GROUP_OTHER = 'other';
const GROUP_MYSQL = 'mysql';
const GROUP_PHP = 'php';
const GROUP_IMPORTANT = 'important';
public function getExecutionOrder() {
return 1;
}
final protected function newIssue($key) {
$issue = id(new PhabricatorSetupIssue())
->setIssueKey($key);
$this->issues[$key] = $issue;
if ($this->getDefaultGroup()) {
$issue->setGroup($this->getDefaultGroup());
}
return $issue;
}
final public function getIssues() {
return $this->issues;
}
protected function addIssue(PhabricatorSetupIssue $issue) {
$this->issues[$issue->getIssueKey()] = $issue;
return $this;
}
public function getDefaultGroup() {
return null;
}
final public function runSetupChecks() {
$this->issues = array();
$this->executeChecks();
}
final public static function getOpenSetupIssueKeys() {
$cache = PhabricatorCaches::getSetupCache();
return $cache->getKey('phabricator.setup.issue-keys');
}
- final public static function setOpenSetupIssueKeys(array $keys) {
+ final public static function setOpenSetupIssueKeys(
+ array $keys,
+ $update_database) {
$cache = PhabricatorCaches::getSetupCache();
$cache->setKey('phabricator.setup.issue-keys', $keys);
+
+ if ($update_database) {
+ $db_cache = new PhabricatorKeyValueDatabaseCache();
+ try {
+ $json = phutil_json_encode($keys);
+ $db_cache->setKey('phabricator.setup.issue-keys', $json);
+ } catch (Exception $ex) {
+ // Ignore any write failures, since they likely just indicate that we
+ // have a database-related setup issue that needs to be resolved.
+ }
+ }
+ }
+
+ final public static function getOpenSetupIssueKeysFromDatabase() {
+ $db_cache = new PhabricatorKeyValueDatabaseCache();
+ try {
+ $value = $db_cache->getKey('phabricator.setup.issue-keys');
+ if (!strlen($value)) {
+ return null;
+ }
+ return phutil_json_decode($value);
+ } catch (Exception $ex) {
+ return null;
+ }
}
final public static function getUnignoredIssueKeys(array $all_issues) {
assert_instances_of($all_issues, 'PhabricatorSetupIssue');
$keys = array();
foreach ($all_issues as $issue) {
if (!$issue->getIsIgnored()) {
$keys[] = $issue->getIssueKey();
}
}
return $keys;
}
final public static function getConfigNeedsRepair() {
$cache = PhabricatorCaches::getSetupCache();
return $cache->getKey('phabricator.setup.needs-repair');
}
final public static function setConfigNeedsRepair($needs_repair) {
$cache = PhabricatorCaches::getSetupCache();
$cache->setKey('phabricator.setup.needs-repair', $needs_repair);
}
final public static function deleteSetupCheckCache() {
$cache = PhabricatorCaches::getSetupCache();
$cache->deleteKeys(
array(
'phabricator.setup.needs-repair',
'phabricator.setup.issue-keys',
));
}
final public static function willProcessRequest() {
$issue_keys = self::getOpenSetupIssueKeys();
if ($issue_keys === null) {
$issues = self::runAllChecks();
foreach ($issues as $issue) {
if ($issue->getIsFatal()) {
$view = id(new PhabricatorSetupIssueView())
->setIssue($issue);
return id(new PhabricatorConfigResponse())
->setView($view);
}
}
- self::setOpenSetupIssueKeys(self::getUnignoredIssueKeys($issues));
+ $issue_keys = self::getUnignoredIssueKeys($issues);
+ self::setOpenSetupIssueKeys($issue_keys, $update_database = true);
+ } else if ($issue_keys) {
+ // If Phabricator is configured in a cluster with multiple web devices,
+ // we can end up with setup issues cached on every device. This can cause
+ // a warning banner to show on every device so that each one needs to
+ // be dismissed individually, which is pretty annoying. See T10876.
+
+ // To avoid this, check if the issues we found have already been cleared
+ // in the database. If they have, we'll just wipe out our own cache and
+ // move on.
+ $issue_keys = self::getOpenSetupIssueKeysFromDatabase();
+ if ($issue_keys !== null) {
+ self::setOpenSetupIssueKeys($issue_keys, $update_database = false);
+ }
}
// Try to repair configuration unless we have a clean bill of health on it.
// We need to keep doing this on every page load until all the problems
// are fixed, which is why it's separate from setup checks (which run
// once per restart).
$needs_repair = self::getConfigNeedsRepair();
if ($needs_repair !== false) {
$needs_repair = self::repairConfig();
self::setConfigNeedsRepair($needs_repair);
}
}
final public static function loadAllChecks() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setSortMethod('getExecutionOrder')
->execute();
}
final public static function runAllChecks() {
$checks = self::loadAllChecks();
$issues = array();
foreach ($checks as $check) {
$check->runSetupChecks();
foreach ($check->getIssues() as $key => $issue) {
if (isset($issues[$key])) {
throw new Exception(
pht(
"Two setup checks raised an issue with key '%s'!",
$key));
}
$issues[$key] = $issue;
if ($issue->getIsFatal()) {
break 2;
}
}
}
$ignore_issues = PhabricatorEnv::getEnvConfig('config.ignore-issues');
foreach ($ignore_issues as $ignorable => $derp) {
if (isset($issues[$ignorable])) {
$issues[$ignorable]->setIsIgnored(true);
}
}
return $issues;
}
final public static function repairConfig() {
$needs_repair = false;
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
foreach ($options as $option) {
try {
$option->getGroup()->validateOption(
$option,
PhabricatorEnv::getEnvConfig($option->getKey()));
} catch (PhabricatorConfigValidationException $ex) {
PhabricatorEnv::repairConfig($option->getKey(), $option->getDefault());
$needs_repair = true;
}
}
return $needs_repair;
}
}
diff --git a/src/applications/config/controller/PhabricatorConfigIssueListController.php b/src/applications/config/controller/PhabricatorConfigIssueListController.php
index 02bec4e082..c3dc7f577c 100644
--- a/src/applications/config/controller/PhabricatorConfigIssueListController.php
+++ b/src/applications/config/controller/PhabricatorConfigIssueListController.php
@@ -1,114 +1,115 @@
<?php
final class PhabricatorConfigIssueListController
extends PhabricatorConfigController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$nav = $this->buildSideNavView();
$nav->selectFilter('issue/');
$issues = PhabricatorSetupCheck::runAllChecks();
PhabricatorSetupCheck::setOpenSetupIssueKeys(
- PhabricatorSetupCheck::getUnignoredIssueKeys($issues));
+ PhabricatorSetupCheck::getUnignoredIssueKeys($issues),
+ $update_database = true);
$important = $this->buildIssueList(
$issues, PhabricatorSetupCheck::GROUP_IMPORTANT);
$php = $this->buildIssueList(
$issues, PhabricatorSetupCheck::GROUP_PHP);
$mysql = $this->buildIssueList(
$issues, PhabricatorSetupCheck::GROUP_MYSQL);
$other = $this->buildIssueList(
$issues, PhabricatorSetupCheck::GROUP_OTHER);
$setup_issues = array();
if ($important) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('Important Setup Issues'))
->setColor(PHUIObjectBoxView::COLOR_RED)
->setObjectList($important);
}
if ($php) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('PHP Setup Issues'))
->setObjectList($php);
}
if ($mysql) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('MySQL Setup Issues'))
->setObjectList($mysql);
}
if ($other) {
$setup_issues[] = id(new PHUIObjectBoxView())
->setHeaderText(pht('Other Setup Issues'))
->setObjectList($other);
}
if (empty($setup_issues)) {
$setup_issues[] = id(new PHUIInfoView())
->setTitle(pht('No Issues'))
->appendChild(
pht('Your install has no current setup issues to resolve.'))
->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
}
$title = pht('Setup Issues');
$crumbs = $this
->buildApplicationCrumbs($nav)
->addTextCrumb(pht('Setup'), $this->getApplicationURI('issue/'));
$view = id(new PHUITwoColumnView())
->setNavigation($nav)
->setMainColumn(array(
$setup_issues,
));
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
private function buildIssueList(array $issues, $group) {
assert_instances_of($issues, 'PhabricatorSetupIssue');
$list = new PHUIObjectItemListView();
$ignored_items = array();
$items = 0;
foreach ($issues as $issue) {
if ($issue->getGroup() == $group) {
$items++;
$href = $this->getApplicationURI('/issue/'.$issue->getIssueKey().'/');
$item = id(new PHUIObjectItemView())
->setHeader($issue->getName())
->setHref($href)
->addAttribute($issue->getSummary());
if (!$issue->getIsIgnored()) {
$item->setStatusIcon('fa-warning yellow');
$list->addItem($item);
} else {
$item->addIcon('fa-eye-slash', pht('Ignored'));
$item->setDisabled(true);
$item->setStatusIcon('fa-warning grey');
$ignored_items[] = $item;
}
}
}
foreach ($ignored_items as $item) {
$list->addItem($item);
}
if ($items == 0) {
return null;
} else {
return $list;
}
}
}
diff --git a/src/applications/config/controller/PhabricatorConfigIssueViewController.php b/src/applications/config/controller/PhabricatorConfigIssueViewController.php
index b1d1c299a5..36fb77ce74 100644
--- a/src/applications/config/controller/PhabricatorConfigIssueViewController.php
+++ b/src/applications/config/controller/PhabricatorConfigIssueViewController.php
@@ -1,61 +1,62 @@
<?php
final class PhabricatorConfigIssueViewController
extends PhabricatorConfigController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$issue_key = $request->getURIData('key');
$issues = PhabricatorSetupCheck::runAllChecks();
PhabricatorSetupCheck::setOpenSetupIssueKeys(
- PhabricatorSetupCheck::getUnignoredIssueKeys($issues));
+ PhabricatorSetupCheck::getUnignoredIssueKeys($issues),
+ $update_database = true);
if (empty($issues[$issue_key])) {
$content = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->setTitle(pht('Issue Resolved'))
->appendChild(pht('This setup issue has been resolved. '))
->appendChild(
phutil_tag(
'a',
array(
'href' => $this->getApplicationURI('issue/'),
),
pht('Return to Open Issue List')));
$title = pht('Resolved Issue');
} else {
$issue = $issues[$issue_key];
$content = $this->renderIssue($issue);
$title = $issue->getShortName();
}
$crumbs = $this
->buildApplicationCrumbs()
->setBorder(true)
->addTextCrumb(pht('Setup Issues'), $this->getApplicationURI('issue/'))
->addTextCrumb($title, $request->getRequestURI());
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($content);
}
private function renderIssue(PhabricatorSetupIssue $issue) {
require_celerity_resource('setup-issue-css');
$view = new PhabricatorSetupIssueView();
$view->setIssue($issue);
$container = phutil_tag(
'div',
array(
'class' => 'setup-issue-background',
),
$view->render());
return $container;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Mar 17, 1:12 AM (15 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
964001
Default Alt Text
(12 KB)

Event Timeline