Completed
Push — master ( bf1ec5...85c89e )
by Leandro
14:16
created

Serializer::executeProvider()   C

Complexity

Conditions 8
Paths 5

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 8

Importance

Changes 5
Bugs 1 Features 1
Metric Value
c 5
b 1
f 1
dl 0
loc 31
ccs 24
cts 24
cp 1
rs 5.3846
cc 8
eloc 20
nc 5
nop 2
crap 8
1
<?php
2
3
namespace leandrogehlen\exporter\serializers;
4
5
use leandrogehlen\exporter\data\Column;
6
use leandrogehlen\exporter\data\Dictionary;
7
use leandrogehlen\exporter\data\Exporter;
8
use leandrogehlen\exporter\data\Provider;
9
use leandrogehlen\exporter\data\Session;
10
use yii\base\InvalidConfigException;
11
use yii\base\Object;
12
use yii\db\Query;
13
use yii\helpers\ArrayHelper;
14
15
16
17
/**
18
 * Serializer converts DB data into specific before it is sent out
19
 *
20
 * @author Leandro Guindani Gehlen <[email protected]>
21
 */
22
abstract class Serializer extends Object
23
{
24
25
    /**
26
     * @event Event an event raised at the beginning of serialize row
27
     */
28
    const EVENT_BEFORE_SERIALIZE_ROW = 'beforeSerializeRow';
29
30
    /**
31
     * @var Exporter
32
     */
33
    public $exporter;
34
35
    /**
36
     * Serializes the given session into a format that can be easily turned into other formats.
37
     * @param Session[] $sessions
38
     * @param array $master
39
     * @return array
40
     */
41
    abstract public function serialize($sessions, $master = []);
42
43
44
    /**
45
     * Formats the specified data.
46
     * @param array $data
47
     * @return string
48
     */
49
    abstract public function formatData($data);
50
51
    /**
52
     * Executes the query statement and returns ALL rows at once.
53
     * @param Provider $provider the provider name
54
     * @return array
55
     * @throws InvalidConfigException
56
     */
57 7
    protected function executeProvider($provider, $master)
58
    {
59 7
        $db = $this->exporter->db;
60 7
        $query = $provider->query;
61
62 7
        if ($query instanceof Query) {
63 2
            list($sql) = $db->getQueryBuilder()->build($query);
64 7
        } elseif (is_string($query)) {
65 6
            $sql = $query;
66 6
        } else {
67 1
            throw new InvalidConfigException('The query of provider "' . $provider->name .  '" must be string or Query object');
68
        }
69
70 6
        $params = [];
71 6
        if (preg_match_all('/:\w+/', $sql, $matches)) {
72 3
            foreach ($matches[0] as $param) {
73 3
                $name = substr($param, 1);
74 3
                $value = ArrayHelper::getValue($master, $name);
75
76 3
                if ($value === null) {
77 1
                    $parameter = $this->exporter->findParameter($name);
78 1
                    if ($parameter !== null) {
79 1
                        $value = is_callable($parameter->value) ? call_user_func($parameter->value) : $parameter->value;
80 1
                    }
81 1
                }
82 3
                $params[$name] = $value;
83 3
            }
84 3
        }
85
86 6
        return $db->createCommand($sql, $params)->queryAll();
87
    }
88
89
    /**
90
     * This method is invoked before serialize row.
91
     * @param string|array $record
92
     * @param Session $session
93
     * @return string|array
94
     */
95 5
    public function beforeSerializeRow($record, $session)
96
    {
97 5
        $event = $this->exporter->findEvent(self::EVENT_BEFORE_SERIALIZE_ROW);
98 4
        return ($event !== null) ? call_user_func($event->expression, $record, $session) : $record;
99
    }
100
101
    /**
102
     * Extract formatted value.
103
     * @param Column $column
104
     * @param array $row
105
     * @return mixed|string
106
     */
107 6
    protected function extractValue($column, $row)
108
    {
109 6
        $complete = $column->complete;
110 6
        $size = $column->size;
111 6
        $format = $column->format;
112 6
        $align = $column->align;
113 6
        $expression = null;
114 6
        $value = ArrayHelper::getValue($row, $column->name);
115
116 6
        if (is_callable($column->value)){
117 4
            $expression = $column->value;
118 6
        } elseif ($column->value !== null) {
119 6
            $value = $column->value;
120 6
        }
121
122 6
        $dictionary = $column->dictionary ? $this->exporter->findDictionary($column->dictionary) : null;
123 6
        if ($dictionary) {
124 3
            if ($dictionary->value) {
125 3
                if ($expression === null && is_callable($dictionary->value)) {
126 1
                    $expression = $dictionary->value;
127 3
                } elseif ($value === null) {
128 2
                    $value = $dictionary->value;
129 2
                }
130 3
            }
131 3
            if ($complete === null) {
132 3
                $complete = $dictionary->complete;
133 3
            }
134 3
            if ($align === null) {
135 3
                $align = $dictionary->align;
136 3
            }
137 3
            if ($size === null) {
138 3
                $size = $dictionary->size;
139 3
            }
140 3
            if ($format === null) {
141 3
                $format = $dictionary->format;
142 3
            }
143 3
        }
144
145 6
        if ($format) {
146 1
            $value = $this->exporter->formatter->format($value, $format);
147 1
        }
148
149 6
        if (is_callable($expression)) {
150 4
            $value = call_user_func($expression, $value, $row);
151 4
        }
152
153 6
        $value = (string) $value;
154 6
        if ($size === null) {
155 3
            return $value;
156
        } else {
157 3
            $padding = $this->toPadding($align);
158 3
            return ($size > strlen($value) && $complete !== null) ? str_pad($value, $size, $complete, $padding) : substr($value, 0, $size);
159
        }
160
    }
161
162
    /**
163
     * Converts the [[align]] property to valid padding type.
164
     * @see {@link http://php.net/manual/pt_BR/function.str-pad.php php manual}.
165
     * @param string $align the column alignment
166
     * @return int
167
     */
168 3
    private function toPadding($align)
169
    {
170 3
        if ($align == Dictionary::ALIGN_RIGHT) {
171 1
            return STR_PAD_LEFT;
172 3
        } elseif ($align == Dictionary::ALIGN_BOTH) {
173
            return STR_PAD_BOTH;
174
        } else {
175 3
            return STR_PAD_RIGHT;
176
        }
177
    }
178
}
179