Packages

  • 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

  • Overview
  • Package
  • 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:  * @package Nette\Database\Table
  7:  */
  8: 
  9: 
 10: 
 11: /**
 12:  * Representation of filtered table grouped by some column.
 13:  * GroupedSelection is based on the great library NotORM http://www.notorm.com written by Jakub Vrana.
 14:  *
 15:  * @author     Jakub Vrana
 16:  * @author     Jan Skrasek
 17:  * @package Nette\Database\Table
 18:  */
 19: class GroupedTableSelection extends TableSelection
 20: {
 21:     /** @var TableSelection referenced table */
 22:     protected $refTable;
 23: 
 24:     /** @var string grouping column name */
 25:     protected $column;
 26: 
 27:     /** @var int primary key */
 28:     protected $active;
 29: 
 30: 
 31:     /**
 32:      * Creates filtered and grouped table representation.
 33:      * @param  TableSelection  $refTable
 34:      * @param  string  database table name
 35:      * @param  string  joining column
 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:      * Sets active group.
 47:      * @internal
 48:      * @param  int  primary key of grouped rows
 49:      * @return GroupedTableSelection
 50:      */
 51:     public function setActive($active)
 52:     {
 53:         $this->active = $active;
 54:         return $this;
 55:     }
 56: 
 57: 
 58:     /** @deprecated */
 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:             // improve index utilization
 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:     /********************* aggregations ****************d*g**/
 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:     /********************* internal ****************d*g**/
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:             // we have not fetched any data => init accessedColumns by cached accessedColumns
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); // injects correct parent GroupedSelection
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:     /********************* manipulation ****************d*g**/
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: 
Nette Framework 2.0.18 (for PHP 5.2, un-prefixed) API documentation generated by ApiGen 2.8.0