Filesystem: added fileGetContents to reduce ErrorToExceptionHandler boilerplate code

This commit is contained in:
Dylan K. Taylor 2022-12-25 17:13:51 +00:00
parent b1c0eae1f6
commit 0d169b4e80
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
16 changed files with 53 additions and 51 deletions

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\build\make_release; namespace pocketmine\build\make_release;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use pocketmine\utils\VersionString; use pocketmine\utils\VersionString;
use pocketmine\VersionInfo; use pocketmine\VersionInfo;
@ -30,7 +31,6 @@ use function array_keys;
use function array_map; use function array_map;
use function dirname; use function dirname;
use function fgets; use function fgets;
use function file_get_contents;
use function file_put_contents; use function file_put_contents;
use function fwrite; use function fwrite;
use function getopt; use function getopt;
@ -50,7 +50,7 @@ use const STR_PAD_LEFT;
require_once dirname(__DIR__) . '/vendor/autoload.php'; require_once dirname(__DIR__) . '/vendor/autoload.php';
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{ function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
$versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist"); $versionInfo = Filesystem::fileGetContents($versionInfoPath);
$versionInfo = preg_replace( $versionInfo = preg_replace(
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m', $pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
'$1const BASE_VERSION = "' . $newVersion . '";', '$1const BASE_VERSION = "' . $newVersion . '";',

View File

@ -125,7 +125,6 @@ use function count;
use function date; use function date;
use function fclose; use function fclose;
use function file_exists; use function file_exists;
use function file_get_contents;
use function file_put_contents; use function file_put_contents;
use function filemtime; use function filemtime;
use function fopen; use function fopen;
@ -777,7 +776,7 @@ class Server{
$this->logger->info("Loading server configuration"); $this->logger->info("Loading server configuration");
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml"); $pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
if(!file_exists($pocketmineYmlPath)){ if(!file_exists($pocketmineYmlPath)){
$content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file"); $content = Filesystem::fileGetContents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
if(VersionInfo::IS_DEVELOPMENT_BUILD){ if(VersionInfo::IS_DEVELOPMENT_BUILD){
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content); $content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
} }
@ -950,7 +949,7 @@ class Server{
copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile); copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile);
} }
try{ try{
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile))); $pluginGraylist = PluginGraylist::fromArray(yaml_parse(Filesystem::fileGetContents($graylistFile)));
}catch(\InvalidArgumentException $e){ }catch(\InvalidArgumentException $e){
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage()); $this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
$this->forceShutdownExit(); $this->forceShutdownExit();

View File

