PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/nette/database/src/Database/Table/ActiveRow.php

https://gitlab.com/paveltizek/shop
PHP | 340 lines | 191 code | 67 blank | 82 comment | 28 complexity | 5638a33f166dc17ece8f9edd67a282b8 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (https://nette.org)
  4. * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  5. */
  6. namespace Nette\Database\Table;
  7. use Nette;
  8. /**
  9. * Single row representation.
  10. * ActiveRow is based on the great library NotORM http://www.notorm.com written by Jakub Vrana.
  11. */
  12. class ActiveRow implements \IteratorAggregate, IRow
  13. {
  14. /** @var Selection */
  15. private $table;
  16. /** @var array of row data */
  17. private $data;
  18. /** @var bool */
  19. private $dataRefreshed = FALSE;
  20. public function __construct(array $data, Selection $table)
  21. {
  22. $this->data = $data;
  23. $this->table = $table;
  24. }
  25. /**
  26. * @internal
  27. */
  28. public function setTable(Selection $table)
  29. {
  30. $this->table = $table;
  31. }
  32. /**
  33. * @internal
  34. */
  35. public function getTable()
  36. {
  37. return $this->table;
  38. }
  39. public function __toString()
  40. {
  41. try {
  42. return (string) $this->getPrimary();
  43. } catch (\Throwable $e) {
  44. } catch (\Exception $e) {
  45. }
  46. if (isset($e)) {
  47. if (func_num_args()) {
  48. throw $e;
  49. }
  50. trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
  51. }
  52. }
  53. /**
  54. * @return array
  55. */
  56. public function toArray()
  57. {
  58. $this->accessColumn(NULL);
  59. return $this->data;
  60. }
  61. /**
  62. * Returns primary key value.
  63. * @param bool
  64. * @return mixed possible int, string, array, object (Nette\Utils\DateTime)
  65. */
  66. public function getPrimary($need = TRUE)
  67. {
  68. $primary = $this->table->getPrimary($need);
  69. if ($primary === NULL) {
  70. return NULL;
  71. } elseif (!is_array($primary)) {
  72. if (isset($this->data[$primary])) {
  73. return $this->data[$primary];
  74. } elseif ($need) {
  75. throw new Nette\InvalidStateException("Row does not contain primary $primary column data.");
  76. } else {
  77. return NULL;
  78. }
  79. } else {
  80. $primaryVal = array();
  81. foreach ($primary as $key) {
  82. if (!isset($this->data[$key])) {
  83. if ($need) {
  84. throw new Nette\InvalidStateException("Row does not contain primary $key column data.");
  85. } else {
  86. return NULL;
  87. }
  88. }
  89. $primaryVal[$key] = $this->data[$key];
  90. }
  91. return $primaryVal;
  92. }
  93. }
  94. /**
  95. * Returns row signature (composition of primary keys)
  96. * @param bool
  97. * @return string
  98. */
  99. public function getSignature($need = TRUE)
  100. {
  101. return implode('|', (array) $this->getPrimary($need));
  102. }
  103. /**
  104. * Returns referenced row.
  105. * @param string
  106. * @param string
  107. * @return IRow or NULL if the row does not exist
  108. */
  109. public function ref($key, $throughColumn = NULL)
  110. {
  111. $row = $this->table->getReferencedTable($this, $key, $throughColumn);
  112. if ($row === FALSE) {
  113. throw new Nette\MemberAccessException("No reference found for \${$this->table->name}->ref($key).");
  114. }
  115. return $row;
  116. }
  117. /**
  118. * Returns referencing rows.
  119. * @param string
  120. * @param string
  121. * @return GroupedSelection
  122. */
  123. public function related($key, $throughColumn = NULL)
  124. {
  125. $groupedSelection = $this->table->getReferencingTable($key, $throughColumn, $this[$this->table->getPrimary()]);
  126. if (!$groupedSelection) {
  127. throw new Nette\MemberAccessException("No reference found for \${$this->table->name}->related($key).");
  128. }
  129. return $groupedSelection;
  130. }
  131. /**
  132. * Updates row.
  133. * @param array|\Traversable (column => value)
  134. * @return bool
  135. */
  136. public function update($data)
  137. {
  138. if ($data instanceof \Traversable) {
  139. $data = iterator_to_array($data);
  140. }
  141. $primary = $this->getPrimary();
  142. if (!is_array($primary)) {
  143. $primary = array($this->table->getPrimary() => $primary);
  144. }
  145. $selection = $this->table->createSelectionInstance()
  146. ->wherePrimary($primary);
  147. if ($selection->update($data)) {
  148. if ($tmp = array_intersect_key($data, $primary)) {
  149. $selection = $this->table->createSelectionInstance()
  150. ->wherePrimary($tmp + $primary);
  151. }
  152. $selection->select('*');
  153. if (($row = $selection->fetch()) === FALSE) {
  154. throw new Nette\InvalidStateException('Database refetch failed; row does not exist!');
  155. }
  156. $this->data = $row->data;
  157. return TRUE;
  158. } else {
  159. return FALSE;
  160. }
  161. }
  162. /**
  163. * Deletes row.
  164. * @return int number of affected rows
  165. */
  166. public function delete()
  167. {
  168. $res = $this->table->createSelectionInstance()
  169. ->wherePrimary($this->getPrimary())
  170. ->delete();
  171. if ($res > 0 && ($signature = $this->getSignature(FALSE))) {
  172. unset($this->table[$signature]);
  173. }
  174. return $res;
  175. }
  176. /********************* interface IteratorAggregate ****************d*g**/
  177. public function getIterator()
  178. {
  179. $this->accessColumn(NULL);
  180. return new \ArrayIterator($this->data);
  181. }
  182. /********************* interface ArrayAccess & magic accessors ****************d*g**/
  183. /**
  184. * Stores value in column.
  185. * @param string column name
  186. * @param string value
  187. * @return void
  188. */
  189. public function offsetSet($key, $value)
  190. {
  191. $this->__set($key, $value);
  192. }
  193. /**
  194. * Returns value of column.
  195. * @param string column name
  196. * @return string
  197. */
  198. public function offsetGet($key)
  199. {
  200. return $this->__get($key);
  201. }
  202. /**
  203. * Tests if column exists.
  204. * @param string column name
  205. * @return bool
  206. */
  207. public function offsetExists($key)
  208. {
  209. return $this->__isset($key);
  210. }
  211. /**
  212. * Removes column from data.
  213. * @param string column name
  214. * @return void
  215. */
  216. public function offsetUnset($key)
  217. {
  218. $this->__unset($key);
  219. }
  220. public function __set($key, $value)
  221. {
  222. throw new Nette\DeprecatedException('ActiveRow is read-only; use update() method instead.');
  223. }
  224. /**
  225. * @param string
  226. * @return ActiveRow|mixed
  227. * @throws Nette\MemberAccessException
  228. */
  229. public function &__get($key)
  230. {
  231. if ($this->accessColumn($key)) {
  232. return $this->data[$key];
  233. }
  234. $referenced = $this->table->getReferencedTable($this, $key);
  235. if ($referenced !== FALSE) {
  236. $this->accessColumn($key, FALSE);
  237. return $referenced;
  238. }
  239. $this->removeAccessColumn($key);
  240. $hint = Nette\Utils\ObjectMixin::getSuggestion(array_keys($this->data), $key);
  241. throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'" . ($hint ? ", did you mean '$hint'?" : '.'));
  242. }
  243. public function __isset($key)
  244. {
  245. if ($this->accessColumn($key)) {
  246. return isset($this->data[$key]);
  247. }
  248. $this->removeAccessColumn($key);
  249. return FALSE;
  250. }
  251. public function __unset($key)
  252. {
  253. throw new Nette\DeprecatedException('ActiveRow is read-only.');
  254. }
  255. /**
  256. * @internal
  257. */
  258. public function accessColumn($key, $selectColumn = TRUE)
  259. {
  260. if ($this->table->accessColumn($key, $selectColumn) && !$this->dataRefreshed) {
  261. if (!isset($this->table[$this->getSignature()])) {
  262. throw new Nette\InvalidStateException('Database refetch failed; row does not exist!');
  263. }
  264. $this->data = $this->table[$this->getSignature()]->data;
  265. $this->dataRefreshed = TRUE;
  266. }
  267. return isset($this->data[$key]) || array_key_exists($key, $this->data);
  268. }
  269. protected function removeAccessColumn($key)
  270. {
  271. $this->table->removeAccessColumn($key);
  272. }
  273. }