From 4c7bde1400820f36caf8b2a5374007384c3018f3 Mon Sep 17 00:00:00 2001 From: winter Date: Mon, 9 Dec 2024 21:31:54 +0000 Subject: rename to Digitigrade / PawPub :3 --- Digitigrade/Model/FetchableModel.php | 78 ++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Digitigrade/Model/FetchableModel.php (limited to 'Digitigrade/Model/FetchableModel.php') diff --git a/Digitigrade/Model/FetchableModel.php b/Digitigrade/Model/FetchableModel.php new file mode 100644 index 0000000..30b68e7 --- /dev/null +++ b/Digitigrade/Model/FetchableModel.php @@ -0,0 +1,78 @@ +bStrictObjectTypeChecking = false; + } + + private static function fetchFromRemote(string $uri, bool $autoSave): ?static { + // fetch the object + $data = @file_get_contents($uri, context: stream_context_create(['http' => [ + 'header' => 'Accept: application/json' + ]])); + if ($data === false) + return null; + $data = json_decode($data); + if ($data === null) + return null; + // default everything nullable to null + $obj = new static(); + $reflProps = (new \ReflectionClass(static::class))->getProperties(); + foreach ($reflProps as $reflProp) { + assert($reflProp instanceof \ReflectionProperty); // for intellisense lmao + if ($reflProp->getType()->allowsNull()) { + $obj->{$reflProp->getName()} = null; + } + } + // rename 'self' to 'uri' because of reasons + if (property_exists($data, 'self')) { + $data->uri = $data->self; + unset($data->self); + } + // map all present fields + self::$mapper->map($data, $obj); + // (hopefully) recursively fetch any other fetchable models contained in this one + foreach ($reflProps as $reflProp) { + assert($reflProp instanceof \ReflectionProperty); + $reflType = $reflProp->getType(); + $propName = $reflProp->getName(); + if (!($reflType instanceof \ReflectionNamedType)) + continue; + $type = $reflType->getName(); + if (is_subclass_of($type, FetchableModel::class) && is_string($data->{$propName})) { + // try to avoid recursion + // TODO: make a better effort at avoiding recursion (e.g. when it's more than one step nested) + if ($data->{$propName} == $uri) { + $obj->{$propName} = $obj; + } else { + $obj->{$propName} = $type::findByUri($data->{$propName}, $autoSave); + } + } + } + + if ($autoSave) { + $obj->save(); + } + + return $obj; + } + + public static function findByUri(string $uri, bool $autoSave = true, bool $forceRefetch = false): ?static { + if (!$forceRefetch) { + $obj = static::findWhere('uri = ?', [$uri]); + if ($obj != null) + return $obj; + } + return static::fetchFromRemote($uri, $autoSave); + } +} + +FetchableModel::__initStatic(); \ No newline at end of file -- cgit v1.3