Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/config/check/PhabricatorSetupCheck.php b/src/applications/config/check/PhabricatorSetupCheck.php
index 0d9101efe3..e0574b7636 100644
--- a/src/applications/config/check/PhabricatorSetupCheck.php
+++ b/src/applications/config/check/PhabricatorSetupCheck.php
@@ -1,305 +1,301 @@
<?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() {
if ($this->isPreflightCheck()) {
return 0;
} else {
return 1000;
}
}
/**
* Should this check execute before we load configuration?
*
* The majority of checks (particularly, those checks which examine
* configuration) should run in the normal setup phase, after configuration
* loads. However, a small set of critical checks (mostly, tests for PHP
* setup and extensions) need to run before we can load configuration.
*
* @return bool True to execute before configuration is loaded.
*/
public function isPreflightCheck() {
return false;
}
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 resetSetupState() {
$cache = PhabricatorCaches::getSetupCache();
$cache->deleteKey('phabricator.setup.issue-keys');
$server_cache = PhabricatorCaches::getServerStateCache();
$server_cache->deleteKey('phabricator.in-flight');
$use_scope = AphrontWriteGuard::isGuardActive();
if ($use_scope) {
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
} else {
AphrontWriteGuard::allowDangerousUnguardedWrites(true);
}
- $caught = null;
try {
$db_cache = new PhabricatorKeyValueDatabaseCache();
$db_cache->deleteKey('phabricator.setup.issue-keys');
} catch (Exception $ex) {
- $caught = $ex;
+ // If we hit an exception here, just ignore it. In particular, this can
+ // happen on initial startup before the databases are initialized.
}
if ($use_scope) {
unset($unguarded);
} else {
AphrontWriteGuard::allowDangerousUnguardedWrites(false);
}
-
- if ($caught) {
- throw $caught;
- }
}
final public static function setOpenSetupIssueKeys(
array $keys,
$update_database) {
$cache = PhabricatorCaches::getSetupCache();
$cache->setKey('phabricator.setup.issue-keys', $keys);
$server_cache = PhabricatorCaches::getServerStateCache();
$server_cache->setKey('phabricator.in-flight', 1);
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 willPreflightRequest() {
$checks = self::loadAllChecks();
foreach ($checks as $check) {
if (!$check->isPreflightCheck()) {
continue;
}
$check->runSetupChecks();
foreach ($check->getIssues() as $key => $issue) {
return self::newIssueResponse($issue);
}
}
return null;
}
public static function newIssueResponse(PhabricatorSetupIssue $issue) {
$view = id(new PhabricatorSetupIssueView())
->setIssue($issue);
return id(new PhabricatorConfigResponse())
->setView($view);
}
final public static function willProcessRequest() {
$issue_keys = self::getOpenSetupIssueKeys();
if ($issue_keys === null) {
$engine = new PhabricatorSetupEngine();
$response = $engine->execute();
if ($response) {
return $response;
}
} 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);
}
}
/**
* Test if we've survived through setup on at least one normal request
* without fataling.
*
* If we've made it through setup without hitting any fatals, we switch
* to render a more friendly error page when encountering issues like
* database connection failures. This gives users a smoother experience in
* the face of intermittent failures.
*
* @return bool True if we've made it through setup since the last restart.
*/
final public static function isInFlight() {
$cache = PhabricatorCaches::getServerStateCache();
return (bool)$cache->getKey('phabricator.in-flight');
}
final public static function loadAllChecks() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setSortMethod('getExecutionOrder')
->execute();
}
final public static function runNormalChecks() {
$checks = self::loadAllChecks();
foreach ($checks as $key => $check) {
if ($check->isPreflightCheck()) {
unset($checks[$key]);
}
}
$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/settings/editor/PhabricatorUserPreferencesEditor.php b/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
index c2ec0a7094..a927cc7475 100644
--- a/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
+++ b/src/applications/settings/editor/PhabricatorUserPreferencesEditor.php
@@ -1,184 +1,184 @@
<?php
final class PhabricatorUserPreferencesEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorSettingsApplication';
}
public function getEditorObjectsDescription() {
return pht('Settings');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorUserPreferencesTransaction::TYPE_SETTING;
return $types;
}
protected function expandTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
$settings = $this->getSettings();
$setting = idx($settings, $setting_key);
if ($setting) {
return $setting->expandSettingTransaction($object, $xaction);
}
return parent::expandTransaction($object, $xaction);
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
return $object->getPreference($setting_key);
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$actor = $this->getActor();
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
$settings = PhabricatorSetting::getAllEnabledSettings($actor);
$setting = $settings[$setting_key];
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
$value = $xaction->getNewValue();
$value = $setting->getTransactionNewValue($value);
return $value;
}
return parent::getCustomTransactionNewValue($object, $xaction);
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
$new_value = $xaction->getNewValue();
if ($new_value === null) {
$object->unsetPreference($setting_key);
} else {
$object->setPreference($setting_key, $new_value);
}
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
return;
}
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
$settings = $this->getSettings();
switch ($type) {
case PhabricatorUserPreferencesTransaction::TYPE_SETTING:
foreach ($xactions as $xaction) {
$setting_key = $xaction->getMetadataValue(
PhabricatorUserPreferencesTransaction::PROPERTY_SETTING);
$setting = idx($settings, $setting_key);
if (!$setting) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
'There is no known application setting with key "%s".',
$setting_key),
$xaction);
continue;
}
try {
$setting->validateTransactionValue($xaction->getNewValue());
} catch (Exception $ex) {
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
$ex->getMessage(),
$xaction);
}
}
break;
}
return $errors;
}
protected function applyFinalEffects(
PhabricatorLiskDAO $object,
array $xactions) {
$user_phid = $object->getUserPHID();
if ($user_phid) {
PhabricatorUserCache::clearCache(
PhabricatorUserPreferencesCacheType::KEY_PREFERENCES,
$user_phid);
} else {
$cache = PhabricatorCaches::getMutableStructureCache();
- $cache->deleteKey(PhabricatorUserPreferences::getGlobalCacheKey());
+ $cache->deleteKey(PhabricatorUser::getGlobalSettingsCacheKey());
PhabricatorUserCache::clearCacheForAllUsers(
PhabricatorUserPreferencesCacheType::KEY_PREFERENCES);
}
return $xactions;
}
private function getSettings() {
$actor = $this->getActor();
$settings = PhabricatorSetting::getAllEnabledSettings($actor);
foreach ($settings as $key => $setting) {
$setting = clone $setting;
$setting->setViewer($actor);
$settings[$key] = $setting;
}
return $settings;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jul 24, 1:50 AM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
182479
Default Alt Text
(15 KB)

Event Timeline