Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • ActiveRow
  • GroupedSelection
  • Selection
  • SqlBuilder
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  */
 11: 
 12: namespace Nette\Database\Table;
 13: 
 14: use Nette;
 15: 
 16: 
 17: /**
 18:  * Representation of filtered table grouped by some column.
 19:  * GroupedSelection is based on the great library NotORM http://www.notorm.com written by Jakub Vrana.
 20:  *
 21:  * @author     Jakub Vrana
 22:  * @author     Jan Skrasek
 23:  */
 24: class GroupedSelection extends Selection
 25: {
 26:     /** @var Selection referenced table */
 27:     protected $refTable;
 28: 
 29:     /** @var string grouping column name */
 30:     protected $column;
 31: 
 32:     /** @var int primary key */
 33:     protected $active;
 34: 
 35: 
 36:     /**
 37:      * Creates filtered and grouped table representation.
 38:      * @param  Selection  $refTable
 39:      * @param  string  database table name
 40:      * @param  string  joining column
 41:      */
 42:     public function __construct(Selection $refTable, $table, $column)
 43:     {
 44:         parent::__construct($table, $refTable->connection);
 45:         $this->refTable = $refTable;
 46:         $this->column = $column;
 47:     }
 48: 
 49: 
 50:     /**
 51:      * Sets active group.
 52:      * @internal
 53:      * @param  int  primary key of grouped rows
 54:      * @return GroupedSelection
 55:      */
 56:     public function setActive($active)
 57:     {
 58:         $this->active = $active;
 59:         return $this;
 60:     }
 61: 
 62: 
 63:     /** @deprecated */
 64:     public function through($column)
 65:     {
 66:         trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::related("' . $this->name . '", "' . $column . '") instead.', E_USER_WARNING);
 67:         $this->column = $column;
 68:         $this->delimitedColumn = $this->refTable->connection->getSupplementalDriver()->delimite($this->column);
 69:         return $this;
 70:     }
 71: 
 72: 
 73:     public function select($columns)
 74:     {
 75:         if (!$this->sqlBuilder->getSelect()) {
 76:             $this->sqlBuilder->addSelect("$this->name.$this->column");
 77:         }
 78: 
 79:         return parent::select($columns);
 80:     }
 81: 
 82: 
 83:     public function order($columns)
 84:     {
 85:         if (!$this->sqlBuilder->getOrder()) {
 86:             // improve index utilization
 87:             $this->sqlBuilder->addOrder("$this->name.$this->column" . (preg_match('~\bDESC\z~i', $columns) ? ' DESC' : ''));
 88:         }
 89: 
 90:         return parent::order($columns);
 91:     }
 92: 
 93: 
 94:     /********************* aggregations ****************d*g**/
 95: 
 96: 
 97:     public function aggregation($function)
 98:     {
 99:         $aggregation = & $this->getRefTable($refPath)->aggregation[$refPath . $function . $this->getSql() . json_encode($this->sqlBuilder->getParameters())];
100: 
101:         if ($aggregation === NULL) {
102:             $aggregation = array();
103: 
104:             $selection = $this->createSelectionInstance();
105:             $selection->getSqlBuilder()->importConditions($this->getSqlBuilder());
106:             $selection->select($function);
107:             $selection->select("$this->name.$this->column");
108:             $selection->group("$this->name.$this->column");
109: 
110:             foreach ($selection as $row) {
111:                 $aggregation[$row[$this->column]] = $row;
112:             }
113:         }
114: 
115:         if (isset($aggregation[$this->active])) {
116:             foreach ($aggregation[$this->active] as $val) {
117:                 return $val;
118:             }
119:         }
120:     }
121: 
122: 
123:     public function count($column = NULL)
124:     {
125:         $return = parent::count($column);
126:         return isset($return) ? $return : 0;
127:     }
128: 
129: 
130:     /********************* internal ****************d*g**/
131: 
132: 
133:     protected function execute()
134:     {
135:         if ($this->rows !== NULL) {
136:             $this->observeCache = $this;
137:             return;
138:         }
139: 
140:         $hash = md5($this->getSql() . json_encode($this->sqlBuilder->getParameters()));
141:         $accessedColumns = $this->accessedColumns;
142: 
143:         $referencingBase = & $this->getRefTable($refPath)->referencing[$this->getCacheKey()];
144:         $referencing = & $referencingBase[$refPath . $hash];
145:         $this->rows = & $referencing['rows'];
146:         $this->referenced = & $referencing['refs'];
147:         $this->accessedColumns = & $referencing['accessed'];
148:         $this->observeCache = & $referencingBase['observeCache'];
149:         $refData = & $referencing['data'];
150: 
151:         if ($refData === NULL) {
152:             // we have not fetched any data => init accessedColumns by cached accessedColumns
153:             $this->accessedColumns = $accessedColumns;
154: 
155:             $limit = $this->sqlBuilder->getLimit();
156:             $rows = count($this->refTable->rows);
157:             if ($limit && $rows > 1) {
158:                 $this->sqlBuilder->setLimit(NULL, NULL);
159:             }
160:             parent::execute();
161:             $this->sqlBuilder->setLimit($limit, NULL);
162:             $refData = array();
163:             $offset = array();
164:             $this->accessColumn($this->column);
165:             foreach ((array) $this->rows as $key => $row) {
166:                 $ref = & $refData[$row[$this->column]];
167:                 $skip = & $offset[$row[$this->column]];
168:                 if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->sqlBuilder->getOffset())) {
169:                     $ref[$key] = $row;
170:                 } else {
171:                     unset($this->rows[$key]);
172:                 }
173:                 $skip++;
174:                 unset($ref, $skip);
175:             }
176:         }
177: 
178:         $this->observeCache = $this;
179:         $this->data = & $refData[$this->active];
180:         if ($this->data === NULL) {
181:             $this->data = array();
182:         } else {
183:             foreach ($this->data as $row) {
184:                 $row->setTable($this); // injects correct parent GroupedSelection
185:             }
186:             reset($this->data);
187:             $this->checkReferenced = TRUE;
188:         }
189:     }
190: 
191: 
192:     protected function getRefTable(& $refPath)
193:     {
194:         $refObj = $this->refTable;
195:         $refPath = $this->name . '.';
196:         while ($refObj instanceof GroupedSelection) {
197:             $refPath .= $refObj->name . '.';
198:             $refObj = $refObj->refTable;
199:         }
200: 
201:         return $refObj;
202:     }
203: 
204: 
205:     /********************* manipulation ****************d*g**/
206: 
207: 
208:     public function insert($data)
209:     {
210:         if ($data instanceof \Traversable && !$data instanceof Selection) {
211:             $data = iterator_to_array($data);
212:         }
213: 
214:         if (Nette\Utils\Validators::isList($data)) {
215:             foreach (array_keys($data) as $key) {
216:                 $data[$key][$this->column] = $this->active;
217:             }
218:         } else {
219:             $data[$this->column] = $this->active;
220:         }
221: 
222:         return parent::insert($data);
223:     }
224: 
225: 
226:     public function update($data)
227:     {
228:         $builder = $this->sqlBuilder;
229: 
230:         $this->sqlBuilder = clone $this->sqlBuilder;
231:         $this->where($this->column, $this->active);
232:         $return = parent::update($data);
233: 
234:         $this->sqlBuilder = $builder;
235:         return $return;
236:     }
237: 
238: 
239:     public function delete()
240:     {
241:         $builder = $this->sqlBuilder;
242: 
243:         $this->sqlBuilder = clone $this->sqlBuilder;
244:         $this->where($this->column, $this->active);
245:         $return = parent::delete();
246: 
247:         $this->sqlBuilder = $builder;
248:         return $return;
249:     }
250: 
251: }
252: 
Nette Framework 2.0.11 API API documentation generated by ApiGen 2.8.0