Skip to content

Commit d32d5f6

Browse files
committed
Merge branch 'feature/seo'
2 parents 9859754 + cfa84e2 commit d32d5f6

File tree

6 files changed

+107
-190
lines changed

6 files changed

+107
-190
lines changed

config/inspirecms.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@
434434
'segment_provider' => DefaultSegmentProvider::class,
435435
'preview_provider' => DefaultPreviewProvider::class,
436436
'slug_generator' => DefaultSlugGenerator::class,
437+
'fallback_seo' => [
438+
'title' => env('APP_NAME', 'Home'),
439+
'description' => null,
440+
'keywords' => null,
441+
'image' => null,
442+
],
437443
],
438444

439445
'sitemap' => [

src/Dtos/ContentDto.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,24 @@ public function getSeo(?string $locale = null)
217217
{
218218
$seo = collect($this->seo);
219219

220-
return $seo->get($locale ?? $this->getLocale()) ?? $seo->get($this->getFallbackLocale());
220+
$locale ??= $this->getLocale();
221+
222+
$result = $seo->get($locale);
223+
224+
// Using fallback locale
225+
if (! $result &&
226+
($fallbackLocale = $this->getFallbackLocale()) &&
227+
($fallbackSeo = $seo->get($fallbackLocale))
228+
) {
229+
$result = $fallbackSeo;
230+
}
231+
232+
// Using default SEO data if not found
233+
if (! $result) {
234+
$result = inspirecms()->getFallbackSeo();
235+
}
236+
237+
return $result;
221238
}
222239

223240
public function isRedirectable(): bool

src/Dtos/SeoDto.php

Lines changed: 69 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
use Illuminate\Contracts\Support\Htmlable;
66
use Illuminate\Support\Collection;
77
use Illuminate\Support\HtmlString;
8+
use SolutionForest\InspireCms\InspireCmsConfig;
89
use SolutionForest\InspireCms\Support\Base\Dtos\BaseDto;
10+
use SolutionForest\InspireCms\Support\Dtos\MediaAssetDto;
911

1012
class SeoDto extends BaseDto
1113
{
@@ -72,83 +74,13 @@ class SeoDto extends BaseDto
7274
*/
7375
public $siteName;
7476

75-
/**
76-
* The locale of the content.
77-
*
78-
* @var string
79-
*/
80-
public $locale;
81-
82-
/**
83-
* The published time of the content.
84-
*
85-
* @var string
86-
*/
87-
public $publishedTime;
88-
89-
/**
90-
* The last modified time of the content.
91-
*
92-
* @var string
93-
*/
94-
public $modifiedTime;
95-
96-
/**
97-
* The author of the content.
98-
*
99-
* @var string
100-
*/
101-
public $author;
102-
103-
/**
104-
* The section of the site where the content is located.
105-
*
106-
* @var string
107-
*/
108-
public $section;
109-
110-
/**
111-
* The tag associated with the content.
112-
*
113-
* @var string
114-
*/
115-
public $tag;
116-
117-
/**
118-
* The category of the content.
119-
*
120-
* @var string
121-
*/
122-
public $category;
123-
12477
/**
12578
* The canonical URL of the content.
12679
*
12780
* @var string
12881
*/
12982
public $canonical;
13083

131-
/**
132-
* The alternate URL of the content.
133-
*
134-
* @var string
135-
*/
136-
public $alternate;
137-
138-
/**
139-
* The AMP HTML version of the content.
140-
*
141-
* @var string
142-
*/
143-
public $ampHtml;
144-
145-
/**
146-
* The AMP version of the content.
147-
*
148-
* @var string
149-
*/
150-
public $amp;
151-
15284
/**
15385
* Indicates whether the content should not be indexed by search engines.
15486
*
@@ -163,55 +95,6 @@ class SeoDto extends BaseDto
16395
*/
16496
public $noFollow;
16597

166-
/**
167-
* Indicates whether the content should not be archived by search engines.
168-
*
169-
* @var string
170-
*/
171-
public $noArchive;
172-
173-
/**
174-
* Indicates whether search engines should not show a snippet of the content.
175-
*
176-
* @var string
177-
*/
178-
public $noSnippet;
179-
180-
/**
181-
* Indicates whether the content should not be included in the Open Directory Project.
182-
*
183-
* @var string
184-
*/
185-
public $noOdp;
186-
187-
/**
188-
* Indicates whether the content should not be included in Yahoo Directory.
189-
*
190-
* @var string
191-
*/
192-
public $noYdir;
193-
194-
/**
195-
* Indicates whether images on the content should not be indexed by search engines.
196-
*
197-
* @var string
198-
*/
199-
public $noImageIndex;
200-
201-
/**
202-
* Indicates whether the content should not be translated by search engines.
203-
*
204-
* @var string
205-
*/
206-
public $noTranslate;
207-
208-
/**
209-
* Indicates whether the content should not be cached by search engines.
210-
*
211-
* @var string
212-
*/
213-
public $noCache;
214-
21598
/**
21699
* @var Collection<self>|null
217100
*/
@@ -228,10 +111,6 @@ public static function fromArray(array $parameters)
228111
'og_image' => 'ogImage',
229112
'noindex' => 'noIndex',
230113
'nofollow' => 'noFollow',
231-
'noarchive' => 'noArchive',
232-
'nosnippet' => 'noSnippet',
233-
'noodp' => 'noOdp',
234-
'noydir' => 'noYdir',
235114
];
236115

237116
foreach ($parameters as $key => $value) {
@@ -259,11 +138,34 @@ public static function fromArray(array $parameters)
259138

260139
$dto = parent::fromArray($parameters);
261140

141+
$fallbackSeo = InspireCmsConfig::get('frontend.fallback_seo', []);
142+
$fallbackExtraMapper = [
143+
'title' => ['ogTitle'],
144+
'description' => ['ogDescription'],
145+
'image' => ['ogImage'],
146+
];
147+
if (is_array($fallbackSeo) && ! empty($fallbackSeo)) {
148+
foreach ($fallbackSeo as $key => $value) {
149+
$keysToMap = array_unique(array_merge(
150+
[$key],
151+
$fallbackExtraMapper[$key] ?? []
152+
));
153+
foreach ($keysToMap ?? [] as $mappedKey) {
154+
if (! property_exists($dto, $mappedKey)) {
155+
continue;
156+
}
157+
if (! isset($dto->{$mappedKey}) || empty($dto->{$mappedKey})) {
158+
$dto->{$mappedKey} = $value;
159+
}
160+
}
161+
}
162+
}
163+
262164
return $dto;
263165
}
264166

265167
/**
266-
* @param self[]|Collection<slef>|null $ancestors
168+
* @param self[]|Collection<self>|null $ancestors
267169
* @return self
268170
*/
269171
public function setAncestors($ancestors)
@@ -317,8 +219,8 @@ public function __toString(): string
317219
$html .= "<meta property=\"og:description\" content=\"{$ogDescription}\">\n";
318220
}
319221

