Completed
Push — master ( be2c66...bfc226 )
by Ron
02:38
created

RunnableSelect   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 19
Bugs 1 Features 7
Metric Value
wmc 28
c 19
b 1
f 7
lcom 1
cbo 6
dl 0
loc 196
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A bindValues() 0 4 1
A bindValue() 0 4 1
A clearValues() 0 4 1
A setPreserveTypes() 0 4 1
A fetchRowsLazy() 0 8 2
A fetchRows() 0 15 4
A fetchRow() 0 13 3
A fetchKeyValue() 0 14 3
A fetchGroups() 0 16 4
A fetchArray() 0 5 1
A fetchValue() 0 9 2
A getFoundRows() 0 3 1
A createTempStatement() 0 12 2
A createStatement() 0 10 2
1
<?php
2
namespace Kir\MySQL\Builder;
3
4
use Kir\MySQL\Builder\Helpers\FieldTypeProvider;
5
use Kir\MySQL\Builder\Helpers\FieldValueConverter;
6
use Kir\MySQL\Builder\Helpers\LazyRowGenerator;
7
8
/**
9
 */
10
class RunnableSelect extends Select {
11
	/** @var array */
12
	private $values = array();
13
	/** @var bool */
14
	private $preserveTypes;
15
	/** @var int */
16
	private $foundRows = 0;
17
18
	/**
19
	 * @param array $values
20
	 * @return $this
21
	 */
22
	public function bindValues(array $values) {
23
		$this->values = array_merge($this->values, $values);
24
		return $this;
25
	}
26
27
	/**
28
	 * @param string $key
29
	 * @param string|int|bool|float|null $value
30
	 * @return $this
31
	 */
32
	public function bindValue($key, $value) {
33
		$this->values[$key] = $value;
34
		return $this;
35
	}
36
37
	/**
38
	 * @return $this
39
	 */
40
	public function clearValues() {
41
		$this->values = array();
42
		return $this;
43
	}
44
45
	/**
46
	 * @param bool $preserveTypes
47
	 * @return $this
48
	 */
49
	public function setPreserveTypes($preserveTypes = true) {
50
		$this->preserveTypes = $preserveTypes;
51
		return $this;
52
	}
53
54
	/**
55
	 * @param \Closure $callback
56
	 * @return array[]
57
	 */
58
	public function fetchRows(\Closure $callback = null) {
59
		return $this->createTempStatement(function (QueryStatement $statement) use ($callback) {
60
			$data = $statement->fetchAll(\PDO::FETCH_ASSOC);
61
			if($this->preserveTypes) {
62
				$columnDefinitions = FieldTypeProvider::getFieldTypes($statement);
63
				foreach($data as &$row) {
64
					$row = FieldValueConverter::convertValues($row, $columnDefinitions);
65
				}
66
			}
67
			if($callback !== null) {
68
				$data = array_map($callback, $data);
69
			}
70
			return $data;
71
		});
72
	}
73
74
	/**
75
	 * @param \Closure $callback
76
	 * @return array[]|\Generator
77
	 */
78
	public function fetchRowsLazy(\Closure $callback = null) {
79
		if(version_compare(PHP_VERSION, '5.5', '<=')) {
80
			return $this->fetchRows($callback);
81
		}
82
		$statement = $this->createStatement();
83
		$generator = new LazyRowGenerator($this->preserveTypes);
84
		return $generator->generate($statement, $callback);
85
	}
86
87
	/**
88
	 * @return string[]
89
	 */
90
	public function fetchRow() {
91
		return $this->createTempStatement(function (QueryStatement $statement) {
92
			$row = $statement->fetch(\PDO::FETCH_ASSOC);
93
			if(!is_array($row)) {
94
				return array();
95
			}
96
			if($this->preserveTypes) {
97
				$columnDefinitions = FieldTypeProvider::getFieldTypes($statement);
98
				$row = FieldValueConverter::convertValues($row, $columnDefinitions);
99
			}
100
			return $row;
101
		});
102
	}
103
104
	/**
105
	 * @param bool $treatValueAsArray
106
	 * @return mixed[]
107
	 */
108
	public function fetchKeyValue($treatValueAsArray = false) {
109
		return $this->createTempStatement(function (QueryStatement $statement) use ($treatValueAsArray) {
110
			if($treatValueAsArray) {
111
				$rows = $statement->fetchAll(\PDO::FETCH_ASSOC);
112
				$result = array();
113
				foreach($rows as $row) {
114
					list($key) = array_values($row);
115
					$result[$key] = $row;
116
				}
117
				return $result;
118
			}
119
			return $statement->fetchAll(\PDO::FETCH_KEY_PAIR);
120
		});
121
	}
122
123
	/**
124
	 * @param array $fields
125
	 * @return array
126
	 */
127
	public function fetchGroups(array $fields) {
128
		$rows = $this->fetchRows();
129
		$result = array();
130
		foreach($rows as $row) {
131
			$tmp = &$result;
132
			foreach($fields as $field) {
133
				$value = $row[$field];
134
				if(!array_key_exists($value, $tmp)) {
135
					$tmp[$value] = [];
136
				}
137
				$tmp = &$tmp[$value];
138
			}
139
			$tmp[] = $row;
140
		}
141
		return $result;
142
	}
143
144
	/**
145
	 * @return string[]
146
	 */
147
	public function fetchArray() {
148
		return $this->createTempStatement(function (QueryStatement $stmt) {
149
			return $stmt->fetchAll(\PDO::FETCH_COLUMN);
150
		});
151
	}
152
153
	/**
154
	 * @param mixed $default
155
	 * @return null|bool|string|int|float
156
	 */
157
	public function fetchValue($default = null) {
158
		return $this->createTempStatement(function (QueryStatement $stmt) use ($default) {
159
			$result = $stmt->fetch(\PDO::FETCH_NUM);
160
			if($result !== false) {
161
				return $result[0];
162
			}
163
			return $default;
164
		});
165
	}
166
167
	/**
168
	 * @return bool
169
	 */
170
	public function getFoundRows() {
171
		return $this->foundRows;
172
	}
173
174
	/**
175
	 * @param callback $fn
176
	 * @return mixed
177
	 * @throws \Exception
178
	 */
179
	private function createTempStatement($fn) {
180
		$stmt = $this->createStatement();
181
		$res = null;
182
		try {
183
			$res = call_user_func($fn, $stmt);
184
		} catch (\Exception $e) { // PHP 5.4 compatibility
185
			$stmt->closeCursor();
186
			throw $e;
187
		}
188
		$stmt->closeCursor();
189
		return $res;
190
	}
191
192
	/**
193
	 * @return QueryStatement
194
	 */
195
	private function createStatement() {
196
		$db = $this->db();
197
		$query = $this->__toString();
198
		$statement = $db->prepare($query);
199
		$statement->execute($this->values);
200
		if($this->getCalcFoundRows()) {
201
			$this->foundRows = (int) $db->query('SELECT FOUND_ROWS()')->fetchColumn();
202
		}
203
		return $statement;
204
	}
205
}
206