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" . (preg_match('~\\bDESC$~i', $columns) ? ' DESC' : '');
77: }
78: return parent::order($columns);
79: }
80:
81:
82:
83: public function aggregation($function)
84: {
85: $join = $this->createJoins(implode(',', $this->conditions), TRUE) + $this->createJoins($function);
86: $column = ($join ? "$this->table." : '') . $this->column;
87: $query = "SELECT $function, $this->delimitedColumn FROM $this->delimitedName" . implode($join);
88: if ($this->where) {
89: $query .= ' WHERE (' . implode(') AND (', $this->where) . ')';
90: }
91: $query .= " GROUP BY $this->delimitedColumn";
92: $aggregation = & $this->refTable->aggregation[$query];
93: if ($aggregation === NULL) {
94: $aggregation = array();
95: foreach ($this->query($query, $this->parameters) as $row) {
96: $aggregation[$row[$this->column]] = $row;
97: }
98: }
99:
100: foreach ($aggregation[$this->active] as $val) {
101: return $val;
102: }
103: }
104:
105:
106:
107: public function insert($data)
108: {
109: if ($data instanceof \Traversable && !$data instanceof TableSelection) {
110: $data = iterator_to_array($data);
111: }
112: if (is_array($data)) {
113: $data[$this->column] = $this->active;
114: }
115: return parent::insert($data);
116: }
117:
118:
119:
120: public function update($data)
121: {
122: $where = $this->where;
123: $this->where[0] = "$this->delimitedColumn = " . $this->connection->quote($this->active);
124: $return = parent::update($data);
125: $this->where = $where;
126: return $return;
127: }
128:
129:
130:
131: public function delete()
132: {
133: $where = $this->where;
134: $this->where[0] = "$this->delimitedColumn = " . $this->connection->quote($this->active);
135: $return = parent::delete();
136: $this->where = $where;
137: return $return;
138: }
139:
140:
141:
142: protected function execute()
143: {
144: if ($this->rows !== NULL) {
145: return;
146: }
147:
148: $referencing = & $this->refTable->referencing[$this->getSql()];
149: if ($referencing === NULL) {
150: $limit = $this->limit;
151: $rows = count($this->refTable->rows);
152: if ($this->limit && $rows > 1) {
153: $this->limit = NULL;
154: }
155: parent::execute();
156: $this->limit = $limit;
157: $referencing = array();
158: $offset = array();
159: foreach ($this->rows as $key => $row) {
160: $ref = & $referencing[$row[$this->column]];
161: $skip = & $offset[$row[$this->column]];
162: if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->offset)) {
163: $ref[$key] = $row;
164: } else {
165: unset($this->rows[$key]);
166: }
167: $skip++;
168: unset($ref, $skip);
169: }
170: }
171:
172: $this->data = & $referencing[$this->active];
173: if ($this->data === NULL) {
174: $this->data = array();
175: }
176: }
177:
178: }
179: