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