1: <?php
2:
3: namespace Baril\Orderly\Concerns;
4:
5: use Baril\Orderly\Relations\BelongsToManyOrderable;
6: use Baril\Orderly\Relations\MorphToManyOrderable;
7: use Illuminate\Support\Arr;
8: use Illuminate\Support\Str;
9:
10: trait HasOrderableRelationships
11: {
12: public static function bootHasOrderableRelationships()
13: {
14: static::$manyMethods = array_merge(static::$manyMethods, [
15: 'belongsToManyOrderable',
16: 'morphToManyOrderable',
17: 'morphedByManyOrderable',
18: 'belongsToManyOrdered',
19: 'morphToManyOrdered',
20: 'morphedByManyOrdered',
21: ]);
22: }
23:
24: /**
25: * Define a many-to-many orderable relationship.
26: * The prototype is similar as the belongsToMany method, with the
27: * $orderColumn added as the 2nd parameter.
28: *
29: * @param string $related
30: * @param string $orderColumn
31: * @param string $table
32: * @param string $foreignPivotKey
33: * @param string $relatedPivotKey
34: * @param string $parentKey
35: * @param string $relatedKey
36: * @param string $relation
37: *
38: * @return BelongsToSortedMany
39: */
40: public function belongsToManyOrderable(
41: $related,
42: $orderColumn = 'position',
43: $table = null,
44: $foreignPivotKey = null,
45: $relatedPivotKey = null,
46: $parentKey = null,
47: $relatedKey = null,
48: $relation = null
49: ) {
50:
51: // If no relationship name was passed, we will pull backtraces to get the
52: // name of the calling function. We will use that function name as the
53: // title of this relation since that is a great convention to apply.
54: if (is_null($relation)) {
55: $relation = $this->guessBelongsToManyRelation();
56: }
57:
58: // First, we'll need to determine the foreign key and "other key" for the
59: // relationship. Once we have determined the keys we'll make the query
60: // instances as well as the relationship instances we need for this.
61: $instance = $this->newRelatedInstance($related);
62:
63: $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();
64:
65: $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();
66:
67: // If no table name was provided, we can guess it by concatenating the two
68: // models using underscores in alphabetical order. The two model names
69: // are transformed to snake case from their default CamelCase also.
70: if (is_null($table)) {
71: $table = $this->joiningTable($related);
72: }
73:
74: return new BelongsToManyOrderable(
75: $instance->newQuery(),
76: $this,
77: $orderColumn,
78: $table,
79: $foreignPivotKey,
80: $relatedPivotKey,
81: $parentKey ?: $this->getKeyName(),
82: $relatedKey ?: $instance->getKeyName(),
83: $relation
84: );
85: }
86:
87: public function belongsToManyOrdered(
88: $related,
89: $orderColumn = 'position',
90: $table = null,
91: $foreignPivotKey = null,
92: $relatedPivotKey = null,
93: $parentKey = null,
94: $relatedKey = null,
95: $relation = null
96: ) {
97:
98: return $this->belongsToManyOrderable(
99: $related,
100: $orderColumn,
101: $table,
102: $foreignPivotKey,
103: $relatedPivotKey,
104: $parentKey,
105: $relatedKey,
106: $relation
107: )->ordered();
108: }
109:
110: /**
111: * Define a polymorphic orderable many-to-many relationship.
112: *
113: * @param string $related
114: * @param string $name
115: * @param string $table
116: * @param string $foreignPivotKey
117: * @param string $relatedPivotKey
118: * @param string $parentKey
119: * @param string $relatedKey
120: * @param bool $inverse
121: * @return \Baril\Orderly\Relations\MorphToManyOrderable
122: */
123: public function morphToManyOrderable(
124: $related,
125: $name,
126: $orderColumn = 'position',
127: $table = null,
128: $foreignPivotKey = null,
129: $relatedPivotKey = null,
130: $parentKey = null,
131: $relatedKey = null,
132: $inverse = false
133: ) {
134:
135: $caller = $this->guessBelongsToManyRelation();
136:
137: // First, we will need to determine the foreign key and "other key" for the
138: // relationship. Once we have determined the keys we will make the query
139: // instances, as well as the relationship instances we need for these.
140: $instance = $this->newRelatedInstance($related);
141:
142: $foreignPivotKey = $foreignPivotKey ?: $name . '_id';
143:
144: $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();
145:
146: // Now we're ready to create a new query builder for this related model and
147: // the relationship instances for this relation. This relations will set
148: // appropriate query constraints then entirely manages the hydrations.
149: $table = $table ?: Str::plural($name);
150:
151: return new MorphToManyOrderable(
152: $instance->newQuery(),
153: $this,
154: $name,
155: $orderColumn,
156: $table,
157: $foreignPivotKey,
158: $relatedPivotKey,
159: $parentKey ?: $this->getKeyName(),
160: $relatedKey ?: $instance->getKeyName(),
161: $caller,
162: $inverse
163: );
164: }
165:
166: public function morphToManyOrdered(
167: $related,
168: $name,
169: $orderColumn = 'position',
170: $table = null,
171: $foreignPivotKey = null,
172: $relatedPivotKey = null,
173: $parentKey = null,
174: $relatedKey = null,
175: $inverse = false
176: ) {
177:
178: return $this->morphToManyOrderable(
179: $related,
180: $name,
181: $orderColumn,
182: $table,
183: $foreignPivotKey,
184: $relatedPivotKey,
185: $parentKey,
186: $relatedKey,
187: $inverse
188: )->ordered();
189: }
190:
191: /**
192: * Define a polymorphic, inverse, orderable many-to-many relationship.
193: * The prototype is similar as the morphedByMany method, with the
194: * $orderColumn added as the 3rd parameter.
195: *
196: * @param string $related
197: * @param string $name
198: * @param string $orderColumn
199: * @param string $table
200: * @param string $foreignPivotKey
201: * @param string $relatedPivotKey
202: * @param string $parentKey
203: * @param string $relatedKey
204: * @return \Baril\Orderly\Relations\MorphToManyOrderable
205: */
206: public function morphedByManyOrderable(
207: $related,
208: $name,
209: $orderColumn = 'position',
210: $table = null,
211: $foreignPivotKey = null,
212: $relatedPivotKey = null,
213: $parentKey = null,
214: $relatedKey = null
215: ) {
216:
217: $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();
218:
219: // For the inverse of the polymorphic many-to-many relations, we will change
220: // the way we determine the foreign and other keys, as it is the opposite
221: // of the morph-to-many method since we're figuring out these inverses.
222: $relatedPivotKey = $relatedPivotKey ?: $name . '_id';
223:
224: return $this->morphToManyOrderable(
225: $related,
226: $name,
227: $orderColumn,
228: $table,
229: $foreignPivotKey,
230: $relatedPivotKey,
231: $parentKey,
232: $relatedKey,
233: true
234: );
235: }
236:
237: public function morphedByManyOrdered(
238: $related,
239: $name,
240: $orderColumn = 'position',
241: $table = null,
242: $foreignPivotKey = null,
243: $relatedPivotKey = null,
244: $parentKey = null,
245: $relatedKey = null
246: ) {
247:
248: return $this->morphedByManyOrderable(
249: $related,
250: $name,
251: $orderColumn,
252: $table,
253: $foreignPivotKey,
254: $relatedPivotKey,
255: $parentKey,
256: $relatedKey
257: )->ordered();
258: }
259: }
260: