1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Database\Table;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22: 23:
24: class GroupedSelection extends Selection
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, Selection $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->delimitedName." : '') . $this->delimitedColumn;
88: $query = "SELECT $function, $column FROM $this->delimitedName" . implode($join);
89: if ($this->where) {
90: $query .= ' WHERE (' . implode(') AND (', $this->where) . ')';
91: }
92: $query .= " GROUP BY $column";
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:
102: if (isset($aggregation[$this->active])) {
103: foreach ($aggregation[$this->active] as $val) {
104: return $val;
105: }
106: }
107: }
108:
109:
110:
111: public function count($column = '')
112: {
113: $return = parent::count($column);
114: return isset($return) ? $return : 0;
115: }
116:
117:
118:
119: public function insert($data)
120: {
121: if ($data instanceof \Traversable && !$data instanceof Selection) {
122: $data = iterator_to_array($data);
123: }
124: if (is_array($data)) {
125: $data[$this->column] = $this->active;
126: }
127: return parent::insert($data);
128: }
129:
130:
131:
132: public function update($data)
133: {
134: $where = $this->where;
135: $this->where[0] = "$this->delimitedColumn = " . $this->connection->quote($this->active);
136: $return = parent::update($data);
137: $this->where = $where;
138: return $return;
139: }
140:
141:
142:
143: public function delete()
144: {
145: $where = $this->where;
146: $this->where[0] = "$this->delimitedColumn = " . $this->connection->quote($this->active);
147: $return = parent::delete();
148: $this->where = $where;
149: return $return;
150: }
151:
152:
153:
154: protected function execute()
155: {
156: if ($this->rows !== NULL) {
157: return;
158: }
159:
160: $referencing = & $this->refTable->referencing[$this->getSql()];
161: if ($referencing === NULL) {
162: $limit = $this->limit;
163: $rows = count($this->refTable->rows);
164: if ($this->limit && $rows > 1) {
165: $this->limit = NULL;
166: }
167: parent::execute();
168: $this->limit = $limit;
169: $referencing = array();
170: $offset = array();
171: foreach ($this->rows as $key => $row) {
172: $ref = & $referencing[$row[$this->column]];
173: $skip = & $offset[$row[$this->column]];
174: if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->offset)) {
175: $ref[$key] = $row;
176: } else {
177: unset($this->rows[$key]);
178: }
179: $skip++;
180: unset($ref, $skip);
181: }
182: }
183:
184: $this->data = & $referencing[$this->active];
185: if ($this->data === NULL) {
186: $this->data = array();
187: }
188: }
189:
190: }
191: