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