1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Database\Selector;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22: 23:
24: class GroupedTableSelection extends TableSelection
25: {
26:
27: private $refTable;
28:
29:
30: private $column;
31:
32:
33: private $delimitedColumn;
34:
35:
36: public $active;
37:
38:
39:
40: public function __construct($name, TableSelection $refTable, $column)
41: {
42: parent::__construct($name, $refTable->connection);
43: $this->refTable = $refTable;
44: $this->through($column);
45: }
46:
47:
48:
49: 50: 51: 52: 53:
54: public function through($column)
55: {
56: $this->column = $column;
57: $this->delimitedColumn = $this->refTable->connection->getSupplementalDriver()->delimite($this->column);
58: return $this;
59: }
60:
61:
62:
63: public function select($columns)
64: {
65: if (!$this->select) {
66: $this->select[] = "$this->delimitedName.$this->delimitedColumn";
67: }
68: return parent::select($columns);
69: }
70:
71:
72:
73: public function order($columns)
74: {
75: if (!$this->order) { 76: $this->order[] = "$this->delimitedName.$this->delimitedColumn"
77: . (preg_match('~\\bDESC$~i', $columns) ? ' DESC' : '');
78: }
79: return parent::order($columns);
80: }
81:
82:
83:
84: public function aggregation($function)
85: {
86: $join = $this->createJoins(implode(',', $this->conditions), TRUE) + $this->createJoins($function);
87: $column = ($join ? "$this->table." : '') . $this->column;
88: $query = "SELECT $function, $this->delimitedColumn FROM $this->delimitedName" . implode($join);
89: if ($this->where) {
90: $query .= ' WHERE (' . implode(') AND (', $this->where) . ')';
91: }
92: $query .= " GROUP BY $this->delimitedColumn";
93: $aggregation = & $this->refTable->aggregation[$query];
94: if ($aggregation === NULL) {
95: $aggregation = array();
96: foreach ($this->query($query, $this->parameters) as $row) {
97: $aggregation[$row[$this->column]] = $row;
98: }
99: }
100:
101: foreach ($aggregation[$this->active] as $val) {
102: return $val;
103: }
104: }
105:
106:
107:
108: public function insert($data)
109: {
110: if ($data instanceof \Traversable && !$data instanceof TableSelection) {
111: $data = iterator_to_array($data);
112: }
113: if (is_array($data)) {
114: $data[$this->column] = $this->active;
115: }
116: return parent::insert($data);
117: }
118:
119:
120:
121: public function update($data)
122: {
123: $where = $this->where;
124: $this->where[0] = "$this->delimitedColumn = " . $this->connection->quote($this->active);
125: $return = parent::update($data);
126: $this->where = $where;
127: return $return;
128: }
129:
130:
131:
132: public function delete()
133: {
134: $where = $this->where;
135: $this->where[0] = "$this->delimitedColumn = " . $this->connection->quote($this->active);
136: $return = parent::delete();
137: $this->where = $where;
138: return $return;
139: }
140:
141:
142:
143: protected function execute()
144: {
145: if ($this->rows !== NULL) {
146: return;
147: }
148:
149: $referencing = & $this->refTable->referencing[$this->getSql()];
150: if ($referencing === NULL) {
151: $limit = $this->limit;
152: $rows = count($this->refTable->rows);
153: if ($this->limit && $rows > 1) {
154: $this->limit = NULL;
155: }
156: parent::execute();
157: $this->limit = $limit;
158: $referencing = array();
159: $offset = array();
160: foreach ($this->rows as $key => $row) {
161: $ref = & $referencing[$row[$this->column]];
162: $skip = & $offset[$row[$this->column]];
163: if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->offset)) {
164: $ref[$key] = $row;
165: } else {
166: unset($this->rows[$key]);
167: }
168: $skip++;
169: unset($ref, $skip);
170: }
171: }
172:
173: $this->data = & $referencing[$this->active];
174: if ($this->data === NULL) {
175: $this->data = array();
176: }
177: }
178:
179: }
180: