Files
my-projects-website/app/application/app/Services/Site/DocumentationService.php

152 lines
6.3 KiB
PHP

<?php declare(strict_types=1);
namespace App\Services\Site;
use App\Dto\Service\Site\Documentation;
use App\Enums\CacheTag;
use App\Enums\DocumentationVersionStatus;
use App\Models\DocumentationCategory;
use App\Models\Documentation as ModelDocumentation;
use App\Models\DocumentationVersion;
use App\Models\Project;
use App\Models\User;
use App\Repositories\DocumentationCategoryRepository;
use App\Repositories\DocumentationRepository;
use App\ServiceResults\ServiceResultArray;
use App\ServiceResults\ServiceResultError;
use App\ServiceResults\Site\DocumentationService\DefaultVersion;
use app\ServiceResults\Site\PagePossibleWithoutTranslation;
use App\Services\Service;
use App\Dto\Builder\DocumentationCategory as DocumentationCategoryBuilderDto;
use App\Dto\Builder\Documentation as DocumentationBuilderDto;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Collection;
final class DocumentationService extends Service
{
public function __construct(
private readonly DocumentationCategoryRepository $documentationCategoryRepository,
private readonly DocumentationRepository $documentationRepository
) { }
public function defaultVersion(Project $project, ?User $user): ServiceResultError | DefaultVersion
{
$seconds = 3600;
$isPublic = null;
if ($user?->cannot('viewAny', DocumentationVersion::class)) {
$isPublic = 1;
}
$version = CacheTag::DocumantationVersion->getCache()
->remember(self::class . $project->id . '_' . $isPublic ?? 0, $seconds, function () use ($project, $isPublic) {
$versions = $project->documentationVersions()
->when($isPublic, function (Builder $query) {
$query->where('is_public', 1);
})
->limit(10)
->get();
return $versions->firstWhere('status', DocumentationVersionStatus::CurrentVersion)
??
$versions->first() ?? false;
});
if ($version === false) {
return $this->errNotFound(__('Not Found'));
}
return new DefaultVersion($version);
}
public function index(Documentation $documentation): ServiceResultError | ServiceResultArray
{
return $this->result(array_merge($documentation->toArray(), [
'categories' => $this->getCategories($documentation, null),
'documentations' => $this->getDocumentations($documentation, null),
]));
}
public function category(string $slug, Documentation $documentation): ServiceResultError | PagePossibleWithoutTranslation
{
$category = $this->documentationCategoryRepository->getCategoryBySlugWithContent($slug, $documentation->getVersion()->id, $documentation->getWebsiteTranslations()->getLanguage());
if (!$category) {
return $this->errNotFound(__('Not Found'));
}
if (
$category->is_public === false &&
($documentation->getUser() === null || $documentation->getUser()->cannot('view', $category))
) {
return $this->errFobidden(__('Access is denied'));
}
$data = array_merge($documentation->toArray(), [
'category' => $category,
'categories' => $this->getCategories($documentation, $category->id),
'documentations' => $this->getDocumentations($documentation, $category->id),
]);
return $this->resultSitePage($documentation->getProject(), $documentation->getWebsiteTranslations(), $data, \is_null($category->content?->title));
}
public function view(string $slug, Documentation $documentation): ServiceResultError | PagePossibleWithoutTranslation
{
$document = $this->documentationRepository->getDocumentationBySlugWithContent($slug, $documentation->getVersion()->id, $documentation->getWebsiteTranslations()->getLanguage());
if (!$document) {
return $this->errNotFound(__('Not Found'));
}
if (
$document->is_public === false &&
($documentation->getUser() === null || $documentation->getUser()->cannot('view', $document))
) {
return $this->errFobidden(__('Access is denied'));
}
$data = array_merge($documentation->toArray(), [
'documentation' => $document,
]);
return $this->resultSitePage($documentation->getProject(), $documentation->getWebsiteTranslations(), $data, \is_null($document->content?->title));
}
private function getCategories(Documentation $documentation, ?int $parentId): Collection
{
$isPublic = null;
if ($documentation->getUser() === null || $documentation->getUser()->cannot('viewAny', DocumentationCategory::class)) {
$isPublic = true;
}
$builderDto = new DocumentationCategoryBuilderDto(
isPublic: $isPublic,
parentId: new DocumentationCategoryBuilderDto\Category($parentId),
);
$with = [
'content' => function (HasOne $hasOne) use ($documentation) {
$hasOne->where('language_id', $documentation->getWebsiteTranslations()->getLanguage()->id);
}
];
return $this->documentationCategoryRepository->getCategories(
$documentation->getVersion()->id,
$builderDto,
$with
)->all();
}
private function getDocumentations(Documentation $documentation, ?int $categoryId): Collection
{
$isPublic = null;
if ($documentation->getUser() === null || $documentation->getUser()->cannot('viewAny', ModelDocumentation::class)) {
$isPublic = true;
}
$builderDto = new DocumentationBuilderDto(
isPublic: $isPublic,
categoryId: new DocumentationCategoryBuilderDto\Category($categoryId),
);
$with = [
'content' => function (HasOne $hasOne) use ($documentation) {
$hasOne->where('language_id', $documentation->getWebsiteTranslations()->getLanguage()->id);
}
];
return $this->documentationRepository->getDocumentations(
$documentation->getVersion()->id,
$builderDto,
$with
)->all();
}
}