Completed
Pull Request — master (#443)
by Ilya
15:00
created

QueryBuilder::__get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Spatie\QueryBuilder;
4
5
use ArrayAccess;
6
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\Relations\Relation;
9
use Illuminate\Http\Request;
10
use Illuminate\Support\Collection;
11
use Illuminate\Support\Traits\ForwardsCalls;
12
use LogicException;
13
use Spatie\QueryBuilder\Concerns\AddsFieldsToQuery;
14
use Spatie\QueryBuilder\Concerns\AddsIncludesToQuery;
15
use Spatie\QueryBuilder\Concerns\AppendsAttributesToResults;
16
use Spatie\QueryBuilder\Concerns\FiltersQuery;
17
use Spatie\QueryBuilder\Concerns\SortsQuery;
18
use Spatie\QueryBuilder\Exceptions\InvalidSubject;
19
20
/**
21
 * @mixin EloquentBuilder
22
 */
23
class QueryBuilder implements ArrayAccess
24
{
25
    use FiltersQuery,
26
        SortsQuery,
27
        AddsIncludesToQuery,
28
        AddsFieldsToQuery,
29
        AppendsAttributesToResults,
30
        ForwardsCalls;
31
32
    /** @var QueryBuilderRequest */
33
    protected $request;
34
35
    /** @var EloquentBuilder|Relation */
36
    protected $subject;
37
38
    public function __construct($subject, ?Request $request = null)
39
    {
40
        $this->initializeSubject($subject)
41
            ->initializeRequest($request ?? app(Request::class));
42
    }
43
44
    protected function initializeSubject($subject): self
45
    {
46
        throw_unless(
47
            $subject instanceof EloquentBuilder || $subject instanceof Relation,
48
            InvalidSubject::make($subject)
49
        );
50
51
        $this->subject = $subject;
52
53
        return $this;
54
    }
55
56
    protected function initializeRequest(?Request $request = null): self
57
    {
58
        $this->request = $request
59
            ? QueryBuilderRequest::fromRequest($request)
60
            : app(QueryBuilderRequest::class);
61
62
        return $this;
63
    }
64
65
    public function getEloquentBuilder(): EloquentBuilder
66
    {
67
        if ($this->subject instanceof EloquentBuilder) {
68
            return $this->subject;
69
        }
70
71
        if ($this->subject instanceof Relation) {
72
            return $this->subject->getQuery();
73
        }
74
75
        throw InvalidSubject::make($this->subject);
76
    }
77
78
    public function getSubject()
79
    {
80
        return $this->subject;
81
    }
82
83
    /**
84
     * @param EloquentBuilder|Relation|string $subject
85
     * @param Request|null $request
86
     * @return static
87
     */
88
    public static function for($subject, ?Request $request = null): self
89
    {
90
        if (is_subclass_of($subject, Model::class)) {
91
            $subject = $subject::query();
92
        }
93
94
        return new static($subject, $request);
95
    }
96
97
    public function __call($name, $arguments)
98
    {
99
        $result = $this->forwardCallTo($this->subject, $name, $arguments);
100
101
        if ($result === $this->subject) {
102
            return $this;
103
        }
104
105
        if ($result instanceof Model) {
106
            $this->addAppendsToResults(collect([$result]));
107
        }
108
109
        if ($result instanceof Collection) {
110
            $this->addAppendsToResults($result);
111
        }
112
113
        return $result;
114
    }
115
116
    public function __get($name)
117
    {
118
        return $this->subject->{$name};
119
    }
120
121
    public function __set($name, $value)
122
    {
123
        $this->subject->{$name} = $value;
124
    }
125
126
    public function offsetExists($offset)
127
    {
128
        return isset($this->subject[$offset]);
129
    }
130
131
    public function offsetGet($offset)
132
    {
133
        return $this->subject[$offset];
134
    }
135
136
    public function offsetSet($offset, $value)
137
    {
138
        $this->subject[$offset] = $value;
139
    }
140
141
    public function offsetUnset($offset)
142
    {
143
        unset($this->subject[$offset]);
144
    }
145
}
146