File: /home/posscale/public_html/printmanager/vendor/filament/tables/src/Table/Concerns/HasQuery.php
<?php
namespace Filament\Tables\Table\Concerns;
use Closure;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\HasOneOrManyThrough;
use Illuminate\Database\Eloquent\Relations\Relation;
use function Livewire\invade;
trait HasQuery
{
protected Builder | Closure | null $query = null;
protected string | Closure | null $inverseRelationship = null;
protected ?Closure $getRelationshipUsing = null;
/**
* @var array<Closure>
*/
protected array $queryScopes = [];
public function query(Builder | Closure | null $query): static
{
$this->query = $query;
return $this;
}
public function modifyQueryUsing(Closure $callback): static
{
$this->queryScopes[] = $callback;
return $this;
}
public function relationship(?Closure $relationship): static
{
$this->getRelationshipUsing = $relationship;
return $this;
}
public function inverseRelationship(string | Closure | null $name): static
{
$this->inverseRelationship = $name;
return $this;
}
protected function applyQueryScopes(Builder $query): Builder
{
foreach ($this->queryScopes as $scope) {
$query = $this->evaluate($scope, ['query' => $query]) ?? $query;
}
return $query;
}
public function getQuery(): Builder | Relation
{
if ($query = $this->evaluate($this->query)) {
return $this->applyQueryScopes($query->clone());
}
if ($query = $this->getRelationshipQuery()) {
return $this->applyQueryScopes($query->clone());
}
$livewireClass = $this->getLivewire()::class;
throw new Exception("Table [{$livewireClass}] must have a [query()].");
}
public function getRelationshipQuery(): ?Builder
{
$relationship = $this->getRelationship();
if (! $relationship) {
return null;
}
$query = $relationship->getQuery();
if ($relationship instanceof (class_exists(HasOneOrManyThrough::class) ? HasOneOrManyThrough::class : HasManyThrough::class)) {
// https://github.com/laravel/framework/issues/4962
$query->select($query->getModel()->getTable() . '.*');
return $query;
}
if ($relationship instanceof BelongsToMany) {
// https://github.com/laravel/framework/issues/4962
if (! $this->allowsDuplicates()) {
$this->selectPivotDataInQuery($query);
}
// https://github.com/filamentphp/filament/issues/2079
$query->withCasts(
app($relationship->getPivotClass())->getCasts(),
);
}
return $query;
}
public function selectPivotDataInQuery(Builder | Relation $query): Builder | Relation
{
/** @var BelongsToMany $relationship */
$relationship = $this->getRelationship();
$columns = [
$relationship->getTable() . '.*',
$query->getModel()->getTable() . '.*',
];
if (! $this->allowsDuplicates()) {
$columns = [
...invade($relationship)->aliasedPivotColumns(),
...$columns,
];
}
$query->select($columns);
return $query;
}
public function getRelationship(): Relation | Builder | null
{
return $this->evaluate($this->getRelationshipUsing);
}
public function getInverseRelationship(): ?string
{
$relationship = $this->getRelationship();
if (! $relationship) {
return null;
}
$inverseRelationship = $this->evaluate($this->inverseRelationship);
if ($inverseRelationship) {
return $inverseRelationship;
}
$parentModelClass = str(class_basename($relationship->getParent()::class));
if ($relationship instanceof HasOneOrMany) {
return (string) $parentModelClass->singular()->camel();
}
return (string) $parentModelClass->plural()->camel();
}
public function getInverseRelationshipFor(Model $record): Relation | Builder
{
return $record->{$this->getInverseRelationship()}();
}
}