PageRenderTime 62ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/packages/orm/classes/hasone.php

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