diff --git a/app/Http/Controllers/Forum/TopicController.php b/app/Http/Controllers/Forum/TopicController.php index bbe06c1b7..e7e848f88 100644 --- a/app/Http/Controllers/Forum/TopicController.php +++ b/app/Http/Controllers/Forum/TopicController.php @@ -22,6 +22,7 @@ use Coyote\Services\Forum\TreeBuilder\ListDecorator; use Coyote\Topic; use Illuminate\Http\Request; +use Spatie\SchemaOrg\Schema; class TopicController extends BaseController { @@ -130,6 +131,18 @@ public function index(Request $request, $forum, $topic) TopicResource::withoutWrapping(); + $author = $topic->firstPost()->get()->first()->user->name; + $schema = Schema::discussionForumPosting() + ->identifier($request->getUri()) + ->headline($topic->title) + ->author( + Schema::person() + ->name($author) + )->interactionStatistic( + Schema::interactionCounter() + ->userInteractionCount($topic->replies) + ); + return $this->view('forum.topic', compact('posts', 'forum', 'paginate', 'reasons'))->with([ 'mlt' => $this->moreLikeThis($topic), 'model' => $topic, // we need eloquent model in twig to show information about locked/moved topic @@ -139,7 +152,8 @@ public function index(Request $request, $forum, $topic) 'all_forums' => $allForums, 'user_forums' => $userForums, 'description' => excerpt(array_first($posts['data'])['text'], 100), - 'flags' => $this->flags($forum) + 'flags' => $this->flags($forum), + 'schema' => $schema, ]); } diff --git a/app/Services/Breadcrumb.php b/app/Services/Breadcrumb.php index a5c50a409..bf50edeb2 100644 --- a/app/Services/Breadcrumb.php +++ b/app/Services/Breadcrumb.php @@ -3,6 +3,7 @@ namespace Coyote\Services; use Illuminate\Contracts\Support\Arrayable; +use Spatie\SchemaOrg\Schema; /** * Prosta klasa sluzaca do budowania elementu obecnego na kazdej podstronie, czyli breadcrumb @@ -48,7 +49,24 @@ public function push($name, $url = null) */ public function render() { - return view('components/breadcrumb', ['breadcrumbs' => $this->breadcrumbs]); + return view( + 'components/breadcrumb', + [ + 'breadcrumbs' => $this->breadcrumbs, + 'schema' => Schema::breadcrumbList() + ->itemListElement(array_map( + function ($breadcrumb, int $index) { + return Schema::listItem() + ->position($index + 1) + ->identifier($breadcrumb['url']) + ->name($breadcrumb['name']); + }, + $this->breadcrumbs, + array_keys($this->breadcrumbs), + ) + ), + ] + ); } /** diff --git a/composer.json b/composer.json index 3f6d153f4..bdc4b8bb8 100644 --- a/composer.json +++ b/composer.json @@ -50,6 +50,7 @@ "rawr/t-regx": "^v0.17.0", "rcrowe/twigbridge": "^0.12", "sentry/sentry-laravel": "^2.3", + "spatie/schema-org": "^3.14", "stripe/stripe-php": "^7.66", "twig/extensions": "^1.5" }, diff --git a/composer.lock b/composer.lock index 57d0bd001..5aaa7b119 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "94a38d5d0512ac0d1f85fa7f43bf5571", + "content-hash": "3d52844743640a80171e2be400826c00", "packages": [ { "name": "adam-boduch/laravel-grid", @@ -7847,6 +7847,79 @@ ], "time": "2023-02-09T10:38:43+00:00" }, + { + "name": "spatie/schema-org", + "version": "3.14.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/schema-org.git", + "reference": "ada9f696ae958236d6707caced77b2630185bb76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/schema-org/zipball/ada9f696ae958236d6707caced77b2630185bb76", + "reference": "ada9f696ae958236d6707caced77b2630185bb76", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.6", + "graham-campbell/analyzer": "^3.0.5", + "illuminate/collections": "^8.62.0", + "league/flysystem": "^2.3.0 || ^3.0", + "pestphp/pest": "^1.21", + "symfony/console": "^5.3.7 || 6.0", + "twig/twig": "^3.3.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\SchemaOrg\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sebastian De Deyne", + "email": "sebastian@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Tom Witkowski", + "email": "dev.gummibeer@gmail.com", + "homepage": "https://gummibeer.de", + "role": "Developer" + } + ], + "description": "A fluent builder Schema.org types and ld+json generator", + "homepage": "https://github.com/spatie/schema-org", + "keywords": [ + "schema-org", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/schema-org/issues", + "source": "https://github.com/spatie/schema-org/tree/3.14.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-02-14T16:46:30+00:00" + }, { "name": "spomky-labs/base64url", "version": "v2.0.4", diff --git a/resources/views/components/breadcrumb.twig b/resources/views/components/breadcrumb.twig index 67f24917b..da2d85a1d 100644 --- a/resources/views/components/breadcrumb.twig +++ b/resources/views/components/breadcrumb.twig @@ -20,3 +20,5 @@ + +{{ schema.toScript()|raw }} diff --git a/resources/views/components/schema.twig b/resources/views/components/schema.twig new file mode 100644 index 000000000..6804eae50 --- /dev/null +++ b/resources/views/components/schema.twig @@ -0,0 +1,14 @@ +{% macro organization() %} + +{% endmacro %} diff --git a/resources/views/forum/topic.twig b/resources/views/forum/topic.twig index 351b4eba9..58a4a6aa0 100644 --- a/resources/views/forum/topic.twig +++ b/resources/views/forum/topic.twig @@ -7,6 +7,7 @@ {% import 'components.modals' as modals %} {% block content %} + {{ schema.to_script|raw }} {% if model.locked_at and model.locker.id %}

@@ -36,7 +37,6 @@ {% endif %} - {% for post in posts.data %}

diff --git a/resources/views/layout.twig b/resources/views/layout.twig index 7495d2607..e24d73b46 100644 --- a/resources/views/layout.twig +++ b/resources/views/layout.twig @@ -47,6 +47,9 @@ {% block body %} {% import 'components.forms' as forms %} {% import 'components.widgets' as widgets %} + {% import 'components.schema' as schema %} + + {{ schema.organization() }}