ldc-op-insta/app/Http/Controllers/Bo/TopMediaController.php
2023-04-21 14:49:53 +00:00

156 lines
4.7 KiB
PHP

<?php
namespace App\Http\Controllers\Bo;
use App\Enums\ExcludeTypeEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Ajax\ExcludeTopMediaRequest;
use App\Jobs\InstaGetTopMediasJob;
use App\Lib\Instagram\Objects\TopMedia;
use App\Models\InstaMedia;
use App\Models\InstaMediaExclusion;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class TopMediaController extends Controller
{
/**
* Show paginated Top Media List
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\View\View
*/
public function index(Request $request): View
{
/** @var \Illuminate\Database\Eloquent\Builder $topMediaList */
$topMediaList = InstaMedia::query();
$ranking = $this->getRanking();
if ($request->search) {
$this->searchQuery(
$topMediaList,
$request->search,
null,
'insta_id',
'username',
'permalink'
);
} //end if
$this->sortQuery($topMediaList);
$searchFields = trans('Id Instagram, Participant, Lien');
$topMediaList->orderBy('updated_at', 'DESC');
$topMediaList = $topMediaList->paginate();
return \view('bo.pages.top-media.index', \compact('topMediaList', 'searchFields', 'ranking'));
}
/**
* Show the refresh vue component
*
* @return \Illuminate\View\View
*/
public function refresh(): View
{
return \view('bo.pages.top-media.refresh');
}
// * Ajax Methods.
/**
* Fetch Insta media list from api
*
* @param boolean $refresh
* @return \Illuminate\Http\JsonResponse
*/
public function fetch(bool $refresh = false): JsonResponse
{
$responseData = [
'ready' => false
];
if (
Cache::get('top_media_job_fetch_dispatched') or
Cache::get('top_media_job_fetch_running')
) {
return response()->json($responseData);
}
if (empty(Cache::get('top_media_ajax_fetch')) or $refresh) {
\dispatch(new InstaGetTopMediasJob())->onConnection('database');
Cache::put('top_media_job_fetch_dispatched', true);
return response()->json($responseData);
}
$responseData['ready'] = true;
$responseData['data'] = Cache::get('top_media_ajax_fetch');
return \response()->json($responseData);
}
/**
* Fetch Media Picture Object
*
* @param string $ig_media_hash
* @return \Illuminate\Http\JsonResponse
*/
public function fetchPicture(string $ig_media_hash): JsonResponse
{
return \response()->json(Cache::remember(
"media_picture_ajax_fetch{$ig_media_hash}",
// * 3H cache
3 * 60 * 60,
fn () => InstaMedia::fetchInstagramMediaPictures($ig_media_hash)
));
}
/**
* Save the new list
*
* @return \Illuminate\Http\RedirectResponse
*/
public function save(): JsonResponse
{
return DB::transaction(function () {
/** @var \Illuminate\Support\Collection<\App\Lib\Instagram\Objects\TopMedia> */
$igMediaList = Cache::get('top_media_ajax_fetch');
// * 'Truncate' our list to preserve only the desired media amount.
// Dont use truncate here because it implies a commit.
InstaMedia::query()->delete();
$igMediaList->map(function (TopMedia $ig_media) {
(new InstaMedia((array)$ig_media))->saveOrFail();
});
\session()->flash('success', trans('Le classement à bien été mis à jour'));
return \response()->json();
});
}
/**
* Exclude a top Media or a username
*
* @param \App\Http\Requests\Bo\Ajax\ExcludeTopMediaRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function exclude(ExcludeTopMediaRequest $request): JsonResponse
{
$excludeData = [
'type' => $request->insta_id ? ExcludeTypeEnum::post : ExcludeTypeEnum::user,
'value' => $request->insta_id ?: $request->username
];
InstaMediaExclusion::query()->firstOrCreate($excludeData, $excludeData)->saveOrFail();
return \response()->json($excludeData);
}
/**
* Get Actual ranking
*
* @return \Illuminate\Support\Collection<App\Models\InstaMedia>
*/
private function getRanking(): Collection
{
return InstaMedia::query()->orderBy('id')->pluck('insta_id')->flip();
}
}