| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace JPNut\Versioning; |
||||
| 4 | |||||
| 5 | use Carbon\Carbon; |
||||
| 6 | use Illuminate\Database\Eloquent\Builder; |
||||
| 7 | use Illuminate\Database\Eloquent\Model; |
||||
| 8 | use Illuminate\Database\Eloquent\Scope; |
||||
| 9 | use Illuminate\Database\Query\JoinClause; |
||||
| 10 | |||||
| 11 | class VersioningScope implements Scope |
||||
| 12 | { |
||||
| 13 | /** |
||||
| 14 | * All of the extensions to be added to the builder. |
||||
| 15 | * |
||||
| 16 | * @var array |
||||
| 17 | */ |
||||
| 18 | protected array $extensions = ['AtVersion', 'AtTime']; |
||||
| 19 | |||||
| 20 | /** |
||||
| 21 | * Apply the scope to a given Eloquent query builder. |
||||
| 22 | * |
||||
| 23 | * @param \Illuminate\Database\Eloquent\Builder $builder |
||||
| 24 | * @param \Illuminate\Database\Eloquent\Model|\JPNut\Versioning\Versionable $model |
||||
| 25 | * |
||||
| 26 | * @return void |
||||
| 27 | */ |
||||
| 28 | public function apply(Builder $builder, Model $model) |
||||
| 29 | { |
||||
| 30 | // |
||||
| 31 | } |
||||
| 32 | |||||
| 33 | /** |
||||
| 34 | * Extend the query builder with the needed functions. |
||||
| 35 | * |
||||
| 36 | * @param \Illuminate\Database\Eloquent\Builder $builder |
||||
| 37 | * |
||||
| 38 | * @return void |
||||
| 39 | */ |
||||
| 40 | public function extend(Builder $builder) |
||||
| 41 | { |
||||
| 42 | foreach ($this->extensions as $extension) { |
||||
| 43 | $this->{"add{$extension}"}($builder); |
||||
| 44 | } |
||||
| 45 | } |
||||
| 46 | |||||
| 47 | /** |
||||
| 48 | * @param \Illuminate\Database\Eloquent\Builder $builder |
||||
| 49 | * |
||||
| 50 | * @return void |
||||
| 51 | */ |
||||
| 52 | protected function addAtVersion(Builder $builder) |
||||
| 53 | { |
||||
| 54 | $builder->macro( |
||||
| 55 | 'atVersion', |
||||
| 56 | function (Builder $builder, $version) { |
||||
| 57 | /** @var \Illuminate\Database\Eloquent\Model|\JPNut\Versioning\Versionable $model */ |
||||
| 58 | $model = $builder->getModel(); |
||||
| 59 | |||||
| 60 | $this->remove($builder, $builder->getModel()); |
||||
| 61 | |||||
| 62 | $builder |
||||
| 63 | ->join( |
||||
| 64 | $model->getVersionTable(), |
||||
| 65 | function ($join) use ($model, $version) { |
||||
| 66 | $join->on( |
||||
| 67 | $model->getQualifiedKeyName(), '=', $model->getQualifiedVersionTableForeignKeyName() |
||||
|
0 ignored issues
–
show
|
|||||
| 68 | ) |
||||
| 69 | ->where($model->getQualifiedVersionTableKeyName(), '=', $version); |
||||
| 70 | } |
||||
| 71 | ) |
||||
| 72 | ->select( |
||||
| 73 | $model->defaultVersionSelect() |
||||
| 74 | ); |
||||
| 75 | |||||
| 76 | return $builder; |
||||
| 77 | } |
||||
| 78 | ); |
||||
| 79 | } |
||||
| 80 | |||||
| 81 | /** |
||||
| 82 | * Remove the scope from the given Eloquent query builder. |
||||
| 83 | * |
||||
| 84 | * @param \Illuminate\Database\Eloquent\Builder $builder |
||||
| 85 | * @param \Illuminate\Database\Eloquent\Model|\JPNut\Versioning\Versionable $model |
||||
| 86 | * |
||||
| 87 | * @return void |
||||
| 88 | */ |
||||
| 89 | public function remove(Builder $builder, Model $model) |
||||
| 90 | { |
||||
| 91 | $table = $model->getVersionTable(); |
||||
| 92 | |||||
| 93 | $query = $builder->getQuery(); |
||||
| 94 | |||||
| 95 | $query->joins = collect($query->joins)->reject( |
||||
| 96 | function ($join) use ($table) { |
||||
| 97 | return $this->isVersionJoinConstraint($join, $table); |
||||
|
0 ignored issues
–
show
It seems like
$table can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $table of JPNut\Versioning\Version...VersionJoinConstraint() does only seem to accept string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 98 | } |
||||
| 99 | )->values()->all(); |
||||
| 100 | } |
||||
| 101 | |||||
| 102 | /** |
||||
| 103 | * Determine if the given join clause is a version constraint. |
||||
| 104 | * |
||||
| 105 | * @param \Illuminate\Database\Query\JoinClause $join |
||||
| 106 | * @param string $table |
||||
| 107 | * |
||||
| 108 | * @return bool |
||||
| 109 | */ |
||||
| 110 | protected function isVersionJoinConstraint(JoinClause $join, string $table) |
||||
| 111 | { |
||||
| 112 | return $join->type === 'inner' && $join->table === $table; |
||||
| 113 | } |
||||
| 114 | |||||
| 115 | /** |
||||
| 116 | * @param \Illuminate\Database\Eloquent\Builder $builder |
||||
| 117 | * |
||||
| 118 | * @return void |
||||
| 119 | */ |
||||
| 120 | protected function addAtTime(Builder $builder) |
||||
| 121 | { |
||||
| 122 | $builder->macro( |
||||
| 123 | 'atTime', |
||||
| 124 | function (Builder $builder, Carbon $moment) { |
||||
| 125 | /** @var \Illuminate\Database\Eloquent\Model|\JPNut\Versioning\Versionable $model */ |
||||
| 126 | $model = $builder->getModel(); |
||||
| 127 | |||||
| 128 | $this->remove($builder, $builder->getModel()); |
||||
| 129 | |||||
| 130 | $createdAt = $model->getQualifiedVersionTableCreatedAtName(); |
||||
| 131 | |||||
| 132 | $builder |
||||
| 133 | ->join( |
||||
| 134 | $model->getVersionTable(), |
||||
| 135 | function ($join) use ($model, $moment, $createdAt) { |
||||
| 136 | $join->on( |
||||
| 137 | $model->getQualifiedKeyName(), '=', $model->getQualifiedVersionTableForeignKeyName() |
||||
| 138 | ) |
||||
| 139 | ->where($createdAt, '<=', $moment) |
||||
| 140 | ->orderBy($createdAt, 'desc') |
||||
| 141 | ->limit(1); |
||||
| 142 | } |
||||
| 143 | ) |
||||
| 144 | ->orderBy($createdAt, 'desc') |
||||
|
0 ignored issues
–
show
It seems like
$createdAt can also be of type Illuminate\Database\Eloquent\Builder; however, parameter $column of Illuminate\Database\Query\Builder::orderBy() does only seem to accept Closure|Illuminate\Database\Query\Builder|string, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 145 | ->limit(1) |
||||
| 146 | ->select( |
||||
| 147 | $model->defaultVersionSelect() |
||||
| 148 | ); |
||||
| 149 | |||||
| 150 | return $builder; |
||||
| 151 | } |
||||
| 152 | ); |
||||
| 153 | } |
||||
| 154 | } |
||||
| 155 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.