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

/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphTo.php

https://gitlab.com/judielsm/Handora
PHP | 267 lines | 109 code | 38 blank | 120 comment | 5 complexity | db806ca843d2e0cd842062b95d3821b2 MD5 | raw file
  1. <?php
  2. namespace Illuminate\Database\Eloquent\Relations;
  3. use Illuminate\Database\Eloquent\Model;
  4. use Illuminate\Database\Eloquent\Builder;
  5. use Illuminate\Database\Eloquent\Collection;
  6. class MorphTo extends BelongsTo
  7. {
  8. /**
  9. * The type of the polymorphic relation.
  10. *
  11. * @var string
  12. */
  13. protected $morphType;
  14. /**
  15. * The models whose relations are being eager loaded.
  16. *
  17. * @var \Illuminate\Database\Eloquent\Collection
  18. */
  19. protected $models;
  20. /**
  21. * All of the models keyed by ID.
  22. *
  23. * @var array
  24. */
  25. protected $dictionary = [];
  26. /*
  27. * Indicates if soft-deleted model instances should be fetched.
  28. *
  29. * @var bool
  30. */
  31. protected $withTrashed = false;
  32. /**
  33. * Create a new morph to relationship instance.
  34. *
  35. * @param \Illuminate\Database\Eloquent\Builder $query
  36. * @param \Illuminate\Database\Eloquent\Model $parent
  37. * @param string $foreignKey
  38. * @param string $otherKey
  39. * @param string $type
  40. * @param string $relation
  41. * @return void
  42. */
  43. public function __construct(Builder $query, Model $parent, $foreignKey, $otherKey, $type, $relation)
  44. {
  45. $this->morphType = $type;
  46. parent::__construct($query, $parent, $foreignKey, $otherKey, $relation);
  47. }
  48. /**
  49. * Get the results of the relationship.
  50. *
  51. * @return mixed
  52. */
  53. public function getResults()
  54. {
  55. if (! $this->otherKey) {
  56. return;
  57. }
  58. return $this->query->first();
  59. }
  60. /**
  61. * Set the constraints for an eager load of the relation.
  62. *
  63. * @param array $models
  64. * @return void
  65. */
  66. public function addEagerConstraints(array $models)
  67. {
  68. $this->buildDictionary($this->models = Collection::make($models));
  69. }
  70. /**
  71. * Build a dictionary with the models.
  72. *
  73. * @param \Illuminate\Database\Eloquent\Collection $models
  74. * @return void
  75. */
  76. protected function buildDictionary(Collection $models)
  77. {
  78. foreach ($models as $model) {
  79. if ($model->{$this->morphType}) {
  80. $this->dictionary[$model->{$this->morphType}][$model->{$this->foreignKey}][] = $model;
  81. }
  82. }
  83. }
  84. /**
  85. * Match the eagerly loaded results to their parents.
  86. *
  87. * @param array $models
  88. * @param \Illuminate\Database\Eloquent\Collection $results
  89. * @param string $relation
  90. * @return array
  91. */
  92. public function match(array $models, Collection $results, $relation)
  93. {
  94. return $models;
  95. }
  96. /**
  97. * Associate the model instance to the given parent.
  98. *
  99. * @param \Illuminate\Database\Eloquent\Model $model
  100. * @return \Illuminate\Database\Eloquent\Model
  101. */
  102. public function associate($model)
  103. {
  104. $this->parent->setAttribute($this->foreignKey, $model->getKey());
  105. $this->parent->setAttribute($this->morphType, $model->getMorphClass());
  106. return $this->parent->setRelation($this->relation, $model);
  107. }
  108. /**
  109. * Dissociate previously associated model from the given parent.
  110. *
  111. * @return \Illuminate\Database\Eloquent\Model
  112. */
  113. public function dissociate()
  114. {
  115. $this->parent->setAttribute($this->foreignKey, null);
  116. $this->parent->setAttribute($this->morphType, null);
  117. return $this->parent->setRelation($this->relation, null);
  118. }
  119. /**
  120. * Get the results of the relationship.
  121. *
  122. * Called via eager load method of Eloquent query builder.
  123. *
  124. * @return mixed
  125. */
  126. public function getEager()
  127. {
  128. foreach (array_keys($this->dictionary) as $type) {
  129. $this->matchToMorphParents($type, $this->getResultsByType($type));
  130. }
  131. return $this->models;
  132. }
  133. /**
  134. * Match the results for a given type to their parents.
  135. *
  136. * @param string $type
  137. * @param \Illuminate\Database\Eloquent\Collection $results
  138. * @return void
  139. */
  140. protected function matchToMorphParents($type, Collection $results)
  141. {
  142. foreach ($results as $result) {
  143. if (isset($this->dictionary[$type][$result->getKey()])) {
  144. foreach ($this->dictionary[$type][$result->getKey()] as $model) {
  145. $model->setRelation($this->relation, $result);
  146. }
  147. }
  148. }
  149. }
  150. /**
  151. * Get all of the relation results for a type.
  152. *
  153. * @param string $type
  154. * @return \Illuminate\Database\Eloquent\Collection
  155. */
  156. protected function getResultsByType($type)
  157. {
  158. $instance = $this->createModelByType($type);
  159. $key = $instance->getKeyName();
  160. $query = $instance->newQuery();
  161. $query = $this->useWithTrashed($query);
  162. return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
  163. }
  164. /**
  165. * Gather all of the foreign keys for a given type.
  166. *
  167. * @param string $type
  168. * @return array
  169. */
  170. protected function gatherKeysByType($type)
  171. {
  172. $foreign = $this->foreignKey;
  173. return collect($this->dictionary[$type])->map(function ($models) use ($foreign) {
  174. return head($models)->{$foreign};
  175. })->values()->unique();
  176. }
  177. /**
  178. * Create a new model instance by type.
  179. *
  180. * @param string $type
  181. * @return \Illuminate\Database\Eloquent\Model
  182. */
  183. public function createModelByType($type)
  184. {
  185. return new $type;
  186. }
  187. /**
  188. * Get the foreign key "type" name.
  189. *
  190. * @return string
  191. */
  192. public function getMorphType()
  193. {
  194. return $this->morphType;
  195. }
  196. /**
  197. * Get the dictionary used by the relationship.
  198. *
  199. * @return array
  200. */
  201. public function getDictionary()
  202. {
  203. return $this->dictionary;
  204. }
  205. /**
  206. * Fetch soft-deleted model instances with query.
  207. *
  208. * @return $this
  209. */
  210. public function withTrashed()
  211. {
  212. $this->withTrashed = true;
  213. $this->query = $this->useWithTrashed($this->query);
  214. return $this;
  215. }
  216. /**
  217. * Return trashed models with query if told so.
  218. *
  219. * @param \Illuminate\Database\Eloquent\Builder $query
  220. * @return \Illuminate\Database\Eloquent\Builder
  221. */
  222. protected function useWithTrashed(Builder $query)
  223. {
  224. if ($this->withTrashed && $query->getMacro('withTrashed') !== null) {
  225. return $query->withTrashed();
  226. }
  227. return $query;
  228. }
  229. }