Completed
Push — master ( edd149...e1a63f )
by Sander
02:39
created

PosttypeBuilder::addArrayOfWheres()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Sanderdekroon\Parlant\Builder;
4
5
use InvalidArgumentException;
6
use Sanderdekroon\Parlant\Container;
7
use Sanderdekroon\Parlant\Grammar\PosttypeGrammar;
8
use Sanderdekroon\Parlant\Compiler\PosttypeCompiler;
9
use Sanderdekroon\Parlant\Configurator\ParlantConfigurator;
10
use Sanderdekroon\Parlant\Configurator\ConfiguratorInterface;
11
12
class PosttypeBuilder implements BuilderInterface
13
{
14
    use BuildsQueries, QueriesMeta, QueriesTaxonomies;
15
16
17
    protected $grammar;
18
    
19
    protected $compiler;
20
    protected $bindings;
21
22
    protected $configuration;
23
24
25
    public function __construct(Container $container = null)
26
    {
27
        $this->grammar = new PosttypeGrammar; // Replace via DI
28
        $this->compiler = new PosttypeCompiler($this->grammar); // Replace via DI
29
        $this->bindings = $container ?: new Container;
30
    }
31
32
33
    public function configure($configuration)
34
    {
35
        // If the supplied configuration is an instance of the ConfiguratorInterface
36
        // we can add it directly to the PosttypeBuilder. This way a developer
37
        // can supply their own configurator implementation.
38
        if ($configuration instanceof ConfiguratorInterface) {
39
            return $this->configuration = $configuration;
40
        }
41
42
        // If the developer wants to add additional configuration but has not
43
        // supplied an instance of the ConfiguratorInterface, we'll create
44
        // a new instance of our own implementation of the configurator.
45
        if (is_null($this->configuration)) {
46
            $this->configuration = new ParlantConfigurator;
47
        }
48
49
        return $this->configuration->add($configuration);
50
    }
51
52
53
    public function setConfig($key, $value)
54
    {
55
        if ($this->requiresConfiguration()) {
56
            $this->applyDefaultConfiguration();
57
        }
58
59
        return $this->updateConfiguration($key, $value);
60
    }
61
62
63
    protected function updateConfiguration($key, $value)
64
    {
65
        $this->configuration->add($key, $value);
66
67
        return $this;
68
    }
69
70
    /**
71
     * Determine if the builder requires additional configuration.
72
     * @return bool
73
     */
74
    protected function requiresConfiguration()
75
    {
76
        return is_null($this->configuration);
77
    }
78
79
    /**
80
     * Fill the configuration property with an instance of our ParlantConfigurator.
81
     * @return ParlantConfigurator
82
     */
83
    protected function applyDefaultConfiguration()
84
    {
85
        return $this->configuration = new ParlantConfigurator;
86
    }
87
88
    /**
89
     * Set the posttype the developer is querying.
90
     * @param  string $posttype
91
     * @return $this
92
     */
93
    public function type($posttype)
94
    {
95
        // Since this is the entry method (for now), we'll assume the developer allready
96
        // has supplied some form of configuration. If nothing is found, we'll create a
97
        // new instance of our ParlantConfigurator which sets some default settings.
98
        if ($this->requiresConfiguration()) {
99
            $this->applyDefaultConfiguration();
100
        }
101
102
        $this->setBinding('post_type', $posttype);
103
        return $this;
104
    }
105
106
107
    public function where($column, $operator = null, $value = null, $boolean = 'and')
108
    {
109
        // If the column is an array, we will assume it is an array of key-value pairs
110
        // and can add them each as a where clause. We will maintain the boolean we
111
        // received when the method was called and pass it into the nested where.
112
        if (is_array($column)) {
113
            return $this->addArrayOfWheres($column, $boolean);
0 ignored issues
show
Unused Code introduced by
The call to Sanderdekroon\Parlant\Bu...der::addArrayOfWheres() has too many arguments starting with $boolean. ( Ignorable by Annotation )

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

113
            return $this->/** @scrutinizer ignore-call */ addArrayOfWheres($column, $boolean);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
114
        }
115
116
        // Here we will make some assumptions about the operator. If only 2 values are
117
        // passed to the method, we will assume that the operator is an equals sign
118
        // and keep going. Otherwise, we'll require the operator to be passed in.
119
        list($value, $operator) = $this->prepareValueAndOperator(
120
            $value,
121
            $operator,
122
            (func_num_args() == 2 || is_null($value)) //Is this the best solution?
123
        );
124
125
        // If the given operator is not found in the list of valid operators we will
126
        // assume that the developer is just short-cutting the '=' operators and
127
        // we will set the operators to '=' and set the values appropriately.
128
        if ($this->invalidOperator($operator)) {
129
            list($value, $operator) = [$operator, '='];
130
        }
131
132
133
        // If the value is "null", we will just assume the developer wants to add a
134
        // where null clause to the query. So, we will allow a short-cut here to
135
        // that method for convenience so the developer doesn't have to check.
136
        // if (is_null($value)) {
137
        //     return $this->whereNull($column, $boolean, $operator != '=');
138
        // }
139
140
        // Now that we are working with just a simple query we can put the elements
141
        // in our array and add the query binding to our array of bindings that
142
        // will be bound to each SQL statements when it is finally executed.
143
        $type = 'Basic';
144
145
        $this->appendBinding('wheres', compact(
146
            'type',
147
            'column',
148
            'operator',
149
            'value',
150
            'boolean'
151
        ));
152
153
        return $this;
154
    }
155
156
    /**
157
     * Add an array of where statements. The array should contain a numeric array
158
     * where the values can be used as arguments for the where() method.
159
     * @param array $wheres
160
     */
161
    protected function addArrayOfWheres($wheres)
162
    {
163
        foreach ($wheres as $where) {
164
            $this->where(...$where);
0 ignored issues
show
Bug introduced by
$where is expanded, but the parameter $column of Sanderdekroon\Parlant\Bu...osttypeBuilder::where() does not expect variable arguments. ( Ignorable by Annotation )

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

164
            $this->where(/** @scrutinizer ignore-type */ ...$where);
Loading history...
165
        }
166
167
        return $this;
168
    }
169
170
    /**
171
     * Limit the number of posts to return to the $number
172
     * @param  int $number
173
     * @return $this
174
     */
175
    public function limit($number)
176
    {
177
        $this->setBinding('limit', (int)$number);
178
        return $this;
179
    }
180
181
    /**
182
     * Set the post offset.
183
     * @param  int $number
184
     * @return $this
185
     */
186
    public function offset($number)
187
    {
188
        $this->setBinding('offset', (int)$number);
189
        return $this;
190
    }
191
192
    /**
193
     * Prepare the value and operator. If $useDefault is true, return the default operator (=)
194
     * Throws an exception if the operator is not supported with the current grammer.
195
     * @param  mixed        $value
196
     * @param  string       $operator
197
     * @param  boolean      $useDefault
198
     * @throws InvalidArgumentException
199
     * @return array
200
     */
201
    protected function prepareValueAndOperator($value, $operator, $useDefault = false, $termDefault = false)
202
    {
203
        if ($useDefault) {
204
            return [$operator, $termDefault ? 'IN' : '='];
205
        }
206
207
        if ($this->invalidOperator($operator) && !is_null($value)) {
208
            throw new InvalidArgumentException('Illegal operator and value combination.');
209
        }
210
211
        return [$value, $operator];
212
    }
213
214
    /**
215
     * Determine if an operator is invalid or unsupported
216
     * @param  string $operator
217
     * @return bool
218
     */
219
    private function invalidOperator($operator)
220
    {
221
        return !in_array($operator, $this->grammar->getOperators());
222
    }
223
224
    /**
225
     * Set an query binding
226
     * @param  string    $key   @todo validate if the $key is valid with the grammar
227
     * @param  mixed     $data
228
     * @return bool
229
     */
230
    private function setBinding($key, $data)
231
    {
232
        return $this->bindings->bind($key, $data);
233
    }
234
235
    /**
236
     * Append an query binding
237
     * @param  string   $key  @todo validate if the $key is valid with the grammar
238
     * @param  mixed    $data
239
     * @return bool
240
     */
241
    private function appendBinding($key, $data)
242
    {
243
        return $this->bindings->append($key, $data);
244
    }
245
246
247
    private function getBinding($key)
0 ignored issues
show
Unused Code introduced by
The method getBinding() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
248
    {
249
        return $this->bindings->get($key);
250
    }
251
252
    public function dumpBindings()
253
    {
254
        return $this->bindings->all();
255
    }
256
257
    public function dumpSettings()
258
    {
259
        return $this->configuration->dump();
260
    }
261
}
262