Passed
Push — master ( 666edc...4ba5ff )
by Stephen
06:52
created

QueryBuilder   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 35
c 1
b 0
f 0
dl 0
loc 194
rs 10
wmc 16

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getNextModelId() 0 5 1
A getNextModel() 0 3 1
A __construct() 0 4 1
A selectRawJson() 0 6 1
A setTableAndKeyNames() 0 6 2
A concatColumns() 0 8 3
A whereLike() 0 5 1
A getPreviousModelId() 0 5 1
A getPreviousModel() 0 3 1
A orderByCreatedAt() 0 5 1
A ifStatement() 0 3 1
A orWhereLike() 0 5 1
A getFlatArray() 0 5 1
1
<?php
2
3
namespace Sfneal\Builders;
4
5
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Query\Builder;
9
use Sfneal\Builders\Traits\CountAndPaginate;
10
11
class QueryBuilder extends EloquentBuilder
12
{
13
    use CountAndPaginate;
14
15
    /**
16
     * @var string Declare a custom MySQL select string to be used by selectRawJson()
17
     */
18
    protected $selectRawJson;
19
20
    /**
21
     * @var Model
22
     */
23
    protected $targetModel;
24
25
    /**
26
     * @var string Name of the User model's table
27
     */
28
    protected $tableName;
29
30
    /**
31
     * @var string Name of the User model's primary key
32
     */
33
    protected $primaryKeyName;
34
35
    /**
36
     * UserBuilder constructor.
37
     *
38
     * @param Builder $query
39
     */
40
    public function __construct(Builder $query)
41
    {
42
        $this->setTableAndKeyNames();
43
        parent::__construct($query);
44
    }
45
46
    /**
47
     * Set the $tableName & $primaryKeyName properties.
48
     *
49
     * @return void
50
     */
51
    private function setTableAndKeyNames(): void
52
    {
53
        // Only declare table & pk if the target model is declared
54
        if (isset($this->targetModel)) {
55
            $this->tableName = $this->targetModel::getTableName();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->targetModel::getTableName() can also be of type Illuminate\Database\Eloquent\Builder. However, the property $tableName is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
56
            $this->primaryKeyName = $this->targetModel::getPrimaryKeyName();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->targetModel::getPrimaryKeyName() can also be of type Illuminate\Database\Eloquent\Builder. However, the property $primaryKeyName is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
57
        }
58
    }
59
60
    /**
61
     * Retrieve a concatenation string that combines two columns in a table into a single column.
62
     *
63
     * @param string $column1
64
     * @param string $column2
65
     * @param string $delimiter
66
     * @return string
67
     */
68
    protected function concatColumns(string $column1, string $column2, string $delimiter = ' '): string
69
    {
70
        // Prepend table name if its been declared
71
        $column1 = (isset($this->tableName)) ? "{$this->tableName}.{$column1}" : $column1;
72
        $column2 = (isset($this->tableName)) ? "{$this->tableName}.{$column2}" : $column2;
73
74
        // Return concatenate the two columns using the delimiter
75
        return "concat({$column1}, '{$delimiter}', {$column2})";
76
    }
77
78
    /**
79
     * Retrieve a MySQL if statement that can be used within a query.
80
     *
81
     * @param string $condition
82
     * @param string $expr_true
83
     * @param string $expr_false
84
     * @return string
85
     */
86
    protected function ifStatement(string $condition, string $expr_true, string $expr_false): string
87
    {
88
        return "if({$condition}, {$expr_true}, {$expr_false})";
89
    }
90
91
    /**
92
     * Wildcard where like query to determine if any part of the value is found.
93
     *
94
     * @param string $column
95
     * @param $value
96
     * @return $this
97
     */
98
    public function whereLike(string $column, $value)
99
    {
100
        $this->where($column, 'LIKE', '%'.$value.'%');
101
102
        return $this;
103
    }
104
105
    /**
106
     * Wildcard or where like query to determine if any part of the value is found.
107
     *
108
     * @param string $column
109
     * @param $value
110
     * @return $this
111
     */
112
    public function orWhereLike(string $column, $value)
113
    {
114
        $this->orWhere($column, 'LIKE', '%'.$value.'%');
115
116
        return $this;
117
    }
118
119
    /**
120
     * Retrieve a flat, single-dimensional array of results without keys.
121
     *
122
     * @param string $column
123
     * @return array
124
     */
125
    public function getFlatArray(string $column)
126
    {
127
        return array_map(function ($collection) use ($column) {
128
            return $collection[$column];
129
        }, $this->distinct()->get($column)->toArray());
0 ignored issues
show
Bug introduced by
The method distinct() does not exist on Sfneal\Builders\QueryBuilder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

129
        }, $this->/** @scrutinizer ignore-call */ distinct()->get($column)->toArray());
