changes
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\Page;
|
||||
use App\Containers\AppStructure\Models\SubSection;
|
||||
|
||||
class AttachPageToSubSectionAction
|
||||
{
|
||||
public function run(Page $page, SubSection $subSection): Page
|
||||
{
|
||||
// Pessimistic lock to prevent race conditions
|
||||
$page = Page::lockForUpdate()->findOrFail($page->id);
|
||||
|
||||
if ($page->sub_section_id !== null) {
|
||||
throw new \InvalidArgumentException('Страница уже принадлежит другому подразделу');
|
||||
}
|
||||
|
||||
$page->section()->associate($subSection);
|
||||
$page->save();
|
||||
|
||||
return $page;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\Page;
|
||||
use App\Containers\Dashboard\Tasks\Content\GenerateSearchDataTask;
|
||||
|
||||
class CreatePageAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly GeneratePagePathAction $generatePagePathAction,
|
||||
private readonly GenerateSearchDataTask $generateSearchDataTask,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Создает новую страницу
|
||||
*
|
||||
* @param array $data Валидированные данные формы (title, slug, sub_section_id, code, searchable, icon, content, settings)
|
||||
* @return Page Созданная страница
|
||||
*/
|
||||
public function run(array $data): Page
|
||||
{
|
||||
$subSectionId = $data['sub_section_id'] ?? null;
|
||||
|
||||
// Генерируем path на основе subSection
|
||||
$data['path'] = $this->generatePagePathAction->run($data['slug'], $subSectionId);
|
||||
|
||||
// Генерируем search_data из контента
|
||||
if (!empty($data['content'])) {
|
||||
$data['search_data'] = $this->generateSearchDataTask->run($data['content']);
|
||||
}
|
||||
|
||||
// Удаляем sub_section_id — он не является полем модели Page
|
||||
unset($data['sub_section_id']);
|
||||
|
||||
return Page::create($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\Page;
|
||||
|
||||
class DeletePageAction
|
||||
{
|
||||
/**
|
||||
* Удаляет страницу
|
||||
*
|
||||
* @param Page $page Страница для удаления
|
||||
* @return bool Результат удаления
|
||||
*/
|
||||
public function run(Page $page): bool
|
||||
{
|
||||
return $page->delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\Page;
|
||||
|
||||
class DetachPageFromSubSectionAction
|
||||
{
|
||||
public function run(Page $page): Page
|
||||
{
|
||||
$page->section()->dissociate();
|
||||
$page->save();
|
||||
|
||||
return $page;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\SubSection;
|
||||
|
||||
class GeneratePagePathAction
|
||||
{
|
||||
public function run(string $slug, ?int $subSectionId = null): string
|
||||
{
|
||||
if ($subSectionId === null) {
|
||||
return $slug;
|
||||
}
|
||||
|
||||
$subSection = SubSection::with('mainSection')->find($subSectionId);
|
||||
|
||||
if ($subSection === null) {
|
||||
return $slug;
|
||||
}
|
||||
|
||||
if ($subSection->mainSection === null) {
|
||||
return $subSection->slug . '/' . $slug;
|
||||
}
|
||||
|
||||
return $subSection->mainSection->slug . '/' . $subSection->slug . '/' . $slug;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\Page;
|
||||
use App\Containers\AppStructure\Models\SubSection;
|
||||
|
||||
class ListPagesAction
|
||||
{
|
||||
public function run(array $filters): array
|
||||
{
|
||||
$query = Page::query()->with(['section.mainSection']);
|
||||
|
||||
// Search
|
||||
if (!empty($filters['search'])) {
|
||||
$query->where(function ($q) use ($filters) {
|
||||
$q->where('title', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('path', 'like', '%' . $filters['search'] . '%');
|
||||
});
|
||||
}
|
||||
|
||||
// Tab filter
|
||||
if (!empty($filters['tab'])) {
|
||||
if ($filters['tab'] === 'is_registered') {
|
||||
$query->where('is_registered', true)->where('is_url', false);
|
||||
} elseif ($filters['tab'] === 'is_url') {
|
||||
$query->where('is_url', true);
|
||||
} else {
|
||||
$query->where('is_registered', false)->where('is_url', false);
|
||||
}
|
||||
} else {
|
||||
// Default: show created pages
|
||||
$query->where('is_registered', false)->where('is_url', false);
|
||||
}
|
||||
|
||||
// SubSection filter
|
||||
if (!empty($filters['sub_section_id'])) {
|
||||
$query->where('sub_section_id', $filters['sub_section_id']);
|
||||
}
|
||||
|
||||
$pages = $query->orderBy('created_at', 'desc')->paginate(15);
|
||||
|
||||
$subSections = SubSection::with('mainSection')
|
||||
->whereNotNull('title')
|
||||
->orderBy('title')
|
||||
->get();
|
||||
|
||||
return [
|
||||
'pages' => $pages,
|
||||
'subSections' => $subSections,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Containers\Dashboard\Actions\Pages;
|
||||
|
||||
use App\Containers\AppStructure\Models\Page;
|
||||
use App\Containers\Dashboard\Tasks\Content\GenerateSearchDataTask;
|
||||
|
||||
class UpdatePageAction
|
||||
{
|
||||
public function __construct(
|
||||
private readonly GeneratePagePathAction $generatePagePathAction,
|
||||
private readonly GenerateSearchDataTask $generateSearchDataTask,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Обновляет страницу
|
||||
*
|
||||
* @param Page $page Страница для обновления
|
||||
* @param array $data Валидированные данные формы
|
||||
* @return Page Обновленная страница
|
||||
*/
|
||||
public function run(Page $page, array $data): Page
|
||||
{
|
||||
// Если контент изменился, перегенерируем search_data
|
||||
if (isset($data['content']) && json_encode($data['content']) !== json_encode($page->content)) {
|
||||
$data['search_data'] = $this->generateSearchDataTask->run($data['content']);
|
||||
}
|
||||
|
||||
// Если страница не зарегистрирована, перегенерируем path
|
||||
if ($page->is_registered == false) {
|
||||
$subSectionId = $data['sub_section_id'] ?? $page->sub_section_id;
|
||||
$slug = $data['slug'] ?? $page->slug;
|
||||
|
||||
$data['path'] = $this->generatePagePathAction->run($slug, $subSectionId);
|
||||
}
|
||||
|
||||
// Удаляем sub_section_id — он не является полем модели Page
|
||||
unset($data['sub_section_id']);
|
||||
|
||||
$page->update($data);
|
||||
|
||||
return $page->fresh();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user