diff --git a/app/Libraries/Search/ForumSearch.php b/app/Libraries/Search/ForumSearch.php index 3b7b4d8faa8..f10ca8ead5d 100644 --- a/app/Libraries/Search/ForumSearch.php +++ b/app/Libraries/Search/ForumSearch.php @@ -82,6 +82,14 @@ public function data() return $this->response(); } + /** + * @return Builder + */ + public function posts(): Builder + { + return Post::withTrashed()->whereKey($this->response()->ids('post_id')); + } + /** * Returns a Builder for a Collection of all the posts that appeared in this query. */ diff --git a/app/Models/Forum/LegacyIcon.php b/app/Models/Forum/LegacyIcon.php new file mode 100644 index 00000000000..e5b0d660682 --- /dev/null +++ b/app/Models/Forum/LegacyIcon.php @@ -0,0 +1,26 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +namespace App\Models\Forum; + +/** + * Icons used to label various models from phpBB. On the old website, they were + * available for use, but now they are read-only. + * + * @property bool $display_on_posting + * @property int $icons_height + * @property int $icons_id + * @property int $icons_order + * @property string $icons_url + * @property int $icons_width + */ +class LegacyIcon extends Model +{ + public $timestamps = false; + + protected $casts = ['display_on_posting' => 'boolean']; + protected $primaryKey = 'icons_id'; + protected $table = 'phpbb_icons'; +} diff --git a/app/Models/Forum/Post.php b/app/Models/Forum/Post.php index 3f1c04ee3cc..c0b617dec73 100644 --- a/app/Models/Forum/Post.php +++ b/app/Models/Forum/Post.php @@ -395,6 +395,18 @@ public function isBeatmapsetPost() } } + public function legacyIcon(): ?LegacyIcon + { + // TODO: $this->icon_id shouldn't be null, but there are some cases + // where we make a new Post model and don't refresh it with the default + // attributes from database + if ($this->icon_id === null) { + return null; + } + + return app('forum-legacy-icons')->byId($this->icon_id); + } + public function validationErrorsTranslationPrefix(): string { return 'forum.post'; diff --git a/app/Models/Forum/Topic.php b/app/Models/Forum/Topic.php index 2ad4fd54c62..e32bd692b2e 100644 --- a/app/Models/Forum/Topic.php +++ b/app/Models/Forum/Topic.php @@ -506,6 +506,11 @@ public function isActive() return $this->topic_last_post_time > Carbon::now()->subMonths($GLOBALS['cfg']['osu']['forum']['necropost_months']); } + public function legacyIcon(): ?LegacyIcon + { + return app('forum-legacy-icons')->byId($this->icon_id); + } + public function markRead($user, $markTime) { if ($user === null) { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 4dce720a780..dee72be5fe6 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -28,6 +28,7 @@ class AppServiceProvider extends ServiceProvider const LOCAL_CACHE_SINGLETONS = [ 'chat-filters' => Singletons\ChatFilters::class, 'countries' => Singletons\Countries::class, + 'forum-legacy-icons' => Singletons\ForumLegacyIcons::class, 'groups' => Singletons\Groups::class, 'layout-cache' => Singletons\LayoutCache::class, 'medals' => Singletons\Medals::class, diff --git a/app/Singletons/ForumLegacyIcons.php b/app/Singletons/ForumLegacyIcons.php new file mode 100644 index 00000000000..ad6b80a0f00 --- /dev/null +++ b/app/Singletons/ForumLegacyIcons.php @@ -0,0 +1,33 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Singletons; + +use App\Models\Forum\LegacyIcon; +use App\Traits\Memoizes; +use Illuminate\Database\Eloquent\Collection; + +class ForumLegacyIcons +{ + use Memoizes; + + /** + * Get a legacy forum icon by its ID. + */ + public function byId(int $id): ?LegacyIcon + { + return $this->allById()->get($id); + } + + /** + * @return Collection + */ + private function allById(): Collection + { + return $this->memoize(__FUNCTION__, fn () => LegacyIcon::all()->keyBy('icons_id')); + } +} diff --git a/app/Traits/Memoizes.php b/app/Traits/Memoizes.php index 458f3220f62..5590c49779a 100644 --- a/app/Traits/Memoizes.php +++ b/app/Traits/Memoizes.php @@ -14,7 +14,12 @@ public function resetMemoized(): void $this->memoized = []; } - protected function memoize(string $key, callable $function) + /** + * @template TReturn + * @param callable(): TReturn $function + * @return TReturn + */ + protected function memoize(string $key, callable $function): mixed { if (!array_key_exists($key, $this->memoized)) { $this->memoized[$key] = $function(); diff --git a/config/osu.php b/config/osu.php index c2f878d8e2d..15679bdb30c 100644 --- a/config/osu.php +++ b/config/osu.php @@ -223,6 +223,7 @@ 'bounty-form' => env('OS_BOUNTY_URL'), 'dev' => 'https://discord.gg/ppy', 'experimental_host' => presence(env('OSU_EXPERIMENTAL_HOST')), + 'forum_legacy_icons' => 'https://old.ppy.sh/forum/images/icons', 'installer' => 'https://m1.ppy.sh/r/osu!install.exe', 'installer-mirror' => 'https://m2.ppy.sh/r/osu!install.exe', 'lazer_dl.android' => presence(env('OSU_URL_LAZER_ANDROID')) ?? 'https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk', diff --git a/database/migrations/2024_06_17_203000_create_phpbb_icons.php b/database/migrations/2024_06_17_203000_create_phpbb_icons.php new file mode 100644 index 00000000000..82a15e9364e --- /dev/null +++ b/database/migrations/2024_06_17_203000_create_phpbb_icons.php @@ -0,0 +1,42 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class extends Migration +{ + /** + * Run the migrations. + */ + public function up(): void + { + if (Schema::hasTable('phpbb_icons')) { + return; + } + + Schema::create('phpbb_icons', function (Blueprint $table) { + $table->mediumIncrements('icons_id'); + $table->string('icons_url')->default(''); + $table->tinyInteger('icons_width')->default(0); + $table->tinyInteger('icons_height')->default(0); + $table->unsignedMediumInteger('icons_order')->default(0); + $table->boolean('display_on_posting')->default(true); + + $table->index(['display_on_posting'], 'display_on_posting'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::drop('phpbb_icons'); + } +}; diff --git a/resources/css/bem-index.less b/resources/css/bem-index.less index 497d2660257..83191c1d17a 100644 --- a/resources/css/bem-index.less +++ b/resources/css/bem-index.less @@ -165,6 +165,7 @@ @import "bem/forum-issue-icon"; @import "bem/forum-item"; @import "bem/forum-item-stripe"; +@import "bem/forum-legacy-icon"; @import "bem/forum-list"; @import "bem/forum-poll"; @import "bem/forum-poll-container"; diff --git a/resources/css/bem/forum-legacy-icon.less b/resources/css/bem/forum-legacy-icon.less new file mode 100644 index 00000000000..3aa4915f0c1 --- /dev/null +++ b/resources/css/bem/forum-legacy-icon.less @@ -0,0 +1,6 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +.forum-legacy-icon { + margin: 0 5px; +} diff --git a/resources/css/bem/forum-topic-entry.less b/resources/css/bem/forum-topic-entry.less index 82355ad9327..11982226682 100644 --- a/resources/css/bem/forum-topic-entry.less +++ b/resources/css/bem/forum-topic-entry.less @@ -132,7 +132,8 @@ } } - &__issue-icons { + &__icons { + align-items: center; flex: none; display: flex; padding: 5px 5px 0; diff --git a/resources/css/bem/search-forum-post.less b/resources/css/bem/search-forum-post.less index 98c1bcc6917..d1ee4501677 100644 --- a/resources/css/bem/search-forum-post.less +++ b/resources/css/bem/search-forum-post.less @@ -4,6 +4,8 @@ .search-forum-post { @avatar-size: 50px; @margin: 5px; + + align-items: center; display: flex; flex-direction: row; flex-wrap: wrap; diff --git a/resources/views/forum/_legacy_icon.blade.php b/resources/views/forum/_legacy_icon.blade.php new file mode 100644 index 00000000000..d733425c289 --- /dev/null +++ b/resources/views/forum/_legacy_icon.blade.php @@ -0,0 +1,11 @@ +{{-- + Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. + See the LICENCE file in the repository root for full licence text. +--}} + diff --git a/resources/views/forum/forums/_topic.blade.php b/resources/views/forum/forums/_topic.blade.php index 48c253e61dd..7bfbe9bf496 100644 --- a/resources/views/forum/forums/_topic.blade.php +++ b/resources/views/forum/forums/_topic.blade.php @@ -85,7 +85,11 @@ class=" -
+
+ @if ($topic->legacyIcon() !== null) + @include('forum._legacy_icon', ['icon' => $topic->legacyIcon()]) + @endif + @foreach ($topic->issueTags() as $tag)
post_time) !!}
+ + @if ($post->legacyIcon() !== null) +
+ @include('forum._legacy_icon', ['icon' => $post->legacyIcon()]) +
+ @endif
@if (count($buttons) > 0) diff --git a/resources/views/home/_search_result_forum_post.blade.php b/resources/views/home/_search_result_forum_post.blade.php index e4d1f6d0665..a89b2ae6791 100644 --- a/resources/views/home/_search_result_forum_post.blade.php +++ b/resources/views/home/_search_result_forum_post.blade.php @@ -4,6 +4,7 @@ --}} {{-- more code than template in this view :best: --}} @php + $posts = $search->posts()->select('post_id', 'icon_id')->get()->keyBy('post_id'); $users = $search->users()->select('user_id', 'username', 'user_avatar')->get()->keyBy('user_id'); $topics = $search->topics()->with('forum')->get()->keyBy('topic_id'); $skipTitle = $search->isTopicSpecificSearch(); @@ -12,6 +13,7 @@ @foreach ($search->data() as $entry) @php // $entry should be of type App\Libraries\Elasticsearch\Hit + $post = $posts[$entry->source('post_id')]; $postUrl = post_url($entry->source('topic_id'), $entry->source('post_id')); $postId = $entry->source('post_id'); $topic = $topics[$entry->source('topic_id')] ?? new App\Models\Forum\Topic(); @@ -25,6 +27,7 @@ @endphp
@include('objects.search._forum_post', [ + 'post' => $post, 'user' => $user, 'title' => $title, 'link' => $postUrl, diff --git a/resources/views/objects/search/_forum_post.blade.php b/resources/views/objects/search/_forum_post.blade.php index 1e43e1ad993..4c75f604a72 100644 --- a/resources/views/objects/search/_forum_post.blade.php +++ b/resources/views/objects/search/_forum_post.blade.php @@ -14,6 +14,11 @@ > + + @if ($post->legacyIcon() !== null) + @include('forum._legacy_icon', ['icon' => $post->legacyIcon()]) + @endif +
@if (isset($title))