1
|
|
|
<?php
|
2
|
|
|
|
3
|
|
|
namespace AtDataGrid\DataSource\ZendDb;
|
4
|
|
|
|
5
|
|
|
use AtDataGrid\Filter\FilterInterface;
|
6
|
|
|
use AtDataGrid\Filter\ZendSqlFilter;
|
7
|
|
|
use Zend\Db\Adapter\Adapter;
|
8
|
|
|
use Zend\Db\Metadata\Metadata;
|
9
|
|
|
use Zend\Db\Sql\Select;
|
10
|
|
|
use Zend\Db\TableGateway\Feature\RowGatewayFeature;
|
11
|
|
|
use Zend\Db\TableGateway\TableGateway as ZendTableGateway;
|
12
|
|
|
use Zend\Paginator\Adapter\DbSelect as DbSelectPaginatorAdapter;
|
13
|
|
|
use AtDataGrid\DataSource\AbstractDataSource;
|
14
|
|
|
use AtDataGrid\Column;
|
15
|
|
|
|
16
|
|
|
class TableGateway extends AbstractDataSource
|
17
|
|
|
{
|
18
|
|
|
/**
|
19
|
|
|
* @var ZendTableGateway
|
20
|
|
|
*/
|
21
|
|
|
protected $tableGateway;
|
22
|
|
|
|
23
|
|
|
/**
|
24
|
|
|
* @var Select
|
25
|
|
|
*/
|
26
|
|
|
protected $select;
|
27
|
|
|
|
28
|
|
|
/**
|
29
|
|
|
* Base table columns
|
30
|
|
|
*
|
31
|
|
|
* @var array
|
32
|
|
|
*/
|
33
|
|
|
protected $tableColumns = [];
|
34
|
|
|
|
35
|
|
|
/**
|
36
|
|
|
* Joined tables
|
37
|
|
|
*
|
38
|
|
|
* @var array
|
39
|
|
|
*/
|
40
|
|
|
protected $joinedTables = [];
|
41
|
|
|
|
42
|
|
|
/**
|
43
|
|
|
* Joined table columns
|
44
|
|
|
*
|
45
|
|
|
* @var array
|
46
|
|
|
*/
|
47
|
|
|
protected $joinedColumns = [];
|
48
|
|
|
|
49
|
|
|
/**
|
50
|
|
|
* @param ZendTableGateway $tableGateway
|
51
|
|
|
*/
|
52
|
|
|
public function __construct(ZendTableGateway $tableGateway)
|
53
|
|
|
{
|
54
|
|
|
$tableGateway->getFeatureSet()->addFeature(new RowGatewayFeature());
|
55
|
|
|
$this->tableGateway = $tableGateway;
|
56
|
|
|
|
57
|
|
|
$this->select = $tableGateway->getSql()->select();
|
58
|
|
|
$this->paginatorAdapter = new DbSelectPaginatorAdapter($this->select, $tableGateway->getAdapter());
|
59
|
|
|
}
|
60
|
|
|
|
61
|
|
|
/**
|
62
|
|
|
* @return Select
|
63
|
|
|
*/
|
64
|
|
|
public function getSelect()
|
65
|
|
|
{
|
66
|
|
|
return $this->select;
|
67
|
|
|
}
|
68
|
|
|
|
69
|
|
|
/**
|
70
|
|
|
* Join other table and collect joined columns
|
71
|
|
|
*
|
72
|
|
|
* @param $joinedTableName
|
73
|
|
|
* @param $alias
|
74
|
|
|
* @param $keyName
|
75
|
|
|
* @param $foreignKeyName
|
76
|
|
|
* @param null $columns
|
77
|
|
|
*/
|
78
|
|
|
public function with($joinedTableName, $alias, $keyName, $foreignKeyName, $columns = null)
|
79
|
|
|
{
|
80
|
|
|
$tableMetadata = new Metadata($this->getDbAdapter());
|
81
|
|
|
$joinedTableColumns = $tableMetadata->getColumns($joinedTableName);
|
82
|
|
|
|
83
|
|
|
$joinedColumns = [];
|
84
|
|
|
|
85
|
|
|
foreach ($joinedTableColumns as $column) {
|
86
|
|
|
$columnName = $column->getName();
|
87
|
|
|
|
88
|
|
|
if ($columns != null && ! in_array($columnName, $columns)) {
|
89
|
|
|
continue;
|
90
|
|
|
}
|
91
|
|
|
|
92
|
|
|
$fullColumnName = $alias . '__' . $columnName;
|
93
|
|
|
|
94
|
|
|
$joinedColumns[$fullColumnName] = $columnName;
|
95
|
|
|
$this->joinedColumns[$fullColumnName] = $fullColumnName;
|
96
|
|
|
}
|
97
|
|
|
|
98
|
|
|
$this->getSelect()->join(
|
99
|
|
|
[$alias => $joinedTableName],
|
100
|
|
|
$this->tableGateway->getTable(). '.' . $keyName . ' = '. $alias . '.' . $foreignKeyName,
|
101
|
|
|
$joinedColumns
|
102
|
|
|
);
|
103
|
|
|
}
|
104
|
|
|
|
105
|
|
|
/**
|
106
|
|
|
* @return array
|
107
|
|
|
*/
|
108
|
|
|
public function loadColumns()
|
109
|
|
|
{
|
110
|
|
|
$columns = array();
|
111
|
|
|
$tableMetadata = new Metadata($this->getDbAdapter());
|
112
|
|
|
$baseTableColumns = $tableMetadata->getColumns($this->tableGateway->getTable());
|
113
|
|
|
|
114
|
|
|
// Setup default settings for base table column fields
|
115
|
|
|
foreach ($baseTableColumns as $column) {
|
116
|
|
|
$columnName = $column->getName();
|
117
|
|
|
$columnDataType = $column->getDataType();
|
118
|
|
|
|
119
|
|
|
$this->tableColumns[] = $columnName;
|
120
|
|
|
|
121
|
|
|
// @todo Move it to separate class
|
122
|
|
|
switch (true) {
|
123
|
|
|
case in_array($columnDataType, ['datetime', 'timestamp', 'time']):
|
124
|
|
|
$column = new Column\DateTime($columnName);
|
125
|
|
|
break;
|
126
|
|
|
|
127
|
|
|
case in_array($columnDataType, ['date', 'year']):
|
128
|
|
|
$column = new Column\Date($columnName);
|
129
|
|
|
break;
|
130
|
|
|
|
131
|
|
|
case in_array($columnDataType, ['mediumtext', 'text', 'longtext']):
|
132
|
|
|
$column = new Column\Textarea($columnName);
|
133
|
|
|
break;
|
134
|
|
|
|
135
|
|
|
default:
|
136
|
|
|
$column = new Column\Literal($columnName);
|
137
|
|
|
break;
|
138
|
|
|
}
|
139
|
|
|
|
140
|
|
|
$column->setLabel($columnName);
|
141
|
|
|
|
142
|
|
|
$columns[$columnName] = $column;
|
143
|
|
|
}
|
144
|
|
|
|
145
|
|
|
// Setup default settings for joined table column fields
|
146
|
|
|
foreach ($this->joinedColumns as $columnName) {
|
147
|
|
|
$column = new Column\Literal($columnName);
|
148
|
|
|
$column->setLabel($columnName);
|
149
|
|
|
|
150
|
|
|
$columns[$columnName] = $column;
|
151
|
|
|
}
|
152
|
|
|
|
153
|
|
|
$this->setCommentAsLabel($columns);
|
154
|
|
|
|
155
|
|
|
return $columns;
|
156
|
|
|
}
|
157
|
|
|
|
158
|
|
|
/**
|
159
|
|
|
* @param $columns
|
160
|
|
|
*/
|
161
|
|
|
protected function setCommentAsLabel($columns)
|
162
|
|
|
{
|
163
|
|
|
$query = 'SELECT COLUMN_NAME as name, COLUMN_COMMENT as comment FROM information_schema.COLUMNS
|
164
|
|
|
WHERE TABLE_SCHEMA = "' . $this->getDbAdapter()->getCurrentSchema() . '" AND TABLE_NAME = "' . $this->tableGateway->getTable() . '"';
|
165
|
|
|
|
166
|
|
|
$columnsInfo = $this->getDbAdapter()->query($query, Adapter::QUERY_MODE_EXECUTE);
|
167
|
|
|
if ($columnsInfo) {
|
168
|
|
|
foreach ($columnsInfo as $info) {
|
169
|
|
|
if (!empty($info['comment'])) {
|
170
|
|
|
$columns[$info['name']]->setLabel($info['comment']);
|
171
|
|
|
}
|
172
|
|
|
}
|
173
|
|
|
}
|
174
|
|
|
}
|
175
|
|
|
|
176
|
|
|
/**
|
177
|
|
|
* @param $order ['field1' => 'direction1', 'field2' => 'direction2']
|
178
|
|
|
* @param array $filters
|
179
|
|
|
* @return $this
|
180
|
|
|
* @throws \Exception
|
181
|
|
|
*/
|
182
|
|
|
public function prepare($order = [], $filters = [])
|
183
|
|
|
{
|
184
|
|
|
// Sorting
|
185
|
|
|
if (!empty($order)) {
|
186
|
|
|
if (in_array(key($order), $this->tableColumns)) {
|
187
|
|
|
$this->getSelect()->order($order);
|
188
|
|
|
}
|
189
|
|
|
}
|
190
|
|
|
|
191
|
|
|
// Filtering
|
192
|
|
|
foreach ($filters as $columnName => $filter) {
|
193
|
|
|
if (!$filter instanceof FilterInterface) {
|
194
|
|
|
throw new \RuntimeException('Data grid filter must implements FilterInterface');
|
195
|
|
|
}
|
196
|
|
|
|
197
|
|
|
if (!$filter instanceof ZendSqlFilter) {
|
198
|
|
|
throw new \RuntimeException('ZendDb/TableGateway data source requires Filter\ZendSql filters');
|
199
|
|
|
}
|
200
|
|
|
$filter->apply($this->getSelect(), $this->tableGateway->getTable(). '.' . $columnName, $filter->getValue());
|
201
|
|
|
}
|
202
|
|
|
|
203
|
|
|
$this->getEventManager()->trigger(self::EVENT_DATASOURCE_PREPARE_POST, $this->getSelect());
|
204
|
|
|
|
205
|
|
|
//var_dump($this->getSelect()->getSqlString());exit;
|
|
|
|
|
206
|
|
|
|
207
|
|
|
return $this;
|
208
|
|
|
}
|
209
|
|
|
|
210
|
|
|
/**
|
211
|
|
|
* Return row by identifier (primary key)
|
212
|
|
|
*
|
213
|
|
|
* @param $key
|
214
|
|
|
* @return array|mixed
|
215
|
|
|
*/
|
216
|
|
|
public function find($key)
|
217
|
|
|
{
|
218
|
|
|
return $this->tableGateway->select([$this->getIdentifierFieldName() => $key])->current();
|
219
|
|
|
}
|
220
|
|
|
|
221
|
|
|
/**
|
222
|
|
|
* Get only fields which present in table
|
223
|
|
|
*
|
224
|
|
|
* @param array $data
|
225
|
|
|
* @return array
|
226
|
|
|
*/
|
227
|
|
|
protected function cleanDataForSql($data = [])
|
228
|
|
|
{
|
229
|
|
|
$cleanData = [];
|
230
|
|
|
foreach ($data as $key => $value) {
|
231
|
|
|
if (in_array($key, $this->tableColumns)) {
|
232
|
|
|
$cleanData[$key] = $value;
|
233
|
|
|
}
|
234
|
|
|
}
|
235
|
|
|
|
236
|
|
|
return $cleanData;
|
237
|
|
|
}
|
238
|
|
|
|
239
|
|
|
/**
|
240
|
|
|
* @param $data
|
241
|
|
|
* @return int|mixed
|
242
|
|
|
*/
|
243
|
|
|
public function insert($data)
|
244
|
|
|
{
|
245
|
|
|
$this->tableGateway->insert($this->cleanDataForSql($data));
|
246
|
|
|
return $this->tableGateway->getLastInsertValue();
|
247
|
|
|
}
|
248
|
|
|
|
249
|
|
|
/**
|
250
|
|
|
* @param $data
|
251
|
|
|
* @param $key
|
252
|
|
|
* @return int|mixed
|
253
|
|
|
*/
|
254
|
|
|
public function update($data, $key)
|
255
|
|
|
{
|
256
|
|
|
return $this->tableGateway->update($this->cleanDataForSql($data), [$this->getIdentifierFieldName() => $key]);
|
257
|
|
|
}
|
258
|
|
|
|
259
|
|
|
/**
|
260
|
|
|
* @param $key
|
261
|
|
|
* @return int|mixed
|
262
|
|
|
*/
|
263
|
|
|
public function delete($key)
|
264
|
|
|
{
|
265
|
|
|
return $this->tableGateway->delete([$this->getIdentifierFieldName() => $key]);
|
266
|
|
|
}
|
267
|
|
|
|
268
|
|
|
/**
|
269
|
|
|
* @return Adapter|\Zend\Db\Adapter\AdapterInterface
|
270
|
|
|
*/
|
271
|
|
|
protected function getDbAdapter()
|
272
|
|
|
{
|
273
|
|
|
return $this->tableGateway->getAdapter();
|
274
|
|
|
}
|
275
|
|
|
|
276
|
|
|
/**
|
277
|
|
|
* @return DbSelectPaginatorAdapter
|
278
|
|
|
*/
|
279
|
|
|
public function getPaginatorAdapter()
|
280
|
|
|
{
|
281
|
|
|
return $this->paginatorAdapter;
|
282
|
|
|
}
|
283
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.