Allow for reverse Indexing

This commit is contained in:
root 2022-12-03 17:08:52 +01:00
parent f1d00615b6
commit 548a2376d4
3 changed files with 96 additions and 9 deletions

View File

@ -12,4 +12,6 @@ interface IJsonUnflattener
* @return JsonSerializable|null * @return JsonSerializable|null
*/ */
public function unflattenByID(string $className, $identifier) : JsonSerializable|null; public function unflattenByID(string $className, $identifier) : JsonSerializable|null;
public function updateIndex(IJsonIdentifiable $source, IJsonIdentifiable $dest, bool $delete);
} }

View File

@ -8,6 +8,7 @@ class JsonDatabase implements IJsonUnflattener
private static $LIVE = 'live'; private static $LIVE = 'live';
private static $ARCHIVE = 'archive'; private static $ARCHIVE = 'archive';
private static $EXTENSION = '.json'; private static $EXTENSION = '.json';
private static $EXTENSION_INDEX = '.index';
private ?string $storagePath = null; private ?string $storagePath = null;
private bool $nested = false; private bool $nested = false;
private bool $fullDomain = true; private bool $fullDomain = true;
@ -148,6 +149,87 @@ class JsonDatabase implements IJsonUnflattener
return JsonSerializable::Deserialize($json, $this->nested, $this, $class); return JsonSerializable::Deserialize($json, $this->nested, $this, $class);
} }
public function updateIndex(IJsonIdentifiable $source, IJsonIdentifiable $dest, bool $delete = false)
{
if ($source->flatIdentifier() == null || $dest->flatIdentifier() == null)
return;
$destID = self::SanitizeIdentifier(strval($dest->flatIdentifier()));
$srcID = self::SanitizeIdentifier(strval($source->flatIdentifier()));
if (empty($destID) || empty($srcID))
return;
$destPath = $this->getObjectPath(get_class($dest), $destID) . self::$EXTENSION_INDEX;
if (strlen($destPath) > PHP_MAXPATHLEN)
throw new Exception('JsonDatabase: Specified Path ' . $destPath . ' is longer than allowed.');
$indexJson = [];
// Index exists
if (is_file($destPath))
{
$indexJson = json_decode(file_get_contents($destPath), true);
if ($indexJson == false)
$indexJson = [];
}
// Check if entry exists
$subArray = [];
if (array_key_exists(get_class($source), $indexJson))
$subArray = $indexJson[get_class($source)];
// Already indexed
if (in_array($srcID, $subArray) && !$delete)
return;
else if (in_array($srcID, $subArray) && $delete)
unset($subArray[array_search($srcID, $subArray)]);
else
$subArray[] = $srcID;
$indexJson[get_class($source)] = $subArray;
if (is_writable(dirname($destPath)) || mkdir(dirname($destPath), 0770, true))
file_put_contents($destPath, json_encode($indexJson));
else
throw new \Exception('JsonDatabase: Path ' . $destPath . ' is not writable.');
}
public function fromIndex(string $serClass, $serIdentifier, string $findClass): array
{
if ($serIdentifier == null)
return [];
$serIdentifier = self::SanitizeIdentifier(strval($serIdentifier));
if (empty($serIdentifier) || empty($serClass))
return [];
$serPath = $this->getObjectPath($serClass, $serIdentifier) . self::$EXTENSION_INDEX;
if (strlen($serPath) > PHP_MAXPATHLEN)
throw new Exception('JsonDatabase: Specified Path ' . $destPath . ' is longer than allowed.');
$indexJson = [];
// Index exists
if (is_file($serPath))
{
$indexJson = json_decode(file_get_contents($serPath), true);
if ($indexJson == false)
return [];
// TODO: Check if the referenced objects exist on disk
if (array_key_exists(get_class($findClass), $indexJson))
return $indexJson[get_class($findClass)];
else
return [];
}
else {
return [];
}
}
public function save(JsonSerializable $obj, ?string $name = null) public function save(JsonSerializable $obj, ?string $name = null)
{ {
if ($name != null && !empty(trim($name))) { if ($name != null && !empty(trim($name))) {
@ -184,7 +266,7 @@ class JsonDatabase implements IJsonUnflattener
if (is_writable(dirname($objPath)) || mkdir(dirname($objPath), 0770, true)) if (is_writable(dirname($objPath)) || mkdir(dirname($objPath), 0770, true))
file_put_contents($objPath, $objJson); file_put_contents($objPath, $objJson);
else else
throw new \Exception('JsonDatabase: Path ' . $historyPath . ' is not writable.'); throw new \Exception('JsonDatabase: Path ' . $objPath . ' is not writable.');
return $name; return $name;
} }

View File

@ -89,7 +89,7 @@ abstract class JsonSerializable
* @param bool $to_array Do we want the result as an array instead of a json encoded string? * @param bool $to_array Do we want the result as an array instead of a json encoded string?
* @return string|array Returns a json encoded string or a key value array * @return string|array Returns a json encoded string or a key value array
*/ */
public function Serialize($nested = false, $to_array = false) public function Serialize($nested = false, $to_array = false, IJsonUnflattener $callback = null)
{ {
// Initialize result set array // Initialize result set array
$result = array(); $result = array();
@ -106,18 +106,21 @@ abstract class JsonSerializable
// Add var name and value to result set // Add var name and value to result set
if (isset($value) && $value != null && $value instanceof JsonSerializable) if (isset($value) && $value != null && $value instanceof JsonSerializable)
{ {
if ($nested) if ($nested) {
$result[$key] = $value->Serialize(true, true); $result[$key] = $value->Serialize(true, true);
else if ($value instanceof IJsonIdentifiable && $value->flatIdentifier() !== null) } else if ($value instanceof IJsonIdentifiable && $value->flatIdentifier() !== null) {
$result[$key] = $value->flatIdentifier(); $result[$key] = $value->flatIdentifier();
else
continue;
if ($this instanceof IJsonIdentifiable && $callback != null)
call_user_func([$callback, 'updateIndex'], $this, $value, false);
} else {
continue;
}
} }
else if (isset($value) && $value != null && is_array($value)) { else if (isset($value) && $value != null && is_array($value)) {
$arrayType = self::getPropertyArrayType(new \ReflectionProperty($this, $key)); $arrayType = self::getPropertyArrayType(new \ReflectionProperty($this, $key));
if ($arrayType != null) if ($arrayType != null)
$result[$key] = self::SerializeArray($value, $nested, true); $result[$key] = self::SerializeArray(objects: $value, nested: $nested, to_array: true, callback: $callback);
else else
$result[$key] = $value; $result[$key] = $value;
} }
@ -139,7 +142,7 @@ abstract class JsonSerializable
* @param bool $nested Indicates if we should also serialize nested object instances * @param bool $nested Indicates if we should also serialize nested object instances
* @return string returns a json formatted string * @return string returns a json formatted string
*/ */
public static function SerializeArray($objects = [], $nested = false, $to_array = false) public static function SerializeArray($objects = [], $nested = false, $to_array = false, IJsonUnflattener $callback = null)
{ {
// Initialize a an array of results // Initialize a an array of results
$results = array(); $results = array();
@ -149,7 +152,7 @@ abstract class JsonSerializable
if ($object instanceof JsonSerializable) if ($object instanceof JsonSerializable)
{ {
if ($nested) if ($nested)
$results[] = $object->Serialize(nested: true, to_array: true); $results[] = $object->Serialize(nested: true, to_array: true, callback: $callback);
else if ($object instanceof IJsonIdentifiable && $object->flatIdentifier() !== null) else if ($object instanceof IJsonIdentifiable && $object->flatIdentifier() !== null)
$results[] = $object->flatIdentifier(); $results[] = $object->flatIdentifier();
else else