Passed
Branch main (c57f14)
by Thierry
03:13
created

SelectUtilTrait::applySqlFunction()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 12
rs 10
1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Traits;
4
5
use function intval;
6
use function implode;
7
use function strtoupper;
8
use function in_array;
9
use function preg_match;
10
use function preg_replace;
11
use function preg_match_all;
12
13
trait SelectUtilTrait
14
{
15
    /**
16
     * Filter length value including enums
17
     *
18
     * @param string $length
19
     *
20
     * @return string
21
     */
22
    public function processLength(string $length): string
23
    {
24
        if (!$length) {
25
            return '';
26
        }
27
        $enumLength = $this->driver->enumLength();
28
        if (preg_match("~^\\s*\\(?\\s*$enumLength(?:\\s*,\\s*$enumLength)*+\\s*\\)?\\s*\$~", $length) &&
29
            preg_match_all("~$enumLength~", $length, $matches)) {
30
            return '(' . implode(',', $matches[0]) . ')';
31
        }
32
        return preg_replace('~^[0-9].*~', '(\0)', preg_replace('~[^-0-9,+()[\]]~', '', $length));
33
    }
34
35
    /**
36
     * Process limit box in select
37
     *
38
     * @return int
39
     */
40
    public function processSelectLimit(): int
41
    {
42
        return isset($this->input->values['limit']) ? intval($this->input->values['limit']) : 50;
43
    }
44
45
    /**
46
     * Process length box in select
47
     *
48
     * @return int
49
     */
50
    public function processSelectLength(): int
51
    {
52
        return isset($this->input->values['text_length']) ? intval($this->input->values['text_length']) : 100;
53
    }
54
55
    /**
56
     * Process order box in select
57
     *
58
     * @return array
59
     */
60
    public function processSelectOrder(): array
61
    {
62
        $expressions = [];
63
        foreach ((array) $this->input->values['order'] as $key => $value) {
64
            if ($value !== '') {
65
                $regexp = '~^((COUNT\(DISTINCT |[A-Z0-9_]+\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\)|COUNT\(\*\))$~';
66
                $expression = $value;
67
                if (preg_match($regexp, $expression) === false) {
68
                    $expression = $this->driver->escapeId($expression);
69
                }
70
                if (isset($this->input->values['desc'][$key])) {
71
                    $expression .= ' DESC';
72
                }
73
                $expressions[] = $expression;
74
            }
75
        }
76
        return $expressions;
77
    }
78
79
    /**
80
     * Process extras in select form
81
     *
82
     * @param array $where AND conditions
83
     * @param array $foreignKeys
84
     *
85
     * @return bool
86
     */
87
    // public function processSelectEmail(array $where, array $foreignKeys)
88
    // {
89
    //     return false;
90
    // }
91
92
    /**
93
     * Apply SQL function
94
     *
95
     * @param string $function
96
     * @param string $column escaped column identifier
97
     *
98
     * @return string
99
     */
100
    public function applySqlFunction(string $function, string $column): string
101
    {
102
        if (!$function) {
103
            return $column;
104
        }
105
        if ($function === 'unixepoch') {
106
            return "DATETIME($column, '$function')";
107
        }
108
        if ($function === 'count distinct') {
109
            return "COUNT(DISTINCT $column)";
110
        }
111
        return strtoupper($function) . "($column)";
112
    }
113
114
    /**
115
     * @param array $value
116
     *
117
     * @return bool
118
     */
119
    private function colHasValidValue(array $value): bool
120
    {
121
        return $value['fun'] === 'count' ||
122
            ($value['col'] !== '' && (!$value['fun'] ||
123
                in_array($value['fun'], $this->driver->functions()) ||
124
                in_array($value['fun'], $this->driver->grouping())));
125
    }
126
127
    /**
128
     * Process columns box in select
129
     *
130
     * @return array
131
     */
132
    public function processSelectColumns(): array
133
    {
134
        $select = []; // select expressions, empty for *
135
        $group = []; // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
136
        foreach ((array) $this->input->values['columns'] as $key => $value) {
137
            if ($this->colHasValidValue($value)) {
138
                $fields = '*';
139
                if ($value['col'] !== '') {
140
                    $fields = $this->driver->escapeId($value['col']);
141
                }
142
                $select[$key] = $this->applySqlFunction($value['fun'], $fields);
143
                if (!in_array($value['fun'], $this->driver->grouping())) {
144
                    $group[] = $select[$key];
145
                }
146
            }
147
        }
148
        return [$select, $group];
149
    }
150
}
151