*/ public function prepareOldFiles( ?Entry $entry = null ): array { if( $entry === null ){ $files = old( 'files_uuid', [] ); } else { $files = old( 'files_uuid', $entry->files->pluck('file_uuid')->toArray() ); } if( $files === [] ) return []; $service = app(FileServersService::class); return array_map( function( string $uuid ) use ($service) { $file = EntryFile::where('file_uuid', $uuid)->first(); if( $file ) return [ 'name' => $file->filename, 'totalChunks' => 0, // Already uploaded. 'rawFile' => null, 'progressValue' => 0, 'currentChunk' => 0, 'done' => true, 'error' => null, 'uuid' => $uuid, 'state' => $file->state, 'file_explorer' => $service->getArchiveExplorerUrl($file), 'file_explorer_files' => null, 'download_url' => $service->getDownloadFileUrl($file, false), 'can_be_online_patched' => EntryHelpers::enableOnlinePatcherBasedOnExtension($file['filename']), 'meta_online_patcher' => $file->online_patcher, 'meta_secondary_online_patcher' => $file->secondary_online_patcher, 'meta_play_online' => $file->playOnlineSetting()->exists() ? true : false, 'meta_play_online_core' => $file->playOnlineSetting()->exists() ? $file->playOnlineSetting->core : '', 'meta_play_online_threads' => $file->playOnlineSetting()->exists() ? $file->playOnlineSetting->threads : false, ]; $file = Cache::get("uploaded_file_{$uuid}"); if( $file ) return [ 'name' => $file['filename'], 'totalChunks' => 0, // Already uploaded. 'rawFile' => null, 'progressValue' => 0, 'currentChunk' => 0, 'done' => true, 'error' => null, 'uuid' => $uuid, 'state' => $file['state'], 'file_explorer' => null, 'file_explorer_files' => null, 'download_url' => null, 'can_be_online_patched' => EntryHelpers::enableOnlinePatcherBasedOnExtension($file['filename']), 'meta_online_patcher' => false, 'meta_secondary_online_patcher' => false, 'meta_play_online' => false, 'meta_play_online_core' => null, 'meta_play_online_threads' => false ]; return null; }, $files ); } /** * @param StoreEntryRequest $request * @param string $section * * @return Entry * @throws SubmissionException * @throws \Throwable */ public function storeEntry( Request $request, string $section ){ // STEP 1 : Prepare basic fields. $this->request = $request; $this->section = $section; $user_id = \Auth::user()->user_id; $entry = DB::transaction(function () use ( $user_id ) { // STEP 2 : Create game. $gameId = $this->Step2_CreateAndReturnGameId(); // STEP 3 : Create Complete title. $completeTitle = $this->Step3_BuildCompleteTitle( $gameId ); // STEP 4 : Generate slug and entry title. $entrySlug = EntryHelpers::uniqueSlug( $completeTitle, Entry::class ); if( section_must_be( 'translations', $this->section ) && !$this->request->input('entry_title') ){ $entryTitle = Game::find($gameId)->name ?? ""; } else { $entryTitle = $this->request->input('entry_title'); } // STEP 5 : Removed / Delayed. // $mainImage = $this->Step5_MoveMainImage(); // STEP 6 : Prepare entry fields and save entry. $fields = [ 'type' => $this->section, 'title' => $entryTitle, 'slug' => $entrySlug, 'description' => $this->request->input('description'), 'main_image' => $this->request->input('main-image'), 'state' => $this->request->input('submit-state'), 'game_id' => $gameId, 'platform_id' => $this->request->input('platform_only_id'), '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, 'level_id' => $this->request->input('level') ]; $entry = Entry::create( $fields ); // STEP 7 : Save entry fields. $this->Step7_SaveEntryFiles( $entry ); // STEP 8 : Save hashes. if( section_must_be( ['translations', 'romhacks' ], $this->section ) ) $this->Step8_SaveHashes( $entry->id ); // STEP 9 : Save Authors. $this->Step9_SaveAuthors( $entry ); // STEP 10 : Save Modifications. if( section_must_be( ['romhacks','lua-scripts'], $this->section ) ){ $this->Step10_SaveRomhacksModifications( $entry ); } if( section_must_be( 'utilities', $this->section ) ){ $this->Step10_SaveUtilitiesSystems( $entry ); } // STEP 11 : Save Languages $this->Step11_SaveLanguages( $entry ); // STEP 11.5 : Save Categories if( section_must_be( 'utilities', $this->section ) ) { $this->Step11_5_SaveCategories($entry); } // STEP 12 : Prepare Gallery images. $this->Step12a_PrepareGalleryImages( $entry ); return $entry; }); // Step 12, Move main image and gallery. $this->Step12b_MoveMainImage( $entry ); $this->Step12c_SaveGalleryImages( $entry ); // Step 13: Try to create the comments section. $this->Step13_CreateCommentsThread( $entry ); // Step 14: Refresh XF count. if( $entry->state !== 'draft') XenForoHelpers::updateEntriesCount( $entry->user_id ); return $entry; } /** * @return null|int * * @throws SubmissionException */ private function Step2_CreateAndReturnGameId(): ?int { $mode = $this->request->input('game_selection_mode', 'game'); if( $mode !== 'game' ) return null; // Already existing game. if( $this->request->input('game_id') ) return $this->request->input('game_id'); // No fields like a draft. if( !$this->request->input('new-game-title') && !$this->request->input('new-game-platform') && !$this->request->input('new-game-genre') ) return null; // 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" ); $platform = Platform::find( $this->request->input('new-game-platform') ); $genre = Genre::find( $this->request->input('new-game-genre') ); if( !$platform || !$genre ) throw new SubmissionException( "Incorrect game platform id" ); $gameSlug = EntryHelpers::uniqueSlug( $this->request->input('new-game-title'), Game::class ); return Game::create([ 'name' => trim( $this->request->input('new-game-title') ), 'slug' => $gameSlug, 'platform_id' => $platform->id, 'genre_id' => $genre->id, ]); } /** * Prepare and build complete title. * * @param int|null $gameId * * @return string */ private function Step3_BuildCompleteTitle( ?int $gameId = null ): string { $fields = []; $fields['entry_title'] = $this->request->input('entry_title') ?? null; if( section_must_be( [ 'homebrew', 'translations' ], $this->section ) && $gameId ){ $fields['game_name'] = $gameId ? Game::find( $gameId )->name : null; } 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', 'translations', 'homebrew', 'lua-scripts'], $this->section ) ) { // TODO: Add single platform ID compatibility. $fields['platform_name'] = $gameId ? Game::find( $gameId )->platform->name : Platform::find( $this->request->input('platform_only_id') )?->name ?? null; } return EntryHelpers::buildCompleteTitle( $this->section, $fields ); } /** * @param int $entryId * * @return void * @throws SubmissionException */ private function Step7_SaveEntryFiles( Entry $entry, ?array $uuidData = null ): void { if( !$uuidData ) $uuidData = $this->request->input('files_uuid', [] ); $metadataArray = $this->request->input('files_metadata', []); 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. If it's an edition, delete all the new files and retry." ); if( section_must_be( [ 'romhacks', 'translations' ], $entry->type ) ) { $onlinePatcher = (bool)($metadataArray[$uuid]['online_patcher'] ?? false); if (!$onlinePatcher) $onlinePatcher = EntryHelpers::enableOnlinePatcherBasedOnExtension($fileData['filename']); $secondaryOnlinePatcher = (bool)($metadataArray[$uuid]['secondary_online_patcher'] ?? false); } else { $onlinePatcher = false; $secondaryOnlinePatcher = false; } $file = EntryFile::create([ 'entry_id' => $entry->id, 'file_uuid' => $uuid, 'filename' => $fileData['filename'], 'filepath' => $fileData['filepath'], 'favorite_server' => $fileData['favorite_server'], 'favorite_at' => \DateTimeImmutable::createFromTimestamp( $fileData['favorite_at'] ), 'filesize' => $fileData['filesize'], 'state' => 'public', 'online_patcher' => $onlinePatcher, 'secondary_online_patcher' => $secondaryOnlinePatcher, ]); if( section_must_be( ['romhacks', 'translations', 'homebrew'], $entry->type ) ) { $playOnline = (bool)($metadataArray[$uuid]['play_online'] ?? false); $playOnlineCore = $metadataArray[$uuid]['play_online_core'] ?? null; $playOnlineThreads = (bool)($metadataArray[$uuid]['play_online_threads'] ?? false); if (!$playOnline && $entry->getRealPlatform()?->play_online_core !== null) { $playOnline = true; $playOnlineCore = $entry->getRealPlatform()?->play_online_core; } if ($playOnline) { $file->playOnlineSetting()->updateOrCreate( ['file_id' => $file->id], [ 'core' => $playOnlineCore, 'threads' => $playOnlineThreads, ] ); } } } } /** * @param int $entryId * * @return void */ private function Step8_SaveHashes( int $entryId ): void { foreach ( $this->request->input('hashes', [] ) ?? [] as $hash ) { if( !isset($hash['filename'], $hash['hash_crc32'], $hash['hash_sha1'], $hash['verified']) ) { continue; } EntryHash::create([ 'entry_id' => $entryId, 'filename' => $hash['filename'], 'hash_crc32' => $hash['hash_crc32'], 'hash_sha1' => $hash['hash_sha1'], 'verified' => $hash['verified'], ]); } } /** * @param Entry $entry * * @return void * @throws SubmissionException */ 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 ); if( !$author ) throw new SubmissionException( "Author {$authorId} does not exist." ); $entry->authors()->attach( $author->id ); } // New Authors 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] ); $entry->authors()->attach( $author->id ); } } /** * @param Entry $entry * * @return void * @throws SubmissionException */ 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 ) throw new SubmissionException( "Modification {$modificationId} does not exist." ); $entry->modifications()->attach( $modification->id ); } } /** * @param Entry $entry * * @return void * @throws SubmissionException */ private function Step10_SaveUtilitiesSystems( Entry $entry ): void { // TODO: Replace by edit version foreach ( $this->request->input('systems', [] ) ?? [] as $systemId ) { $system = System::find( $systemId ); if( !$system ) throw new SubmissionException( "System {$systemId} does not exist." ); $entry->systems()->attach( $system->id ); } } /** * @param Entry $entry * * @return void * @throws SubmissionException */ 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 ) throw new SubmissionException( "Language {$languageId} does not exist." ); $entry->languages()->attach( $language->id ); } } /** * @param Entry $entry * * @return void * @throws SubmissionException */ private function Step11_5_SaveCategories( Entry $entry ): void { // TODO: Replace by edit version. foreach ( $this->request->input('categories', [] ) ?? [] as $categoryId ) { $category = Category::find( $categoryId ); if( !$category ) throw new SubmissionException( "Category {$categoryId} does not exist." ); $entry->categories()->attach( $category->id ); } } private function Step12a_PrepareGalleryImages( Entry $entry ): void { foreach ( $this->request->input('gallery', [] ) ?? [] as $i => $imagePath ) { $entry->gallery()->create([ 'image' => $imagePath, 'order' => $i ]); } } /** * @param Entry $entry * * @return void */ private function Step12b_MoveMainImage( Entry $entry ): void { $mainImage = $entry->main_image; if( !$mainImage ) return; $newPath = 'entries/main-images/' . basename($mainImage); if( !Storage::disk('public')->move($mainImage, $newPath) ) return; $entry->update(['main_image' => $newPath]); } private function Step12c_SaveGalleryImages( Entry $entry ): void { foreach ( $entry->gallery ?? [] as $galleryItem ) { $newPath = 'entries/gallery-images/' . $entry->id . '/' . basename($galleryItem->image); if( !Storage::disk('public')->move($galleryItem->image, $newPath) ) continue; $galleryItem->update(['image' => $newPath]); } } public function editEntry(Request $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; if( \Auth::user()->can('moderate', $entry) ){ $user_id = $this->request->input('owner_user_id'); $oldUserId = $this->entry->user_id; } else { $user_id = \Auth::user()->user_id; $oldUserId = null; } $oldMainImage = $entry->main_image; $galleryPaths = []; $entry = DB::transaction( function() use ( $user_id, &$galleryPaths ){ // STEP 2: Create game if different. $gameId = null; $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, 'platform_id' => $this->request->input('platform_only_id'), '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, 'level_id' => $this->request->input('level'), ]; if( \Auth::user()->can('moderate', $this->entry) ){ $fields['staff_comment'] = $this->request->input('staff_comment'); $fields['featured'] = $this->request->input('featured') ?? false; if( $fields['featured'] == true && $this->entry->featured_at === null ) $fields['featured_at'] = now(); if( $fields['featured'] == false ) $fields['featured_at'] = null; $fields['comments_thread_id'] = $this->request->input('comments_thread_id'); } $this->entry->update( $fields ); // STEP 6: Update entry files. $this->eStep6_UpdateEntryFiles( $this->entry->id ); // STEP 7: Update hashes. if( section_must_be( ['translations', 'romhacks' ], $this->section ) ) $this->eStep7_UpdateHashes( $this->entry->id ); // STEP 8: Update Authors. $this->eStep8_UpdateAuthors(); // STEP 9: Update romhacks modifications. if( section_must_be( ['romhacks', 'lua-scripts'], $this->section ) ) { $this->eStep9_UpdateRomhacksModifications(); } if( section_must_be( 'utilities', $this->section ) ) { $this->eStep9_UpdateUtilitiesSystems(); } // STEP 10: Update Languages. $this->eStep10_UpdateLanguages(); // STEP 10.5 : Update categories if( section_must_be( 'utilities', $this->section ) ) $this->eStep10_5_UpdateCategories(); // STEP 11: Prepare new gallery images and prepare deletion of others ones. $galleryPaths = $this->eStep11a_UpdateGalleryImages(); return $this->entry; }); // STEP 11 : Update main image if needed. $this->eStep11b_UpdateMainImage( $oldMainImage ); // STEP 11 : Update gallery storage. $this->eStep11c_UpdateGalleryImages( $galleryPaths ); // STEP 12: Refresh XF count. if( $entry->state !== 'draft' ) { if ($oldUserId) XenForoHelpers::updateEntriesCount($oldUserId); XenForoHelpers::updateEntriesCount($entry->user_id); } // STEP 13: Try to create comments area if it doesn't exist. $this->Step13_CreateCommentsThread( $this->entry ); return $entry; } /** * @throws SubmissionException */ private function eStep2_VerifyCreateAndEditGameId(): ?int { $mode = $this->request->input('game_selection_mode', 'game'); if ($mode !== 'game') { return null; } // 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; } } // In draft. if( !$this->request->input('new-game-title') && !$this->request->input('new-game-platform') && !$this->request->input('new-game-genre') ) 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', []) ?? []; $requestStates = $this->request->input('files_state', []) ?? []; $existingUuids = EntryFile::where( 'entry_id', $entryId )->pluck('file_uuid')->toArray(); $needDeletion = array_diff( $existingUuids, $requestUuids ); if( !empty( $needDeletion ) ){ $userId = \Auth::user()->user_id; EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->whereNot('state', 'archived')->get()->each( function ( $f ) use ( $userId ) { DeleteFile::dispatch( $f->filepath, $f->filename, $userId); }); EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->whereNot('state', 'archived')->delete(); } $needAddition = array_diff( $requestUuids, $existingUuids ); if( !empty( $needAddition ) ){ $this->Step7_SaveEntryFiles( $this->entry, $needAddition ); // Same code. } $metadataArray = $this->request->input('files_metadata', []); $stateMap = array_combine( $requestUuids, $requestStates ); foreach( $stateMap as $uuid => $state ){ if( section_must_be( ['romhacks', 'translations'], $this->entry->type ) ) { $onlinePatcher = (bool)($metadataArray[$uuid]['online_patcher'] ?? false); $secondaryOnlinePatcher = (bool)($metadataArray[$uuid]['secondary_online_patcher'] ?? false); } else { $onlinePatcher = false; $secondaryOnlinePatcher = false; } $entryFile = EntryFile::where('file_uuid', $uuid)->where('entry_id', $entryId)->where('state', '!=', 'archived')->first(); if( !$entryFile ) continue; $entryFile->update([ 'state' => $state, 'online_patcher' => $onlinePatcher, 'secondary_online_patcher' => $secondaryOnlinePatcher, ]); if( section_must_be( ['romhacks', 'translations', 'homebrew'], $this->entry->type ) ) { $playOnline = (bool)($metadataArray[$uuid]['play_online'] ?? false); $playOnlineCore = $metadataArray[$uuid]['play_online_core'] ?? null; $playOnlineThreads = (bool)($metadataArray[$uuid]['play_online_threads'] ?? false); if ($playOnline) { if ($playOnlineCore === null || !in_array($playOnlineCore, PlayOnlineHelpers::getCoreLists())) $playOnlineCore = $this->entry->getRealPlatform()->play_online_core ? $this->entry->getRealPlatform()->play_online_core : 'nes'; $entryFile->playOnlineSetting()->updateOrCreate( ['file_id' => $entryFile->id], [ 'core' => $playOnlineCore, 'threads' => $playOnlineThreads, ] ); } else { $entryFile->playOnlineSetting()->delete(); } } } } 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 eStep9_UpdateUtilitiesSystems(): void { $requestSystems = $this->request->input('systems', [] ) ?? []; if( !empty( $requestSystems ) ){ $valid = System::whereIn( 'id', $requestSystems )->pluck('id')->toArray(); if( count( $valid ) !== count( $requestSystems ) ){ throw new SubmissionException( "One of the systems doesn't exist." ); } } $this->entry->systems()->sync( $requestSystems ); } /** * @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 ); } /** * @return void * @throws SubmissionException */ private function eStep10_5_UpdateCategories(): void { $requestCategories = $this->request->input('categories', [] ) ?? []; if( !empty( $requestCategories ) ){ $valid = Category::whereIn( 'id', $requestCategories )->pluck('id')->toArray(); if( count( $valid ) !== count( $requestCategories ) ){ throw new SubmissionException( "One of the categories doesn't exist." ); } } $this->entry->categories()->sync( $requestCategories ); } 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 ) ){ $this->entry->gallery()->whereIn('image', $needDeletion )->delete(); } $needAddition = array_diff( $requestGallery, $existingGalleryPaths ); $images = []; foreach( $needAddition as $imagePath ){ $images[] = $this->entry->gallery()->create([ 'image' => $imagePath, ]); } foreach ( $requestGallery as $i => $imagePath ){ $this->entry->gallery()->where('image', $imagePath )->update(['order' => $i]); } return [ 'addition' => $images, 'deletion' => $needDeletion ]; } private function eStep11b_UpdateMainImage( ?string $oldMainImagePath ): void { $currentMainImagePath = $this->entry->main_image; if( $currentMainImagePath === $oldMainImagePath ) return; if( !$currentMainImagePath ) { if( $oldMainImagePath && Storage::disk('public')->exists($oldMainImagePath) ) Storage::disk('public')->delete($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->state !== 'published' ) return; if( !$entry->comments_thread_id ) CreateXenForoCommentsThread::dispatch( $entry ); // app(XenforoApiService::class)->createCommentsThread( $entry ); } }