322 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace Illuminate\Database\Eloquent\Relations\Concerns;
 | 
						|
 | 
						|
use Illuminate\Database\Eloquent\Builder;
 | 
						|
use Illuminate\Database\Eloquent\Model;
 | 
						|
use Illuminate\Support\Str;
 | 
						|
 | 
						|
trait AsPivot
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * The parent model of the relationship.
 | 
						|
     *
 | 
						|
     * @var \Illuminate\Database\Eloquent\Model
 | 
						|
     */
 | 
						|
    public $pivotParent;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The name of the foreign key column.
 | 
						|
     *
 | 
						|
     * @var string
 | 
						|
     */
 | 
						|
    protected $foreignKey;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The name of the "other key" column.
 | 
						|
     *
 | 
						|
     * @var string
 | 
						|
     */
 | 
						|
    protected $relatedKey;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Create a new pivot model instance.
 | 
						|
     *
 | 
						|
     * @param  \Illuminate\Database\Eloquent\Model  $parent
 | 
						|
     * @param  array  $attributes
 | 
						|
     * @param  string  $table
 | 
						|
     * @param  bool  $exists
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public static function fromAttributes(Model $parent, $attributes, $table, $exists = false)
 | 
						|
    {
 | 
						|
        $instance = new static;
 | 
						|
 | 
						|
        $instance->timestamps = $instance->hasTimestampAttributes($attributes);
 | 
						|
 | 
						|
        // The pivot model is a "dynamic" model since we will set the tables dynamically
 | 
						|
        // for the instance. This allows it work for any intermediate tables for the
 | 
						|
        // many to many relationship that are defined by this developer's classes.
 | 
						|
        $instance->setConnection($parent->getConnectionName())
 | 
						|
            ->setTable($table)
 | 
						|
            ->forceFill($attributes)
 | 
						|
            ->syncOriginal();
 | 
						|
 | 
						|
        // We store off the parent instance so we will access the timestamp column names
 | 
						|
        // for the model, since the pivot model timestamps aren't easily configurable
 | 
						|
        // from the developer's point of view. We can use the parents to get these.
 | 
						|
        $instance->pivotParent = $parent;
 | 
						|
 | 
						|
        $instance->exists = $exists;
 | 
						|
 | 
						|
        return $instance;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Create a new pivot model from raw values returned from a query.
 | 
						|
     *
 | 
						|
     * @param  \Illuminate\Database\Eloquent\Model  $parent
 | 
						|
     * @param  array  $attributes
 | 
						|
     * @param  string  $table
 | 
						|
     * @param  bool  $exists
 | 
						|
     * @return static
 | 
						|
     */
 | 
						|
    public static function fromRawAttributes(Model $parent, $attributes, $table, $exists = false)
 | 
						|
    {
 | 
						|
        $instance = static::fromAttributes($parent, [], $table, $exists);
 | 
						|
 | 
						|
        $instance->timestamps = $instance->hasTimestampAttributes($attributes);
 | 
						|
 | 
						|
        $instance->setRawAttributes($attributes, $exists);
 | 
						|
 | 
						|
        return $instance;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set the keys for a save update query.
 | 
						|
     *
 | 
						|
     * @param  \Illuminate\Database\Eloquent\Builder  $query
 | 
						|
     * @return \Illuminate\Database\Eloquent\Builder
 | 
						|
     */
 | 
						|
    protected function setKeysForSaveQuery(Builder $query)
 | 
						|
    {
 | 
						|
        if (isset($this->attributes[$this->getKeyName()])) {
 | 
						|
            return parent::setKeysForSaveQuery($query);
 | 
						|
        }
 | 
						|
 | 
						|
        $query->where($this->foreignKey, $this->getOriginal(
 | 
						|
            $this->foreignKey, $this->getAttribute($this->foreignKey)
 | 
						|
        ));
 | 
						|
 | 
						|
        return $query->where($this->relatedKey, $this->getOriginal(
 | 
						|
            $this->relatedKey, $this->getAttribute($this->relatedKey)
 | 
						|
        ));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Delete the pivot model record from the database.
 | 
						|
     *
 | 
						|
     * @return int
 | 
						|
     */
 | 
						|
    public function delete()
 | 
						|
    {
 | 
						|
        if (isset($this->attributes[$this->getKeyName()])) {
 | 
						|
            return (int) parent::delete();
 | 
						|
        }
 | 
						|
 | 
						|
        if ($this->fireModelEvent('deleting') === false) {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        $this->touchOwners();
 | 
						|
 | 
						|
        return tap($this->getDeleteQuery()->delete(), function () {
 | 
						|
            $this->exists = false;
 | 
						|
 | 
						|
            $this->fireModelEvent('deleted', false);
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the query builder for a delete operation on the pivot.
 | 
						|
     *
 | 
						|
     * @return \Illuminate\Database\Eloquent\Builder
 | 
						|
     */
 | 
						|
    protected function getDeleteQuery()
 | 
						|
    {
 | 
						|
        return $this->newQueryWithoutRelationships()->where([
 | 
						|
            $this->foreignKey => $this->getOriginal($this->foreignKey, $this->getAttribute($this->foreignKey)),
 | 
						|
            $this->relatedKey => $this->getOriginal($this->relatedKey, $this->getAttribute($this->relatedKey)),
 | 
						|
        ]);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the table associated with the model.
 | 
						|
     *
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getTable()
 | 
						|
    {
 | 
						|
        if (! isset($this->table)) {
 | 
						|
            $this->setTable(str_replace(
 | 
						|
                '\\', '', Str::snake(Str::singular(class_basename($this)))
 | 
						|
            ));
 | 
						|
        }
 | 
						|
 | 
						|
        return $this->table;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the foreign key column name.
 | 
						|
     *
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getForeignKey()
 | 
						|
    {
 | 
						|
        return $this->foreignKey;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the "related key" column name.
 | 
						|
     *
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getRelatedKey()
 | 
						|
    {
 | 
						|
        return $this->relatedKey;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the "related key" column name.
 | 
						|
     *
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getOtherKey()
 | 
						|
    {
 | 
						|
        return $this->getRelatedKey();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Set the key names for the pivot model instance.
 | 
						|
     *
 | 
						|
     * @param  string  $foreignKey
 | 
						|
     * @param  string  $relatedKey
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function setPivotKeys($foreignKey, $relatedKey)
 | 
						|
    {
 | 
						|
        $this->foreignKey = $foreignKey;
 | 
						|
 | 
						|
        $this->relatedKey = $relatedKey;
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Determine if the pivot model or given attributes has timestamp attributes.
 | 
						|
     *
 | 
						|
     * @param  array|null  $attributes
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    public function hasTimestampAttributes($attributes = null)
 | 
						|
    {
 | 
						|
        return array_key_exists($this->getCreatedAtColumn(), $attributes ?? $this->attributes);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the name of the "created at" column.
 | 
						|
     *
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getCreatedAtColumn()
 | 
						|
    {
 | 
						|
        return $this->pivotParent
 | 
						|
            ? $this->pivotParent->getCreatedAtColumn()
 | 
						|
            : parent::getCreatedAtColumn();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the name of the "updated at" column.
 | 
						|
     *
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function getUpdatedAtColumn()
 | 
						|
    {
 | 
						|
        return $this->pivotParent
 | 
						|
            ? $this->pivotParent->getUpdatedAtColumn()
 | 
						|
            : parent::getUpdatedAtColumn();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the queueable identity for the entity.
 | 
						|
     *
 | 
						|
     * @return mixed
 | 
						|
     */
 | 
						|
    public function getQueueableId()
 | 
						|
    {
 | 
						|
        if (isset($this->attributes[$this->getKeyName()])) {
 | 
						|
            return $this->getKey();
 | 
						|
        }
 | 
						|
 | 
						|
        return sprintf(
 | 
						|
            '%s:%s:%s:%s',
 | 
						|
            $this->foreignKey, $this->getAttribute($this->foreignKey),
 | 
						|
            $this->relatedKey, $this->getAttribute($this->relatedKey)
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get a new query to restore one or more models by their queueable IDs.
 | 
						|
     *
 | 
						|
     * @param  int[]|string[]|string  $ids
 | 
						|
     * @return \Illuminate\Database\Eloquent\Builder
 | 
						|
     */
 | 
						|
    public function newQueryForRestoration($ids)
 | 
						|
    {
 | 
						|
        if (is_array($ids)) {
 | 
						|
            return $this->newQueryForCollectionRestoration($ids);
 | 
						|
        }
 | 
						|
 | 
						|
        if (! Str::contains($ids, ':')) {
 | 
						|
            return parent::newQueryForRestoration($ids);
 | 
						|
        }
 | 
						|
 | 
						|
        $segments = explode(':', $ids);
 | 
						|
 | 
						|
        return $this->newQueryWithoutScopes()
 | 
						|
            ->where($segments[0], $segments[1])
 | 
						|
            ->where($segments[2], $segments[3]);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get a new query to restore multiple models by their queueable IDs.
 | 
						|
     *
 | 
						|
     * @param  int[]|string[]  $ids
 | 
						|
     * @return \Illuminate\Database\Eloquent\Builder
 | 
						|
     */
 | 
						|
    protected function newQueryForCollectionRestoration(array $ids)
 | 
						|
    {
 | 
						|
        $ids = array_values($ids);
 | 
						|
 | 
						|
        if (! Str::contains($ids[0], ':')) {
 | 
						|
            return parent::newQueryForRestoration($ids);
 | 
						|
        }
 | 
						|
 | 
						|
        $query = $this->newQueryWithoutScopes();
 | 
						|
 | 
						|
        foreach ($ids as $id) {
 | 
						|
            $segments = explode(':', $id);
 | 
						|
 | 
						|
            $query->orWhere(function ($query) use ($segments) {
 | 
						|
                return $query->where($segments[0], $segments[1])
 | 
						|
                    ->where($segments[2], $segments[3]);
 | 
						|
            });
 | 
						|
        }
 | 
						|
 | 
						|
        return $query;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Unset all the loaded relations for the instance.
 | 
						|
     *
 | 
						|
     * @return $this
 | 
						|
     */
 | 
						|
    public function unsetRelations()
 | 
						|
    {
 | 
						|
        $this->pivotParent = null;
 | 
						|
        $this->relations = [];
 | 
						|
 | 
						|
        return $this;
 | 
						|
    }
 | 
						|
}
 |