PageRenderTime 142ms CodeModel.GetById 20ms RepoModel.GetById 3ms app.codeStats 0ms

/berry/lib/berry/sql/vars.php

http://goodgirl.googlecode.com/
PHP | 302 lines | 196 code | 80 blank | 26 comment | 46 complexity | 7dcf81c3d32f63ffe5404cec4a994406 MD5 | raw file
  1. <?php /* `,
  2. ,\, #
  3. B E R R Y |/ ?
  4. <http://goodgirl.ru/berry> | ~ )\
  5. <http://goodgirl.ru/berry/license> /__/\ \____
  6. / \_/ \
  7. ???? zloy ? ???????? <http://lexa.cutenews.ru> / <_ ____,_-/\ __
  8. ---------------------------------------------------------/___/_____ \--'\|/----
  9. \/|*/
  10. abstract class SQL_Vars extends SQL_Etc implements ArrayAccess, Iterator {
  11. ////////////////////////////////////////////////////////////////////////////////
  12. function __isset($name){
  13. return isset($this[$name]);
  14. }
  15. ////////////////////////////////////////////////////////////////////////////////
  16. function __unset($name){ unset($this[$name]);
  17. }
  18. ////////////////////////////////////////////////////////////////////////////////
  19. function __get($name){
  20. return $this[$name];
  21. }
  22. ////////////////////////////////////////////////////////////////////////////////
  23. function __set($name, $value){ $this[$name] = $value;
  24. }
  25. ////////////////////////////////////////////////////////////////////////////////
  26. function offsetExists($offset){ if (
  27. $this[$offset] instanceof SQl or
  28. $this[$offset] instanceof SQl_Element
  29. )
  30. return (b::len($this[$offset]) > 0);
  31. return ($this[$offset] !== null);
  32. }
  33. ////////////////////////////////////////////////////////////////////////////////
  34. function offsetUnset($offset){ $this[$offset] = null;
  35. unset($this->values[$offset]);
  36. }
  37. ////////////////////////////////////////////////////////////////////////////////
  38. function offsetGet($offset){ return (method_exists($this, ($func = '_get_'.$offset)) ? $this->$func() : self::_get($offset));
  39. }
  40. ////////////////////////////////////////////////////////////////////////////////
  41. function offsetSet($offset, $value){
  42. method_exists($this, ($func = '_set_'.$offset)) ? $this->$func($value) : self::_set($offset, $value);
  43. }
  44. ////////////////////////////////////////////////////////////////////////////////
  45. function rewind(){ if (!isset($this->iterator)){ if ($len = b::len($this))
  46. $this->iterator = range(0, ($len - 1));
  47. else
  48. $this->iterator = array();
  49. }
  50. return reset($this->iterator);
  51. }
  52. ////////////////////////////////////////////////////////////////////////////////
  53. function key(){
  54. return key($this->iterator);
  55. }
  56. ////////////////////////////////////////////////////////////////////////////////
  57. function current(){
  58. return $this[current($this->iterator)];
  59. }
  60. ////////////////////////////////////////////////////////////////////////////////
  61. function next(){
  62. next($this->iterator);
  63. }
  64. ////////////////////////////////////////////////////////////////////////////////
  65. function valid(){
  66. return (current($this->iterator) !== false);
  67. }
  68. ////////////////////////////////////////////////////////////////////////////////
  69. protected function _get($name){ $key = self::hash('_get');
  70. if ($this->select and !isset(self::$cache[$key])){
  71. $class = clone $this;
  72. $class->select[] = $class->primary_key;
  73. self::$cache[$key] = new SQL_Element($class->fetch_array());
  74. }
  75. if (
  76. isset(self::$cache[$key][$name]) or
  77. (is_array(self::$cache[$key]) and array_key_exists($name, self::$cache[$key]))
  78. )
  79. return self::$cache[$key][$name];
  80. if (is_null($name)){
  81. $key = ($this->parallel ? (max(array_keys($this->parallel)) + 1) : 0);
  82. if ($this->where and $key < ($count = b::len($this)))
  83. $key = $count;
  84. $class = clone $this;
  85. $class->parallel = $class->where = array();
  86. return $this->parallel[$key] = $class;
  87. }
  88. if (isset($this->values[$name]))
  89. return $this->values[$name];
  90. if ($this->relations[$name]){
  91. if (!isset($this->parallel[$name]))
  92. $this->parallel[$name] = self::_object($name);
  93. return $this->parallel[$name];
  94. }
  95. if (is_int($name)){
  96. if (!isset($this->parallel[$name])){
  97. if ($this->parent and !$this->where)
  98. return;
  99. $class = clone $this;
  100. $class->parallel = array();
  101. $class->select = $class->group_by = array($this->primary_key);
  102. $array = $class->fetch_col();
  103. if (!$class->id = $array[$name])
  104. return;
  105. $class->select = $this->select;
  106. $class->group_by = $this->group_by;
  107. $class->where($this->primary_key.' = ?d', $class->id);
  108. $this->parallel[$name] = $class;
  109. }
  110. return $this->parallel[$name];
  111. }
  112. if ($_name = self::_is_HABTM($name)){
  113. $relation = $this->relations[$_name];
  114. if ($id = $this[$relation['local']['field']]){
  115. $foreign = $relation['foreign'];
  116. $this->values[$name] = new ArrayObject(
  117. self::table($foreign['table1'])->
  118. select($foreign['field3'])->
  119. where($foreign['field1'].' = ?', $id)->
  120. fetch_col()
  121. );
  122. } else {
  123. $this->values[$name] = new ArrayObject;
  124. }
  125. $tmp = (array)$this->values[$name];
  126. sort($tmp);
  127. self::$cache[$this->table][$name] = $tmp;
  128. return $this->values[$name];
  129. }
  130. if (!isset($this->parallel[$this->alias])){ $array = ($this->where ? $this->fetch_array() : array());
  131. $this->parallel[$this->alias] = new SQL_Element($array);
  132. }
  133. return $this->parallel[$this->alias][$name];
  134. }
  135. ////////////////////////////////////////////////////////////////////////////////
  136. protected function _set($name, $value){ $key = self::hash('_get');
  137. if (is_array($value) or $value instanceof SQL){ if ($name === null)
  138. $name = max(array_keys($this->parallel));
  139. if ($class = self::_get($name)){ $values = (is_array($value) ? $value : $value->values);
  140. foreach ($values as $k => $v)
  141. $class[$k] = $v;
  142. if (!$this->id or !is_int($name))
  143. return;
  144. $value = $class;
  145. }
  146. } elseif (is_int($value) or is_float($value)){ self::$cache[$key.'[+-]'][$name][] = ($value - $this[$name]);
  147. self::$cache[$key][$name] = $value;
  148. if ($sum = array_sum(self::$cache[$key.'[+-]'][$name]))
  149. $value = self::raw(sprintf('(%s + %s)', $name, $sum));
  150. else return;
  151. } elseif ($value === null){ if ($value === $this[$name])
  152. return;
  153. $value = self::raw('null');
  154. self::$cache[$key][$name] = null; }
  155. if ($name === null){ $this->values[] = $value;
  156. } elseif (self::_is_HABTM($name)){ $this->values[$name] = new ArrayObject($value); } else { if ($value === $this[$name])
  157. return;
  158. $this->values[$name] = $value;
  159. }
  160. if ($relation = $this->relations['#']){
  161. $local = $relation['local'];
  162. $foreign = $relation['foreign'];
  163. if ($relation['type'] == 'has_one' and !$this->parent[$local['field']]){
  164. $class = clone $this->parent;
  165. $class->parallel = array();
  166. $class->values = array('#'.$local['field'] => $foreign['alias']);
  167. $this->parent->parallel[] = $class;
  168. }
  169. if ($relation['type'] == 'belongs_to' or $relation['type'] == 'has_many'){
  170. if ($this->parent->id)
  171. $this->values[$foreign['field']] = $this->parent->id;
  172. else
  173. $this->values['#'.$foreign['field']] = $local['alias'];
  174. }
  175. if ($relation['type'] == 'has_and_belongs_to_many' and !$this->id){
  176. $class = self::table($foreign['alias1']);
  177. $class->parallel = array();
  178. $class->values = array('#'.$foreign['field3'] => inflector::singular($foreign['alias2']));
  179. if ($this->parent->id)
  180. $class->values[$foreign['field1']] = $this->parent->id;
  181. else
  182. $class->values['#'.$foreign['field1']] = $local['alias'];
  183. $this->parent->parallel[] = $class;
  184. }
  185. }
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////
  188. protected function _is_HABTM($name){ if (
  189. substr($name, -4) == '_ids' and
  190. ($_name = substr($name, 0, -4)) and
  191. ($relation = $this->relations[$_name]) and
  192. $relation['type'] == 'has_and_belongs_to_many'
  193. )
  194. return $_name; }
  195. ////////////////////////////////////////////////////////////////////////////////
  196. protected function _object($name){
  197. $relation = $this->relations[$name];
  198. $local = $relation['local'];
  199. $foreign = $relation['foreign'];
  200. $name = inflector::singular($name);
  201. $class = self::table($name);
  202. $class->parent = $this;
  203. $class->relations['#'] = $relation;
  204. if (!$id = $this[$local['field']])
  205. return $class;
  206. if ($relation['type'] == 'has_and_belongs_to_many'){ $ids = self::table($foreign['table1'])->
  207. select($foreign['field3'])->
  208. where($foreign['field1'].' = ?d', $id)->
  209. fetch_col();
  210. return $class->where_between($name.'.'.$foreign['field2'], $ids);
  211. }
  212. $class->where($foreign['field'].' = ?d', $id);
  213. if ($relation['type'] == 'has_one'){
  214. $class->id = $id;
  215. } elseif ($relation['type'] == 'belongs_to'){
  216. $class->id = -1;
  217. $class->limit = 1;
  218. }
  219. return $class;
  220. }
  221. ////////////////////////////////////////////////////////////////////////////////
  222. }