VersioningScope::extend()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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
Bug introduced by
The method getQualifiedKeyName() does not exist on JPNut\Versioning\Versionable. Did you maybe mean getQualifiedVersionKeyName()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

67
                                $model->/** @scrutinizer ignore-call */ 
68
                                        getQualifiedKeyName(), '=', $model->getQualifiedVersionTableForeignKeyName()

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.

Loading history...
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
Bug introduced by
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 ignore-type  annotation

97
                return $this->isVersionJoinConstraint($join, /** @scrutinizer ignore-type */ $table);
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
Bug introduced by
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 ignore-type  annotation

144
                    ->orderBy(/** @scrutinizer ignore-type */ $createdAt, 'desc')
Loading history...
145
                    ->limit(1)
146
                    ->select(
147
                        $model->defaultVersionSelect()
148
                    );
149
150
                return $builder;
151
            }
152
        );
153
    }
154
}
155