1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Thinktomorrow\Chief\Urls\Application; |
4
|
|
|
|
5
|
|
|
use Thinktomorrow\Chief\Urls\ProvidesUrl\ProvidesUrl; |
6
|
|
|
use Thinktomorrow\Chief\Urls\UrlRecord; |
7
|
|
|
|
8
|
|
|
class SaveUrlSlugs |
9
|
|
|
{ |
10
|
|
|
/** @var bool */ |
11
|
|
|
private $strict = true; |
12
|
|
|
|
13
|
|
|
/** @var ProvidesUrl */ |
14
|
|
|
private $model; |
15
|
|
|
|
16
|
|
|
private $existingRecords; |
17
|
|
|
|
18
|
64 |
|
public function __construct(ProvidesUrl $model) |
19
|
|
|
{ |
20
|
64 |
|
$this->model = $model; |
21
|
64 |
|
} |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Saving urls slugs in strict mode prevents identical urls to be automatically removed. |
25
|
|
|
* When set to false, this would remove the identical url records. |
26
|
|
|
* |
27
|
|
|
* @param bool $strict |
28
|
|
|
* @return $this |
29
|
|
|
*/ |
30
|
4 |
|
public function strict(bool $strict = true) |
31
|
|
|
{ |
32
|
4 |
|
$this->strict = $strict; |
33
|
|
|
|
34
|
4 |
|
return $this; |
35
|
|
|
} |
36
|
|
|
|
37
|
64 |
|
public function handle(array $slugs): void |
38
|
|
|
{ |
39
|
64 |
|
$this->existingRecords = UrlRecord::getByModel($this->model); |
40
|
|
|
|
41
|
64 |
|
foreach ($slugs as $locale => $slug) { |
42
|
63 |
|
if (!$slug) { |
43
|
2 |
|
$this->deleteRecord($locale); |
44
|
2 |
|
continue; |
45
|
|
|
} |
46
|
|
|
|
47
|
63 |
|
$this->saveRecord($locale, $this->prependBaseUrlSegment($slug, $locale)); |
48
|
|
|
} |
49
|
64 |
|
} |
50
|
|
|
|
51
|
2 |
|
private function deleteRecord(string $locale) |
52
|
|
|
{ |
53
|
2 |
|
return $this->saveRecord($locale, null); |
|
|
|
|
54
|
|
|
} |
55
|
|
|
|
56
|
63 |
|
private function saveRecord(string $locale, ?string $slug) |
57
|
|
|
{ |
58
|
|
|
// Existing ones for this locale? |
59
|
|
|
$nonRedirectsWithSameLocale = $this->existingRecords->filter(function ($record) use ($locale) { |
60
|
|
|
return ( |
61
|
20 |
|
$record->locale == $locale && |
62
|
20 |
|
!$record->isRedirect() |
63
|
|
|
); |
64
|
63 |
|
}); |
65
|
|
|
|
66
|
|
|
// If slug entry is left empty, all existing records will be deleted |
67
|
63 |
|
if (!$slug) { |
68
|
|
|
$nonRedirectsWithSameLocale->each(function ($existingRecord) { |
69
|
2 |
|
$existingRecord->delete(); |
70
|
2 |
|
}); |
71
|
|
|
|
72
|
2 |
|
return; |
73
|
|
|
} |
74
|
|
|
|
75
|
63 |
|
$this->cleanupExistingRecords($locale, $slug); |
76
|
|
|
|
77
|
|
|
// If slug entry is left empty, all existing records will be deleted |
78
|
63 |
|
if ($nonRedirectsWithSameLocale->isEmpty()) { |
79
|
61 |
|
$this->createRecord($locale, $slug); |
80
|
61 |
|
return; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
// Only replace the existing records that differ from the current passed slugs |
84
|
|
|
$nonRedirectsWithSameLocale->each(function ($existingRecord) use ($slug) { |
85
|
17 |
|
if ($existingRecord->slug != $slug) { |
86
|
16 |
|
$existingRecord->replaceAndRedirect(['slug' => $slug]); |
87
|
|
|
} |
88
|
17 |
|
}); |
89
|
17 |
|
} |
90
|
|
|
|
91
|
61 |
|
private function createRecord($locale, $slug) |
92
|
|
|
{ |
93
|
61 |
|
UrlRecord::create([ |
94
|
61 |
|
'locale' => $locale, |
95
|
61 |
|
'slug' => $slug, |
96
|
61 |
|
'model_type' => $this->model->getMorphClass(), |
|
|
|
|
97
|
61 |
|
'model_id' => $this->model->id, |
|
|
|
|
98
|
|
|
]); |
99
|
61 |
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @param string $locale |
103
|
|
|
* @param string|null $slug |
104
|
|
|
*/ |
105
|
63 |
|
private function cleanupExistingRecords(string $locale, string $slug): void |
106
|
|
|
{ |
107
|
|
|
// In the case where we have any redirects that match the given slug, we need to |
108
|
|
|
// remove the redirect record in favour of the newly added one. |
109
|
63 |
|
$this->deleteIdenticalRedirects($this->existingRecords, $locale, $slug); |
110
|
|
|
|
111
|
63 |
|
$sameExistingRecords = UrlRecord::where('slug', $slug)->where('locale', $locale)->get(); |
112
|
|
|
|
113
|
|
|
// Also delete any redirects that match this locale and slug but are related to another model |
114
|
63 |
|
$this->deleteIdenticalRedirects($sameExistingRecords, $locale, $slug); |
115
|
|
|
|
116
|
|
|
// Also delete any urls that match this locale and slug but are related to another model |
117
|
63 |
|
$this->deleteIdenticalRecords($sameExistingRecords); |
118
|
63 |
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Remove any redirects owned by this model that equal the new slug. |
122
|
|
|
* |
123
|
|
|
* @param $existingRecords |
124
|
|
|
* @param $locale |
125
|
|
|
* @param $slug |
126
|
|
|
*/ |
127
|
63 |
|
private function deleteIdenticalRedirects($existingRecords, $locale, $slug): void |
128
|
|
|
{ |
129
|
|
|
$existingRecords->filter(function ($record) use ($locale) { |
130
|
|
|
return ( |
131
|
18 |
|
$record->locale == $locale && |
132
|
18 |
|
$record->isRedirect() |
133
|
|
|
); |
134
|
|
|
})->each(function ($existingRecord) use ($slug) { |
135
|
4 |
|
if ($existingRecord->slug == $slug) { |
136
|
2 |
|
$existingRecord->delete(); |
137
|
|
|
} |
138
|
63 |
|
}); |
139
|
63 |
|
} |
140
|
|
|
|
141
|
63 |
|
private function deleteIdenticalRecords($existingRecords): void |
142
|
|
|
{ |
143
|
63 |
|
if($this->strict) return; |
144
|
|
|
|
145
|
|
|
// The old homepage url should be removed since this is no longer in effect. |
146
|
|
|
// In case of any redirect to this old homepage, the last used redirect is now back in effect. |
147
|
|
|
$existingRecords->reject(function($existingRecord){ |
148
|
|
|
return ( |
149
|
1 |
|
$existingRecord->model_type == $this->model->getMorphClass() && |
150
|
1 |
|
$existingRecord->model_id == $this->model->id); |
|
|
|
|
151
|
|
|
})->each(function($existingRecord){ |
152
|
|
|
|
153
|
|
|
// TODO: if there is a redirect to this page, we'll take this one as the new url |
154
|
|
|
$existingRecord->delete(); |
155
|
4 |
|
}); |
156
|
4 |
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* @param string $slug |
160
|
|
|
* @param $locale |
161
|
|
|
* @return string |
162
|
|
|
*/ |
163
|
63 |
|
private function prependBaseUrlSegment(string $slug, $locale): string |
164
|
|
|
{ |
165
|
63 |
|
$slugWithBaseSegment = $this->model->baseUrlSegment($locale) . '/' . $slug; |
166
|
63 |
|
$slugWithBaseSegment = trim($slugWithBaseSegment, '/'); |
167
|
|
|
|
168
|
|
|
// If slug with base segment is empty string, it means that the passed slug was probably a "/" character. |
169
|
|
|
// so we'll want to return it in case the base segment is not added. |
170
|
63 |
|
return $slugWithBaseSegment ?: '/'; |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.