master

laravel/framework

Last updated at: 29/12/2023 09:23

SerializesAndRestoresModelIdentifiers.php

TLDR

This file provides a trait called SerializesAndRestoresModelIdentifiers that contains methods for serializing and restoring model identifiers used in the Laravel Queue system.

Methods

getSerializedPropertyValue

This method is used to prepare a property value for serialization. It takes in a value and a boolean flag indicating whether to include relations. If the value is a queueable collection, it creates a new ModelIdentifier object with the class, IDs, relations, and connection of the collection. If the value is a queueable entity, it creates a new ModelIdentifier object with the class, ID, relations, and connection of the entity. If the value is neither a queueable collection nor a queueable entity, the value is returned as is.

getRestoredPropertyValue

This method is used to restore a property value after deserialization. It takes in a value and checks if it is an instance of ModelIdentifier. If it is not, the value is returned as is. If it is, the method checks if the ID is an array. If it is, a collection of models is restored using the restoreCollection method. If it is not, a single model is restored using the restoreModel method.

restoreCollection

This method is used to restore a queueable collection instance. It takes in a ModelIdentifier object and returns a new instance of EloquentCollection or a custom collection class specified in the ModelIdentifier. If the class is a pivot table or uses the AsPivot trait, the collection is returned as is. Otherwise, the collection is keyed by the models' primary keys and filtered to include only models with the specified IDs.

restoreModel

This method is used to restore a model from a ModelIdentifier instance. It takes in a ModelIdentifier object and returns the first model that matches the ID and connection, loaded with the specified relations.

getQueryForModelRestoration

This method is used to get the query for model restoration. It takes in a model instance and an ID or array of IDs and returns a new query builder instance for restoration.

<?php

namespace Illuminate\Queue;

use Illuminate\Contracts\Database\ModelIdentifier;
use Illuminate\Contracts\Queue\QueueableCollection;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Relations\Concerns\AsPivot;
use Illuminate\Database\Eloquent\Relations\Pivot;

trait SerializesAndRestoresModelIdentifiers
{
    /**
     * Get the property value prepared for serialization.
     *
     * @param  mixed  $value
     * @param  bool  $withRelations
     * @return mixed
     */
    protected function getSerializedPropertyValue($value, $withRelations = true)
    {
        if ($value instanceof QueueableCollection) {
            return (new ModelIdentifier(
                $value->getQueueableClass(),
                $value->getQueueableIds(),
                $withRelations ? $value->getQueueableRelations() : [],
                $value->getQueueableConnection()
            ))->useCollectionClass(
                ($collectionClass = get_class($value)) !== EloquentCollection::class
                    ? $collectionClass
                    : null
            );
        }

        if ($value instanceof QueueableEntity) {
            return new ModelIdentifier(
                get_class($value),
                $value->getQueueableId(),
                $withRelations ? $value->getQueueableRelations() : [],
                $value->getQueueableConnection()
            );
        }

        return $value;
    }

    /**
     * Get the restored property value after deserialization.
     *
     * @param  mixed  $value
     * @return mixed
     */
    protected function getRestoredPropertyValue($value)
    {
        if (! $value instanceof ModelIdentifier) {
            return $value;
        }

        return is_array($value->id)
                ? $this->restoreCollection($value)
                : $this->restoreModel($value);
    }

    /**
     * Restore a queueable collection instance.
     *
     * @param  \Illuminate\Contracts\Database\ModelIdentifier  $value
     * @return \Illuminate\Database\Eloquent\Collection
     */
    protected function restoreCollection($value)
    {
        if (! $value->class || count($value->id) === 0) {
            return ! is_null($value->collectionClass ?? null)
                ? new $value->collectionClass
                : new EloquentCollection;
        }

        $collection = $this->getQueryForModelRestoration(
            (new $value->class)->setConnection($value->connection), $value->id
        )->useWritePdo()->get();

        if (is_a($value->class, Pivot::class, true) ||
            in_array(AsPivot::class, class_uses($value->class))) {
            return $collection;
        }

        $collection = $collection->keyBy->getKey();

        $collectionClass = get_class($collection);

        return new $collectionClass(
            collect($value->id)->map(function ($id) use ($collection) {
                return $collection[$id] ?? null;
            })->filter()
        );
    }

    /**
     * Restore the model from the model identifier instance.
     *
     * @param  \Illuminate\Contracts\Database\ModelIdentifier  $value
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function restoreModel($value)
    {
        return $this->getQueryForModelRestoration(
            (new $value->class)->setConnection($value->connection), $value->id
        )->useWritePdo()->firstOrFail()->load($value->relations ?? []);
    }

    /**
     * Get the query for model restoration.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  array|int  $ids
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function getQueryForModelRestoration($model, $ids)
    {
        return $model->newQueryForRestoration($ids);
    }
}