@ -26,9 +26,8 @@ namespace pocketmine\crafting;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\ItemFactory; use pocketmine\item\ItemFactory;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils; use pocketmine\utils\Filesystem;
use function array_map; use function array_map;
use function file_get_contents;
use function is_array; use function is_array;
use function json_decode; use function json_decode;
@ -52,7 +51,7 @@ final class CraftingManagerFromDataHelper{
} }
public static function make(string $filePath) : CraftingManager{ public static function make(string $filePath) : CraftingManager{
$recipes = json_decode(Utils::assumeNotFalse(file_get_contents($filePath), "Missing required resource file"), true); $recipes = json_decode(Filesystem::fileGetContents($filePath), true);
if(!is_array($recipes)){ if(!is_array($recipes)){
throw new AssumptionFailedError("recipes.json root should contain a map of recipe types"); throw new AssumptionFailedError("recipes.json root should contain a map of recipe types");
} }

View File

@ -24,8 +24,7 @@ declare(strict_types=1);
namespace pocketmine\data\bedrock; namespace pocketmine\data\bedrock;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Utils; use pocketmine\utils\Filesystem;
use function file_get_contents;
use function is_array; use function is_array;
use function is_int; use function is_int;
use function is_string; use function is_string;
@ -45,7 +44,7 @@ abstract class LegacyToStringBidirectionalIdMap{
private array $stringToLegacy = []; private array $stringToLegacy = [];
public function __construct(string $file){ public function __construct(string $file){
$stringToLegacyId = json_decode(Utils::assumeNotFalse(file_get_contents($file), "Missing required resource file"), true); $stringToLegacyId = json_decode(Filesystem::fileGetContents($file), true);
if(!is_array($stringToLegacyId)){ if(!is_array($stringToLegacyId)){
throw new AssumptionFailedError("Invalid format of ID map"); throw new AssumptionFailedError("Invalid format of ID map");
} }

View File

@ -25,9 +25,9 @@ namespace pocketmine\inventory;
use pocketmine\item\Durable; use pocketmine\item\Durable;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\utils\Filesystem;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function file_get_contents;
use function json_decode; use function json_decode;
final class CreativeInventory{ final class CreativeInventory{
@ -37,7 +37,7 @@ final class CreativeInventory{
private array $creative = []; private array $creative = [];
private function __construct(){ private function __construct(){
$creativeItems = json_decode(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "creativeitems.json")), true); $creativeItems = json_decode(Filesystem::fileGetContents(Path::join(\pocketmine\BEDROCK_DATA_PATH, "creativeitems.json")), true);
foreach($creativeItems as $data){ foreach($creativeItems as $data){
$item = Item::jsonDeserialize($data); $item = Item::jsonDeserialize($data);

View File

@ -24,11 +24,10 @@ declare(strict_types=1);
namespace pocketmine\item; namespace pocketmine\item;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Filesystem;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use pocketmine\utils\Utils;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function explode; use function explode;
use function file_get_contents;
use function is_array; use function is_array;
use function is_int; use function is_int;
use function is_numeric; use function is_numeric;
@ -53,7 +52,7 @@ final class LegacyStringToItemParser{
private static function make() : self{ private static function make() : self{
$result = new self(ItemFactory::getInstance()); $result = new self(ItemFactory::getInstance());
$mappingsRaw = Utils::assumeNotFalse(@file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, 'item_from_string_bc_map.json')), "Missing required resource file"); $mappingsRaw = Filesystem::fileGetContents(Path::join(\pocketmine\RESOURCE_PATH, 'item_from_string_bc_map.json'));
$mappings = json_decode($mappingsRaw, true); $mappings = json_decode($mappingsRaw, true);
if(!is_array($mappings)) throw new AssumptionFailedError("Invalid mappings format, expected array"); if(!is_array($mappings)) throw new AssumptionFailedError("Invalid mappings format, expected array");

View File

@ -27,9 +27,9 @@ use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\types\CacheableNbt; use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use pocketmine\utils\Filesystem;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function file_get_contents;
class StaticPacketCache{ class StaticPacketCache{
use SingletonTrait; use SingletonTrait;
@ -38,9 +38,7 @@ class StaticPacketCache{
* @phpstan-return CacheableNbt<\pocketmine\nbt\tag\CompoundTag> * @phpstan-return CacheableNbt<\pocketmine\nbt\tag\CompoundTag>
*/ */
private static function loadCompoundFromFile(string $filePath) : CacheableNbt{ private static function loadCompoundFromFile(string $filePath) : CacheableNbt{
$rawNbt = @file_get_contents($filePath); return new CacheableNbt((new NetworkNbtSerializer())->read(Filesystem::fileGetContents($filePath))->mustGetCompoundTag());
if($rawNbt === false) throw new \RuntimeException("Failed to read file");
return new CacheableNbt((new NetworkNbtSerializer())->read($rawNbt)->mustGetCompoundTag());
} }
private static function make() : self{ private static function make() : self{

View File

@ -26,10 +26,9 @@ namespace pocketmine\network\mcpe\convert;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary; use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry; use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Filesystem;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use pocketmine\utils\Utils;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function file_get_contents;
use function is_array; use function is_array;
use function is_bool; use function is_bool;
use function is_int; use function is_int;
@ -40,7 +39,7 @@ final class GlobalItemTypeDictionary{
use SingletonTrait; use SingletonTrait;
private static function make() : self{ private static function make() : self{
$data = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'required_item_list.json')), "Missing required resource file"); $data = Filesystem::fileGetContents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'required_item_list.json'));
$table = json_decode($data, true); $table = json_decode($data, true);
if(!is_array($table)){ if(!is_array($table)){
throw new AssumptionFailedError("Invalid item list format"); throw new AssumptionFailedError("Invalid item list format");

View File

@ -26,11 +26,11 @@ namespace pocketmine\network\mcpe\convert;
use pocketmine\data\bedrock\LegacyItemIdToStringIdMap; use pocketmine\data\bedrock\LegacyItemIdToStringIdMap;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary; use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Filesystem;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function array_key_exists; use function array_key_exists;
use function file_get_contents;
use function is_array; use function is_array;
use function is_numeric; use function is_numeric;
use function is_string; use function is_string;
@ -67,7 +67,7 @@ final class ItemTranslator{
private array $complexNetToCoreMapping = []; private array $complexNetToCoreMapping = [];
private static function make() : self{ private static function make() : self{
$data = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'r16_to_current_item_map.json')), "Missing required resource file"); $data = Filesystem::fileGetContents(Path::join(\pocketmine\BEDROCK_DATA_PATH, 'r16_to_current_item_map.json'));
$json = json_decode($data, true); $json = json_decode($data, true);
if(!is_array($json) || !isset($json["simple"], $json["complex"]) || !is_array($json["simple"]) || !is_array($json["complex"])){ if(!is_array($json) || !isset($json["simple"], $json["complex"]) || !is_array($json["simple"]) || !is_array($json["complex"])){
throw new AssumptionFailedError("Invalid item table format"); throw new AssumptionFailedError("Invalid item table format");

View File

@ -30,10 +30,9 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer; use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer; use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext; use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext;
use pocketmine\utils\Filesystem;
use pocketmine\utils\SingletonTrait; use pocketmine\utils\SingletonTrait;
use pocketmine\utils\Utils;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function file_get_contents;
/** /**
* @internal * @internal
@ -57,7 +56,7 @@ final class RuntimeBlockMapping{
public function __construct(string $canonicalBlockStatesFile, string $r12ToCurrentBlockMapFile){ public function __construct(string $canonicalBlockStatesFile, string $r12ToCurrentBlockMapFile){
$stream = PacketSerializer::decoder( $stream = PacketSerializer::decoder(
Utils::assumeNotFalse(file_get_contents($canonicalBlockStatesFile), "Missing required resource file"), Filesystem::fileGetContents($canonicalBlockStatesFile),
0, 0,
new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary()) new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary())
); );
@ -75,7 +74,7 @@ final class RuntimeBlockMapping{
/** @var R12ToCurrentBlockMapEntry[] $legacyStateMap */ /** @var R12ToCurrentBlockMapEntry[] $legacyStateMap */
$legacyStateMap = []; $legacyStateMap = [];
$legacyStateMapReader = PacketSerializer::decoder( $legacyStateMapReader = PacketSerializer::decoder(
Utils::assumeNotFalse(file_get_contents($r12ToCurrentBlockMapFile), "Missing required resource file"), Filesystem::fileGetContents($r12ToCurrentBlockMapFile),
0, 0,
new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary()) new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary())
); );

View File

@ -32,7 +32,6 @@ use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function file_exists; use function file_exists;
use function file_get_contents;
use function rename; use function rename;
use function strtolower; use function strtolower;
use function zlib_decode; use function zlib_decode;
@ -70,8 +69,8 @@ final class DatFilePlayerDataProvider implements PlayerDataProvider{
} }
try{ try{
$contents = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => file_get_contents($path)); $contents = Filesystem::fileGetContents($path);
}catch(\ErrorException $e){ }catch(\RuntimeException $e){
throw new PlayerDataLoadException("Failed to read player data file \"$path\": " . $e->getMessage(), 0, $e); throw new PlayerDataLoadException("Failed to read player data file \"$path\": " . $e->getMessage(), 0, $e);
} }
try{ try{

View File

@ -23,14 +23,13 @@ declare(strict_types=1);
namespace pocketmine\resourcepacks; namespace pocketmine\resourcepacks;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\utils\Config; use pocketmine\utils\Config;
use pocketmine\utils\Filesystem;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function array_keys; use function array_keys;
use function copy; use function copy;
use function count; use function count;
use function file_exists; use function file_exists;
use function file_get_contents;
use function gettype; use function gettype;
use function is_array; use function is_array;
use function is_dir; use function is_dir;
@ -104,10 +103,8 @@ class ResourcePackManager{
$keyPath = Path::join($this->path, $pack . ".key"); $keyPath = Path::join($this->path, $pack . ".key");
if(file_exists($keyPath)){ if(file_exists($keyPath)){
try{ try{
$key = ErrorToExceptionHandler::trapAndRemoveFalse( $key = Filesystem::fileGetContents($keyPath);
fn() => file_get_contents($keyPath) }catch(\RuntimeException $e){
);
}catch(\ErrorException $e){
throw new ResourcePackException("Could not read encryption key file: " . $e->getMessage(), 0, $e); throw new ResourcePackException("Could not read encryption key file: " . $e->getMessage(), 0, $e);
} }
$key = rtrim($key, "\r\n"); $key = rtrim($key, "\r\n");

View File

@ -33,7 +33,6 @@ use function count;
use function date; use function date;
use function explode; use function explode;
use function file_exists; use function file_exists;
use function file_get_contents;
use function get_debug_type; use function get_debug_type;
use function implode; use function implode;
use function is_array; use function is_array;
@ -162,10 +161,7 @@ class Config{
$this->config = $default; $this->config = $default;
$this->save(); $this->save();
}else{ }else{
$content = file_get_contents($this->file); $content = Filesystem::fileGetContents($this->file);
if($content === false){
throw new \RuntimeException("Unable to load config file");
}
switch($this->type){ switch($this->type){
case Config::PROPERTIES: case Config::PROPERTIES:
$config = self::parseProperties($content); $config = self::parseProperties($content);

View File

@ -30,6 +30,7 @@ use function dirname;
use function fclose; use function fclose;
use function fflush; use function fflush;
use function file_exists; use function file_exists;
use function file_get_contents;
use function file_put_contents; use function file_put_contents;
use function flock; use function flock;
use function fopen; use function fopen;
@ -296,4 +297,21 @@ final class Filesystem{
@unlink($temporaryFileName); @unlink($temporaryFileName);
} }
} }
/**
* Wrapper around file_get_contents() which throws an exception instead of generating E_* errors.
*
* @phpstan-param resource|null $context
* @phpstan-param 0|positive-int $offset
* @phpstan-param 0|positive-int|null $length
*
* @throws \RuntimeException
*/
public static function fileGetContents(string $fileName, bool $useIncludePath = false, $context = null, int $offset = 0, ?int $length = null) : string{
try{
return ErrorToExceptionHandler::trapAndRemoveFalse(fn() => file_get_contents($fileName, $useIncludePath, $context, $offset, $length));
}catch(\ErrorException $e){
throw new \RuntimeException("Failed to read file $fileName: " . $e->getMessage(), 0, $e);
}
}
} }

View File

@ -39,7 +39,6 @@ use pocketmine\world\generator\GeneratorManager;
use pocketmine\world\World; use pocketmine\world\World;
use pocketmine\world\WorldCreationOptions; use pocketmine\world\WorldCreationOptions;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function file_get_contents;
use function file_put_contents; use function file_put_contents;
use function strlen; use function strlen;
use function substr; use function substr;
@ -111,9 +110,10 @@ class BedrockWorldData extends BaseNbtWorldData{
} }
protected function load() : CompoundTag{ protected function load() : CompoundTag{
$rawLevelData = @file_get_contents($this->dataPath); try{
if($rawLevelData === false){ $rawLevelData = Filesystem::fileGetContents($this->dataPath);
throw new CorruptedWorldException("Failed to read level.dat (permission denied or doesn't exist)"); }catch(\RuntimeException $e){
throw new CorruptedWorldException($e->getMessage(), 0, $e);
} }
if(strlen($rawLevelData) <= 8){ if(strlen($rawLevelData) <= 8){
throw new CorruptedWorldException("Truncated level.dat"); throw new CorruptedWorldException("Truncated level.dat");

View File

@ -37,7 +37,6 @@ use pocketmine\world\World;
use pocketmine\world\WorldCreationOptions; use pocketmine\world\WorldCreationOptions;
use Symfony\Component\Filesystem\Path; use Symfony\Component\Filesystem\Path;
use function ceil; use function ceil;
use function file_get_contents;
use function file_put_contents; use function file_put_contents;
use function microtime; use function microtime;
use function zlib_decode; use function zlib_decode;
@ -75,9 +74,10 @@ class JavaWorldData extends BaseNbtWorldData{
} }
protected function load() : CompoundTag{ protected function load() : CompoundTag{
$rawLevelData = @file_get_contents($this->dataPath); try{
if($rawLevelData === false){ $rawLevelData = Filesystem::fileGetContents($this->dataPath);
throw new CorruptedWorldException("Failed to read level.dat (permission denied or doesn't exist)"); }catch(\RuntimeException $e){
throw new CorruptedWorldException($e->getMessage(), 0, $e);
} }
$nbt = new BigEndianNbtSerializer(); $nbt = new BigEndianNbtSerializer();
$decompressed = @zlib_decode($rawLevelData); $decompressed = @zlib_decode($rawLevelData);