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

/fuel/packages/orm/classes/belongsto.php

https://bitbucket.org/trujka/codegrounds
PHP | 226 lines | 179 code | 25 blank | 22 comment | 18 complexity | 9e7996e62ce7982de39983baa1226d69 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * Fuel
  4. *
  5. * Fuel is a fast, lightweight, community driven PHP5 framework.
  6. *
  7. * @package Fuel
  8. * @version 1.6
  9. * @author Fuel Development Team
  10. * @license MIT License
  11. * @copyright 2010 - 2013 Fuel Development Team
  12. * @link http://fuelphp.com
  13. */
  14. namespace Orm;
  15. class BelongsTo extends Relation
  16. {
  17. protected $singular = true;
  18. protected $key_from = array();
  19. protected $key_to = array('id');
  20. public function __construct($from, $name, array $config)
  21. {
  22. $this->name = $name;
  23. $this->model_from = $from;
  24. $this->model_to = array_key_exists('model_to', $config)
  25. ? $config['model_to'] : \Inflector::get_namespace($from).'Model_'.\Inflector::classify($name);
  26. $this->key_from = array_key_exists('key_from', $config)
  27. ? (array) $config['key_from'] : (array) \Inflector::foreign_key($this->model_to);
  28. $this->key_to = array_key_exists('key_to', $config)
  29. ? (array) $config['key_to'] : $this->key_to;
  30. $this->conditions = array_key_exists('conditions', $config)
  31. ? (array) $config['conditions'] : array();
  32. $this->cascade_save = array_key_exists('cascade_save', $config)
  33. ? $config['cascade_save'] : $this->cascade_save;
  34. $this->cascade_delete = array_key_exists('cascade_delete', $config)
  35. ? $config['cascade_delete'] : $this->cascade_delete;
  36. if ( ! class_exists($this->model_to))
  37. {
  38. throw new \FuelException('Related model not found by Belongs_To relation "'.$this->name.'": '.$this->model_to);
  39. }
  40. $this->model_to = get_real_class($this->model_to);
  41. }
  42. public function get(Model $from)
  43. {
  44. $query = call_user_func(array($this->model_to, 'query'));
  45. reset($this->key_to);
  46. foreach ($this->key_from as $key)
  47. {
  48. // no point running a query when a key value is null
  49. if ($from->{$key} === null)
  50. {
  51. return null;
  52. }
  53. $query->where(current($this->key_to), $from->{$key});
  54. next($this->key_to);
  55. }
  56. foreach (\Arr::get($this->conditions, 'where', array()) as $key => $condition)
  57. {
  58. is_array($condition) or $condition = array($key, '=', $condition);
  59. $query->where($condition);
  60. }
  61. return $query->get_one();
  62. }
  63. public function join($alias_from, $rel_name, $alias_to_nr, $conditions = array())
  64. {
  65. $alias_to = 't'.$alias_to_nr;
  66. $model = array(
  67. 'model' => $this->model_to,
  68. 'connection' => call_user_func(array($this->model_to, 'connection')),
  69. 'table' => array(call_user_func(array($this->model_to, 'table')), $alias_to),
  70. 'primary_key' => call_user_func(array($this->model_to, 'primary_key')),
  71. 'join_type' => \Arr::get($conditions, 'join_type') ?: \Arr::get($this->conditions, 'join_type', 'left'),
  72. 'join_on' => array(),
  73. 'columns' => $this->select($alias_to),
  74. 'rel_name' => strpos($rel_name, '.') ? substr($rel_name, strrpos($rel_name, '.') + 1) : $rel_name,
  75. 'relation' => $this,
  76. 'where' => \Arr::get($conditions, 'where', array()),
  77. 'order_by' => \Arr::get($conditions, 'order_by') ?: \Arr::get($this->conditions, 'order_by', array()),
  78. );
  79. reset($this->key_to);
  80. foreach ($this->key_from as $key)
  81. {
  82. $model['join_on'][] = array($alias_from.'.'.$key, '=', $alias_to.'.'.current($this->key_to));
  83. next($this->key_to);
  84. }
  85. foreach (array(\Arr::get($this->conditions, 'where', array()), \Arr::get($conditions, 'join_on', array())) as $c)
  86. {
  87. foreach ($c as $key => $condition)
  88. {
  89. ! is_array($condition) and $condition = array($key, '=', $condition);
  90. if ( ! $condition[0] instanceof \Fuel\Core\Database_Expression and strpos($condition[0], '.') === false)
  91. {
  92. $condition[0] = $alias_to.'.'.$condition[0];
  93. }
  94. is_string($condition[2]) and $condition[2] = \Db::quote($condition[2], $model['connection']);
  95. $model['join_on'][] = $condition;
  96. }
  97. }
  98. return array($rel_name => $model);
  99. }
  100. public function save($model_from, $model_to, $original_model_id, $parent_saved, $cascade)
  101. {
  102. if ($parent_saved)
  103. {
  104. return;
  105. }
  106. if ( ! $model_to instanceof $this->model_to and $model_to !== null)
  107. {
  108. throw new \FuelException('Invalid Model instance added to relations in this model.');
  109. }
  110. // Save if it's a yet unsaved object
  111. if ($model_to and $model_to->is_new())
  112. {
  113. $model_to->save(false);
  114. }
  115. $current_model_id = $model_to ? $model_to->implode_pk($model_to) : null;
  116. // Check if there was another model assigned (this supersedes any change to the foreign key(s))
  117. if ($current_model_id != $original_model_id)
  118. {
  119. // change the foreign keys in the model_from to point to the new relation
  120. reset($this->key_from);
  121. $model_from->unfreeze();
  122. foreach ($this->key_to as $pk)
  123. {
  124. $model_from->{current($this->key_from)} = $model_to ? $model_to->{$pk} : null;
  125. next($this->key_from);
  126. }
  127. $model_from->freeze();
  128. }
  129. // if not check the model_from's foreign_keys against the model_to's primary keys
  130. // because that is how the model stores them
  131. elseif ($current_model_id != null)
  132. {
  133. $foreign_keys = count($this->key_to) == 1 ? array($original_model_id) : explode('][', substr($original_model_id, 1, -1));
  134. $changed = false;
  135. $new_rel_id = array();
  136. reset($foreign_keys);
  137. $m = $this->model_to;
  138. foreach ($m::primary_key() as $pk)
  139. {
  140. if (is_null($model_to->{$pk}))
  141. {
  142. $changed = true;
  143. $new_rel_id = null;
  144. break;
  145. }
  146. elseif ($model_to->{$pk} != current($foreign_keys))
  147. {
  148. $changed = true;
  149. }
  150. $new_rel_id[] = $model_to->{$pk};
  151. next($foreign_keys);
  152. }
  153. // if any of the keys changed, reload the relationship - saving the object will save those keys
  154. if ($changed)
  155. {
  156. // Attempt to load the new related object
  157. if ( ! is_null($new_rel_id))
  158. {
  159. $rel_obj = call_user_func(array($this->model_to, 'find'), $new_rel_id);
  160. if (empty($rel_obj))
  161. {
  162. throw new \FuelException('New relation set on '.$this->model_from.' object wasn\'t found.');
  163. }
  164. }
  165. else
  166. {
  167. $rel_obj = null;
  168. }
  169. // Add the new relation to the model_from
  170. $model_from->unfreeze();
  171. $rel = $model_from->_relate();
  172. $rel[$this->name] = $rel_obj;
  173. $model_from->_relate($rel);
  174. $model_from->freeze();
  175. }
  176. }
  177. $cascade = is_null($cascade) ? $this->cascade_save : (bool) $cascade;
  178. if ($cascade and ! empty($model_to))
  179. {
  180. $model_to->save();
  181. }
  182. }
  183. public function delete($model_from, $model_to, $parent_deleted, $cascade)
  184. {
  185. if ($parent_deleted)
  186. {
  187. return;
  188. }
  189. // break current relations
  190. $model_from->unfreeze();
  191. $rels = $model_from->_relate();
  192. $rels[$this->name] = null;
  193. $model_from->_relate($rels);
  194. $model_from->freeze();
  195. $cascade = is_null($cascade) ? $this->cascade_delete : (bool) $cascade;
  196. if ($cascade and ! empty($model_to))
  197. {
  198. $model_to->delete();
  199. }
  200. }
  201. }