<?php declare(strict_types=1); /* * This file is part of modal bundle for Contao. * * (c) Benjamin Roth * * @license LGPL-3.0-or-later */ namespace vonRotenberg\ModalBundle\EventListener\DataContainer; use Contao\Backend; use Contao\BackendUser; use Contao\CoreBundle\Exception\AccessDeniedException; use Contao\CoreBundle\ServiceAnnotation\Callback; use Contao\DataContainer; use Contao\Image; use Contao\Input; use Contao\StringUtil; use Contao\System; use Doctrine\DBAL\Connection; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Bundle\SecurityBundle\Security; use vonRotenberg\ModalBundle\Security\ModalPermissions; class ModalDataContainerListener { private Security $security; private SessionInterface $session; private RequestStack $requestStack; public function __construct(Security $security, RequestStack $requestStack) { $this->security = $security; $this->requestStack = $requestStack; $this->session = $this->requestStack->getSession(); } /** * @Callback(table="tl_vr_modal", target="config.onload") */ public function checkPermission(DataContainer $dc = null): void { $user = $this->security->getUser(); $userId = $user instanceof BackendUser ? (int)$user->id : 0; $objSession = System::getContainer()->get('session'); $session = $objSession->all(); if ($user->isAdmin) { return; } // Set root IDs if (empty($user->modals) || !is_array($user->modals)) { $root = array(0); } else { $root = $user->modals; } if (is_array($session['CURRENT']['IDS'] ?? null)) { $edit_all = array(); $delete_all = array(); foreach ($session['CURRENT']['IDS'] as $id) { if ($this->security->isGranted(ModalPermissions::USER_CAN_EDIT_MODALS, $id)) { $edit_all[] = $id; } if ($this->security->isGranted(ModalPermissions::USER_CAN_DELETE_MODALS, $id)) { $delete_all[] = $id; } } $session['CURRENT']['IDS'] = (Input::get('act') == 'deleteAll') ? $delete_all : $edit_all; } // Set allowed clipboard IDs if (!empty($session['CLIPBOARD']['tl_vr_modal']['id']) && is_array($session['CLIPBOARD']['tl_vr_modal']['id'])) { $clipboard = array(); foreach ($session['CLIPBOARD']['tl_vr_modal']['id'] as $id) { if ($this->security->isGranted(ModalPermissions::USER_CAN_EDIT_MODALS, $id)) { $clipboard[] = $id; } } $session['CLIPBOARD']['tl_article']['id'] = $clipboard; } // Overwrite the session $objSession->replace($session); // Check permissions to add modals if (!$this->security->isGranted(ModalPermissions::USER_CAN_CREATE_MODALS)) { $GLOBALS['TL_DCA']['tl_vr_modal']['config']['closed'] = true; $GLOBALS['TL_DCA']['tl_vr_modal']['config']['notCreatable'] = true; $GLOBALS['TL_DCA']['tl_vr_modal']['config']['notCopyable'] = true; } // Check permissions to delete modals if (!$this->security->isGranted(ModalPermissions::USER_CAN_DELETE_MODALS)) { $GLOBALS['TL_DCA']['tl_vr_modal']['config']['notDeletable'] = true; } // Check current action switch (Input::get('act')) { case 'select': // Allow break; case 'edit': case 'show': if (!in_array(Input::get('id'), $root)) { throw new AccessDeniedException('Not enough permissions to ' . Input::get('act') . ' form ID ' . Input::get('id') . '.'); } break; case 'editAll': case 'overrideAll': $session = $objSession->all(); $session['CURRENT']['IDS'] = array_intersect((array) $session['CURRENT']['IDS'], $root); $objSession->replace($session); break; case 'copy': case 'create': if (!$this->security->isGranted(ModalPermissions::USER_CAN_CREATE_MODALS)) { throw new AccessDeniedException('Not enough permissions to ' . Input::get('act') . ' modals.'); } break; case 'delete': if (!$this->security->isGranted(ModalPermissions::USER_CAN_DELETE_MODALS)) { throw new AccessDeniedException('Not enough permissions to ' . Input::get('act') . ' modal ID ' . Input::get('id') . '.'); } break; case 'deleteAll': case 'copyAll': $session = $this->session->all(); if (Input::get('act') == 'deleteAll' && !$this->security->isGranted(ModalPermissions::USER_CAN_DELETE_MODALS)) { $session['CURRENT']['IDS'] = array(); } else { if (Input::get('act') == 'copyAll' && !$this->security->isGranted(ModalPermissions::USER_CAN_CREATE_MODALS)) { $session['CURRENT']['IDS'] = array(); } } $this->session->replace($session); break; default: if (Input::get('act')) { throw new AccessDeniedException('Not enough permissions to ' . Input::get('act') . ' modals.'); } break; } } /** * @Callback(table="tl_vr_modal", target="config.oncreate") * @Callback(table="tl_vr_modal", target="config.oncopy") */ public function adjustPermissions($insertId) { $user = $this->security->getUser(); $userId = $user instanceof BackendUser ? (int)$user->id : 0; // The oncreate_callback passes $insertId as second argument if (func_num_args() == 4) { $insertId = func_get_arg(1); } if ($user->isAdmin) { return; } // Set root IDs if (empty($user->modals) || !is_array($user->modals)) { $root = array(0); } else { $root = $user->modals; } // The form is enabled already if (in_array($insertId, $root)) { return; } /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = System::getContainer()->get('session')->getBag('contao_backend'); $arrNew = $objSessionBag->get('new_records'); if (is_array($arrNew['tl_vr_modal']) && in_array($insertId, $arrNew['tl_vr_modal'])) { /** @var Connection $db */ $db = System::getContainer()->get('database_connection'); // Add the permissions on group level if ($user->inherit != 'custom') { $objGroup = $db->executeQuery("SELECT id, modals, modalp FROM tl_user_group WHERE id IN(" . implode(',', array_map('\intval', $user->groups)) . ")"); foreach ($objGroup->fetchAllAssociative() as $group) { $arrModalp = StringUtil::deserialize($group['modalp']); if (is_array($arrModalp) && in_array('create', $arrModalp)) { $arrModals = StringUtil::deserialize($group['modals'], true); $arrModals[] = $insertId; $db->prepare("UPDATE tl_user_group SET modals=? WHERE id=?") ->executeQuery([serialize($arrModals), $group['id']]); } } } // Add the permissions on user level if ($user->inherit != 'group') { $objUser = $db->prepare("SELECT modals, modalp FROM tl_user WHERE id=? LIMIT 1") ->executeQuery([$user->id]); $arrModalp = StringUtil::deserialize($objUser->fetchOne()); if (is_array($arrModalp) && in_array('create', $arrModalp)) { $arrModals = StringUtil::deserialize($objUser->modals, true); $arrModals[] = $insertId; $db->prepare("UPDATE tl_user SET modals=? WHERE id=?") ->executeQuery([serialize($arrModals), $user->id]); } } // Add the new element to the user object $root[] = $insertId; $user->forms = $root; } } /** * @Callback(table="tl_vr_modal", target="list.operations.copy.button") */ public function copyModal($row, $href, $label, $title, $icon, $attributes): string { return $this->security->isGranted(ModalPermissions::USER_CAN_CREATE_MODALS) ? '<a href="' . Backend::addToUrl($href . '&id=' . $row['id']) . '" title="' . StringUtil::specialchars($title) . '"' . $attributes . '>' . Image::getHtml($icon, $label) . '</a> ' : Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)) . ' '; } /** * @Callback(table="tl_vr_modal", target="list.operations.delete.button") */ public function deleteModal($row, $href, $label, $title, $icon, $attributes): string { return $this->security->isGranted(ModalPermissions::USER_CAN_DELETE_MODALS) ? '<a href="' . Backend::addToUrl($href . '&id=' . $row['id']) . '" title="' . StringUtil::specialchars($title) . '"' . $attributes . '>' . Image::getHtml($icon, $label) . '</a> ' : Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)) . ' '; } /** * @Callback(table="tl_vr_modal", target="list.operations.edit.button") */ public function editModal($row, $href, $label, $title, $icon, $attributes): string { return $this->security->isGranted(ModalPermissions::USER_CAN_EDIT_MODALS, $row['id']) ? '<a href="' . Backend::addToUrl($href . '&id=' . $row['id']) . '" title="' . StringUtil::specialchars($title) . '"' . $attributes . '>' . Image::getHtml($icon, $label) . '</a> ' : Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)) . ' '; } /** * @Callback(table="tl_vr_modal", target="list.operations.editheader.button") */ public function editHeaderModal($row, $href, $label, $title, $icon, $attributes): string { return $this->security->isGranted(ModalPermissions::USER_CAN_EDIT_MODALS, $row['id']) ? '<a href="' . Backend::addToUrl($href . '&id=' . $row['id']) . '" title="' . StringUtil::specialchars($title) . '"' . $attributes . '>' . Image::getHtml($icon, $label) . '</a> ' : Image::getHtml(preg_replace('/\.svg$/i', '_.svg', $icon)) . ' '; } }