Skip to content

Commit 181ab91

Browse files
authored
Merge pull request #5681 from BookStackApp/parent_tag_classes
Parent tag classes
2 parents 306f41b + dca9765 commit 181ab91

File tree

4 files changed

+76
-16
lines changed

4 files changed

+76
-16
lines changed

app/Activity/Models/Tag.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* @property int $id
1313
* @property string $name
1414
* @property string $value
15+
* @property int $entity_id
16+
* @property string $entity_type
1517
* @property int $order
1618
*/
1719
class Tag extends Model

app/Activity/Tools/TagClassGenerator.php

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
namespace BookStack\Activity\Tools;
44

55
use BookStack\Activity\Models\Tag;
6+
use BookStack\Entities\Models\BookChild;
7+
use BookStack\Entities\Models\Entity;
8+
use BookStack\Entities\Models\Page;
69

710
class TagClassGenerator
811
{
9-
protected array $tags;
10-
11-
/**
12-
* @param Tag[] $tags
13-
*/
14-
public function __construct(array $tags)
15-
{
16-
$this->tags = $tags;
12+
public function __construct(
13+
protected Entity $entity
14+
) {
1715
}
1816

1917
/**
@@ -22,14 +20,23 @@ public function __construct(array $tags)
2220
public function generate(): array
2321
{
2422
$classes = [];
23+
$tags = $this->entity->tags->all();
24+
25+
foreach ($tags as $tag) {
26+
array_push($classes, ...$this->generateClassesForTag($tag));
27+
}
28+
29+
if ($this->entity instanceof BookChild && userCan('view', $this->entity->book)) {
30+
$bookTags = $this->entity->book->tags;
31+
foreach ($bookTags as $bookTag) {
32+
array_push($classes, ...$this->generateClassesForTag($bookTag, 'book-'));
33+
}
34+
}
2535

26-
foreach ($this->tags as $tag) {
27-
$name = $this->normalizeTagClassString($tag->name);
28-
$value = $this->normalizeTagClassString($tag->value);
29-
$classes[] = 'tag-name-' . $name;
30-
if ($value) {
31-
$classes[] = 'tag-value-' . $value;
32-
$classes[] = 'tag-pair-' . $name . '-' . $value;
36+
if ($this->entity instanceof Page && $this->entity->chapter && userCan('view', $this->entity->chapter)) {
37+
$chapterTags = $this->entity->chapter->tags;
38+
foreach ($chapterTags as $chapterTag) {
39+
array_push($classes, ...$this->generateClassesForTag($chapterTag, 'chapter-'));
3340
}
3441
}
3542

@@ -41,6 +48,22 @@ public function generateAsString(): string
4148
return implode(' ', $this->generate());
4249
}
4350

51+
/**
52+
* @return string[]
53+
*/
54+
protected function generateClassesForTag(Tag $tag, string $prefix = ''): array
55+
{
56+
$classes = [];
57+
$name = $this->normalizeTagClassString($tag->name);
58+
$value = $this->normalizeTagClassString($tag->value);
59+
$classes[] = "{$prefix}tag-name-{$name}";
60+
if ($value) {
61+
$classes[] = "{$prefix}tag-value-{$value}";
62+
$classes[] = "{$prefix}tag-pair-{$name}-{$value}";
63+
}
64+
return $classes;
65+
}
66+
4467
protected function normalizeTagClassString(string $value): string
4568
{
4669
$value = str_replace(' ', '', strtolower($value));
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
@push('body-class', e((new \BookStack\Activity\Tools\TagClassGenerator($entity->tags->all()))->generateAsString() . ' '))
1+
@push('body-class', e((new \BookStack\Activity\Tools\TagClassGenerator($entity))->generateAsString() . ' '))

tests/Entity/TagTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,39 @@ public function test_tag_classes_are_escaped()
230230
$resp->assertDontSee('tag-name-<>', false);
231231
$resp->assertSee('tag-name-&lt;&gt;', false);
232232
}
233+
234+
public function test_parent_tag_classes_visible()
235+
{
236+
$page = $this->entities->pageWithinChapter();
237+
$page->chapter->tags()->create(['name' => 'My Chapter Tag', 'value' => 'abc123']);
238+
$page->book->tags()->create(['name' => 'My Book Tag', 'value' => 'def456']);
239+
$this->asEditor();
240+
241+
$html = $this->withHtml($this->get($page->getUrl()));
242+
$html->assertElementExists('body.chapter-tag-pair-mychaptertag-abc123');
243+
$html->assertElementExists('body.book-tag-pair-mybooktag-def456');
244+
245+
$html = $this->withHtml($this->get($page->chapter->getUrl()));
246+
$html->assertElementExists('body.book-tag-pair-mybooktag-def456');
247+
}
248+
249+
public function test_parent_tag_classes_not_visible_if_cannot_see_parent()
250+
{
251+
$page = $this->entities->pageWithinChapter();
252+
$page->chapter->tags()->create(['name' => 'My Chapter Tag', 'value' => 'abc123']);
253+
$page->book->tags()->create(['name' => 'My Book Tag', 'value' => 'def456']);
254+
$editor = $this->users->editor();
255+
$this->actingAs($editor);
256+
257+
$this->permissions->setEntityPermissions($page, ['view'], [$editor->roles()->first()]);
258+
$this->permissions->disableEntityInheritedPermissions($page->chapter);
259+
260+
$html = $this->withHtml($this->get($page->getUrl()));
261+
$html->assertElementNotExists('body.chapter-tag-pair-mychaptertag-abc123');
262+
$html->assertElementExists('body.book-tag-pair-mybooktag-def456');
263+
264+
$this->permissions->disableEntityInheritedPermissions($page->book);
265+
$html = $this->withHtml($this->get($page->getUrl()));
266+
$html->assertElementNotExists('body.book-tag-pair-mybooktag-def456');
267+
}
233268
}

0 commit comments

Comments
 (0)