. */ namespace SP\Domain\Common\Adapters; use __PHP_Incomplete_Class; use JsonException; use SP\Domain\Core\Exceptions\SPException; use function SP\__u; /** * Class Serde */ final class Serde { public static function serialize(array|object|string|int $data): string { return serialize($data); } /** * @throws SPException */ public static function serializeJson(array|object|string|int $data, int $flags = 0): string { try { return json_encode($data, JSON_THROW_ON_ERROR | $flags); } catch (JsonException $e) { throw SPException::from($e); } } /** * @template T of object * * @param string $data * @param class-string|null $class * @return T&object * * @throws SPException */ public static function deserialize(string $data, ?string $class = null): object { $value = unserialize($data); return match (true) { $value === false => throw SPException::error(__u('Couldn\'t deserialize the data')), $class !== null && !is_a($value, $class) => throw SPException::error(__u('Invalid target class')), $value instanceof __PHP_Incomplete_Class => self::fixSerialized($data), default => $value }; } /** * Takes an __PHP_Incomplete_Class and casts it to a stdClass object. * All properties will be made public in this step. * * @link https://stackoverflow.com/a/28353091 * * @param string $serialized * @return object */ private static function fixSerialized(string $serialized): object { $dump = preg_replace_callback( '/s:\d+:"\x00+[^\x00]*\x00+([^"]+)"/', static function ($matches) { return 's:' . strlen($matches[1]) . ':"' . $matches[1] . '"'; }, preg_replace('/^O:\d+:"[^"]++"/', 'O:8:"stdClass"', $serialized) ); return unserialize($dump); } /** * @throws SPException */ public static function deserializeJson(string $data): object { try { return json_decode($data, flags: JSON_THROW_ON_ERROR); } catch (JsonException $e) { throw SPException::from($e); } } }