320-
if ($this->ogImage && ($mediaAssetUrl = inspirecms_asset()->findByKeys($this->ogImage)->first()?->getUrl())) {
321-
$html .= "<meta property=\"og:image\" content=\"{$mediaAssetUrl}\">\n";
222+
if ($odImageUrl = $this->transformImage($this->ogImage)) {
223+
$html .= "<meta property=\"og:image\" content=\"{$odImageUrl}\">\n";
322224
}
323225

324226
if ($this->url) {
@@ -333,86 +235,66 @@ public function __toString(): string
333235
$html .= "<meta property=\"og:site_name\" content=\"{$this->siteName}\">\n";
334236
}
335237

336-
if ($this->locale) {
337-
$html .= "<meta property=\"og:locale\" content=\"{$this->locale}\">\n";
338-
}
339-
340-
if ($this->publishedTime) {
341-
$html .= "<meta property=\"article:published_time\" content=\"{$this->publishedTime}\">\n";
342-
}
343-
344-
if ($this->modifiedTime) {
345-
$html .= "<meta property=\"article:modified_time\" content=\"{$this->modifiedTime}\">\n";
346-
}
347-
348-
if ($this->author) {
349-
$html .= "<meta property=\"article:author\" content=\"{$this->author}\">\n";
350-
}
351-
352-
if ($this->section) {
353-
$html .= "<meta property=\"article:section\" content=\"{$this->section}\">\n";
354-
}
355-
356-
if ($this->tag) {
357-
$html .= "<meta property=\"article:tag\" content=\"{$this->tag}\">\n";
358-
}
359-
360-
if ($this->category) {
361-
$html .= "<meta property=\"article:category\" content=\"{$this->category}\">\n";
362-
}
363-
364238
if ($this->canonical) {
365239
$html .= "<link rel=\"canonical\" href=\"{$this->canonical}\">\n";
366240
}
367241

368-
if ($this->alternate) {
369-
$html .= "<link rel=\"alternate\" href=\"{$this->alternate}\">\n";
242+
$robotsContent = [];
243+
if ($this->noIndex) {
244+
$robotsContent[] = 'noindex';
370245
}
371-
372-
if ($this->ampHtml) {
373-
$html .= "<link rel=\"amphtml\" href=\"{$this->ampHtml}\">\n";
246+
if ($this->noFollow) {
247+
$robotsContent[] = 'nofollow';
374248
}
375-
376-
if ($this->amp) {
377-
$html .= "<link rel=\"amp\" href=\"{$this->amp}\">\n";
249+
if (! empty($robotsContent)) {
250+
$html .= '<meta name="robots" content="' . implode(', ', $robotsContent) . "\">\n";
378251
}
379252

380-
if ($this->noIndex) {
381-
$html .= "<meta name=\"robots\" content=\"noindex\">\n";
382-
}
253+
return $html;
254+
}
383255

384-
if ($this->noFollow) {
385-
$html .= "<meta name=\"robots\" content=\"nofollow\">\n";
256+
protected function transformImage($value)
257+
{
258+
// If the value is empty or null, return null
259+
if (empty($value)) {
260+
return null;
386261
}
387262

388-
if ($this->noArchive) {
389-
$html .= "<meta name=\"robots\" content=\"noarchive\">\n";
390-
}
263+
// If the value is a string, check if it is a valid URL
264+
if (is_string($value)) {
391265

392-
if ($this->noSnippet) {
393-
$html .= "<meta name=\"robots\" content=\"nosnippet\">\n";
394-
}
266+
if (filter_var($value, FILTER_VALIDATE_URL)) {
267+
return $value;
268+
}
395269

396-
if ($this->noOdp) {
397-
$html .= "<meta name=\"robots\" content=\"noodp\">\n";
398-
}
270+
// If not, check if it is a relative URL (e.g., "/storage/images/example.jpg")
271+
if (str_starts_with($value, '/')) {
272+
// Assuming the base URL is defined in your configuration
273+
$baseUrl = config('app.url', 'http://localhost');
399274

400-
if ($this->noYdir) {
401-
$html .= "<meta name=\"robots\" content=\"noydir\">\n";
402-
}
275+
return rtrim($baseUrl, '/') . $value;
276+
}
403277

404-
if ($this->noImageIndex) {
405-
$html .= "<meta name=\"robots\" content=\"noimageindex\">\n";
278+
return null;
406279
}
407280

408-
if ($this->noTranslate) {
409-
$html .= "<meta name=\"robots\" content=\"notranslate\">\n";
410-
}
281+
// If the value is an array (from MediaPicker)
282+
if (is_array($value)) {
283+
284+
try {
285+
$dto = MediaAssetDto::fromArray($value);
286+
// Handle the case where the src is a string
287+
if (filled($dto->src)) {
288+
return $this->transformImage($dto->src);
289+
}
290+
} catch (\Throwable $th) {
291+
//
292+
}
411293

412-
if ($this->noCache) {
413-
$html .= "<meta name=\"robots\" content=\"nocache\">\n";
294+
return null;
414295
}
415296

416-
return $html;
297+
// If the value is not a string or an array, return null
298+
return null;
417299
}
418300
}

src/Facades/InspireCms.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* @method static void forgetCachedNavigation()
2020
* @method static array getContentRoutes()
2121
* @method static void forgetCachedContentRoutes()
22+
* @method static SeoDto getFallbackSeo()
2223
*
2324
* @see \SolutionForest\InspireCms\InspireCms
2425
*/

src/ImportData/Entities/Content.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ public function getWebSettingData(): array
164164
'og_image' => [],
165165
],
166166
'robots' => [
167-
'index' => true,
168-
'follow' => true,
167+
'noindex' => false,
168+
'nofollow' => false,
169169
],
170170
'redirect_path' => null,
171171
'redirect_content_id' => KeyHelper::generateMinUuid(),

0 commit comments

Comments
 (0)