Initial commit
This commit is contained in:
388
app/Services/SubmissionsService.php
Normal file
388
app/Services/SubmissionsService.php
Normal file
@@ -0,0 +1,388 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Exceptions\SubmissionException;
|
||||
use App\Helpers\EntryHelpers;
|
||||
use App\Http\Requests\StoreEntryRequest;
|
||||
use App\Models\Author;
|
||||
use App\Models\Entry;
|
||||
use App\Models\EntryFile;
|
||||
use App\Models\EntryGallery;
|
||||
use App\Models\EntryHash;
|
||||
use App\Models\Game;
|
||||
use App\Models\Genre;
|
||||
use App\Models\Language;
|
||||
use App\Models\Modification;
|
||||
use App\Models\Platform;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* @phpstan-import-type FSFileData from \App\Types\FSTypes
|
||||
*/
|
||||
class SubmissionsService {
|
||||
|
||||
/**
|
||||
* Request for store/edit.
|
||||
* @var StoreEntryRequest|null
|
||||
*/
|
||||
private ?StoreEntryRequest $request = null;
|
||||
|
||||
/**
|
||||
* Section for store/edit.
|
||||
* @var string|null
|
||||
*/
|
||||
private ?string $section = null;
|
||||
|
||||
/**
|
||||
* @return list<FSFileData>
|
||||
*/
|
||||
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 [];
|
||||
|
||||
return array_map(
|
||||
function( string $uuid ) {
|
||||
$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
|
||||
];
|
||||
|
||||
$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
|
||||
];
|
||||
|
||||
return null;
|
||||
},
|
||||
$files );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StoreEntryRequest $request
|
||||
* @param string $section
|
||||
*
|
||||
* @return Entry
|
||||
* @throws SubmissionException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function storeEntry( StoreEntryRequest $request, string $section ){
|
||||
|
||||
// STEP 1 : Prepare basic fields.
|
||||
|
||||
$this->request = $request;
|
||||
$this->section = $section;
|
||||
$user_id = 0; // TODO: Replace that.
|
||||
|
||||
$entry = DB::transaction(function () use ( $user_id ) {
|
||||
|
||||
// STEP 2 : Create game.
|
||||
|
||||
$gameId = null;
|
||||
if( section_must_be( ['romhacks', 'translations'], $this->section ) ){
|
||||
$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,
|
||||
'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,
|
||||
];
|
||||
|
||||
$entry = Entry::create( $fields );
|
||||
|
||||
// STEP 7 : Save entry fields.
|
||||
$this->Step7_SaveEntryFiles( $entry->id );
|
||||
|
||||
// STEP 8 : Save hashes.
|
||||
$this->Step8_SaveHashes( $entry->id );
|
||||
|
||||
// STEP 9 : Save Authors.
|
||||
$this->Step9_SaveAuthors( $entry );
|
||||
|
||||
// STEP 10 : Save Modifications.
|
||||
if( section_must_be( 'romhacks', $this->section ) ){
|
||||
$this->Step10_SaveRomhacksModifications( $entry );
|
||||
}
|
||||
|
||||
// STEP 11 : Save Languages
|
||||
$this->Step11_SaveLanguages( $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 );
|
||||
|
||||
return $entry;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*
|
||||
* @throws SubmissionException
|
||||
*/
|
||||
private function Step2_CreateAndReturnGameId(): int {
|
||||
|
||||
// Already existing game.
|
||||
if( $this->request->input('game_id') )
|
||||
return $this->request->input('game_id');
|
||||
|
||||
// Need to create a 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 );
|
||||
|
||||
$game = Game::create([
|
||||
'name' => trim( $this->request->input('new-game-title') ),
|
||||
'slug' => $gameSlug,
|
||||
'platform_id' => $platform->id,
|
||||
'genre_id' => $genre->id,
|
||||
]);
|
||||
|
||||
return $game->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'] = Game::find( $gameId )->name;
|
||||
}
|
||||
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 ) ) {
|
||||
// TODO: Add single platform ID compatibility.
|
||||
$fields['platform_name'] = Game::find( $gameId )->platform->name;
|
||||
}
|
||||
|
||||
return EntryHelpers::buildCompleteTitle( $this->section, $fields );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $entryId
|
||||
*
|
||||
* @return void
|
||||
* @throws SubmissionException
|
||||
*/
|
||||
private function Step7_SaveEntryFiles( int $entryId ): void
|
||||
{
|
||||
foreach ( $this->request->input('files_uuid', [] ) as $uuid ) {
|
||||
$fileData = Cache::pull("uploaded_file_{$uuid}");
|
||||
if( !$fileData )
|
||||
throw new SubmissionException( "File {$uuid} has expired. Please delete all your files and retry." );
|
||||
|
||||
EntryFile::create([
|
||||
'entry_id' => $entryId,
|
||||
'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'
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
{
|
||||
// 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
|
||||
{
|
||||
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 Step11_SaveLanguages( Entry $entry ): void
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function Step12a_PrepareGalleryImages( Entry $entry ): void
|
||||
{
|
||||
foreach ( $this->request->input('gallery', [] ) as $imagePath ) {
|
||||
EntryGallery::create([
|
||||
'entry_id' => $entry->id,
|
||||
'image' => $imagePath,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entry $entry
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function Step12b_MoveMainImage( Entry $entry ): void {
|
||||
$mainImage = $entry->main_image;
|
||||
$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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user