1: <?php
2:
3: 4: 5: 6: 7:
8:
9:
10:
11: 12: 13: 14: 15: 16: 17: 18:
19: class GroupedTableSelection extends TableSelection
20: {
21:
22: protected $refTable;
23:
24:
25: protected $column;
26:
27:
28: protected $active;
29:
30:
31: 32: 33: 34: 35: 36:
37: public function __construct(TableSelection $refTable, $table, $column)
38: {
39: parent::__construct($table, $refTable->connection);
40: $this->refTable = $refTable;
41: $this->column = $column;
42: }
43:
44:
45: 46: 47: 48: 49: 50:
51: public function setActive($active)
52: {
53: $this->active = $active;
54: return $this;
55: }
56:
57:
58:
59: public function through($column)
60: {
61: trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::related("' . $this->name . '", "' . $column . '") instead.', E_USER_WARNING);
62: $this->column = $column;
63: $this->delimitedColumn = $this->refTable->connection->getSupplementalDriver()->delimite($this->column);
64: return $this;
65: }
66:
67:
68: public function select($columns)
69: {
70: if (!$this->sqlBuilder->getSelect()) {
71: $this->sqlBuilder->addSelect("$this->name.$this->column");
72: }
73:
74: return parent::select($columns);
75: }
76:
77:
78: public function order($columns)
79: {
80: if (!$this->sqlBuilder->getOrder()) {
81:
82: $this->sqlBuilder->addOrder("$this->name.$this->column" . (preg_match('~\bDESC\z~i', $columns) ? ' DESC' : ''));
83: }
84:
85: return parent::order($columns);
86: }
87:
88:
89:
90:
91:
92: public function aggregation($function)
93: {
94: $aggregation = & $this->getRefTable($refPath)->aggregation[$refPath . $function . $this->getSql() . json_encode($this->sqlBuilder->getParameters())];
95:
96: if ($aggregation === NULL) {
97: $aggregation = array();
98:
99: $selection = $this->createSelectionInstance();
100: $selection->getSqlBuilder()->importConditions($this->getSqlBuilder());
101: $selection->select($function);
102: $selection->select("$this->name.$this->column");
103: $selection->group("$this->name.$this->column");
104:
105: foreach ($selection as $row) {
106: $aggregation[$row[$this->column]] = $row;
107: }
108: }
109:
110: if (isset($aggregation[$this->active])) {
111: foreach ($aggregation[$this->active] as $val) {
112: return $val;
113: }
114: }
115: }
116:
117:
118: public function count($column = NULL)
119: {
120: $return = parent::count($column);
121: return isset($return) ? $return : 0;
122: }
123:
124:
125:
126:
127:
128: protected function execute()
129: {
130: if ($this->rows !== NULL) {
131: $this->observeCache = $this;
132: return;
133: }
134:
135: $hash = md5($this->getSql() . json_encode($this->sqlBuilder->getParameters()));
136: $accessedColumns = $this->accessedColumns;
137:
138: $referencingBase = & $this->getRefTable($refPath)->referencing[$this->getCacheKey()];
139: $referencing = & $referencingBase[$refPath . $hash];
140: $this->rows = & $referencing['rows'];
141: $this->referenced = & $referencing['refs'];
142: $this->accessedColumns = & $referencing['accessed'];
143: $this->observeCache = & $referencingBase['observeCache'];
144: $refData = & $referencing['data'];
145:
146: if ($refData === NULL) {
147:
148: $this->accessedColumns = $accessedColumns;
149:
150: $limit = $this->sqlBuilder->getLimit();
151: $rows = count($this->refTable->rows);
152: if ($limit && $rows > 1) {
153: $this->sqlBuilder->setLimit(NULL, NULL);
154: }
155: parent::execute();
156: $this->sqlBuilder->setLimit($limit, NULL);
157: $refData = array();
158: $offset = array();
159: $this->accessColumn($this->column);
160: foreach ((array) $this->rows as $key => $row) {
161: $ref = & $refData[$row[$this->column]];
162: $skip = & $offset[$row[$this->column]];
163: if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->sqlBuilder->getOffset())) {
164: $ref[$key] = $row;
165: } else {
166: unset($this->rows[$key]);
167: }
168: $skip++;
169: unset($ref, $skip);
170: }
171: }
172:
173: $this->observeCache = $this;
174: $this->data = & $refData[$this->active];
175: if ($this->data === NULL) {
176: $this->data = array();
177: } else {
178: foreach ($this->data as $row) {
179: $row->setTable($this);
180: }
181: reset($this->data);
182: $this->checkReferenced = TRUE;
183: }
184: }
185:
186:
187: protected function getRefTable(& $refPath)
188: {
189: $refObj = $this->refTable;
190: $refPath = $this->name . '.';
191: while ($refObj instanceof GroupedTableSelection) {
192: $refPath .= $refObj->name . '.';
193: $refObj = $refObj->refTable;
194: }
195:
196: return $refObj;
197: }
198:
199:
200:
201:
202:
203: public function insert($data)
204: {
205: if ($data instanceof Traversable && !$data instanceof TableSelection) {
206: $data = iterator_to_array($data);
207: }
208:
209: if (Validators::isList($data)) {
210: foreach (array_keys($data) as $key) {
211: $data[$key][$this->column] = $this->active;
212: }
213: } else {
214: $data[$this->column] = $this->active;
215: }
216:
217: return parent::insert($data);
218: }
219:
220:
221: public function update($data)
222: {
223: $builder = $this->sqlBuilder;
224:
225: $this->sqlBuilder = clone $this->sqlBuilder;
226: $this->where($this->column, $this->active);
227: $return = parent::update($data);
228:
229: $this->sqlBuilder = $builder;
230: return $return;
231: }
232:
233:
234: public function delete()
235: {
236: $builder = $this->sqlBuilder;
237:
238: $this->sqlBuilder = clone $this->sqlBuilder;
239: $this->where($this->column, $this->active);
240: $return = parent::delete();
241:
242: $this->sqlBuilder = $builder;
243: return $return;
244: }
245:
246: }
247: