Passed
Branch master (018ba4)
by Mathieu
06:43
created

AbstractExpression::quoteIdentifier()   C

Complexity

Conditions 11
Paths 8

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 23
nc 8
nop 2
dl 0
loc 40
rs 5.2653
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Charcoal\Source;
4
5
use DateTimeInterface;
6
use InvalidArgumentException;
7
8
// From 'charcoal-property'
9
use Charcoal\Property\DateTimeProperty;
10
11
// From 'charcoal-core'
12
use Charcoal\Source\ExpressionInterface;
13
14
/**
15
 * Represents the basic structure of a query expression.
16
 */
17
abstract class AbstractExpression implements
18
    ExpressionInterface
19
{
20
    /**
21
     * Expression name.
22
     *
23
     * @var string|null
24
     */
25
    protected $name;
26
27
    /**
28
     * Whether the expression is active.
29
     *
30
     * @var boolean
31
     */
32
    protected $active = true;
33
34
    /**
35
     * Set the expression data.
36
     *
37
     * @param  array<string,mixed> $data The expression data;
38
     *     as an associative array.
39
     * @return self
40
     */
41
    public function setData(array $data)
42
    {
43
        if (isset($data['name'])) {
44
            $this->setName($data['name']);
45
        }
46
47
        if (isset($data['active'])) {
48
            $this->setActive($data['active']);
49
        }
50
51
        return $this;
52
    }
53
54
    /**
55
     * Retrieve the default values.
56
     *
57
     * @return array<string,mixed> An associative array.
58
     */
59
    abstract public function defaultData();
60
61
    /**
62
     * Retrieve the expression data structure.
63
     *
64
     * @return array<string,mixed> An associative array.
65
     */
66
    abstract public function data();
67
68
    /**
69
     * Set whether the expression is active or not.
70
     *
71
     * @param  boolean $active The active flag.
72
     * @return self
73
     */
74
    public function setActive($active)
75
    {
76
        $this->active = !!$active;
77
        return $this;
78
    }
79
80
    /**
81
     * Determine if the expression is active or not.
82
     *
83
     * @return boolean TRUE if active, FALSE is disabled.
84
     */
85
    public function active()
86
    {
87
        return $this->active;
88
    }
89
90
    /**
91
     * Set the expression name.
92
     *
93
     * @param  string $name A unique identifier.
94
     * @throws InvalidArgumentException If the expression name is not a string.
95
     * @return self
96
     */
97
    public function setName($name)
98
    {
99
        if (!is_string($name)) {
100
            throw new InvalidArgumentException('Expression name must be a string');
101
        }
102
103
        $this->name = $name;
104
        return $this;
105
    }
106
107
    /**
108
     * Retrieve the expression name.
109
     *
110
     * @return string|null
111
     */
112
    public function name()
113
    {
114
        return $this->name;
115
    }
116
117
    /**
118
     * Parse the given value.
119
     *
120
     * @param  mixed $value The value to be parsed.
121
     * @return mixed Returns the parsed value.
122
     */
123
    public static function parseValue($value)
124
    {
125
        if ($value instanceof DateTimeInterface) {
126
            $value = $value->format('Y-m-d H:i:s');
127
        } elseif ($value instanceof DateTimeProperty) {
128
            $value = $value->storageVal($value->val());
129
        } elseif (is_string($value)) {
130
            $str = strtolower($value);
131
            if ($str === 'true') {
132
                $value = true;
133
            } elseif ($str === 'false') {
134
                $value = false;
135
            }
136
        }
137
138
        return $value;
139
    }
140
141
    /**
142
     * Quote the given scalar value.
143
     *
144
     * @param  mixed $value The value to be quoted.
145
     * @return mixed Returns:
146
     *     - If $value is not a scalar value, the value is returned intact.
147
     *     - if $value is a boolean, the value is cast to an integer.
148
     *     - If $value is not a number, the value is stringified
149
     *       and wrapped in double quotes.
150
     */
151
    public static function quoteValue($value)
152
    {
153
        $value = static::parseValue($value);
154
155
        if (!is_scalar($value)) {
156
            return $value;
157
        }
158
159
        if (is_bool($value)) {
160
            return (int)$value;
161
        }
162
163
        if (!is_numeric($value)) {
164
            $value = htmlspecialchars($value, ENT_QUOTES);
165
            $value = sprintf('"%s"', $value);
166
        }
167
168
        return $value;
169
    }
170
171
    /**
172
     * Quote the given field name.
173
     *
174
     * @param  string      $identifier The field name.
175
     * @param  string|null $tableName  If provided, the table name is prepended to the $identifier.
176
     * @throws InvalidArgumentException If the parameters are not string.
177
     * @return string
178
     */
179
    public static function quoteIdentifier($identifier, $tableName = null)
180
    {
181
        if ($identifier === null || $identifier === '') {
182
            return '';
183
        }
184
185
        if (!is_string($identifier)) {
186
            throw new InvalidArgumentException(sprintf(
187
                'Field Name must be a string, received %s',
188
                is_object($identifier) ? get_class($identifier) : gettype($identifier)
189
            ));
190
        }
191
192
        if ($tableName !== null) {
193
            if (!is_string($tableName)) {
194
                throw new InvalidArgumentException(sprintf(
195
                    'Table Name must be a string, received %s',
196
                    is_object($tableName) ? get_class($tableName) : gettype($tableName)
197
                ));
198
            }
199
200
            if ($tableName === '') {
201
                throw new InvalidArgumentException(
202
                    'Table Name can not be empty.'
203
                );
204
            }
205
206
            if ($identifier === '*') {
207
                $template = '%1$s.*';
208
            } else {
209
                $template = '%1$s.`%2$s`';
210
            }
211
212
            return sprintf($template, $tableName, $identifier);
213
        }
214
215
        if ($identifier === '*') {
216
            return $identifier;
217
        } else {
218
            return sprintf('`%1$s`', $identifier);
219
        }
220
    }
221
222
    /**
223
     * Compare two values.
224
     *
225
     * @param  mixed $a The custom value.
226
     * @param  mixed $b The default value.
227
     * @return integer
228
     */
229
    public static function diffValues($a, $b)
230
    {
231
        if ($a === $b) {
232
            return 0;
233
        }
234
235
        return 1;
236
    }
237
238
    /**
239
     * Determine if the given value is callable, but not a string.
240
     *
241
     * @param  mixed $value The value to be checked.
242
     * @return boolean
243
     */
244
    public static function isCallable($value)
245
    {
246
        return !is_string($value) && is_callable($value);
247
    }
248
249
    /**
250
     * Retrieve the expression data that can be serialized with {@see json_encode()}.
251
     *
252
     * Convert the expression to its JSON representation.
253
     * Convert the expression into something JSON serializable.
254
     * Returns an array of parameters to serialize when this is serialized with json_encode().
255
     *
256
     * @see    JsonSerializable
257
     * @uses   self::diffValues()
258
     * @return array<string,mixed> An associative array containing only mutated values.
259
     */
260
    public function jsonSerialize()
261
    {
262
        return array_udiff_assoc($this->data(), $this->defaultData(), [ $this, 'diffValues' ]);
263
    }
264
265
    /**
266
     * Generate a storable representation of the expression object.
267
     *
268
     * @see    Serializable
269
     * @return string Returns a string containing a byte-stream representation of the object.
270
     */
271
    public function serialize()
272
    {
273
        return serialize($this->jsonSerialize());
274
    }
275
276
    /**
277
     * Convert the serialized data into an expression object.
278
     *
279
     * @see    Serializable
280
     * @param  string $data The serialized data.
281
     * @return void
282
     */
283
    public function unserialize($data)
284
    {
285
        $data = unserialize($data);
286
        $this->setData($data);
287
    }
288
}
289