| @copyright 2007-2026 (c) AVE.cms
| @link https://ave-cms.ru
| @version 3.3
*/
namespace App\Adminx\PublicSite;
defined('BASEPATH') || die('Direct access to this location is not allowed.');
use App\Adminx\Support\CodeEditor;
use App\Common\AdminAssets;
use App\Common\AuditLog;
use App\Common\Auth;
use App\Common\Controller as BaseController;
use App\Common\Permission;
use App\Content\Presentation\PresentationAssignmentRepository;
use App\Content\Presentation\PresentationDataRegistry;
use App\Content\Presentation\PresentationPreview;
use App\Content\Presentation\PresentationRepository;
use App\Content\Presentation\PresentationRevisionRepository;
use App\Content\Presentation\PresentationSyntax;
use App\Helpers\Request;
class PresentationsController extends BaseController
{
public function index(array $params = array())
{
if (!Permission::check('view_public_site')) {
return $this->renderStatus('@adminx/404.twig', array('title' => 'Недостаточно прав'), 403);
}
AdminAssets::addStyle($this->base() . '/modules/PublicSite/assets/presentations.css', 51);
AdminAssets::addScript($this->base() . '/modules/PublicSite/assets/presentations.js', 51);
CodeEditor::useCodeMirror('htmlmixed');
CodeEditor::useCodeMirror('text/css');
$query = Request::getStr('q', '');
$kind = Request::getStr('kind', '');
$state = Request::getStr('state', '');
return $this->render('@public_site/presentations.twig', array(
'available' => PresentationRepository::available(),
'presentations' => PresentationRepository::all($query, $kind, $state),
'stats' => PresentationRepository::stats(),
'kinds' => PresentationRepository::kinds(),
'filters' => array('q' => $query, 'kind' => $kind, 'state' => $state),
'data_groups' => PresentationDataRegistry::groups(true),
'documents' => PresentationModel::documents(),
'legacy_sources' => PresentationModel::legacySources(),
'assignment_targets' => PresentationModel::assignmentTargets(),
'can_manage' => Permission::check('manage_public_presentations'),
'defaults' => $this->defaults(),
));
}
public function show(array $params = array())
{
if (!Permission::check('view_public_site')) { return $this->error('Недостаточно прав', array(), 403); }
$item = PresentationRepository::one(isset($params['id']) ? (int) $params['id'] : 0);
if (!$item) { return $this->error('Представление не найдено', array(), 404); }
$item['assignments'] = PresentationModel::assignments($item['id']);
return $this->success('', array('data' => $item));
}
public function store(array $params = array())
{
return $this->persist(0);
}
public function update(array $params = array())
{
return $this->persist(isset($params['id']) ? (int) $params['id'] : 0);
}
public function lint(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
$result = PresentationSyntax::checkMany($this->markup(Request::postAll()));
return $result['ok']
? $this->success($result['message'], array('data' => $result))
: $this->error($result['message'], array(), 422);
}
public function preview(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
try {
$result = PresentationPreview::render(Request::postInt('preview_document_id', 0), Request::postAll());
$css = Request::postStr('draft_css', '');
$html = '
'
. ''
. ''
. ($css !== '' ? '' : '')
. '' . $result['markup'] . '';
} catch (\Throwable $e) {
return $this->error($e->getMessage(), array(), 422);
}
return $this->success('Предпросмотр обновлён', array('data' => array(
'html' => $html,
'json' => $result['json'],
'document' => array(
'id' => isset($result['data']['item']['id']) ? (int) $result['data']['item']['id'] : 0,
'title' => isset($result['data']['item']['title']) ? (string) $result['data']['item']['title'] : '',
),
)));
}
public function diagnose(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
try {
$result = PresentationModel::diagnose(
isset($params['id']) ? (int) $params['id'] : 0,
Request::postAll()
);
} catch (\Throwable $e) {
return $this->error($e->getMessage(), array(), 422);
}
$warnings = isset($result['summary']['warning']) ? (int) $result['summary']['warning'] : 0;
return $this->success(
$result['ready'] ? ($warnings ? 'Ошибок нет, есть предупреждения' : 'Представление готово') : 'Найдены ошибки',
array('data' => $result)
);
}
public function publish(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
$id = isset($params['id']) ? (int) $params['id'] : 0;
try { $item = PresentationRepository::publish($id, Auth::id()); }
catch (\Throwable $e) { return $this->error($e->getMessage(), array(), 422); }
$this->audit('public_site.presentation_published', $id, array('version' => $item['version']));
return $this->success('Представление опубликовано', array('data' => $item));
}
public function copy(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
try { $id = PresentationRepository::copy(isset($params['id']) ? (int) $params['id'] : 0, Auth::id()); }
catch (\Throwable $e) { return $this->error($e->getMessage(), array(), 422); }
$this->audit('public_site.presentation_copied', $id, array());
return $this->success('Копия создана', array('data' => array('id' => $id)));
}
public function delete(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
$id = isset($params['id']) ? (int) $params['id'] : 0;
try { $deleted = PresentationRepository::delete($id); }
catch (\Throwable $e) { return $this->error($e->getMessage(), array(), 422); }
if (!$deleted) { return $this->error('Представление не найдено', array(), 404); }
$this->audit('public_site.presentation_deleted', $id, array());
return $this->success('Представление удалено');
}
public function revisions(array $params = array())
{
if (!Permission::check('view_public_site')) { return $this->error('Недостаточно прав', array(), 403); }
$id = isset($params['id']) ? (int) $params['id'] : 0;
if (!PresentationRepository::one($id)) { return $this->error('Представление не найдено', array(), 404); }
return $this->success('', array('data' => array('revisions' => PresentationRevisionRepository::all($id))));
}
public function revision(array $params = array())
{
if (!Permission::check('view_public_site')) { return $this->error('Недостаточно прав', array(), 403); }
$item = PresentationRevisionRepository::one(isset($params['revision']) ? (int) $params['revision'] : 0);
return $item ? $this->success('', array('data' => $item)) : $this->error('Ревизия не найдена', array(), 404);
}
public function restoreRevision(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
try { $id = PresentationRevisionRepository::restore(isset($params['revision']) ? (int) $params['revision'] : 0, Auth::id()); }
catch (\Throwable $e) { return $this->error($e->getMessage(), array(), 422); }
$this->audit('public_site.presentation_revision_restored', $id, array());
return $this->success('Ревизия восстановлена в черновик', array('data' => array('id' => $id)));
}
public function deleteRevision(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
$id = PresentationRevisionRepository::delete(isset($params['revision']) ? (int) $params['revision'] : 0);
return $id ? $this->success('Ревизия удалена') : $this->error('Ревизия не найдена', array(), 404);
}
public function deleteRevisions(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
$id = isset($params['id']) ? (int) $params['id'] : 0;
if (!PresentationRepository::one($id)) { return $this->error('Представление не найдено', array(), 404); }
return $this->success('Ревизии удалены', array('data' => array(
'count' => PresentationRevisionRepository::deleteAll($id),
)));
}
public function saveAssignment(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
$presentationId = isset($params['id']) ? (int) $params['id'] : 0;
try {
$input = PresentationModel::validateAssignment(Request::postAll());
$id = PresentationAssignmentRepository::save($presentationId, $input, Auth::id());
} catch (\Throwable $e) {
return $this->error($e->getMessage(), array(), 422);
}
$this->audit('public_site.presentation_assignment_saved', $presentationId, array('assignment_id' => $id));
return $this->success('Назначение сохранено', array('data' => array(
'assignments' => PresentationModel::assignments($presentationId),
)));
}
public function deleteAssignment(array $params = array())
{
if (($error = $this->guard()) !== null) { return $error; }
PresentationAssignmentRepository::delete(isset($params['assignment']) ? (int) $params['assignment'] : 0);
return $this->success('Назначение удалено');
}
protected function persist($id)
{
if (($error = $this->guard()) !== null) { return $error; }
try { $savedId = PresentationRepository::save((int) $id, Request::postAll(), Auth::id()); }
catch (\Throwable $e) { return $this->error($e->getMessage(), array(), 422); }
$this->audit($id > 0 ? 'public_site.presentation_updated' : 'public_site.presentation_created', $savedId, array());
return $this->success($id > 0 ? 'Черновик сохранён' : 'Представление создано', array(
'data' => array('id' => $savedId),
));
}
protected function guard()
{
return $this->guardPermission('manage_public_presentations');
}
protected function markup(array $input)
{
return array(
'Элемент' => isset($input['draft_item_markup']) ? (string) $input['draft_item_markup'] : '',
'Обёртка' => isset($input['draft_wrapper_markup']) ? (string) $input['draft_wrapper_markup'] : '',
'Пустой результат' => isset($input['draft_empty_markup']) ? (string) $input['draft_empty_markup'] : '',
);
}
protected function defaults()
{
return array(
'item' => '' . "\n"
. ' ' . "\n"
. ' {% if item.excerpt %}{{ item.excerpt }}
{% endif %}' . "\n"
. '',
'wrapper' => '' . "\n" . ' {{ content|raw }}' . "\n" . '
',
'empty' => 'Материалы не найдены.
',
);
}
protected function audit($action, $targetId, array $meta)
{
$user = Auth::user();
AuditLog::record($action, array(
'actor_id' => Auth::id(),
'actor_name' => $user && isset($user['name']) ? (string) $user['name'] : '',
'target_type' => 'presentation',
'target_id' => (int) $targetId,
'meta' => $meta,
));
}
}