/framework/application/data/YPFHasManyRelation.php

https://github.com/yonpols/ypframework · PHP · 351 lines · 279 code · 70 blank · 2 comment · 33 complexity · 868979ef7b6750fb4d314faac5a9cdaf MD5 · raw file

  1. <?php
  2. class YPFHasManyRelation extends YPFModelBaseRelation implements IYPFModelQuery, Iterator {
  3. protected $acceptsNested;
  4. protected $customQueries;
  5. protected $tiedModelQuery;
  6. protected $relatorInstance;
  7. protected $iterationQuery = null;
  8. protected $iterationKeys = null;
  9. protected $iterationPos = 0;
  10. protected function __construct($relatorModelName, $relationName, $relationParams) {
  11. $this->relationName = $relationName;
  12. $this->relationParams = $relationParams;
  13. $this->relatorModelName = $relatorModelName;
  14. $this->relatorModelParams = YPFModelBase::getModelParams($relatorModelName);
  15. $this->relatedModelName = $this->relationParams['has_many'];
  16. $this->relatedModelParams = YPFModelBase::getModelParams($this->relatedModelName);
  17. if (isset($this->relationParams['accepts_nested']))
  18. $this->acceptsNested = $this->relationParams['accepts_nested'];
  19. if ($this->relatedModelParams === null)
  20. throw new ErrorDataModel ($this->relatedModelName, 'Model not defined.');
  21. $sqlConditions = isset($relationParams['sqlConditions'])? arraize($relationParams['sqlConditions']): array();
  22. $sqlGrouping = isset($relationParams['sqlGrouping'])? arraize($relationParams['sqlGrouping']): array();
  23. $sqlOrdering = isset($relationParams['sqlOrdering'])? arraize($relationParams['sqlOrdering']): array();
  24. $this->customQueries = isset($relationParams['queries'])? arraize($relationParams['queries']): array();
  25. $this->customQueries = array_merge($this->customQueries, $this->relatedModelParams->customQueries);
  26. $model = $this->relatedModelName;
  27. $this->baseModelQuery = $model::all()->where($sqlConditions)->groupBy($sqlGrouping)->orderBy($sqlOrdering);
  28. $this->baseModelQuery->setCustomQueries($this->customQueries);
  29. if (isset($relationParams['alias'])) {
  30. $this->tableAlias = $relationParams['alias'];
  31. $this->baseModelQuery = $this->baseModelQuery->alias($this->tableAlias);
  32. }
  33. }
  34. public function __get($name) {
  35. if (isset($this->customQueries[$name]))
  36. return $this->tiedModelQuery->{$name};
  37. }
  38. public function toArray() {
  39. if (is_array($this->iterationQuery))
  40. return $this->iterationQuery;
  41. else
  42. return $this->tiedModelQuery->toArray();
  43. }
  44. public function get($relatorModel) {
  45. $relation = clone $this;
  46. $relation->tieToRelator($relatorModel);
  47. return $relation;
  48. }
  49. public function has($instance) {
  50. if (is_array($this->iterationQuery))
  51. return array_search ($instance, $this->iterationQuery);
  52. else
  53. return ($this->tiedModelQuery->where($instance->getSqlIdConditions($this->tiedModelQuery->getTableAlias()))->count() > 0);
  54. }
  55. public function set($relatorModel, $value)
  56. {
  57. if ($this->acceptsNested) {
  58. if ($this->inCache($relatorModel))
  59. $list = $this->getCache($relatorModel);
  60. else
  61. $list = array();
  62. $class = $this->relatedModelName;
  63. foreach ($value as $ikey => $idata) {
  64. if (isset($list[$ikey]))
  65. $item = $list[$ikey];
  66. else {
  67. $item = $class::find($idata);
  68. if (!$item)
  69. $item = new $class();
  70. }
  71. if (isset($idata['_delete']) && $idata['_delete']) {
  72. if (!$item->isNew())
  73. $item->delete();
  74. } else {
  75. $item->setAttributes($idata);
  76. if ($item->isNew())
  77. $list[$ikey] = $item;
  78. else
  79. $list[$item->getSerializedKey()] = $item;
  80. }
  81. }
  82. $this->setCache($relatorModel, $list);
  83. } else
  84. throw new ErrorDataModel($this->relatorModelName, sprintf('Can\'t assign values to has_many relation: %s', $this->relationName));
  85. }
  86. public function tieToRelator($relatorModel)
  87. {
  88. $this->relatorInstance = $relatorModel;
  89. $relatorKey = $relatorModel->getSerializedKey();
  90. $aliasPrefix = ($this->tableAlias !== null)? $this->tableAlias: $this->relatedModelParams->tableName;
  91. $whereConditions = array();
  92. foreach($this->relationParams['keys'] as $index=>$key)
  93. {
  94. if (is_numeric($index))
  95. $whereConditions[sprintf('`%s`.`%s`', $aliasPrefix, $key)] = $relatorModel->__get($this->relatorModelParams->keyFields[$index]);
  96. else
  97. $whereConditions[sprintf('`%s`.`%s`', $aliasPrefix, $key)] = $relatorModel->{$index};
  98. }
  99. $this->tiedModelQuery = $this->baseModelQuery->where($whereConditions);
  100. if ($this->inCache($relatorModel))
  101. $this->iterationQuery = $this->getCache($relatorModel);
  102. else
  103. $this->iterationQuery = null;
  104. }
  105. public function includeInQuery(YPFModelQuery $query) {
  106. if ($this->tableAlias) {
  107. $joinedTableName = sprintf('`%s` AS `%s`', $this->relatedModelParams->tableName, $this->tableAlias);
  108. $joinedAliasPrefix = $this->tableAlias;
  109. } elseif ($this->relatedModelParams->tableAlias) {
  110. $joinedTableName = sprintf('`%s` AS `%s`', $this->relatedModelParams->tableName, $this->relatedModelParams->tableAlias);
  111. $joinedAliasPrefix = $this->relatedModelParams->tableAlias;
  112. } else {
  113. $joinedTableName = sprintf('`%s`', $this->relatedModelParams->tableName);
  114. $joinedAliasPrefix = $this->relatedModelParams->tableName;
  115. }
  116. if ($this->relatorModelParams->tableAlias)
  117. $joiningAliasPrefix = $this->relatorModelParams->tableAlias;
  118. else
  119. $joiningAliasPrefix = $this->relatorModelParams->tableName;
  120. $joinConditions = array();
  121. foreach($this->relationParams['keys'] as $index=>$key)
  122. if (is_numeric($index))
  123. $joinConditions[] = sprintf('`%s`.`%s` = `%s`.`%s`',
  124. $joiningAliasPrefix, $this->relatorModelParams->keyFields[$index],
  125. $joinedAliasPrefix, $key);
  126. else
  127. $joinConditions[] = sprintf('`%s`.`%s` = `%s`.`%s`',
  128. $joiningAliasPrefix, $index,
  129. $joinedAliasPrefix, $key);
  130. if (isset($this->relationParams['sqlConditions']))
  131. $query = $query->where(arraize(isset($this->relationParams['sqlConditions'])));
  132. if (isset($this->relationParams['sqlGrouping']))
  133. $query = $query->groupBy(arraize(isset($this->relationParams['sqlGrouping'])));
  134. if (isset($this->relationParams['sqlOrdering']))
  135. $query = $query->orderBy(arraize(isset($this->relationParams['sqlOrdering'])));
  136. return $query->join($joinedTableName, $joinConditions);
  137. }
  138. public function save() {
  139. if ($this->acceptsNested && is_array($this->iterationQuery)) {
  140. $result = true;
  141. foreach ($this->iterationQuery as $item) {
  142. $this->add($item);
  143. $result = $result && $item->save();
  144. }
  145. return $result;
  146. } else
  147. return true;
  148. }
  149. public function create($values = array())
  150. {
  151. $newInstanace = eval(sprintf('return new %s();', $this->relatedModelName));
  152. foreach ($values as $key=>$value)
  153. $newInstanace->{$key} = $value;
  154. foreach($this->relationParams['keys'] as $index=>$key) {
  155. $pk = $this->relatorModelParams->keyFields[$index];
  156. $newInstanace->{$key} = $this->relatorInstance->{$pk};
  157. }
  158. return $newInstanace;
  159. }
  160. public function add($newInstance)
  161. {
  162. foreach($this->relationParams['keys'] as $index=>$key) {
  163. $pk = $this->relatorModelParams->keyFields[$index];
  164. $newInstance->{$key} = $this->relatorInstance->{$pk};
  165. }
  166. }
  167. public function __toJSON() {
  168. parent::__toJSON();
  169. }
  170. public function __toJSONRepresentable() {
  171. return $this->tiedModelQuery->__toJSONRepresentable();
  172. }
  173. public function __toXML($xmlParent = null) {
  174. return $this->tiedModelQuery->__toXML($xmlParent);
  175. }
  176. // ----------- ModelQuery Implementation--------------------------------
  177. public function sum($expression) {
  178. return $this->tiedModelQuery->sum($expression);
  179. }
  180. public function max($expression) {
  181. return $this->tiedModelQuery->max($expression);
  182. }
  183. public function min($expression) {
  184. return $this->tiedModelQuery->min($expression);
  185. }
  186. public function value($expression) {
  187. return $this->tiedModelQuery->value($expression);
  188. }
  189. public function fields($fields)
  190. {
  191. return $this->tiedModelQuery->fields($fields);
  192. }
  193. public function all()
  194. {
  195. return $this->tiedModelQuery->all();
  196. }
  197. public function count()
  198. {
  199. return $this->tiedModelQuery->count();
  200. }
  201. public function first()
  202. {
  203. return $this->tiedModelQuery->first();
  204. }
  205. public function delete()
  206. {
  207. return $this->tiedModelQuery->delete();
  208. }
  209. public function groupBy($sqlGrouping)
  210. {
  211. return $this->tiedModelQuery->groupBy($sqlGrouping);
  212. }
  213. public function having($sqlGroupContions) {
  214. return call_user_func_array(array($this->tiedModelQuery, 'having'), func_get_args());
  215. }
  216. public function last()
  217. {
  218. return $this->tiedModelQuery->last();
  219. }
  220. public function limit($limit)
  221. {
  222. return $this->tiedModelQuery->limit($limit);
  223. }
  224. public function orderBy($sqlOrdering)
  225. {
  226. return $this->tiedModelQuery->orderBy($sqlOrdering);
  227. }
  228. public function where($sqlConditions)
  229. {
  230. return call_user_func_array(array($this->tiedModelQuery, 'where'), func_get_args());
  231. }
  232. public function join($table, $conditions)
  233. {
  234. return $this->tiedModelQuery->join($table, $conditions);
  235. }
  236. public function alias($alias)
  237. {
  238. return $this->tiedModelQuery->alias($alias);
  239. }
  240. public function getModelParams() {
  241. return $this->tiedModelQuery->getModelParams();
  242. }
  243. // ----------- Iterator Implementation --------------------------------
  244. public function current()
  245. {
  246. if (is_array($this->iterationQuery))
  247. return $this->iterationQuery[$this->iterationKeys[$this->iterationPos]];
  248. else
  249. return $this->iterationQuery->current();
  250. }
  251. public function key()
  252. {
  253. if (is_array($this->iterationQuery))
  254. return $this->iterationPos;
  255. else
  256. return $this->iterationQuery->key();
  257. }
  258. public function next()
  259. {
  260. if (is_array($this->iterationQuery))
  261. $this->iterationPos++;
  262. else
  263. $this->iterationQuery->next();
  264. }
  265. public function rewind()
  266. {
  267. if (is_array($this->iterationQuery)) {
  268. $this->iterationKeys = array_keys($this->iterationQuery);
  269. $this->iterationPos = 0;
  270. } else
  271. $this->iterationQuery = $this->all();
  272. }
  273. public function valid()
  274. {
  275. if (is_array($this->iterationQuery))
  276. return ($this->iterationPos < count($this->iterationQuery));
  277. else
  278. return $this->iterationQuery->valid();
  279. }
  280. }
  281. ?>