Added the ability to add links to the project.

This commit is contained in:
2024-04-15 22:53:34 +05:00
parent 4583908230
commit 63ea5dac92
29 changed files with 756 additions and 13 deletions

View File

@@ -0,0 +1,203 @@
<?php declare(strict_types=1);
namespace App\Services\Admin\Project;
use App\Dto\Builder\ProjectLink as ProjectLinkBuilderDto;
use App\Dto\QuerySettingsDto;
use App\Dto\Service\Admin\Project\Link\StoreUpdate;
use App\Models\ProjectLink;
use App\Models\User;
use App\Repositories\ProjectLinkRepository;
use App\Repositories\ProjectRepository;
use App\Services\ProjectLink\ProjectLinkCommandHandler;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use App\ServiceResults\ServiceResultArray;
use App\ServiceResults\ServiceResultError;
use App\ServiceResults\ServiceResultSuccess;
use App\ServiceResults\StoreUpdateResult;
final class LinkService extends Service
{
public function __construct(
private readonly ProjectRepository $projectRepository,
private readonly ProjectLinkRepository $projectLinkRepository,
private readonly ProjectLinkCommandHandler $projectLinkCommandHandler,
) { }
public function index(int $projectId, ProjectLinkBuilderDto $linkBuilderDto, QuerySettingsDto $querySettingsDto, User $user): ServiceResultError | ServiceResultArray
{
$project = $this->projectRepository->getProjectById($projectId);
if (\is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('viewAny', ProjectLink::class)) {
return $this->errFobidden(__('Access is denied'));
}
$links = $this->projectLinkRepository->getLinksFromProject(
$project->id,
$linkBuilderDto,
$querySettingsDto->getQueryWith()
)->pagination(
$querySettingsDto->getLimit(),
$querySettingsDto->getPage()
);
return $this->result([
'links' => $links,
'project' => $project,
]);
}
public function create(int $projectId, User $user): ServiceResultError | ServiceResultArray
{
$project = $this->projectRepository->getProjectById($projectId);
if (\is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('create', ProjectLink::class)) {
return $this->errFobidden(__('Access is denied'));
}
return $this->result([
'link' => new ProjectLink(),
'project' => $project,
]);
}
public function edit(int $projectId, int $linkId, User $user): ServiceResultError | ServiceResultArray
{
$project = $this->projectRepository->getProjectById($projectId);
if (\is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
$link = $this->projectLinkRepository->getLinkById($linkId);
if (\is_null($link)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('view', $link)) {
return $this->errFobidden(__('Access is denied'));
}
return $this->result([
'link' => $link,
'project' => $project,
]);
}
public function store(int $projectId, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
if ($user->cannot('create', ProjectLink::class)) {
return $this->errFobidden(__('Access is denied'));
}
$project = $this->projectRepository->getProjectById($projectId);
if (\is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
if (
$data->getLanguageId() !== null
&& $project->languages()->where('id', $data->getLanguageId())->exists() === false
) {
return $this->errValidate(
__('validation.exists', ['attribute' => __('validation.attributes.language_id')]),
['language_id' => __('validation.exists', ['attribute' => __('validation.attributes.language_id')])]
);
}
try {
$link = DB::transaction(function () use ($data, $project, $user) {
$dataLink = $this->getDataLink($data);
return $this->projectLinkCommandHandler->handleStore($project, $dataLink);
});
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->resultStoreUpdateModel($link, __('The link was successfully created'));
}
public function update(int $projectId, int $linkId, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
{
$project = $this->projectRepository->getProjectById($projectId);
if (\is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
if (
$data->getLanguageId() !== null
&& $project->languages()->where('id', $data->getLanguageId())->exists() === false
) {
return $this->errValidate(
__('validation.exists', ['attribute' => __('validation.attributes.language_id')]),
['language_id' => __('validation.exists', ['attribute' => __('validation.attributes.language_id')])]
);
}
$link = $this->projectLinkRepository->getLinkById($linkId);
if (\is_null($link)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('update', $link)) {
return $this->errFobidden(__('Access is denied'));
}
try {
$link = DB::transaction(function () use ($data, $link) {
$dataLink = $this->getDataLink($data);
return $this->projectLinkCommandHandler->handleUpdate($link, $dataLink);
});
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->resultStoreUpdateModel($link, __('The link was successfully updated'));
}
public function destroy(int $projectId, int $linkId, User $user): ServiceResultError|ServiceResultSuccess
{
$project = $this->projectRepository->getProjectById($projectId);
if (\is_null($project)) {
return $this->errNotFound(__('Not Found'));
}
$link = $this->projectLinkRepository->getLinkById($linkId);
if (\is_null($link)) {
return $this->errNotFound(__('Not Found'));
}
if ($user->cannot('delete', $link)) {
return $this->errFobidden(__('Access is denied'));
}
try {
DB::transaction(function () use ($link) {
$this->projectLinkCommandHandler->handleDestroy($link);
});
} catch (\Throwable $e) {
report($e);
return $this->errService(__('Server Error'));
}
return $this->ok(__('The link has been deleted'));
}
private function getDataLink(StoreUpdate $data): array
{
return [
'title' => $data->getTitle(),
'link' => $data->getLink(),
'sort' => $data->getSort(),
'language_id' => $data->getLanguageId(),
];
}
}

View File

@@ -0,0 +1,15 @@
<?php declare(strict_types=1);
namespace App\Services\ProjectLink;
use App\Dto\Builder\ProjectLink as ProjectLinkBuilderDto;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
final readonly class BuilderCommand
{
public function execute(Relation | Builder $query, ProjectLinkBuilderDto $projectLinkBuilderDto): Relation | Builder
{
return $query;
}
}

View File

@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
namespace App\Services\ProjectLink;
use App\Models\Project;
use App\Models\ProjectLink;
final readonly class ProjectLinkCommandHandler
{
public function handleStore(Project $project, array $data): ProjectLink
{
return $project->links()->create($data);
}
public function handleUpdate(ProjectLink $link, array $data): ProjectLink
{
$link->update($data);
return $link;
}
public function handleDestroy(ProjectLink $link): void
{
$link->delete();
}
}