Config: Clean up error handling, throw exceptions instead of returning false (#2314)

This also has the happy side effect of removing a cyclic dependency between Config and Server. There's only the dependency on MainLogger left to get rid of now.
This commit is contained in:
Dylan K. Taylor 2018-07-21 15:50:58 +01:00 committed by GitHub
parent c5bf746e4c
commit 01a9e53394
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -23,9 +23,6 @@ declare(strict_types=1);
namespace pocketmine\utils; namespace pocketmine\utils;
use pocketmine\Server;
/** /**
* Config Class for simple config manipulation of multiple formats. * Config Class for simple config manipulation of multiple formats.
*/ */
@ -76,14 +73,12 @@ class Config{
]; ];
/** /**
* @param string $file Path of the file to be loaded * @param string $file Path of the file to be loaded
* @param int $type Config type to load, -1 by default (detect) * @param int $type Config type to load, -1 by default (detect)
* @param array $default Array with the default values that will be written to the file if it did not exist * @param array $default Array with the default values that will be written to the file if it did not exist
* @param null &$correct Sets correct to true if everything has been loaded correctly
*/ */
public function __construct(string $file, int $type = Config::DETECT, array $default = [], &$correct = null){ public function __construct(string $file, int $type = Config::DETECT, array $default = []){
$this->load($file, $type, $default); $this->load($file, $type, $default);
$correct = $this->correct;
} }
/** /**
@ -92,7 +87,6 @@ class Config{
public function reload(){ public function reload(){
$this->config = []; $this->config = [];
$this->nestedCache = []; $this->nestedCache = [];
$this->correct = false;
$this->load($this->file, $this->type); $this->load($this->file, $this->type);
} }
@ -114,14 +108,14 @@ class Config{
} }
/** /**
* @param $file * @param string $file
* @param int $type * @param int $type
* @param array $default * @param array $default
* *
* @return bool * @throws \InvalidArgumentException if config type could not be auto-detected
* @throws \InvalidStateException if config type is invalid
*/ */
public function load(string $file, int $type = Config::DETECT, array $default = []) : bool{ public function load(string $file, int $type = Config::DETECT, array $default = []) : void{
$this->correct = true;
$this->file = $file; $this->file = $file;
$this->type = $type; $this->type = $type;
@ -131,7 +125,7 @@ class Config{
if(isset(Config::$formats[$extension])){ if(isset(Config::$formats[$extension])){
$this->type = Config::$formats[$extension]; $this->type = Config::$formats[$extension];
}else{ }else{
$this->correct = false; throw new \InvalidArgumentException("Cannot detect config type of " . $this->file);
} }
} }
@ -139,93 +133,66 @@ class Config{
$this->config = $default; $this->config = $default;
$this->save(); $this->save();
}else{ }else{
if($this->correct){ $content = file_get_contents($this->file);
$content = file_get_contents($this->file); switch($this->type){
switch($this->type){ case Config::PROPERTIES:
case Config::PROPERTIES: $this->parseProperties($content);
$this->parseProperties($content); break;
break; case Config::JSON:
case Config::JSON: $this->config = json_decode($content, true);
$this->config = json_decode($content, true); break;
break; case Config::YAML:
case Config::YAML: $content = self::fixYAMLIndexes($content);
$content = self::fixYAMLIndexes($content); $this->config = yaml_parse($content);
$this->config = yaml_parse($content); break;
break; case Config::SERIALIZED:
case Config::SERIALIZED: $this->config = unserialize($content);
$this->config = unserialize($content); break;
break; case Config::ENUM:
case Config::ENUM: $this->parseList($content);
$this->parseList($content); break;
break; default:
default: throw new \InvalidStateException("Config type is unknown");
$this->correct = false; }
if(!is_array($this->config)){
return false; $this->config = $default;
} }
if(!is_array($this->config)){ if($this->fillDefaults($default, $this->config) > 0){
$this->config = $default; $this->save();
}
if($this->fillDefaults($default, $this->config) > 0){
$this->save();
}
}else{
return false;
} }
} }
return true;
} }
/** /**
* @return bool * Flushes the config to disk in the appropriate format.
*
* @throws \InvalidStateException if config type is not valid
*/ */
public function check() : bool{ public function save() : void{
return $this->correct; $content = null;
} switch($this->type){
case Config::PROPERTIES:
/** $content = $this->writeProperties();
* @return bool break;
*/ case Config::JSON:
public function save() : bool{ $content = json_encode($this->config, $this->jsonOptions);
if($this->correct){ break;
try{ case Config::YAML:
$content = null; $content = yaml_emit($this->config, YAML_UTF8_ENCODING);
switch($this->type){ break;
case Config::PROPERTIES: case Config::SERIALIZED:
$content = $this->writeProperties(); $content = serialize($this->config);
break; break;
case Config::JSON: case Config::ENUM:
$content = json_encode($this->config, $this->jsonOptions); $content = implode("\r\n", array_keys($this->config));
break; break;
case Config::YAML: default:
$content = yaml_emit($this->config, YAML_UTF8_ENCODING); throw new \InvalidStateException("Config type is unknown, has not been set or not detected");
break;
case Config::SERIALIZED:
$content = serialize($this->config);
break;
case Config::ENUM:
$content = implode("\r\n", array_keys($this->config));
break;
default:
throw new \InvalidStateException("Config type is unknown, has not been set or not detected");
}
file_put_contents($this->file, $content);
}catch(\Throwable $e){
$logger = Server::getInstance()->getLogger();
$logger->critical("Could not save Config " . $this->file . ": " . $e->getMessage());
if(\pocketmine\DEBUG > 1){
$logger->logException($e);
}
}
$this->changed = false;
return true;
}else{
return false;
} }
file_put_contents($this->file, $content);
$this->changed = false;
} }
/** /**
@ -415,7 +382,7 @@ class Config{
* @return bool|mixed * @return bool|mixed
*/ */
public function get($k, $default = false){ public function get($k, $default = false){
return ($this->correct and isset($this->config[$k])) ? $this->config[$k] : $default; return $this->config[$k] ?? $default;
} }
/** /**