Loading history...
130
    }
131
132
    /**
133
     * Retrieve raw query results formatted for Ajax select2 form inputs.
134
     *
135
     * @param string|null $raw
136
     * @return $this
137
     */
138
    public function selectRawJson(string $raw = null)
139
    {
140
        $this->withoutGlobalScopes();
141
        $this->selectRaw($raw ?? $this->selectRawJson);
0 ignored issues
show
Bug introduced by
The method selectRaw() does not exist on Sfneal\Builders\QueryBuilder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

141
        $this->/** @scrutinizer ignore-call */ 
142
               selectRaw($raw ?? $this->selectRawJson);
Loading history...
142
143
        return $this;
144
    }
145
146
    /**
147
     * Order query results by the 'created_at' column.
148
     *
149
     * @param string $direction
150
     * @return $this
151
     */
152
    public function orderByCreatedAt(string $direction = 'desc')
153
    {
154
        $this->orderBy('created_at', $direction);
0 ignored issues
show
Bug introduced by
The method orderBy() does not exist on Sfneal\Builders\QueryBuilder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

154
        $this->/** @scrutinizer ignore-call */ 
155
               orderBy('created_at', $direction);
Loading history...
155
156
        return $this;
157
    }
158
159
    /**
160
     * Retrieve the 'next' Model in the database.
161
     *
162
     * @param int|null $model_id
163
     * @return QueryBuilder|Collection|Model|null
164
     */
165
    public function getNextModel(int $model_id = null)
166
    {
167
        return $this->find($this->getNextModelId($model_id));
168
    }
169
170
    /**
171
     * Retrieve the 'previous' Model in the database.
172
     *
173
     * @param int|null $model_id
174
     * @return QueryBuilder|Collection|Model|null
175
     */
176
    public function getPreviousModel(int $model_id = null)
177
    {
178
        return $this->find($this->getPreviousModelId($model_id));
179
    }
180
181
    /**
182
     * Retrieve the 'next' Model's ID.
183
     *
184
     * @param int|null $model_id
185
     * @return mixed
186
     */
187
    public function getNextModelId(int $model_id = null)
188
    {
189
        return $this
190
            ->where($this->model->getKeyName(), '>', $model_id ?? $this->model->getKey())
191
            ->min($this->model->getKeyName());
0 ignored issues
show
Bug introduced by
The method min() does not exist on Sfneal\Builders\QueryBuilder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

191
            ->/** @scrutinizer ignore-call */ min($this->model->getKeyName());
Loading history...
192
    }
193
194
    /**
195
     * Retrieve the 'previous' Model's ID.
196
     *
197
     * @param int|null $model_id
198
     * @return mixed
199
     */
200
    public function getPreviousModelId(int $model_id = null)
201
    {
202
        return $this
203
            ->where($this->model->getKeyName(), '<', $model_id ?? $this->model->getKey())
204
            ->max($this->model->getKeyName());
0 ignored issues
show
Bug introduced by
The method max() does not exist on Sfneal\Builders\QueryBuilder. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

204
            ->/** @scrutinizer ignore-call */ max($this->model->getKeyName());
Loading history...
205
    }
206
}
207