171 lines
6.4 KiB
PHP

<?php declare(strict_types=1);
namespace App\Services\Admin\Project;
use App\Contracts\ServiceResultError;
use App\Dto\Service\Admin\Project\About\StoreUpdate;
use App\Enums\Morph;
use App\Jobs\Translate\ProcessProjectContent;
use App\Models\ProjectContent;
use App\Models\User;
use App\Repositories\ProjectContentRepository;
use App\Repositories\ProjectLanguageRepository;
use App\Repositories\ProjectRepository;
use App\ServiceResults\ServiceResultArray;
use App\ServiceResults\StoreUpdateResult;
use App\Services\ProjectContent\ProjectContentCommandHandler;
use App\Services\Service;
use App\Services\Storage\StorageService;
use Illuminate\Support\Facades\DB;
final class AboutService extends Service
{
public function __construct(
private readonly ProjectRepository $projectRepository,
private readonly ProjectLanguageRepository $projectLanguageRepository,
private readonly ProjectContentRepository $projectContentRepository,
private readonly ProjectContentCommandHandler $projectContentCommandHandler,
private readonly StorageService $storageService,
) { }
public function languages(int $projectId, User $user): ServiceResultError | ServiceResultArray
{
$project = $this->projectRepository->getProjectById($projectId);
if (is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('viewAny', ProjectContent::class)) {
return $this->errFobidden(__('Access is denied'));
}
return $this->result([
'project' => $project,
]);
}
public function edit(int $projectId, int $languageId, User $user): ServiceResultError | ServiceResultArray
{
$project = $this->projectRepository->getProjectById($projectId);
$language = $project?->languages()->firstWhere('id', $languageId);
if (\is_null($project) || \is_null($language)) {
return $this->errNotFound(__('Not Found'));
}
$content = $project->contents()->firstWhere('language_id', $languageId);
if (\is_null($content)) {
if ($user->cannot('create', ProjectContent::class)) {
return $this->errFobidden(__('Access is denied'));
}
$content = new ProjectContent();
$content->project_id = $project->id;
$content->language_id = $language->id;
} else if($user->cannot('update', $content)) {
return $this->errFobidden(__('Access is denied'));
}
return $this->result([
'project' => $project,
'language' => $language,
'content' => $content,
'serviceTranslationEnable' => config('translation_service.enable', false),
]);
}
public function storeOrUpdate(int $projectId, int $languageId, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
if (! $this->projectLanguageRepository->isExistsLanguageById($projectId, $languageId)) {
return $this->errNotFound(__('Not Found'));
}
$content = $this->projectContentRepository->getContentByLanguageId($projectId, $languageId);
if (is_null($content)) {
return $this->store($projectId, $languageId, $data, $user);
}
return $this->update($content, $data, $user);
}
private function store(int $projectId, int $languageId, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
if ($user->cannot('create', ProjectContent::class)) {
return $this->errFobidden(__('Access is denied'));
}
$storages = $this->storageService->getStoragesAndValidate($data->getStorages(), Morph::ProjectContent);
if (!$storages->isSuccess()) {
return $storages;
}
try {
$aboutProject = DB::transaction(function () use ($data, $projectId, $languageId, $storages) {
$dataAboutProject = $this->getDataAboutProject($data);
$aboutProject = $this->projectContentCommandHandler->handleStore($projectId, $languageId, $dataAboutProject);
$this->storageService->saveAndDelete($aboutProject, $storages);
return $aboutProject;
});
if (\config('translation_service.enable', false)) {
$this->translateContent($aboutProject, $data);
}
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->resultStoreUpdateModel($aboutProject, __('Project information has been successfully updated'));
}
private function update(ProjectContent $content, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
if ($user->cannot('update', $content)) {
return $this->errFobidden(__('Access is denied'));
}
$storages = $this->storageService->getStoragesAndValidate($data->getStorages(), Morph::ProjectContent);
if (!$storages->isSuccess()) {
return $storages;
}
try {
$aboutProject = DB::transaction(function () use ($data, $content, $storages) {
$dataAboutProject = $this->getDataAboutProject($data);
$aboutProject = $this->projectContentCommandHandler->handleUpdate($content, $dataAboutProject);
$this->storageService->saveAndDelete($aboutProject, $storages);
return $aboutProject;
});
if (\config('translation_service.enable', false)) {
$this->translateContent($aboutProject, $data);
}
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->resultStoreUpdateModel($aboutProject, __('Project information has been successfully updated'));
}
private function getDataAboutProject(StoreUpdate $data): array
{
return [
'title' => $data->getTitle(),
'description' => $data->getDescription(),
];
}
private function translateContent(ProjectContent $projectContent, StoreUpdate $data): void
{
if (! $data->isTranslateAutomatically()) {
return;
}
$translateExceptLanguages = [$projectContent->language_id];
$translateContentIds = [$projectContent->id];
ProcessProjectContent::dispatch($projectContent->project_id, $translateContentIds, $translateExceptLanguages);
}
}