238 lines
5.7 KiB
PHP
238 lines
5.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This file is part of the Carbon package.
|
|
*
|
|
* (c) Brian Nesbitt <brian@nesbot.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
namespace Carbon\Traits;
|
|
|
|
use Carbon\Exceptions\InvalidFormatException;
|
|
use ReturnTypeWillChange;
|
|
use Throwable;
|
|
|
|
/**
|
|
* Trait Serialization.
|
|
*
|
|
* Serialization and JSON stuff.
|
|
*
|
|
* Depends on the following properties:
|
|
*
|
|
* @property int $year
|
|
* @property int $month
|
|
* @property int $daysInMonth
|
|
* @property int $quarter
|
|
*
|
|
* Depends on the following methods:
|
|
*
|
|
* @method string|static locale(string $locale = null, string ...$fallbackLocales)
|
|
* @method string toJSON()
|
|
*/
|
|
trait Serialization
|
|
{
|
|
use ObjectInitialisation;
|
|
|
|
/**
|
|
* The custom Carbon JSON serializer.
|
|
*
|
|
* @var callable|null
|
|
*/
|
|
protected static $serializer;
|
|
|
|
/**
|
|
* List of key to use for dump/serialization.
|
|
*
|
|
* @var string[]
|
|
*/
|
|
protected $dumpProperties = ['date', 'timezone_type', 'timezone'];
|
|
|
|
/**
|
|
* Locale to dump comes here before serialization.
|
|
*
|
|
* @var string|null
|
|
*/
|
|
protected $dumpLocale;
|
|
|
|
/**
|
|
* Embed date properties to dump in a dedicated variables so it won't overlap native
|
|
* DateTime ones.
|
|
*
|
|
* @var array|null
|
|
*/
|
|
protected $dumpDateProperties;
|
|
|
|
/**
|
|
* Return a serialized string of the instance.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function serialize()
|
|
{
|
|
return serialize($this);
|
|
}
|
|
|
|
/**
|
|
* Create an instance from a serialized string.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @throws InvalidFormatException
|
|
*
|
|
* @return static
|
|
*/
|
|
public static function fromSerialized($value)
|
|
{
|
|
$instance = @unserialize((string) $value);
|
|
|
|
if (!$instance instanceof static) {
|
|
throw new InvalidFormatException("Invalid serialized value: $value");
|
|
}
|
|
|
|
return $instance;
|
|
}
|
|
|
|
/**
|
|
* The __set_state handler.
|
|
*
|
|
* @param string|array $dump
|
|
*
|
|
* @return static
|
|
*/
|
|
#[ReturnTypeWillChange]
|
|
public static function __set_state($dump)
|
|
{
|
|
if (\is_string($dump)) {
|
|
return static::parse($dump);
|
|
}
|
|
|
|
/** @var \DateTimeInterface $date */
|
|
$date = get_parent_class(static::class) && method_exists(parent::class, '__set_state')
|
|
? parent::__set_state((array) $dump)
|
|
: (object) $dump;
|
|
|
|
return static::instance($date);
|
|
}
|
|
|
|
/**
|
|
* Returns the list of properties to dump on serialize() called on.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function __sleep()
|
|
{
|
|
$properties = $this->getSleepProperties();
|
|
|
|
if ($this->localTranslator ?? null) {
|
|
$properties[] = 'dumpLocale';
|
|
$this->dumpLocale = $this->locale ?? null;
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Set locale if specified on unserialize() called.
|
|
*/
|
|
#[ReturnTypeWillChange]
|
|
public function __wakeup()
|
|
{
|
|
if (get_parent_class() && method_exists(parent::class, '__wakeup')) {
|
|
// @codeCoverageIgnoreStart
|
|
try {
|
|
parent::__wakeup();
|
|
} catch (Throwable $exception) {
|
|
// FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later.
|
|
['date' => $date, 'timezone' => $timezone] = $this->dumpDateProperties;
|
|
parent::__construct($date, unserialize($timezone));
|
|
}
|
|
// @codeCoverageIgnoreEnd
|
|
}
|
|
|
|
$this->constructedObjectId = spl_object_hash($this);
|
|
|
|
if (isset($this->dumpLocale)) {
|
|
$this->locale($this->dumpLocale);
|
|
$this->dumpLocale = null;
|
|
}
|
|
|
|
$this->cleanupDumpProperties();
|
|
}
|
|
|
|
/**
|
|
* Prepare the object for JSON serialization.
|
|
*
|
|
* @return array|string
|
|
*/
|
|
#[ReturnTypeWillChange]
|
|
public function jsonSerialize()
|
|
{
|
|
$serializer = $this->localSerializer ?? static::$serializer;
|
|
|
|
if ($serializer) {
|
|
return \is_string($serializer)
|
|
? $this->rawFormat($serializer)
|
|
: $serializer($this);
|
|
}
|
|
|
|
return $this->toJSON();
|
|
}
|
|
|
|
/**
|
|
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
|
|
* You should rather transform Carbon object before the serialization.
|
|
*
|
|
* JSON serialize all Carbon instances using the given callback.
|
|
*
|
|
* @param callable $callback
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function serializeUsing($callback)
|
|
{
|
|
static::$serializer = $callback;
|
|
}
|
|
|
|
/**
|
|
* Cleanup properties attached to the public scope of DateTime when a dump of the date is requested.
|
|
* foreach ($date as $_) {}
|
|
* serializer($date)
|
|
* var_export($date)
|
|
* get_object_vars($date)
|
|
*/
|
|
public function cleanupDumpProperties()
|
|
{
|
|
foreach ($this->dumpProperties as $property) {
|
|
if (isset($this->$property)) {
|
|
unset($this->$property);
|
|
}
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
private function getSleepProperties(): array
|
|
{
|
|
$properties = $this->dumpProperties;
|
|
|
|
// @codeCoverageIgnoreStart
|
|
if (!\extension_loaded('msgpack')) {
|
|
return $properties;
|
|
}
|
|
|
|
if (isset($this->constructedObjectId)) {
|
|
$this->dumpDateProperties = [
|
|
'date' => $this->format('Y-m-d H:i:s.u'),
|
|
'timezone' => serialize($this->timezone ?? null),
|
|
];
|
|
|
|
$properties[] = 'dumpDateProperties';
|
|
}
|
|
|
|
return $properties;
|
|
// @codeCoverageIgnoreEnd
|
|
}
|
|
}
|