152 lines
6.3 KiB
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();
|
|
}
|
|
}
|