Skip to content

Commit 0d8c774

Browse files
Scope duplicate title & description checks to the current site (#615)
1 parent 8b7003d commit 0d8c774

7 files changed

Lines changed: 126 additions & 24 deletions

File tree

src/Reporting/Chunk.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ protected function createPage($content)
8686
->withCurrent($content)
8787
->get();
8888

89+
$data['site'] = $content->locale();
90+
8991
return new Page($content->id(), $data, $this->report);
9092
}
9193
}

src/Reporting/Page.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ public function url()
127127
return $this->get('canonical_url');
128128
}
129129

130+
public function site()
131+
{
132+
return $this->get('site');
133+
}
134+
130135
public function id()
131136
{
132137
return $this->id;

src/Reporting/Rules/UniqueMetaDescription.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,14 @@ public function processPage()
5757

5858
protected function groupAllPagesByDescription()
5959
{
60-
return Blink::once('seo-pro-report-'.$this->report->id().'-page-descriptions-grouped', function () {
61-
return $this->page->report()->pages()->mapToGroups(function ($page) {
62-
return [$page->get('description') => $page->id()];
63-
});
60+
$site = $this->page->site();
61+
62+
return Blink::once('seo-pro-report-'.$this->report->id().'-page-descriptions-grouped-'.$site, function () use ($site) {
63+
return $this->page->report()->pages()
64+
->filter(fn ($page) => $page->site() === $site)
65+
->mapToGroups(function ($page) {
66+
return [$page->get('description') => $page->id()];
67+
});
6468
});
6569
}
6670

src/Reporting/Rules/UniqueTitleTag.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,14 @@ public function processPage()
5757

5858
protected function groupAllPagesByTitle()
5959
{
60-
return Blink::once('seo-pro-report-'.$this->report->id().'-page-titles-grouped', function () {
61-
return $this->page->report()->pages()->mapToGroups(function ($page) {
62-
return [$page->get('title') => $page->id()];
63-
});
60+
$site = $this->page->site();
61+
62+
return Blink::once('seo-pro-report-'.$this->report->id().'-page-titles-grouped-'.$site, function () use ($site) {
63+
return $this->page->report()->pages()
64+
->filter(fn ($page) => $page->site() === $site)
65+
->mapToGroups(function ($page) {
66+
return [$page->get('title') => $page->id()];
67+
});
6468
});
6569
}
6670

tests/Localized/ReportTest.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
namespace Tests\Localized;
4+
5+
use Illuminate\Support\Carbon;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use Statamic\Facades\Entry;
8+
use Statamic\Facades\Term;
9+
use Statamic\Facades\YAML;
10+
use Statamic\SeoPro\Reporting\Report;
11+
use Statamic\Support\Str;
12+
13+
class ReportTest extends LocalizedTestCase
14+
{
15+
protected function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
Entry::all()->filter(fn ($entry) => $entry->hasOrigin())->each->delete();
20+
Entry::all()->each->delete();
21+
Term::all()->each->delete();
22+
23+
if ($this->files->exists($path = $this->reportsPath())) {
24+
$this->files->deleteDirectory($path);
25+
}
26+
}
27+
28+
/**
29+
* @see https://github.com/statamic/seo-pro/issues/213
30+
*/
31+
#[Test]
32+
public function it_does_not_flag_duplicate_titles_and_descriptions_across_sites()
33+
{
34+
$this->makeArticle('default', 'one', 'Shared Title', 'Shared Description');
35+
$this->makeArticle('french', 'two', 'Shared Title', 'Shared Description');
36+
37+
$this->assertEqualsIgnoringLineEndings(0, $this->getReportResult('UniqueTitleTag'));
38+
$this->assertEqualsIgnoringLineEndings(0, $this->getReportResult('UniqueMetaDescription'));
39+
}
40+
41+
/**
42+
* @see https://github.com/statamic/seo-pro/issues/213
43+
*/
44+
#[Test]
45+
public function it_still_flags_duplicate_titles_and_descriptions_within_the_same_site()
46+
{
47+
$this->makeArticle('default', 'one', 'Shared Title', 'Shared Description');
48+
$this->makeArticle('default', 'two', 'Shared Title', 'Shared Description');
49+
$this->makeArticle('french', 'three', 'Shared Title', 'Shared Description');
50+
51+
$this->assertEqualsIgnoringLineEndings(2, $this->getReportResult('UniqueTitleTag'));
52+
$this->assertEqualsIgnoringLineEndings(2, $this->getReportResult('UniqueMetaDescription'));
53+
}
54+
55+
private function makeArticle($site, $slug, $title, $description)
56+
{
57+
Entry::make()
58+
->collection('articles')
59+
->blueprint('articles')
60+
->locale($site)
61+
->slug($slug)
62+
->date('2024-01-01')
63+
->set('title', $title)
64+
->set('seo', ['title' => $title, 'description' => $description])
65+
->save();
66+
67+
return $this;
68+
}
69+
70+
private function reportsPath($path = null)
71+
{
72+
if ($path) {
73+
$path = Str::ensureLeft($path, '/');
74+
}
75+
76+
return storage_path('statamic/seopro/reports').$path;
77+
}
78+
79+
private function getReportResult($key)
80+
{
81+
Carbon::setTestNow(now());
82+
83+
Report::create()->save()->generate();
84+
85+
return YAML::file($this->reportsPath('1/report.yaml'))->parse()['results'][$key];
86+
}
87+
}

tests/ReportTest.php

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ public function it_properly_reports_on_description_length()
466466
], $this->getReportResult('IdealMetaDescriptionLength'));
467467
}
468468

469-
public function reportsPath($path = null)
469+
private function reportsPath($path = null)
470470
{
471471
if ($path) {
472472
$path = Str::ensureLeft($path, '/');
@@ -475,7 +475,7 @@ public function reportsPath($path = null)
475475
return storage_path('statamic/seopro/reports').$path;
476476
}
477477

478-
protected function generateEntries($count)
478+
private function generateEntries($count)
479479
{
480480
collect(range(1, $count))->each(function ($i) {
481481
Entry::make()
@@ -489,7 +489,7 @@ protected function generateEntries($count)
489489
return $this;
490490
}
491491

492-
protected function generateTerms($count)
492+
private function generateTerms($count)
493493
{
494494
collect(range(1, $count))->each(function ($i) {
495495
Term::make()
@@ -502,26 +502,14 @@ protected function generateTerms($count)
502502
return $this;
503503
}
504504

505-
protected function getReportResult($key)
505+
private function getReportResult($key)
506506
{
507507
Carbon::setTestNow($now = now());
508508

509509
Report::create()->save()->generate();
510510

511511
return YAML::file($this->reportsPath('1/report.yaml'))->parse()['results'][$key];
512512
}
513-
514-
/**
515-
* Normalize line endings before performing assertion in windows.
516-
*/
517-
public static function assertEqualsIgnoringLineEndings($needle, $haystack, $message = ''): void
518-
{
519-
parent::assertEquals(
520-
is_string($needle) ? static::normalizeMultilineString($needle) : $needle,
521-
is_string($haystack) ? static::normalizeMultilineString($haystack) : $haystack,
522-
$message
523-
);
524-
}
525513
}
526514

527515
class TestChunk extends Chunk

tests/TestCase.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,18 @@ public static function assertStringNotContainsStringIgnoringLineEndings($needle,
138138
);
139139
}
140140

141+
/**
142+
* Normalize line endings before performing assertion in windows.
143+
*/
144+
public static function assertEqualsIgnoringLineEndings(mixed $expected, mixed $actual, string $message = ''): void
145+
{
146+
parent::assertEquals(
147+
is_string($expected) ? static::normalizeMultilineString($expected) : $expected,
148+
is_string($actual) ? static::normalizeMultilineString($actual) : $actual,
149+
$message
150+
);
151+
}
152+
141153
protected function assertArrayHasKeys(array $keys, array|\ArrayAccess $array): void
142154
{
143155
foreach ($keys as $key) {

0 commit comments

Comments
 (0)