A lot of things.

This commit is contained in:
2026-05-27 21:24:38 +02:00
parent b361f07954
commit d02baa89d6
43 changed files with 1340 additions and 231 deletions

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Helpers\EntryHelpers;
use App\Models\Entry;
use Illuminate\Http\Request;
use Illuminate\View\View;
@@ -25,7 +26,9 @@ class EntryController extends Controller
if( $entry->type !== $section )
abort(404);
return view('entries.show', compact('entry', 'section'));
$comments = EntryHelpers::getLatestComments( $entry );
return view('entries.show', compact('entry', 'section', 'comments' ) );
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Http\Controllers;
use App\Models\Entry;
use Illuminate\Http\Request;
class RedirectController extends Controller
{
public function entryReportRedirect( Request $request )
{
$id = $request->input('id');
$entry = Entry::findOrFail($id);
return redirect()->route('entries.show', ['section' => $entry->type, 'entry' => $entry])->with('success', "Your report has been sent.");
}
}

View File

@@ -102,164 +102,19 @@ class SubmissionController extends Controller
public function update(StoreEntryRequest $request, string $section, Entry $entry)
{
if( $entry->type !== $section ) {
abort(404);
try {
$entry = $this->services->editEntry($request, $section, $entry);
return match ($entry->state) {
'published' => redirect()->route('entries.show', ['section' => $section, 'entry' => $entry->slug])->with('success', "Your entry has been published."),
'pending' => redirect()->route('home')->with('success', "Your entry has been submitted and is pending review."),
default => redirect()->route('home')->with('success', "Your entry has been saved as a draft.")
};
} catch ( SubmissionException $e ) {
return back()->withInput()->withErrors(['error' => $e->getMessage()]);
} catch ( \Exception $e ) {
return back()->withInput()->withErrors(['error' => 'Unknown error: '.$e->getMessage()]);
}
$gameId = null;
if( !$request->input('game_id') ){
if( $request->input('new-game-title') && $request->input('new-game-platform') && $request->input('new-game-genre') ){
$platform = Platform::find($request->input('new-game-platform'));
$genre = Genre::find($request->input('new-game-genre'));
$game = Game::create([
'name' => $request->input('new-game-title'),
'slug' => Str::slug($request->input('new-game-title')),
'platform_id' => $platform->id,
'genre_id' => $genre->id,
]);
$gameId = $game->id;
}
} else {
$gameId = $request->input('game_id');
}
$mainImage = $entry->main_image;
if ( $request->hasFile('main-image') ) {
if ( $mainImage ) {
Storage::disk('public')->delete($mainImage);
}
$mainImage = $request->file('main-image')->store('entries/main_images', 'public');
} elseif ( $request->input('remove_main_image') === '1' ) {
if ( $mainImage ) {
Storage::disk('public')->delete($mainImage);
}
$mainImage = null;
}
$staffCredits = collect($request->input('credits', []))
->filter(fn($item) => isset($item['name']) || isset($item['description']))
->map(function ($item) {
$name = trim($item['name'] ?? '');
$description = trim($item['description'] ?? '');
if ($name === '' && $description === '') {
return null;
}
return trim($name . ($name !== '' && $description !== '' ? ' — ' : '') . $description);
})
->filter()
->implode("\n");
$fields = [
'type' => $section,
'title' => $request->input('entry_title'),
'slug' => $request->input('slug') ?? Str::slug($request->input('entry_title', '')),
'description' => $request->input('description'),
'main_image' => $mainImage,
'state' => $request->input('submit-state', 'draft'),
'game_id' => $gameId,
'status_id' => $request->input('status'),
'version' => $request->input('version'),
'release_date' => $request->input('release-date'),
'staff_credits' => $staffCredits ?: null,
'relevant_link' => $request->input('release_site'),
'youtube_link' => $request->input('youtube_video'),
];
$entry->update($fields);
$entry->hashes()->delete();
foreach ( $request->input('hashes', []) as $hash ) {
if( !isset($hash['filename'], $hash['crc32'], $hash['sha1'], $hash['verified']) ) {
continue;
}
EntryHash::create([
'entry_id' => $entry->id,
'filename' => $hash['filename'],
'hash_crc32' => $hash['crc32'],
'hash_sha1' => $hash['sha1'],
'verified' => $hash['verified'],
]);
}
$authorIds = [];
foreach ( $request->input('authors', []) as $authorId ) {
$author = Author::find($authorId);
if( $author ) {
$authorIds[] = $author->id;
}
}
foreach( $request->input('new-authors', []) as $authorName ) {
$authorName = trim($authorName);
if ($authorName === '') continue;
$author = Author::firstOrCreate(
['slug' => Str::slug($authorName)],
['name' => $authorName],
);
$authorIds[] = $author->id;
}
$entry->authors()->sync(array_values(array_unique($authorIds)));
if( section_must_be( 'romhacks', $section ) ){
$entry->modifications()->sync($request->input('modifications', []));
} else {
$entry->modifications()->sync([]);
}
$entry->languages()->sync($request->input('languages', []));
$existingFileUuids = $request->input('existing_file_ids', []);
if (!is_array($existingFileUuids)) {
$existingFileUuids = [];
}
$entry->files()->whereNotIn('file_uuid', $existingFileUuids)->delete();
foreach ( $request->input('file_ids', []) as $file_uuid ) {
$fileData = Cache::pull("uploaded_file_{$file_uuid}");
if( ! $fileData ) {
continue;
}
EntryFile::create([
'entry_id' => $entry->id,
'file_uuid' => $fileData['uuid'],
'filename' => $fileData['filename'],
'filepath' => $fileData['filepath'],
'favorite_server' => $fileData['favorite_server'],
'favorite_at' => \DateTimeImmutable::createFromTimestamp( $fileData['favorite_at'] ),
'filesize' => $fileData['filesize'],
'state' => 'public'
]);
}
$existingGalleryIds = $request->input('existing_gallery_ids', []);
if (!is_array($existingGalleryIds)) {
$existingGalleryIds = [];
}
$entry->gallery()->whereNotIn('id', $existingGalleryIds)->get()->each(function ($gallery) {
if ($gallery->image) {
Storage::disk('public')->delete($gallery->image);
}
$gallery->delete();
});
foreach ( $request->file('gallery', [] ) as $galleryFile ){
if( !$galleryFile->isValid() ){
continue;
}
$path = $galleryFile->store('entries/gallery/' . $entry->id, 'public');
EntryGallery::create([
'entry_id' => $entry->id,
'image' => $path
]);
}
return match( $entry->state ){
'published' => redirect()->route('entries.show', [ 'section' => $section, 'entry' => $entry->slug ])->with('success', "Your entry has been published."),
'pending' => redirect()->route('home')->with('success', "Your entry has been submitted and is pending review."),
default => redirect()->route('home')->with('success', "Your entry has been saved as a draft.")
};
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers;
use App\Models\Entry;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class WebhookController extends Controller
{
public function XenForoNewPost(Request $request)
{
if( $request->header('XF-Webhook-Secret') !== env('WEBHOOK_SECRET') )
abort(403);
$threadId = $request->input('data.thread_id');
if( $threadId ){
$entry = Entry::where('comments_thread_id', $threadId)->first();
if( $entry ){
Cache::forget("entry_comments_{$entry->id}");
}
}
return response()->json(['success' => true]);
}
}

View File

@@ -24,7 +24,7 @@ class CheckXenForoPermissions
foreach ($permissions as $permissionStr) {
[$group, $permission] = explode('.', $permissionStr);
if( !\Auth::user()->can($group, $permission) )
if( !\Auth::user()->_can($group, $permission) )
return $this->deny($request, $permission);
}

View File

@@ -14,8 +14,11 @@ class StoreEntryRequest extends FormRequest
*/
public function authorize(): bool
{
// TODO: Change it by role.
return true;
$entry = $this->route('entry');
if( $entry )
return $this->user()->can('update', $entry);
return $this->user()->can('create', '\App\Models\Entry');
}
/**

View File

@@ -2,6 +2,7 @@
namespace App\Http\Requests;
use App\Services\TemporaryFileService;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
@@ -12,7 +13,7 @@ class TemporaryFileUploadRequest extends FormRequest
*/
public function authorize(): bool
{
return true;
return $this->user()->can('create', TemporaryFileService::class );
}
/**