PageRenderTime 111ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/Nette/Database/Table/GroupedSelection.php

http://github.com/nette/nette
PHP | 206 lines | 135 code | 52 blank | 19 comment | 19 complexity | 20a47b7b125e22fe88ba842f4db4beef MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (http://nette.org)
  4. *
  5. * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  6. *
  7. * For the full copyright and license information, please view
  8. * the file license.txt that was distributed with this source code.
  9. */
  10. namespace Nette\Database\Table;
  11. use Nette;
  12. /**
  13. * Representation of filtered table grouped by some column.
  14. * GroupedSelection is based on the great library NotORM http://www.notorm.com written by Jakub Vrana.
  15. *
  16. * @author Jakub Vrana
  17. */
  18. class GroupedSelection extends Selection
  19. {
  20. /** @var Selection referenced table */
  21. private $refTable;
  22. /** @var string grouping column name */
  23. private $column;
  24. /** @var string */
  25. private $delimitedColumn;
  26. /** @var mixed */
  27. private $active;
  28. public function __construct($name, Selection $refTable, $column, $active = NULL)
  29. {
  30. parent::__construct($name, $refTable->connection);
  31. $this->refTable = $refTable;
  32. $this->column = $column;
  33. $this->delimitedColumn = $this->connection->getSupplementalDriver()->delimite($this->column);
  34. $this->active = $active;
  35. }
  36. /** @deprecated */
  37. public function through($column)
  38. {
  39. trigger_error(__METHOD__ . '() is deprecated; use ' . __CLASS__ . '::related("' . $this->name . '", "' . $column . '") instead.', E_USER_WARNING);
  40. $this->column = $column;
  41. $this->delimitedColumn = $this->refTable->connection->getSupplementalDriver()->delimite($this->column);
  42. return $this;
  43. }
  44. public function select($columns)
  45. {
  46. if (!$this->select) {
  47. $this->select[] = "$this->delimitedName.$this->delimitedColumn";
  48. }
  49. return parent::select($columns);
  50. }
  51. public function order($columns)
  52. {
  53. if (!$this->order) { // improve index utilization
  54. $this->order[] = "$this->delimitedName.$this->delimitedColumn"
  55. . (preg_match('~\\bDESC$~i', $columns) ? ' DESC' : '');
  56. }
  57. return parent::order($columns);
  58. }
  59. public function aggregation($function)
  60. {
  61. $aggregation = & $this->refTable->aggregation[$function . implode('', $this->where) . implode('', $this->conditions)];
  62. if ($aggregation === NULL) {
  63. $aggregation = array();
  64. $selection = new Selection($this->name, $this->connection);
  65. $selection->where = $this->where;
  66. $selection->parameters = $this->parameters;
  67. $selection->conditions = $this->conditions;
  68. $selection->select($function);
  69. $selection->select("{$this->name}.{$this->column}");
  70. $selection->group("{$this->name}.{$this->column}");
  71. foreach ($selection as $row) {
  72. $aggregation[$row[$this->column]] = $row;
  73. }
  74. }
  75. if (isset($aggregation[$this->active])) {
  76. foreach ($aggregation[$this->active] as $val) {
  77. return $val;
  78. }
  79. }
  80. }
  81. public function count($column = '')
  82. {
  83. $return = parent::count($column);
  84. return isset($return) ? $return : 0;
  85. }
  86. public function insert($data)
  87. {
  88. if ($data instanceof \Traversable && !$data instanceof Selection) {
  89. $data = iterator_to_array($data);
  90. }
  91. if (Nette\Utils\Validators::isList($data)) {
  92. foreach (array_keys($data) as $key) {
  93. $data[$key][$this->column] = $this->active;
  94. }
  95. } else {
  96. $data[$this->column] = $this->active;
  97. }
  98. return parent::insert($data);
  99. }
  100. public function update($data)
  101. {
  102. $condition = array($this->where, $this->parameters);
  103. $this->where[0] = "$this->delimitedColumn = ?";
  104. $this->parameters[0] = $this->active;
  105. $return = parent::update($data);
  106. list($this->where, $this->parameters) = $condition;
  107. return $return;
  108. }
  109. public function delete()
  110. {
  111. $condition = array($this->where, $this->parameters);
  112. $this->where[0] = "$this->delimitedColumn = ?";
  113. $this->parameters[0] = $this->active;
  114. $return = parent::delete();
  115. list($this->where, $this->parameters) = $condition;
  116. return $return;
  117. }
  118. protected function execute()
  119. {
  120. if ($this->rows !== NULL) {
  121. return;
  122. }
  123. $hash = md5($this->getSql() . json_encode($this->parameters));
  124. $referencing = & $this->refTable->referencing[$hash];
  125. if ($referencing === NULL) {
  126. $limit = $this->limit;
  127. $rows = count($this->refTable->rows);
  128. if ($this->limit && $rows > 1) {
  129. $this->limit = NULL;
  130. }
  131. parent::execute();
  132. $this->limit = $limit;
  133. $referencing = array();
  134. $offset = array();
  135. foreach ($this->rows as $key => $row) {
  136. $ref = & $referencing[$row[$this->column]];
  137. $skip = & $offset[$row[$this->column]];
  138. if ($limit === NULL || $rows <= 1 || (count($ref) < $limit && $skip >= $this->offset)) {
  139. $ref[$key] = $row;
  140. } else {
  141. unset($this->rows[$key]);
  142. }
  143. $skip++;
  144. unset($ref, $skip);
  145. }
  146. }
  147. $this->data = & $referencing[$this->active];
  148. if ($this->data === NULL) {
  149. $this->data = array();
  150. } else {
  151. reset($this->data);
  152. }
  153. }
  154. }