1
|
|
|
<?php |
2
|
|
|
namespace AlgoWeb\PODataLaravel\Models; |
3
|
|
|
|
4
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo; |
5
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany; |
6
|
|
|
use Illuminate\Database\Eloquent\Relations\MorphMany; |
7
|
|
|
use Illuminate\Database\Eloquent\Relations\MorphOne; |
8
|
|
|
use Illuminate\Database\Eloquent\Relations\MorphToMany; |
9
|
|
|
use Illuminate\Support\Facades\App as App; |
10
|
|
|
use Illuminate\Database\Eloquent\Relations\Relation; |
11
|
|
|
use POData\Providers\Metadata\ResourceStreamInfo; |
12
|
|
|
use POData\Providers\Metadata\Type\EdmPrimitiveType; |
13
|
|
|
use Illuminate\Database\Eloquent\Model; |
14
|
|
|
|
15
|
|
|
trait MetadataTrait |
16
|
|
|
{ |
17
|
|
|
/* |
18
|
|
|
* Array to record mapping between doctrine types and OData types |
19
|
|
|
*/ |
20
|
|
|
protected $mapping = [ |
21
|
|
|
'integer' => EdmPrimitiveType::INT32, |
22
|
|
|
'string' => EdmPrimitiveType::STRING, |
23
|
|
|
'datetime' => EdmPrimitiveType::DATETIME, |
24
|
|
|
'float' => EdmPrimitiveType::SINGLE, |
25
|
|
|
'decimal' => EdmPrimitiveType::DECIMAL, |
26
|
|
|
'text' => EdmPrimitiveType::STRING, |
27
|
|
|
'boolean' => EdmPrimitiveType::BOOLEAN, |
28
|
3 |
|
'blob' => "stream" |
29
|
|
|
]; |
30
|
3 |
|
|
31
|
|
|
/* |
32
|
|
|
* Retrieve and assemble this model's metadata for OData packaging |
33
|
2 |
|
*/ |
34
|
2 |
|
public function metadata() |
35
|
|
|
{ |
36
|
2 |
|
assert($this instanceof Model, get_class($this)); |
37
|
|
|
|
38
|
2 |
|
// Break these out separately to enable separate reuse |
39
|
1 |
|
$connect = $this->getConnection(); |
40
|
|
|
$builder = $connect->getSchemaBuilder(); |
41
|
|
|
|
42
|
1 |
|
$table = $this->getTable(); |
43
|
1 |
|
|
44
|
1 |
|
if (!$builder->hasTable($table)) { |
45
|
|
|
return []; |
46
|
1 |
|
} |
47
|
|
|
|
48
|
1 |
|
$columns = $builder->getColumnListing($table); |
49
|
1 |
|
$mask = $this->metadataMask(); |
50
|
1 |
|
$columns = array_intersect($columns, $mask); |
51
|
|
|
|
52
|
1 |
|
$tableData = []; |
53
|
1 |
|
|
54
|
1 |
|
$rawFoo = $connect->getDoctrineSchemaManager()->listTableColumns($table); |
55
|
|
|
$foo = []; |
56
|
1 |
|
$getters = $this->collectGetters(); |
57
|
|
|
|
58
|
1 |
|
foreach ($rawFoo as $key => $val) { |
59
|
1 |
|
// Work around glitch in Doctrine when reading from MariaDB which added ` characters to root key value |
60
|
1 |
|
$key = trim($key, '`'); |
61
|
1 |
|
$foo[$key] = $val; |
62
|
1 |
|
} |
63
|
1 |
|
|
64
|
1 |
|
foreach ($columns as $column) { |
65
|
|
|
// Doctrine schema manager returns columns with lowercased names |
66
|
1 |
|
$rawColumn = $foo[strtolower($column)]; |
67
|
|
|
$nullable = !($rawColumn->getNotNull()); |
68
|
|
|
$fillable = in_array($column, $this->getFillable()); |
69
|
|
|
$rawType = $rawColumn->getType(); |
70
|
|
|
$type = $rawType->getName(); |
71
|
|
|
$tableData[$column] = ['type' => $type, 'nullable' => $nullable, 'fillable' => $fillable]; |
72
|
|
|
} |
73
|
4 |
|
|
74
|
|
|
foreach ($getters as $get) { |
75
|
4 |
|
$tableData[$get] = ['type' => 'text', 'nullable' => false, 'fillable' => false]; |
76
|
|
|
} |
77
|
4 |
|
|
78
|
4 |
|
return $tableData; |
79
|
4 |
|
} |
80
|
2 |
|
|
81
|
4 |
|
/* |
82
|
1 |
|
* Return the set of fields that are permitted to be in metadata |
83
|
1 |
|
* - following same visible-trumps-hidden guideline as Laravel |
84
|
|
|
*/ |
85
|
4 |
|
public function metadataMask() |
86
|
|
|
{ |
87
|
|
|
$attribs = array_keys($this->getAllAttributes()); |
88
|
|
|
|
89
|
|
|
$visible = $this->getVisible(); |
90
|
|
|
$hidden = $this->getHidden(); |
91
|
5 |
|
if (0 < count($visible)) { |
92
|
|
|
assert(!empty($visible)); |
93
|
5 |
|
$attribs = array_intersect($visible, $attribs); |
94
|
5 |
|
} elseif (0 < count($hidden)) { |
95
|
1 |
|
assert(!empty($hidden)); |
96
|
|
|
$attribs = array_diff($attribs, $hidden); |
97
|
|
|
} |
98
|
4 |
|
|
99
|
|
|
return $attribs; |
100
|
4 |
|
} |
101
|
|
|
|
102
|
4 |
|
/* |
103
|
4 |
|
* Get the endpoint name being exposed |
104
|
4 |
|
* |
105
|
4 |
|
*/ |
106
|
4 |
|
public function getEndpointName() |
107
|
4 |
|
{ |
108
|
|
|
$endpoint = isset($this->endpoint) ? $this->endpoint : null; |
109
|
4 |
|
|
110
|
1 |
|
if (!isset($endpoint)) { |
111
|
1 |
|
$bitter = get_class(); |
112
|
1 |
|
$name = substr($bitter, strrpos($bitter, '\\')+1); |
113
|
1 |
|
return strtolower($name); |
114
|
|
|
} |
115
|
4 |
|
return strtolower($endpoint); |
116
|
4 |
|
} |
117
|
|
|
|
118
|
4 |
|
/* |
119
|
|
|
* Assemble this model's OData metadata as xml schema |
120
|
|
|
*/ |
121
|
|
|
public function getXmlSchema($MetaNamespace = "Data") |
122
|
|
|
{ |
123
|
|
|
$raw = $this->metadata(); |
124
|
|
|
if ([] == $raw) { |
125
|
|
|
return null; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$metadata = App::make('metadata'); |
129
|
|
|
|
130
|
|
|
$rf = new \ReflectionClass(get_class($this)); |
131
|
|
|
$complex = $metadata->addEntityType($rf, $rf->getShortName(), $MetaNamespace); |
132
|
|
|
$keyName = $this->getKeyName(); |
133
|
|
|
if (null != $keyName) { |
134
|
|
|
$metadata->addKeyProperty($complex, $keyName, $this->mapping[$raw[$keyName]['type']]); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
foreach ($raw as $key => $secret) { |
138
|
|
|
if ($key == $keyName) { |
139
|
|
|
continue; |
140
|
|
|
} |
141
|
|
|
if ($secret['type'] == "blob") { |
142
|
|
|
$complex->setMediaLinkEntry(true); |
143
|
|
|
$streamInfo = new ResourceStreamInfo($key); |
144
|
|
|
assert($complex->isMediaLinkEntry()); |
145
|
|
|
$complex->addNamedStream($streamInfo); |
146
|
|
|
continue; |
147
|
|
|
} |
148
|
|
|
$metadata->addPrimitiveProperty($complex, $key, $this->mapping[$secret['type']]); // tag as isBag? |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
return $complex; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
public function hookUpRelationships($entityTypes, $resourceSets) |
155
|
|
|
{ |
156
|
|
|
assert(is_array($entityTypes) && is_array($resourceSets), "Both entityTypes and resourceSets must be arrays"); |
157
|
|
|
$metadata = App::make('metadata'); |
158
|
|
|
$rel = $this->getRelationshipsFromMethods(); |
159
|
|
|
$thisClass = get_class($this); |
160
|
|
|
$thisInTypes = array_key_exists($thisClass, $entityTypes); |
161
|
|
|
$thisInSets = array_key_exists($thisClass, $resourceSets); |
162
|
|
|
|
163
|
|
|
if (!($thisInSets && $thisInTypes)) { |
164
|
|
|
return $rel; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
$resourceType = $entityTypes[$thisClass]; |
168
|
|
|
// if $r is in $combined keys, then its in keyspaces of both $entityTypes and $resourceSets |
169
|
|
|
$combinedKeys = array_intersect(array_keys($entityTypes), array_keys($resourceSets)); |
170
|
|
View Code Duplication |
foreach ($rel["HasOne"] as $n => $r) { |
171
|
|
|
$r = trim($r, '\\'); |
172
|
|
|
if (in_array($r, $combinedKeys)) { |
173
|
|
|
$targResourceSet = $resourceSets[$r]; |
174
|
|
|
$metadata->addResourceReferenceProperty($resourceType, $n, $targResourceSet); |
175
|
3 |
|
} |
176
|
|
|
} |
177
|
3 |
View Code Duplication |
foreach ($rel["HasMany"] as $n => $r) { |
|
|
|
|
178
|
|
|
$r = trim($r, '\\'); |
179
|
3 |
|
if (in_array($r, $combinedKeys)) { |
180
|
3 |
|
$targResourceSet = $resourceSets[$r]; |
181
|
3 |
|
$metadata->addResourceSetReferenceProperty($resourceType, $n, $targResourceSet); |
182
|
3 |
|
} |
183
|
3 |
|
} |
184
|
3 |
|
return $rel; |
185
|
3 |
|
} |
186
|
3 |
|
|
187
|
3 |
|
public function getRelationships() |
188
|
3 |
|
{ |
189
|
|
|
$hooks = []; |
190
|
3 |
|
|
191
|
|
|
$rels = $this->getRelationshipsFromMethods(true); |
192
|
3 |
|
|
193
|
3 |
|
foreach ($rels['UnknownPolyMorphSide'] as $property => $foo) { |
194
|
3 |
|
$isMany = $foo instanceof MorphToMany; |
195
|
3 |
|
$targ = get_class($foo->getRelated()); |
196
|
3 |
|
$mult = $isMany ? '*' : '1'; |
197
|
3 |
|
|
198
|
3 |
View Code Duplication |
if ($isMany) { |
|
|
|
|
199
|
3 |
|
$fkMethodName = method_exists($foo, 'getQualifiedForeignKeyName') |
200
|
3 |
|
? 'getQualifiedForeignKeyName' : 'getQualifiedForeignPivotKeyName'; |
201
|
3 |
|
$rkMethodName = method_exists($foo, 'getQualifiedRelatedKeyName') |
202
|
|
|
? 'getQualifiedRelatedKeyName' : 'getQualifiedRelatedPivotKeyName'; |
203
|
3 |
|
} |
204
|
3 |
|
|
205
|
3 |
|
$keyRaw = $isMany ? $foo->$fkMethodName() : $foo->getForeignKey(); |
|
|
|
|
206
|
3 |
|
$keySegments = explode('.', $keyRaw); |
207
|
3 |
|
$keyName = $keySegments[count($keySegments) - 1]; |
208
|
3 |
|
$localRaw = $isMany ? $foo->$rkMethodName() : $foo->getQualifiedParentKeyName(); |
|
|
|
|
209
|
3 |
|
$localSegments = explode('.', $localRaw); |
210
|
3 |
|
$localName = $localSegments[count($localSegments) - 1]; |
211
|
|
|
|
212
|
3 |
|
$first = $keyName; |
213
|
3 |
|
$last = $localName; |
214
|
3 |
|
if (!isset($hooks[$first])) { |
215
|
|
|
$hooks[$first] = []; |
216
|
3 |
|
} |
217
|
3 |
|
$hooks[$first][$targ] = [ |
218
|
3 |
|
'property' => $property, |
219
|
3 |
|
'local' => $last, |
220
|
3 |
|
'multiplicity' => $mult |
221
|
|
|
]; |
222
|
1 |
|
} |
223
|
3 |
|
|
224
|
|
|
foreach ($rels['KnownPolyMorphSide'] as $property => $foo) { |
225
|
1 |
|
$isMany = $foo instanceof MorphToMany; |
226
|
|
|
$targ = get_class($foo->getRelated()); |
227
|
1 |
|
$mult = $isMany ? '*' : $foo instanceof MorphMany ? '*' : '1'; |
228
|
|
|
$mult = $foo instanceof MorphOne ? '0..1' : $mult; |
229
|
1 |
|
|
230
|
|
|
$keyRaw = $isMany ? $foo->getQualifiedForeignKeyName() : $foo->getForeignKeyName(); |
|
|
|
|
231
|
3 |
|
$keySegments = explode('.', $keyRaw); |
232
|
2 |
|
$keyName = $keySegments[count($keySegments) - 1]; |
233
|
2 |
|
$localRaw = $isMany ? $foo->getQualifiedRelatedKeyName() : $foo->getQualifiedParentKeyName(); |
|
|
|
|
234
|
3 |
|
$localSegments = explode('.', $localRaw); |
235
|
3 |
|
$localName = $localSegments[count($localSegments) - 1]; |
236
|
3 |
|
$first = $isMany ? $keyName : $localName; |
237
|
3 |
|
$last = $isMany ? $localName : $keyName; |
238
|
3 |
|
if (!isset($hooks[$first])) { |
239
|
3 |
|
$hooks[$first] = []; |
240
|
3 |
|
} |
241
|
|
|
$hooks[$first][$targ] = [ |
242
|
|
|
'property' => $property, |
243
|
|
|
'local' => $last, |
244
|
|
|
'multiplicity' => $mult |
245
|
|
|
]; |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
foreach ($rels['HasOne'] as $property => $foo) { |
249
|
|
|
if ($foo instanceof MorphOne) { |
250
|
|
|
continue; |
251
|
|
|
} |
252
|
|
|
$isBelong = $foo instanceof BelongsTo; |
253
|
|
|
$mult = $isBelong ? '1' : '0..1'; |
254
|
|
|
$targ = get_class($foo->getRelated()); |
255
|
|
|
$keyName = $isBelong ? $foo->getForeignKey() : $foo->getForeignKeyName(); |
256
|
|
|
$localRaw = $isBelong ? $foo->getOwnerKey() : $foo->getQualifiedParentKeyName(); |
257
|
|
|
$localSegments = explode('.', $localRaw); |
258
|
|
|
$localName = $localSegments[count($localSegments) - 1]; |
259
|
|
|
$first = $isBelong ? $localName : $keyName; |
260
|
|
|
$last = $isBelong ? $keyName : $localName; |
261
|
|
|
if (!isset($hooks[$first])) { |
262
|
|
|
$hooks[$first] = []; |
263
|
|
|
} |
264
|
|
|
$hooks[$first][$targ] = [ |
265
|
|
|
'property' => $property, |
266
|
|
|
'local' => $last, |
267
|
|
|
'multiplicity' => $mult |
268
|
|
|
]; |
269
|
|
|
} |
270
|
|
|
foreach ($rels['HasMany'] as $property => $foo) { |
271
|
|
|
if ($foo instanceof MorphMany || $foo instanceof MorphToMany) { |
272
|
|
|
continue; |
273
|
|
|
} |
274
|
|
|
$isBelong = $foo instanceof BelongsToMany; |
275
|
|
|
$mult = '*'; |
276
|
|
|
$targ = get_class($foo->getRelated()); |
277
|
|
|
|
278
|
|
View Code Duplication |
if ($isBelong) { |
|
|
|
|
279
|
|
|
$fkMethodName = method_exists($foo, 'getQualifiedForeignKeyName') |
280
|
|
|
? 'getQualifiedForeignKeyName' : 'getQualifiedForeignPivotKeyName'; |
281
|
|
|
$rkMethodName = method_exists($foo, 'getQualifiedRelatedKeyName') |
282
|
|
|
? 'getQualifiedRelatedKeyName' : 'getQualifiedRelatedPivotKeyName'; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
$keyRaw = $isBelong ? $foo->$fkMethodName() : $foo->getForeignKeyName(); |
286
|
|
|
$keySegments = explode('.', $keyRaw); |
287
|
|
|
$keyName = $keySegments[count($keySegments) - 1]; |
288
|
|
|
$localRaw = $isBelong ? $foo->$rkMethodName() : $foo->getQualifiedParentKeyName(); |
289
|
|
|
$localSegments = explode('.', $localRaw); |
290
|
|
|
$localName = $localSegments[count($localSegments) - 1]; |
291
|
|
|
if (!isset($hooks[$keyName])) { |
292
|
|
|
$hooks[$keyName] = []; |
293
|
|
|
} |
294
|
|
|
$hooks[$keyName][$targ] = [ |
295
|
|
|
'property' => $property, |
296
|
|
|
'local' => $localName, |
297
|
|
|
'multiplicity' => $mult |
298
|
|
|
]; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
return $hooks; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
protected function getAllAttributes() |
305
|
|
|
{ |
306
|
|
|
// Adapted from http://stackoverflow.com/a/33514981 |
307
|
|
|
// $columns = $this->getFillable(); |
308
|
|
|
// Another option is to get all columns for the table like so: |
309
|
|
|
$builder = $this->getConnection()->getSchemaBuilder(); |
310
|
|
|
$columns = $builder->getColumnListing($this->getTable()); |
311
|
|
|
// but it's safer to just get the fillable fields |
312
|
|
|
|
313
|
|
|
$attributes = $this->getAttributes(); |
314
|
|
|
|
315
|
|
|
foreach ($columns as $column) { |
316
|
|
|
if (!array_key_exists($column, $attributes)) { |
317
|
|
|
$attributes[$column] = null; |
318
|
|
|
} |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
$methods = $this->collectGetters(); |
322
|
|
|
|
323
|
|
|
foreach ($methods as $method) { |
324
|
|
|
$attributes[$method] = null; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
return $attributes; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
protected function getRelationshipsFromMethods($biDir = false) |
331
|
|
|
{ |
332
|
|
|
$model = $this; |
333
|
|
|
$relationships = array( |
334
|
|
|
"HasOne" => array(), |
335
|
|
|
"UnknownPolyMorphSide"=>array(), |
336
|
|
|
"HasMany"=>array(), |
337
|
|
|
"KnownPolyMorphSide"=>array() |
338
|
|
|
); |
339
|
|
|
$methods = get_class_methods($model); |
340
|
|
|
if (!empty($methods)) { |
341
|
|
|
foreach ($methods as $method) { |
342
|
|
|
if (!method_exists('Illuminate\Database\Eloquent\Model', $method) |
343
|
|
|
) { |
344
|
|
|
//Use reflection to inspect the code, based on Illuminate/Support/SerializableClosure.php |
345
|
|
|
$reflection = new \ReflectionMethod($model, $method); |
346
|
|
|
|
347
|
|
|
$file = new \SplFileObject($reflection->getFileName()); |
348
|
|
|
$file->seek($reflection->getStartLine()-1); |
349
|
|
|
$code = ''; |
350
|
|
|
while ($file->key() < $reflection->getEndLine()) { |
351
|
|
|
$code .= $file->current(); |
352
|
|
|
$file->next(); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
$code = trim(preg_replace('/\s\s+/', '', $code)); |
356
|
|
|
assert(false !== stripos($code, 'function'), 'Function definition must have keyword \'function\''); |
357
|
|
|
$begin = strpos($code, 'function('); |
358
|
|
|
$code = substr($code, $begin, strrpos($code, '}')-$begin+1); |
359
|
|
|
$lastCode = $code[strlen($code)-1]; |
360
|
|
|
assert("}" == $lastCode, "Final character of function definition must be closing brace"); |
361
|
|
|
foreach (array( |
362
|
|
|
'hasMany', |
363
|
|
|
'hasManyThrough', |
364
|
|
|
'belongsToMany', |
365
|
|
|
'hasOne', |
366
|
|
|
'belongsTo', |
367
|
|
|
'morphOne', |
368
|
|
|
'morphTo', |
369
|
|
|
'morphMany', |
370
|
|
|
'morphToMany', |
371
|
|
|
'morphedByMany' |
372
|
|
|
) as $relation) { |
373
|
|
|
$search = '$this->'.$relation.'('; |
374
|
|
|
if ($pos = stripos($code, $search)) { |
375
|
|
|
//Resolve the relation's model to a Relation object. |
376
|
|
|
$relationObj = $model->$method(); |
377
|
|
|
if ($relationObj instanceof Relation) { |
378
|
|
|
$relatedModel = '\\'.get_class($relationObj->getRelated()); |
379
|
|
|
$relations = [ |
380
|
|
|
'hasManyThrough', |
381
|
|
|
'belongsToMany', |
382
|
|
|
'hasMany', |
383
|
|
|
'morphMany', |
384
|
|
|
'morphToMany', |
385
|
|
|
'morphedByMany' |
386
|
|
|
]; |
387
|
|
|
if (in_array($relation, $relations)) { |
388
|
|
|
//Collection or array of models (because Collection is Arrayable) |
389
|
|
|
$relationships["HasMany"][$method] = $biDir ? $relationObj : $relatedModel; |
390
|
|
|
} elseif ($relation === "morphTo") { |
391
|
|
|
// Model isn't specified because relation is polymorphic |
392
|
|
|
$relationships["UnknownPolyMorphSide"][$method] = |
393
|
|
|
$biDir ? $relationObj : '\Illuminate\Database\Eloquent\Model|\Eloquent'; |
394
|
|
|
} else { |
395
|
|
|
//Single model is returned |
396
|
|
|
$relationships["HasOne"][$method] = $biDir ? $relationObj : $relatedModel; |
397
|
|
|
} |
398
|
|
|
if (in_array($relation, ["morphMany", "morphOne", "morphedByMany"])) { |
399
|
|
|
$relationships["KnownPolyMorphSide"][$method] = |
400
|
|
|
$biDir ? $relationObj : $relatedModel; |
401
|
|
|
} |
402
|
|
|
if (in_array($relation, ["morphToMany"])) { |
403
|
|
|
$relationships["UnknownPolyMorphSide"][$method] = |
404
|
|
|
$biDir ? $relationObj : $relatedModel; |
405
|
|
|
} |
406
|
|
|
} |
407
|
|
|
} |
408
|
|
|
} |
409
|
|
|
} |
410
|
|
|
} |
411
|
|
|
} |
412
|
|
|
return $relationships; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* Get the visible attributes for the model. |
417
|
|
|
* |
418
|
|
|
* @return array |
419
|
|
|
*/ |
420
|
|
|
public abstract function getVisible(); |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* Get the hidden attributes for the model. |
424
|
|
|
* |
425
|
|
|
* @return array |
426
|
|
|
*/ |
427
|
|
|
public abstract function getHidden(); |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Get the primary key for the model. |
431
|
|
|
* |
432
|
|
|
* @return string |
433
|
|
|
*/ |
434
|
|
|
public abstract function getKeyName(); |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Get the current connection name for the model. |
438
|
|
|
* |
439
|
|
|
* @return string |
440
|
|
|
*/ |
441
|
|
|
public abstract function getConnectionName(); |
442
|
|
|
|
443
|
|
|
/** |
444
|
|
|
* Get the database connection for the model. |
445
|
|
|
* |
446
|
|
|
* @return \Illuminate\Database\Connection |
447
|
|
|
*/ |
448
|
|
|
public abstract function getConnection(); |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Get all of the current attributes on the model. |
452
|
|
|
* |
453
|
|
|
* @return array |
454
|
|
|
*/ |
455
|
|
|
public abstract function getAttributes(); |
456
|
|
|
|
457
|
|
|
/** |
458
|
|
|
* Get the table associated with the model. |
459
|
|
|
* |
460
|
|
|
* @return string |
461
|
|
|
*/ |
462
|
|
|
public abstract function getTable(); |
463
|
|
|
|
464
|
|
|
/** |
465
|
|
|
* Get the fillable attributes for the model. |
466
|
|
|
* |
467
|
|
|
* @return array |
468
|
|
|
*/ |
469
|
|
|
public abstract function getFillable(); |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Dig up all defined getters on the model |
473
|
|
|
* |
474
|
|
|
* @return array |
475
|
|
|
*/ |
476
|
|
|
protected function collectGetters() |
477
|
|
|
{ |
478
|
|
|
$getterz = []; |
479
|
|
|
$methods = get_class_methods($this); |
480
|
|
|
foreach ($methods as $method) { |
481
|
|
|
if (starts_with($method, 'get') && ends_with($method, 'Attribute') && 'getAttribute' != $method) { |
482
|
|
|
$getterz[] = $method; |
483
|
|
|
} |
484
|
|
|
} |
485
|
|
|
$methods = []; |
486
|
|
|
|
487
|
|
|
foreach ($getterz as $getter) { |
488
|
|
|
$residual = substr($getter, 3); |
489
|
|
|
$residual = substr($residual, 0, -9); |
490
|
|
|
$methods[] = $residual; |
491
|
|
|
} |
492
|
|
|
return $methods; |
493
|
|
|
} |
494
|
|
|
} |
495
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.