PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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

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