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

@@ -5,6 +5,7 @@ namespace App\Services;
use App\Exceptions\SubmissionException;
use App\Helpers\EntryHelpers;
use App\Http\Requests\StoreEntryRequest;
use App\Jobs\CreateXenForoCommentsThread;
use App\Models\Author;
use App\Models\Entry;
use App\Models\EntryFile;
@@ -36,6 +37,12 @@ class SubmissionsService {
*/
private ?string $section = null;
/**
* Entry for edit.
* @var Entry|null
*/
private ?Entry $entry = null;
/**
* @return list<FSFileData>
*/
@@ -174,6 +181,9 @@ class SubmissionsService {
$this->Step12b_MoveMainImage( $entry );
$this->Step12c_SaveGalleryImages( $entry );
// Step 13: Try to create the comments section.
$this->Step13_CreateCommentsThread( $entry );
return $entry;
}
@@ -190,6 +200,13 @@ class SubmissionsService {
return $this->request->input('game_id');
// Need to create a game.
$game = $this->createGameFromFormFields();
return $game->id;
}
private function createGameFromFormFields(): Game
{
if( !$this->request->input('new-game-title') || !$this->request->input('new-game-platform') || !$this->request->input('new-game-genre') )
throw new SubmissionException( "New game informations is missing" );
@@ -201,14 +218,12 @@ class SubmissionsService {
$gameSlug = EntryHelpers::uniqueSlug( $this->request->input('new-game-title'), Game::class );
$game = Game::create([
return Game::create([
'name' => trim( $this->request->input('new-game-title') ),
'slug' => $gameSlug,
'platform_id' => $platform->id,
'genre_id' => $genre->id,
]);
return $game->id;
}
/**
@@ -228,7 +243,7 @@ class SubmissionsService {
if( section_must_be( 'translations', $this->section ) ) {
$fields['languages_string'] = Language::whereIn('id', $this->request->input('languages', []))->pluck('name')->implode(', ');
}
if( section_must_be(['romhacks', 'homebrew', 'lua-scripts', 'tutorials'], $this->section ) ) {
if( section_must_be(['romhacks', 'translations', 'homebrew', 'lua-scripts', 'tutorials'], $this->section ) ) {
// TODO: Add single platform ID compatibility.
$fields['platform_name'] = Game::find( $gameId )->platform->name;
}
@@ -242,12 +257,15 @@ class SubmissionsService {
* @return void
* @throws SubmissionException
*/
private function Step7_SaveEntryFiles( int $entryId ): void
private function Step7_SaveEntryFiles( int $entryId, ?array $uuidData = null ): void
{
foreach ( $this->request->input('files_uuid', [] ) as $uuid ) {
if( !$uuidData )
$uuidData = $this->request->input('files_uuid', [] );
foreach ( $uuidData as $uuid ) {
$fileData = Cache::pull("uploaded_file_{$uuid}");
if( !$fileData )
throw new SubmissionException( "File {$uuid} has expired. Please delete all your files and retry." );
throw new SubmissionException( "File {$uuid} has expired. Please delete all your files and retry. If it's an edition, delete all your new files and retry." );
EntryFile::create([
'entry_id' => $entryId,
@@ -293,6 +311,8 @@ class SubmissionsService {
*/
private function Step9_SaveAuthors( Entry $entry ): void
{
// TODO: Code fragment to be replaced by edit version.
// Existing authors.
foreach ( $this->request->input('authors', [] ) as $authorId ) {
$author = Author::find( $authorId );
@@ -323,6 +343,9 @@ class SubmissionsService {
*/
private function Step10_SaveRomhacksModifications( Entry $entry ): void
{
// TODO: Replace by edit version
foreach ( $this->request->input('modifications', [] ) as $modificationId ) {
$modification = Modification::find( $modificationId );
if( !$modification )
@@ -339,6 +362,8 @@ class SubmissionsService {
*/
private function Step11_SaveLanguages( Entry $entry ): void
{
// TODO: Replace by edit version.
foreach ( $this->request->input('languages', [] ) as $languageId ) {
$language = Language::find( $languageId );
if( !$language )
@@ -385,4 +410,325 @@ class SubmissionsService {
}
}
public function editEntry( StoreEntryRequest $request, string $section, Entry $entry ): Entry
{
// STEP 1: Prepare basic fields and keep in save some others fields.
$this->request = $request;
$this->section = $section;
$this->entry = $entry;
$user_id = 0; // TODO: Replace that.
$oldMainImage = $entry->main_image;
$galleryPaths = [];
$entry = DB::transaction( function() use ( $user_id, &$galleryPaths ){
// STEP 2: Create game if different.
$gameId = null;
if( section_must_be( ['romhacks', 'translations' ], $this->section ) ){
$gameId = $this->eStep2_VerifyCreateAndEditGameId();
}
// STEP 3: Recreate complete title and refresh slug if needed.
$completeTitle = $this->Step3_BuildCompleteTitle( $gameId );
if( $completeTitle !== $this->entry->complete_title ) {
$this->entry->complete_title = $completeTitle;
$this->entry->slug = EntryHelpers::uniqueSlug( $completeTitle, Entry::class, $this->entry->id );
}
// STEP 4: Regenerate entry title.
if( section_must_be( 'translations', $this->section ) &&
!$this->request->input('entry_title') ){
$this->entry->title = Game::find($gameId)->name;
} else {
$this->entry->title = $this->request->input('entry_title');
}
// STEP 5: Update entry fields.
$fields = [
'type' => $this->section,
'title' => $this->entry->title, // Useless, I know.
'slug' => $this->entry->slug,
'description' => $this->request->input('description'),
'main_image' => $this->request->input('main-image'),
'state' => $this->request->input('submit-state'),
'game_id' => $gameId,
'status_id' => $this->request->input('status'),
'version' => $this->request->input('version'),
'release_date' => $this->request->input('release-date'),
'staff_credits' => $this->request->input('staff_credits'),
'relevant_link' => $this->request->input('release_site'),
'youtube_link' => $this->request->input('youtube_video'),
'user_id' => $user_id,
'complete_title' => $completeTitle,
];
$this->entry->update( $fields );
// STEP 6: Update entry files.
$this->eStep6_UpdateEntryFiles( $this->entry->id );
// STEP 7: Update hashes.
$this->eStep7_UpdateHashes( $this->entry->id );
// STEP 8: Update Authors.
$this->eStep8_UpdateAuthors();
// STEP 9: Update romhacks modifications.
if( section_must_be( 'romhacks', $this->section ) ) {
$this->eStep9_UpdateRomhacksModifications();
}
// STEP 10: Update Languages.
$this->eStep10_UpdateLanguages();
// STEP 11: Prepare new gallery images and prepare deletion of others ones.
$galleryPaths = $this->eStep11a_UpdateGalleryImages();
// STEP 13: Try to create comments area if it doesn't exist.
$this->Step13_CreateCommentsThread( $this->entry );
return $this->entry;
});
// STEP 11 : Update main image if needed.
$this->eStep11b_UpdateMainImage( $oldMainImage );
// STEP 11 : Update gallery storage.
$this->eStep11c_UpdateGalleryImages( $galleryPaths );
return $entry;
}
/**
* @throws SubmissionException
*/
private function eStep2_VerifyCreateAndEditGameId(): int
{
// Already existing game.
if( $this->request->input('game_id') ){
if( $this->entry->game_id == $this->request->input('game_id') ){
return $this->entry->game_id; // No changes.
} else { // Change in game but already exist.
$game = Game::find( $this->request->input('game_id') );
if( !$game )
throw new SubmissionException( "Game {$this->request->input('game_id')} does not exist." );
$this->entry->game_id = $game->id;
return $this->entry->game_id;
}
}
// Need to create a game.
$game = $this->createGameFromFormFields();
$this->entry->game_id = $game->id;
return $this->entry->game_id;
}
/**
* @throws SubmissionException
*/
private function eStep6_UpdateEntryFiles(int $entryId ): void
{
$requestUuids = $this->request->input('files_uuid', []);
$existingUuids = EntryFile::where( 'entry_id', $entryId )->pluck('file_uuid')->toArray();
$needDeletion = array_diff( $existingUuids, $requestUuids );
if( !empty( $needDeletion ) ){
EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->delete();
}
$needAddition = array_diff( $requestUuids, $existingUuids );
if( !empty( $needAddition ) ){
$this->Step7_SaveEntryFiles( $this->entry->id, $needAddition ); // Same code.
}
}
private function eStep7_UpdateHashes(int $entryId): void
{
$requestHashes = collect( $this->request->input('hashes', [] ) )
->filter( fn($h) => isset( $h['filename'], $h['hash_crc32'], $h['hash_sha1'], $h['verified'] ) )
->keyBy( 'hash_sha1' )
->toArray();
;
$existingHashes = EntryHash::where( 'entry_id', $entryId )->get()->keyBy( 'hash_sha1' );
$hashsToDelete = array_diff( $existingHashes->keys()->toArray(), array_keys( $requestHashes ) );
if( !empty( $hashsToDelete ) ){
EntryHash::where( 'entry_id', $entryId )->whereIn('hash_sha1', $hashsToDelete)->delete();
}
foreach( $requestHashes as $sha1 => $hash ){
if( $existingHashes->has( $sha1 ) ){
$existingHashes->get( $sha1 )->update([
'filename' => $hash['filename'],
'hash_crc32' => $hash['hash_crc32'],
'hash_sha1' => $hash['hash_sha1'],
'verified' => $hash['verified'],
]);
} else {
EntryHash::create([
'entry_id' => $entryId,
'filename' => $hash['filename'],
'hash_crc32' => $hash['hash_crc32'],
'hash_sha1' => $hash['hash_sha1'],
'verified' => $hash['verified'],
]);
}
}
}
/**
* @return void
* @throws SubmissionException
*/
private function eStep8_UpdateAuthors(): void
{
$syncAuthorsId = [];
$requestAuthorsId = $this->request->input('authors', [] );
if( !empty( $requestAuthorsId ) ){
$valid = Author::whereIn( 'id', $requestAuthorsId )->pluck('id')->toArray();
if( count( $valid ) !== count( $requestAuthorsId ) ){
throw new SubmissionException( "One of the authors doesn't exist." );
}
$syncAuthorsId = array_merge( $syncAuthorsId, $requestAuthorsId );
}
foreach ( $this->request->input('new-authors', [] ) as $authorName ) {
$authorName = trim($authorName);
if ($authorName === '')
continue;
$author = Author::firstOrCreate(
['slug' => EntryHelpers::uniqueSlug($authorName, Author::class)],
['name' => $authorName]
);
$syncAuthorsId[] = $author->id;
}
$this->entry->authors()->sync( $syncAuthorsId );
}
/**
* @return void
* @throws SubmissionException
*/
private function eStep9_UpdateRomhacksModifications(): void
{
$requestModifications = $this->request->input('modifications', [] );
if( !empty( $requestModifications ) ){
$valid = Modification::whereIn( 'id', $requestModifications )->pluck('id')->toArray();
if( count( $valid ) !== count( $requestModifications ) ){
throw new SubmissionException( "One of the modifications doesn't exist." );
}
}
$this->entry->modifications()->sync( $requestModifications );
}
/**
* @return void
* @throws SubmissionException
*/
private function eStep10_UpdateLanguages(): void
{
$requestLanguages = $this->request->input('languages', [] );
if( !empty( $requestLanguages ) ){
$valid = Language::whereIn( 'id', $requestLanguages )->pluck('id')->toArray();
if( count( $valid ) !== count( $requestLanguages ) ){
throw new SubmissionException( "One of the languages doesn't exist." );
}
}
$this->entry->languages()->sync( $requestLanguages );
}
private function eStep11a_UpdateGalleryImages(): array
{
$requestGallery = $this->request->input('gallery', [] );
$existingGalleryPaths = $this->entry->gallery->pluck('image')->toArray();
$needDeletion = array_diff( $existingGalleryPaths, $requestGallery );
if( !empty( $needDeletion ) ){
EntryGallery::where('entry_id', $this->entry->id)->whereIn('image', $needDeletion )->delete();
}
$needAddition = array_diff( $requestGallery, $existingGalleryPaths );
$images = [];
foreach( $needAddition as $imagePath ){
$images[] = EntryGallery::create([
'entry_id' => $this->entry->id,
'image' => $imagePath,
]);
}
return [ 'addition' => $images, 'deletion' => $needDeletion ];
}
private function eStep11b_UpdateMainImage( ?string $oldMainImagePath ): void
{
$currentMainImagePath = $this->entry->main_image;
if( $currentMainImagePath === $oldMainImagePath )
return;
$newPath = 'entries/main-images/' . basename( $currentMainImagePath );
if( !Storage::disk('public')->move( $currentMainImagePath, $newPath ) ){
$this->entry->update(['main_image' => $oldMainImagePath]);
return;
}
$this->entry->update(['main_image' => $newPath]);
if( $oldMainImagePath && Storage::disk('public')->exists($oldMainImagePath) )
Storage::disk('public')->delete($oldMainImagePath);
}
private function eStep11c_UpdateGalleryImages( array $pathsChanges ): void
{
foreach ( $pathsChanges['deletion'] as $deletePath ){
if( Storage::disk('public')->exists($deletePath) )
Storage::disk('public')->delete($deletePath);
}
foreach ( $pathsChanges['addition'] as $galleryItem ){
$newPath = 'entries/gallery-images/' . $this->entry->id . '/' . basename( $galleryItem->image );
if( !Storage::disk('public')->move( $galleryItem->image, $newPath ) ){
continue;
}
$galleryItem->update(['image' => $newPath]);
}
}
private function Step13_CreateCommentsThread( Entry $entry ): void
{
if( !$entry->comments_thread_id )
CreateXenForoCommentsThread::dispatch( $entry );
// app(XenforoApiService::class)->createCommentsThread( $entry );
}
}