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

Classes

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