Add @type phpdoc to allow for typed arrays
This commit is contained in:
parent
006437f670
commit
f1d00615b6
@ -189,22 +189,22 @@ class JsonDatabase implements IJsonUnflattener
|
||||
return $name;
|
||||
}
|
||||
|
||||
public function delete(string $className, $identifier): bool
|
||||
public function delete(string $className, $identifier, ?int $timestamp = null): bool
|
||||
{
|
||||
if ($class == null || empty(trim($name)))
|
||||
if ($className == null || empty(trim($identifier)))
|
||||
return false;
|
||||
|
||||
if ($name != null && !empty(trim(strval($name))))
|
||||
$name = JSONDatabase::SanitizeIdentifier($name);
|
||||
if ($identifier != null && !empty(trim(strval($identifier))))
|
||||
$identifier = JSONDatabase::SanitizeIdentifier($identifier);
|
||||
else
|
||||
return false;
|
||||
|
||||
$class = trim($class);
|
||||
$class = trim($className);
|
||||
|
||||
if (!$this->audit && $timestamp != null)
|
||||
return false;
|
||||
|
||||
$objPath = $this->getObjectPath($class, $name, ($timestamp != null));
|
||||
$objPath = $this->getObjectPath($className, $identifier, ($timestamp != null));
|
||||
|
||||
if (strlen($objPath) > PHP_MAXPATHLEN)
|
||||
return false;
|
||||
@ -215,7 +215,7 @@ class JsonDatabase implements IJsonUnflattener
|
||||
return unlink($objPath);
|
||||
}
|
||||
|
||||
public function delete(IJsonIdentifiable $obj): bool
|
||||
public function deleteObj(IJsonIdentifiable $obj): bool
|
||||
{
|
||||
return $this->delete(get_class($obj), $obj->flatIdentifier());
|
||||
}
|
||||
|
@ -37,6 +37,52 @@ abstract class JsonSerializable
|
||||
return (new \ReflectionClass($typeName))->isSubclassOf(JsonSerializable::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if is strongly typed array of type JsonSerializable and return the type
|
||||
* @param string $property Property we should check against
|
||||
* @return bool returns class name if type/class of property extends JsonSerializable
|
||||
*/
|
||||
private static function getPropertyArrayType(\ReflectionProperty $property)
|
||||
{
|
||||
if (!isset($property) || $property === null || !$property->hasType())
|
||||
return false;
|
||||
|
||||
// Get builtin type or class of given property
|
||||
$type = $property->getType();
|
||||
|
||||
// A built-in type is any type that is not a class, interface, or trait.
|
||||
// Assume false on simple types, we can only check this on classes
|
||||
if (!$type->isBuiltin() && $type->getName() != 'array')
|
||||
return null;
|
||||
|
||||
$docComment = $property->getDocComment();
|
||||
|
||||
if (!$docComment)
|
||||
return null;
|
||||
|
||||
$line = strtok($docComment, "\r\n");
|
||||
|
||||
// TODO: Maybe use preg_match here, maybe faster: https://stackoverflow.com/a/6250269
|
||||
while ($line !== false) {
|
||||
$docType = substr($line, strpos($line, '@type ') + 6);
|
||||
if (!empty(trim($docType)))
|
||||
{
|
||||
$docType = trim($docType);
|
||||
if (class_exists($docType)) {
|
||||
$refClass = new \ReflectionClass($docType);
|
||||
if ($refClass->isSubclassOf(JsonSerializable::class))
|
||||
return $refClass->getName();
|
||||
}
|
||||
// We found a type property, do not further iterate
|
||||
return null;
|
||||
}
|
||||
|
||||
$line = strtok( "\r\n" );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a JsonSerializable Object to an array or to a json string
|
||||
* @param bool $nested Indicates if we should also serialize nested object instances
|
||||
@ -68,6 +114,13 @@ abstract class JsonSerializable
|
||||
continue;
|
||||
|
||||
}
|
||||
else if (isset($value) && $value != null && is_array($value)) {
|
||||
$arrayType = self::getPropertyArrayType(new \ReflectionProperty($this, $key));
|
||||
if ($arrayType != null)
|
||||
$result[$key] = self::SerializeArray($value, $nested, true);
|
||||
else
|
||||
$result[$key] = $value;
|
||||
}
|
||||
else {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
@ -86,17 +139,29 @@ abstract class JsonSerializable
|
||||
* @param bool $nested Indicates if we should also serialize nested object instances
|
||||
* @return string returns a json formatted string
|
||||
*/
|
||||
public static function SerializeArray($objects = [], $nested = false)
|
||||
public static function SerializeArray($objects = [], $nested = false, $to_array = false)
|
||||
{
|
||||
// Initialize a an array of results
|
||||
$results = array();
|
||||
|
||||
// Iterate through provided JsonSerializable Objects and serialize them
|
||||
foreach ($objects as $object)
|
||||
$results[] = $object->Serialize($nested, true);
|
||||
foreach ($objects as $object) {
|
||||
if ($object instanceof JsonSerializable)
|
||||
{
|
||||
if ($nested)
|
||||
$results[] = $object->Serialize(nested: true, to_array: true);
|
||||
else if ($object instanceof IJsonIdentifiable && $object->flatIdentifier() !== null)
|
||||
$results[] = $object->flatIdentifier();
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the json encoded string
|
||||
return json_encode($results);
|
||||
// If json is demanded, encode, else just return the array
|
||||
if ($to_array)
|
||||
return $results;
|
||||
else
|
||||
return json_encode($results);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,7 +200,15 @@ abstract class JsonSerializable
|
||||
// If simple data type, just assign it to var in class
|
||||
// TODO: Exception handling, what if class specifies an int but string was provided?
|
||||
$selfSubclass = self::isPropertyJsonSerializable($property);
|
||||
if ($selfSubclass)
|
||||
$arrayType = self::getPropertyArrayType($property);
|
||||
if ($arrayType != null)
|
||||
{
|
||||
if (is_array($value))
|
||||
$classInstance->{$key} = self::DeserializeArray($value, $nested, $callback, $arrayType);
|
||||
else
|
||||
continue;
|
||||
}
|
||||
elseif ($selfSubclass)
|
||||
{
|
||||
try {
|
||||
if (is_array($value)) {
|
||||
@ -183,7 +256,7 @@ abstract class JsonSerializable
|
||||
* @param string|array $json json string containing the array or array to decode
|
||||
* @return JsonSerializable[] Returns an Array of Instances of JsonSerializable
|
||||
*/
|
||||
public static function DeserializeArray(string|array $json, bool $nested = false)
|
||||
public static function DeserializeArray(string|array $json, bool $nested = false, IJsonUnflattener $callback = null, string $className = null)
|
||||
{
|
||||
// Check if we need to decode from json first
|
||||
if (is_string($json))
|
||||
@ -194,14 +267,12 @@ abstract class JsonSerializable
|
||||
// Loop through the array
|
||||
foreach ($json as $item)
|
||||
{
|
||||
// Uh oh, check if there is an nested array within the array and deserialize children
|
||||
// If not, or if we are not supposed to, just deserialize the current layer or ignore
|
||||
if ($nested && is_array($item))
|
||||
$items[] = self::DeserializeArray(json: $item, nested: $nested);
|
||||
else if (is_array($item))
|
||||
continue;
|
||||
if (is_array($item))
|
||||
$items[] = self::Deserialize(json: $item, nested: $nested, callback: $callback, className: $className);
|
||||
else if ($className != null && $callback != null && !is_object($item))
|
||||
$items[] = call_user_func([$callback, 'unflattenByID'], $className, $item);
|
||||
else
|
||||
$items[] = self::Deserialize(json: $item, nested: $nested);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Returns the result
|
||||
|
Loading…
Reference in New Issue
Block a user