Completed
Push — master ( abc7fc...ef6c42 )
by Anton
02:25
created

AliasDecorator::prepare()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 7.551
c 0
b 0
f 0
cc 7
eloc 11
nc 7
nop 1
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\ORM\Helpers;
10
11
use Spiral\Database\Builders\Prototypes\AbstractSelect;
12
use Spiral\Database\Exceptions\BuilderException;
13
use Spiral\ORM\Entities\RecordSelector;
14
15
/**
16
 * WhereDecorator used to trick user functions and route where() calls to specified destination
17
 * (where, onWhere, etc). This functionality used to describe WHERE conditions in ORM loaders using
18
 * unified where syntax.
19
 *
20
 * Decorator can additionally decorate target table name, using magic expression "{@}". Table name
21
 * decoration is required as Loader target table can be unknown for user.
22
 *
23
 * @todo support @ alias?
24
 */
25
class AliasDecorator
26
{
27
    /**
28
     * Target function postfix. All requests will be routed using this pattern and "or", "and"
29
     * prefixes.
30
     *
31
     * @var string
32
     */
33
    protected $target = 'where';
34
35
    /**
36
     * Decorator will replace {@} with this alias in every where column.
37
     *
38
     * @var string
39
     */
40
    protected $alias = '';
41
42
    /**
43
     * Decorated query builder.
44
     *
45
     * @var AbstractSelect|RecordSelector
46
     */
47
    protected $query = null;
48
49
    /**
50
     * @param AbstractSelect|RecordSelector $query
51
     * @param string                        $target
52
     * @param string                        $alias
53
     */
54
    public function __construct($query, string $target = 'where', string $alias = '')
55
    {
56
        $this->query = $query;
57
        $this->target = $target;
58
        $this->alias = $alias;
59
    }
60
61
    /**
62
     * Update target method all where requests should be router into.
63
     *
64
     * @param string $target
65
     */
66
    public function setTarget(string $target)
67
    {
68
        $this->target = $target;
69
    }
70
71
    /**
72
     * Get active routing target.
73
     *
74
     * @return string
75
     */
76
    public function getTarget(): string
77
    {
78
        return $this->target;
79
    }
80
81
    /**
82
     * Simple WHERE condition with various set of arguments. Routed to where/on/having based
83
     * on decorator settings.
84
     *
85
     * @see AbstractWhere
86
     *
87
     * @param mixed ...$args [(column, value), (column, operator, value)]
88
     *
89
     * @return $this|self
90
     *
91
     * @throws BuilderException
92
     */
93
    public function where(...$args): AliasDecorator
94
    {
95
        if ($args[0] instanceof \Closure) {
96
            call_user_func($args[0], $this);
97
98
            return $this;
99
        }
100
101
        //We have to prepare only first argument
102
        $args[0] = $this->prepare($args[0]);
103
104
        //Routing where
105
        call_user_func_array([$this->query, $this->target], $args);
106
107
        return $this;
108
    }
109
110
    /**
111
     * @param array $orderBy In a form [expression => direction]
112
     *
113
     * @return \Spiral\ORM\Helpers\AliasDecorator
114
     */
115
    public function orderBy(array $orderBy): AliasDecorator
116
    {
117
        $this->query->orderBy($this->prepare($orderBy));
118
119
        return $this;
120
    }
121
122
    /**
123
     * Simple AND WHERE condition with various set of arguments. Routed to where/on/having based
124
     * on decorator settings.
125
     *
126
     * @see AbstractWhere
127
     *
128
     * @param mixed ...$args [(column, value), (column, operator, value)]
129
     *
130
     * @return $this|self
131
     *
132
     * @throws BuilderException
133
     */
134
    public function andWhere(...$args): AliasDecorator
135
    {
136
        if ($args[0] instanceof \Closure) {
137
            call_user_func($args[0], $this);
138
139
            return $this;
140
        }
141
142
        //We have to prepare only first argument
143
        $args[0] = $this->prepare($args[0]);
144
145
        //Routing where
146
        call_user_func_array([$this->query, 'and' . ucfirst($this->target)], $args);
147
148
        return $this;
149
    }
150
151
    /**
152
     * Simple OR WHERE condition with various set of arguments. Routed to where/on/having based
153
     * on decorator settings.
154
     *
155
     * @see AbstractWhere
156
     *
157
     * @param mixed ...$args [(column, value), (column, operator, value)]
158
     *
159
     * @return $this|self
160
     *
161
     * @throws BuilderException
162
     */
163
    public function orWhere(...$args): AliasDecorator
164
    {
165
        if ($args[0] instanceof \Closure) {
166
            call_user_func($args[0], $this);
167
168
            return $this;
169
        }
170
171
        //We have to prepare only first argument
172
        $args[0] = $this->prepare($args[0]);
173
174
        //Routing where
175
        call_user_func_array([$this->query, 'or' . ucfirst($this->target)], $args);
176
177
        return $this;
178
    }
179
180
    /**
181
     * Helper function used to replace {@} alias with actual table name.
182
     *
183
     * @param mixed $where
184
     *
185
     * @return mixed
186
     */
187
    protected function prepare($where)
188
    {
189
        if (is_string($where)) {
190
            return str_replace('{@}', $this->alias, $where);
191
        }
192
193
        if (!is_array($where)) {
194
            return $where;
195
        }
196
197
        $result = [];
198
        foreach ($where as $column => $value) {
199
            if (is_string($column) && !is_int($column)) {
200
                $column = str_replace('{@}', $this->alias, $column);
201
            }
202
203
            $result[$column] = !is_array($value) ? $value : $this->prepare($value);
204
        }
205
206
        return $result;
207
    }
208
}
209