Completed
Branch master (6f5620)
by Anton
02:08
created

SqlSource   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 80.95%

Importance

Changes 0
Metric Value
dl 0
loc 100
ccs 34
cts 42
cp 0.8095
rs 10
c 0
b 0
f 0
wmc 13
lcom 1
cbo 4

2 Methods

Rating   Name   Duplication   Size   Complexity  
A setSource() 0 9 2
C process() 0 67 11
1
<?php
2
/**
3
 * Bluz Framework Component
4
 *
5
 * @copyright Bluz PHP Team
6
 * @link      https://github.com/bluzphp/framework
7
 */
8
9
declare(strict_types=1);
10
11
namespace Bluz\Grid\Source;
12
13
use Bluz\Db;
14
use Bluz\Grid;
15
use Bluz\Proxy;
16
17
/**
18
 * SQL Source Adapter for Grid package
19
 *
20
 * @package  Bluz\Grid
21
 * @author   Anton Shevchuk
22
 */
23
class SqlSource extends AbstractSource
24
{
25
    /**
26
     * @var string SQL
27
     */
28
    protected $source;
29
30
    /**
31
     * Set SQL source
32
     *
33
     * @param  string $source
34
     *
35
     * @return self
36
     * @throws \Bluz\Grid\GridException
37
     */
38 2
    public function setSource($source)
39
    {
40 2
        if (!is_string($source)) {
41 1
            throw new Grid\GridException('Source of `SqlSource` should be string with SQL query');
42
        }
43 1
        $this->source = $source;
44
45 1
        return $this;
46
    }
47
48
    /**
49
     * Process
50
     *
51
     * @param  array[] $settings
52
     *
53
     * @return \Bluz\Grid\Data
54
     */
55 1
    public function process(array $settings = [])
56
    {
57
        // process filters
58 1
        $where = [];
59 1
        if (!empty($settings['filters'])) {
60 1
            foreach ($settings['filters'] as $column => $filters) {
61 1
                foreach ($filters as $filter => $value) {
62 1
                    if ($filter === Grid\Grid::FILTER_LIKE) {
63 1
                        $value = '%' . $value . '%';
64
                    }
65 1
                    $where[] = $column . ' ' .
66 1
                        $this->filters[$filter] . ' ' .
67 1
                        Proxy\Db::quote((string)$value);
68
                }
69
            }
70
        }
71
72
        // process orders
73 1
        $orders = [];
74 1
        if (!empty($settings['orders'])) {
75
            // Obtain a list of columns
76
            foreach ($settings['orders'] as $column => $order) {
77
                $column = Proxy\Db::quoteIdentifier($column);
78
                $orders[] = $column . ' ' . $order;
79
            }
80
        }
81
82
        // process pages
83 1
        $limit = ' LIMIT ' . ($settings['page'] - 1) * $settings['limit'] . ', ' . $settings['limit'];
84
85
        // prepare query
86 1
        $type = Proxy\Db::getOption('connect', 'type');
87
88 1
        if (strtolower($type) === 'mysql') {
89
            // MySQL
90 1
            $dataSql = preg_replace('/SELECT\s(.*?)\sFROM/is', 'SELECT SQL_CALC_FOUND_ROWS $1 FROM', $this->source, 1);
91 1
            $totalSql = 'SELECT FOUND_ROWS()';
92
        } else {
93
            // other
94
            $dataSql = $this->source;
95
            $totalSql = preg_replace('/SELECT\s(.*?)\sFROM/is', 'SELECT COUNT(*) FROM', $this->source, 1);
96
            if (count($where)) {
97
                $totalSql .= ' WHERE ' . implode(' AND ', $where);
98
            }
99
        }
100
101 1
        if (count($where)) {
102 1
            $dataSql .= ' WHERE ' . implode(' AND ', $where);
103
        }
104 1
        if (count($orders)) {
105
            $dataSql .= ' ORDER BY ' . implode(', ', $orders);
106
        }
107 1
        $dataSql .= $limit;
108
109
        // run queries
110
        // use transaction to avoid errors
111 1
        Proxy\Db::transaction(
112 1
            function () use (&$data, &$total, $dataSql, $totalSql) {
113 1
                $data = Proxy\Db::fetchAll($dataSql);
114 1
                $total = (int)Proxy\Db::fetchOne($totalSql);
115 1
            }
116
        );
117
118 1
        $gridData = new Grid\Data($data);
119 1
        $gridData->setTotal($total);
120 1
        return $gridData;
121
    }
122
}
123