A lot of things
This commit is contained in:
223
app/Services/ActivityService.php
Normal file
223
app/Services/ActivityService.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Entry;
|
||||
use App\Models\News;
|
||||
use App\View\Components\EntryCard;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ActivityService
|
||||
{
|
||||
private const CACHE_ENTRIES = 300; // seconds.
|
||||
private const CACHE_NEWS = 300; // seconds.
|
||||
private const CACHE_MESSAGES = 300; // seconds.
|
||||
private const CACHE_THREADS = 300; // seconds.
|
||||
private const CACHE_CLUBS = 300; // seconds.
|
||||
private const ITEMS_PER_TYPE = 15;
|
||||
|
||||
public function getActivities( array $activities = [ 'entries', 'news', 'messages', 'threads', 'clubs' ] ): Collection
|
||||
{
|
||||
$c = collect();
|
||||
if( in_array( 'entries', $activities ) ) {
|
||||
$c = $c->merge($this->getEntries());
|
||||
}
|
||||
if( in_array( 'news', $activities ) ) {
|
||||
$c = $c->merge($this->getNews());
|
||||
}
|
||||
if( in_array( 'messages', $activities ) ) {
|
||||
$c = $c->merge($this->getMessages());
|
||||
}
|
||||
if( in_array( 'threads', $activities ) ) {
|
||||
$c = $c->merge($this->getThreads());
|
||||
}
|
||||
if( in_array( 'clubs', $activities ) ) {
|
||||
$c = $c->merge($this->getClubs());
|
||||
}
|
||||
|
||||
return $c->sortByDesc('date')
|
||||
->values()
|
||||
->take(30)
|
||||
->map(function(array $item){
|
||||
$obj = (object) $item;
|
||||
$obj->date = Carbon::createFromTimestamp($obj->date);
|
||||
return $obj;
|
||||
});
|
||||
}
|
||||
|
||||
private function formatEntry( Entry $entry ): array
|
||||
{
|
||||
return [
|
||||
'type' => 'entry',
|
||||
'title' => $entry->complete_title ?? $entry->title,
|
||||
'url' => route('entries.show', ['section' => $entry->type, 'entry' => $entry]),
|
||||
'image' => $entry->main_image ? \Storage::url($entry->main_image) : null,
|
||||
'date' => $entry->created_at->timestamp,
|
||||
'author' => $entry->authors->pluck('name')->implode(', '),
|
||||
'user_id' => $entry->user_id,
|
||||
'badge' => EntryCard::ENTRY_TYPES_BADGE[$entry->type],
|
||||
'badge_class' => $entry->type,
|
||||
'excerpt' => $entry->description ? \Str::limit(strip_tags($entry->description), 80) : null,
|
||||
'meta' => $entry->getRealPlatform()?->name
|
||||
];
|
||||
}
|
||||
|
||||
private function formatNews( News $news ): array
|
||||
{
|
||||
return [
|
||||
'type' => 'news',
|
||||
'title' => $news->title,
|
||||
'url' => route('news.show', ['news' => $news]),
|
||||
'image' => $news->gallery()->first() ? \Storage::url($news->gallery()->first()->image) : null,
|
||||
'date' => $news->created_at->timestamp,
|
||||
'author' => null,
|
||||
'user_id' => $news->user_id,
|
||||
'badge' => 'News',
|
||||
'badge_class' => 'news',
|
||||
'excerpt' => $news->description ? \Str::limit(strip_tags($news->description), 80) : null,
|
||||
'meta' => $news->category?->name
|
||||
];
|
||||
}
|
||||
|
||||
private function formatMessage( object $message ): array
|
||||
{
|
||||
return [
|
||||
'type' => 'message',
|
||||
'title' => $message->title,
|
||||
'url' => xfRoute('threads/.' ) . $message->thread_id . '/post-' . $message->post_id,
|
||||
'image' => null,
|
||||
'date' => $message->post_date,
|
||||
'author' => null,
|
||||
'user_id' => $message->user_id,
|
||||
'badge' => 'Post',
|
||||
'badge_class' => 'message',
|
||||
'excerpt' => $message->message ? \Str::limit(strip_tags($message->message), 80) : null,
|
||||
'meta' => null
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
private function formatThread( object $thread ): array
|
||||
{
|
||||
return [
|
||||
'type' => 'thread',
|
||||
'title' => $thread->title,
|
||||
'url' => xfRoute('threads/.' ) . $thread->thread_id,
|
||||
'image' => null,
|
||||
'date' => $thread->post_date,
|
||||
'author' => null,
|
||||
'user_id' => $thread->user_id,
|
||||
'badge' => 'Thread',
|
||||
'badge_class' => 'thread',
|
||||
'excerpt' => $thread->message ? \Str::limit(strip_tags($thread->message), 80) : null,
|
||||
'meta' => null
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
private function formatClub( object $club ): array
|
||||
{
|
||||
return [
|
||||
'type' => 'club',
|
||||
'title' => $club->title,
|
||||
'url' => xfRoute('forums/.' ) . $club->node_id,
|
||||
'image' => null, // TODO: Remplacer par banner_date
|
||||
'date' => $club->club_creation_date,
|
||||
'author' => null,
|
||||
'user_id' => $club->user_id,
|
||||
'badge' => 'Club',
|
||||
'badge_class' => 'club',
|
||||
'excerpt' => $club->description ? \Str::limit(strip_tags($club->description), 80) : null,
|
||||
'meta' => null
|
||||
];
|
||||
}
|
||||
|
||||
private function getEntries(): array
|
||||
{
|
||||
return Cache::remember('activity_entries', self::CACHE_ENTRIES, function() {
|
||||
return Entry::published()
|
||||
->with(['authors', 'game.platform'])
|
||||
->latest('created_at')
|
||||
->limit(self::ITEMS_PER_TYPE)
|
||||
->get()
|
||||
->map($this->formatEntry(...))
|
||||
->toArray();
|
||||
});
|
||||
}
|
||||
|
||||
private function getNews(): array
|
||||
{
|
||||
return Cache::remember('activity_news', self::CACHE_NEWS, function() {
|
||||
return News::published()
|
||||
->with('gallery')
|
||||
->latest('created_at')
|
||||
->limit(self::ITEMS_PER_TYPE)
|
||||
->get()
|
||||
->map($this->formatNews(...))
|
||||
->toArray();
|
||||
});
|
||||
}
|
||||
|
||||
private function getMessages(): array
|
||||
{
|
||||
return Cache::remember('activity_messages', self::CACHE_MESSAGES, function() {
|
||||
return DB::connection('xenforo')
|
||||
->table('post')
|
||||
->join('user', 'post.user_id', '=', 'user.user_id')
|
||||
->join('thread', 'post.thread_id', '=', 'thread.thread_id')
|
||||
->where('post.message_state', 'visible')
|
||||
->where('thread.first_post_id', '!=', 'post.post_id')
|
||||
->orderByDesc('post.post_date')
|
||||
->limit(self::ITEMS_PER_TYPE)
|
||||
->select([
|
||||
'thread.title', 'thread.thread_id', 'post.post_id', 'post.post_date',
|
||||
'post.user_id', 'post.message'
|
||||
])
|
||||
->get()
|
||||
->map($this->formatMessage(...))
|
||||
->toArray();
|
||||
});
|
||||
}
|
||||
|
||||
private function getThreads(): array
|
||||
{
|
||||
return Cache::remember('activity_threads', self::CACHE_THREADS, function() {
|
||||
return DB::connection('xenforo')
|
||||
->table('thread')
|
||||
->join('user', 'thread.user_id', '=', 'user.user_id')
|
||||
->join('post', 'thread.first_post_id', '=', 'post.post_id')
|
||||
->where('thread.discussion_state', 'visible')
|
||||
->where('thread.discussion_type', '!=', 'redirect' )
|
||||
->orderByDesc('thread.post_date')
|
||||
->limit(self::ITEMS_PER_TYPE)
|
||||
->select([
|
||||
'thread.title', 'thread.thread_id', 'thread.post_date', 'thread.user_id',
|
||||
'post.message'
|
||||
])
|
||||
->get()
|
||||
->map($this->formatThread(...))
|
||||
->toArray();
|
||||
});
|
||||
}
|
||||
|
||||
private function getClubs(): array
|
||||
{
|
||||
return Cache::remember('activity_clubs', self::CACHE_CLUBS, function() {
|
||||
return DB::connection('xenforo')
|
||||
->table('club')
|
||||
->where('club_state', 'visible')
|
||||
->orderByDesc('club_creation_date')
|
||||
->limit(self::ITEMS_PER_TYPE)
|
||||
->select([
|
||||
'club.title', 'club.description', 'club.node_id',
|
||||
'club.club_creation_date', 'club.user_id'
|
||||
])
|
||||
->get()
|
||||
->map($this->formatClub(...))
|
||||
->toArray();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\EntryFile;
|
||||
use App\Models\LogXfUser;
|
||||
use Illuminate\Http\Client\ConnectionException;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@@ -110,7 +111,6 @@ class FileServersService {
|
||||
'filename' => $filename,
|
||||
'current_chunk' => $currentChunk,
|
||||
'total_chunks' => $totalChunks,
|
||||
// TODO : Must replace User ID
|
||||
'zeus' => $this->generateZeusToken( \Auth::user()->user_id, $server['base_url'], "Uploadchunk" ),
|
||||
]);
|
||||
|
||||
@@ -129,4 +129,43 @@ class FileServersService {
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function deleteFile(
|
||||
string $filePath,
|
||||
string $fileName,
|
||||
int $userId
|
||||
): bool {
|
||||
|
||||
foreach( $this->servers as $serverKey => $server ){
|
||||
|
||||
$response = Http::withHeaders([])
|
||||
->post( $server['delete_file'], [
|
||||
'filepath' => $filePath,
|
||||
'filename' => $fileName,
|
||||
'zeus' => $this->generateZeusToken( $userId, $server['base_url'], "Deletefile" ),
|
||||
]);
|
||||
|
||||
if (!$response->successful()) {
|
||||
throw new \RuntimeException( $response->body() );
|
||||
}
|
||||
|
||||
$data = $response->json();
|
||||
if( isset( $data['status'] ) && $data['status'] === 'deleted' ){
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
activity('entry-file')
|
||||
->causedBy(LogXfUser::find($userId))
|
||||
->withProperties([
|
||||
'filepath' => $filePath,
|
||||
'filename' => $fileName,
|
||||
])
|
||||
->event('file_deletion')
|
||||
->log('File deleted');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
194
app/Services/NewsService.php
Normal file
194
app/Services/NewsService.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Helpers\EntryHelpers;
|
||||
use App\Jobs\CreateXenForoCommentsThread;
|
||||
use App\Models\Entry;
|
||||
use App\Models\News;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class NewsService
|
||||
{
|
||||
/**
|
||||
* Request for store/edit.
|
||||
* @var Request|null
|
||||
*/
|
||||
private ?Request $request = null;
|
||||
|
||||
/**
|
||||
* Entry for edit.
|
||||
* @var News|null
|
||||
*/
|
||||
private ?News $news = null;
|
||||
|
||||
|
||||
public function storeNews(Request $request): News
|
||||
{
|
||||
$this->request = $request;
|
||||
$user_id = \Auth::user()->user_id;
|
||||
|
||||
$news = DB::transaction(function () use ($user_id) {
|
||||
|
||||
// STEP 1 : Slug
|
||||
$slug = EntryHelpers::uniqueSlug( $this->request->input('title'), News::class );
|
||||
|
||||
$fields = [
|
||||
'title' => $this->request->input('title'),
|
||||
'slug' => $slug,
|
||||
'category_id' => $this->request->input('category'),
|
||||
'description' => $this->request->input('description'),
|
||||
'state' => $this->request->input('submit-state'),
|
||||
'entry_id' => $this->request->input('entry_id'),
|
||||
'relevant_link' => $this->request->input('release_site'),
|
||||
'youtube_link' => $this->request->input('youtube_link'),
|
||||
'user_id' => $user_id,
|
||||
];
|
||||
|
||||
$news = News::create( $fields );
|
||||
|
||||
// STEP 3 : Prepare Gallery images.
|
||||
$this->Step3a_PrepareGalleryImages( $news );
|
||||
|
||||
return $news;
|
||||
|
||||
});
|
||||
|
||||
$this->Step3b_SaveGalleryImages( $news );
|
||||
|
||||
$this->Step4_CreateCommentsThread( $news );
|
||||
|
||||
return $news;
|
||||
}
|
||||
|
||||
private function Step3a_PrepareGalleryImages(News $news): void
|
||||
{
|
||||
foreach( $this->request->input('gallery', [] ) ?? [] as $i => $imagePath ){
|
||||
$news->gallery()->create([
|
||||
'image' => $imagePath,
|
||||
'order' => $i
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function Step3b_SaveGalleryImages(News $news): void
|
||||
{
|
||||
foreach ( $news->gallery ?? [] as $galleryItem ) {
|
||||
$newPath = 'news/gallery-images/' . $news->id . '/' . basename($galleryItem->image);
|
||||
|
||||
if( !Storage::disk('public')->move($galleryItem->image, $newPath) )
|
||||
continue;
|
||||
|
||||
$galleryItem->update(['image' => $newPath]);
|
||||
}
|
||||
}
|
||||
|
||||
private function Step4_CreateCommentsThread( News $news ): void
|
||||
{
|
||||
if( $news->state !== 'published' )
|
||||
return;
|
||||
|
||||
if( !$news->comments_thread_id )
|
||||
CreateXenForoCommentsThread::dispatch( $news );
|
||||
}
|
||||
|
||||
public function editNews(Request $request, News $news): News
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->news = $news;
|
||||
|
||||
if( \Auth::user()->can('moderate', $news) ){
|
||||
$user_id = $this->request->input('owner_user_id');
|
||||
} else {
|
||||
$user_id = \Auth::user()->user_id;
|
||||
}
|
||||
|
||||
$galleryPaths = [];
|
||||
|
||||
$news = DB::transaction(function () use ($user_id, &$galleryPaths) {
|
||||
|
||||
// STEP 1 : Refresh slug.
|
||||
if( $this->request->input('title') !== $this->news->title ){
|
||||
$this->news->slug = EntryHelpers::uniqueSlug( $this->request->input('title'), News::class, $this->news->id );
|
||||
}
|
||||
|
||||
$fields = [
|
||||
'title' => $this->request->input('title'),
|
||||
'slug' => $this->news->slug,
|
||||
'category_id' => $this->request->input('category'),
|
||||
'description' => $this->request->input('description'),
|
||||
'state' => $this->request->input('submit-state'),
|
||||
'entry_id' => $this->request->input('entry_id'),
|
||||
'relevant_link' => $this->request->input('release_site'),
|
||||
'youtube_link' => $this->request->input('youtube_link'),
|
||||
'user_id' => $user_id,
|
||||
];
|
||||
|
||||
if( \Auth::user()->can('moderate', $this->news) ){
|
||||
$fields['staff_comment'] = $this->request->input('staff_comment');
|
||||
$fields['comments_thread_id'] = $this->request->input('comments_thread_id');
|
||||
}
|
||||
|
||||
$this->news->update( $fields );
|
||||
|
||||
$galleryPaths = $this->eStep3a_UpdateGalleryImages();
|
||||
|
||||
return $this->news;
|
||||
|
||||
});
|
||||
|
||||
$this->eStep3b_UpdateGalleryImages( $galleryPaths );
|
||||
|
||||
$this->step4_CreateCommentsThread( $news );
|
||||
|
||||
return $news;
|
||||
|
||||
}
|
||||
|
||||
private function eStep3a_UpdateGalleryImages(): array
|
||||
{
|
||||
$requestGallery = $this->request->input('gallery', [] ) ?? [];
|
||||
$existingGalleryPaths = $this->news->gallery->pluck('image')->toArray();
|
||||
|
||||
$needDeletion = array_diff( $existingGalleryPaths, $requestGallery );
|
||||
|
||||
if( !empty( $needDeletion ) ){
|
||||
$this->news->gallery()->whereIn('image', $needDeletion )->delete();
|
||||
}
|
||||
|
||||
$needAddition = array_diff( $requestGallery, $existingGalleryPaths );
|
||||
$images = [];
|
||||
foreach( $needAddition as $imagePath ){
|
||||
$images[] = $this->news->gallery()->create([
|
||||
'image' => $imagePath,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach( $requestGallery as $i => $imagePath ){
|
||||
$this->news->gallery()->where('image', $imagePath )->update(['order' => $i]);
|
||||
}
|
||||
|
||||
return [ 'addition' => $images, 'deletion' => $needDeletion ];
|
||||
}
|
||||
|
||||
private function eStep3b_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 = 'news/gallery-images/' . $this->news->id . '/' . basename( $galleryItem->image );
|
||||
|
||||
if( !Storage::disk('public')->move( $galleryItem->image, $newPath ) ){
|
||||
continue;
|
||||
}
|
||||
|
||||
$galleryItem->update(['image' => $newPath]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,11 @@ namespace App\Services;
|
||||
|
||||
use App\Exceptions\SubmissionException;
|
||||
use App\Helpers\EntryHelpers;
|
||||
use App\Helpers\PlayOnlineHelpers;
|
||||
use App\Helpers\XenForoHelpers;
|
||||
use App\Http\Requests\StoreEntryRequest;
|
||||
use App\Jobs\CreateXenForoCommentsThread;
|
||||
use App\Jobs\DeleteFile;
|
||||
use App\Models\Author;
|
||||
use App\Models\Category;
|
||||
use App\Models\Entry;
|
||||
@@ -76,8 +78,12 @@ class SubmissionsService {
|
||||
'error' => null,
|
||||
'uuid' => $uuid,
|
||||
'state' => $file->state,
|
||||
'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}");
|
||||
@@ -92,8 +98,12 @@ class SubmissionsService {
|
||||
'error' => null,
|
||||
'uuid' => $uuid,
|
||||
'state' => $file['state'],
|
||||
'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;
|
||||
@@ -298,15 +308,20 @@ class SubmissionsService {
|
||||
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 your new files and retry." );
|
||||
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." );
|
||||
|
||||
$onlinePatcher = (bool)($metadataArray[$uuid]['online_patcher'] ?? false);
|
||||
if( !$onlinePatcher )
|
||||
$onlinePatcher = EntryHelpers::enableOnlinePatcherBasedOnExtension( $fileData['filename'] );
|
||||
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);
|
||||
$secondaryOnlinePatcher = (bool)($metadataArray[$uuid]['secondary_online_patcher'] ?? false);
|
||||
} else {
|
||||
$onlinePatcher = false;
|
||||
$secondaryOnlinePatcher = false;
|
||||
}
|
||||
|
||||
EntryFile::create([
|
||||
$file = EntryFile::create([
|
||||
'entry_id' => $entry->id,
|
||||
'file_uuid' => $uuid,
|
||||
'filename' => $fileData['filename'],
|
||||
@@ -319,6 +334,26 @@ class SubmissionsService {
|
||||
'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,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,9 +487,10 @@ class SubmissionsService {
|
||||
|
||||
private function Step12a_PrepareGalleryImages( Entry $entry ): void
|
||||
{
|
||||
foreach ( $this->request->input('gallery', [] ) ?? [] as $imagePath ) {
|
||||
foreach ( $this->request->input('gallery', [] ) ?? [] as $i => $imagePath ) {
|
||||
$entry->gallery()->create([
|
||||
'image' => $imagePath,
|
||||
'order' => $i
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -556,6 +592,10 @@ class SubmissionsService {
|
||||
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');
|
||||
}
|
||||
|
||||
@@ -666,6 +706,10 @@ class SubmissionsService {
|
||||
|
||||
$needDeletion = array_diff( $existingUuids, $requestUuids );
|
||||
if( !empty( $needDeletion ) ){
|
||||
$userId = \Auth::user()->user_id;
|
||||
EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->get()->each( function ( $f ) use ( $userId ) {
|
||||
DeleteFile::dispatch( $f->filepath, $f->filename, $userId);
|
||||
});
|
||||
EntryFile::where('entry_id', $entryId)->whereIn('file_uuid', $needDeletion)->delete();
|
||||
}
|
||||
|
||||
@@ -680,15 +724,45 @@ class SubmissionsService {
|
||||
|
||||
foreach( $stateMap as $uuid => $state ){
|
||||
|
||||
$onlinePatcher = (bool)($metadataArray[$uuid]['online_patcher'] ?? false);
|
||||
$secondaryOnlinePatcher = (bool)($metadataArray[$uuid]['secondary_online_patcher'] ?? false);
|
||||
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::where('file_uuid', $uuid)->where('entry_id', $entryId)->where('state', '!=', 'archived')
|
||||
->update([
|
||||
'state' => $state,
|
||||
'online_patcher' => $onlinePatcher,
|
||||
'secondary_online_patcher' => $secondaryOnlinePatcher,
|
||||
]);
|
||||
$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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,6 +934,10 @@ class SubmissionsService {
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ( $requestGallery as $i => $imagePath ){
|
||||
$this->entry->gallery()->where('image', $imagePath )->update(['order' => $i]);
|
||||
}
|
||||
|
||||
return [ 'addition' => $images, 'deletion' => $needDeletion ];
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ class XenforoApiService {
|
||||
return $response['success'] ?? false;
|
||||
}
|
||||
|
||||
public function createCommentsThread( Entry $entry ): bool
|
||||
public function createCommentsThread( Entry|News $entry ): bool
|
||||
{
|
||||
if( !$entry->comments_thread_id || $entry->comments_thread_id <= 0 ){
|
||||
$data = [
|
||||
@@ -134,6 +134,14 @@ class XenforoApiService {
|
||||
return $response['success'] ?? false;
|
||||
}
|
||||
|
||||
public function featuredRequest( Entry $entry ): bool
|
||||
{
|
||||
$response = $this->post("romhackplaza_entry/featured", data: [
|
||||
'entry_id' => $entry->id, 'user_id' => $entry->user_id, 'entry_title' => $entry->complete_title ?? $entry->title,
|
||||
]);
|
||||
return $response['success'] ?? false;
|
||||
}
|
||||
|
||||
public function deleteThreadWithEntry(int $threadId): bool
|
||||
{
|
||||
return (bool) $this->delete( "threads/{$threadId}", data: ['reason' => "Deletion with entry." ] );
|
||||
|
||||
@@ -195,9 +195,9 @@ class XenforoService {
|
||||
|
||||
}
|
||||
|
||||
private function hashCSRFToken( string $token ): string
|
||||
private function hashCSRFToken( string $token, int $timestamp ): string
|
||||
{
|
||||
return hash_hmac('md5', $token . time(), config('app.xf_salt') );
|
||||
return hash_hmac('md5', $token . $timestamp, config('app.xf_salt') );
|
||||
}
|
||||
public function getCSRFToken(): string
|
||||
{
|
||||
@@ -207,6 +207,28 @@ class XenforoService {
|
||||
Cookie::queue('xf_csrf', $token, 0, '/', config('session.domain'), 0, false, false );
|
||||
}
|
||||
|
||||
return time() . ',' . $this->hashCSRFToken($token);
|
||||
$timestamp = time();
|
||||
return $timestamp . ',' . $this->hashCSRFToken($token, $timestamp);
|
||||
}
|
||||
public function verifyCSRFToken( string $requestToken ): bool
|
||||
{
|
||||
$token = Cookie::get('xf_csrf');
|
||||
if( !$token ){
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
[$timestamp, $hash] = explode(',', $requestToken);
|
||||
} catch (\Throwable $th) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$timestamp = intval($timestamp);
|
||||
$currentTimestamp = time();
|
||||
|
||||
if( abs( $currentTimestamp - $timestamp ) > 3600 )
|
||||
return false;
|
||||
|
||||
return $hash === $this->hashCSRFToken($token, $timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user