Files
ntspi-app/app/Containers/Dashboard/Actions/Pages/ImportPageAction.php
T
F4ilji d4ef7daeb1 feat(dashboard): add page export/import functionality
- ExportPageAction: exports page with SEO and section path as JSON
- ImportPageAction: imports page from JSON, resolves section by slug path
- PageController: export/download and import endpoints
- Routes: GET /{page}/export, POST /import
- Index.vue: export button per row, import button in header (local only)
- Import restricted to APP_ENV=local (backend + frontend check)
2026-08-03 10:21:14 +05:00

85 lines
2.6 KiB
PHP

<?php
namespace App\Containers\Dashboard\Actions\Pages;
use App\Containers\AppStructure\Models\MainSection;
use App\Containers\AppStructure\Models\Page;
use App\Containers\AppStructure\Models\SubSection;
use App\Containers\Dashboard\Tasks\Content\GenerateSearchDataTask;
class ImportPageAction
{
public function __construct(
private readonly GenerateSearchDataTask $generateSearchDataTask,
) {}
/**
* Импортирует страницу из JSON-структуры
*
* @param array $data Раскодированный JSON-массив экспорта
* @return Page Созданная страница
* @throws \InvalidArgumentException
*/
public function run(array $data): Page
{
if (empty($data['page']['title'])) {
throw new \InvalidArgumentException('Отсутствует обязательное поле "page.title"');
}
if (empty($data['page']['slug'])) {
throw new \InvalidArgumentException('Отсутствует обязательное поле "page.slug"');
}
$pageData = $data['page'];
// Resolve sub_section_id via slug path
$pageData['sub_section_id'] = $this->resolveSubSectionId($data['section_path'] ?? null);
// Generate search_data from content
if (!empty($pageData['content'])) {
$pageData['search_data'] = $this->generateSearchDataTask->run($pageData['content']);
}
// Remove fields that should not be set during import
unset($pageData['icon']);
$page = Page::create($pageData);
// Attach SEO if present
if (!empty($data['seo'])) {
$page->seo()->create([
'title' => $data['seo']['title'] ?? null,
'description' => $data['seo']['description'] ?? null,
]);
}
return $page;
}
private function resolveSubSectionId(?array $sectionPath): ?int
{
if (empty($sectionPath)) {
return null;
}
$mainSectionSlug = $sectionPath['main_section_slug'] ?? null;
$subSectionSlug = $sectionPath['sub_section_slug'] ?? null;
if (!$mainSectionSlug || !$subSectionSlug) {
return null;
}
$mainSection = MainSection::where('slug', $mainSectionSlug)->first();
if (!$mainSection) {
return null;
}
$subSection = SubSection::where('main_section_id', $mainSection->id)
->where('slug', $subSectionSlug)
->first();
return $subSection?->id;
}
}