-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathHasApiRelations.php
122 lines (98 loc) · 4.46 KB
/
HasApiRelations.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
namespace App\Models\Behaviors;
/**
* TODO: Requires HasRelations. Shouldn't this just extend HasRelations, then?
*/
trait HasApiRelations
{
public function apiElements()
{
return $this->morphToMany(\App\Models\ApiRelation::class, 'api_relatable')->withPivot(['position', 'relation'])->orderBy('position');
}
public function apiModels($relation, $model, $ttl = null)
{
// Obtain the API class
$modelClass = '\\App\\Models\\Api\\' . ucfirst($model);
// Get all Ids
$ids = $this->{$relation}->pluck('datahub_id')->toArray();
if (empty($ids)) {
return collect();
}
// Load real the real models from the API
$results = $modelClass::query()->ttl($ttl)->ids($ids)->get();
// Sort them by the original ids listing (coming from our CMS position attribute)
$sorted = $results->sortBy(function ($model, $key) use ($ids) {
return collect($ids)->search(function ($id, $key) use ($model) {
return $id == $model->id;
});
})->values();
return $sorted;
}
public function getRelatedWithApiModels($browser_name, $apiModelsDefinitions, $typeUsesApi)
{
if (!isset($this->relatedCache[$browser_name])) {
$this->loadRelatedWithApiModels($browser_name, $apiModelsDefinitions, $typeUsesApi);
}
return $this->relatedCache[$browser_name];
}
public function loadRelatedWithApiModels($browser_name, $apiModelsDefinitions, $typeUsesApi)
{
$this->load('relatedItems');
return $this->relatedCache[$browser_name] = $this->relatedItems
->where('browser_name', $browser_name)
->groupBy('related_type')
->map(function ($items, $type) use ($apiModelsDefinitions, $browser_name, $typeUsesApi) {
if (!isset($typeUsesApi[$type])) {
throw new \Exception('Cannot tell if type uses API: ' . $type);
}
if ($typeUsesApi[$type]) {
$apiElements = $this->getApiElements($items, $type, $apiModelsDefinitions);
$localApiMapping = $this->getLocalApiMapping($items, $apiElements);
return $localApiMapping->map(function ($relatedElement) use ($apiElements) {
// Get the API elements and use them to build the browser elements
$apiRelationElement = \App\Models\ApiRelation::where('id', $relatedElement->related_id)->first();
$apiElement = $apiElements->where('id', $apiRelationElement->datahub_id)->first();
$apiElement->position = $relatedElement->position;
return $apiElement;
})->values();
} else {
return $items->map(function ($relatedElement) {
$element = $relatedElement->related;
$element->position = $relatedElement->position;
if ($element->isNotUnlisted === false) {
return false;
}
if ($element->isPublished === false) {
return false;
}
return $element;
})->filter();
}
})->flatten(1)->sortBy('position');
}
public function getApiElements($items, $type, $apiModelsDefinitions)
{
// Get all related id's
$relatedIds = $items->pluck('related_id')->toArray();
// Get all datahub id's
$datahubIds = \App\Models\ApiRelation::whereIn('id', $relatedIds)->pluck('datahub_id')->toArray();
// Use those to load API records
$apiModelDefinition = $apiModelsDefinitions[$type];
$apiModel = $apiModelDefinition['apiModel'];
return $apiModel::query()->ids($datahubIds)->get();
}
public function getLocalApiMapping($items, $apiElements)
{
// Find locally selected objects
return $items->filter(function ($relatedElement) use ($apiElements) {
$apiRelationElement = \App\Models\ApiRelation::where('id', $relatedElement->related_id)
->first()
?->datahub_id;
$result = $apiElements->where('id', $apiRelationElement)->first();
if ($result) {
$result->position = $relatedElement->position;
}
return $result;
});
}
}