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
 | ||
|  |     } | ||
|  | } |