Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)
This commit is contained in:
@@ -9,112 +9,180 @@
|
||||
|
||||
namespace App\Twig;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use App\Entity\Bookmark;
|
||||
use App\Entity\User;
|
||||
use App\Repository\BookmarkRepository;
|
||||
use App\Utils\ProfileManager;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class DatatableExtensions extends AbstractExtension
|
||||
final class DatatableExtensions extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* @var RequestStack
|
||||
* @var array<string, array<string, array<string, string|bool>>>
|
||||
*/
|
||||
protected $requestStack;
|
||||
private array $dataTables = [];
|
||||
private array $tableNames = [];
|
||||
private ?string $prefix = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $cookies = [];
|
||||
|
||||
/**
|
||||
* @param RequestStack $requestStack
|
||||
*/
|
||||
public function __construct(RequestStack $requestStack)
|
||||
public function __construct(private BookmarkRepository $bookmarkRepository, private ProfileManager $profileManager)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('is_visible_column', [$this, 'isColumnVisible']),
|
||||
new TwigFunction('is_datatable_configured', [$this, 'isDatatableConfigured']),
|
||||
new TwigFunction('initialize_datatable', [$this, 'initializeDatatable']),
|
||||
new TwigFunction('datatable_column_class', [$this, 'getDatatableColumnClass']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dataTable
|
||||
* @return bool
|
||||
*/
|
||||
public function isDatatableConfigured(string $dataTable)
|
||||
private function getDatatableName(string $dataTable): string
|
||||
{
|
||||
$cookie = $this->getVisibilityCookieName($dataTable);
|
||||
if (!\array_key_exists($dataTable, $this->tableNames)) {
|
||||
$this->tableNames[$dataTable] = $this->profileManager->getDatatableName($dataTable, $this->prefix);
|
||||
}
|
||||
|
||||
return $this->requestStack->getCurrentRequest()->cookies->has($cookie);
|
||||
return $this->tableNames[$dataTable];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dataTable
|
||||
* @return string
|
||||
*/
|
||||
protected function getVisibilityCookieName(string $dataTable)
|
||||
public function initializeDatatable(User $user, Session $session, string $dataTable, array $defaultColumns): array
|
||||
{
|
||||
return $dataTable . '_visibility';
|
||||
}
|
||||
if ($this->prefix === null) {
|
||||
$this->prefix = $this->profileManager->getProfileFromSession($session);
|
||||
$dataTable = $this->getDatatableName($dataTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only for datatables, do not use it outside this context.
|
||||
*
|
||||
* @param string $dataTable
|
||||
* @param string $column
|
||||
* @param array $columns
|
||||
* @return bool
|
||||
*/
|
||||
public function isColumnVisible(string $dataTable, string $column, array $columns)
|
||||
{
|
||||
// name handling is spread between here and datatables.html.twig (data_table_column_modal)
|
||||
$cookie = $this->getVisibilityCookieName($dataTable);
|
||||
|
||||
if (!isset($this->cookies[$cookie])) {
|
||||
$visibility = false;
|
||||
if ($this->requestStack->getCurrentRequest()->cookies->has($cookie)) {
|
||||
$visibility = json_decode($this->requestStack->getCurrentRequest()->cookies->get($cookie), true);
|
||||
if (!\array_key_exists($dataTable, $this->dataTables)) {
|
||||
$columns = [];
|
||||
foreach ($defaultColumns as $key => $settings) {
|
||||
$columns[$key] = [
|
||||
'visible' => $this->checkInColumDefinition($defaultColumns, $key),
|
||||
'class' => \array_key_exists($key, $defaultColumns) ? $this->getClass($settings) : ''
|
||||
];
|
||||
// add an auto-generated class
|
||||
$columns[$key]['class'] = trim($columns[$key]['class'] . ' col_' . $key);
|
||||
}
|
||||
$this->cookies[$cookie] = $visibility;
|
||||
}
|
||||
$values = $this->cookies[$cookie];
|
||||
|
||||
if (empty($values) || !\is_array($values)) {
|
||||
return $this->checkInColumDefinition($columns, $column);
|
||||
$bookmark = $this->bookmarkRepository->findBookmark($user, Bookmark::COLUMN_VISIBILITY, $dataTable);
|
||||
if ($bookmark !== null) {
|
||||
$content = $bookmark->getContent();
|
||||
foreach ($content as $key => $value) {
|
||||
if (!\array_key_exists($key, $columns)) {
|
||||
// if a column does not exist any longer, it needs to be skipped, otherwise an error will
|
||||
// be raised while accessing the visible/class keys
|
||||
continue;
|
||||
}
|
||||
$columns[$key]['visible'] = (bool) $value;
|
||||
}
|
||||
|
||||
// disable all columns, which were not bookmarked as visible
|
||||
foreach (array_diff(array_keys($columns), array_keys($content)) as $key) {
|
||||
if (!str_contains($columns[$key]['class'], 'alwaysVisible')) {
|
||||
$columns[$key]['visible'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// now make sure that all columns have proper classes - this might only be applied if a bookmark exists
|
||||
foreach (array_keys($columns) as $key) {
|
||||
if ($columns[$key]['visible']) {
|
||||
$columns[$key]['class'] = $this->makeVisible($columns[$key]['class']);
|
||||
} else {
|
||||
$columns[$key]['class'] = $this->makeHidden($columns[$key]['class']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->dataTables[$dataTable] = $columns;
|
||||
}
|
||||
|
||||
if (!isset($values[$column])) {
|
||||
return $this->checkInColumDefinition($columns, $column);
|
||||
return $this->dataTables[$dataTable];
|
||||
}
|
||||
|
||||
public function getDatatableColumnClass(string $dataTable, string $column): string
|
||||
{
|
||||
$dataTable = $this->getDatatableName($dataTable);
|
||||
|
||||
if (!\array_key_exists($dataTable, $this->dataTables)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($values[$column] === false) {
|
||||
if (!\array_key_exists($column, $this->dataTables[$dataTable])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->dataTables[$dataTable][$column]['class'];
|
||||
}
|
||||
|
||||
private function checkInColumDefinition(array $columns, string $column): bool
|
||||
{
|
||||
if (!\array_key_exists($column, $columns)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
$tmp = $this->getClass($columns[$column]);
|
||||
|
||||
if (str_contains($tmp, 'alwaysVisible')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$result = true;
|
||||
if (stripos($tmp, 'd-none') !== false) {
|
||||
$result = false;
|
||||
}
|
||||
|
||||
if (str_contains($tmp, '-table-cell')) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function checkInColumDefinition(array $columns, string $column)
|
||||
private function makeVisible(string $allClasses): string
|
||||
{
|
||||
if (\array_key_exists($column, $columns)) {
|
||||
$tmp = $columns[$column];
|
||||
if (\is_array($tmp)) {
|
||||
$tmp = $tmp['class'];
|
||||
}
|
||||
foreach (explode(' ', $tmp) as $class) {
|
||||
if ($class === 'hidden') {
|
||||
return false;
|
||||
}
|
||||
$newClass = [];
|
||||
foreach (explode(' ', $allClasses) as $class) {
|
||||
if (!str_contains($class, '-none')) {
|
||||
$newClass[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return implode(' ', $newClass);
|
||||
}
|
||||
|
||||
private function makeHidden(string $allClasses): string
|
||||
{
|
||||
$newClass = [];
|
||||
foreach (explode(' ', $allClasses) as $class) {
|
||||
if (!str_contains($class, '-table-cell')) {
|
||||
$newClass[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
$newClass = implode(' ', $newClass);
|
||||
|
||||
if (!str_contains($newClass, '-none')) {
|
||||
$newClass .= ' d-none';
|
||||
}
|
||||
|
||||
return $newClass;
|
||||
}
|
||||
|
||||
private function getClass($class): string
|
||||
{
|
||||
if (\is_array($class)) {
|
||||
if (!\array_key_exists('class', $class)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $class['class'];
|
||||
}
|
||||
|
||||
if (!\is_string($class)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user