171 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			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);
 | 
						|
    }
 | 
						|
}
 |